From b3235183d929ef32c77f6f5baa199981cfa6ed675353db074c6955bc0728c523 Mon Sep 17 00:00:00 2001 From: OBS User unknown Date: Sat, 20 Oct 2007 15:42:04 +0000 Subject: [PATCH] OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/xorg-x11-server?expand=0&rev=51 --- 0018-vnc-support.txt | 59203 -------------------------------- 0018-vnc-support.txt.diff | 40 - 0018-vnc-support.txt.mbox | 187 - xorg-server-1.4-vnc-fix.patch | 22 + xorg-server-1.4-vnc.patch | 24047 +++++++++++++ xorg-x11-server.changes | 5 + xorg-x11-server.spec | 30 +- 7 files changed, 24088 insertions(+), 59446 deletions(-) delete mode 100644 0018-vnc-support.txt delete mode 100644 0018-vnc-support.txt.diff delete mode 100644 0018-vnc-support.txt.mbox create mode 100644 xorg-server-1.4-vnc-fix.patch create mode 100644 xorg-server-1.4-vnc.patch diff --git a/0018-vnc-support.txt b/0018-vnc-support.txt deleted file mode 100644 index 439025c..0000000 --- a/0018-vnc-support.txt +++ /dev/null @@ -1,59203 +0,0 @@ -From 76c92b4af6b33da219439ecafab83f6500a5108b Mon Sep 17 00:00:00 2001 -From: Christiaan Welvaart -Date: Fri, 3 Nov 2006 14:44:06 -0300 -Subject: [PATCH] vnc support - -VNC support, adapted from http://xf4vnc.sourceforge.net/ CVS ---- - Makefile.am | 5 - configure.ac | 99 + - fb/fbcmap.c | 2 - hw/Makefile.am | 7 - hw/dmx/Makefile.am | 14 - hw/dmx/dmx.h | 4 - hw/dmx/dmxinit.c | 7 - hw/dmx/dmxsync.c | 4 - hw/dmx/input/Makefile.am | 4 - hw/dmx/input/dmxinputinit.c | 7 - hw/dmx/vnc/Makefile.am | 43 + - hw/dmx/vnc/auth.c | 562 ++++++++ - hw/dmx/vnc/cmap.c | 163 ++ - hw/dmx/vnc/corre.c | 355 +++++ - hw/dmx/vnc/cursor.c | 401 +++++ - hw/dmx/vnc/cutpaste.c | 87 + - hw/dmx/vnc/d3des.c | 440 ++++++ - hw/dmx/vnc/d3des.h | 51 + - hw/dmx/vnc/dispcur.c | 804 +++++++++++ - hw/dmx/vnc/draw.c | 2097 +++++++++++++++++++++++++++++ - hw/dmx/vnc/hextile.c | 352 +++++ - hw/dmx/vnc/httpd.c | 520 +++++++ - hw/dmx/vnc/kbdptr.c | 446 ++++++ - hw/dmx/vnc/keyboard.h | 167 ++ - hw/dmx/vnc/loginauth.c | 142 ++ - hw/dmx/vnc/rdp.c | 145 ++ - hw/dmx/vnc/rfb.h | 697 ++++++++++ - hw/dmx/vnc/rfbkeyb.c | 412 ++++++ - hw/dmx/vnc/rfbmouse.c | 243 +++ - hw/dmx/vnc/rfbproto.h | 1347 ++++++++++++++++++ - hw/dmx/vnc/rfbserver.c | 2265 +++++++++++++++++++++++++++++++ - hw/dmx/vnc/rre.c | 325 ++++ - hw/dmx/vnc/sockets.c | 656 +++++++++ - hw/dmx/vnc/sprite.c | 2491 ++++++++++++++++++++++++++++++++++ - hw/dmx/vnc/sprite.h | 141 ++ - hw/dmx/vnc/spritest.h | 138 ++ - hw/dmx/vnc/stats.c | 113 ++ - hw/dmx/vnc/tableinitcmtemplate.c | 89 + - hw/dmx/vnc/tableinittctemplate.c | 142 ++ - hw/dmx/vnc/tabletranstemplate.c | 119 ++ - hw/dmx/vnc/tight.c | 1827 +++++++++++++++++++++++++ - hw/dmx/vnc/translate.c | 496 +++++++ - hw/dmx/vnc/vncInit.c | 436 ++++++ - hw/dmx/vnc/vncauth.c | 239 +++ - hw/dmx/vnc/vncauth.h | 34 - hw/dmx/vnc/vncext.c | 689 +++++++++ - hw/dmx/vnc/vncint.h | 154 ++ - hw/dmx/vnc/xistubs.c | 319 ++++ - hw/dmx/vnc/zlib.c | 306 ++++ - hw/vnc/LICENCE.TXT | 340 +++++ - hw/vnc/Makefile.am | 54 + - hw/vnc/README | 14 - hw/vnc/auth.c | 562 ++++++++ - hw/vnc/cmap.c | 163 ++ - hw/vnc/corre.c | 353 +++++ - hw/vnc/cursor.c | 404 ++++++ - hw/vnc/cutpaste.c | 87 + - hw/vnc/d3des.c | 434 ++++++ - hw/vnc/dispcur.c | 804 +++++++++++ - hw/vnc/dpmsstubs.c | 48 + - hw/vnc/draw.c | 2108 +++++++++++++++++++++++++++++ - hw/vnc/hextile.c | 351 +++++ - hw/vnc/httpd.c | 516 +++++++ - hw/vnc/init.c | 1066 +++++++++++++++ - hw/vnc/kbdptr.c | 425 ++++++ - hw/vnc/keyboard.h | 167 ++ - hw/vnc/loginauth.c | 138 ++ - hw/vnc/rdp.c | 142 ++ - hw/vnc/rfb.h | 725 ++++++++++ - hw/vnc/rfbkeyb.c | 412 ++++++ - hw/vnc/rfbmouse.c | 244 +++ - hw/vnc/rfbproto.h | 1347 ++++++++++++++++++ - hw/vnc/rfbserver.c | 2273 +++++++++++++++++++++++++++++++ - hw/vnc/rre.c | 323 ++++ - hw/vnc/sockets.c | 654 +++++++++ - hw/vnc/sprite.c | 2491 ++++++++++++++++++++++++++++++++++ - hw/vnc/sprite.h | 141 ++ - hw/vnc/spritest.h | 138 ++ - hw/vnc/stats.c | 113 ++ - hw/vnc/tableinitcmtemplate.c | 89 + - hw/vnc/tableinittctemplate.c | 142 ++ - hw/vnc/tabletranstemplate.c | 119 ++ - hw/vnc/tight.c | 1824 +++++++++++++++++++++++++ - hw/vnc/translate.c | 496 +++++++ - hw/vnc/vncauth.h | 33 - hw/vnc/vncext.c | 794 +++++++++++ - hw/vnc/xistubs.c | 319 ++++ - hw/vnc/zlib.c | 309 ++++ - hw/xfree86/Makefile.am | 8 - hw/xfree86/common/xf86.h | 4 - hw/xfree86/dixmods/Makefile.am | 9 - hw/xfree86/vnc/Makefile.am | 45 + - hw/xfree86/vnc/README | 1 - hw/xfree86/vnc/auth.c | 563 ++++++++ - hw/xfree86/vnc/cmap.c | 163 ++ - hw/xfree86/vnc/corre.c | 355 +++++ - hw/xfree86/vnc/cursor.c | 405 ++++++ - hw/xfree86/vnc/cutpaste.c | 87 + - hw/xfree86/vnc/draw.c | 2108 +++++++++++++++++++++++++++++ - hw/xfree86/vnc/hextile.c | 352 +++++ - hw/xfree86/vnc/httpd.c | 520 +++++++ - hw/xfree86/vnc/kbdptr.c | 426 ++++++ - hw/xfree86/vnc/keyboard.h | 167 ++ - hw/xfree86/vnc/loginauth.c | 141 ++ - hw/xfree86/vnc/rfb.h | 726 ++++++++++ - hw/xfree86/vnc/rfbkeyb.c | 410 ++++++ - hw/xfree86/vnc/rfbmouse.c | 240 +++ - hw/xfree86/vnc/rfbproto.h | 1347 ++++++++++++++++++ - hw/xfree86/vnc/rfbserver.c | 2278 +++++++++++++++++++++++++++++++ - hw/xfree86/vnc/rre.c | 325 ++++ - hw/xfree86/vnc/sockets.c | 656 +++++++++ - hw/xfree86/vnc/sprite.h | 141 ++ - hw/xfree86/vnc/stats.c | 113 ++ - hw/xfree86/vnc/tableinitcmtemplate.c | 89 + - hw/xfree86/vnc/tableinittctemplate.c | 142 ++ - hw/xfree86/vnc/tabletranstemplate.c | 119 ++ - hw/xfree86/vnc/tight.c | 1831 +++++++++++++++++++++++++ - hw/xfree86/vnc/translate.c | 497 +++++++ - hw/xfree86/vnc/vncInit.c | 640 +++++++++ - hw/xfree86/vnc/vncauth.h | 34 - hw/xfree86/vnc/vncext.c | 791 +++++++++++ - hw/xfree86/vnc/vncint.h | 155 ++ - hw/xfree86/vnc/zlib.c | 306 ++++ - mi/mieq.c | 4 - mi/miinitext.c | 12 - xcliplist/Makefile.am | 18 - xcliplist/cliplist.c | 128 ++ - xcliplist/cliplistmod.c | 46 + - 128 files changed, 58163 insertions(+), 7 deletions(-) - -diff --git a/Makefile.am b/Makefile.am -index 08a17f5..d75fb9d 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -34,6 +34,10 @@ if DBE - DBE_DIR=dbe - endif - -+if XCLIPLIST -+XCLIPLIST_DIR=xcliplist -+endif -+ - SUBDIRS = \ - doc \ - include \ -@@ -58,6 +62,7 @@ SUBDIRS = \ - $(XTRAP_DIR) \ - $(COMPOSITE_DIR) \ - $(GLX_DIR) \ -+ $(XCLIPLIST_DIR) \ - exa \ - hw - -diff --git a/configure.ac b/configure.ac -index 4915cdb..1d03481 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -431,7 +431,13 @@ AC_ARG_ENABLE(xinput, AS_HELP_ST - - dnl DDXes. - AC_ARG_ENABLE(xorg, AS_HELP_STRING([--enable-xorg], [Build Xorg server (default: auto)]), [XORG=$enableval], [XORG=auto]) -+AC_ARG_ENABLE(xorg_vnc, AS_HELP_STRING([--enable-xorg-vnc], [Build vnc module for Xorg (default: no)]), [XORG_VNC=$enableval], [XORG_VNC=no]) - AC_ARG_ENABLE(dmx, AS_HELP_STRING([--enable-dmx], [Build DMX server (default: auto)]), [DMX=$enableval], [DMX=auto]) -+AC_ARG_ENABLE(xdmx_vnc, AS_HELP_STRING([--enable-xdmx-vnc], [Enable VNC support for Xdmx (default: no)]), [XDMX_VNC=$enableval], [XDMX_VNC=no]) -+ -+AC_ARG_ENABLE(xcliplist, AS_HELP_STRING([--enable-xcliplist], [Build XClipList extension (default: auto)]), [XCLIPLIST=$enableval], [XCLIPLIST=auto]) -+AC_ARG_ENABLE(xvnc, AS_HELP_STRING([--enable-xvnc], [Build Xvnc server (default: no)]), [XVNC=$enableval], [XVNC=no]) -+ - AC_ARG_ENABLE(xvfb, AS_HELP_STRING([--enable-xvfb], [Build Xvfb server (default: yes)]), [XVFB=$enableval], [XVFB=yes]) - AC_ARG_ENABLE(xnest, AS_HELP_STRING([--enable-xnest], [Build Xnest server (default: auto)]), [XNEST=$enableval], [XNEST=auto]) - AC_ARG_ENABLE(xwin, AS_HELP_STRING([--enable-xwin], [Build XWin server (default: auto)]), [XWIN=$enableval], [XWIN=auto]) -@@ -764,6 +770,20 @@ if test "x$XINPUT" = xyes; then - XI_INC='-I$(top_srcdir)/Xi' - fi - -+if test "x$XCLIPLIST" = xauto; then -+ if test "x$XORG" = xno; then -+ XCLIPLIST=no -+ else -+ PKG_CHECK_MODULES([XCLIPLIST], [xcliplistproto xcliplist], [XCLIPLIST=yes], [XCLIPLIST=no]) -+ fi -+fi -+AM_CONDITIONAL(XCLIPLIST, [test "x$XCLIPLIST" = xyes]) -+if test "x$XCLIPLIST" = xyes; then -+ AC_DEFINE(XCLIPLIST, 1, [Support XClipList extension]) -+ REQUIRED_MODULES="$REQUIRED_MODULES xcliplistproto" -+ XCLIPLIST_LIB='$(top_builddir)/xcliplist/libxcliplist.la' -+fi -+ - AM_CONDITIONAL(XF86UTILS, test "x$XF86UTILS" = xyes) - - AC_DEFINE(SHAPE, 1, [Support SHAPE extension]) -@@ -877,6 +897,8 @@ MI_EXT_LIB='$(top_builddir)/mi/libmiext. - MI_INC='-I$(top_srcdir)/mi' - FB_LIB='$(top_builddir)/fb/libfb.la' - FB_INC='-I$(top_srcdir)/fb' -+MFB_LIB='$(top_builddir)/mfb/libmfb.la' -+MFB_INC='-I$(top_srcdir)/mfb' - MIEXT_SHADOW_INC='-I$(top_srcdir)/miext/shadow' - MIEXT_SHADOW_LIB='$(top_builddir)/miext/shadow/libshadow.la' - XPSTUBS_LIB='$(top_builddir)/dix/libxpstubs.la' -@@ -995,6 +1023,72 @@ AM_CONDITIONAL([DMX_BUILD_LNX], [test "x - AM_CONDITIONAL([DMX_BUILD_USB], [test "x$DMX_BUILD_USB" = xyes]) - - -+ -+dnl VNC DDX -+ -+AC_MSG_CHECKING([whether to build Xvnc DDX]) -+PKG_CHECK_MODULES([VNCMODULES], [xmuu xext x11 xrender xfont xi vncproto xau $XDMCP_MODULES], [have_vnc=yes], [have_vnc=no]) -+if test "x$XVNC" = xauto; then -+ XVNC="$have_vnc" -+fi -+AC_MSG_RESULT([$XVNC]) -+AM_CONDITIONAL(XVNC, [test "x$XVNC" = xyes]) -+ -+if test "x$XVNC" = xyes; then -+ if test "x$have_vnc" = xno; then -+ AC_MSG_ERROR([Xvnc build explicitly requested, but required -+ modules not found.]) -+ fi -+ XVNC_CFLAGS="-DVNCSERVER -DHAVE_XVNC_CONFIG_H" -+ AC_SUBST([XVNC_CFLAGS]) -+ VNC_INCLUDES="$XEXT_INC $RENDER_INC $XTRAP_INC $RECORD_INC" -+ XVNC_LIBS="$GLX_LIBS $MFB_LIB $FB_LIB $MI_LIB $XEXT_LIB $RENDER_LIB $XTRAP_LIB $RECORD_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $OS_LIB $CWRAP_LIB" -+ AC_SUBST([XVNC_LIBS]) -+ -+ if test "x$GLX" = xyes; then -+ PKG_CHECK_MODULES([GL], [glproto]) -+ fi -+ PKG_CHECK_MODULES([XVNCCONFIG_DEP], [xaw7 xmu xt xpm x11]) -+ AC_SUBST(XVNCCONFIG_DEP_CFLAGS) -+ AC_SUBST(XVNCCONFIG_DEP_LIBS) -+fi -+ -+ -+dnl Xorg VNC module -+ -+AC_MSG_CHECKING([whether to build Xorg VNC module]) -+ -+if test "x$XORG_VNC" = xauto; then -+ XORG_VNC="$have_vnc" -+fi -+AC_MSG_RESULT([$XORG_VNC]) -+AM_CONDITIONAL(XORG_VNC, [test "x$XORG_VNC" = xyes]) -+ -+if test "x$XORG_VNC" = xyes; then -+ if test "x$have_vnc" = xno; then -+ AC_MSG_ERROR([VNC module build explicitly requested, but required -+ modules not found.]) -+ fi -+fi -+ -+ -+dnl VNC support for Xdmx -+AC_MSG_CHECKING([whether to build Xdmx VNC support]) -+ -+if test "x$XDMX_VNC" = xauto; then -+ XDMX_VNC="$have_vnc" -+fi -+AC_MSG_RESULT([$XDMX_VNC]) -+AM_CONDITIONAL(XDMX_VNC, [test "x$XDMX_VNC" = xyes]) -+ -+if test "x$XDMX_VNC" = xyes; then -+ if test "x$have_vnc" = xno; then -+ AC_MSG_ERROR([VNC support for Xdmx explicitly requested, but required -+ modules not found.]) -+ fi -+fi -+ -+ - dnl Xvfb DDX - - AC_MSG_CHECKING([whether to build Xvfb DDX]) -@@ -1370,7 +1463,7 @@ AM_CONDITIONAL([LINUX_ALPHA], [test "x$l - AM_CONDITIONAL([LNXACPI], [test "x$linux_acpi" = xyes]) - AM_CONDITIONAL([SOLARIS_USL_CONSOLE], [test "x$solaris_usl_console" = xyes]) - AM_CONDITIONAL([SOLARIS_ASM_INLINE], [test "x$solaris_asm_inline" = xyes]) --AM_CONDITIONAL(MFB, [test "x$XORG" = xyes]) -+AM_CONDITIONAL(MFB, [test "x$XORG" = xyes || test "x$XVNC" = xyes]) - AM_CONDITIONAL(CFB, [test "x$XORG" = xyes]) - AM_CONDITIONAL(AFB, [test "x$XORG" = xyes]) - -@@ -1737,6 +1830,7 @@ Xext/Makefile - Xi/Makefile - xfixes/Makefile - exa/Makefile -+xcliplist/Makefile - hw/Makefile - hw/xfree86/Makefile - hw/xfree86/common/Makefile -@@ -1773,6 +1867,7 @@ hw/xfree86/scanpci/Makefile - hw/xfree86/shadowfb/Makefile - hw/xfree86/vbe/Makefile - hw/xfree86/vgahw/Makefile -+hw/xfree86/vnc/Makefile - hw/xfree86/x86emu/Makefile - hw/xfree86/xaa/Makefile - hw/xfree86/xf1bpp/Makefile -@@ -1793,8 +1888,10 @@ hw/dmx/doc/Makefile - hw/dmx/examples/Makefile - hw/dmx/input/Makefile - hw/dmx/glxProxy/Makefile -+hw/dmx/vnc/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/fb/fbcmap.c b/fb/fbcmap.c -index 762c51c..a289d22 100644 ---- a/fb/fbcmap.c -+++ b/fb/fbcmap.c -@@ -39,7 +39,7 @@ #include "colormapst.h" - #include "resource.h" - #include "fb.h" - --#ifndef XFree86Server -+#if !defined(XFree86Server) && !defined(VNCSERVER) - ColormapPtr FbInstalledMaps[MAXSCREENS]; - - int -diff --git a/hw/Makefile.am b/hw/Makefile.am -index 4c35a58..bc50e4f 100644 ---- a/hw/Makefile.am -+++ b/hw/Makefile.am -@@ -30,6 +30,10 @@ if KDRIVE - XPRINT_SUBDIRS = xprint - endif - -+if XVNC -+VNC_SUBDIRS = vnc -+endif -+ - # need to add darwin support here - - SUBDIRS = \ -@@ -40,9 +44,10 @@ SUBDIRS = \ - $(XNEST_SUBDIRS) \ - $(DMX_SUBDIRS) \ - $(KDRIVE_SUBDIRS) \ -+ $(VNC_SUBDIRS) \ - $(XPRINT_SUBDIRS) - --DIST_SUBDIRS = dmx xfree86 vfb xnest xwin darwin kdrive xgl xprint -+DIST_SUBDIRS = dmx xfree86 vfb xnest xwin darwin kdrive xgl xprint vnc - - relink: - for i in $(SUBDIRS) ; do $(MAKE) -C $$i relink ; done -diff --git a/hw/dmx/Makefile.am b/hw/dmx/Makefile.am -index 93abd7a..05740a2 100644 ---- a/hw/dmx/Makefile.am -+++ b/hw/dmx/Makefile.am -@@ -1,6 +1,9 @@ --DIST_SUBDIRS = input config glxProxy examples doc -+DIST_SUBDIRS = input vnc config glxProxy examples doc - --SUBDIRS = input config examples -+if XDMX_VNC -+DMXVNC_SUBDIR = vnc -+endif -+SUBDIRS = input $(DMXVNC_SUBDIR) config examples - bin_PROGRAMS = Xdmx - - if XINERAMA -@@ -92,6 +95,13 @@ Xdmx_CFLAGS = @SERVER_DEFINES@ \ - $(DMX_CFLAGS) \ - @DMXMODULES_CFLAGS@ - -+if XDMX_VNC -+Xdmx_LDADD += vnc/libdmxvnc.a \ -+ -ljpeg -lcrypt -+Xdmx_CFLAGS += $(DIX_CFLAGS) \ -+ -DDMXVNC=1 -+endif -+ - # Man page - appmandir = $(APP_MAN_DIR) - -diff --git a/hw/dmx/dmxinit.c b/hw/dmx/dmxinit.c -index ddc4d2b..da926f4 100644 ---- a/hw/dmx/dmxinit.c -+++ b/hw/dmx/dmxinit.c -@@ -78,6 +78,10 @@ #endif /* GLXEXT */ - ); - #endif /* GLXEXT */ - -+#ifdef DMXVNC -+extern void VNCInit2(void); -+#endif -+ - /* Global variables available to all Xserver/hw/dmx routines. */ - int dmxNumScreens; - DMXScreenInfo *dmxScreens; -@@ -813,6 +817,9 @@ #endif - - dmxLog(dmxInfo, "Shadow framebuffer support %s\n", - dmxShadowFB ? "enabled" : "disabled"); -+#ifdef DMXVNC -+ VNCInit2(); -+#endif - } - - /* RATS: Assuming the fp string (which comes from the command-line argv -diff --git a/hw/dmx/dmxsync.c b/hw/dmx/dmxsync.c -index 02e2446..10ca40d 100644 ---- a/hw/dmx/dmxsync.c -+++ b/hw/dmx/dmxsync.c -@@ -103,6 +103,10 @@ static void dmxSyncBlockHandler(pointer - static void dmxSyncWakeupHandler(pointer blockData, int result, - pointer pReadMask) - { -+#ifdef DMXVNC -+ extern void rfbWakeupHandler2(void); -+ rfbWakeupHandler2(); -+#endif - } - - /** Request the XSync() batching optimization with the specified \a -diff --git a/hw/dmx/input/Makefile.am b/hw/dmx/input/Makefile.am -index d37c2a9..a12b35f 100644 ---- a/hw/dmx/input/Makefile.am -+++ b/hw/dmx/input/Makefile.am -@@ -68,4 +68,8 @@ AM_CFLAGS = @SERVER_DEFINES@ \ - $(GLX_DEFS) \ - @DMXMODULES_CFLAGS@ - -+if XDMX_VNC -+AM_CFLAGS += -DDMXVNC=1 -+endif -+ - EXTRA_DIST = dmxdetach.c -diff --git a/hw/dmx/input/dmxinputinit.c b/hw/dmx/input/dmxinputinit.c -index c81eb84..bca5bcc 100644 ---- a/hw/dmx/input/dmxinputinit.c -+++ b/hw/dmx/input/dmxinputinit.c -@@ -342,6 +342,13 @@ #else - DevicePtr pDev = &pDevice->public; - #endif - -+#ifdef DMXVNC -+ { -+ extern void vncSetKeyboardDevice(DeviceIntPtr kbd); -+ vncSetKeyboardDevice(pDevice); -+ } -+#endif -+ - #ifdef XKB - if (noXkbExtension) { - #endif -diff --git a/hw/dmx/vnc/Makefile.am b/hw/dmx/vnc/Makefile.am -new file mode 100644 -index 0000000..48c07bd ---- /dev/null -+++ b/hw/dmx/vnc/Makefile.am -@@ -0,0 +1,43 @@ -+noinst_LIBRARIES = libdmxvnc.a -+ -+SRCS = \ -+ auth.c \ -+ cmap.c \ -+ corre.c \ -+ cursor.c \ -+ cutpaste.c \ -+ d3des.c \ -+ dispcur.c \ -+ draw.c \ -+ hextile.c \ -+ httpd.c \ -+ kbdptr.c \ -+ loginauth.c \ -+ rdp.c \ -+ rfbkeyb.c \ -+ rfbmouse.c \ -+ rfbserver.c \ -+ rre.c \ -+ sockets.c \ -+ sprite.c \ -+ stats.c \ -+ tight.c \ -+ translate.c \ -+ vncauth.c \ -+ vncext.c \ -+ vncInit.c \ -+ xistubs.c \ -+ zlib.c -+ -+ -+libdmxvnc_a_SOURCES = $(SRCS) -+ -+AM_CFLAGS = \ -+ -I$(top_srcdir)/hw/dmx \ -+ -I$(top_srcdir)/hw/xfree86/common \ -+ -DHAVE_DMX_CONFIG_H \ -+ $(DIX_CFLAGS) \ -+ -DDMXVNC=1 \ -+ @DMXMODULES_CFLAGS@ -+ -+###EXTRA_DIST = dmxdetach.c -diff --git a/hw/dmx/vnc/auth.c b/hw/dmx/vnc/auth.c -new file mode 100644 -index 0000000..06b6b51 ---- /dev/null -+++ b/hw/dmx/vnc/auth.c -@@ -0,0 +1,562 @@ -+/* -+ * auth.c - deal with authentication. -+ * -+ * This file implements authentication when setting up an RFB connection. -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ */ -+ -+/* -+ * Copyright (C) 2003-2004 Constantin Kaplinsky. All Rights Reserved. -+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. -+ * -+ * This is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This software is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this software; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -+ * USA. -+ */ -+ -+#include "rfb.h" -+#include "windowstr.h" -+ -+static void rfbSendSecurityType(rfbClientPtr cl, int securityType); -+static void rfbSendSecurityTypeList(rfbClientPtr cl, int primaryType); -+static void rfbSendTunnelingCaps(rfbClientPtr cl); -+static void rfbSendAuthCaps(rfbClientPtr cl); -+static void rfbVncAuthSendChallenge(rfbClientPtr cl); -+ -+/* -+ * rfbAuthNewClient is called right after negotiating the protocol -+ * version. Depending on the protocol version, we send either a code -+ * for authentication scheme to be used (protocol 3.3), or a list of -+ * possible "security types" (protocol 3.7). -+ */ -+ -+void -+rfbAuthNewClient(cl) -+ rfbClientPtr cl; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ int securityType = rfbSecTypeInvalid; -+ -+ if ((!pVNC->rfbAuthPasswdFile && !pVNC->loginAuthEnabled) || cl->reverseConnection) { -+ securityType = rfbSecTypeNone; -+ } else { -+ if (rfbAuthIsBlocked(cl)) { -+ rfbLog("Too many authentication failures - client rejected\n"); -+ rfbClientConnFailed(cl, "Too many authentication failures"); -+ return; -+ } -+ if (pVNC->rfbAuthPasswdFile) -+ securityType = rfbSecTypeVncAuth; -+ } -+ -+ if (cl->protocol_minor_ver < 7) { -+ /* Make sure we use only RFB 3.3 compatible security types. */ -+ if (securityType == rfbSecTypeInvalid) { -+ rfbLog("VNC authentication disabled - RFB 3.3 client rejected\n"); -+ rfbClientConnFailed(cl, "Your viewer cannot handle required " -+ "authentication methods"); -+ return; -+ } -+ rfbSendSecurityType(cl, securityType); -+ } else { -+ /* Here it's ok when securityType is set to rfbSecTypeInvalid. */ -+ rfbSendSecurityTypeList(cl, securityType); -+ } -+} -+ -+ -+/* -+ * Tell the client what security type will be used (protocol 3.3). -+ */ -+ -+static void -+rfbSendSecurityType(cl, securityType) -+ rfbClientPtr cl; -+ int securityType; -+{ -+ CARD32 value32; -+ -+ /* Send the value. */ -+ value32 = Swap32IfLE(securityType); -+ if (WriteExact(cl->sock, (char *)&value32, 4) < 0) { -+ rfbLogPerror("rfbSendSecurityType: write"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ /* Decide what to do next. */ -+ switch (securityType) { -+ case rfbSecTypeNone: -+ /* Dispatch client input to rfbProcessClientInitMessage. */ -+ cl->state = RFB_INITIALISATION; -+ break; -+ case rfbSecTypeVncAuth: -+ /* Begin the standard VNC authentication procedure. */ -+ rfbVncAuthSendChallenge(cl); -+ break; -+ default: -+ /* Impossible case (hopefully). */ -+ rfbLogPerror("rfbSendSecurityType: assertion failed"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ } -+} -+ -+ -+/* -+ * Advertise our supported security types (protocol 3.7). The list -+ * will include one standard security type (if primaryType is not set -+ * to rfbSecTypeInvalid), and then one more value telling the client -+ * that we support TightVNC protocol extensions. Thus, currently, -+ * there will be either 1 or 2 items in the list. -+ */ -+ -+static void -+rfbSendSecurityTypeList(cl, primaryType) -+ rfbClientPtr cl; -+ int primaryType; -+{ -+ int count = 1; -+ -+ /* Fill in the list of security types in the client structure. */ -+ if (primaryType != rfbSecTypeInvalid) { -+ cl->securityTypes[count++] = (CARD8)primaryType; -+ } -+ cl->securityTypes[count] = (CARD8)rfbSecTypeTight; -+ cl->securityTypes[0] = (CARD8)count++; -+ -+ /* Send the list. */ -+ if (WriteExact(cl->sock, (char *)cl->securityTypes, count) < 0) { -+ rfbLogPerror("rfbSendSecurityTypeList: write"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ /* Dispatch client input to rfbProcessClientSecurityType. */ -+ cl->state = RFB_SECURITY_TYPE; -+} -+ -+ -+/* -+ * Read the security type chosen by the client (protocol 3.7). -+ */ -+ -+void -+rfbProcessClientSecurityType(cl) -+ rfbClientPtr cl; -+{ -+ int n, count, i; -+ CARD8 chosenType; -+ -+ /* Read the security type. */ -+ n = ReadExact(cl->sock, (char *)&chosenType, 1); -+ if (n <= 0) { -+ if (n == 0) -+ rfbLog("rfbProcessClientSecurityType: client gone\n"); -+ else -+ rfbLogPerror("rfbProcessClientSecurityType: read"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ /* Make sure it was present in the list sent by the server. */ -+ count = (int)cl->securityTypes[0]; -+ for (i = 1; i <= count; i++) { -+ if (chosenType == cl->securityTypes[i]) -+ break; -+ } -+ if (i > count) { -+ rfbLog("rfbProcessClientSecurityType: " -+ "wrong security type requested\n"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ /* Now go to the proper authentication procedure. */ -+ switch (chosenType) { -+ case rfbSecTypeNone: -+ /* Dispatch client input to rfbProcessClientInitMessage. */ -+ cl->state = RFB_INITIALISATION; -+ break; -+ case rfbSecTypeVncAuth: -+ /* Begin the standard VNC authentication procedure. */ -+ rfbVncAuthSendChallenge(cl); -+ break; -+ case rfbSecTypeTight: -+ /* We are lucky: the viewer supports TightVNC extensions. */ -+ rfbLog("Enabling TightVNC protocol extensions\n"); -+ /* Switch to the protocol 3.7t. */ -+ cl->protocol_tightvnc = TRUE; -+ /* Advertise our tunneling capabilities. */ -+ rfbSendTunnelingCaps(cl); -+ break; -+ default: -+ /* Impossible case (hopefully). */ -+ rfbLog("rfbProcessClientSecurityType: " -+ "unknown authentication scheme\n"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ } -+} -+ -+ -+/* -+ * Send the list of our tunneling capabilities (protocol 3.7t). -+ */ -+ -+static void -+rfbSendTunnelingCaps(cl) -+ rfbClientPtr cl; -+{ -+ rfbTunnelingCapsMsg caps; -+ CARD32 nTypes = 0; /* we don't support tunneling yet */ -+ -+ caps.nTunnelTypes = Swap32IfLE(nTypes); -+ if (WriteExact(cl->sock, (char *)&caps, sz_rfbTunnelingCapsMsg) < 0) { -+ rfbLogPerror("rfbSendTunnelingCaps: write"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ if (nTypes) { -+ /* Dispatch client input to rfbProcessClientTunnelingType(). */ -+ cl->state = RFB_TUNNELING_TYPE; -+ } else { -+ rfbSendAuthCaps(cl); -+ } -+} -+ -+ -+/* -+ * Read tunneling type requested by the client (protocol 3.7t). -+ * NOTE: Currently, we don't support tunneling, and this function -+ * can never be called. -+ */ -+ -+void -+rfbProcessClientTunnelingType(cl) -+ rfbClientPtr cl; -+{ -+ /* If we were called, then something's really wrong. */ -+ rfbLog("rfbProcessClientTunnelingType: not implemented\n"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+} -+ -+ -+/* -+ * Send the list of our authentication capabilities to the client -+ * (protocol 3.7t). -+ */ -+ -+static void -+rfbSendAuthCaps(cl) -+ rfbClientPtr cl; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ Bool authRequired; -+ rfbAuthenticationCapsMsg caps; -+ rfbCapabilityInfo caplist[MAX_AUTH_CAPS]; -+ int count = 0; -+ -+ authRequired = ((pVNC->rfbAuthPasswdFile != NULL || pVNC->loginAuthEnabled) && -+ !cl->reverseConnection); -+ -+ if (authRequired) { -+ if (pVNC->loginAuthEnabled) { -+ SetCapInfo(&caplist[count], rfbAuthUnixLogin, rfbTightVncVendor); -+ cl->authCaps[count++] = rfbAuthUnixLogin; -+ } -+ if (pVNC->rfbAuthPasswdFile != NULL) { -+ SetCapInfo(&caplist[count], rfbAuthVNC, rfbStandardVendor); -+ cl->authCaps[count++] = rfbAuthVNC; -+ } -+ if (count == 0) { -+ /* Should never happen. */ -+ rfbLog("rfbSendAuthCaps: assertion failed\n"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ } -+ -+ cl->nAuthCaps = count; -+ caps.nAuthTypes = Swap32IfLE((CARD32)count); -+ if (WriteExact(cl->sock, (char *)&caps, sz_rfbAuthenticationCapsMsg) < 0) { -+ rfbLogPerror("rfbSendAuthCaps: write"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ if (count) { -+ if (WriteExact(cl->sock, (char *)&caplist[0], -+ count * sz_rfbCapabilityInfo) < 0) { -+ rfbLogPerror("rfbSendAuthCaps: write"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ /* Dispatch client input to rfbProcessClientAuthType. */ -+ cl->state = RFB_AUTH_TYPE; -+ } else { -+ /* Dispatch client input to rfbProcessClientInitMessage. */ -+ cl->state = RFB_INITIALISATION; -+ } -+} -+ -+ -+/* -+ * Read client's preferred authentication type (protocol 3.7t). -+ */ -+ -+void -+rfbProcessClientAuthType(cl) -+ rfbClientPtr cl; -+{ -+ CARD32 auth_type; -+ int n, i; -+ -+ /* Read authentication type selected by the client. */ -+ n = ReadExact(cl->sock, (char *)&auth_type, sizeof(auth_type)); -+ if (n <= 0) { -+ if (n == 0) -+ rfbLog("rfbProcessClientAuthType: client gone\n"); -+ else -+ rfbLogPerror("rfbProcessClientAuthType: read"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ auth_type = Swap32IfLE(auth_type); -+ -+ /* Make sure it was present in the list sent by the server. */ -+ for (i = 0; i < cl->nAuthCaps; i++) { -+ if (auth_type == cl->authCaps[i]) -+ break; -+ } -+ if (i >= cl->nAuthCaps) { -+ rfbLog("rfbProcessClientAuthType: " -+ "wrong authentication type requested\n"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ switch (auth_type) { -+ case rfbAuthNone: -+ /* Dispatch client input to rfbProcessClientInitMessage. */ -+ cl->state = RFB_INITIALISATION; -+ break; -+ case rfbAuthVNC: -+ rfbVncAuthSendChallenge(cl); -+ break; -+ case rfbAuthUnixLogin: -+ /* FIXME: Do (cl->state = RFB_LOGIN_AUTH) instead? */ -+ rfbLoginAuthProcessClientMessage(cl); -+ break; -+ default: -+ rfbLog("rfbProcessClientAuthType: unknown authentication scheme\n"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ } -+} -+ -+ -+/* -+ * Send the authentication challenge. -+ */ -+ -+static void -+rfbVncAuthSendChallenge(cl) -+ rfbClientPtr cl; -+{ -+ vncRandomBytes(cl->authChallenge); -+ if (WriteExact(cl->sock, (char *)cl->authChallenge, CHALLENGESIZE) < 0) { -+ rfbLogPerror("rfbVncAuthSendChallenge: write"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ /* Dispatch client input to rfbVncAuthProcessResponse. */ -+ cl->state = RFB_AUTHENTICATION; -+} -+ -+/* -+ * rfbVncAuthProcessResponse is called when the client sends its -+ * authentication response. -+ */ -+ -+void -+rfbVncAuthProcessResponse(cl) -+ rfbClientPtr cl; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ char passwdFullControl[9]; -+ char passwdViewOnly[9]; -+ int numPasswords; -+ Bool ok; -+ int n; -+ CARD8 encryptedChallenge1[CHALLENGESIZE]; -+ CARD8 encryptedChallenge2[CHALLENGESIZE]; -+ CARD8 response[CHALLENGESIZE]; -+ CARD32 authResult; -+ -+ n = ReadExact(cl->sock, (char *)response, CHALLENGESIZE); -+ if (n <= 0) { -+ if (n != 0) -+ rfbLogPerror("rfbVncAuthProcessResponse: read"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ numPasswords = vncDecryptPasswdFromFile2(pVNC->rfbAuthPasswdFile, -+ passwdFullControl, -+ passwdViewOnly); -+ if (numPasswords == 0) { -+ rfbLog("rfbVncAuthProcessResponse: could not get password from %s\n", -+ pVNC->rfbAuthPasswdFile); -+ -+ authResult = Swap32IfLE(rfbVncAuthFailed); -+ -+ if (WriteExact(cl->sock, (char *)&authResult, 4) < 0) { -+ rfbLogPerror("rfbVncAuthProcessResponse: write"); -+ } -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ memcpy(encryptedChallenge1, cl->authChallenge, CHALLENGESIZE); -+ vncEncryptBytes(encryptedChallenge1, passwdFullControl); -+ memcpy(encryptedChallenge2, cl->authChallenge, CHALLENGESIZE); -+ vncEncryptBytes(encryptedChallenge2, -+ (numPasswords == 2) ? passwdViewOnly : passwdFullControl); -+ -+ /* Lose the passwords from memory */ -+ memset(passwdFullControl, 0, 9); -+ memset(passwdViewOnly, 0, 9); -+ -+ ok = FALSE; -+ if (memcmp(encryptedChallenge1, response, CHALLENGESIZE) == 0) { -+ rfbLog("Full-control authentication passed by %s\n", cl->host); -+ ok = TRUE; -+ cl->viewOnly = FALSE; -+ } else if (memcmp(encryptedChallenge2, response, CHALLENGESIZE) == 0) { -+ rfbLog("View-only authentication passed by %s\n", cl->host); -+ ok = TRUE; -+ cl->viewOnly = TRUE; -+ } -+ -+ if (!ok) { -+ rfbLog("rfbVncAuthProcessResponse: authentication failed from %s\n", -+ cl->host); -+ -+ if (rfbAuthConsiderBlocking(cl)) { -+ authResult = Swap32IfLE(rfbVncAuthTooMany); -+ } else { -+ authResult = Swap32IfLE(rfbVncAuthFailed); -+ } -+ -+ if (WriteExact(cl->sock, (char *)&authResult, 4) < 0) { -+ rfbLogPerror("rfbVncAuthProcessResponse: write"); -+ } -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ rfbAuthUnblock(cl); -+ -+ authResult = Swap32IfLE(rfbVncAuthOK); -+ -+ if (WriteExact(cl->sock, (char *)&authResult, 4) < 0) { -+ rfbLogPerror("rfbVncAuthProcessResponse: write"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ /* Dispatch client input to rfbProcessClientInitMessage(). */ -+ cl->state = RFB_INITIALISATION; -+} -+ -+ -+/* -+ * Functions to prevent too many successive authentication failures. -+ * FIXME: This should be performed separately per each client IP. -+ */ -+ -+/* Maximum authentication failures before blocking connections */ -+#define MAX_AUTH_TRIES 5 -+ -+/* Delay in ms, doubles for each failure over MAX_AUTH_TRIES */ -+#define AUTH_TOO_MANY_BASE_DELAY 10 * 1000 -+ -+/* -+ * This function should not be called directly, it is called by -+ * setting a timer in rfbAuthConsiderBlocking(). -+ */ -+ -+static CARD32 -+rfbAuthReenable(OsTimerPtr timer, CARD32 now, pointer arg) -+{ -+ rfbClientPtr cl = (rfbClientPtr) arg; -+ VNCSCREENPTR(cl->pScreen); -+ pVNC->rfbAuthTooManyTries = FALSE; -+ return 0; -+} -+ -+/* -+ * This function should be called after each authentication failure. -+ * The return value will be true if there was too many failures. -+ */ -+ -+Bool -+rfbAuthConsiderBlocking(rfbClientPtr cl) -+{ -+ VNCSCREENPTR(cl->pScreen); -+ int i; -+ -+ pVNC->rfbAuthTries++; -+ -+ if (pVNC->rfbAuthTries >= MAX_AUTH_TRIES) { -+ CARD32 delay = AUTH_TOO_MANY_BASE_DELAY; -+ for (i = MAX_AUTH_TRIES; i < pVNC->rfbAuthTries; i++) -+ delay *= 2; -+ pVNC->timer = TimerSet(pVNC->timer, 0, delay, rfbAuthReenable, NULL); -+ pVNC->rfbAuthTooManyTries = TRUE; -+ return TRUE; -+ } -+ -+ return FALSE; -+} -+ -+/* -+ * This function should be called after successful authentication. -+ * It resets the counter of authentication failures. Note that it's -+ * not necessary to clear the rfbAuthTooManyTries flag as it will be -+ * reset by the timer function. -+ */ -+ -+void -+rfbAuthUnblock(rfbClientPtr cl) -+{ -+ VNCSCREENPTR(cl->pScreen); -+ pVNC->rfbAuthTries = 0; -+} -+ -+/* -+ * This function should be called before authentication process. -+ * The return value will be true if there was too many authentication -+ * failures, and the server should not allow another try. -+ */ -+ -+Bool -+rfbAuthIsBlocked(rfbClientPtr cl) -+{ -+ VNCSCREENPTR(cl->pScreen); -+ return pVNC->rfbAuthTooManyTries; -+} -+ -diff --git a/hw/dmx/vnc/cmap.c b/hw/dmx/vnc/cmap.c -new file mode 100644 -index 0000000..88aad12 ---- /dev/null -+++ b/hw/dmx/vnc/cmap.c -@@ -0,0 +1,163 @@ -+/* -+ * cmap.c -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ */ -+ -+/* -+ * 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 "rfb.h" -+ -+int -+rfbListInstalledColormaps(pScreen, pmaps) -+ ScreenPtr pScreen; -+ Colormap *pmaps; -+{ -+ VNCSCREENPTR(pScreen); -+ /* By the time we are processing requests, we can guarantee that there -+ * is always a colormap installed */ -+ if (pVNC->rfbInstalledColormap) -+ *pmaps = pVNC->rfbInstalledColormap->mid; -+ -+#if XFREE86VNC -+ pScreen->ListInstalledColormaps = pVNC->ListInstalledColormaps; -+ (*pScreen->ListInstalledColormaps)(pScreen, pmaps); -+ pScreen->ListInstalledColormaps = rfbListInstalledColormaps; -+#endif -+ -+ return (1); -+} -+ -+ -+void -+rfbInstallColormap(pmap) -+ ColormapPtr pmap; -+{ -+ VNCSCREENPTR(pmap->pScreen); -+ -+ if (pmap != pVNC->rfbInstalledColormap) { -+ -+ if(pVNC->rfbInstalledColormap != (ColormapPtr)None) -+ WalkTree(pmap->pScreen, TellLostMap, -+ (char *)&pVNC->rfbInstalledColormap->mid); -+ /* Install pmap */ -+ pVNC->rfbInstalledColormap = pmap; -+ WalkTree(pmap->pScreen, TellGainedMap, (char *)&pmap->mid); -+ -+ rfbSetClientColourMaps(0, 0); -+ } -+#if XFREE86VNC -+ pmap->pScreen->InstallColormap = pVNC->InstallColormap; -+ (*pmap->pScreen->InstallColormap)(pmap); -+ pmap->pScreen->InstallColormap = rfbInstallColormap; -+#endif -+} -+ -+void -+rfbUninstallColormap(pmap) -+ ColormapPtr pmap; -+{ -+ VNCSCREENPTR(pmap->pScreen); -+ -+ if(pmap == pVNC->rfbInstalledColormap) -+ { -+ if (pmap->mid != pmap->pScreen->defColormap) -+ { -+ pVNC->rfbInstalledColormap = -+ (ColormapPtr) LookupIDByType(pmap->pScreen->defColormap, -+ RT_COLORMAP); -+ (*pmap->pScreen->InstallColormap)(pVNC->rfbInstalledColormap); -+ } -+ } -+#if XFREE86VNC -+ pmap->pScreen->UninstallColormap = pVNC->UninstallColormap; -+ (*pmap->pScreen->UninstallColormap)(pmap); -+ pmap->pScreen->UninstallColormap = rfbUninstallColormap; -+#endif -+} -+ -+ -+/* -+ * rfbStoreColors. We have a set of pixels but they may be in any order. -+ * If some of them happen to be in continuous ascending order then we can -+ * group them together into a single call to rfbSetClientColourMaps. -+ */ -+ -+void -+rfbStoreColors(pmap, ndef, pdefs) -+ ColormapPtr pmap; -+ int ndef; -+ xColorItem *pdefs; -+{ -+ VNCSCREENPTR(pmap->pScreen); -+ int i; -+ int first = -1; -+ int n = 0; -+ -+ if (pmap == pVNC->rfbInstalledColormap) { -+ for (i = 0; i < ndef; i++) { -+ if ((first != -1) && (first + n == pdefs[i].pixel)) { -+ n++; -+ } else { -+ if (first != -1) { -+ rfbSetClientColourMaps(first, n); -+ } -+ first = pdefs[i].pixel; -+ n = 1; -+ } -+ } -+ rfbSetClientColourMaps(first, n); -+ } -+#if XFREE86VNC -+ pmap->pScreen->StoreColors = pVNC->StoreColors; -+ (*pmap->pScreen->StoreColors)(pmap, ndef, pdefs); -+ pmap->pScreen->StoreColors = rfbStoreColors; -+#endif -+} -diff --git a/hw/dmx/vnc/corre.c b/hw/dmx/vnc/corre.c -new file mode 100644 -index 0000000..ec1c917 ---- /dev/null -+++ b/hw/dmx/vnc/corre.c -@@ -0,0 +1,355 @@ -+/* -+ * corre.c -+ * -+ * Routines to implement Compact Rise-and-Run-length Encoding (CoRRE). This -+ * code is based on krw's original javatel rfbserver. -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ */ -+ -+/* -+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. -+ * -+ * This is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This software is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this software; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -+ * USA. -+ */ -+ -+#include -+#include -+#include -+#include "rfb.h" -+ -+/* -+ * rreBeforeBuf contains pixel data in the client's format. -+ * rreAfterBuf contains the RRE encoded version. If the RRE encoded version is -+ * larger than the raw data or if it exceeds rreAfterBufSize then -+ * raw encoding is used instead. -+ */ -+ -+static int rreBeforeBufSize = 0; -+static char *rreBeforeBuf = NULL; -+ -+static int rreAfterBufSize = 0; -+static char *rreAfterBuf = NULL; -+static int rreAfterBufLen; -+ -+static int subrectEncode8(CARD8 *data, int w, int h); -+static int subrectEncode16(CARD16 *data, int w, int h); -+static int subrectEncode32(CARD32 *data, int w, int h); -+static CARD32 getBgColour(char *data, int size, int bpp); -+static Bool rfbSendSmallRectEncodingCoRRE(rfbClientPtr cl, int x, int y, -+ int w, int h); -+ -+ -+/* -+ * rfbSendRectEncodingCoRRE - send an arbitrary size rectangle using CoRRE -+ * encoding. -+ */ -+ -+Bool -+rfbSendRectEncodingCoRRE(cl, x, y, w, h) -+ rfbClientPtr cl; -+ int x, y, w, h; -+{ -+ if (h > cl->correMaxHeight) { -+ return (rfbSendRectEncodingCoRRE(cl, x, y, w, cl->correMaxHeight) && -+ rfbSendRectEncodingCoRRE(cl, x, y + cl->correMaxHeight, -+ w, h - cl->correMaxHeight)); -+ } -+ -+ if (w > cl->correMaxWidth) { -+ return (rfbSendRectEncodingCoRRE(cl, x, y, cl->correMaxWidth, h) && -+ rfbSendRectEncodingCoRRE(cl, x + cl->correMaxWidth, y, -+ w - cl->correMaxWidth, h)); -+ } -+ -+ return rfbSendSmallRectEncodingCoRRE(cl, x, y, w, h); -+} -+ -+ -+ -+/* -+ * rfbSendSmallRectEncodingCoRRE - send a small (guaranteed < 256x256) -+ * rectangle using CoRRE encoding. -+ */ -+ -+static Bool -+rfbSendSmallRectEncodingCoRRE(cl, x, y, w, h) -+ rfbClientPtr cl; -+ int x, y, w, h; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ rfbFramebufferUpdateRectHeader rect; -+ rfbRREHeader hdr; -+ int nSubrects; -+ int i; -+ unsigned char *fbptr = (pVNC->pfbMemory + (pVNC->paddedWidthInBytes * y) -+ + (x * (pVNC->bitsPerPixel / 8))); -+ -+ int maxRawSize = (pVNC->width * pVNC->height -+ * (cl->format.bitsPerPixel / 8)); -+ -+ if (rreBeforeBufSize < maxRawSize) { -+ rreBeforeBufSize = maxRawSize; -+ if (rreBeforeBuf == NULL) -+ rreBeforeBuf = (char *)xalloc(rreBeforeBufSize); -+ else -+ rreBeforeBuf = (char *)xrealloc(rreBeforeBuf, rreBeforeBufSize); -+ } -+ -+ if (rreAfterBufSize < maxRawSize) { -+ rreAfterBufSize = maxRawSize; -+ if (rreAfterBuf == NULL) -+ rreAfterBuf = (char *)xalloc(rreAfterBufSize); -+ else -+ rreAfterBuf = (char *)xrealloc(rreAfterBuf, rreAfterBufSize); -+ } -+ -+ (*cl->translateFn)(cl->pScreen, cl->translateLookupTable, -+ &pVNC->rfbServerFormat, -+ &cl->format, fbptr, rreBeforeBuf, -+ pVNC->paddedWidthInBytes, w, h, x, y); -+ -+ switch (cl->format.bitsPerPixel) { -+ case 8: -+ nSubrects = subrectEncode8((CARD8 *)rreBeforeBuf, w, h); -+ break; -+ case 16: -+ nSubrects = subrectEncode16((CARD16 *)rreBeforeBuf, w, h); -+ break; -+ case 32: -+ nSubrects = subrectEncode32((CARD32 *)rreBeforeBuf, w, h); -+ break; -+ default: -+ rfbLog("getBgColour: bpp %d?\n",cl->format.bitsPerPixel); -+ exit(1); -+ } -+ -+ if (nSubrects < 0) { -+ -+ /* RRE encoding was too large, use raw */ -+ -+ return rfbSendRectEncodingRaw(cl, x, y, w, h); -+ } -+ -+ cl->rfbRectanglesSent[rfbEncodingCoRRE]++; -+ cl->rfbBytesSent[rfbEncodingCoRRE] += (sz_rfbFramebufferUpdateRectHeader -+ + sz_rfbRREHeader + rreAfterBufLen); -+ -+ if (pVNC->ublen + sz_rfbFramebufferUpdateRectHeader + sz_rfbRREHeader -+ > UPDATE_BUF_SIZE) -+ { -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ } -+ -+ rect.r.x = Swap16IfLE(x); -+ rect.r.y = Swap16IfLE(y); -+ rect.r.w = Swap16IfLE(w); -+ rect.r.h = Swap16IfLE(h); -+ rect.encoding = Swap32IfLE(rfbEncodingCoRRE); -+ -+ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&rect, -+ sz_rfbFramebufferUpdateRectHeader); -+ pVNC->ublen += sz_rfbFramebufferUpdateRectHeader; -+ -+ hdr.nSubrects = Swap32IfLE(nSubrects); -+ -+ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&hdr, sz_rfbRREHeader); -+ pVNC->ublen += sz_rfbRREHeader; -+ -+ for (i = 0; i < rreAfterBufLen;) { -+ -+ int bytesToCopy = UPDATE_BUF_SIZE - pVNC->ublen; -+ -+ if (i + bytesToCopy > rreAfterBufLen) { -+ bytesToCopy = rreAfterBufLen - i; -+ } -+ -+ memcpy(&pVNC->updateBuf[pVNC->ublen], &rreAfterBuf[i], bytesToCopy); -+ -+ pVNC->ublen += bytesToCopy; -+ i += bytesToCopy; -+ -+ if (pVNC->ublen == UPDATE_BUF_SIZE) { -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ } -+ } -+ -+ return TRUE; -+} -+ -+ -+ -+/* -+ * subrectEncode() encodes the given multicoloured rectangle as a background -+ * colour overwritten by single-coloured rectangles. It returns the number -+ * of subrectangles in the encoded buffer, or -1 if subrect encoding won't -+ * fit in the buffer. It puts the encoded rectangles in rreAfterBuf. The -+ * single-colour rectangle partition is not optimal, but does find the biggest -+ * horizontal or vertical rectangle top-left anchored to each consecutive -+ * coordinate position. -+ * -+ * The coding scheme is simply [...] where each -+ * is []. -+ */ -+ -+#define DEFINE_SUBRECT_ENCODE(bpp) \ -+static int \ -+subrectEncode##bpp(data,w,h) \ -+ CARD##bpp *data; \ -+ int w; \ -+ int h; \ -+{ \ -+ CARD##bpp cl; \ -+ rfbCoRRERectangle subrect; \ -+ int x,y; \ -+ int i,j; \ -+ int hx=0,hy,vx=0,vy; \ -+ int hyflag; \ -+ CARD##bpp *seg; \ -+ CARD##bpp *line; \ -+ int hw,hh,vw,vh; \ -+ int thex,they,thew,theh; \ -+ int numsubs = 0; \ -+ int newLen; \ -+ CARD##bpp bg = (CARD##bpp)getBgColour((char*)data,w*h,bpp); \ -+ \ -+ *((CARD##bpp*)rreAfterBuf) = bg; \ -+ \ -+ rreAfterBufLen = (bpp/8); \ -+ \ -+ for (y=0; y 0) && (i >= hx)) {hy += 1;} else {hyflag = 0;} \ -+ } \ -+ vy = j-1; \ -+ \ -+ /* We now have two possible subrects: (x,y,hx,hy) and (x,y,vx,vy) \ -+ * We'll choose the bigger of the two. \ -+ */ \ -+ hw = hx-x+1; \ -+ hh = hy-y+1; \ -+ vw = vx-x+1; \ -+ vh = vy-y+1; \ -+ \ -+ thex = x; \ -+ they = y; \ -+ \ -+ if ((hw*hh) > (vw*vh)) { \ -+ thew = hw; \ -+ theh = hh; \ -+ } else { \ -+ thew = vw; \ -+ theh = vh; \ -+ } \ -+ \ -+ subrect.x = thex; \ -+ subrect.y = they; \ -+ subrect.w = thew; \ -+ subrect.h = theh; \ -+ \ -+ newLen = rreAfterBufLen + (bpp/8) + sz_rfbCoRRERectangle; \ -+ if ((newLen > (w * h * (bpp/8))) || (newLen > rreAfterBufSize)) \ -+ return -1; \ -+ \ -+ numsubs += 1; \ -+ *((CARD##bpp*)(rreAfterBuf + rreAfterBufLen)) = cl; \ -+ rreAfterBufLen += (bpp/8); \ -+ memcpy(&rreAfterBuf[rreAfterBufLen],&subrect,sz_rfbCoRRERectangle); \ -+ rreAfterBufLen += sz_rfbCoRRERectangle; \ -+ \ -+ /* \ -+ * Now mark the subrect as done. \ -+ */ \ -+ for (j=they; j < (they+theh); j++) { \ -+ for (i=thex; i < (thex+thew); i++) { \ -+ data[j*w+i] = bg; \ -+ } \ -+ } \ -+ } \ -+ } \ -+ } \ -+ \ -+ return numsubs; \ -+} -+ -+DEFINE_SUBRECT_ENCODE(8) -+DEFINE_SUBRECT_ENCODE(16) -+DEFINE_SUBRECT_ENCODE(32) -+ -+ -+/* -+ * getBgColour() gets the most prevalent colour in a byte array. -+ */ -+static CARD32 -+getBgColour(data,size,bpp) -+ char *data; -+ int size; -+ int bpp; -+{ -+ -+#define NUMCLRS 256 -+ -+ static int counts[NUMCLRS]; -+ int i,j,k; -+ -+ int maxcount = 0; -+ CARD8 maxclr = 0; -+ -+ if (bpp != 8) { -+ if (bpp == 16) { -+ return ((CARD16 *)data)[0]; -+ } else if (bpp == 32) { -+ return ((CARD32 *)data)[0]; -+ } else { -+ rfbLog("getBgColour: bpp %d?\n",bpp); -+ exit(1); -+ } -+ } -+ -+ for (i=0; i= NUMCLRS) { -+ rfbLog("getBgColour: unusual colour = %d\n", k); -+ exit(1); -+ } -+ counts[k] += 1; -+ if (counts[k] > maxcount) { -+ maxcount = counts[k]; -+ maxclr = ((CARD8 *)data)[j]; -+ } -+ } -+ -+ return maxclr; -+} -diff --git a/hw/dmx/vnc/cursor.c b/hw/dmx/vnc/cursor.c -new file mode 100644 -index 0000000..caed042 ---- /dev/null -+++ b/hw/dmx/vnc/cursor.c -@@ -0,0 +1,401 @@ -+/* -+ * cursor.c - support for cursor shape updates. -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ */ -+ -+/* -+ * Copyright (C) 2000, 2001 Const Kaplinsky. All Rights Reserved. -+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. -+ * -+ * This is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This software is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this software; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -+ * USA. -+ */ -+ -+#include -+#include -+#include "rfb.h" -+#include "mipointer.h" -+#include "sprite.h" -+#include "cursorstr.h" -+#include "servermd.h" -+ -+ -+/* Copied from Xvnc/lib/font/util/utilbitmap.c */ -+static unsigned char _reverse_byte[0x100] = { -+ 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 -+}; -+ -+ -+static int EncodeRichCursorData8 (char *buf, rfbPixelFormat *fmt, -+ CursorPtr pCursor); -+static int EncodeRichCursorData16 (ScreenPtr pScreen, -+ char *buf, rfbPixelFormat *fmt, -+ CursorPtr pCursor); -+static int EncodeRichCursorData32 (ScreenPtr pScreen, -+ char *buf, rfbPixelFormat *fmt, -+ CursorPtr pCursor); -+ -+ -+/* -+ * Send cursor shape either in X-style format or in client pixel format. -+ */ -+ -+Bool -+rfbSendCursorShape(cl, pScreen) -+ rfbClientPtr cl; -+ ScreenPtr pScreen; -+{ -+ VNCSCREENPTR(pScreen); -+ CursorPtr pCursor; -+ rfbFramebufferUpdateRectHeader rect; -+ rfbXCursorColors colors; -+ int saved_ublen; -+ int bitmapRowBytes, paddedRowBytes, maskBytes, dataBytes; -+ int i, j; -+ CARD8 *bitmapData; -+ CARD8 bitmapByte; -+ -+ if (cl->useRichCursorEncoding) { -+ rect.encoding = Swap32IfLE(rfbEncodingRichCursor); -+ } else { -+ rect.encoding = Swap32IfLE(rfbEncodingXCursor); -+ } -+ -+ pCursor = pVNC->pCurs; -+ -+ /* If there is no cursor, send update with empty cursor data. */ -+ -+ if ( pCursor != NULL && -+ pCursor->bits->width == 1 && -+ pCursor->bits->height == 1 && -+ pCursor->bits->mask[0] == 0 ) { -+ pCursor = NULL; -+ } -+ -+ if (pCursor == NULL) { -+ if (pVNC->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE ) { -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ } -+ rect.r.x = rect.r.y = 0; -+ rect.r.w = rect.r.h = 0; -+ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&rect, -+ sz_rfbFramebufferUpdateRectHeader); -+ pVNC->ublen += sz_rfbFramebufferUpdateRectHeader; -+ -+ cl->rfbCursorShapeBytesSent += sz_rfbFramebufferUpdateRectHeader; -+ cl->rfbCursorShapeUpdatesSent++; -+ -+ return TRUE; -+ } -+ -+ /* Calculate data sizes. */ -+ -+ bitmapRowBytes = (pCursor->bits->width + 7) / 8; -+ paddedRowBytes = PixmapBytePad(pCursor->bits->width, 1); -+ maskBytes = bitmapRowBytes * pCursor->bits->height; -+ dataBytes = (cl->useRichCursorEncoding) ? -+ (pCursor->bits->width * pCursor->bits->height * -+ (cl->format.bitsPerPixel / 8)) : maskBytes; -+ -+ /* Send buffer contents if needed. */ -+ -+ if ( pVNC->ublen + sz_rfbFramebufferUpdateRectHeader + -+ sz_rfbXCursorColors + maskBytes + dataBytes > UPDATE_BUF_SIZE ) { -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ } -+ -+ if ( pVNC->ublen + sz_rfbFramebufferUpdateRectHeader + -+ sz_rfbXCursorColors + maskBytes + dataBytes > UPDATE_BUF_SIZE ) { -+ return FALSE; /* FIXME. */ -+ } -+ -+ saved_ublen = pVNC->ublen; -+ -+ /* Prepare rectangle header. */ -+ -+ rect.r.x = Swap16IfLE(pCursor->bits->xhot); -+ rect.r.y = Swap16IfLE(pCursor->bits->yhot); -+ rect.r.w = Swap16IfLE(pCursor->bits->width); -+ rect.r.h = Swap16IfLE(pCursor->bits->height); -+ -+ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&rect,sz_rfbFramebufferUpdateRectHeader); -+ pVNC->ublen += sz_rfbFramebufferUpdateRectHeader; -+ -+ /* Prepare actual cursor data (depends on encoding used). */ -+ -+ if (!cl->useRichCursorEncoding) { -+ /* XCursor encoding. */ -+ colors.foreRed = (char)(pCursor->foreRed >> 8); -+ colors.foreGreen = (char)(pCursor->foreGreen >> 8); -+ colors.foreBlue = (char)(pCursor->foreBlue >> 8); -+ colors.backRed = (char)(pCursor->backRed >> 8); -+ colors.backGreen = (char)(pCursor->backGreen >> 8); -+ colors.backBlue = (char)(pCursor->backBlue >> 8); -+ -+ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&colors, sz_rfbXCursorColors); -+ pVNC->ublen += sz_rfbXCursorColors; -+ -+ bitmapData = (CARD8 *)pCursor->bits->source; -+ -+ for (i = 0; i < pCursor->bits->height; i++) { -+ for (j = 0; j < bitmapRowBytes; j++) { -+ bitmapByte = bitmapData[i * paddedRowBytes + j]; -+ if (screenInfo.bitmapBitOrder == LSBFirst) { -+ bitmapByte = _reverse_byte[bitmapByte]; -+ } -+ pVNC->updateBuf[pVNC->ublen++] = (char)bitmapByte; -+ } -+ } -+ } else { -+ /* RichCursor encoding. */ -+ switch (cl->format.bitsPerPixel) { -+ case 8: -+ pVNC->ublen += EncodeRichCursorData8(&pVNC->updateBuf[pVNC->ublen], -+ &cl->format, pCursor); -+ break; -+ case 16: -+ pVNC->ublen += EncodeRichCursorData16(pScreen, &pVNC->updateBuf[pVNC->ublen], -+ &cl->format, pCursor); -+ break; -+ case 32: -+ pVNC->ublen += EncodeRichCursorData32(pScreen, &pVNC->updateBuf[pVNC->ublen], -+ &cl->format, pCursor); -+ break; -+ default: -+ return FALSE; -+ } -+ } -+ -+ /* Prepare transparency mask. */ -+ -+ bitmapData = (CARD8 *)pCursor->bits->mask; -+ -+ for (i = 0; i < pCursor->bits->height; i++) { -+ for (j = 0; j < bitmapRowBytes; j++) { -+ bitmapByte = bitmapData[i * paddedRowBytes + j]; -+ if (screenInfo.bitmapBitOrder == LSBFirst) { -+ bitmapByte = _reverse_byte[bitmapByte]; -+ } -+ pVNC->updateBuf[pVNC->ublen++] = (char)bitmapByte; -+ } -+ } -+ -+ /* Update statistics. */ -+ -+ cl->rfbCursorShapeBytesSent += (pVNC->ublen - saved_ublen); -+ cl->rfbCursorShapeUpdatesSent++; -+ -+ return TRUE; -+} -+ -+/* -+ * Send cursor position (PointerPos pseudo-encoding). -+ */ -+Bool -+rfbSendCursorPos(cl, pScreen) -+ rfbClientPtr cl; -+ ScreenPtr pScreen; -+{ -+ VNCSCREENPTR(pScreen); -+ rfbFramebufferUpdateRectHeader rect; -+#if XFREE86VNC -+ ScreenPtr pCursorScreen = miPointerCurrentScreen(); -+#endif -+ int x, y; -+ -+ if (pVNC->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) { -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ } -+ -+#if XFREE86VNC -+ if (pScreen == pCursorScreen) -+ miPointerPosition(&x, &y); -+#else -+ rfbSpriteGetCursorPos(pScreen, &x, &y); -+#endif -+ -+ rect.encoding = Swap32IfLE(rfbEncodingPointerPos); -+ rect.r.x = Swap16IfLE((CARD16)x); -+ rect.r.y = Swap16IfLE((CARD16)y); -+ rect.r.w = 0; -+ rect.r.h = 0; -+ -+ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&rect, -+ sz_rfbFramebufferUpdateRectHeader); -+ pVNC->ublen += sz_rfbFramebufferUpdateRectHeader; -+ -+ cl->rfbCursorPosBytesSent += sz_rfbFramebufferUpdateRectHeader; -+ cl->rfbCursorPosUpdatesSent++; -+ -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ -+ cl->cursorX = x; -+ cl->cursorY = y; -+ -+ return TRUE; -+} -+ -+/* -+ * Code to convert cursor source bitmap to the desired pixel format. -+ */ -+ -+#define RGB48_TO_PIXEL(fmt,r,g,b) \ -+ (((CARD32)(r) * ((fmt)->redMax + 1) >> 16) << (fmt)->redShift | \ -+ ((CARD32)(g) * ((fmt)->greenMax + 1) >> 16) << (fmt)->greenShift | \ -+ ((CARD32)(b) * ((fmt)->blueMax + 1) >> 16) << (fmt)->blueShift) -+ -+static int -+EncodeRichCursorData8(buf, fmt, pCursor) -+ char *buf; -+ rfbPixelFormat *fmt; -+ CursorPtr pCursor; -+{ -+ int widthPixels, widthBytes; -+ int x, y, b; -+ CARD8 *src; -+ char pix[2]; -+ CARD8 bitmapByte; -+ -+ pix[0] = (char)RGB48_TO_PIXEL(fmt, pCursor->backRed, pCursor->backGreen, -+ pCursor->backBlue); -+ pix[1] = (char)RGB48_TO_PIXEL(fmt, pCursor->foreRed, pCursor->foreGreen, -+ pCursor->foreBlue); -+ -+ src = (CARD8 *)pCursor->bits->source; -+ widthPixels = pCursor->bits->width; -+ widthBytes = PixmapBytePad(widthPixels, 1); -+ -+ for (y = 0; y < pCursor->bits->height; y++) { -+ for (x = 0; x < widthPixels / 8; x++) { -+ bitmapByte = src[y * widthBytes + x]; -+ if (screenInfo.bitmapBitOrder == LSBFirst) { -+ bitmapByte = _reverse_byte[bitmapByte]; -+ } -+ for (b = 7; b >= 0; b--) { -+ *buf++ = pix[bitmapByte >> b & 1]; -+ } -+ } -+ if (widthPixels % 8) { -+ bitmapByte = src[y * widthBytes + x]; -+ if (screenInfo.bitmapBitOrder == LSBFirst) { -+ bitmapByte = _reverse_byte[bitmapByte]; -+ } -+ for (b = 7; b > 7 - widthPixels % 8; b--) { -+ *buf++ = pix[bitmapByte >> b & 1]; -+ } -+ } -+ } -+ -+ return (widthPixels * pCursor->bits->height); -+} -+ -+#define DEFINE_RICH_ENCODE(bpp) \ -+ \ -+static int \ -+EncodeRichCursorData##bpp(pScreen, buf, fmt, pCursor) \ -+ ScreenPtr pScreen; \ -+ char *buf; \ -+ rfbPixelFormat *fmt; \ -+ CursorPtr pCursor; \ -+{ \ -+ VNCSCREENPTR(pScreen); \ -+ int widthPixels, widthBytes; \ -+ int x, y, b; \ -+ CARD8 *src; \ -+ CARD##bpp pix[2]; \ -+ CARD8 bitmapByte; \ -+ \ -+ pix[0] = (CARD##bpp)RGB48_TO_PIXEL(fmt, pCursor->backRed, \ -+ pCursor->backGreen, \ -+ pCursor->backBlue); \ -+ pix[1] = (CARD##bpp)RGB48_TO_PIXEL(fmt, pCursor->foreRed, \ -+ pCursor->foreGreen, \ -+ pCursor->foreBlue); \ -+ if (!pVNC->rfbServerFormat.bigEndian != !fmt->bigEndian) { \ -+ pix[0] = Swap##bpp(pix[0]); \ -+ pix[1] = Swap##bpp(pix[1]); \ -+ } \ -+ \ -+ src = (CARD8 *)pCursor->bits->source; \ -+ widthPixels = pCursor->bits->width; \ -+ widthBytes = PixmapBytePad(widthPixels, 1); \ -+ \ -+ for (y = 0; y < pCursor->bits->height; y++) { \ -+ for (x = 0; x < widthPixels / 8; x++) { \ -+ bitmapByte = src[y * widthBytes + x]; \ -+ if (screenInfo.bitmapBitOrder == LSBFirst) { \ -+ bitmapByte = _reverse_byte[bitmapByte]; \ -+ } \ -+ for (b = 7; b >= 0; b--) { \ -+ memcpy (buf, (char *)&pix[bitmapByte >> b & 1], \ -+ sizeof(CARD##bpp)); \ -+ buf += sizeof(CARD##bpp); \ -+ } \ -+ } \ -+ if (widthPixels % 8) { \ -+ bitmapByte = src[y * widthBytes + x]; \ -+ if (screenInfo.bitmapBitOrder == LSBFirst) { \ -+ bitmapByte = _reverse_byte[bitmapByte]; \ -+ } \ -+ for (b = 7; b > 7 - widthPixels % 8; b--) { \ -+ memcpy (buf, (char *)&pix[bitmapByte >> b & 1], \ -+ sizeof(CARD##bpp)); \ -+ buf += sizeof(CARD##bpp); \ -+ } \ -+ } \ -+ } \ -+ \ -+ return (widthPixels * pCursor->bits->height * (bpp / 8)); \ -+} -+ -+DEFINE_RICH_ENCODE(16) -+DEFINE_RICH_ENCODE(32) -+ -diff --git a/hw/dmx/vnc/cutpaste.c b/hw/dmx/vnc/cutpaste.c -new file mode 100644 -index 0000000..13aebbb ---- /dev/null -+++ b/hw/dmx/vnc/cutpaste.c -@@ -0,0 +1,87 @@ -+/* -+ * cutpaste.c - routines to deal with cut & paste buffers / selection. -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ */ -+ -+/* -+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. -+ * -+ * This is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This software is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this software; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -+ * USA. -+ */ -+ -+#include -+#define NEED_EVENTS -+#include -+#include -+#include -+#include "rfb.h" -+#include "selection.h" -+#include "input.h" -+ -+extern Selection *CurrentSelections; -+extern int NumCurrentSelections; -+ -+ -+static Bool inSetXCutText = FALSE; -+ -+/* -+ * rfbSetXCutText sets the cut buffer to be the given string. We also clear -+ * the primary selection. Ideally we'd like to set it to the same thing, but I -+ * can't work out how to do that without some kind of helper X client. -+ */ -+ -+void -+rfbSetXCutText(char *str, int len) -+{ -+ int i = 0; -+ -+ inSetXCutText = TRUE; -+ ChangeWindowProperty(WindowTable[0], XA_CUT_BUFFER0, XA_STRING, -+ 8, PropModeReplace, len, -+ (pointer)str, TRUE); -+ -+ while ((i < NumCurrentSelections) && -+ CurrentSelections[i].selection != XA_PRIMARY) -+ i++; -+ -+ if (i < NumCurrentSelections) { -+ xEvent event; -+ -+ if (CurrentSelections[i].client) { -+ event.u.u.type = SelectionClear; -+ event.u.selectionClear.time = GetTimeInMillis(); -+ event.u.selectionClear.window = CurrentSelections[i].window; -+ event.u.selectionClear.atom = CurrentSelections[i].selection; -+ (void) TryClientEvents (CurrentSelections[i].client, &event, 1, -+ NoEventMask, NoEventMask /* CantBeFiltered */, -+ NullGrab); -+ } -+ -+ CurrentSelections[i].window = None; -+ CurrentSelections[i].pWin = NULL; -+ CurrentSelections[i].client = NullClient; -+ } -+ -+ inSetXCutText = FALSE; -+} -+ -+ -+void rfbGotXCutText(char *str, int len) -+{ -+ if (!inSetXCutText) -+ rfbSendServerCutText(str, len); -+} -diff --git a/hw/dmx/vnc/d3des.c b/hw/dmx/vnc/d3des.c -new file mode 100644 -index 0000000..8a358ce ---- /dev/null -+++ b/hw/dmx/vnc/d3des.c -@@ -0,0 +1,440 @@ -+/* -+ * This is D3DES (V5.09) by Richard Outerbridge with the double and -+ * triple-length support removed for use in VNC. Also the bytebit[] array -+ * has been reversed so that the most significant bit in each byte of the -+ * key is ignored, not the least significant. -+ * -+ * These changes are: -+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. -+ * -+ * This software is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -+ */ -+ -+/* D3DES (V5.09) - -+ * -+ * A portable, public domain, version of the Data Encryption Standard. -+ * -+ * Written with Symantec's THINK (Lightspeed) C by Richard Outerbridge. -+ * Thanks to: Dan Hoey for his excellent Initial and Inverse permutation -+ * code; Jim Gillogly & Phil Karn for the DES key schedule code; Dennis -+ * Ferguson, Eric Young and Dana How for comparing notes; and Ray Lau, -+ * for humouring me on. -+ * -+ * Copyright (c) 1988,1989,1990,1991,1992 by Richard Outerbridge. -+ * (GEnie : OUTER; CIS : [71755,204]) Graven Imagery, 1992. -+ */ -+ -+#include "d3des.h" -+ -+static void scrunch(unsigned char *, unsigned long *); -+static void unscrun(unsigned long *, unsigned char *); -+static void desfunc(unsigned long *, unsigned long *); -+static void cookey(unsigned long *); -+ -+static unsigned long KnL[32] = { 0L }; -+static unsigned long KnR[32] = { 0L }; -+static unsigned long Kn3[32] = { 0L }; -+static unsigned char Df_Key[24] = { -+ 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef, -+ 0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10, -+ 0x89,0xab,0xcd,0xef,0x01,0x23,0x45,0x67 }; -+ -+static unsigned short bytebit[8] = { -+ 01, 02, 04, 010, 020, 040, 0100, 0200 }; -+ -+static unsigned long bigbyte[24] = { -+ 0x800000L, 0x400000L, 0x200000L, 0x100000L, -+ 0x80000L, 0x40000L, 0x20000L, 0x10000L, -+ 0x8000L, 0x4000L, 0x2000L, 0x1000L, -+ 0x800L, 0x400L, 0x200L, 0x100L, -+ 0x80L, 0x40L, 0x20L, 0x10L, -+ 0x8L, 0x4L, 0x2L, 0x1L }; -+ -+/* Use the key schedule specified in the Standard (ANSI X3.92-1981). */ -+ -+static unsigned char pc1[56] = { -+ 56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17, -+ 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35, -+ 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21, -+ 13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3 }; -+ -+static unsigned char totrot[16] = { -+ 1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28 }; -+ -+static unsigned char pc2[48] = { -+ 13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9, -+ 22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1, -+ 40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47, -+ 43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31 }; -+ -+void deskey(key, edf) /* Thanks to James Gillogly & Phil Karn! */ -+unsigned char *key; -+int edf; -+{ -+ register int i, j, l, m, n; -+ unsigned char pc1m[56], pcr[56]; -+ unsigned long kn[32]; -+ -+ for ( j = 0; j < 56; j++ ) { -+ l = pc1[j]; -+ m = l & 07; -+ pc1m[j] = (key[l >> 3] & bytebit[m]) ? 1 : 0; -+ } -+ for( i = 0; i < 16; i++ ) { -+ if( edf == DE1 ) m = (15 - i) << 1; -+ else m = i << 1; -+ n = m + 1; -+ kn[m] = kn[n] = 0L; -+ for( j = 0; j < 28; j++ ) { -+ l = j + totrot[i]; -+ if( l < 28 ) pcr[j] = pc1m[l]; -+ else pcr[j] = pc1m[l - 28]; -+ } -+ for( j = 28; j < 56; j++ ) { -+ l = j + totrot[i]; -+ if( l < 56 ) pcr[j] = pc1m[l]; -+ else pcr[j] = pc1m[l - 28]; -+ } -+ for( j = 0; j < 24; j++ ) { -+ if( pcr[pc2[j]] ) kn[m] |= bigbyte[j]; -+ if( pcr[pc2[j+24]] ) kn[n] |= bigbyte[j]; -+ } -+ } -+ cookey(kn); -+ return; -+ } -+ -+static void cookey(raw1) -+register unsigned long *raw1; -+{ -+ register unsigned long *cook, *raw0; -+ unsigned long dough[32]; -+ register int i; -+ -+ cook = dough; -+ for( i = 0; i < 16; i++, raw1++ ) { -+ raw0 = raw1++; -+ *cook = (*raw0 & 0x00fc0000L) << 6; -+ *cook |= (*raw0 & 0x00000fc0L) << 10; -+ *cook |= (*raw1 & 0x00fc0000L) >> 10; -+ *cook++ |= (*raw1 & 0x00000fc0L) >> 6; -+ *cook = (*raw0 & 0x0003f000L) << 12; -+ *cook |= (*raw0 & 0x0000003fL) << 16; -+ *cook |= (*raw1 & 0x0003f000L) >> 4; -+ *cook++ |= (*raw1 & 0x0000003fL); -+ } -+ usekey(dough); -+ return; -+ } -+ -+void cpkey(into) -+register unsigned long *into; -+{ -+ register unsigned long *from, *endp; -+ -+ from = KnL, endp = &KnL[32]; -+ while( from < endp ) *into++ = *from++; -+ return; -+ } -+ -+void usekey(from) -+register unsigned long *from; -+{ -+ register unsigned long *to, *endp; -+ -+ to = KnL, endp = &KnL[32]; -+ while( to < endp ) *to++ = *from++; -+ return; -+ } -+ -+void des(inblock, outblock) -+unsigned char *inblock, *outblock; -+{ -+ unsigned long work[2]; -+ -+ scrunch(inblock, work); -+ desfunc(work, KnL); -+ unscrun(work, outblock); -+ return; -+ } -+ -+static void scrunch(outof, into) -+register unsigned char *outof; -+register unsigned long *into; -+{ -+ *into = (*outof++ & 0xffL) << 24; -+ *into |= (*outof++ & 0xffL) << 16; -+ *into |= (*outof++ & 0xffL) << 8; -+ *into++ |= (*outof++ & 0xffL); -+ *into = (*outof++ & 0xffL) << 24; -+ *into |= (*outof++ & 0xffL) << 16; -+ *into |= (*outof++ & 0xffL) << 8; -+ *into |= (*outof & 0xffL); -+ return; -+ } -+ -+static void unscrun(outof, into) -+register unsigned long *outof; -+register unsigned char *into; -+{ -+ *into++ = (*outof >> 24) & 0xffL; -+ *into++ = (*outof >> 16) & 0xffL; -+ *into++ = (*outof >> 8) & 0xffL; -+ *into++ = *outof++ & 0xffL; -+ *into++ = (*outof >> 24) & 0xffL; -+ *into++ = (*outof >> 16) & 0xffL; -+ *into++ = (*outof >> 8) & 0xffL; -+ *into = *outof & 0xffL; -+ return; -+ } -+ -+static unsigned long SP1[64] = { -+ 0x01010400L, 0x00000000L, 0x00010000L, 0x01010404L, -+ 0x01010004L, 0x00010404L, 0x00000004L, 0x00010000L, -+ 0x00000400L, 0x01010400L, 0x01010404L, 0x00000400L, -+ 0x01000404L, 0x01010004L, 0x01000000L, 0x00000004L, -+ 0x00000404L, 0x01000400L, 0x01000400L, 0x00010400L, -+ 0x00010400L, 0x01010000L, 0x01010000L, 0x01000404L, -+ 0x00010004L, 0x01000004L, 0x01000004L, 0x00010004L, -+ 0x00000000L, 0x00000404L, 0x00010404L, 0x01000000L, -+ 0x00010000L, 0x01010404L, 0x00000004L, 0x01010000L, -+ 0x01010400L, 0x01000000L, 0x01000000L, 0x00000400L, -+ 0x01010004L, 0x00010000L, 0x00010400L, 0x01000004L, -+ 0x00000400L, 0x00000004L, 0x01000404L, 0x00010404L, -+ 0x01010404L, 0x00010004L, 0x01010000L, 0x01000404L, -+ 0x01000004L, 0x00000404L, 0x00010404L, 0x01010400L, -+ 0x00000404L, 0x01000400L, 0x01000400L, 0x00000000L, -+ 0x00010004L, 0x00010400L, 0x00000000L, 0x01010004L }; -+ -+static unsigned long SP2[64] = { -+ 0x80108020L, 0x80008000L, 0x00008000L, 0x00108020L, -+ 0x00100000L, 0x00000020L, 0x80100020L, 0x80008020L, -+ 0x80000020L, 0x80108020L, 0x80108000L, 0x80000000L, -+ 0x80008000L, 0x00100000L, 0x00000020L, 0x80100020L, -+ 0x00108000L, 0x00100020L, 0x80008020L, 0x00000000L, -+ 0x80000000L, 0x00008000L, 0x00108020L, 0x80100000L, -+ 0x00100020L, 0x80000020L, 0x00000000L, 0x00108000L, -+ 0x00008020L, 0x80108000L, 0x80100000L, 0x00008020L, -+ 0x00000000L, 0x00108020L, 0x80100020L, 0x00100000L, -+ 0x80008020L, 0x80100000L, 0x80108000L, 0x00008000L, -+ 0x80100000L, 0x80008000L, 0x00000020L, 0x80108020L, -+ 0x00108020L, 0x00000020L, 0x00008000L, 0x80000000L, -+ 0x00008020L, 0x80108000L, 0x00100000L, 0x80000020L, -+ 0x00100020L, 0x80008020L, 0x80000020L, 0x00100020L, -+ 0x00108000L, 0x00000000L, 0x80008000L, 0x00008020L, -+ 0x80000000L, 0x80100020L, 0x80108020L, 0x00108000L }; -+ -+static unsigned long SP3[64] = { -+ 0x00000208L, 0x08020200L, 0x00000000L, 0x08020008L, -+ 0x08000200L, 0x00000000L, 0x00020208L, 0x08000200L, -+ 0x00020008L, 0x08000008L, 0x08000008L, 0x00020000L, -+ 0x08020208L, 0x00020008L, 0x08020000L, 0x00000208L, -+ 0x08000000L, 0x00000008L, 0x08020200L, 0x00000200L, -+ 0x00020200L, 0x08020000L, 0x08020008L, 0x00020208L, -+ 0x08000208L, 0x00020200L, 0x00020000L, 0x08000208L, -+ 0x00000008L, 0x08020208L, 0x00000200L, 0x08000000L, -+ 0x08020200L, 0x08000000L, 0x00020008L, 0x00000208L, -+ 0x00020000L, 0x08020200L, 0x08000200L, 0x00000000L, -+ 0x00000200L, 0x00020008L, 0x08020208L, 0x08000200L, -+ 0x08000008L, 0x00000200L, 0x00000000L, 0x08020008L, -+ 0x08000208L, 0x00020000L, 0x08000000L, 0x08020208L, -+ 0x00000008L, 0x00020208L, 0x00020200L, 0x08000008L, -+ 0x08020000L, 0x08000208L, 0x00000208L, 0x08020000L, -+ 0x00020208L, 0x00000008L, 0x08020008L, 0x00020200L }; -+ -+static unsigned long SP4[64] = { -+ 0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L, -+ 0x00802080L, 0x00800081L, 0x00800001L, 0x00002001L, -+ 0x00000000L, 0x00802000L, 0x00802000L, 0x00802081L, -+ 0x00000081L, 0x00000000L, 0x00800080L, 0x00800001L, -+ 0x00000001L, 0x00002000L, 0x00800000L, 0x00802001L, -+ 0x00000080L, 0x00800000L, 0x00002001L, 0x00002080L, -+ 0x00800081L, 0x00000001L, 0x00002080L, 0x00800080L, -+ 0x00002000L, 0x00802080L, 0x00802081L, 0x00000081L, -+ 0x00800080L, 0x00800001L, 0x00802000L, 0x00802081L, -+ 0x00000081L, 0x00000000L, 0x00000000L, 0x00802000L, -+ 0x00002080L, 0x00800080L, 0x00800081L, 0x00000001L, -+ 0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L, -+ 0x00802081L, 0x00000081L, 0x00000001L, 0x00002000L, -+ 0x00800001L, 0x00002001L, 0x00802080L, 0x00800081L, -+ 0x00002001L, 0x00002080L, 0x00800000L, 0x00802001L, -+ 0x00000080L, 0x00800000L, 0x00002000L, 0x00802080L }; -+ -+static unsigned long SP5[64] = { -+ 0x00000100L, 0x02080100L, 0x02080000L, 0x42000100L, -+ 0x00080000L, 0x00000100L, 0x40000000L, 0x02080000L, -+ 0x40080100L, 0x00080000L, 0x02000100L, 0x40080100L, -+ 0x42000100L, 0x42080000L, 0x00080100L, 0x40000000L, -+ 0x02000000L, 0x40080000L, 0x40080000L, 0x00000000L, -+ 0x40000100L, 0x42080100L, 0x42080100L, 0x02000100L, -+ 0x42080000L, 0x40000100L, 0x00000000L, 0x42000000L, -+ 0x02080100L, 0x02000000L, 0x42000000L, 0x00080100L, -+ 0x00080000L, 0x42000100L, 0x00000100L, 0x02000000L, -+ 0x40000000L, 0x02080000L, 0x42000100L, 0x40080100L, -+ 0x02000100L, 0x40000000L, 0x42080000L, 0x02080100L, -+ 0x40080100L, 0x00000100L, 0x02000000L, 0x42080000L, -+ 0x42080100L, 0x00080100L, 0x42000000L, 0x42080100L, -+ 0x02080000L, 0x00000000L, 0x40080000L, 0x42000000L, -+ 0x00080100L, 0x02000100L, 0x40000100L, 0x00080000L, -+ 0x00000000L, 0x40080000L, 0x02080100L, 0x40000100L }; -+ -+static unsigned long SP6[64] = { -+ 0x20000010L, 0x20400000L, 0x00004000L, 0x20404010L, -+ 0x20400000L, 0x00000010L, 0x20404010L, 0x00400000L, -+ 0x20004000L, 0x00404010L, 0x00400000L, 0x20000010L, -+ 0x00400010L, 0x20004000L, 0x20000000L, 0x00004010L, -+ 0x00000000L, 0x00400010L, 0x20004010L, 0x00004000L, -+ 0x00404000L, 0x20004010L, 0x00000010L, 0x20400010L, -+ 0x20400010L, 0x00000000L, 0x00404010L, 0x20404000L, -+ 0x00004010L, 0x00404000L, 0x20404000L, 0x20000000L, -+ 0x20004000L, 0x00000010L, 0x20400010L, 0x00404000L, -+ 0x20404010L, 0x00400000L, 0x00004010L, 0x20000010L, -+ 0x00400000L, 0x20004000L, 0x20000000L, 0x00004010L, -+ 0x20000010L, 0x20404010L, 0x00404000L, 0x20400000L, -+ 0x00404010L, 0x20404000L, 0x00000000L, 0x20400010L, -+ 0x00000010L, 0x00004000L, 0x20400000L, 0x00404010L, -+ 0x00004000L, 0x00400010L, 0x20004010L, 0x00000000L, -+ 0x20404000L, 0x20000000L, 0x00400010L, 0x20004010L }; -+ -+static unsigned long SP7[64] = { -+ 0x00200000L, 0x04200002L, 0x04000802L, 0x00000000L, -+ 0x00000800L, 0x04000802L, 0x00200802L, 0x04200800L, -+ 0x04200802L, 0x00200000L, 0x00000000L, 0x04000002L, -+ 0x00000002L, 0x04000000L, 0x04200002L, 0x00000802L, -+ 0x04000800L, 0x00200802L, 0x00200002L, 0x04000800L, -+ 0x04000002L, 0x04200000L, 0x04200800L, 0x00200002L, -+ 0x04200000L, 0x00000800L, 0x00000802L, 0x04200802L, -+ 0x00200800L, 0x00000002L, 0x04000000L, 0x00200800L, -+ 0x04000000L, 0x00200800L, 0x00200000L, 0x04000802L, -+ 0x04000802L, 0x04200002L, 0x04200002L, 0x00000002L, -+ 0x00200002L, 0x04000000L, 0x04000800L, 0x00200000L, -+ 0x04200800L, 0x00000802L, 0x00200802L, 0x04200800L, -+ 0x00000802L, 0x04000002L, 0x04200802L, 0x04200000L, -+ 0x00200800L, 0x00000000L, 0x00000002L, 0x04200802L, -+ 0x00000000L, 0x00200802L, 0x04200000L, 0x00000800L, -+ 0x04000002L, 0x04000800L, 0x00000800L, 0x00200002L }; -+ -+static unsigned long SP8[64] = { -+ 0x10001040L, 0x00001000L, 0x00040000L, 0x10041040L, -+ 0x10000000L, 0x10001040L, 0x00000040L, 0x10000000L, -+ 0x00040040L, 0x10040000L, 0x10041040L, 0x00041000L, -+ 0x10041000L, 0x00041040L, 0x00001000L, 0x00000040L, -+ 0x10040000L, 0x10000040L, 0x10001000L, 0x00001040L, -+ 0x00041000L, 0x00040040L, 0x10040040L, 0x10041000L, -+ 0x00001040L, 0x00000000L, 0x00000000L, 0x10040040L, -+ 0x10000040L, 0x10001000L, 0x00041040L, 0x00040000L, -+ 0x00041040L, 0x00040000L, 0x10041000L, 0x00001000L, -+ 0x00000040L, 0x10040040L, 0x00001000L, 0x00041040L, -+ 0x10001000L, 0x00000040L, 0x10000040L, 0x10040000L, -+ 0x10040040L, 0x10000000L, 0x00040000L, 0x10001040L, -+ 0x00000000L, 0x10041040L, 0x00040040L, 0x10000040L, -+ 0x10040000L, 0x10001000L, 0x10001040L, 0x00000000L, -+ 0x10041040L, 0x00041000L, 0x00041000L, 0x00001040L, -+ 0x00001040L, 0x00040040L, 0x10000000L, 0x10041000L }; -+ -+static void desfunc(block, keys) -+register unsigned long *block, *keys; -+{ -+ register unsigned long fval, work, right, leftt; -+ register int round; -+ -+ leftt = block[0]; -+ right = block[1]; -+ work = ((leftt >> 4) ^ right) & 0x0f0f0f0fL; -+ right ^= work; -+ leftt ^= (work << 4); -+ work = ((leftt >> 16) ^ right) & 0x0000ffffL; -+ right ^= work; -+ leftt ^= (work << 16); -+ work = ((right >> 2) ^ leftt) & 0x33333333L; -+ leftt ^= work; -+ right ^= (work << 2); -+ work = ((right >> 8) ^ leftt) & 0x00ff00ffL; -+ leftt ^= work; -+ right ^= (work << 8); -+ right = ((right << 1) | ((right >> 31) & 1L)) & 0xffffffffL; -+ work = (leftt ^ right) & 0xaaaaaaaaL; -+ leftt ^= work; -+ right ^= work; -+ leftt = ((leftt << 1) | ((leftt >> 31) & 1L)) & 0xffffffffL; -+ -+ for( round = 0; round < 8; round++ ) { -+ work = (right << 28) | (right >> 4); -+ work ^= *keys++; -+ fval = SP7[ work & 0x3fL]; -+ fval |= SP5[(work >> 8) & 0x3fL]; -+ fval |= SP3[(work >> 16) & 0x3fL]; -+ fval |= SP1[(work >> 24) & 0x3fL]; -+ work = right ^ *keys++; -+ fval |= SP8[ work & 0x3fL]; -+ fval |= SP6[(work >> 8) & 0x3fL]; -+ fval |= SP4[(work >> 16) & 0x3fL]; -+ fval |= SP2[(work >> 24) & 0x3fL]; -+ leftt ^= fval; -+ work = (leftt << 28) | (leftt >> 4); -+ work ^= *keys++; -+ fval = SP7[ work & 0x3fL]; -+ fval |= SP5[(work >> 8) & 0x3fL]; -+ fval |= SP3[(work >> 16) & 0x3fL]; -+ fval |= SP1[(work >> 24) & 0x3fL]; -+ work = leftt ^ *keys++; -+ fval |= SP8[ work & 0x3fL]; -+ fval |= SP6[(work >> 8) & 0x3fL]; -+ fval |= SP4[(work >> 16) & 0x3fL]; -+ fval |= SP2[(work >> 24) & 0x3fL]; -+ right ^= fval; -+ } -+ -+ right = (right << 31) | (right >> 1); -+ work = (leftt ^ right) & 0xaaaaaaaaL; -+ leftt ^= work; -+ right ^= work; -+ leftt = (leftt << 31) | (leftt >> 1); -+ work = ((leftt >> 8) ^ right) & 0x00ff00ffL; -+ right ^= work; -+ leftt ^= (work << 8); -+ work = ((leftt >> 2) ^ right) & 0x33333333L; -+ right ^= work; -+ leftt ^= (work << 2); -+ work = ((right >> 16) ^ leftt) & 0x0000ffffL; -+ leftt ^= work; -+ right ^= (work << 16); -+ work = ((right >> 4) ^ leftt) & 0x0f0f0f0fL; -+ leftt ^= work; -+ right ^= (work << 4); -+ *block++ = right; -+ *block = leftt; -+ return; -+ } -+ -+/* Validation sets: -+ * -+ * Single-length key, single-length plaintext - -+ * Key : 0123 4567 89ab cdef -+ * Plain : 0123 4567 89ab cde7 -+ * Cipher : c957 4425 6a5e d31d -+ * -+ * Double-length key, single-length plaintext - -+ * Key : 0123 4567 89ab cdef fedc ba98 7654 3210 -+ * Plain : 0123 4567 89ab cde7 -+ * Cipher : 7f1d 0a77 826b 8aff -+ * -+ * Double-length key, double-length plaintext - -+ * Key : 0123 4567 89ab cdef fedc ba98 7654 3210 -+ * Plain : 0123 4567 89ab cdef 0123 4567 89ab cdff -+ * Cipher : 27a0 8440 406a df60 278f 47cf 42d6 15d7 -+ * -+ * Triple-length key, single-length plaintext - -+ * Key : 0123 4567 89ab cdef fedc ba98 7654 3210 89ab cdef 0123 4567 -+ * Plain : 0123 4567 89ab cde7 -+ * Cipher : de0b 7c06 ae5e 0ed5 -+ * -+ * Triple-length key, double-length plaintext - -+ * Key : 0123 4567 89ab cdef fedc ba98 7654 3210 89ab cdef 0123 4567 -+ * Plain : 0123 4567 89ab cdef 0123 4567 89ab cdff -+ * Cipher : ad0d 1b30 ac17 cf07 0ed1 1c63 81e4 4de5 -+ * -+ * d3des V5.0a rwo 9208.07 18:44 Graven Imagery -+ **********************************************************************/ -diff --git a/hw/dmx/vnc/d3des.h b/hw/dmx/vnc/d3des.h -new file mode 100644 -index 0000000..ea3da44 ---- /dev/null -+++ b/hw/dmx/vnc/d3des.h -@@ -0,0 +1,51 @@ -+/* -+ * This is D3DES (V5.09) by Richard Outerbridge with the double and -+ * triple-length support removed for use in VNC. -+ * -+ * These changes are: -+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. -+ * -+ * This software is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -+ */ -+ -+/* d3des.h - -+ * -+ * Headers and defines for d3des.c -+ * Graven Imagery, 1992. -+ * -+ * Copyright (c) 1988,1989,1990,1991,1992 by Richard Outerbridge -+ * (GEnie : OUTER; CIS : [71755,204]) -+ */ -+ -+#define EN0 0 /* MODE == encrypt */ -+#define DE1 1 /* MODE == decrypt */ -+ -+extern void deskey(unsigned char *, int); -+/* hexkey[8] MODE -+ * Sets the internal key register according to the hexadecimal -+ * key contained in the 8 bytes of hexkey, according to the DES, -+ * for encryption or decryption according to MODE. -+ */ -+ -+extern void usekey(unsigned long *); -+/* cookedkey[32] -+ * Loads the internal key register with the data in cookedkey. -+ */ -+ -+extern void cpkey(unsigned long *); -+/* cookedkey[32] -+ * Copies the contents of the internal key register into the storage -+ * located at &cookedkey[0]. -+ */ -+ -+extern void des(unsigned char *, unsigned char *); -+/* from[8] to[8] -+ * Encrypts/Decrypts (according to the key currently loaded in the -+ * internal key register) one block of eight bytes at address 'from' -+ * into the block at address 'to'. They can be the same. -+ */ -+ -+/* d3des.h V5.09 rwo 9208.04 15:06 Graven Imagery -+ ********************************************************************/ -diff --git a/hw/dmx/vnc/dispcur.c b/hw/dmx/vnc/dispcur.c -new file mode 100644 -index 0000000..ceea9fa ---- /dev/null -+++ b/hw/dmx/vnc/dispcur.c -@@ -0,0 +1,804 @@ -+/* -+ * dispcur.c -+ * -+ * cursor display routines - based on midispcur.c -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ */ -+ -+/* -+ * 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) 1989 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. -+*/ -+ -+#if HAVE_DMX_CONFIG_H -+#include "dmx-config.h" -+#endif -+ -+#define NEED_EVENTS -+# include "X11/X.h" -+# include "misc.h" -+# include "input.h" -+# include "cursorstr.h" -+# include "windowstr.h" -+# include "regionstr.h" -+# include "dixstruct.h" -+# include "scrnintstr.h" -+# include "servermd.h" -+# include "mipointer.h" -+# include "sprite.h" -+# include "gcstruct.h" -+ -+#ifdef ARGB_CURSOR -+# include "picturestr.h" -+#endif -+ -+/* per-screen private data */ -+ -+static int rfbDCScreenIndex; -+static unsigned long rfbDCGeneration = 0; -+ -+static Bool rfbDCCloseScreen(int index, ScreenPtr pScreen); -+ -+typedef struct { -+ GCPtr pSourceGC, pMaskGC; -+ GCPtr pSaveGC, pRestoreGC; -+ GCPtr pMoveGC; -+ GCPtr pPixSourceGC, pPixMaskGC; -+ CloseScreenProcPtr CloseScreen; -+ PixmapPtr pSave, pTemp; -+#ifdef ARGB_CURSOR -+ PicturePtr pRootPicture; -+ PicturePtr pTempPicture; -+#endif -+} rfbDCScreenRec, *rfbDCScreenPtr; -+ -+/* per-cursor per-screen private data */ -+typedef struct { -+ PixmapPtr sourceBits; /* source bits */ -+ PixmapPtr maskBits; /* mask bits */ -+#ifdef ARGB_CURSOR -+ PicturePtr pPicture; -+#endif -+} rfbDCCursorRec, *rfbDCCursorPtr; -+ -+/* -+ * sprite/cursor method table -+ */ -+ -+static Bool rfbDCRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor); -+static Bool rfbDCUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCursor); -+static Bool rfbDCPutUpCursor(ScreenPtr pScreen, CursorPtr pCursor, -+ int x, int y, unsigned long source, -+ unsigned long mask); -+static Bool rfbDCSaveUnderCursor(ScreenPtr pScreen, int x, int y, -+ int w, int h); -+static Bool rfbDCRestoreUnderCursor(ScreenPtr pScreen, int x, int y, -+ int w, int h); -+static Bool rfbDCMoveCursor(ScreenPtr pScreen, CursorPtr pCursor, -+ int x, int y, int w, int h, int dx, int dy, -+ unsigned long source, unsigned long mask); -+static Bool rfbDCChangeSave(ScreenPtr pScreen, int x, int y, int w, int h, -+ int dx, int dy); -+ -+static rfbSpriteCursorFuncRec rfbDCFuncs = { -+ rfbDCRealizeCursor, -+ rfbDCUnrealizeCursor, -+ rfbDCPutUpCursor, -+ rfbDCSaveUnderCursor, -+ rfbDCRestoreUnderCursor, -+ rfbDCMoveCursor, -+ rfbDCChangeSave, -+}; -+ -+Bool -+rfbDCInitialize (pScreen, screenFuncs) -+ ScreenPtr pScreen; -+ miPointerScreenFuncPtr screenFuncs; -+{ -+ rfbDCScreenPtr pScreenPriv; -+ -+ if (rfbDCGeneration != serverGeneration) -+ { -+ rfbDCScreenIndex = AllocateScreenPrivateIndex (); -+ if (rfbDCScreenIndex < 0) -+ return FALSE; -+ rfbDCGeneration = serverGeneration; -+ } -+ pScreenPriv = (rfbDCScreenPtr) xalloc (sizeof (rfbDCScreenRec)); -+ if (!pScreenPriv) -+ return FALSE; -+ -+ /* -+ * initialize the entire private structure to zeros -+ */ -+ -+ pScreenPriv->pSourceGC = -+ pScreenPriv->pMaskGC = -+ pScreenPriv->pSaveGC = -+ pScreenPriv->pRestoreGC = -+ pScreenPriv->pMoveGC = -+ pScreenPriv->pPixSourceGC = -+ pScreenPriv->pPixMaskGC = NULL; -+#ifdef ARGB_CURSOR -+ pScreenPriv->pRootPicture = NULL; -+ pScreenPriv->pTempPicture = NULL; -+#endif -+ -+ pScreenPriv->pSave = pScreenPriv->pTemp = NULL; -+ -+ pScreenPriv->CloseScreen = pScreen->CloseScreen; -+ pScreen->CloseScreen = rfbDCCloseScreen; -+ -+ pScreen->devPrivates[rfbDCScreenIndex].ptr = (pointer) pScreenPriv; -+ -+ if (!rfbSpriteInitialize (pScreen, &rfbDCFuncs, screenFuncs)) -+ { -+ xfree ((pointer) pScreenPriv); -+ return FALSE; -+ } -+ return TRUE; -+} -+ -+#define tossGC(gc) (gc ? FreeGC (gc, (GContext) 0) : 0) -+#define tossPix(pix) (pix ? (*pScreen->DestroyPixmap) (pix) : TRUE) -+#define tossPict(pict) (pict ? FreePicture (pict, 0) : 0) -+ -+static Bool -+rfbDCCloseScreen (index, pScreen) -+ ScreenPtr pScreen; -+{ -+ rfbDCScreenPtr pScreenPriv; -+ -+ pScreenPriv = (rfbDCScreenPtr) pScreen->devPrivates[rfbDCScreenIndex].ptr; -+ pScreen->CloseScreen = pScreenPriv->CloseScreen; -+ tossGC (pScreenPriv->pSourceGC); -+ tossGC (pScreenPriv->pMaskGC); -+ tossGC (pScreenPriv->pSaveGC); -+ tossGC (pScreenPriv->pRestoreGC); -+ tossGC (pScreenPriv->pMoveGC); -+ tossGC (pScreenPriv->pPixSourceGC); -+ tossGC (pScreenPriv->pPixMaskGC); -+ tossPix (pScreenPriv->pSave); -+ tossPix (pScreenPriv->pTemp); -+#ifdef ARGB_CURSOR -+ tossPict (pScreenPriv->pRootPicture); -+ tossPict (pScreenPriv->pTempPicture); -+#endif -+ xfree ((pointer) pScreenPriv); -+ return (*pScreen->CloseScreen) (index, pScreen); -+} -+ -+static Bool -+rfbDCRealizeCursor (pScreen, pCursor) -+ ScreenPtr pScreen; -+ CursorPtr pCursor; -+{ -+ if (pCursor->bits->refcnt <= 1) -+ pCursor->bits->devPriv[pScreen->myNum] = (pointer)NULL; -+ return TRUE; -+} -+ -+#ifdef ARGB_CURSOR -+#define EnsurePicture(picture,draw,win) (picture || rfbDCMakePicture(&picture,draw,win)) -+ -+static VisualPtr -+rfbDCGetWindowVisual (WindowPtr pWin) -+{ -+ ScreenPtr pScreen = pWin->drawable.pScreen; -+ VisualID vid = wVisual (pWin); -+ int i; -+ -+ for (i = 0; i < pScreen->numVisuals; i++) -+ if (pScreen->visuals[i].vid == vid) -+ return &pScreen->visuals[i]; -+ return 0; -+} -+ -+static PicturePtr -+rfbDCMakePicture (PicturePtr *ppPicture, DrawablePtr pDraw, WindowPtr pWin) -+{ -+ ScreenPtr pScreen = pDraw->pScreen; -+ VisualPtr pVisual; -+ PictFormatPtr pFormat; -+ XID subwindow_mode = IncludeInferiors; -+ PicturePtr pPicture; -+ int error; -+ -+ pVisual = rfbDCGetWindowVisual (pWin); -+ if (!pVisual) -+ return 0; -+ pFormat = PictureMatchVisual (pScreen, pDraw->depth, pVisual); -+ if (!pFormat) -+ return 0; -+ pPicture = CreatePicture (0, pDraw, pFormat, -+ CPSubwindowMode, &subwindow_mode, -+ serverClient, &error); -+ *ppPicture = pPicture; -+ return pPicture; -+} -+#endif -+ -+static rfbDCCursorPtr -+rfbDCRealize (pScreen, pCursor) -+ ScreenPtr pScreen; -+ CursorPtr pCursor; -+{ -+ rfbDCCursorPtr pPriv; -+ GCPtr pGC; -+ XID gcvals[3]; -+ -+ pPriv = (rfbDCCursorPtr) xalloc (sizeof (rfbDCCursorRec)); -+ if (!pPriv) -+ return (rfbDCCursorPtr)NULL; -+#ifdef ARGB_CURSOR -+ if (pCursor->bits->argb) -+ { -+ PixmapPtr pPixmap; -+ PictFormatPtr pFormat; -+ int error; -+ -+ pFormat = PictureMatchFormat (pScreen, 32, PICT_a8r8g8b8); -+ if (!pFormat) -+ { -+ xfree ((pointer) pPriv); -+ return (rfbDCCursorPtr)NULL; -+ } -+ -+ pPriv->sourceBits = 0; -+ pPriv->maskBits = 0; -+ pPixmap = (*pScreen->CreatePixmap) (pScreen, pCursor->bits->width, -+ pCursor->bits->height, 32); -+ if (!pPixmap) -+ { -+ xfree ((pointer) pPriv); -+ return (rfbDCCursorPtr)NULL; -+ } -+ pGC = GetScratchGC (32, pScreen); -+ if (!pGC) -+ { -+ (*pScreen->DestroyPixmap) (pPixmap); -+ xfree ((pointer) pPriv); -+ return (rfbDCCursorPtr)NULL; -+ } -+ ValidateGC (&pPixmap->drawable, pGC); -+ (*pGC->ops->PutImage) (&pPixmap->drawable, pGC, 32, -+ 0, 0, pCursor->bits->width, -+ pCursor->bits->height, -+ 0, ZPixmap, (char *) pCursor->bits->argb); -+ FreeScratchGC (pGC); -+ pPriv->pPicture = CreatePicture (0, &pPixmap->drawable, -+ pFormat, 0, 0, serverClient, &error); -+ (*pScreen->DestroyPixmap) (pPixmap); -+ if (!pPriv->pPicture) -+ { -+ xfree ((pointer) pPriv); -+ return (rfbDCCursorPtr)NULL; -+ } -+ pCursor->bits->devPriv[pScreen->myNum] = (pointer) pPriv; -+ return pPriv; -+ } -+ pPriv->pPicture = 0; -+#endif -+ pPriv->sourceBits = (*pScreen->CreatePixmap) (pScreen, pCursor->bits->width, pCursor->bits->height, 1); -+ if (!pPriv->sourceBits) -+ { -+ xfree ((pointer) pPriv); -+ return (rfbDCCursorPtr)NULL; -+ } -+ pPriv->maskBits = (*pScreen->CreatePixmap) (pScreen, pCursor->bits->width, pCursor->bits->height, 1); -+ if (!pPriv->maskBits) -+ { -+ (*pScreen->DestroyPixmap) (pPriv->sourceBits); -+ xfree ((pointer) pPriv); -+ return (rfbDCCursorPtr)NULL; -+ } -+ pCursor->bits->devPriv[pScreen->myNum] = (pointer) pPriv; -+ -+ /* create the two sets of bits, clipping as appropriate */ -+ -+ pGC = GetScratchGC (1, pScreen); -+ if (!pGC) -+ { -+ (void) rfbDCUnrealizeCursor (pScreen, pCursor); -+ return (rfbDCCursorPtr)NULL; -+ } -+ -+ ValidateGC ((DrawablePtr)pPriv->sourceBits, pGC); -+ (*pGC->ops->PutImage) ((DrawablePtr)pPriv->sourceBits, pGC, 1, -+ 0, 0, pCursor->bits->width, pCursor->bits->height, -+ 0, XYPixmap, (char *)pCursor->bits->source); -+ gcvals[0] = GXand; -+ ChangeGC (pGC, GCFunction, gcvals); -+ ValidateGC ((DrawablePtr)pPriv->sourceBits, pGC); -+ (*pGC->ops->PutImage) ((DrawablePtr)pPriv->sourceBits, pGC, 1, -+ 0, 0, pCursor->bits->width, pCursor->bits->height, -+ 0, XYPixmap, (char *)pCursor->bits->mask); -+ -+ /* mask bits -- pCursor->mask & ~pCursor->source */ -+ gcvals[0] = GXcopy; -+ ChangeGC (pGC, GCFunction, gcvals); -+ ValidateGC ((DrawablePtr)pPriv->maskBits, pGC); -+ (*pGC->ops->PutImage) ((DrawablePtr)pPriv->maskBits, pGC, 1, -+ 0, 0, pCursor->bits->width, pCursor->bits->height, -+ 0, XYPixmap, (char *)pCursor->bits->mask); -+ gcvals[0] = GXandInverted; -+ ChangeGC (pGC, GCFunction, gcvals); -+ ValidateGC ((DrawablePtr)pPriv->maskBits, pGC); -+ (*pGC->ops->PutImage) ((DrawablePtr)pPriv->maskBits, pGC, 1, -+ 0, 0, pCursor->bits->width, pCursor->bits->height, -+ 0, XYPixmap, (char *)pCursor->bits->source); -+ FreeScratchGC (pGC); -+ return pPriv; -+} -+ -+static Bool -+rfbDCUnrealizeCursor (pScreen, pCursor) -+ ScreenPtr pScreen; -+ CursorPtr pCursor; -+{ -+ rfbDCCursorPtr pPriv; -+ -+ pPriv = (rfbDCCursorPtr) pCursor->bits->devPriv[pScreen->myNum]; -+ if (pPriv && (pCursor->bits->refcnt <= 1)) -+ { -+ if (pPriv->sourceBits) -+ (*pScreen->DestroyPixmap) (pPriv->sourceBits); -+ if (pPriv->maskBits) -+ (*pScreen->DestroyPixmap) (pPriv->maskBits); -+#ifdef ARGB_CURSOR -+ if (pPriv->pPicture) -+ FreePicture (pPriv->pPicture, 0); -+#endif -+ xfree ((pointer) pPriv); -+ pCursor->bits->devPriv[pScreen->myNum] = (pointer)NULL; -+ } -+ return TRUE; -+} -+ -+static void -+rfbDCPutBits (pDrawable, pPriv, sourceGC, maskGC, x, y, w, h, source, mask) -+ DrawablePtr pDrawable; -+ GCPtr sourceGC, maskGC; -+ int x, y; -+ unsigned w, h; -+ rfbDCCursorPtr pPriv; -+ unsigned long source, mask; -+{ -+ XID gcvals[1]; -+ -+ if (sourceGC->fgPixel != source) -+ { -+ gcvals[0] = source; -+ DoChangeGC (sourceGC, GCForeground, gcvals, 0); -+ } -+ if (sourceGC->serialNumber != pDrawable->serialNumber) -+ ValidateGC (pDrawable, sourceGC); -+ (*sourceGC->ops->PushPixels) (sourceGC, pPriv->sourceBits, pDrawable, w, h, x, y); -+ if (maskGC->fgPixel != mask) -+ { -+ gcvals[0] = mask; -+ DoChangeGC (maskGC, GCForeground, gcvals, 0); -+ } -+ if (maskGC->serialNumber != pDrawable->serialNumber) -+ ValidateGC (pDrawable, maskGC); -+ (*maskGC->ops->PushPixels) (maskGC, pPriv->maskBits, pDrawable, w, h, x, y); -+} -+ -+#define EnsureGC(gc,win) (gc || rfbDCMakeGC(&gc, win)) -+ -+static GCPtr -+rfbDCMakeGC(ppGC, pWin) -+ GCPtr *ppGC; -+ WindowPtr pWin; -+{ -+ GCPtr pGC; -+ int status; -+ XID gcvals[2]; -+ -+ gcvals[0] = IncludeInferiors; -+ gcvals[1] = FALSE; -+ pGC = CreateGC((DrawablePtr)pWin, -+ GCSubwindowMode|GCGraphicsExposures, gcvals, &status); -+ if (pGC && pWin->drawable.pScreen->DrawGuarantee) -+ (*pWin->drawable.pScreen->DrawGuarantee) (pWin, pGC, GuaranteeVisBack); -+ *ppGC = pGC; -+ return pGC; -+} -+ -+static Bool -+rfbDCPutUpCursor (pScreen, pCursor, x, y, source, mask) -+ ScreenPtr pScreen; -+ CursorPtr pCursor; -+ int x, y; -+ unsigned long source, mask; -+{ -+ rfbDCScreenPtr pScreenPriv; -+ rfbDCCursorPtr pPriv; -+ WindowPtr pWin; -+ -+ pPriv = (rfbDCCursorPtr) pCursor->bits->devPriv[pScreen->myNum]; -+ if (!pPriv) -+ { -+ pPriv = rfbDCRealize(pScreen, pCursor); -+ if (!pPriv) -+ return FALSE; -+ } -+ pScreenPriv = (rfbDCScreenPtr) pScreen->devPrivates[rfbDCScreenIndex].ptr; -+ pWin = WindowTable[pScreen->myNum]; -+#ifdef ARGB_CURSOR -+ if (pPriv->pPicture) -+ { -+ if (!EnsurePicture(pScreenPriv->pRootPicture, &pWin->drawable, pWin)) -+ return FALSE; -+ CompositePicture (PictOpOver, -+ pPriv->pPicture, -+ NULL, -+ pScreenPriv->pRootPicture, -+ 0, 0, 0, 0, -+ x, y, -+ pCursor->bits->width, -+ pCursor->bits->height); -+ } -+ else -+#endif -+ { -+ if (!EnsureGC(pScreenPriv->pSourceGC, pWin)) -+ return FALSE; -+ if (!EnsureGC(pScreenPriv->pMaskGC, pWin)) -+ { -+ FreeGC (pScreenPriv->pSourceGC, (GContext) 0); -+ pScreenPriv->pSourceGC = 0; -+ return FALSE; -+ } -+ rfbDCPutBits ((DrawablePtr)pWin, pPriv, -+ pScreenPriv->pSourceGC, pScreenPriv->pMaskGC, -+ x, y, pCursor->bits->width, pCursor->bits->height, -+ source, mask); -+ } -+ return TRUE; -+} -+ -+static Bool -+rfbDCSaveUnderCursor (pScreen, x, y, w, h) -+ ScreenPtr pScreen; -+ int x, y, w, h; -+{ -+ rfbDCScreenPtr pScreenPriv; -+ PixmapPtr pSave; -+ WindowPtr pWin; -+ GCPtr pGC; -+ -+ pScreenPriv = (rfbDCScreenPtr) pScreen->devPrivates[rfbDCScreenIndex].ptr; -+ pSave = pScreenPriv->pSave; -+ pWin = WindowTable[pScreen->myNum]; -+ if (!pSave || pSave->drawable.width < w || pSave->drawable.height < h) -+ { -+ if (pSave) -+ (*pScreen->DestroyPixmap) (pSave); -+ pScreenPriv->pSave = pSave = -+ (*pScreen->CreatePixmap) (pScreen, w, h, pScreen->rootDepth); -+ if (!pSave) -+ return FALSE; -+ } -+ if (!EnsureGC(pScreenPriv->pSaveGC, pWin)) -+ return FALSE; -+ pGC = pScreenPriv->pSaveGC; -+ if (pSave->drawable.serialNumber != pGC->serialNumber) -+ ValidateGC ((DrawablePtr) pSave, pGC); -+ (*pGC->ops->CopyArea) ((DrawablePtr) pWin, (DrawablePtr) pSave, pGC, -+ x, y, w, h, 0, 0); -+ return TRUE; -+} -+ -+static Bool -+rfbDCRestoreUnderCursor (pScreen, x, y, w, h) -+ ScreenPtr pScreen; -+ int x, y, w, h; -+{ -+ rfbDCScreenPtr pScreenPriv; -+ PixmapPtr pSave; -+ WindowPtr pWin; -+ GCPtr pGC; -+ -+ pScreenPriv = (rfbDCScreenPtr) pScreen->devPrivates[rfbDCScreenIndex].ptr; -+ pSave = pScreenPriv->pSave; -+ pWin = WindowTable[pScreen->myNum]; -+ if (!pSave) -+ return FALSE; -+ if (!EnsureGC(pScreenPriv->pRestoreGC, pWin)) -+ return FALSE; -+ pGC = pScreenPriv->pRestoreGC; -+ if (pWin->drawable.serialNumber != pGC->serialNumber) -+ ValidateGC ((DrawablePtr) pWin, pGC); -+ (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC, -+ 0, 0, w, h, x, y); -+ return TRUE; -+} -+ -+static Bool -+rfbDCChangeSave (pScreen, x, y, w, h, dx, dy) -+ ScreenPtr pScreen; -+ int x, y, w, h, dx, dy; -+{ -+ rfbDCScreenPtr pScreenPriv; -+ PixmapPtr pSave; -+ WindowPtr pWin; -+ GCPtr pGC; -+ int sourcex, sourcey, destx, desty, copyw, copyh; -+ -+ pScreenPriv = (rfbDCScreenPtr) pScreen->devPrivates[rfbDCScreenIndex].ptr; -+ pSave = pScreenPriv->pSave; -+ pWin = WindowTable[pScreen->myNum]; -+ /* -+ * restore the bits which are about to get trashed -+ */ -+ if (!pSave) -+ return FALSE; -+ if (!EnsureGC(pScreenPriv->pRestoreGC, pWin)) -+ return FALSE; -+ pGC = pScreenPriv->pRestoreGC; -+ if (pWin->drawable.serialNumber != pGC->serialNumber) -+ ValidateGC ((DrawablePtr) pWin, pGC); -+ /* -+ * copy the old bits to the screen. -+ */ -+ if (dy > 0) -+ { -+ (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC, -+ 0, h - dy, w, dy, x + dx, y + h); -+ } -+ else if (dy < 0) -+ { -+ (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC, -+ 0, 0, w, -dy, x + dx, y + dy); -+ } -+ if (dy >= 0) -+ { -+ desty = y + dy; -+ sourcey = 0; -+ copyh = h - dy; -+ } -+ else -+ { -+ desty = y; -+ sourcey = - dy; -+ copyh = h + dy; -+ } -+ if (dx > 0) -+ { -+ (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC, -+ w - dx, sourcey, dx, copyh, x + w, desty); -+ } -+ else if (dx < 0) -+ { -+ (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC, -+ 0, sourcey, -dx, copyh, x + dx, desty); -+ } -+ if (!EnsureGC(pScreenPriv->pSaveGC, pWin)) -+ return FALSE; -+ pGC = pScreenPriv->pSaveGC; -+ if (pSave->drawable.serialNumber != pGC->serialNumber) -+ ValidateGC ((DrawablePtr) pSave, pGC); -+ /* -+ * move the bits that are still valid within the pixmap -+ */ -+ if (dx >= 0) -+ { -+ sourcex = 0; -+ destx = dx; -+ copyw = w - dx; -+ } -+ else -+ { -+ destx = 0; -+ sourcex = - dx; -+ copyw = w + dx; -+ } -+ if (dy >= 0) -+ { -+ sourcey = 0; -+ desty = dy; -+ copyh = h - dy; -+ } -+ else -+ { -+ desty = 0; -+ sourcey = -dy; -+ copyh = h + dy; -+ } -+ (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pSave, pGC, -+ sourcex, sourcey, copyw, copyh, destx, desty); -+ /* -+ * copy the new bits from the screen into the remaining areas of the -+ * pixmap -+ */ -+ if (dy > 0) -+ { -+ (*pGC->ops->CopyArea) ((DrawablePtr) pWin, (DrawablePtr) pSave, pGC, -+ x, y, w, dy, 0, 0); -+ } -+ else if (dy < 0) -+ { -+ (*pGC->ops->CopyArea) ((DrawablePtr) pWin, (DrawablePtr) pSave, pGC, -+ x, y + h + dy, w, -dy, 0, h + dy); -+ } -+ if (dy >= 0) -+ { -+ desty = dy; -+ sourcey = y + dy; -+ copyh = h - dy; -+ } -+ else -+ { -+ desty = 0; -+ sourcey = y; -+ copyh = h + dy; -+ } -+ if (dx > 0) -+ { -+ (*pGC->ops->CopyArea) ((DrawablePtr) pWin, (DrawablePtr) pSave, pGC, -+ x, sourcey, dx, copyh, 0, desty); -+ } -+ else if (dx < 0) -+ { -+ (*pGC->ops->CopyArea) ((DrawablePtr) pWin, (DrawablePtr) pSave, pGC, -+ x + w + dx, sourcey, -dx, copyh, w + dx, desty); -+ } -+ return TRUE; -+} -+ -+static Bool -+rfbDCMoveCursor (pScreen, pCursor, x, y, w, h, dx, dy, source, mask) -+ ScreenPtr pScreen; -+ CursorPtr pCursor; -+ int x, y, w, h, dx, dy; -+ unsigned long source, mask; -+{ -+ rfbDCCursorPtr pPriv; -+ rfbDCScreenPtr pScreenPriv; -+ int status; -+ WindowPtr pWin; -+ GCPtr pGC; -+ XID gcval = FALSE; -+ PixmapPtr pTemp; -+ -+ pPriv = (rfbDCCursorPtr) pCursor->bits->devPriv[pScreen->myNum]; -+ if (!pPriv) -+ { -+ pPriv = rfbDCRealize(pScreen, pCursor); -+ if (!pPriv) -+ return FALSE; -+ } -+ pScreenPriv = (rfbDCScreenPtr) pScreen->devPrivates[rfbDCScreenIndex].ptr; -+ pWin = WindowTable[pScreen->myNum]; -+ pTemp = pScreenPriv->pTemp; -+ if (!pTemp || -+ pTemp->drawable.width != pScreenPriv->pSave->drawable.width || -+ pTemp->drawable.height != pScreenPriv->pSave->drawable.height) -+ { -+ if (pTemp) -+ (*pScreen->DestroyPixmap) (pTemp); -+#ifdef ARGB_CURSOR -+ if (pScreenPriv->pTempPicture) -+ { -+ FreePicture (pScreenPriv->pTempPicture, 0); -+ pScreenPriv->pTempPicture = 0; -+ } -+#endif -+ pScreenPriv->pTemp = pTemp = (*pScreen->CreatePixmap) -+ (pScreen, w, h, pScreenPriv->pSave->drawable.depth); -+ if (!pTemp) -+ return FALSE; -+ } -+ if (!pScreenPriv->pMoveGC) -+ { -+ pScreenPriv->pMoveGC = CreateGC ((DrawablePtr)pTemp, -+ GCGraphicsExposures, &gcval, &status); -+ if (!pScreenPriv->pMoveGC) -+ return FALSE; -+ } -+ /* -+ * copy the saved area to a temporary pixmap -+ */ -+ pGC = pScreenPriv->pMoveGC; -+ if (pGC->serialNumber != pTemp->drawable.serialNumber) -+ ValidateGC ((DrawablePtr) pTemp, pGC); -+ (*pGC->ops->CopyArea)((DrawablePtr)pScreenPriv->pSave, -+ (DrawablePtr)pTemp, pGC, 0, 0, w, h, 0, 0); -+ -+ /* -+ * draw the cursor in the temporary pixmap -+ */ -+#ifdef ARGB_CURSOR -+ if (pPriv->pPicture) -+ { -+ if (!EnsurePicture(pScreenPriv->pTempPicture, &pTemp->drawable, pWin)) -+ return FALSE; -+ CompositePicture (PictOpOver, -+ pPriv->pPicture, -+ NULL, -+ pScreenPriv->pTempPicture, -+ 0, 0, 0, 0, -+ dx, dy, -+ pCursor->bits->width, -+ pCursor->bits->height); -+ } -+ else -+#endif -+ { -+ if (!pScreenPriv->pPixSourceGC) -+ { -+ pScreenPriv->pPixSourceGC = CreateGC ((DrawablePtr)pTemp, -+ GCGraphicsExposures, &gcval, &status); -+ if (!pScreenPriv->pPixSourceGC) -+ return FALSE; -+ } -+ if (!pScreenPriv->pPixMaskGC) -+ { -+ pScreenPriv->pPixMaskGC = CreateGC ((DrawablePtr)pTemp, -+ GCGraphicsExposures, &gcval, &status); -+ if (!pScreenPriv->pPixMaskGC) -+ return FALSE; -+ } -+ rfbDCPutBits ((DrawablePtr)pTemp, pPriv, -+ pScreenPriv->pPixSourceGC, pScreenPriv->pPixMaskGC, -+ dx, dy, pCursor->bits->width, pCursor->bits->height, -+ source, mask); -+ } -+ -+ /* -+ * copy the temporary pixmap onto the screen -+ */ -+ -+ if (!EnsureGC(pScreenPriv->pRestoreGC, pWin)) -+ return FALSE; -+ pGC = pScreenPriv->pRestoreGC; -+ if (pWin->drawable.serialNumber != pGC->serialNumber) -+ ValidateGC ((DrawablePtr) pWin, pGC); -+ -+ (*pGC->ops->CopyArea) ((DrawablePtr) pTemp, (DrawablePtr) pWin, -+ pGC, -+ 0, 0, w, h, x, y); -+ return TRUE; -+} -diff --git a/hw/dmx/vnc/draw.c b/hw/dmx/vnc/draw.c -new file mode 100644 -index 0000000..4154dd5 ---- /dev/null -+++ b/hw/dmx/vnc/draw.c -@@ -0,0 +1,2097 @@ -+/* -+ * draw.c - drawing routines for the RFB X server. This is a set of -+ * wrappers around the standard MI/MFB/CFB drawing routines which work out -+ * to a fair approximation the region of the screen being modified by the -+ * drawing. If the RFB client is ready then the modified region of the screen -+ * is sent to the client, otherwise the modified region will simply grow with -+ * each drawing request until the client is ready. -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ */ -+ -+/* -+ * 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) 1989 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 "rfb.h" -+ -+int rfbDeferUpdateTime = 40; /* ms */ -+ -+ -+/****************************************************************************/ -+/* -+ * Macro definitions -+ */ -+/****************************************************************************/ -+ -+#define TRC(x) /* (rfbLog x) */ -+ -+/* ADD_TO_MODIFIED_REGION adds the given region to the modified region for each -+ client */ -+ -+#define ADD_TO_MODIFIED_REGION(pScreen,reg) \ -+ { \ -+ rfbClientPtr cl; \ -+ for (cl = rfbClientHead; cl; cl = cl->next) { \ -+ REGION_UNION((pScreen),&cl->modifiedRegion,&cl->modifiedRegion,reg);\ -+ } \ -+ } -+ -+/* SCHEDULE_FB_UPDATE is used at the end of each drawing routine to schedule an -+ update to be sent to each client if there is one pending and the client is -+ ready for it. */ -+ -+#define SCHEDULE_FB_UPDATE(pScreen,pVNC) \ -+ if (!pVNC->dontSendFramebufferUpdate) { \ -+ rfbClientPtr cl, nextCl; \ -+ for (cl = rfbClientHead; cl; cl = nextCl) { \ -+ nextCl = cl->next; \ -+ if (!cl->deferredUpdateScheduled && FB_UPDATE_PENDING(cl) && \ -+ REGION_NOTEMPTY(pScreen,&cl->requestedRegion)) \ -+ { \ -+ rfbScheduleDeferredUpdate(pScreen, cl); \ -+ } \ -+ } \ -+ } -+ -+/* function prototypes */ -+ -+static void rfbScheduleDeferredUpdate(ScreenPtr pScreen, rfbClientPtr cl); -+static void rfbCopyRegion(ScreenPtr pScreen, rfbClientPtr cl, -+ RegionPtr src, RegionPtr dst, int dx, int dy); -+#ifdef DEBUG -+static void PrintRegion(ScreenPtr pScreen, RegionPtr reg); -+#endif -+ -+/* GC funcs */ -+ -+static void rfbValidateGC(GCPtr, unsigned long /*changes*/, DrawablePtr); -+static void rfbChangeGC(GCPtr, unsigned long /*mask*/); -+static void rfbCopyGC(GCPtr /*src*/, unsigned long /*mask*/, GCPtr /*dst*/); -+static void rfbDestroyGC(GCPtr); -+static void rfbChangeClip(GCPtr, int /*type*/, pointer /*pValue*/, -+ int /*nrects*/); -+static void rfbDestroyClip(GCPtr); -+static void rfbCopyClip(GCPtr /*dst*/, GCPtr /*src*/); -+ -+/* GC ops */ -+ -+static void rfbFillSpans(DrawablePtr pDrawable, GCPtr pGC, int nInit, DDXPointPtr pptInit, int *pwidthInit, int fSorted); -+static void rfbSetSpans(DrawablePtr pDrawable, -+ GCPtr pGC, -+ char *psrc, -+ register DDXPointPtr ppt, -+ int *pwidth, -+ int nspans, -+ int fSorted); -+static void rfbPutImage(); -+static RegionPtr rfbCopyArea(); -+static RegionPtr rfbCopyPlane(); -+static void rfbPolyPoint(); -+static void rfbPolylines (DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, DDXPointPtr ppts); -+static void rfbPolySegment(); -+static void rfbPolyRectangle(); -+static void rfbPolyArc(); -+static void rfbFillPolygon(); -+static void rfbPolyFillRect(); -+static void rfbPolyFillArc(); -+static int rfbPolyText8(); -+static int rfbPolyText16(); -+static void rfbImageText8(); -+static void rfbImageText16(); -+static void rfbImageGlyphBlt(); -+static void rfbPolyGlyphBlt(); -+static void rfbPushPixels(); -+ -+ -+static GCFuncs rfbGCFuncs = { -+ rfbValidateGC, -+ rfbChangeGC, -+ rfbCopyGC, -+ rfbDestroyGC, -+ rfbChangeClip, -+ rfbDestroyClip, -+ rfbCopyClip, -+}; -+ -+ -+static GCOps rfbGCOps = { -+ rfbFillSpans, rfbSetSpans, rfbPutImage, -+ rfbCopyArea, rfbCopyPlane, rfbPolyPoint, -+ rfbPolylines, rfbPolySegment, rfbPolyRectangle, -+ rfbPolyArc, rfbFillPolygon, rfbPolyFillRect, -+ rfbPolyFillArc, rfbPolyText8, rfbPolyText16, -+ rfbImageText8, rfbImageText16, rfbImageGlyphBlt, -+ rfbPolyGlyphBlt, rfbPushPixels -+}; -+ -+ -+ -+/****************************************************************************/ -+/* -+ * Screen functions wrapper stuff -+ */ -+/****************************************************************************/ -+ -+#define SCREEN_PROLOGUE(scrn, field) \ -+ ScreenPtr pScreen = scrn; \ -+ VNCSCREENPTR(pScreen); \ -+ pScreen->field = pVNC->field; -+ -+#define SCREEN_EPILOGUE(field, wrapper) \ -+ pScreen->field = wrapper; -+ -+ -+/* -+ * CloseScreen wrapper -- unwrap everything, free the private data -+ * and call the wrapped CloseScreen function. -+ */ -+ -+Bool -+rfbCloseScreen (int i, ScreenPtr pScreen) -+{ -+ VNCSCREENPTR(pScreen); -+#if XFREE86VNC -+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; -+#endif -+ int sock; -+ -+ for (sock = 0; sock <= pVNC->maxFd; sock++) { -+ if (FD_ISSET(sock, &pVNC->allFds)) -+ if (sock != pVNC->rfbListenSock && sock != pVNC->httpListenSock) { -+ rfbCloseSock(pScreen, sock); -+ } -+ } -+ -+ if (pVNC->rfbListenSock > 0) -+ if (close(pVNC->rfbListenSock)) -+ ErrorF("Close of port %d failed\n",pVNC->rfbPort); -+ -+ if (pVNC->httpListenSock > 0) -+ if (close(pVNC->httpListenSock)) -+ ErrorF("Close of port %d failed\n",pVNC->httpPort); -+ -+ pScreen->CloseScreen = pVNC->CloseScreen; -+ pScreen->CreateGC = pVNC->CreateGC; -+ pScreen->PaintWindowBackground = pVNC->PaintWindowBackground; -+ pScreen->PaintWindowBorder = pVNC->PaintWindowBorder; -+ pScreen->CopyWindow = pVNC->CopyWindow; -+ pScreen->ClearToBackground = pVNC->ClearToBackground; -+ pScreen->RestoreAreas = pVNC->RestoreAreas; -+ pScreen->WakeupHandler = pVNC->WakeupHandler; -+ -+#if XFREE86VNC -+ pScreen->InstallColormap = pVNC->InstallColormap; -+ pScreen->UninstallColormap = pVNC->UninstallColormap; -+ pScreen->ListInstalledColormaps = pVNC->ListInstalledColormaps; -+ pScreen->StoreColors = pVNC->StoreColors; -+ pScrn->EnableDisableFBAccess = pVNC->EnableDisableFBAccess; -+ -+ xfree(pVNC); -+#endif -+ -+ TRC((stderr,"Unwrapped screen functions\n")); -+ -+ return (*pScreen->CloseScreen) (i, pScreen); -+} -+ -+#if XFREE86VNC -+void -+rfbEnableDisableFBAccess (int index, Bool enable) -+{ -+ ScrnInfoPtr pScrn = xf86Screens[index]; -+ VNCSCREENPTR(pScrn->pScreen); -+ -+ /* -+ * Blank the screen for security while inputs are disabled. -+ * When VT switching is fixed, we might be able to allow -+ * control even when switched away. -+ */ -+ if (!enable) { -+ WindowPtr pWin = WindowTable[index]; -+ ScreenPtr pScreen = pWin->drawable.pScreen; -+ GCPtr pGC; -+ xRectangle rect; -+ -+ rect.x = 0; -+ rect.y = 0; -+ rect.width = pScrn->virtualX; -+ rect.height = pScrn->virtualY; -+ -+ if (!(pGC = GetScratchGC(pScreen->rootDepth, pScreen))) { -+ ErrorF("Couldn't blank screen"); -+ } else { -+ CARD32 attributes[2]; -+ attributes[0] = pScreen->whitePixel; -+ attributes[1] = pScreen->blackPixel; -+ (void)ChangeGC(pGC, GCForeground | GCBackground, attributes); -+ -+ ValidateGC((DrawablePtr)pWin, pGC); -+ -+ (*pGC->ops->PolyFillRect)((DrawablePtr)pWin, pGC, 1, &rect); -+ -+ FreeScratchGC(pGC); -+ -+ /* Flush pending packets */ -+ rfbCheckFds(pScreen); -+ httpCheckFds(pScreen); -+ } -+ } -+ -+ pScrn->EnableDisableFBAccess = pVNC->EnableDisableFBAccess; -+ (*pScrn->EnableDisableFBAccess)(index, enable); -+ pScrn->EnableDisableFBAccess = rfbEnableDisableFBAccess; -+} -+#endif -+ -+/* -+ * CreateGC - wrap the GC funcs (the GC ops will be wrapped when the GC -+ * func "ValidateGC" is called). -+ */ -+ -+Bool -+rfbCreateGC (GCPtr pGC) -+{ -+ Bool ret; -+ rfbGCPtr pGCPriv; -+ -+ SCREEN_PROLOGUE(pGC->pScreen,CreateGC); -+ -+ pGCPriv = (rfbGCPtr)pGC->devPrivates[rfbGCIndex].ptr; -+ -+ ret = (*pScreen->CreateGC) (pGC); -+ -+ TRC((stderr,"rfbCreateGC called\n")); -+ -+ pGCPriv->wrapOps = NULL; -+ pGCPriv->wrapFuncs = pGC->funcs; -+ pGC->funcs = &rfbGCFuncs; -+ -+ SCREEN_EPILOGUE(CreateGC,rfbCreateGC); -+ -+ return ret; -+} -+ -+/* -+ * PaintWindowBackground - the region being modified is just the given region. -+ */ -+ -+void -+rfbPaintWindowBackground (WindowPtr pWin, RegionPtr pRegion, int what) -+{ -+ SCREEN_PROLOGUE(pWin->drawable.pScreen,PaintWindowBackground); -+ -+ TRC((stderr,"rfbPaintWindowBackground called\n")); -+ -+ ADD_TO_MODIFIED_REGION(pScreen,pRegion); -+ -+ (*pScreen->PaintWindowBackground) (pWin, pRegion, what); -+ -+ SCHEDULE_FB_UPDATE(pScreen, pVNC); -+ -+ SCREEN_EPILOGUE(PaintWindowBackground,rfbPaintWindowBackground); -+} -+ -+/* -+ * PaintWindowBorder - the region being modified is just the given region. -+ */ -+ -+void -+rfbPaintWindowBorder (WindowPtr pWin, RegionPtr pRegion, int what) -+{ -+ SCREEN_PROLOGUE(pWin->drawable.pScreen,PaintWindowBorder); -+ -+ TRC((stderr,"rfbPaintWindowBorder called\n")); -+ -+ ADD_TO_MODIFIED_REGION(pScreen,pRegion); -+ -+ (*pScreen->PaintWindowBorder) (pWin, pRegion, what); -+ -+ SCHEDULE_FB_UPDATE(pScreen, pVNC); -+ -+ SCREEN_EPILOGUE(PaintWindowBorder,rfbPaintWindowBorder); -+} -+ -+#ifdef CHROMIUM -+Bool -+rfbRealizeWindow(WindowPtr pWin) -+{ -+ CRWindowTable *wt = NULL, *nextWt = NULL; -+ Bool ret; -+ SCREEN_PROLOGUE(pWin->drawable.pScreen,RealizeWindow); -+ -+ for (wt = windowTable; wt; wt = nextWt) { -+ nextWt = wt->next; -+ if (wt->XwinId == pWin->drawable.id) { -+ rfbSendChromiumWindowShow(wt->CRwinId, 1); -+ } -+ } -+ -+ ret = (*pScreen->RealizeWindow)(pWin); -+ -+ SCREEN_EPILOGUE(RealizeWindow,rfbRealizeWindow); -+ -+ return ret; -+} -+ -+Bool -+rfbUnrealizeWindow(WindowPtr pWin) -+{ -+ CRWindowTable *wt = NULL, *nextWt = NULL; -+ Bool ret; -+ SCREEN_PROLOGUE(pWin->drawable.pScreen,UnrealizeWindow); -+ -+ for (wt = windowTable; wt; wt = nextWt) { -+ nextWt = wt->next; -+ if (wt->XwinId == pWin->drawable.id) { -+ rfbSendChromiumWindowShow(wt->CRwinId, 0); -+ } -+ } -+ -+ ret = (*pScreen->UnrealizeWindow)(pWin); -+ -+ SCREEN_EPILOGUE(UnrealizeWindow,rfbUnrealizeWindow); -+ -+ return ret; -+} -+ -+Bool -+rfbDestroyWindow(WindowPtr pWin) -+{ -+ CRWindowTable *wt = NULL, *nextWt = NULL; -+ Bool ret; -+ SCREEN_PROLOGUE(pWin->drawable.pScreen,DestroyWindow); -+ -+ for (wt = windowTable; wt; wt = nextWt) { -+ nextWt = wt->next; -+ if (wt->XwinId == pWin->drawable.id) { -+ rfbSendChromiumWindowShow(wt->CRwinId, 0); -+ } -+ } -+ -+ ret = (*pScreen->DestroyWindow)(pWin); -+ -+ SCREEN_EPILOGUE(DestroyWindow,rfbDestroyWindow); -+ -+ return ret; -+} -+ -+void -+rfbResizeWindow(WindowPtr pWin, int x, int y, unsigned int w, unsigned int h, WindowPtr pSib) -+{ -+ CRWindowTable *wt = NULL, *nextWt = NULL; -+ SCREEN_PROLOGUE(pWin->drawable.pScreen,ResizeWindow); -+ -+ for (wt = windowTable; wt; wt = nextWt) { -+ nextWt = wt->next; -+ if (wt->XwinId == pWin->drawable.id) { -+ rfbSendChromiumMoveResizeWindow(wt->CRwinId, pWin->drawable.x, pWin->drawable.y, w, h); -+ } -+ } -+ -+ (*pScreen->ResizeWindow)(pWin, x, y, w, h, pSib); -+ -+ SCREEN_EPILOGUE(ResizeWindow,rfbResizeWindow); -+} -+ -+Bool -+rfbPositionWindow(WindowPtr pWin, int x, int y) -+{ -+ Bool ret; -+ CRWindowTable *wt, *nextWt; -+ SCREEN_PROLOGUE(pWin->drawable.pScreen,PositionWindow); -+ -+ for (wt = windowTable; wt; wt = nextWt) { -+ nextWt = wt->next; -+ if (wt->XwinId == pWin->drawable.id) { -+ rfbSendChromiumMoveResizeWindow(wt->CRwinId, x, y, pWin->drawable.width, pWin->drawable.height); -+ } -+ } -+ -+ ret = (*pScreen->PositionWindow)(pWin, x, y); -+ -+ SCREEN_EPILOGUE(PositionWindow,rfbPositionWindow); -+ -+ return ret; -+} -+ -+void -+rfbClipNotify(WindowPtr pWin, int x, int y) -+{ -+ CRWindowTable *wt, *nextWt; -+ SCREEN_PROLOGUE(pWin->drawable.pScreen,ClipNotify); -+ -+ for (wt = windowTable; wt; wt = nextWt) { -+ nextWt = wt->next; -+ if (wt->XwinId == pWin->drawable.id) { -+ int numClipRects = REGION_NUM_RECTS(&pWin->clipList); -+ BoxPtr pClipRects = REGION_RECTS(&pWin->clipList); -+ -+ /* Possible optimization - has the cliplist really? changed */ -+ -+ rfbSendChromiumClipList(wt->CRwinId, pClipRects, numClipRects); -+ } -+ } -+ -+ if (*pScreen->ClipNotify) -+ (*pScreen->ClipNotify)(pWin, x, y); -+ -+ SCREEN_EPILOGUE(ClipNotify,rfbClipNotify); -+} -+#endif /* CHROMIUM */ -+ -+/* -+ * CopyWindow - the region being modified is the translation of the old -+ * region, clipped to the border clip region of the window. Note that any -+ * parts of the window which have become newly-visible will not be affected by -+ * this call - a separate PaintWindowBackground/Border will be called to do -+ * that. If the client will accept CopyRect messages then use rfbCopyRegion to -+ * optimise the pending screen changes into a single "copy region" plus the -+ * ordinary modified region. -+ */ -+ -+void -+rfbCopyWindow (WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr pOldRegion) -+{ -+ rfbClientPtr cl; -+ RegionRec srcRegion, dstRegion; -+ SCREEN_PROLOGUE(pWin->drawable.pScreen,CopyWindow); -+ -+ TRC((stderr,"rfbCopyWindow called\n")); -+ -+ REGION_NULL(pScreen,&dstRegion); -+ REGION_COPY(pScreen,&dstRegion,pOldRegion); -+ REGION_TRANSLATE(pWin->drawable.pScreen, &dstRegion, -+ pWin->drawable.x - ptOldOrg.x, -+ pWin->drawable.y - ptOldOrg.y); -+ REGION_INTERSECT(pWin->drawable.pScreen, &dstRegion, &dstRegion, -+ &pWin->borderClip); -+ -+ for (cl = rfbClientHead; cl; cl = cl->next) { -+ if (cl->useCopyRect) { -+ REGION_NULL(pScreen,&srcRegion); -+ REGION_COPY(pScreen,&srcRegion,pOldRegion); -+ -+ rfbCopyRegion(pScreen, cl, &srcRegion, &dstRegion, -+ pWin->drawable.x - ptOldOrg.x, -+ pWin->drawable.y - ptOldOrg.y); -+ -+ REGION_UNINIT(pScreen, &srcRegion); -+ -+ } else { -+ -+ REGION_UNION(pScreen, &cl->modifiedRegion, &cl->modifiedRegion, -+ &dstRegion); -+ } -+ } -+ -+ REGION_UNINIT(pScreen, &dstRegion); -+ -+ (*pScreen->CopyWindow) (pWin, ptOldOrg, pOldRegion); -+ -+ SCHEDULE_FB_UPDATE(pScreen, pVNC); -+ -+ SCREEN_EPILOGUE(CopyWindow,rfbCopyWindow); -+} -+ -+/* -+ * ClearToBackground - when generateExposures is false, the region being -+ * modified is the given rectangle (clipped to the "window clip region"). -+ */ -+ -+void -+rfbClearToBackground (WindowPtr pWin, int x, int y, int w, int h, -+ Bool generateExposures) -+{ -+ RegionRec tmpRegion; -+ BoxRec box; -+ SCREEN_PROLOGUE(pWin->drawable.pScreen,ClearToBackground); -+ -+ TRC((stderr,"rfbClearToBackground called\n")); -+ -+ if (!generateExposures) { -+ 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); -+ -+ SAFE_REGION_INIT(pScreen, &tmpRegion, &box, 0); -+ -+ REGION_INTERSECT(pScreen, &tmpRegion, &tmpRegion, &pWin->clipList); -+ -+ ADD_TO_MODIFIED_REGION(pScreen, &tmpRegion); -+ -+ REGION_UNINIT(pScreen, &tmpRegion); -+ } -+ -+ (*pScreen->ClearToBackground) (pWin, x, y, w, h, generateExposures); -+ -+ if (!generateExposures) { -+ SCHEDULE_FB_UPDATE(pScreen, pVNC); -+ } -+ -+ SCREEN_EPILOGUE(ClearToBackground,rfbClearToBackground); -+} -+ -+/* -+ * RestoreAreas - just be safe here - the region being modified is the whole -+ * exposed region. -+ */ -+ -+RegionPtr -+rfbRestoreAreas (WindowPtr pWin, RegionPtr prgnExposed) -+{ -+ RegionPtr result; -+ SCREEN_PROLOGUE(pWin->drawable.pScreen,RestoreAreas); -+ -+ TRC((stderr,"rfbRestoreAreas called\n")); -+ -+ ADD_TO_MODIFIED_REGION(pScreen, prgnExposed); -+ -+ result = (*pScreen->RestoreAreas) (pWin, prgnExposed); -+ -+ SCHEDULE_FB_UPDATE(pScreen, pVNC); -+ -+ SCREEN_EPILOGUE(RestoreAreas,rfbRestoreAreas); -+ -+ return result; -+} -+ -+ -+ -+/****************************************************************************/ -+/* -+ * GC funcs wrapper stuff -+ * -+ * We only really want to wrap the GC ops, but to do this we need to wrap -+ * ValidateGC and so all the other GC funcs must be wrapped as well. -+ */ -+/****************************************************************************/ -+ -+#define GC_FUNC_PROLOGUE(pGC) \ -+ rfbGCPtr pGCPriv = (rfbGCPtr) (pGC)->devPrivates[rfbGCIndex].ptr; \ -+ (pGC)->funcs = pGCPriv->wrapFuncs; \ -+ if (pGCPriv->wrapOps) \ -+ (pGC)->ops = pGCPriv->wrapOps; -+ -+#define GC_FUNC_EPILOGUE(pGC) \ -+ pGCPriv->wrapFuncs = (pGC)->funcs; \ -+ (pGC)->funcs = &rfbGCFuncs; \ -+ if (pGCPriv->wrapOps) { \ -+ pGCPriv->wrapOps = (pGC)->ops; \ -+ (pGC)->ops = &rfbGCOps; \ -+ } -+ -+ -+/* -+ * ValidateGC - call the wrapped ValidateGC, then wrap the resulting GC ops if -+ * the drawing will be to a viewable window. -+ */ -+ -+static void -+rfbValidateGC (GCPtr pGC, unsigned long changes, DrawablePtr pDrawable) -+{ -+ /*VNCSCREENPTR(pGC->pScreen);*/ -+ GC_FUNC_PROLOGUE(pGC); -+ -+ TRC((stderr,"rfbValidateGC called\n")); -+ -+ (*pGC->funcs->ValidateGC) (pGC, changes, pDrawable); -+ -+ pGCPriv->wrapOps = NULL; -+ 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)) { -+ pGCPriv->wrapOps = pGC->ops; -+ TRC((stderr,"rfbValidateGC: wrapped GC ops\n")); -+ } -+ } -+ -+ GC_FUNC_EPILOGUE(pGC); -+} -+ -+/* -+ * All other GC funcs simply unwrap the GC funcs and ops, call the wrapped -+ * function and then rewrap the funcs and ops. -+ */ -+ -+static void -+rfbChangeGC (pGC, mask) -+ GCPtr pGC; -+ unsigned long mask; -+{ -+ GC_FUNC_PROLOGUE(pGC); -+ (*pGC->funcs->ChangeGC) (pGC, mask); -+ GC_FUNC_EPILOGUE(pGC); -+} -+ -+static void -+rfbCopyGC (pGCSrc, mask, pGCDst) -+ GCPtr pGCSrc, pGCDst; -+ unsigned long mask; -+{ -+ GC_FUNC_PROLOGUE(pGCDst); -+ (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst); -+ GC_FUNC_EPILOGUE(pGCDst); -+} -+ -+static void -+rfbDestroyGC (pGC) -+ GCPtr pGC; -+{ -+ GC_FUNC_PROLOGUE(pGC); -+ (*pGC->funcs->DestroyGC) (pGC); -+ GC_FUNC_EPILOGUE(pGC); -+} -+ -+static void -+rfbChangeClip (pGC, type, pvalue, nrects) -+ GCPtr pGC; -+ int type; -+ pointer pvalue; -+ int nrects; -+{ -+ GC_FUNC_PROLOGUE(pGC); -+ (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects); -+ GC_FUNC_EPILOGUE(pGC); -+} -+ -+static void -+rfbDestroyClip(pGC) -+ GCPtr pGC; -+{ -+ GC_FUNC_PROLOGUE(pGC); -+ (* pGC->funcs->DestroyClip)(pGC); -+ GC_FUNC_EPILOGUE(pGC); -+} -+ -+static void -+rfbCopyClip(pgcDst, pgcSrc) -+ GCPtr pgcDst, pgcSrc; -+{ -+ GC_FUNC_PROLOGUE(pgcDst); -+ (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc); -+ GC_FUNC_EPILOGUE(pgcDst); -+} -+ -+ -+/****************************************************************************/ -+/* -+ * GC ops wrapper stuff -+ * -+ * Note that these routines will only have been wrapped for drawing to -+ * viewable windows so we don't need to check each time that the drawable -+ * is a viewable window. -+ */ -+/****************************************************************************/ -+ -+#define GC_OP_PROLOGUE(pDrawable,pGC) \ -+ ScreenPtr pScreen = pGC->pScreen; \ -+ VNCSCREENPTR(pScreen); \ -+ rfbGCPtr pGCPrivate = (rfbGCPtr) (pGC)->devPrivates[rfbGCIndex].ptr; \ -+ GCFuncs *oldFuncs = pGC->funcs; \ -+ (void) pScreen; /* silence compiler */ \ -+ (pGC)->funcs = pGCPrivate->wrapFuncs; \ -+ (pGC)->ops = pGCPrivate->wrapOps; -+ -+#define GC_OP_EPILOGUE(pGC) \ -+ pGCPrivate->wrapOps = (pGC)->ops; \ -+ (pGC)->funcs = oldFuncs; \ -+ (pGC)->ops = &rfbGCOps; -+ -+ -+/* -+ * FillSpans - being very safe - the region being modified is the border clip -+ * region of the window. -+ */ -+ -+static void -+rfbFillSpans(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted) -+ DrawablePtr pDrawable; -+ GCPtr pGC; -+ int nInit; /* number of spans to fill */ -+ DDXPointPtr pptInit; /* pointer to list of start points */ -+ int *pwidthInit; /* pointer to list of n widths */ -+ int fSorted; -+{ -+ GC_OP_PROLOGUE(pDrawable,pGC); -+ -+ TRC((stderr,"rfbFillSpans called\n")); -+ -+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, -+ &((WindowPtr)pDrawable)->borderClip); -+ -+ (*pGC->ops->FillSpans) (pDrawable, pGC, nInit, pptInit,pwidthInit,fSorted); -+ -+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); -+ -+ GC_OP_EPILOGUE(pGC); -+} -+ -+/* -+ * SetSpans - being very safe - the region being modified is the border clip -+ * region of the window. -+ */ -+ -+static void -+rfbSetSpans(DrawablePtr pDrawable, -+ GCPtr pGC, -+ char *psrc, -+ register DDXPointPtr ppt, -+ int *pwidth, -+ int nspans, -+ int fSorted) -+{ -+ GC_OP_PROLOGUE(pDrawable,pGC); -+ -+ TRC((stderr,"rfbSetSpans called\n")); -+ -+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, -+ &((WindowPtr)pDrawable)->borderClip); -+ -+ (*pGC->ops->SetSpans) (pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted); -+ -+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); -+ -+ GC_OP_EPILOGUE(pGC); -+} -+ -+/* -+ * PutImage - the region being modified is the rectangle of the -+ * PutImage (clipped to the window clip region). -+ */ -+ -+static void -+rfbPutImage(pDrawable, pGC, depth, x, y, w, h, leftPad, format, pBits) -+ DrawablePtr pDrawable; -+ GCPtr pGC; -+ int depth; -+ int x; -+ int y; -+ int w; -+ int h; -+ int leftPad; -+ int format; -+ char *pBits; -+{ -+ RegionRec tmpRegion; -+ BoxRec box; -+ GC_OP_PROLOGUE(pDrawable, pGC); -+ -+ TRC((stderr,"rfbPutImage called\n")); -+ -+ box.x1 = x + pDrawable->x; -+ box.y1 = y + pDrawable->y; -+ box.x2 = box.x1 + w; -+ box.y2 = box.y1 + h; -+ -+ SAFE_REGION_INIT(pDrawable->pScreen, &tmpRegion, &box, 0); -+ -+ REGION_INTERSECT(pDrawable->pScreen, &tmpRegion, &tmpRegion, -+ pGC->pCompositeClip); -+ -+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, &tmpRegion); -+ -+ REGION_UNINIT(pDrawable->pScreen, &tmpRegion); -+ -+ (*pGC->ops->PutImage) (pDrawable, pGC, depth, x, y, w, h, -+ leftPad, format, pBits); -+ -+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); -+ -+ GC_OP_EPILOGUE(pGC); -+} -+ -+/* -+ * CopyArea - the region being modified is the destination rectangle (clipped -+ * to the window clip region). -+ * If the client will accept CopyRect messages then use rfbCopyRegion -+ * to optimise the pending screen changes into a single "copy region" plus -+ * the ordinary modified region. -+ */ -+ -+static RegionPtr -+rfbCopyArea (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty) -+ DrawablePtr pSrc; -+ DrawablePtr pDst; -+ GCPtr pGC; -+ int srcx; -+ int srcy; -+ int w; -+ int h; -+ int dstx; -+ int dsty; -+{ -+ rfbClientPtr cl; -+ RegionPtr rgn; -+ RegionRec srcRegion, dstRegion; -+ BoxRec box; -+ GC_OP_PROLOGUE(pDst, pGC); -+ -+ TRC((stderr,"rfbCopyArea called\n")); -+ -+ box.x1 = dstx + pDst->x; -+ box.y1 = dsty + pDst->y; -+ box.x2 = box.x1 + w; -+ box.y2 = box.y1 + h; -+ -+ SAFE_REGION_INIT(pDst->pScreen, &dstRegion, &box, 0); -+ REGION_INTERSECT(pDst->pScreen, &dstRegion, &dstRegion, -+ pGC->pCompositeClip); -+ -+ if ((pSrc->type == DRAWABLE_WINDOW) && (pSrc->pScreen == pDst->pScreen)) { -+ box.x1 = srcx + pSrc->x; -+ box.y1 = srcy + pSrc->y; -+ box.x2 = box.x1 + w; -+ box.y2 = box.y1 + h; -+ -+ for (cl = rfbClientHead; cl; cl = cl->next) { -+ if (cl->useCopyRect) { -+ SAFE_REGION_INIT(pSrc->pScreen, &srcRegion, &box, 0); -+ REGION_INTERSECT(pSrc->pScreen, &srcRegion, &srcRegion, -+ &((WindowPtr)pSrc)->clipList); -+ -+ rfbCopyRegion(pSrc->pScreen, cl, &srcRegion, &dstRegion, -+ dstx + pDst->x - srcx - pSrc->x, -+ dsty + pDst->y - srcy - pSrc->y); -+ -+ REGION_UNINIT(pSrc->pScreen, &srcRegion); -+ -+ } else { -+ -+ REGION_UNION(pScreen, &cl->modifiedRegion, &cl->modifiedRegion, -+ &dstRegion); -+ } -+ } -+ -+ } else { -+ -+ ADD_TO_MODIFIED_REGION(pDst->pScreen, &dstRegion); -+ } -+ -+ REGION_UNINIT(pDst->pScreen, &dstRegion); -+ -+ rgn = (*pGC->ops->CopyArea) (pSrc, pDst, pGC, srcx, srcy, w, h, -+ dstx, dsty); -+ -+ SCHEDULE_FB_UPDATE(pDst->pScreen, pVNC); -+ -+ GC_OP_EPILOGUE(pGC); -+ -+ return rgn; -+} -+ -+ -+/* -+ * CopyPlane - the region being modified is the destination rectangle (clipped -+ * to the window clip region). -+ */ -+ -+static RegionPtr -+rfbCopyPlane (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty, plane) -+ DrawablePtr pSrc; -+ DrawablePtr pDst; -+ register GCPtr pGC; -+ int srcx, -+ srcy; -+ int w, -+ h; -+ int dstx, -+ dsty; -+ unsigned long plane; -+{ -+ RegionPtr rgn; -+ RegionRec tmpRegion; -+ BoxRec box; -+ GC_OP_PROLOGUE(pDst, pGC); -+ -+ TRC((stderr,"rfbCopyPlane called\n")); -+ -+ box.x1 = dstx + pDst->x; -+ box.y1 = dsty + pDst->y; -+ box.x2 = box.x1 + w; -+ box.y2 = box.y1 + h; -+ -+ SAFE_REGION_INIT(pDst->pScreen, &tmpRegion, &box, 0); -+ -+ REGION_INTERSECT(pDst->pScreen, &tmpRegion, &tmpRegion, -+ pGC->pCompositeClip); -+ -+ ADD_TO_MODIFIED_REGION(pDst->pScreen, &tmpRegion); -+ -+ REGION_UNINIT(pDst->pScreen, &tmpRegion); -+ -+ rgn = (*pGC->ops->CopyPlane) (pSrc, pDst, pGC, srcx, srcy, w, h, -+ dstx, dsty, plane); -+ -+ SCHEDULE_FB_UPDATE(pDst->pScreen, pVNC); -+ -+ GC_OP_EPILOGUE(pGC); -+ -+ return rgn; -+} -+ -+/* -+ * PolyPoint - find the smallest rectangle which encloses the points drawn -+ * (and clip). -+ */ -+ -+static void -+rfbPolyPoint (pDrawable, pGC, mode, npt, pts) -+ DrawablePtr pDrawable; -+ GCPtr pGC; -+ int mode; /* Origin or Previous */ -+ int npt; -+ xPoint *pts; -+{ -+ int i; -+ RegionRec tmpRegion; -+ BoxRec box; -+ GC_OP_PROLOGUE(pDrawable, pGC); -+ -+ TRC((stderr,"rfbPolyPoint called\n")); -+ -+ if (npt) { -+ int minX = pts[0].x, maxX = pts[0].x; -+ int minY = pts[0].y, maxY = pts[0].y; -+ -+ if (mode == CoordModePrevious) -+ { -+ int x = pts[0].x, y = pts[0].y; -+ -+ for (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 (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; -+ } -+ } -+ -+ box.x1 = minX + pDrawable->x; -+ box.y1 = minY + pDrawable->y; -+ box.x2 = maxX + 1 + pDrawable->x; -+ box.y2 = maxY + 1 + pDrawable->y; -+ -+ SAFE_REGION_INIT(pDrawable->pScreen, &tmpRegion, &box, 0); -+ -+ REGION_INTERSECT(pDrawable->pScreen, &tmpRegion, &tmpRegion, -+ pGC->pCompositeClip); -+ -+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, &tmpRegion); -+ -+ REGION_UNINIT(pDrawable->pScreen, &tmpRegion); -+ } -+ -+ (*pGC->ops->PolyPoint) (pDrawable, pGC, mode, npt, pts); -+ -+ if (npt) { -+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); -+ } -+ -+ GC_OP_EPILOGUE(pGC); -+} -+ -+/* -+ * PolyLines - take the union of bounding boxes around each line (and clip). -+ */ -+ -+static void -+rfbPolylines (DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, DDXPointPtr ppts) -+{ -+ RegionPtr tmpRegion; -+ xRectangle *rects; -+ int i, extra, nlines, lw; -+ int x1, x2, y1, y2; -+ GC_OP_PROLOGUE(pDrawable, pGC); -+ -+ TRC((stderr,"rfbPolylines called\n")); -+ -+ if (npt) { -+ lw = pGC->lineWidth; -+ if (lw == 0) -+ lw = 1; -+ -+ if (npt == 1) -+ { -+ nlines = 1; -+ rects = (xRectangle *)xalloc(sizeof(xRectangle)); -+ if (!rects) { -+ FatalError("rfbPolylines: xalloc failed\n"); -+ } -+ -+ rects[0].x = ppts[0].x - lw + pDrawable->x; /* being safe here */ -+ rects[0].y = ppts[0].y - lw + pDrawable->y; -+ rects[0].width = 2*lw; -+ rects[0].height = 2*lw; -+ } -+ else -+ { -+ nlines = npt - 1; -+ rects = (xRectangle *)xalloc(nlines*sizeof(xRectangle)); -+ if (!rects) { -+ FatalError("rfbPolylines: xalloc failed\n"); -+ } -+ -+ /* -+ * 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 -+ */ -+ -+ if (pGC->joinStyle == JoinMiter) { -+ extra = 6 * lw; -+ } else { -+ extra = lw / 2; -+ } -+ -+ x1 = ppts[0].x + pDrawable->x; -+ y1 = ppts[0].y + pDrawable->y; -+ -+ for (i = 0; i < nlines; i++) { -+ if (mode == CoordModeOrigin) { -+ x2 = pDrawable->x + ppts[i+1].x; -+ y2 = pDrawable->y + ppts[i+1].y; -+ } else { -+ x2 = x1 + ppts[i+1].x; -+ y2 = y1 + ppts[i+1].y; -+ } -+ -+ if (x1 > x2) { -+ rects[i].x = x2 - extra; -+ rects[i].width = x1 - x2 + 1 + 2 * extra; -+ } else { -+ rects[i].x = x1 - extra; -+ rects[i].width = x2 - x1 + 1 + 2 * extra; -+ } -+ -+ if (y1 > y2) { -+ rects[i].y = y2 - extra; -+ rects[i].height = y1 - y2 + 1 + 2 * extra; -+ } else { -+ rects[i].y = y1 - extra; -+ rects[i].height = y2 - y1 + 1 + 2 * extra; -+ } -+ -+ x1 = x2; -+ y1 = y2; -+ } -+ } -+ tmpRegion = RECTS_TO_REGION(pDrawable->pScreen, nlines, rects,CT_NONE); -+ REGION_INTERSECT(pDrawable->pScreen, tmpRegion, tmpRegion, -+ pGC->pCompositeClip); -+ -+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, tmpRegion); -+ -+ REGION_DESTROY(pDrawable->pScreen, tmpRegion); -+ xfree((char *)rects); -+ } -+ -+ (*pGC->ops->Polylines) (pDrawable, pGC, mode, npt, ppts); -+ -+ if (npt) { -+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); -+ } -+ -+ GC_OP_EPILOGUE(pGC); -+} -+ -+/* -+ * PolySegment - take the union of bounding boxes around each segment (and -+ * clip). -+ */ -+ -+static void -+rfbPolySegment(pDrawable, pGC, nseg, segs) -+ DrawablePtr pDrawable; -+ GCPtr pGC; -+ int nseg; -+ xSegment *segs; -+{ -+ RegionPtr tmpRegion; -+ xRectangle *rects; -+ int i, extra, lw; -+ -+ GC_OP_PROLOGUE(pDrawable, pGC); -+ -+ TRC((stderr,"rfbPolySegment called\n")); -+ -+ if (nseg) { -+ rects = (xRectangle *)xalloc(nseg*sizeof(xRectangle)); -+ if (!rects) { -+ FatalError("rfbPolySegment: xalloc failed\n"); -+ } -+ -+ lw = pGC->lineWidth; -+ if (lw == 0) -+ lw = 1; -+ -+ extra = lw / 2; -+ -+ for (i = 0; i < nseg; i++) -+ { -+ if (segs[i].x1 > segs[i].x2) { -+ rects[i].x = segs[i].x2 - extra + pDrawable->x; -+ rects[i].width = segs[i].x1 - segs[i].x2 + 1 + 2 * extra; -+ } else { -+ rects[i].x = segs[i].x1 - extra + pDrawable->x; -+ rects[i].width = segs[i].x2 - segs[i].x1 + 1 + 2 * extra; -+ } -+ -+ if (segs[i].y1 > segs[i].y2) { -+ rects[i].y = segs[i].y2 - extra + pDrawable->y; -+ rects[i].height = segs[i].y1 - segs[i].y2 + 1 + 2 * extra; -+ } else { -+ rects[i].y = segs[i].y1 - extra + pDrawable->y; -+ rects[i].height = segs[i].y2 - segs[i].y1 + 1 + 2 * extra; -+ } -+ } -+ -+ tmpRegion = RECTS_TO_REGION(pDrawable->pScreen, nseg, rects, CT_NONE); -+ REGION_INTERSECT(pDrawable->pScreen, tmpRegion, tmpRegion, -+ pGC->pCompositeClip); -+ -+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, tmpRegion); -+ -+ REGION_DESTROY(pDrawable->pScreen, tmpRegion); -+ xfree((char *)rects); -+ } -+ -+ (*pGC->ops->PolySegment) (pDrawable, pGC, nseg, segs); -+ -+ if (nseg) { -+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); -+ } -+ -+ GC_OP_EPILOGUE(pGC); -+} -+ -+/* -+ * PolyRectangle (rectangle outlines) - take the union of bounding boxes -+ * around each line (and clip). -+ */ -+ -+static void -+rfbPolyRectangle(pDrawable, pGC, nrects, rects) -+ DrawablePtr pDrawable; -+ GCPtr pGC; -+ int nrects; -+ xRectangle *rects; -+{ -+ int i, extra, lw; -+ RegionPtr tmpRegion; -+ xRectangle *regRects; -+ GC_OP_PROLOGUE(pDrawable, pGC); -+ -+ TRC((stderr,"rfbPolyRectangle called\n")); -+ -+ if (nrects) { -+ regRects = (xRectangle *)xalloc(nrects*4*sizeof(xRectangle)); -+ if (!regRects) { -+ FatalError("rfbPolyRectangle: xalloc failed\n"); -+ } -+ -+ lw = pGC->lineWidth; -+ if (lw == 0) -+ lw = 1; -+ -+ extra = lw / 2; -+ -+ for (i = 0; i < nrects; i++) -+ { -+ 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; -+ } -+ -+ tmpRegion = RECTS_TO_REGION(pDrawable->pScreen, nrects*4, -+ regRects, CT_NONE); -+ REGION_INTERSECT(pDrawable->pScreen, tmpRegion, tmpRegion, -+ pGC->pCompositeClip); -+ -+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, tmpRegion); -+ -+ REGION_DESTROY(pDrawable->pScreen, tmpRegion); -+ xfree((char *)regRects); -+ } -+ -+ (*pGC->ops->PolyRectangle) (pDrawable, pGC, nrects, rects); -+ -+ if (nrects) { -+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); -+ } -+ -+ GC_OP_EPILOGUE(pGC); -+} -+ -+/* -+ * PolyArc - take the union of bounding boxes around each arc (and clip). -+ * Bounding boxes assume each is a full circle / ellipse. -+ */ -+ -+static void -+rfbPolyArc(pDrawable, pGC, narcs, arcs) -+ DrawablePtr pDrawable; -+ register GCPtr pGC; -+ int narcs; -+ xArc *arcs; -+{ -+ int i, extra, lw; -+ RegionPtr tmpRegion; -+ xRectangle *rects; -+ GC_OP_PROLOGUE(pDrawable, pGC); -+ -+ TRC((stderr,"rfbPolyArc called\n")); -+ -+ if (narcs) { -+ rects = (xRectangle *)xalloc(narcs*sizeof(xRectangle)); -+ if (!rects) { -+ FatalError("rfbPolyArc: xalloc failed\n"); -+ } -+ -+ lw = pGC->lineWidth; -+ if (lw == 0) -+ lw = 1; -+ -+ extra = lw / 2; -+ -+ for (i = 0; i < narcs; i++) -+ { -+ rects[i].x = arcs[i].x - extra + pDrawable->x; -+ rects[i].y = arcs[i].y - extra + pDrawable->y; -+ rects[i].width = arcs[i].width + lw; -+ rects[i].height = arcs[i].height + lw; -+ } -+ -+ tmpRegion = RECTS_TO_REGION(pDrawable->pScreen, narcs, rects, CT_NONE); -+ REGION_INTERSECT(pDrawable->pScreen, tmpRegion, tmpRegion, -+ pGC->pCompositeClip); -+ -+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, tmpRegion); -+ -+ REGION_DESTROY(pDrawable->pScreen, tmpRegion); -+ xfree((char *)rects); -+ } -+ -+ (*pGC->ops->PolyArc) (pDrawable, pGC, narcs, arcs); -+ -+ if (narcs) { -+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); -+ } -+ -+ GC_OP_EPILOGUE(pGC); -+} -+ -+/* -+ * FillPolygon - take bounding box around polygon (and clip). -+ */ -+ -+static void -+rfbFillPolygon(pDrawable, pGC, shape, mode, count, pts) -+ register DrawablePtr pDrawable; -+ register GCPtr pGC; -+ int shape, mode; -+ int count; -+ DDXPointPtr pts; -+{ -+ int i; -+ RegionRec tmpRegion; -+ BoxRec box; -+ GC_OP_PROLOGUE(pDrawable, pGC); -+ -+ TRC((stderr,"rfbFillPolygon called\n")); -+ -+ if (count) { -+ int minX = pts[0].x, maxX = pts[0].x; -+ int minY = pts[0].y, maxY = pts[0].y; -+ -+ if (mode == CoordModePrevious) -+ { -+ int x = pts[0].x, y = pts[0].y; -+ -+ for (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 (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; -+ } -+ } -+ -+ box.x1 = minX + pDrawable->x; -+ box.y1 = minY + pDrawable->y; -+ box.x2 = maxX + 1 + pDrawable->x; -+ box.y2 = maxY + 1 + pDrawable->y; -+ -+ SAFE_REGION_INIT(pDrawable->pScreen, &tmpRegion, &box, 0); -+ -+ REGION_INTERSECT(pDrawable->pScreen, &tmpRegion, &tmpRegion, -+ pGC->pCompositeClip); -+ -+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, &tmpRegion); -+ -+ REGION_UNINIT(pDrawable->pScreen, &tmpRegion); -+ } -+ -+ (*pGC->ops->FillPolygon) (pDrawable, pGC, shape, mode, count, pts); -+ -+ if (count) { -+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); -+ } -+ -+ GC_OP_EPILOGUE(pGC); -+} -+ -+/* -+ * PolyFillRect - take the union of the given rectangles (and clip). -+ */ -+ -+static void -+rfbPolyFillRect(pDrawable, pGC, nrects, rects) -+ DrawablePtr pDrawable; -+ GCPtr pGC; -+ int nrects; -+ xRectangle *rects; -+{ -+ RegionPtr tmpRegion; -+ xRectangle *regRects; -+ int i; -+ GC_OP_PROLOGUE(pDrawable, pGC); -+ -+ TRC((stderr,"rfbPolyFillRect called\n")); -+ -+ if (nrects) { -+ regRects = (xRectangle *)xalloc(nrects*sizeof(xRectangle)); -+ if (!regRects) { -+ FatalError("rfbPolyFillRect: xalloc failed\n"); -+ } -+ -+ for (i = 0; i < nrects; i++) { -+ 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; -+ } -+ -+ tmpRegion = RECTS_TO_REGION(pDrawable->pScreen, nrects, regRects, -+ CT_NONE); -+ REGION_INTERSECT(pDrawable->pScreen, tmpRegion, tmpRegion, -+ pGC->pCompositeClip); -+ -+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, tmpRegion); -+ -+ REGION_DESTROY(pDrawable->pScreen, tmpRegion); -+ xfree((char *)regRects); -+ } -+ -+ (*pGC->ops->PolyFillRect) (pDrawable, pGC, nrects, rects); -+ -+ if (nrects) { -+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); -+ } -+ -+ GC_OP_EPILOGUE(pGC); -+} -+ -+/* -+ * PolyFillArc - take the union of bounding boxes around each arc (and clip). -+ * Bounding boxes assume each is a full circle / ellipse. -+ */ -+ -+static void -+rfbPolyFillArc(pDrawable, pGC, narcs, arcs) -+ DrawablePtr pDrawable; -+ GCPtr pGC; -+ int narcs; -+ xArc *arcs; -+{ -+ int i, extra, lw; -+ RegionPtr tmpRegion; -+ xRectangle *rects; -+ GC_OP_PROLOGUE(pDrawable, pGC); -+ -+ TRC((stderr,"rfbPolyFillArc called\n")); -+ -+ if (narcs) { -+ rects = (xRectangle *)xalloc(narcs*sizeof(xRectangle)); -+ if (!rects) { -+ FatalError("rfbPolyFillArc: xalloc failed\n"); -+ } -+ -+ lw = pGC->lineWidth; -+ if (lw == 0) -+ lw = 1; -+ -+ extra = lw / 2; -+ -+ for (i = 0; i < narcs; i++) -+ { -+ rects[i].x = arcs[i].x - extra + pDrawable->x; -+ rects[i].y = arcs[i].y - extra + pDrawable->y; -+ rects[i].width = arcs[i].width + lw; -+ rects[i].height = arcs[i].height + lw; -+ } -+ -+ tmpRegion = RECTS_TO_REGION(pDrawable->pScreen, narcs, rects, CT_NONE); -+ REGION_INTERSECT(pDrawable->pScreen, tmpRegion, tmpRegion, -+ pGC->pCompositeClip); -+ -+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, tmpRegion); -+ -+ REGION_DESTROY(pDrawable->pScreen, tmpRegion); -+ xfree((char *)rects); -+ } -+ -+ (*pGC->ops->PolyFillArc) (pDrawable, pGC, narcs, arcs); -+ -+ if (narcs) { -+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); -+ } -+ -+ GC_OP_EPILOGUE(pGC); -+} -+ -+/* -+ * Get a rough bounding box around n characters of the given font. -+ */ -+ -+static void GetTextBoundingBox(pDrawable, font, x, y, n, pbox) -+ DrawablePtr pDrawable; -+ FontPtr font; -+ int x, y, n; -+ BoxPtr pbox; -+{ -+ int maxAscent, maxDescent, maxCharWidth; -+ -+ if (FONTASCENT(font) > FONTMAXBOUNDS(font,ascent)) -+ maxAscent = FONTASCENT(font); -+ else -+ maxAscent = FONTMAXBOUNDS(font,ascent); -+ -+ if (FONTDESCENT(font) > FONTMAXBOUNDS(font,descent)) -+ maxDescent = FONTDESCENT(font); -+ else -+ maxDescent = FONTMAXBOUNDS(font,descent); -+ -+ if (FONTMAXBOUNDS(font,rightSideBearing) > FONTMAXBOUNDS(font,characterWidth)) -+ maxCharWidth = FONTMAXBOUNDS(font,rightSideBearing); -+ else -+ maxCharWidth = FONTMAXBOUNDS(font,characterWidth); -+ -+ pbox->x1 = pDrawable->x + x; -+ pbox->y1 = pDrawable->y + y - maxAscent; -+ pbox->x2 = pbox->x1 + maxCharWidth * n; -+ pbox->y2 = pbox->y1 + maxAscent + maxDescent; -+ -+ if (FONTMINBOUNDS(font,leftSideBearing) < 0) { -+ pbox->x1 += FONTMINBOUNDS(font,leftSideBearing); -+ } -+} -+ -+ -+/* -+ * PolyText8 - use rough bounding box. -+ */ -+ -+static int -+rfbPolyText8(pDrawable, pGC, x, y, count, chars) -+ DrawablePtr pDrawable; -+ GCPtr pGC; -+ int x, y; -+ int count; -+ char *chars; -+{ -+ int ret; -+ RegionRec tmpRegion; -+ BoxRec box; -+ GC_OP_PROLOGUE(pDrawable, pGC); -+ -+ TRC((stderr,"rfbPolyText8 called '%.*s'\n",count,chars)); -+ -+ if (count) { -+ GetTextBoundingBox(pDrawable, pGC->font, x, y, count, &box); -+ -+ SAFE_REGION_INIT(pDrawable->pScreen, &tmpRegion, &box, 0); -+ -+ REGION_INTERSECT(pDrawable->pScreen, &tmpRegion, &tmpRegion, -+ pGC->pCompositeClip); -+ -+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, &tmpRegion); -+ -+ REGION_UNINIT(pDrawable->pScreen, &tmpRegion); -+ } -+ -+ ret = (*pGC->ops->PolyText8) (pDrawable, pGC, x, y, count, chars); -+ -+ if (count) { -+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); -+ } -+ -+ GC_OP_EPILOGUE(pGC); -+ return ret; -+} -+ -+/* -+ * PolyText16 - use rough bounding box. -+ */ -+ -+static int -+rfbPolyText16(pDrawable, pGC, x, y, count, chars) -+ DrawablePtr pDrawable; -+ GCPtr pGC; -+ int x, y; -+ int count; -+ unsigned short *chars; -+{ -+ int ret; -+ RegionRec tmpRegion; -+ BoxRec box; -+ GC_OP_PROLOGUE(pDrawable, pGC); -+ -+ TRC((stderr,"rfbPolyText16 called\n")); -+ -+ if (count) { -+ GetTextBoundingBox(pDrawable, pGC->font, x, y, count, &box); -+ -+ SAFE_REGION_INIT(pDrawable->pScreen, &tmpRegion, &box, 0); -+ -+ REGION_INTERSECT(pDrawable->pScreen, &tmpRegion, &tmpRegion, -+ pGC->pCompositeClip); -+ -+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, &tmpRegion); -+ -+ REGION_UNINIT(pDrawable->pScreen, &tmpRegion); -+ } -+ -+ ret = (*pGC->ops->PolyText16) (pDrawable, pGC, x, y, count, chars); -+ -+ if (count) { -+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); -+ } -+ -+ GC_OP_EPILOGUE(pGC); -+ return ret; -+} -+ -+/* -+ * ImageText8 - use rough bounding box. -+ */ -+ -+static void -+rfbImageText8(pDrawable, pGC, x, y, count, chars) -+ DrawablePtr pDrawable; -+ GCPtr pGC; -+ int x, y; -+ int count; -+ char *chars; -+{ -+ RegionRec tmpRegion; -+ BoxRec box; -+ GC_OP_PROLOGUE(pDrawable, pGC); -+ -+ TRC((stderr,"rfbImageText8 called '%.*s'\n",count,chars)); -+ -+ if (count) { -+ GetTextBoundingBox(pDrawable, pGC->font, x, y, count, &box); -+ -+ SAFE_REGION_INIT(pDrawable->pScreen, &tmpRegion, &box, 0); -+ -+ REGION_INTERSECT(pDrawable->pScreen, &tmpRegion, &tmpRegion, -+ pGC->pCompositeClip); -+ -+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, &tmpRegion); -+ -+ REGION_UNINIT(pDrawable->pScreen, &tmpRegion); -+ } -+ -+ (*pGC->ops->ImageText8) (pDrawable, pGC, x, y, count, chars); -+ -+ if (count) { -+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); -+ } -+ -+ GC_OP_EPILOGUE(pGC); -+} -+ -+/* -+ * ImageText16 - use rough bounding box. -+ */ -+ -+static void -+rfbImageText16(pDrawable, pGC, x, y, count, chars) -+ DrawablePtr pDrawable; -+ GCPtr pGC; -+ int x, y; -+ int count; -+ unsigned short *chars; -+{ -+ RegionRec tmpRegion; -+ BoxRec box; -+ GC_OP_PROLOGUE(pDrawable, pGC); -+ -+ TRC((stderr,"rfbImageText16 called\n")); -+ -+ if (count) { -+ GetTextBoundingBox(pDrawable, pGC->font, x, y, count, &box); -+ -+ SAFE_REGION_INIT(pDrawable->pScreen, &tmpRegion, &box, 0); -+ -+ REGION_INTERSECT(pDrawable->pScreen, &tmpRegion, &tmpRegion, -+ pGC->pCompositeClip); -+ -+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, &tmpRegion); -+ -+ REGION_UNINIT(pDrawable->pScreen, &tmpRegion); -+ } -+ -+ (*pGC->ops->ImageText16) (pDrawable, pGC, x, y, count, chars); -+ -+ if (count) { -+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); -+ } -+ -+ GC_OP_EPILOGUE(pGC); -+} -+ -+/* -+ * ImageGlyphBlt - use rough bounding box. -+ */ -+ -+static void -+rfbImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase) -+ DrawablePtr pDrawable; -+ GCPtr pGC; -+ int x, y; -+ unsigned int nglyph; -+ CharInfoPtr *ppci; /* array of character info */ -+ pointer pglyphBase; /* start of array of glyphs */ -+{ -+ RegionRec tmpRegion; -+ BoxRec box; -+ GC_OP_PROLOGUE(pDrawable, pGC); -+ -+ TRC((stderr,"rfbImageGlyphBlt called\n")); -+ -+ if (nglyph) { -+ GetTextBoundingBox(pDrawable, pGC->font, x, y, nglyph, &box); -+ -+ SAFE_REGION_INIT(pDrawable->pScreen, &tmpRegion, &box, 0); -+ -+ REGION_INTERSECT(pDrawable->pScreen, &tmpRegion, &tmpRegion, -+ pGC->pCompositeClip); -+ -+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, &tmpRegion); -+ -+ REGION_UNINIT(pDrawable->pScreen, &tmpRegion); -+ } -+ -+ (*pGC->ops->ImageGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci,pglyphBase); -+ -+ if (nglyph) { -+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); -+ } -+ -+ GC_OP_EPILOGUE(pGC); -+} -+ -+/* -+ * PolyGlyphBlt - use rough bounding box. -+ */ -+ -+static void -+rfbPolyGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase) -+ DrawablePtr pDrawable; -+ GCPtr pGC; -+ int x, y; -+ unsigned int nglyph; -+ CharInfoPtr *ppci; /* array of character info */ -+ pointer pglyphBase; /* start of array of glyphs */ -+{ -+ RegionRec tmpRegion; -+ BoxRec box; -+ GC_OP_PROLOGUE(pDrawable, pGC); -+ -+ TRC((stderr,"rfbPolyGlyphBlt called\n")); -+ -+ if (nglyph) { -+ GetTextBoundingBox(pDrawable, pGC->font, x, y, nglyph, &box); -+ -+ SAFE_REGION_INIT(pDrawable->pScreen, &tmpRegion, &box, 0); -+ -+ REGION_INTERSECT(pDrawable->pScreen, &tmpRegion, &tmpRegion, -+ pGC->pCompositeClip); -+ -+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, &tmpRegion); -+ -+ REGION_UNINIT(pDrawable->pScreen, &tmpRegion); -+ } -+ -+ (*pGC->ops->PolyGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); -+ -+ if (nglyph) { -+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); -+ } -+ -+ GC_OP_EPILOGUE(pGC); -+} -+ -+/* -+ * PushPixels - be fairly safe - region modified is intersection of the given -+ * rectangle with the window clip region. -+ */ -+ -+static void -+rfbPushPixels(pGC, pBitMap, pDrawable, w, h, x, y) -+ GCPtr pGC; -+ PixmapPtr pBitMap; -+ DrawablePtr pDrawable; -+ int w, h, x, y; -+{ -+ RegionRec tmpRegion; -+ BoxRec box; -+ GC_OP_PROLOGUE(pDrawable, pGC); -+ -+ TRC((stderr,"rfbPushPixels called\n")); -+ -+ box.x1 = x + pDrawable->x; -+ box.y1 = y + pDrawable->y; -+ box.x2 = box.x1 + w; -+ box.y2 = box.y1 + h; -+ -+ SAFE_REGION_INIT(pDrawable->pScreen, &tmpRegion, &box, 0); -+ -+ REGION_INTERSECT(pDrawable->pScreen, &tmpRegion, &tmpRegion, -+ pGC->pCompositeClip); -+ -+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, &tmpRegion); -+ -+ REGION_UNINIT(pDrawable->pScreen, &tmpRegion); -+ -+ (*pGC->ops->PushPixels) (pGC, pBitMap, pDrawable, w, h, x, y); -+ -+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); -+ -+ GC_OP_EPILOGUE(pGC); -+} -+ -+#ifdef RENDER -+void -+rfbComposite( -+ 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; -+ VNCSCREENPTR(pScreen); -+ RegionRec tmpRegion; -+ BoxRec box; -+ PictureScreenPtr ps = GetPictureScreen(pScreen); -+ -+ box.x1 = pDst->pDrawable->x + xDst; -+ box.y1 = pDst->pDrawable->y + yDst; -+ box.x2 = box.x1 + width; -+ box.y2 = box.y1 + height; -+ -+ REGION_INIT(pScreen, &tmpRegion, &box, 0); -+ -+ ADD_TO_MODIFIED_REGION(pScreen, &tmpRegion); -+ -+ ps->Composite = pVNC->Composite; -+ (*ps->Composite)(op, pSrc, pMask, pDst, xSrc, ySrc, -+ xMask, yMask, xDst, yDst, width, height); -+ ps->Composite = rfbComposite; -+ -+ SCHEDULE_FB_UPDATE(pScreen, pVNC); -+ -+ REGION_UNINIT(pScreen, &tmpRegion); -+} -+#endif /* RENDER */ -+ -+/****************************************************************************/ -+/* -+ * Other functions -+ */ -+/****************************************************************************/ -+ -+/* -+ * rfbCopyRegion. Args are src and dst regions plus a translation (dx,dy). -+ * Takes these args together with the existing modified region and possibly an -+ * existing copy region and translation. Produces a combined modified region -+ * plus copy region and translation. Note that the copy region is the -+ * destination of the copy. -+ * -+ * First we trim parts of src which are invalid (ie in the modified region). -+ * Then we see if there is any overlap between the src and the existing copy -+ * region. If not then the two copies cannot be combined, so we choose -+ * whichever is bigger to form the basis of a new copy, while the other copy is -+ * just done the hard way by being added to the modified region. So if the -+ * existing copy is bigger then we simply add the destination of the new copy -+ * to the modified region and we're done. If the new copy is bigger, we add -+ * the old copy region to the modified region and behave as though there is no -+ * existing copy region. -+ * -+ * At this stage we now know that either the two copies can be combined, or -+ * that there is no existing copy. We temporarily add both the existing copy -+ * region and dst to the modified region (this is the entire area of the screen -+ * affected in any way). Finally we calculate the new copy region, and remove -+ * it from the modified region. -+ * -+ * Note: -+ * 1. The src region is modified by this routine. -+ * 2. When the copy region is empty, copyDX and copyDY MUST be set to zero. -+ */ -+ -+static void -+rfbCopyRegion(pScreen, cl, src, dst, dx, dy) -+ ScreenPtr pScreen; -+ rfbClientPtr cl; -+ RegionPtr src; -+ RegionPtr dst; -+ int dx, dy; -+{ -+ RegionRec tmp; -+ -+ /* src = src - modifiedRegion */ -+ -+ REGION_SUBTRACT(pScreen, src, src, &cl->modifiedRegion); -+ -+ if (REGION_NOTEMPTY(pScreen, &cl->copyRegion)) { -+ -+ REGION_NULL(pScreen, &tmp); -+ REGION_INTERSECT(pScreen, &tmp, src, &cl->copyRegion); -+ -+ if (REGION_NOTEMPTY(pScreen, &tmp)) { -+ -+ /* if src and copyRegion overlap: -+ src = src intersect copyRegion */ -+ -+ REGION_COPY(pScreen, src, &tmp); -+ -+ } else { -+ -+ /* if no overlap, find bigger region */ -+ -+ int newArea = (((REGION_EXTENTS(pScreen,src))->x2 -+ - (REGION_EXTENTS(pScreen,src))->x1) -+ * ((REGION_EXTENTS(pScreen,src))->y2 -+ - (REGION_EXTENTS(pScreen,src))->y1)); -+ -+ int oldArea = (((REGION_EXTENTS(pScreen,&cl->copyRegion))->x2 -+ - (REGION_EXTENTS(pScreen,&cl->copyRegion))->x1) -+ * ((REGION_EXTENTS(pScreen,&cl->copyRegion))->y2 -+ - (REGION_EXTENTS(pScreen,&cl->copyRegion))->y1)); -+ -+ if (oldArea > newArea) { -+ -+ /* existing copy is bigger: -+ modifiedRegion = modifiedRegion union dst -+ copyRegion = copyRegion - dst -+ return */ -+ -+ REGION_UNION(pScreen, &cl->modifiedRegion, &cl->modifiedRegion, -+ dst); -+ REGION_SUBTRACT(pScreen, &cl->copyRegion, &cl->copyRegion, -+ dst); -+ if (!REGION_NOTEMPTY(pScreen, &cl->copyRegion)) { -+ cl->copyDX = 0; -+ cl->copyDY = 0; -+ } -+ return; -+ } -+ -+ /* new copy is bigger: -+ modifiedRegion = modifiedRegion union copyRegion -+ copyRegion = empty */ -+ -+ REGION_UNION(pScreen, &cl->modifiedRegion, &cl->modifiedRegion, -+ &cl->copyRegion); -+ REGION_EMPTY(pScreen, &cl->copyRegion); -+ cl->copyDX = cl->copyDY = 0; -+ } -+ } -+ -+ -+ /* modifiedRegion = modifiedRegion union dst union copyRegion */ -+ -+ REGION_UNION(pScreen, &cl->modifiedRegion, &cl->modifiedRegion, dst); -+ REGION_UNION(pScreen, &cl->modifiedRegion, &cl->modifiedRegion, -+ &cl->copyRegion); -+ -+ /* copyRegion = T(src) intersect dst */ -+ -+ REGION_TRANSLATE(pScreen, src, dx, dy); -+ REGION_INTERSECT(pScreen, &cl->copyRegion, src, dst); -+ -+ /* modifiedRegion = modifiedRegion - copyRegion */ -+ -+ REGION_SUBTRACT(pScreen, &cl->modifiedRegion, &cl->modifiedRegion, -+ &cl->copyRegion); -+ -+ /* combine new translation T with existing translation */ -+ -+ if (REGION_NOTEMPTY(pScreen, &cl->copyRegion)) { -+ cl->copyDX += dx; -+ cl->copyDY += dy; -+ } else { -+ cl->copyDX = 0; -+ cl->copyDY = 0; -+ } -+} -+ -+ -+/* -+ * rfbDeferredUpdateCallback() is called when a client's deferredUpdateTimer -+ * goes off. -+ */ -+ -+static CARD32 -+rfbDeferredUpdateCallback(OsTimerPtr timer, CARD32 now, pointer arg) -+{ -+ rfbClientPtr cl = (rfbClientPtr)arg; -+ -+ rfbSendFramebufferUpdate(cl->pScreen, cl); -+ -+ cl->deferredUpdateScheduled = FALSE; -+ return 0; -+} -+ -+ -+/* -+ * rfbScheduleDeferredUpdate() is called from the SCHEDULE_FB_UPDATE macro -+ * to schedule an update. -+ */ -+ -+static void -+rfbScheduleDeferredUpdate(ScreenPtr pScreen, rfbClientPtr cl) -+{ -+ if (rfbDeferUpdateTime != 0) { -+ cl->deferredUpdateTimer = TimerSet(cl->deferredUpdateTimer, 0, -+ rfbDeferUpdateTime, -+ rfbDeferredUpdateCallback, cl); -+ cl->deferredUpdateScheduled = TRUE; -+ } else { -+ rfbSendFramebufferUpdate(pScreen, cl); -+ } -+} -+ -+ -+/* -+ * PrintRegion is useful for debugging. -+ */ -+ -+#ifdef DEBUG -+static void -+PrintRegion(ScreenPtr pScreen, RegionPtr reg) -+{ -+ int nrects = REGION_NUM_RECTS(reg); -+ int i; -+ -+ ErrorF("Region num rects %d extents %d,%d %d,%d\n",nrects, -+ (REGION_EXTENTS(pScreen,reg))->x1, -+ (REGION_EXTENTS(pScreen,reg))->y1, -+ (REGION_EXTENTS(pScreen,reg))->x2, -+ (REGION_EXTENTS(pScreen,reg))->y2); -+ -+ for (i = 0; i < nrects; i++) { -+ ErrorF(" rect %d,%d %dx%d\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); -+ } -+} -+#endif -diff --git a/hw/dmx/vnc/hextile.c b/hw/dmx/vnc/hextile.c -new file mode 100644 -index 0000000..6017489 ---- /dev/null -+++ b/hw/dmx/vnc/hextile.c -@@ -0,0 +1,352 @@ -+/* -+ * hextile.c -+ * -+ * Routines to implement Hextile Encoding -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ */ -+ -+/* -+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. -+ * -+ * This is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This software is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this software; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -+ * USA. -+ */ -+ -+#include -+#include -+#include "rfb.h" -+ -+static Bool sendHextiles8(rfbClientPtr cl, int x, int y, int w, int h); -+static Bool sendHextiles16(rfbClientPtr cl, int x, int y, int w, int h); -+static Bool sendHextiles32(rfbClientPtr cl, int x, int y, int w, int h); -+ -+ -+/* -+ * rfbSendRectEncodingHextile - send a rectangle using hextile encoding. -+ */ -+ -+Bool -+rfbSendRectEncodingHextile(cl, x, y, w, h) -+ rfbClientPtr cl; -+ int x, y, w, h; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ rfbFramebufferUpdateRectHeader rect; -+ -+ if (pVNC->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) { -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ } -+ -+ rect.r.x = Swap16IfLE(x); -+ rect.r.y = Swap16IfLE(y); -+ rect.r.w = Swap16IfLE(w); -+ rect.r.h = Swap16IfLE(h); -+ rect.encoding = Swap32IfLE(rfbEncodingHextile); -+ -+ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&rect, -+ sz_rfbFramebufferUpdateRectHeader); -+ pVNC->ublen += sz_rfbFramebufferUpdateRectHeader; -+ -+ cl->rfbRectanglesSent[rfbEncodingHextile]++; -+ cl->rfbBytesSent[rfbEncodingHextile] += sz_rfbFramebufferUpdateRectHeader; -+ -+ switch (cl->format.bitsPerPixel) { -+ case 8: -+ return sendHextiles8(cl, x, y, w, h); -+ case 16: -+ return sendHextiles16(cl, x, y, w, h); -+ case 32: -+ return sendHextiles32(cl, x, y, w, h); -+ } -+ -+ rfbLog("rfbSendRectEncodingHextile: bpp %d?\n", cl->format.bitsPerPixel); -+ return FALSE; -+} -+ -+ -+#define PUT_PIXEL8(pix) (pVNC->updateBuf[pVNC->ublen++] = (pix)) -+ -+#define PUT_PIXEL16(pix) (pVNC->updateBuf[pVNC->ublen++] = ((char*)&(pix))[0], \ -+ pVNC->updateBuf[pVNC->ublen++] = ((char*)&(pix))[1]) -+ -+#define PUT_PIXEL32(pix) (pVNC->updateBuf[pVNC->ublen++] = ((char*)&(pix))[0], \ -+ pVNC->updateBuf[pVNC->ublen++] = ((char*)&(pix))[1], \ -+ pVNC->updateBuf[pVNC->ublen++] = ((char*)&(pix))[2], \ -+ pVNC->updateBuf[pVNC->ublen++] = ((char*)&(pix))[3]) -+ -+ -+#define DEFINE_SEND_HEXTILES(bpp) \ -+ \ -+ \ -+static Bool subrectEncode##bpp(ScreenPtr pScreen, CARD##bpp *data, int w, \ -+ int h, CARD##bpp bg, \ -+ CARD##bpp fg, Bool mono); \ -+static void testColours##bpp(CARD##bpp *data, int size, Bool *mono, \ -+ Bool *solid, CARD##bpp *bg, CARD##bpp *fg); \ -+ \ -+ \ -+/* \ -+ * rfbSendHextiles \ -+ */ \ -+ \ -+static Bool \ -+sendHextiles##bpp(cl, rx, ry, rw, rh) \ -+ rfbClientPtr cl; \ -+ int rx, ry, rw, rh; \ -+{ \ -+ VNCSCREENPTR(cl->pScreen); \ -+ int x, y, w, h; \ -+ int startUblen; \ -+ unsigned char *fbptr; \ -+ CARD##bpp bg = 0, fg = 0, newBg, newFg; \ -+ Bool mono, solid; \ -+ Bool validBg = FALSE; \ -+ Bool validFg = FALSE; \ -+ CARD##bpp clientPixelData[16*16*(bpp/8)]; \ -+ \ -+ for (y = ry; y < ry+rh; y += 16) { \ -+ for (x = rx; x < rx+rw; x += 16) { \ -+ w = h = 16; \ -+ if (rx+rw - x < 16) \ -+ w = rx+rw - x; \ -+ if (ry+rh - y < 16) \ -+ h = ry+rh - y; \ -+ \ -+ if ((pVNC->ublen + 1 + (2 + 16 * 16) * (bpp/8)) > UPDATE_BUF_SIZE) { \ -+ if (!rfbSendUpdateBuf(cl)) \ -+ return FALSE; \ -+ } \ -+ \ -+ fbptr = (pVNC->pfbMemory + (pVNC->paddedWidthInBytes * y) \ -+ + (x * (pVNC->bitsPerPixel / 8))); \ -+ \ -+ (*cl->translateFn)(cl->pScreen, cl->translateLookupTable, \ -+ &pVNC->rfbServerFormat, \ -+ &cl->format, fbptr, (char *)clientPixelData, \ -+ pVNC->paddedWidthInBytes, w, h, x, y); \ -+ \ -+ startUblen = pVNC->ublen; \ -+ pVNC->updateBuf[startUblen] = 0; \ -+ pVNC->ublen++; \ -+ \ -+ testColours##bpp(clientPixelData, w * h, \ -+ &mono, &solid, &newBg, &newFg); \ -+ \ -+ if (!validBg || (newBg != bg)) { \ -+ validBg = TRUE; \ -+ bg = newBg; \ -+ pVNC->updateBuf[startUblen] |= rfbHextileBackgroundSpecified; \ -+ PUT_PIXEL##bpp(bg); \ -+ } \ -+ \ -+ if (solid) { \ -+ cl->rfbBytesSent[rfbEncodingHextile] += pVNC->ublen - startUblen; \ -+ continue; \ -+ } \ -+ \ -+ pVNC->updateBuf[startUblen] |= rfbHextileAnySubrects; \ -+ \ -+ if (mono) { \ -+ if (!validFg || (newFg != fg)) { \ -+ validFg = TRUE; \ -+ fg = newFg; \ -+ pVNC->updateBuf[startUblen] |= rfbHextileForegroundSpecified; \ -+ PUT_PIXEL##bpp(fg); \ -+ } \ -+ } else { \ -+ validFg = FALSE; \ -+ pVNC->updateBuf[startUblen] |= rfbHextileSubrectsColoured; \ -+ } \ -+ \ -+ if (!subrectEncode##bpp(cl->pScreen, clientPixelData, w, h, bg, fg, mono)) { \ -+ /* encoding was too large, use raw */ \ -+ validBg = FALSE; \ -+ validFg = FALSE; \ -+ pVNC->ublen = startUblen; \ -+ pVNC->updateBuf[pVNC->ublen++] = rfbHextileRaw; \ -+ (*cl->translateFn)(cl->pScreen, cl->translateLookupTable, \ -+ &pVNC->rfbServerFormat, &cl->format, fbptr,\ -+ (char *)clientPixelData, \ -+ pVNC->paddedWidthInBytes, w, h, x, y); \ -+ \ -+ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)clientPixelData,\ -+ w * h * (bpp/8)); \ -+ \ -+ pVNC->ublen += w * h * (bpp/8); \ -+ } \ -+ \ -+ cl->rfbBytesSent[rfbEncodingHextile] += pVNC->ublen - startUblen; \ -+ } \ -+ } \ -+ \ -+ return TRUE; \ -+} \ -+ \ -+ \ -+static Bool \ -+subrectEncode##bpp(ScreenPtr pScreen, CARD##bpp *data, int w, int h, \ -+ CARD##bpp bg, CARD##bpp fg, Bool mono) \ -+{ \ -+ VNCSCREENPTR(pScreen); \ -+ CARD##bpp clientdata; \ -+ int x,y; \ -+ int i,j; \ -+ int hx=0,hy,vx=0,vy; \ -+ int hyflag; \ -+ CARD##bpp *seg; \ -+ CARD##bpp *line; \ -+ int hw,hh,vw,vh; \ -+ int thex,they,thew,theh; \ -+ int numsubs = 0; \ -+ int newLen; \ -+ int nSubrectsUblen; \ -+ \ -+ nSubrectsUblen = pVNC->ublen; \ -+ pVNC->ublen++; \ -+ \ -+ for (y=0; y 0) && (i >= hx)) { \ -+ hy += 1; \ -+ } else { \ -+ hyflag = 0; \ -+ } \ -+ } \ -+ vy = j-1; \ -+ \ -+ /* We now have two possible subrects: (x,y,hx,hy) and \ -+ * (x,y,vx,vy). We'll choose the bigger of the two. \ -+ */ \ -+ hw = hx-x+1; \ -+ hh = hy-y+1; \ -+ vw = vx-x+1; \ -+ vh = vy-y+1; \ -+ \ -+ thex = x; \ -+ they = y; \ -+ \ -+ if ((hw*hh) > (vw*vh)) { \ -+ thew = hw; \ -+ theh = hh; \ -+ } else { \ -+ thew = vw; \ -+ theh = vh; \ -+ } \ -+ \ -+ if (mono) { \ -+ newLen = pVNC->ublen - nSubrectsUblen + 2; \ -+ } else { \ -+ newLen = pVNC->ublen - nSubrectsUblen + bpp/8 + 2; \ -+ } \ -+ \ -+ if (newLen > (w * h * (bpp/8))) \ -+ return FALSE; \ -+ \ -+ numsubs += 1; \ -+ \ -+ if (!mono) PUT_PIXEL##bpp(clientdata); \ -+ \ -+ pVNC->updateBuf[pVNC->ublen++] = rfbHextilePackXY(thex,they); \ -+ pVNC->updateBuf[pVNC->ublen++] = rfbHextilePackWH(thew,theh); \ -+ \ -+ /* \ -+ * Now mark the subrect as done. \ -+ */ \ -+ for (j=they; j < (they+theh); j++) { \ -+ for (i=thex; i < (thex+thew); i++) { \ -+ data[j*w+i] = bg; \ -+ } \ -+ } \ -+ } \ -+ } \ -+ } \ -+ \ -+ pVNC->updateBuf[nSubrectsUblen] = numsubs; \ -+ \ -+ return TRUE; \ -+} \ -+ \ -+ \ -+/* \ -+ * testColours() tests if there are one (solid), two (mono) or more \ -+ * colours in a tile and gets a reasonable guess at the best background \ -+ * pixel, and the foreground pixel for mono. \ -+ */ \ -+ \ -+static void \ -+testColours##bpp(data,size,mono,solid,bg,fg) \ -+ CARD##bpp *data; \ -+ int size; \ -+ Bool *mono; \ -+ Bool *solid; \ -+ CARD##bpp *bg; \ -+ CARD##bpp *fg; \ -+{ \ -+ CARD##bpp colour1 = 0, colour2 = 0; \ -+ int n1 = 0, n2 = 0; \ -+ *mono = TRUE; \ -+ *solid = TRUE; \ -+ \ -+ for (; size > 0; size--, data++) { \ -+ \ -+ if (n1 == 0) \ -+ colour1 = *data; \ -+ \ -+ if (*data == colour1) { \ -+ n1++; \ -+ continue; \ -+ } \ -+ \ -+ if (n2 == 0) { \ -+ *solid = FALSE; \ -+ colour2 = *data; \ -+ } \ -+ \ -+ if (*data == colour2) { \ -+ n2++; \ -+ continue; \ -+ } \ -+ \ -+ *mono = FALSE; \ -+ break; \ -+ } \ -+ \ -+ if (n1 > n2) { \ -+ *bg = colour1; \ -+ *fg = colour2; \ -+ } else { \ -+ *bg = colour2; \ -+ *fg = colour1; \ -+ } \ -+} -+ -+DEFINE_SEND_HEXTILES(8) -+DEFINE_SEND_HEXTILES(16) -+DEFINE_SEND_HEXTILES(32) -diff --git a/hw/dmx/vnc/httpd.c b/hw/dmx/vnc/httpd.c -new file mode 100644 -index 0000000..863543a ---- /dev/null -+++ b/hw/dmx/vnc/httpd.c -@@ -0,0 +1,520 @@ -+/* -+ * httpd.c - a simple HTTP server -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ */ -+ -+/* -+ * Copyright (C) 2002 Constantin Kaplinsky. All Rights Reserved. -+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. -+ * -+ * This is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This software is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this software; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -+ * USA. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#ifndef USE_LIBWRAP -+#define USE_LIBWRAP 0 -+#endif -+#if USE_LIBWRAP -+#include -+#endif -+ -+#include "rfb.h" -+ -+#define NOT_FOUND_STR "HTTP/1.0 404 Not found\r\n\r\n" \ -+ "File Not Found\n" \ -+ "

File Not Found

\n" -+ -+#define OK_STR "HTTP/1.0 200 OK\r\n\r\n" -+ -+static void httpProcessInput(ScreenPtr pScreen); -+static Bool compareAndSkip(char **ptr, const char *str); -+static Bool parseParams(const char *request, char *result, int max_bytes); -+static Bool validateString(char *str); -+ -+/* -+ * httpInitSockets sets up the TCP socket to listen for HTTP connections. -+ */ -+ -+Bool -+httpInitSockets(ScreenPtr pScreen) -+{ -+ VNCSCREENPTR(pScreen); -+ -+ if (!pVNC->httpDir) -+ return FALSE; -+ -+ pVNC->buf_filled = 0; -+ -+ if (pVNC->httpPort == 0) { -+ pVNC->httpPort = 5800 + atoi(display) + pScreen->myNum; -+ } -+ -+ if ((pVNC->httpListenSock = ListenOnTCPPort(pScreen, pVNC->httpPort)) < 0) { -+ rfbLog("ListenOnTCPPort %d failed\n",pVNC->httpPort); -+ pVNC->httpPort = 0; -+ return FALSE; -+ } -+ -+ rfbLog("Listening for HTTP connections on TCP port %d\n", pVNC->httpPort); -+ rfbLog(" URL http://%s:%d\n",rfbThisHost,pVNC->httpPort); -+ -+ AddEnabledDevice(pVNC->httpListenSock); -+ -+ return TRUE; -+} -+ -+ -+/* -+ * httpCheckFds is called from ProcessInputEvents to check for input on the -+ * HTTP socket(s). If there is input to process, httpProcessInput is called. -+ */ -+ -+void -+httpCheckFds(ScreenPtr pScreen) -+{ -+ VNCSCREENPTR(pScreen); -+ int nfds; -+ fd_set fds; -+ struct timeval tv; -+ struct sockaddr_in addr; -+ SOCKLEN_T addrlen = sizeof(addr); -+ -+ if (!pVNC->httpDir) -+ return; -+ -+ FD_ZERO(&fds); -+ FD_SET(pVNC->httpListenSock, &fds); -+ if (pVNC->httpSock >= 0) { -+ FD_SET(pVNC->httpSock, &fds); -+ } -+ tv.tv_sec = 0; -+ tv.tv_usec = 0; -+ nfds = select(max(pVNC->httpSock,pVNC->httpListenSock) + 1, &fds, NULL, NULL, &tv); -+ if (nfds == 0) { -+ return; -+ } -+ if (nfds < 0) { -+ if (errno != EINTR) -+ rfbLogPerror("httpCheckFds: select"); -+ return; -+ } -+ -+ if ((pVNC->httpSock >= 0) && FD_ISSET(pVNC->httpSock, &fds)) { -+ httpProcessInput(pScreen); -+ } -+ -+ if (FD_ISSET(pVNC->httpListenSock, &fds)) { -+ int flags; -+ -+ if (pVNC->httpSock >= 0) close(pVNC->httpSock); -+ -+ if ((pVNC->httpSock = accept(pVNC->httpListenSock, -+ (struct sockaddr *)&addr, &addrlen)) < 0) { -+ rfbLogPerror("httpCheckFds: accept"); -+ return; -+ } -+ -+#if USE_LIBWRAP -+ if (!hosts_ctl("Xvnc", STRING_UNKNOWN, inet_ntoa(addr.sin_addr), -+ STRING_UNKNOWN)) { -+ rfbLog("Rejected HTTP connection from client %s\n", -+ inet_ntoa(addr.sin_addr)); -+ close(pVNC->httpSock); -+ pVNC->httpSock = -1; -+ return; -+ } -+#endif -+ -+ flags = fcntl (pVNC->httpSock, F_GETFL); -+ -+ if (flags == -1 || -+ fcntl (pVNC->httpSock, F_SETFL, flags | O_NONBLOCK) == -1) { -+ rfbLogPerror("httpCheckFds: fcntl"); -+ close (pVNC->httpSock); -+ pVNC->httpSock = -1; -+ return; -+ } -+ -+ AddEnabledDevice(pVNC->httpSock); -+ } -+} -+ -+ -+static void -+httpCloseSock(ScreenPtr pScreen) -+{ -+ VNCSCREENPTR(pScreen); -+ close(pVNC->httpSock); -+ RemoveEnabledDevice(pVNC->httpSock); -+ pVNC->httpSock = -1; -+ pVNC->buf_filled = 0; -+} -+ -+ -+/* -+ * httpProcessInput is called when input is received on the HTTP socket. -+ */ -+ -+static void -+httpProcessInput(ScreenPtr pScreen) -+{ -+ VNCSCREENPTR(pScreen); -+ struct sockaddr_in addr; -+ SOCKLEN_T addrlen = sizeof(addr); -+ char fullFname[512]; -+ char params[1024]; -+ char *ptr; -+ char *fname; -+ int maxFnameLen; -+ int fd; -+ Bool performSubstitutions = FALSE; -+ char str[256]; -+ struct passwd *user = getpwuid(getuid()); -+ -+ if (strlen(pVNC->httpDir) > 255) { -+ rfbLog("-httpd directory too long\n"); -+ httpCloseSock(pScreen); -+ return; -+ } -+ strcpy(fullFname, pVNC->httpDir); -+ fname = &fullFname[strlen(fullFname)]; -+ maxFnameLen = 511 - strlen(fullFname); -+ -+ /* Read data from the HTTP client until we get a complete request. */ -+ while (1) { -+ ssize_t got = read (pVNC->httpSock, pVNC->buf + pVNC->buf_filled, -+ sizeof (pVNC->buf) - pVNC->buf_filled - 1); -+ -+ if (got <= 0) { -+ if (got == 0) { -+ rfbLog("httpd: premature connection close\n"); -+ } else { -+ if (errno == EAGAIN) { -+ return; -+ } -+ rfbLogPerror("httpProcessInput: read"); -+ } -+ httpCloseSock(pScreen); -+ return; -+ } -+ -+ pVNC->buf_filled += got; -+ pVNC->buf[pVNC->buf_filled] = '\0'; -+ -+ /* Is it complete yet (is there a blank line)? */ -+ if (strstr (pVNC->buf, "\r\r") || strstr (pVNC->buf, "\n\n") || -+ strstr (pVNC->buf, "\r\n\r\n") || strstr (pVNC->buf, "\n\r\n\r")) -+ break; -+ } -+ -+ /* Process the request. */ -+ if (strncmp(pVNC->buf, "GET ", 4)) { -+ rfbLog("httpd: no GET line\n"); -+ httpCloseSock(pScreen); -+ return; -+ } else { -+ /* Only use the first line. */ -+ pVNC->buf[strcspn(pVNC->buf, "\n\r")] = '\0'; -+ } -+ -+ if (strlen(pVNC->buf) > maxFnameLen) { -+ rfbLog("httpd: GET line too long\n"); -+ httpCloseSock(pScreen); -+ return; -+ } -+ -+ if (sscanf(pVNC->buf, "GET %s HTTP/1.0", fname) != 1) { -+ rfbLog("httpd: couldn't parse GET line\n"); -+ httpCloseSock(pScreen); -+ return; -+ } -+ -+ if (fname[0] != '/') { -+ rfbLog("httpd: filename didn't begin with '/'\n"); -+ WriteExact(pVNC->httpSock, NOT_FOUND_STR, strlen(NOT_FOUND_STR)); -+ httpCloseSock(pScreen); -+ return; -+ } -+ -+ if (strchr(fname+1, '/') != NULL) { -+ rfbLog("httpd: asking for file in other directory\n"); -+ WriteExact(pVNC->httpSock, NOT_FOUND_STR, strlen(NOT_FOUND_STR)); -+ httpCloseSock(pScreen); -+ return; -+ } -+ -+ getpeername(pVNC->httpSock, (struct sockaddr *)&addr, &addrlen); -+ rfbLog("httpd: get '%s' for %s\n", fname+1, -+ inet_ntoa(addr.sin_addr)); -+ -+ /* Extract parameters from the URL string if necessary */ -+ -+ params[0] = '\0'; -+ ptr = strchr(fname, '?'); -+ if (ptr != NULL) { -+ *ptr = '\0'; -+ if (!parseParams(&ptr[1], params, 1024)) { -+ params[0] = '\0'; -+ rfbLog("httpd: bad parameters in the URL\n"); -+ } -+ } -+ -+ /* If we were asked for '/', actually read the file index.vnc */ -+ -+ if (strcmp(fname, "/") == 0) { -+ strcpy(fname, "/index.vnc"); -+ rfbLog("httpd: defaulting to '%s'\n", fname+1); -+ } -+ -+ /* Substitutions are performed on files ending .vnc */ -+ -+ if (strlen(fname) >= 4 && strcmp(&fname[strlen(fname)-4], ".vnc") == 0) { -+ performSubstitutions = TRUE; -+ } -+ -+ /* Open the file */ -+ -+ if ((fd = open(fullFname, O_RDONLY)) < 0) { -+ rfbLogPerror("httpProcessInput: open"); -+ WriteExact(pVNC->httpSock, NOT_FOUND_STR, strlen(NOT_FOUND_STR)); -+ httpCloseSock(pScreen); -+ return; -+ } -+ -+ WriteExact(pVNC->httpSock, OK_STR, strlen(OK_STR)); -+ -+ while (1) { -+ int n = read(fd, pVNC->buf, HTTP_BUF_SIZE-1); -+ if (n < 0) { -+ rfbLogPerror("httpProcessInput: read"); -+ close(fd); -+ httpCloseSock(pScreen); -+ return; -+ } -+ -+ if (n == 0) -+ break; -+ -+ if (performSubstitutions) { -+ -+ /* Substitute $WIDTH, $HEIGHT, etc with the appropriate values. -+ This won't quite work properly if the .vnc file is longer than -+ HTTP_BUF_SIZE, but it's reasonable to assume that .vnc files will -+ always be short. */ -+ -+ char *ptr = pVNC->buf; -+ char *dollar; -+ pVNC->buf[n] = 0; /* make sure it's null-terminated */ -+ -+ while ((dollar = strchr(ptr, '$'))) { -+ WriteExact(pVNC->httpSock, ptr, (dollar - ptr)); -+ -+ ptr = dollar; -+ -+ if (compareAndSkip(&ptr, "$WIDTH")) { -+ -+ sprintf(str, "%d", pVNC->width); -+ WriteExact(pVNC->httpSock, str, strlen(str)); -+ -+ } else if (compareAndSkip(&ptr, "$HEIGHT")) { -+ -+ sprintf(str, "%d", pVNC->height); -+ WriteExact(pVNC->httpSock, str, strlen(str)); -+ -+ } else if (compareAndSkip(&ptr, "$APPLETWIDTH")) { -+ -+ sprintf(str, "%d", pVNC->width); -+ WriteExact(pVNC->httpSock, str, strlen(str)); -+ -+ } else if (compareAndSkip(&ptr, "$APPLETHEIGHT")) { -+ -+ sprintf(str, "%d", pVNC->height + 32); -+ WriteExact(pVNC->httpSock, str, strlen(str)); -+ -+ } else if (compareAndSkip(&ptr, "$PORT")) { -+ -+ sprintf(str, "%d", pVNC->rfbPort); -+ WriteExact(pVNC->httpSock, str, strlen(str)); -+ -+ } else if (compareAndSkip(&ptr, "$DESKTOP")) { -+ -+ WriteExact(pVNC->httpSock, desktopName, strlen(desktopName)); -+ -+ } else if (compareAndSkip(&ptr, "$DISPLAY")) { -+ -+ sprintf(str, "%s:%s", rfbThisHost, display); -+ WriteExact(pVNC->httpSock, str, strlen(str)); -+ -+ } else if (compareAndSkip(&ptr, "$USER")) { -+ -+ if (user) { -+ WriteExact(pVNC->httpSock, user->pw_name, -+ strlen(user->pw_name)); -+ } else { -+ WriteExact(pVNC->httpSock, "?", 1); -+ } -+ -+ } else if (compareAndSkip(&ptr, "$PARAMS")) { -+ -+ if (params[0] != '\0') -+ WriteExact(pVNC->httpSock, params, strlen(params)); -+ -+ } else { -+ if (!compareAndSkip(&ptr, "$$")) -+ ptr++; -+ -+ if (WriteExact(pVNC->httpSock, "$", 1) < 0) { -+ close(fd); -+ httpCloseSock(pScreen); -+ return; -+ } -+ } -+ } -+ if (WriteExact(pVNC->httpSock, ptr, (&pVNC->buf[n] - ptr)) < 0) -+ break; -+ -+ } else { -+ -+ /* For files not ending .vnc, just write out the buffer */ -+ -+ if (WriteExact(pVNC->httpSock, pVNC->buf, n) < 0) -+ break; -+ } -+ } -+ -+ close(fd); -+ httpCloseSock(pScreen); -+} -+ -+ -+static Bool -+compareAndSkip(char **ptr, const char *str) -+{ -+ if (strncmp(*ptr, str, strlen(str)) == 0) { -+ *ptr += strlen(str); -+ return TRUE; -+ } -+ -+ return FALSE; -+} -+ -+/* -+ * Parse the request tail after the '?' character, and format a sequence -+ * of tags for inclusion into an HTML page with embedded applet. -+ */ -+ -+static Bool -+parseParams(const char *request, char *result, int max_bytes) -+{ -+ char param_request[128]; -+ char param_formatted[196]; -+ const char *tail; -+ char *delim_ptr; -+ char *value_str; -+ int cur_bytes, len; -+ -+ result[0] = '\0'; -+ cur_bytes = 0; -+ -+ tail = request; -+ for (;;) { -+ /* Copy individual "name=value" string into a buffer */ -+ delim_ptr = strchr((char *)tail, '&'); -+ if (delim_ptr == NULL) { -+ if (strlen(tail) >= sizeof(param_request)) { -+ return FALSE; -+ } -+ strcpy(param_request, tail); -+ } else { -+ len = delim_ptr - tail; -+ if (len >= sizeof(param_request)) { -+ return FALSE; -+ } -+ memcpy(param_request, tail, len); -+ param_request[len] = '\0'; -+ } -+ -+ /* Split the request into parameter name and value */ -+ value_str = strchr(¶m_request[1], '='); -+ if (value_str == NULL) { -+ return FALSE; -+ } -+ *value_str++ = '\0'; -+ if (strlen(value_str) == 0) { -+ return FALSE; -+ } -+ -+ /* Validate both parameter name and value */ -+ if (!validateString(param_request) || !validateString(value_str)) { -+ return FALSE; -+ } -+ -+ /* Prepare HTML-formatted representation of the name=value pair */ -+ len = sprintf(param_formatted, -+ "\n", -+ param_request, value_str); -+ if (cur_bytes + len + 1 > max_bytes) { -+ return FALSE; -+ } -+ strcat(result, param_formatted); -+ cur_bytes += len; -+ -+ /* Go to the next parameter */ -+ if (delim_ptr == NULL) { -+ break; -+ } -+ tail = delim_ptr + 1; -+ } -+ return TRUE; -+} -+ -+/* -+ * Check if the string consists only of alphanumeric characters, '+' -+ * signs, underscores, and dots. Replace all '+' signs with spaces. -+ */ -+ -+static Bool -+validateString(char *str) -+{ -+ char *ptr; -+ -+ for (ptr = str; *ptr != '\0'; ptr++) { -+ if (!isalnum(*ptr) && *ptr != '_' && *ptr != '.') { -+ if (*ptr == '+') { -+ *ptr = ' '; -+ } else { -+ return FALSE; -+ } -+ } -+ } -+ return TRUE; -+} -+ -diff --git a/hw/dmx/vnc/kbdptr.c b/hw/dmx/vnc/kbdptr.c -new file mode 100644 -index 0000000..2610dbe ---- /dev/null -+++ b/hw/dmx/vnc/kbdptr.c -@@ -0,0 +1,446 @@ -+/* -+ * kbdptr.c - deal with keyboard and pointer device over TCP & UDP. -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ * -+ */ -+ -+/* -+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. -+ * -+ * This is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This software is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this software; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -+ * USA. -+ */ -+ -+#include "rfb.h" -+#include "X11/X.h" -+#define NEED_EVENTS -+#include "X11/Xproto.h" -+#include "inputstr.h" -+#define XK_CYRILLIC -+#include -+#include -+#include "mi.h" -+#include "mipointer.h" -+ -+#if DMXVNC -+#include "../dmx.h" -+#include "../dmxinput.h" -+#endif -+ -+#if XFREE86VNC -+#if defined(XINPUT) -+# include "xf86Xinput.h" -+# define Enqueue(ev) xf86eqEnqueue(ev) -+#else -+# define Enqueue(ev) mieqEnqueue(ev) -+#endif -+#else /*XFREE86VNC*/ -+#if DMXVNC -+# define Enqueue(ev) dmxeqEnqueue(ev) -+#else -+# define Enqueue(ev) mieqEnqueue(ev) -+#endif -+#endif /*XFREE86VNC*/ -+ -+ -+#define KEY_IS_PRESSED(keycode) \ -+ (kbdDevice->key->down[(keycode) >> 3] & (1 << ((keycode) & 7))) -+ -+static void vncXConvertCase(KeySym sym, KeySym *lower, KeySym *upper); -+ -+DeviceIntPtr kbdDevice = NULL; -+ -+#include "keyboard.h" -+ -+void -+vncSetKeyboardDevice(DeviceIntPtr kbd) -+{ -+ kbdDevice = kbd; -+} -+ -+/* -+ * Called when the rfbserver receives a rfbKeyEvent event from a client. -+ * Put an X keyboard event into the event queue. -+ */ -+void -+KbdAddEvent(Bool down, KeySym keySym, rfbClientPtr cl) -+{ -+ xEvent ev, fake; -+ KeySymsPtr keySyms; -+ int i; -+ int keyCode = 0; -+ int freeIndex = -1; -+ unsigned long time; -+ Bool fakeShiftPress = FALSE; -+ Bool fakeShiftLRelease = FALSE; -+ Bool fakeShiftRRelease = FALSE; -+ Bool shiftMustBeReleased = FALSE; -+ Bool shiftMustBePressed = FALSE; -+ -+ if (!kbdDevice) return; -+ -+ keySyms = &kbdDevice->key->curKeySyms; -+ -+#ifdef CORBA -+ if (cl) { -+ CARD32 clientId = cl->sock; -+ ChangeWindowProperty(WindowTable[0], VNC_LAST_CLIENT_ID, XA_INTEGER, -+ 32, PropModeReplace, 1, (pointer)&clientId, TRUE); -+ } -+#endif -+ -+ if (down) { -+ ev.u.u.type = KeyPress; -+ } else { -+ ev.u.u.type = KeyRelease; -+ } -+ -+ /* NOTE: This is where it gets hairy for XFree86 servers. -+ * I think the best way to deal with this is invent a new protocol -+ * to send over the wire the remote keyboard type and correctly -+ * handle that as XINPUT extension device (we're part of the way -+ * there for that. -+ * -+ * Alan. -+ */ -+#if !XFREE86VNC -+ /* First check if it's one of our predefined keys. If so then we can make -+ some attempt at allowing an xmodmap inside a VNC desktop behave -+ something like you'd expect - e.g. if keys A & B are swapped over and -+ the VNC client sends an A, then map it to a B when generating the X -+ event. We don't attempt to do this for keycodes which we make up on the -+ fly because it's too hard... */ -+ -+ for (i = 0; i < N_PREDEFINED_KEYS * GLYPHS_PER_KEY; i++) { -+ if (keySym == map[i]) { -+ keyCode = MIN_KEY_CODE + i / GLYPHS_PER_KEY; -+ -+ if (map[(i/GLYPHS_PER_KEY) * GLYPHS_PER_KEY + 1] != NoSymbol) { -+ -+ /* this keycode has more than one symbol associated with it, -+ so shift state is important */ -+ -+ if ((i % GLYPHS_PER_KEY) == 0) -+ shiftMustBeReleased = TRUE; -+ else -+ shiftMustBePressed = TRUE; -+ } -+ break; -+ } -+ } -+#endif -+ -+ if (!keyCode) { -+ -+ /* not one of our predefined keys - see if it's in the current keyboard -+ mapping (i.e. we've already allocated an extra keycode for it) */ -+ -+ if (keySyms->mapWidth < 2) { -+ ErrorF("KbdAddEvent: Sanity check failed - Keyboard mapping has " -+ "less than 2 keysyms per keycode (KeySym 0x%x)\n", -+ (unsigned) keySym); -+ return; -+ } -+ -+ for (i = 0; i < NO_OF_KEYS * keySyms->mapWidth; i++) { -+ if (keySym == keySyms->map[i]) { -+ keyCode = MIN_KEY_CODE + i / keySyms->mapWidth; -+ -+ if (keySyms->map[(i / keySyms->mapWidth) -+ * keySyms->mapWidth + 1] != NoSymbol) { -+ -+ /* this keycode has more than one symbol associated with -+ it, so shift state is important */ -+ -+ if ((i % keySyms->mapWidth) == 0) -+ shiftMustBeReleased = TRUE; -+ else -+ shiftMustBePressed = TRUE; -+ } -+ break; -+ } -+ if ((freeIndex == -1) && (keySyms->map[i] == NoSymbol) -+ && (i % keySyms->mapWidth) == 0) -+ { -+ freeIndex = i; -+ } -+ } -+ } -+ -+ if (!keyCode) { -+ KeySym lower, upper; -+ -+ /* we don't have an existing keycode - make one up on the fly and add -+ it to the keyboard mapping. Thanks to Vlad Harchev for pointing -+ out problems with non-ascii capitalisation. */ -+ -+ if (freeIndex == -1) { -+ ErrorF("KbdAddEvent: ignoring KeySym 0x%x - no free KeyCodes\n", -+ (unsigned) keySym); -+ return; -+ } -+ -+ keyCode = MIN_KEY_CODE + freeIndex / keySyms->mapWidth; -+ -+ vncXConvertCase(keySym, &lower, &upper); -+ -+ if (lower == upper) { -+ keySyms->map[freeIndex] = keySym; -+ -+ } else { -+ keySyms->map[freeIndex] = lower; -+ keySyms->map[freeIndex+1] = upper; -+ -+ if (keySym == lower) -+ shiftMustBeReleased = TRUE; -+ else -+ shiftMustBePressed = TRUE; -+ } -+ -+ SendMappingNotify(MappingKeyboard, keyCode, 1, serverClient); -+ -+ ErrorF("KbdAddEvent: unknown KeySym 0x%x - allocating KeyCode %d\n", -+ (unsigned) keySym, keyCode); -+ } -+ -+ time = GetTimeInMillis(); -+ -+ if (down) { -+ if (shiftMustBePressed && !(kbdDevice->key->state & ShiftMask)) { -+ fakeShiftPress = TRUE; -+ fake.u.u.type = KeyPress; -+ fake.u.u.detail = SHIFT_L_KEY_CODE; -+ fake.u.keyButtonPointer.time = time; -+ Enqueue(&fake); -+ } -+ if (shiftMustBeReleased && (kbdDevice->key->state & ShiftMask)) { -+ if (KEY_IS_PRESSED(SHIFT_L_KEY_CODE)) { -+ fakeShiftLRelease = TRUE; -+ fake.u.u.type = KeyRelease; -+ fake.u.u.detail = SHIFT_L_KEY_CODE; -+ fake.u.keyButtonPointer.time = time; -+ Enqueue(&fake); -+ } -+ if (KEY_IS_PRESSED(SHIFT_R_KEY_CODE)) { -+ fakeShiftRRelease = TRUE; -+ fake.u.u.type = KeyRelease; -+ fake.u.u.detail = SHIFT_R_KEY_CODE; -+ fake.u.keyButtonPointer.time = time; -+ Enqueue(&fake); -+ } -+ } -+ } -+ -+ ev.u.u.detail = keyCode; -+ ev.u.keyButtonPointer.time = time; -+ Enqueue(&ev); -+ -+ if (fakeShiftPress) { -+ fake.u.u.type = KeyRelease; -+ fake.u.u.detail = SHIFT_L_KEY_CODE; -+ fake.u.keyButtonPointer.time = time; -+ Enqueue(&fake); -+ } -+ if (fakeShiftLRelease) { -+ fake.u.u.type = KeyPress; -+ fake.u.u.detail = SHIFT_L_KEY_CODE; -+ fake.u.keyButtonPointer.time = time; -+ Enqueue(&fake); -+ } -+ if (fakeShiftRRelease) { -+ fake.u.u.type = KeyPress; -+ fake.u.u.detail = SHIFT_R_KEY_CODE; -+ fake.u.keyButtonPointer.time = time; -+ Enqueue(&fake); -+ } -+} -+ -+/* -+ * Called when the rfbserver receives a rfbPointerEvent event from a client. -+ * Put an X mouse event into the event queue. -+ */ -+void -+PtrAddEvent(buttonMask, x, y, cl) -+ int buttonMask; -+ int x; -+ int y; -+ rfbClientPtr cl; -+{ -+ xEvent ev; -+ int i; -+ unsigned long time; -+ static int oldButtonMask = 0; -+ -+#ifdef CORBA -+ if (cl) { -+ CARD32 clientId = cl->sock; -+ ChangeWindowProperty(WindowTable[0], VNC_LAST_CLIENT_ID, XA_INTEGER, -+ 32, PropModeReplace, 1, (pointer)&clientId, TRUE); -+ } -+#endif -+ -+ time = GetTimeInMillis(); -+ -+#if DMXVNC -+ dmxCoreMotion(x, y, 0, DMX_NO_BLOCK); -+#else -+ miPointerAbsoluteCursor(x, y, time); -+#endif -+ -+ for (i = 0; i < 5; i++) { -+ if ((buttonMask ^ oldButtonMask) & (1<key->down[i] != 0) { -+ for (j = 0; j < 8; j++) { -+ if (kbdDevice->key->down[i] & (1 << j)) { -+ ev.u.u.type = KeyRelease; -+ ev.u.u.detail = (i << 3) | j; -+ ev.u.keyButtonPointer.time = time; -+ Enqueue(&ev); -+ } -+ } -+ } -+ } -+} -+ -+ -+/* copied from Xlib source */ -+ -+static void vncXConvertCase(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; -+ } -+} -diff --git a/hw/dmx/vnc/keyboard.h b/hw/dmx/vnc/keyboard.h -new file mode 100644 -index 0000000..ab5b1b3 ---- /dev/null -+++ b/hw/dmx/vnc/keyboard.h -@@ -0,0 +1,167 @@ -+/* -+ * Copyright (C) 2002 Alan Hourihane. 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. -+ * -+ * Author: Alan Hourihane -+ */ -+ -+#define MIN_KEY_CODE 8 -+#define MAX_KEY_CODE 255 -+#define NO_OF_KEYS (MAX_KEY_CODE - MIN_KEY_CODE + 1) -+#define GLYPHS_PER_KEY 4 -+ -+#define CONTROL_L_KEY_CODE (MIN_KEY_CODE + 29) -+#define CONTROL_R_KEY_CODE (MIN_KEY_CODE + 101) -+#define SHIFT_L_KEY_CODE (MIN_KEY_CODE + 42) -+#define SHIFT_R_KEY_CODE (MIN_KEY_CODE + 54) -+#define META_L_KEY_CODE (MIN_KEY_CODE + 107) -+#define META_R_KEY_CODE (MIN_KEY_CODE + 108) -+#define ALT_L_KEY_CODE (MIN_KEY_CODE + 56) -+#define ALT_R_KEY_CODE (MIN_KEY_CODE + 105) -+ -+static KeySym map[MAX_KEY_CODE * GLYPHS_PER_KEY] = { -+ /* 0x00 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x01 */ XK_Escape, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x02 */ XK_1, XK_exclam, NoSymbol, NoSymbol, -+ /* 0x03 */ XK_2, XK_at, NoSymbol, NoSymbol, -+ /* 0x04 */ XK_3, XK_numbersign, NoSymbol, NoSymbol, -+ /* 0x05 */ XK_4, XK_dollar, NoSymbol, NoSymbol, -+ /* 0x06 */ XK_5, XK_percent, NoSymbol, NoSymbol, -+ /* 0x07 */ XK_6, XK_asciicircum, NoSymbol, NoSymbol, -+ /* 0x08 */ XK_7, XK_ampersand, NoSymbol, NoSymbol, -+ /* 0x09 */ XK_8, XK_asterisk, NoSymbol, NoSymbol, -+ /* 0x0a */ XK_9, XK_parenleft, NoSymbol, NoSymbol, -+ /* 0x0b */ XK_0, XK_parenright, NoSymbol, NoSymbol, -+ /* 0x0c */ XK_minus, XK_underscore, NoSymbol, NoSymbol, -+ /* 0x0d */ XK_equal, XK_plus, NoSymbol, NoSymbol, -+ /* 0x0e */ XK_BackSpace, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x0f */ XK_Tab, XK_ISO_Left_Tab,NoSymbol, NoSymbol, -+ /* 0x10 */ XK_q, XK_Q, NoSymbol, NoSymbol, -+ /* 0x11 */ XK_w, XK_W, NoSymbol, NoSymbol, -+ /* 0x12 */ XK_e, XK_E, NoSymbol, NoSymbol, -+ /* 0x13 */ XK_r, XK_R, NoSymbol, NoSymbol, -+ /* 0x14 */ XK_t, XK_T, NoSymbol, NoSymbol, -+ /* 0x15 */ XK_y, XK_Y, NoSymbol, NoSymbol, -+ /* 0x16 */ XK_u, XK_U, NoSymbol, NoSymbol, -+ /* 0x17 */ XK_i, XK_I, NoSymbol, NoSymbol, -+ /* 0x18 */ XK_o, XK_O, NoSymbol, NoSymbol, -+ /* 0x19 */ XK_p, XK_P, NoSymbol, NoSymbol, -+ /* 0x1a */ XK_bracketleft, XK_braceleft, NoSymbol, NoSymbol, -+ /* 0x1b */ XK_bracketright,XK_braceright, NoSymbol, NoSymbol, -+ /* 0x1c */ XK_Return, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x1d */ XK_Control_L, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x1e */ XK_a, XK_A, NoSymbol, NoSymbol, -+ /* 0x1f */ XK_s, XK_S, NoSymbol, NoSymbol, -+ /* 0x20 */ XK_d, XK_D, NoSymbol, NoSymbol, -+ /* 0x21 */ XK_f, XK_F, NoSymbol, NoSymbol, -+ /* 0x22 */ XK_g, XK_G, NoSymbol, NoSymbol, -+ /* 0x23 */ XK_h, XK_H, NoSymbol, NoSymbol, -+ /* 0x24 */ XK_j, XK_J, NoSymbol, NoSymbol, -+ /* 0x25 */ XK_k, XK_K, NoSymbol, NoSymbol, -+ /* 0x26 */ XK_l, XK_L, NoSymbol, NoSymbol, -+ /* 0x27 */ XK_semicolon, XK_colon, NoSymbol, NoSymbol, -+ /* 0x28 */ XK_quoteright, XK_quotedbl, NoSymbol, NoSymbol, -+ /* 0x29 */ XK_quoteleft, XK_asciitilde, NoSymbol, NoSymbol, -+ /* 0x2a */ XK_Shift_L, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x2b */ XK_backslash, XK_bar, NoSymbol, NoSymbol, -+ /* 0x2c */ XK_z, XK_Z, NoSymbol, NoSymbol, -+ /* 0x2d */ XK_x, XK_X, NoSymbol, NoSymbol, -+ /* 0x2e */ XK_c, XK_C, NoSymbol, NoSymbol, -+ /* 0x2f */ XK_v, XK_V, NoSymbol, NoSymbol, -+ /* 0x30 */ XK_b, XK_B, NoSymbol, NoSymbol, -+ /* 0x31 */ XK_n, XK_N, NoSymbol, NoSymbol, -+ /* 0x32 */ XK_m, XK_M, NoSymbol, NoSymbol, -+ /* 0x33 */ XK_comma, XK_less, NoSymbol, NoSymbol, -+ /* 0x34 */ XK_period, XK_greater, NoSymbol, NoSymbol, -+ /* 0x35 */ XK_slash, XK_question, NoSymbol, NoSymbol, -+ /* 0x36 */ XK_Shift_R, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x37 */ XK_KP_Multiply, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x38 */ XK_Alt_L, XK_Meta_L, NoSymbol, NoSymbol, -+ /* 0x39 */ XK_space, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x3a */ XK_Caps_Lock, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x3b */ XK_F1, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x3c */ XK_F2, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x3d */ XK_F3, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x3e */ XK_F4, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x3f */ XK_F5, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x40 */ XK_F6, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x41 */ XK_F7, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x42 */ XK_F8, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x43 */ XK_F9, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x44 */ XK_F10, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x45 */ XK_Num_Lock, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x46 */ XK_Scroll_Lock, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x47 */ XK_KP_Home, XK_KP_7, NoSymbol, NoSymbol, -+ /* 0x48 */ XK_KP_Up, XK_KP_8, NoSymbol, NoSymbol, -+ /* 0x49 */ XK_KP_Prior, XK_KP_9, NoSymbol, NoSymbol, -+ /* 0x4a */ XK_KP_Subtract, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x4b */ XK_KP_Left, XK_KP_4, NoSymbol, NoSymbol, -+ /* 0x4c */ XK_KP_Begin, XK_KP_5, NoSymbol, NoSymbol, -+ /* 0x4d */ XK_KP_Right, XK_KP_6, NoSymbol, NoSymbol, -+ /* 0x4e */ XK_KP_Add, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x4f */ XK_KP_End, XK_KP_1, NoSymbol, NoSymbol, -+ /* 0x50 */ XK_KP_Down, XK_KP_2, NoSymbol, NoSymbol, -+ /* 0x51 */ XK_KP_Next, XK_KP_3, NoSymbol, NoSymbol, -+ /* 0x52 */ XK_KP_Insert, XK_KP_0, NoSymbol, NoSymbol, -+ /* 0x53 */ XK_KP_Delete, XK_KP_Decimal, NoSymbol, NoSymbol, -+ /* 0x54 */ XK_Sys_Req, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x55 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x56 */ XK_less, XK_greater, NoSymbol, NoSymbol, -+ /* 0x57 */ XK_F11, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x58 */ XK_F12, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x59 */ XK_Home, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x5a */ XK_Up, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x5b */ XK_Prior, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x5c */ XK_Left, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x5d */ XK_Begin, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x5e */ XK_Right, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x5f */ XK_End, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x60 */ XK_Down, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x61 */ XK_Next, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x62 */ XK_Insert, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x63 */ XK_Delete, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x64 */ XK_KP_Enter, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x65 */ XK_Control_R, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x66 */ XK_Pause, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x67 */ XK_Print, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x68 */ XK_KP_Divide, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x69 */ XK_Alt_R, XK_Meta_R, NoSymbol, NoSymbol, -+ /* 0x6a */ XK_Break, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x6b */ XK_Meta_L, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x6c */ XK_Meta_R, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x6d */ XK_Menu, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x6e */ XK_F13, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x6f */ XK_F14, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x70 */ XK_F15, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x71 */ XK_F16, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x72 */ XK_F17, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x73 */ XK_backslash, XK_underscore, NoSymbol, NoSymbol, -+ /* 0x74 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x75 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x76 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x77 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x78 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x79 */ XK_Henkan, XK_Mode_switch, NoSymbol, NoSymbol, -+ /* 0x7a */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x7b */ XK_Muhenkan, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x7c */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x7d */ XK_backslash, XK_bar, NoSymbol, NoSymbol, -+ /* 0x7e */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x7f */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, -+}; -+ -+#define N_PREDEFINED_KEYS (sizeof(map) / (sizeof(KeySym) * GLYPHS_PER_KEY)) -diff --git a/hw/dmx/vnc/loginauth.c b/hw/dmx/vnc/loginauth.c -new file mode 100644 -index 0000000..0106737 ---- /dev/null -+++ b/hw/dmx/vnc/loginauth.c -@@ -0,0 +1,142 @@ -+/* -+ * loginauth.c - deal with login-style Unix authentication. -+ * -+ * This file implements the UnixLogin authentication protocol when setting up -+ * an RFB connection. -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ */ -+ -+/* -+ * Copyright (C) 2003 Constantin Kaplinsky. 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. -+ */ -+ -+#ifdef HAVE_DMX_CONFIG_H -+#include -+#endif -+ -+#ifdef linux -+#include /* XXX xserver has a shadow.h file too */ -+#endif -+#include -+#include -+#include -+#include -+#include -+#include "rfb.h" -+ -+void rfbLoginAuthProcessClientMessage(rfbClientPtr cl) -+{ -+ int n1 = 0, n2 = 0; -+ CARD32 loginLen, passwdLen, authResult; -+ char *loginBuf, *passwdBuf; -+ struct passwd *ps; -+ char *encPasswd1, *encPasswd2; -+ Bool ok; -+ -+ if ((n1 = ReadExact(cl->sock, (char *)&loginLen, -+ sizeof(loginLen))) <= 0 || -+ (n2 = ReadExact(cl->sock, (char *)&passwdLen, -+ sizeof(passwdLen))) <= 0) { -+ if (n1 != 0 || n2 != 0) -+ rfbLogPerror("rfbLoginAuthProcessClientMessage: read"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ loginLen = Swap32IfLE(loginLen); -+ passwdLen = Swap32IfLE(passwdLen); -+ loginBuf = (char *)xalloc(loginLen + 1); -+ passwdBuf = (char *)xalloc(passwdLen + 1); -+ -+ n1 = n2 = 0; -+ if ((n1 = ReadExact(cl->sock, loginBuf, loginLen)) <= 0 || -+ (n2 = ReadExact(cl->sock, passwdBuf, passwdLen)) <= 0) { -+ if (n1 != 0 || n2 != 0) -+ rfbLogPerror("rfbLoginAuthProcessClientMessage: read"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ loginBuf[loginLen] = '\0'; -+ passwdBuf[passwdLen] = '\0'; -+ -+ encPasswd1 = encPasswd2 = NULL; -+ -+ ps = getpwnam(loginBuf); -+ if (ps == NULL) { -+ rfbLog("rfbLoginAuthProcessClientMessage: " -+ "Cannot get password file entry for \"%s\"\n", loginBuf); -+ } else { -+ encPasswd1 = ps->pw_passwd; -+#ifdef linux -+ if (strlen(ps->pw_passwd) == 1) { -+ struct spwd *sps; -+ -+ sps = getspnam(loginBuf); -+ if (sps == NULL) { -+ rfbLog("rfbLoginAuthProcessClientMessage:" -+ " getspnam() failed for user \"%s\"\n", loginBuf); -+ } else { -+ encPasswd1 = sps->sp_pwdp; -+ } -+ } -+#endif -+ encPasswd2 = crypt(passwdBuf, encPasswd1); -+ memset(passwdBuf, 0, strlen(passwdBuf)); -+ } -+ -+ ok = FALSE; -+ if (encPasswd1 != NULL && encPasswd2 != NULL) { -+ if (strcmp(encPasswd1, encPasswd2) == 0) -+ ok = TRUE; -+ } -+ -+ if (!ok) { -+ rfbLog("rfbAuthProcessClientMessage: authentication failed from %s\n", -+ cl->host); -+ -+ if (rfbAuthConsiderBlocking(cl)) { -+ authResult = Swap32IfLE(rfbVncAuthTooMany); -+ } else { -+ authResult = Swap32IfLE(rfbVncAuthFailed); -+ } -+ -+ if (WriteExact(cl->sock, (char *)&authResult, -+ sizeof(authResult)) < 0) { -+ rfbLogPerror("rfbLoginAuthProcessClientMessage: write"); -+ } -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ rfbAuthUnblock(cl); -+ -+ cl->login = strdup(loginBuf); -+ rfbLog("Login-style authentication passed for user %s at %s\n", -+ cl->login, cl->host); -+ -+ authResult = Swap32IfLE(rfbVncAuthOK); -+ -+ if (WriteExact(cl->sock, (char *)&authResult, sizeof(authResult)) < 0) { -+ rfbLogPerror("rfbLoginAuthProcessClientMessage: write"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ cl->state = RFB_INITIALISATION; -+} -+ -diff --git a/hw/dmx/vnc/rdp.c b/hw/dmx/vnc/rdp.c -new file mode 100644 -index 0000000..c7d4f98 ---- /dev/null -+++ b/hw/dmx/vnc/rdp.c -@@ -0,0 +1,145 @@ -+/* -+ * Copyright (C) 2004 Alan Hourihane. 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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "rfb.h" -+ -+typedef struct rdpClientRec { -+ ScreenPtr pScreen; -+} rdpClientRec, *rdpClientPtr; -+ -+typedef struct rdpInRec { -+ char version; -+ char pad; -+ short length; -+ char hdrlen; -+ unsigned char pdu; -+} rdpInRec, *rdpInPtr; -+ -+static void -+rdpCloseSock(ScreenPtr pScreen) -+{ -+ VNCSCREENPTR(pScreen); -+ close(pVNC->rdpListenSock); -+ RemoveEnabledDevice(pVNC->rdpListenSock); -+ pVNC->rdpListenSock = -1; -+} -+ -+/* -+ * rdpNewClient is called when a new connection has been made by whatever -+ * means. -+ */ -+ -+static rdpClientPtr -+rdpNewClient(ScreenPtr pScreen, int sock) -+{ -+ rdpInRec in; -+ rdpClientPtr cl; -+ BoxRec box; -+ struct sockaddr_in addr; -+ SOCKLEN_T addrlen = sizeof(struct sockaddr_in); -+ VNCSCREENPTR(pScreen); -+ int i; -+ -+ cl = (rdpClientPtr)xalloc(sizeof(rdpClientRec)); -+ -+ cl->pScreen = pScreen; -+ -+ in.version = 3; -+ in.pad = 0; -+ in.length = 0x600; /* big endian */ -+ in.hdrlen = 0x00; -+ in.pdu = 0xCC; -+ -+ if (WriteExact(sock, (char *)&in, sizeof(rdpInRec)) < 0) { -+ rfbLogPerror("rfbNewClient: write"); -+ rdpCloseSock(pScreen); -+ return NULL; -+ } -+ -+ return cl; -+} -+/* -+ * rdpCheckFds is called from ProcessInputEvents to check for input on the -+ * HTTP socket(s). If there is input to process, rdpProcessInput is called. -+ */ -+ -+static void -+rdpCheckFds(ScreenPtr pScreen) -+{ -+ VNCSCREENPTR(pScreen); -+ int nfds; -+ fd_set fds; -+ struct timeval tv; -+ struct sockaddr_in addr; -+ int sock; -+ const int one =1; -+ SOCKLEN_T addrlen = sizeof(addr); -+ -+ FD_ZERO(&fds); -+ FD_SET(pVNC->rdpListenSock, &fds); -+ tv.tv_sec = 0; -+ tv.tv_usec = 0; -+ nfds = select(pVNC->rdpListenSock + 1, &fds, NULL, NULL, &tv); -+ if (nfds == 0) { -+ return; -+ } -+ if (nfds < 0) { -+ if (errno != EINTR) -+ rfbLogPerror("httpCheckFds: select"); -+ return; -+ } -+ -+ if (pVNC->rdpListenSock != -1 && FD_ISSET(pVNC->rdpListenSock, &fds)) { -+ -+ if ((sock = accept(pVNC->rdpListenSock, -+ (struct sockaddr *)&addr, &addrlen)) < 0) { -+ rfbLogPerror("rdpCheckFds: accept"); -+ return; -+ } -+ -+ if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) { -+ rfbLogPerror("rdpCheckFds: fcntl"); -+ close(sock); -+ return; -+ } -+ -+ if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, -+ (char *)&one, sizeof(one)) < 0) { -+ rfbLogPerror("rdpCheckFds: setsockopt"); -+ close(sock); -+ return; -+ } -+ -+ rfbLog("\n"); -+ -+ rfbLog("Got RDP connection from client %s\n", inet_ntoa(addr.sin_addr)); -+ -+ AddEnabledDevice(sock); -+ -+ rdpNewClient(pScreen, sock); -+ } -+} -diff --git a/hw/dmx/vnc/rfb.h b/hw/dmx/vnc/rfb.h -new file mode 100644 -index 0000000..6e86abb ---- /dev/null -+++ b/hw/dmx/vnc/rfb.h -@@ -0,0 +1,697 @@ -+/* -+ * rfb.h - header file for RFB DDX implementation. -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ */ -+ -+/* -+ * Copyright (C) 2000-2004 Const Kaplinsky. All Rights Reserved. -+ * Copyright (C) 2000 Tridia Corporation. All Rights Reserved. -+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. -+ * -+ * This is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This software is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this software; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -+ * USA. -+ */ -+ -+#if HAVE_DMX_CONFIG_H -+#include "dmx-config.h" -+#endif -+ -+#include -+#include "scrnintstr.h" -+#include "colormapst.h" -+#include "dixstruct.h" -+#include "gcstruct.h" -+#include "regionstr.h" -+#include "windowstr.h" -+#include "dixfontstr.h" -+#include "picture.h" -+#include "glyphstr.h" -+#if 0 /* && !XFREE86VNC */ -+#include "osdep.h" -+#endif -+#include -+#include -+/* -+ * HTTP_BUF_SIZE for http transfers -+ */ -+#define HTTP_BUF_SIZE 32768 -+/* -+ * UPDATE_BUF_SIZE must be big enough to send at least one whole line of the -+ * framebuffer. So for a max screen width of say 2K with 32-bit pixels this -+ * means 8K minimum. -+ */ -+#define UPDATE_BUF_SIZE 30000 -+#ifdef RENDER -+#include "picturestr.h" -+#endif -+#define _VNC_SERVER -+#include "vncint.h" -+ -+#if defined(sun) || defined(hpux) -+#define SOCKLEN_T int -+#else -+#define SOCKLEN_T socklen_t -+#endif -+ -+/* It's a good idea to keep these values a bit greater than required. */ -+#define MAX_ENCODINGS 10 -+#define MAX_SECURITY_TYPES 4 -+#define MAX_TUNNELING_CAPS 16 -+#define MAX_AUTH_CAPS 16 -+ -+#define VNCSCREENPTR(ptr) \ -+ vncScreenPtr pVNC = VNCPTR(ptr) -+ -+/* -+ * Per-screen (framebuffer) structure. There is only one of these, since we -+ * don't allow the X server to have multiple screens. -+ */ -+ -+typedef struct -+{ -+ int rfbPort; -+ int rdpPort; -+ int udpPort; -+ int rfbListenSock; -+ int rdpListenSock; -+ int udpSock; -+ int httpPort; -+ int httpListenSock; -+ int httpSock; -+ char * httpDir; -+ char buf[HTTP_BUF_SIZE]; -+ Bool udpSockConnected; -+ char * rfbAuthPasswdFile; -+ size_t buf_filled; -+ int maxFd; -+ fd_set allFds; -+ Bool useGetImage; -+ Bool noCursor; -+ Bool rfbAlwaysShared; -+ Bool rfbNeverShared; -+ Bool rfbDontDisconnect; -+ Bool rfbUserAccept; -+ Bool rfbViewOnly; -+ ColormapPtr savedColormap; -+ ColormapPtr rfbInstalledColormap; -+ rfbPixelFormat rfbServerFormat; -+ Bool rfbAuthTooManyTries; -+ int rfbAuthTries; -+ Bool loginAuthEnabled; -+ struct in_addr interface; -+ OsTimerPtr timer; -+ char updateBuf[UPDATE_BUF_SIZE]; -+ int ublen; -+ int width; -+ int paddedWidthInBytes; -+ int height; -+ int depth; -+ int bitsPerPixel; -+ int sizeInBytes; -+ unsigned char *pfbMemory; -+ Pixel blackPixel; -+ Pixel whitePixel; -+ -+ /* The following two members are used to minimise the amount of unnecessary -+ drawing caused by cursor movement. Whenever any drawing affects the -+ part of the screen where the cursor is, the cursor is removed first and -+ then the drawing is done (this is what the sprite routines test for). -+ Afterwards, however, we do not replace the cursor, even when the cursor -+ is logically being moved across the screen. We only draw the cursor -+ again just as we are about to send the client a framebuffer update. -+ -+ We need to be careful when removing and drawing the cursor because of -+ their relationship with the normal drawing routines. The drawing -+ routines can invoke the cursor routines, but also the cursor routines -+ themselves end up invoking drawing routines. -+ -+ Removing the cursor (rfbSpriteRemoveCursor) is eventually achieved by -+ doing a CopyArea from a pixmap to the screen, where the pixmap contains -+ the saved contents of the screen under the cursor. Before doing this, -+ however, we set cursorIsDrawn to FALSE. Then, when CopyArea is called, -+ it sees that cursorIsDrawn is FALSE and so doesn't feel the need to -+ (recursively!) remove the cursor before doing it. -+ -+ Putting up the cursor (rfbSpriteRestoreCursor) involves a call to -+ PushPixels. While this is happening, cursorIsDrawn must be FALSE so -+ that PushPixels doesn't think it has to remove the cursor first. -+ Obviously cursorIsDrawn is set to TRUE afterwards. -+ -+ Another problem we face is that drawing routines sometimes cause a -+ framebuffer update to be sent to the RFB client. When the RFB client is -+ already waiting for a framebuffer update and some drawing to the -+ framebuffer then happens, the drawing routine sees that the client is -+ ready, so it calls rfbSendFramebufferUpdate. If the cursor is not drawn -+ at this stage, it must be put up, and so rfbSpriteRestoreCursor is -+ called. However, if the original drawing routine was actually called -+ from within rfbSpriteRestoreCursor or rfbSpriteRemoveCursor we don't -+ want this to happen. So both the cursor routines set -+ dontSendFramebufferUpdate to TRUE, and all the drawing routines check -+ this before calling rfbSendFramebufferUpdate. */ -+ -+ Bool cursorIsDrawn; /* TRUE if the cursor is currently drawn */ -+ Bool dontSendFramebufferUpdate; /* TRUE while removing or drawing the -+ cursor */ -+ -+ /* wrapped screen functions */ -+ -+ CloseScreenProcPtr CloseScreen; -+ CreateGCProcPtr CreateGC; -+ PaintWindowBackgroundProcPtr PaintWindowBackground; -+ PaintWindowBorderProcPtr PaintWindowBorder; -+ CopyWindowProcPtr CopyWindow; -+ ClearToBackgroundProcPtr ClearToBackground; -+ RestoreAreasProcPtr RestoreAreas; -+ ScreenWakeupHandlerProcPtr WakeupHandler; -+#ifdef CHROMIUM -+ RealizeWindowProcPtr RealizeWindow; -+ UnrealizeWindowProcPtr UnrealizeWindow; -+ DestroyWindowProcPtr DestroyWindow; -+ ResizeWindowProcPtr ResizeWindow; -+ PositionWindowProcPtr PositionWindow; -+ ClipNotifyProcPtr ClipNotify; -+#endif -+#ifdef RENDER -+ CompositeProcPtr Composite; -+#endif -+ -+} rfbScreenInfo, *rfbScreenInfoPtr; -+ -+ -+/* -+ * rfbTranslateFnType is the type of translation functions. -+ */ -+ -+struct rfbClientRec; -+typedef void (*rfbTranslateFnType)(ScreenPtr pScreen, -+ char *table, rfbPixelFormat *in, -+ rfbPixelFormat *out, -+ unsigned char *iptr, char *optr, -+ int bytesBetweenInputLines, -+ int width, int height, -+ int x, int y); -+ -+ -+/* -+ * Per-client structure. -+ */ -+ -+typedef struct rfbClientRec { -+ int sock; -+ char *host; -+ char *login; -+ -+ int protocol_minor_ver; /* RFB protocol minor version in use. */ -+ Bool protocol_tightvnc; /* TightVNC protocol extensions enabled */ -+ -+ /* Possible client states: */ -+ -+ enum { -+ RFB_PROTOCOL_VERSION, /* establishing protocol version */ -+ RFB_SECURITY_TYPE, /* negotiating security (RFB v.3.7) */ -+ RFB_TUNNELING_TYPE, /* establishing tunneling (RFB v.3.7t) */ -+ RFB_AUTH_TYPE, /* negotiating authentication (RFB v.3.7t) */ -+ RFB_AUTHENTICATION, /* authenticating (VNC authentication) */ -+ RFB_INITIALISATION, /* sending initialisation messages */ -+ RFB_NORMAL /* normal protocol messages */ -+ } state; -+ -+ Bool viewOnly; /* Do not accept input from this client. */ -+ -+ Bool reverseConnection; -+ -+ Bool readyForSetColourMapEntries; -+ -+ Bool useCopyRect; -+ int preferredEncoding; -+ int correMaxWidth, correMaxHeight; -+ -+ /* The list of security types sent to this client (protocol 3.7). -+ Note that the first entry is the number of list items following. */ -+ -+ CARD8 securityTypes[MAX_SECURITY_TYPES + 1]; -+ -+ /* Lists of capability codes sent to clients. We remember these -+ lists to restrict clients from choosing those tunneling and -+ authentication types that were not advertised. */ -+ -+ int nAuthCaps; -+ CARD32 authCaps[MAX_AUTH_CAPS]; -+ -+ /* This is not useful while we don't support tunneling: -+ int nTunnelingCaps; -+ CARD32 tunnelingCaps[MAX_TUNNELING_CAPS]; */ -+ -+ /* The following member is only used during VNC authentication */ -+ -+ CARD8 authChallenge[CHALLENGESIZE]; -+ -+ /* The following members represent the update needed to get the client's -+ framebuffer from its present state to the current state of our -+ framebuffer. -+ -+ If the client does not accept CopyRect encoding then the update is -+ simply represented as the region of the screen which has been modified -+ (modifiedRegion). -+ -+ If the client does accept CopyRect encoding, then the update consists of -+ two parts. First we have a single copy from one region of the screen to -+ another (the destination of the copy is copyRegion), and second we have -+ the region of the screen which has been modified in some other way -+ (modifiedRegion). -+ -+ Although the copy is of a single region, this region may have many -+ rectangles. When sending an update, the copyRegion is always sent -+ before the modifiedRegion. This is because the modifiedRegion may -+ overlap parts of the screen which are in the source of the copy. -+ -+ In fact during normal processing, the modifiedRegion may even overlap -+ the destination copyRegion. Just before an update is sent we remove -+ from the copyRegion anything in the modifiedRegion. */ -+ -+ RegionRec copyRegion; /* the destination region of the copy */ -+ int copyDX, copyDY; /* the translation by which the copy happens */ -+ -+ RegionRec modifiedRegion; /* the region of the screen modified in any -+ other way */ -+ -+ /* As part of the FramebufferUpdateRequest, a client can express interest -+ in a subrectangle of the whole framebuffer. This is stored in the -+ requestedRegion member. In the normal case this is the whole -+ framebuffer if the client is ready, empty if it's not. */ -+ -+ RegionRec requestedRegion; -+ -+ /* The following members represent the state of the "deferred update" timer -+ - when the framebuffer is modified and the client is ready, in most -+ cases it is more efficient to defer sending the update by a few -+ milliseconds so that several changes to the framebuffer can be combined -+ into a single update. */ -+ -+ Bool deferredUpdateScheduled; -+ OsTimerPtr deferredUpdateTimer; -+ -+ /* translateFn points to the translation function which is used to copy -+ and translate a rectangle from the framebuffer to an output buffer. */ -+ -+ rfbTranslateFnType translateFn; -+ -+ char *translateLookupTable; -+ -+ rfbPixelFormat format; -+ -+ /* statistics */ -+ -+ int rfbBytesSent[MAX_ENCODINGS]; -+ int rfbRectanglesSent[MAX_ENCODINGS]; -+ int rfbLastRectMarkersSent; -+ int rfbLastRectBytesSent; -+ int rfbCursorShapeBytesSent; -+ int rfbCursorShapeUpdatesSent; -+ int rfbCursorPosBytesSent; -+ int rfbCursorPosUpdatesSent; -+ int rfbFramebufferUpdateMessagesSent; -+ int rfbRawBytesEquivalent; -+ int rfbKeyEventsRcvd; -+ int rfbPointerEventsRcvd; -+ -+ /* zlib encoding -- necessary compression state info per client */ -+ -+ struct z_stream_s compStream; -+ Bool compStreamInited; -+ -+ CARD32 zlibCompressLevel; -+ -+ /* tight encoding -- preserve zlib streams' state for each client */ -+ -+ z_stream zsStruct[4]; -+ Bool zsActive[4]; -+ int zsLevel[4]; -+ int tightCompressLevel; -+ int tightQualityLevel; -+ -+ Bool enableLastRectEncoding; /* client supports LastRect encoding */ -+ Bool enableCursorShapeUpdates; /* client supports cursor shape updates */ -+ Bool enableCursorPosUpdates; /* client supports PointerPos updates */ -+#ifdef CHROMIUM -+ Bool enableChromiumEncoding; /* client supports Chromium encoding */ -+#endif -+ Bool useRichCursorEncoding; /* rfbEncodingRichCursor is preferred */ -+ Bool cursorWasChanged; /* cursor shape update should be sent */ -+ Bool cursorWasMoved; /* cursor position update should be sent */ -+ -+ int cursorX, cursorY; /* client's cursor position */ -+ -+ struct rfbClientRec *next; -+ -+ ScreenPtr pScreen; -+ int userAccepted; -+ -+#ifdef CHROMIUM -+ unsigned int chromium_port; -+#endif -+} rfbClientRec, *rfbClientPtr; -+ -+#ifdef CHROMIUM -+typedef struct CRWindowTable { -+ unsigned long CRwinId; -+ unsigned long XwinId; -+ BoxPtr clipRects; -+ int numRects; -+ struct CRWindowTable *next; -+} CRWindowTable, *CRWindowTablePtr; -+ -+extern struct CRWindowTable *windowTable; -+#endif -+ -+/* -+ * This macro is used to test whether there is a framebuffer update needing to -+ * be sent to the client. -+ */ -+ -+#define FB_UPDATE_PENDING(cl) \ -+ ((!(cl)->enableCursorShapeUpdates && !pVNC->cursorIsDrawn) || \ -+ ((cl)->enableCursorShapeUpdates && (cl)->cursorWasChanged) || \ -+ ((cl)->enableCursorPosUpdates && (cl)->cursorWasMoved) || \ -+ REGION_NOTEMPTY(((cl)->pScreen),&(cl)->copyRegion) || \ -+ REGION_NOTEMPTY(((cl)->pScreen),&(cl)->modifiedRegion)) -+ -+/* -+ * This macro creates an empty region (ie. a region with no areas) if it is -+ * given a rectangle with a width or height of zero. It appears that -+ * REGION_INTERSECT does not quite do the right thing with zero-width -+ * rectangles, but it should with completely empty regions. -+ */ -+ -+#define SAFE_REGION_INIT(pscreen, preg, rect, size) \ -+{ \ -+ if ( ( (rect) ) && \ -+ ( ( (rect)->x2 == (rect)->x1 ) || \ -+ ( (rect)->y2 == (rect)->y1 ) ) ) { \ -+ REGION_NULL( (pscreen), (preg) ); \ -+ } else { \ -+ REGION_INIT( (pscreen), (preg), (rect), (size) ); \ -+ } \ -+} -+ -+/* -+ * An rfbGCRec is where we store the pointers to the original GC funcs and ops -+ * which we wrap (NULL means not wrapped). -+ */ -+ -+typedef struct { -+ GCFuncs *wrapFuncs; -+ GCOps *wrapOps; -+} rfbGCRec, *rfbGCPtr; -+ -+ -+ -+/* -+ * Macros for endian swapping. -+ */ -+ -+#define Swap16(s) ((((s) & 0xff) << 8) | (((s) >> 8) & 0xff)) -+ -+#define Swap32(l) (((l) >> 24) | \ -+ (((l) & 0x00ff0000) >> 8) | \ -+ (((l) & 0x0000ff00) << 8) | \ -+ ((l) << 24)) -+ -+static const int rfbEndianTest = 1; -+ -+#define Swap16IfLE(s) (*(const char *)&rfbEndianTest ? Swap16(s) : (s)) -+ -+#define Swap32IfLE(l) (*(const char *)&rfbEndianTest ? Swap32(l) : (l)) -+ -+ -+/* -+ * Macro to fill in an rfbCapabilityInfo structure (protocol 3.130). -+ * Normally, using macros is no good, but this macro saves us from -+ * writing constants twice -- it constructs signature names from codes. -+ * Note that "code_sym" argument should be a single symbol, not an expression. -+ */ -+ -+#define SetCapInfo(cap_ptr, code_sym, vendor) \ -+{ \ -+ rfbCapabilityInfo *pcap; \ -+ pcap = (cap_ptr); \ -+ pcap->code = Swap32IfLE(code_sym); \ -+ memcpy(pcap->vendorSignature, (vendor), \ -+ sz_rfbCapabilityInfoVendor); \ -+ memcpy(pcap->nameSignature, sig_##code_sym, \ -+ sz_rfbCapabilityInfoName); \ -+} -+ -+ -+/* init.c */ -+ -+extern char *desktopName; -+extern char rfbThisHost[]; -+extern Atom VNC_LAST_CLIENT_ID; -+ -+extern rfbScreenInfo rfbScreen; -+extern int rfbGCIndex; -+ -+extern int inetdSock; -+ -+extern int rfbBitsPerPixel(int depth); -+extern void rfbLog(char *format, ...); -+extern void rfbLogPerror(char *str); -+ -+ -+/* sockets.c */ -+ -+extern int rfbMaxClientWait; -+ -+extern Bool rfbInitSockets(ScreenPtr pScreen); -+extern void rfbDisconnectUDPSock(ScreenPtr pScreen); -+extern void rfbCloseSock(ScreenPtr pScreen, int sock); -+extern void rfbCheckFds(ScreenPtr pScreen); -+extern void rfbWaitForClient(int sock); -+extern int rfbConnect(ScreenPtr pScreen, char *host, int port); -+ -+extern int ReadExact(int sock, char *buf, int len); -+extern int WriteExact(int sock, char *buf, int len); -+extern int ListenOnTCPPort(ScreenPtr pScreen, int port); -+extern int ListenOnUDPPort(ScreenPtr pScreen, int port); -+extern int ConnectToTcpAddr(char *host, int port); -+ -+ -+/* cmap.c */ -+ -+ -+extern int rfbListInstalledColormaps(ScreenPtr pScreen, Colormap *pmaps); -+extern void rfbInstallColormap(ColormapPtr pmap); -+extern void rfbUninstallColormap(ColormapPtr pmap); -+extern void rfbStoreColors(ColormapPtr pmap, int ndef, xColorItem *pdefs); -+ -+ -+/* draw.c */ -+ -+extern int rfbDeferUpdateTime; -+ -+extern void -+rfbComposite( -+ CARD8 op, -+ PicturePtr pSrc, -+ PicturePtr pMask, -+ PicturePtr pDst, -+ INT16 xSrc, -+ INT16 ySrc, -+ INT16 xMask, -+ INT16 yMask, -+ INT16 xDst, -+ INT16 yDst, -+ CARD16 width, -+ CARD16 height -+); -+ -+extern void rfbGlyphs( -+ CARD8 op, -+ PicturePtr pSrc, -+ PicturePtr pDst, -+ PictFormatPtr maskFormat, -+ INT16 xSrc, -+ INT16 ySrc, -+ int nlistInit, -+ GlyphListPtr listInit, -+ GlyphPtr *glyphsInit -+); -+extern Bool rfbCloseScreen(int,ScreenPtr); -+extern Bool rfbCreateGC(GCPtr); -+extern void rfbPaintWindowBackground(WindowPtr, RegionPtr, int what); -+extern void rfbPaintWindowBorder(WindowPtr, RegionPtr, int what); -+extern void rfbCopyWindow(WindowPtr, DDXPointRec, RegionPtr); -+#ifdef CHROMIUM -+extern Bool rfbRealizeWindow(WindowPtr); -+extern Bool rfbUnrealizeWindow(WindowPtr); -+extern Bool rfbDestroyWindow(WindowPtr); -+extern void rfbResizeWindow(WindowPtr, int x, int y, unsigned int w, unsigned int h, WindowPtr pSib); -+extern Bool rfbPositionWindow(WindowPtr, int x, int y); -+extern void rfbClipNotify(WindowPtr, int x, int y); -+#endif -+extern void rfbClearToBackground(WindowPtr, int x, int y, int w, -+ int h, Bool generateExposures); -+extern RegionPtr rfbRestoreAreas(WindowPtr, RegionPtr); -+ -+ -+/* cutpaste.c */ -+ -+extern void rfbSetXCutText(char *str, int len); -+extern void rfbGotXCutText(char *str, int len); -+ -+ -+/* kbdptr.c */ -+ -+extern Bool compatibleKbd; -+extern unsigned char ptrAcceleration; -+ -+extern void PtrDeviceInit(void); -+extern void PtrDeviceOn(DeviceIntPtr pDev); -+extern void PtrDeviceOff(void); -+extern void PtrDeviceControl(DeviceIntPtr dev, PtrCtrl *ctrl); -+extern void PtrAddEvent(int buttonMask, int x, int y, rfbClientPtr cl); -+ -+extern void KbdDeviceInit(DeviceIntPtr pDevice, KeySymsPtr pKeySyms, CARD8 *pModMap); -+extern void KbdDeviceOn(void); -+extern void KbdDeviceOff(void); -+extern void KbdAddEvent(Bool down, KeySym keySym, rfbClientPtr cl); -+extern void KbdReleaseAllKeys(void); -+ -+ -+/* rfbserver.c */ -+ -+ -+extern rfbClientPtr rfbClientHead; -+extern rfbClientPtr pointerClient; -+ -+extern void rfbUserAllow(int sock, int accept); -+ -+extern void rfbNewClientConnection(ScreenPtr pScreen, int sock); -+extern rfbClientPtr rfbReverseConnection(ScreenPtr pScreen, char *host, int port); -+extern void rfbRootPropertyChange(ScreenPtr pScreen); -+extern void rfbClientConnectionGone(int sock); -+extern void rfbProcessClientMessage(ScreenPtr pScreen, int sock); -+extern void rfbClientConnFailed(rfbClientPtr cl, char *reason); -+extern void rfbNewUDPConnection(int sock); -+extern void rfbProcessUDPInput(ScreenPtr pScreen, int sock); -+extern Bool rfbSendFramebufferUpdate(ScreenPtr pScreen, rfbClientPtr cl); -+extern Bool rfbSendRectEncodingRaw(rfbClientPtr cl, int x,int y,int w,int h); -+extern Bool rfbSendUpdateBuf(rfbClientPtr cl); -+extern Bool rfbSendSetColourMapEntries(rfbClientPtr cl, int firstColour, -+ int nColours); -+extern void rfbSendBell(void); -+extern void rfbSendServerCutText(char *str, int len); -+#ifdef CHROMIUM -+extern void rfbSendChromiumWindowShow(unsigned int winid, unsigned int show); -+extern void rfbSendChromiumMoveResizeWindow(unsigned int winid, int x, int y, unsigned int w, unsigned int h); -+extern void rfbSendChromiumClipList(unsigned int winid, BoxPtr pClipRects, int numClipRects); -+#endif -+ -+/* translate.c */ -+ -+extern Bool rfbEconomicTranslate; -+ -+extern void rfbTranslateNone(ScreenPtr pScreen, char *table, rfbPixelFormat *in, -+ rfbPixelFormat *out, -+ unsigned char *iptr, char *optr, -+ int bytesBetweenInputLines, -+ int width, int height, -+ int x, int y); -+extern Bool rfbSetTranslateFunction(rfbClientPtr cl); -+extern void rfbSetClientColourMaps(int firstColour, int nColours); -+extern Bool rfbSetClientColourMap(rfbClientPtr cl, int firstColour, -+ int nColours); -+ -+ -+/* httpd.c */ -+ -+extern Bool httpInitSockets(ScreenPtr pScreen); -+extern void httpCheckFds(ScreenPtr pScreen); -+ -+ -+ -+/* auth.c */ -+ -+extern void rfbAuthNewClient(rfbClientPtr cl); -+extern void rfbProcessClientSecurityType(rfbClientPtr cl); -+extern void rfbProcessClientTunnelingType(rfbClientPtr cl); -+extern void rfbProcessClientAuthType(rfbClientPtr cl); -+extern void rfbVncAuthProcessResponse(rfbClientPtr cl); -+ -+/* Functions to prevent too many successive authentication failures */ -+extern Bool rfbAuthConsiderBlocking(rfbClientPtr cl); -+extern void rfbAuthUnblock(rfbClientPtr cl); -+extern Bool rfbAuthIsBlocked(rfbClientPtr cl); -+ -+/* loginauth.c */ -+ -+extern void rfbLoginAuthProcessClientMessage(rfbClientPtr cl); -+ -+/* rre.c */ -+ -+extern Bool rfbSendRectEncodingRRE(rfbClientPtr cl, int x,int y,int w,int h); -+ -+ -+/* corre.c */ -+ -+extern Bool rfbSendRectEncodingCoRRE(rfbClientPtr cl, int x,int y,int w,int h); -+ -+ -+/* hextile.c */ -+ -+extern Bool rfbSendRectEncodingHextile(rfbClientPtr cl, int x, int y, int w, -+ int h); -+ -+ -+/* zlib.c */ -+ -+/* Minimum zlib rectangle size in bytes. Anything smaller will -+ * not compress well due to overhead. -+ */ -+#define VNC_ENCODE_ZLIB_MIN_COMP_SIZE (17) -+ -+/* Set maximum zlib rectangle size in pixels. Always allow at least -+ * two scan lines. -+ */ -+#define ZLIB_MAX_RECT_SIZE (128*256) -+#define ZLIB_MAX_SIZE(min) ((( min * 2 ) > ZLIB_MAX_RECT_SIZE ) ? \ -+ ( min * 2 ) : ZLIB_MAX_RECT_SIZE ) -+ -+extern Bool rfbSendRectEncodingZlib(rfbClientPtr cl, int x, int y, int w, -+ int h); -+ -+ -+/* tight.c */ -+ -+#define TIGHT_DEFAULT_COMPRESSION 6 -+ -+extern Bool rfbTightDisableGradient; -+ -+extern int rfbNumCodedRectsTight(rfbClientPtr cl, int x,int y,int w,int h); -+extern Bool rfbSendRectEncodingTight(rfbClientPtr cl, int x,int y,int w,int h); -+ -+ -+/* cursor.c */ -+ -+extern Bool rfbSendCursorShape(rfbClientPtr cl, ScreenPtr pScreen); -+extern Bool rfbSendCursorPos(rfbClientPtr cl, ScreenPtr pScreen); -+ -+ -+/* stats.c */ -+ -+extern void rfbResetStats(rfbClientPtr cl); -+extern void rfbPrintStats(rfbClientPtr cl); -diff --git a/hw/dmx/vnc/rfbkeyb.c b/hw/dmx/vnc/rfbkeyb.c -new file mode 100644 -index 0000000..df5b999 ---- /dev/null -+++ b/hw/dmx/vnc/rfbkeyb.c -@@ -0,0 +1,412 @@ -+/* -+ * Copyright (C) 2002 Alan Hourihane. 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. -+ * -+ * Author: Alan Hourihane -+ */ -+ -+#include -+ -+#if XFREE86VNC -+#ifndef XFree86LOADER -+#include -+#include -+#endif -+ -+#include -+#include -+#define NEED_XF86_TYPES -+#if !defined(DGUX) -+#include -+#include -+#endif -+#include -+#include -+#include /* Needed for InitValuator/Proximity stuff */ -+#include -+#include -+ -+#ifdef XFree86LOADER -+#include -+#endif -+#else -+#include -+#include -+#include -+#endif -+ -+#include "rfb.h" -+ -+extern Bool noXkbExtension; -+extern void rfbSendBell(void); -+extern DeviceIntPtr kbdDevice; -+ -+static const char *DEFAULTS[] = { -+ NULL -+}; -+ -+#include "keyboard.h" -+ -+#ifdef XKB -+#include -+#include -+#include -+ -+#if XFREE86VNC -+ /* -+ * would like to use an XkbComponentNamesRec here but can't without -+ * pulling in a bunch of header files. :-( -+ */ -+static char * xkbkeymap; -+static char * xkbkeycodes; -+static char * xkbtypes; -+static char * xkbcompat; -+static char * xkbsymbols; -+static char * xkbgeometry; -+static Bool xkbcomponents_specified; -+static char * xkbrules; -+static char * xkbmodel; -+static char * xkblayout; -+static char * xkbvariant; -+static char * xkboptions; -+#endif -+#endif -+ -+void -+KbdDeviceInit(DeviceIntPtr pDevice, KeySymsPtr pKeySyms, CARD8 *pModMap) -+{ -+ int i; -+ -+ kbdDevice = pDevice; -+ -+ for (i = 0; i < MAP_LENGTH; i++) -+ pModMap[i] = NoSymbol; -+ -+ pModMap[CONTROL_L_KEY_CODE] = ControlMask; -+ pModMap[CONTROL_R_KEY_CODE] = ControlMask; -+ pModMap[SHIFT_L_KEY_CODE] = ShiftMask; -+ pModMap[SHIFT_R_KEY_CODE] = ShiftMask; -+ pModMap[META_L_KEY_CODE] = Mod1Mask; -+ pModMap[META_R_KEY_CODE] = Mod1Mask; -+ pModMap[ALT_L_KEY_CODE] = Mod1Mask; -+ pModMap[ALT_R_KEY_CODE] = Mod1Mask; -+ -+ pKeySyms->minKeyCode = MIN_KEY_CODE; -+ pKeySyms->maxKeyCode = MAX_KEY_CODE; -+ pKeySyms->mapWidth = GLYPHS_PER_KEY; -+ -+ pKeySyms->map = (KeySym *)xalloc(sizeof(KeySym) -+ * MAP_LENGTH * GLYPHS_PER_KEY); -+ -+ if (!pKeySyms->map) { -+ ErrorF("xalloc failed in KbdDeviceInit\n"); -+ exit(1); -+ } -+ -+ for (i = 0; i < MAP_LENGTH * GLYPHS_PER_KEY; i++) -+ pKeySyms->map[i] = NoSymbol; -+ -+ for (i = 0; i < N_PREDEFINED_KEYS * GLYPHS_PER_KEY; i++) { -+ pKeySyms->map[i] = map[i]; -+ } -+} -+ -+void -+KbdDeviceOn(void) -+{ -+} -+ -+ -+void -+KbdDeviceOff(void) -+{ -+} -+ -+#if XFREE86VNC -+static int -+xf86rfbKeybControlProc(DeviceIntPtr device, int onoff) -+{ -+ KeySymsRec keySyms; -+ CARD8 modMap[MAP_LENGTH]; -+ DevicePtr pDev = (DevicePtr)device; -+ -+ switch (onoff) -+ { -+ case DEVICE_INIT: -+ KbdDeviceInit(device, &keySyms, modMap); -+#ifdef XKB -+ if (noXkbExtension) { -+#endif -+ InitKeyboardDeviceStruct(pDev, &keySyms, modMap, -+ (BellProcPtr)rfbSendBell, -+ (KbdCtrlProcPtr)NoopDDA); -+#ifdef XKB -+ } else { -+ XkbComponentNamesRec names; -+ if (XkbInitialMap) { -+ if ((xkbkeymap = strchr(XkbInitialMap, '/')) != NULL) -+ xkbkeymap++; -+ else -+ xkbkeymap = XkbInitialMap; -+ } -+ if (xkbkeymap) { -+ names.keymap = xkbkeymap; -+ names.keycodes = NULL; -+ names.types = NULL; -+ names.compat = NULL; -+ names.symbols = NULL; -+ names.geometry = NULL; -+ } else { -+ names.keymap = NULL; -+ names.keycodes = xkbkeycodes; -+ names.types = xkbtypes; -+ names.compat = xkbcompat; -+ names.symbols = xkbsymbols; -+ names.geometry = xkbgeometry; -+ } -+ if ((xkbkeymap || xkbcomponents_specified) -+ && (xkbmodel == NULL || xkblayout == NULL)) { -+ xkbrules = NULL; -+ } -+#if 0 -+ XkbSetRulesDflts(xkbrules, xkbmodel, -+ xkblayout, xkbvariant, -+ xkboptions); -+#endif -+ XkbInitKeyboardDeviceStruct(device, -+ &names, -+ &keySyms, -+ modMap, -+ (BellProcPtr)rfbSendBell, -+ (KbdCtrlProcPtr)NoopDDA); -+ } -+#endif /* XKB */ -+ 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 void -+xf86rfbKeybUninit(InputDriverPtr drv, -+ InputInfoPtr pInfo, -+ int flags) -+{ -+ xf86rfbKeybControlProc(pInfo->dev, DEVICE_OFF); -+} -+ -+static InputInfoPtr -+xf86rfbKeybInit(InputDriverPtr drv, -+ IDevPtr dev, -+ int flags) -+{ -+ InputInfoPtr pInfo; -+ char *s; -+ Bool from; -+ -+ if (!(pInfo = xf86AllocateInput(drv, 0))) -+ return NULL; -+ -+ /* Initialise the InputInfoRec. */ -+ pInfo->name = dev->identifier; -+ pInfo->type_name = "rfbKeyb"; -+ pInfo->flags = XI86_KEYBOARD_CAPABLE; -+ pInfo->device_control = xf86rfbKeybControlProc; -+ pInfo->read_input = NULL; -+ pInfo->motion_history_proc = NULL; -+ pInfo->history_size = 0; -+ pInfo->control_proc = NULL; -+ pInfo->close_proc = NULL; -+ pInfo->switch_mode = NULL; -+ pInfo->conversion_proc = NULL; -+ pInfo->reverse_conversion_proc = NULL; -+ pInfo->fd = -1; -+ pInfo->dev = NULL; -+ pInfo->private_flags = 0; -+ pInfo->always_core_feedback = 0; -+ pInfo->conf_idev = dev; -+ -+ /* Collect the options, and process the common options. */ -+ xf86CollectInputOptions(pInfo, DEFAULTS, NULL); -+ xf86ProcessCommonOptions(pInfo, pInfo->options); -+ -+ /* Mark the device configured */ -+ pInfo->flags |= XI86_CONFIGURED; -+ -+#ifdef XKB -+ from = X_DEFAULT; -+ if (noXkbExtension) -+ from = X_CMDLINE; -+ else if (xf86FindOption(dev->commonOptions, "XkbDisable")) { -+ noXkbExtension = -+ xf86SetBoolOption(dev->commonOptions, "XkbDisable", FALSE); -+ from = X_CONFIG; -+ } -+ if (noXkbExtension) -+ xf86Msg(from, "XKB: disabled\n"); -+ -+#define NULL_IF_EMPTY(s) (s[0] ? s : (xfree(s), (char *)NULL)) -+ -+ if (!noXkbExtension && !XkbInitialMap) { -+ if ((s = xf86SetStrOption(dev->commonOptions, "XkbKeymap", NULL))) { -+ xkbkeymap = NULL_IF_EMPTY(s); -+ xf86Msg(X_CONFIG, "XKB: keymap: \"%s\" " -+ "(overrides other XKB settings)\n", xkbkeymap); -+ } else { -+ if ((s = xf86SetStrOption(dev->commonOptions, "XkbCompat", NULL))) { -+ xkbcompat = NULL_IF_EMPTY(s); -+ xkbcomponents_specified = TRUE; -+ xf86Msg(X_CONFIG, "XKB: compat: \"%s\"\n", s); -+ } -+ -+ if ((s = xf86SetStrOption(dev->commonOptions, "XkbTypes", NULL))) { -+ xkbtypes = NULL_IF_EMPTY(s); -+ xkbcomponents_specified = TRUE; -+ xf86Msg(X_CONFIG, "XKB: types: \"%s\"\n", s); -+ } -+ -+ if ((s = xf86SetStrOption(dev->commonOptions, "XkbKeycodes", NULL))) { -+ xkbkeycodes = NULL_IF_EMPTY(s); -+ xkbcomponents_specified = TRUE; -+ xf86Msg(X_CONFIG, "XKB: keycodes: \"%s\"\n", s); -+ } -+ -+ if ((s = xf86SetStrOption(dev->commonOptions, "XkbGeometry", NULL))) { -+ xkbgeometry = NULL_IF_EMPTY(s); -+ xkbcomponents_specified = TRUE; -+ xf86Msg(X_CONFIG, "XKB: geometry: \"%s\"\n", s); -+ } -+ -+ if ((s = xf86SetStrOption(dev->commonOptions, "XkbSymbols", NULL))) { -+ xkbsymbols = NULL_IF_EMPTY(s); -+ xkbcomponents_specified = TRUE; -+ xf86Msg(X_CONFIG, "XKB: symbols: \"%s\"\n", s); -+ } -+ -+ if ((s = xf86SetStrOption(dev->commonOptions, "XkbRules", NULL))) { -+ xkbrules = NULL_IF_EMPTY(s); -+ xkbcomponents_specified = TRUE; -+ xf86Msg(X_CONFIG, "XKB: rules: \"%s\"\n", s); -+ } -+ -+ if ((s = xf86SetStrOption(dev->commonOptions, "XkbModel", NULL))) { -+ xkbmodel = NULL_IF_EMPTY(s); -+ xkbcomponents_specified = TRUE; -+ xf86Msg(X_CONFIG, "XKB: model: \"%s\"\n", s); -+ } -+ -+ if ((s = xf86SetStrOption(dev->commonOptions, "XkbLayout", NULL))) { -+ xkblayout = NULL_IF_EMPTY(s); -+ xkbcomponents_specified = TRUE; -+ xf86Msg(X_CONFIG, "XKB: layout: \"%s\"\n", s); -+ } -+ -+ if ((s = xf86SetStrOption(dev->commonOptions, "XkbVariant", NULL))) { -+ xkbvariant = NULL_IF_EMPTY(s); -+ xkbcomponents_specified = TRUE; -+ xf86Msg(X_CONFIG, "XKB: variant: \"%s\"\n", s); -+ } -+ -+ if ((s = xf86SetStrOption(dev->commonOptions, "XkbOptions", NULL))) { -+ xkboptions = NULL_IF_EMPTY(s); -+ xkbcomponents_specified = TRUE; -+ xf86Msg(X_CONFIG, "XKB: options: \"%s\"\n", s); -+ } -+ } -+ } -+#undef NULL_IF_EMPTY -+#endif /* XKB */ -+ -+ /* Return the configured device */ -+ return (pInfo); -+} -+ -+#ifdef XFree86LOADER -+static -+#endif -+InputDriverRec RFBKEYB = { -+ 1, /* driver version */ -+ "rfbkeyb", /* driver name */ -+ NULL, /* identify */ -+ xf86rfbKeybInit, /* pre-init */ -+ xf86rfbKeybUninit, /* un-init */ -+ NULL, /* module */ -+ 0 /* ref count */ -+}; -+ -+/* -+ *************************************************************************** -+ * -+ * Dynamic loading functions -+ * -+ *************************************************************************** -+ */ -+#ifdef XFree86LOADER -+static void -+xf86rfbKeybUnplug(pointer p) -+{ -+} -+ -+static pointer -+xf86rfbKeybPlug(pointer module, -+ pointer options, -+ int *errmaj, -+ int *errmin) -+{ -+ xf86AddInputDriver(&RFBKEYB, module, 0); -+ -+ return module; -+} -+ -+void -+vncInitKeyb(void) -+{ -+ xf86AddInputDriver(&RFBKEYB, NULL, 0); -+} -+ -+static XF86ModuleVersionInfo xf86rfbKeybVersionRec = -+{ -+ "rfbkeyb", -+ "xf4vnc Project, see http://xf4vnc.sf.net", -+ MODINFOSTRING1, -+ MODINFOSTRING2, -+ XF86_VERSION_CURRENT, -+ 1, 0, 0, -+ ABI_CLASS_XINPUT, -+ ABI_XINPUT_VERSION, -+ MOD_CLASS_XINPUT, -+ {0, 0, 0, 0} /* signature, to be patched into the file by */ -+ /* a tool */ -+}; -+ -+XF86ModuleData rfbkeybModuleData = {&xf86rfbKeybVersionRec, -+ xf86rfbKeybPlug, -+ xf86rfbKeybUnplug}; -+ -+#endif /* XFree86LOADER */ -+#endif /* XFREE86VNC */ -diff --git a/hw/dmx/vnc/rfbmouse.c b/hw/dmx/vnc/rfbmouse.c -new file mode 100644 -index 0000000..c92c8ca ---- /dev/null -+++ b/hw/dmx/vnc/rfbmouse.c -@@ -0,0 +1,243 @@ -+/* -+ * Copyright (C) 2002 Alan Hourihane. 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. -+ * -+ * Author: Alan Hourihane -+ */ -+ -+#if XFREE86VNC -+#ifndef XFree86LOADER -+#include -+#include -+#endif -+ -+#include -+#include -+#define NEED_XF86_TYPES -+#if !defined(DGUX) -+#include -+#include -+#endif -+#include -+#include -+#include /* Needed for InitValuator/Proximity stuff */ -+#include -+#include -+ -+#ifdef XFree86LOADER -+#include -+#endif -+ -+static const char *DEFAULTS[] = { -+ NULL -+}; -+#else -+#include -+#include -+#include -+#endif -+ -+#include "rfb.h" -+ -+ -+unsigned char ptrAcceleration = 50; -+ -+void -+PtrDeviceOn(DeviceIntPtr pDev) -+{ -+#if 0 -+ ptrAcceleration = (unsigned char)pDev->ptrfeed->ctrl.num; -+#endif -+} -+ -+void -+PtrDeviceInit(void) -+{ -+} -+ -+void -+PtrDeviceOff(void) -+{ -+} -+ -+ -+void -+PtrDeviceControl(DeviceIntPtr dev, PtrCtrl *ctrl) -+{ -+#if 0 -+ ptrAcceleration = (char)ctrl->num; -+ -+ if (udpSockConnected) { -+ if (write(udpSock, &ptrAcceleration, 1) <= 0) { -+ ErrorF("PtrDeviceControl: UDP input: write"); -+ rfbDisconnectUDPSock(); -+ } -+ } -+#endif -+} -+ -+#if XFREE86VNC -+static int -+xf86rfbMouseControlProc(DeviceIntPtr device, int onoff) -+{ -+ BYTE map[6]; -+ DevicePtr pDev = (DevicePtr)device; -+ -+ 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(device); -+ break; -+ -+ case DEVICE_OFF: -+ pDev->on = FALSE; -+ PtrDeviceOff(); -+ break; -+ -+ case DEVICE_CLOSE: -+ if (pDev->on) -+ PtrDeviceOff(); -+ break; -+ } -+ return Success; -+} -+ -+static void -+xf86rfbMouseUninit(InputDriverPtr drv, -+ InputInfoPtr pInfo, -+ int flags) -+{ -+ xf86rfbMouseControlProc(pInfo->dev, DEVICE_OFF); -+} -+ -+static InputInfoPtr -+xf86rfbMouseInit(InputDriverPtr drv, -+ IDevPtr dev, -+ int flags) -+{ -+ InputInfoPtr pInfo; -+ -+ if (!(pInfo = xf86AllocateInput(drv, 0))) -+ return NULL; -+ -+ /* Initialise the InputInfoRec. */ -+ pInfo->name = dev->identifier; -+ pInfo->type_name = "rfbMouse"; -+ pInfo->flags = XI86_POINTER_CAPABLE | XI86_SEND_DRAG_EVENTS; -+ pInfo->device_control = xf86rfbMouseControlProc; -+ pInfo->read_input = NULL; -+ pInfo->motion_history_proc = xf86GetMotionEvents; -+ pInfo->history_size = 0; -+ pInfo->control_proc = NULL; -+ pInfo->close_proc = NULL; -+ pInfo->switch_mode = NULL; -+ pInfo->conversion_proc = NULL; -+ pInfo->reverse_conversion_proc = NULL; -+ pInfo->fd = -1; -+ pInfo->dev = NULL; -+ pInfo->private_flags = 0; -+ pInfo->always_core_feedback = 0; -+ pInfo->conf_idev = dev; -+ -+ /* Collect the options, and process the common options. */ -+ xf86CollectInputOptions(pInfo, DEFAULTS, NULL); -+ xf86ProcessCommonOptions(pInfo, pInfo->options); -+ -+ /* Mark the device configured */ -+ pInfo->flags |= XI86_CONFIGURED; -+ -+ /* Return the configured device */ -+ return (pInfo); -+} -+ -+#ifdef XFree86LOADER -+static -+#endif -+InputDriverRec RFBMOUSE = { -+ 1, /* driver version */ -+ "rfbmouse", /* driver name */ -+ NULL, /* identify */ -+ xf86rfbMouseInit, /* pre-init */ -+ xf86rfbMouseUninit, /* un-init */ -+ NULL, /* module */ -+ 0 /* ref count */ -+}; -+ -+/* -+ *************************************************************************** -+ * -+ * Dynamic loading functions -+ * -+ *************************************************************************** -+ */ -+#ifdef XFree86LOADER -+static void -+xf86rfbMouseUnplug(pointer p) -+{ -+} -+ -+static pointer -+xf86rfbMousePlug(pointer module, -+ pointer options, -+ int *errmaj, -+ int *errmin) -+{ -+ xf86AddInputDriver(&RFBMOUSE, module, 0); -+ -+ return module; -+} -+ -+void -+vncInitMouse(void) -+{ -+ xf86AddInputDriver(&RFBMOUSE, NULL, 0); -+} -+ -+static XF86ModuleVersionInfo xf86rfbMouseVersionRec = -+{ -+ "rfbmouse", -+ "xf4vnc Project, see http://xf4vnc.sf.net", -+ MODINFOSTRING1, -+ MODINFOSTRING2, -+ XF86_VERSION_CURRENT, -+ 1, 0, 0, -+ ABI_CLASS_XINPUT, -+ ABI_XINPUT_VERSION, -+ MOD_CLASS_XINPUT, -+ {0, 0, 0, 0} /* signature, to be patched into the file by */ -+ /* a tool */ -+}; -+ -+XF86ModuleData rfbmouseModuleData = {&xf86rfbMouseVersionRec, -+ xf86rfbMousePlug, -+ xf86rfbMouseUnplug}; -+ -+#endif /* XFree86LOADER */ -+#endif -diff --git a/hw/dmx/vnc/rfbproto.h b/hw/dmx/vnc/rfbproto.h -new file mode 100644 -index 0000000..bbef703 ---- /dev/null -+++ b/hw/dmx/vnc/rfbproto.h -@@ -0,0 +1,1347 @@ -+/* -+ * Copyright (C) 2000-2004 Constantin Kaplinsky. All Rights Reserved. -+ * Copyright (C) 2000 Tridia Corporation. All Rights Reserved. -+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. -+ * -+ * This is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This software is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this software; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -+ * USA. -+ */ -+ -+/* -+ * rfbproto.h - header file for the RFB protocol, versions 3.3, 3.7 and 3.7t -+ * (protocol 3.7t is effectively 3.7 with TightVNC extensions enabled) -+ * -+ * Uses types CARD for an n-bit unsigned integer, INT for an n-bit signed -+ * integer (for n = 8, 16 and 32). -+ * -+ * All multiple byte integers are in big endian (network) order (most -+ * significant byte first). Unless noted otherwise there is no special -+ * alignment of protocol structures. -+ * -+ * -+ * Once the initial handshaking is done, all messages start with a type byte, -+ * (usually) followed by message-specific data. The order of definitions in -+ * this file is as follows: -+ * -+ * (1) Structures used in several types of message. -+ * (2) Structures used in the initial handshaking. -+ * (3) Message types. -+ * (4) Encoding types. -+ * (5) For each message type, the form of the data following the type byte. -+ * Sometimes this is defined by a single structure but the more complex -+ * messages have to be explained by comments. -+ */ -+ -+ -+/***************************************************************************** -+ * -+ * Structures used in several messages -+ * -+ *****************************************************************************/ -+ -+/*----------------------------------------------------------------------------- -+ * Structure used to specify a rectangle. This structure is a multiple of 4 -+ * bytes so that it can be interspersed with 32-bit pixel data without -+ * affecting alignment. -+ */ -+ -+typedef struct _rfbRectangle { -+ CARD16 x; -+ CARD16 y; -+ CARD16 w; -+ CARD16 h; -+} rfbRectangle; -+ -+#define sz_rfbRectangle 8 -+ -+ -+/*----------------------------------------------------------------------------- -+ * Structure used to specify pixel format. -+ */ -+ -+typedef struct _rfbPixelFormat { -+ -+ CARD8 bitsPerPixel; /* 8,16,32 only */ -+ -+ CARD8 depth; /* 8 to 32 */ -+ -+ CARD8 bigEndian; /* True if multi-byte pixels are interpreted -+ as big endian, or if single-bit-per-pixel -+ has most significant bit of the byte -+ corresponding to first (leftmost) pixel. Of -+ course this is meaningless for 8 bits/pix */ -+ -+ CARD8 trueColour; /* If false then we need a "colour map" to -+ convert pixels to RGB. If true, xxxMax and -+ xxxShift specify bits used for red, green -+ and blue */ -+ -+ /* the following fields are only meaningful if trueColour is true */ -+ -+ CARD16 redMax; /* maximum red value (= 2^n - 1 where n is the -+ number of bits used for red). Note this -+ value is always in big endian order. */ -+ -+ CARD16 greenMax; /* similar for green */ -+ -+ CARD16 blueMax; /* and blue */ -+ -+ CARD8 redShift; /* number of shifts needed to get the red -+ value in a pixel to the least significant -+ bit. To find the red value from a given -+ pixel, do the following: -+ 1) Swap pixel value according to bigEndian -+ (e.g. if bigEndian is false and host byte -+ order is big endian, then swap). -+ 2) Shift right by redShift. -+ 3) AND with redMax (in host byte order). -+ 4) You now have the red value between 0 and -+ redMax. */ -+ -+ CARD8 greenShift; /* similar for green */ -+ -+ CARD8 blueShift; /* and blue */ -+ -+ CARD8 pad1; -+ CARD16 pad2; -+ -+} rfbPixelFormat; -+ -+#define sz_rfbPixelFormat 16 -+ -+ -+/*----------------------------------------------------------------------------- -+ * Structure used to describe protocol options such as tunneling methods, -+ * authentication schemes and message types (protocol version 3.7t). -+ */ -+ -+typedef struct _rfbCapabilityInfo { -+ -+ CARD32 code; /* numeric identifier */ -+ CARD8 vendorSignature[4]; /* vendor identification */ -+ CARD8 nameSignature[8]; /* abbreviated option name */ -+ -+} rfbCapabilityInfo; -+ -+#define sz_rfbCapabilityInfoVendor 4 -+#define sz_rfbCapabilityInfoName 8 -+#define sz_rfbCapabilityInfo 16 -+ -+/* -+ * Vendors known by TightVNC: standard VNC/RealVNC, TridiaVNC, and TightVNC. -+ */ -+ -+#define rfbStandardVendor "STDV" -+#define rfbTridiaVncVendor "TRDV" -+#define rfbTightVncVendor "TGHT" -+#define rfbTungstenGraphicsVendor "TGIV" -+ -+ -+/***************************************************************************** -+ * -+ * Initial handshaking messages -+ * -+ *****************************************************************************/ -+ -+/*----------------------------------------------------------------------------- -+ * Protocol Version -+ * -+ * The server always sends 12 bytes to start which identifies the latest RFB -+ * protocol version number which it supports. These bytes are interpreted -+ * as a string of 12 ASCII characters in the format "RFB xxx.yyy\n" where -+ * xxx and yyy are the major and minor version numbers (for version 3.7 -+ * this is "RFB 003.007\n"). -+ * -+ * The client then replies with a similar 12-byte message giving the version -+ * number of the protocol which should actually be used (which may be different -+ * to that quoted by the server). -+ * -+ * It is intended that both clients and servers may provide some level of -+ * backwards compatibility by this mechanism. Servers in particular should -+ * attempt to provide backwards compatibility, and even forwards compatibility -+ * to some extent. For example if a client demands version 3.1 of the -+ * protocol, a 3.0 server can probably assume that by ignoring requests for -+ * encoding types it doesn't understand, everything will still work OK. This -+ * will probably not be the case for changes in the major version number. -+ * -+ * The format string below can be used in sprintf or sscanf to generate or -+ * decode the version string respectively. -+ */ -+ -+#define rfbProtocolVersionFormat "RFB %03d.%03d\n" -+#define rfbProtocolMajorVersion 3 -+#define rfbProtocolMinorVersion 7 -+#define rfbProtocolFallbackMinorVersion 3 -+ -+typedef char rfbProtocolVersionMsg[13]; /* allow extra byte for null */ -+ -+#define sz_rfbProtocolVersionMsg 12 -+ -+ -+/* -+ * Negotiation of the security type (protocol version 3.7) -+ * -+ * Once the protocol version has been decided, the server either sends a list -+ * of supported security types, or informs the client about an error (when the -+ * number of security types is 0). Security type rfbSecTypeTight is used to -+ * enable TightVNC-specific protocol extensions. The value rfbSecTypeVncAuth -+ * stands for classic VNC authentication. -+ * -+ * The client selects a particular security type from the list provided by the -+ * server. -+ */ -+ -+#define rfbSecTypeInvalid 0 -+#define rfbSecTypeNone 1 -+#define rfbSecTypeVncAuth 2 -+#define rfbSecTypeTight 16 -+ -+ -+/*----------------------------------------------------------------------------- -+ * Negotiation of Tunneling Capabilities (protocol version 3.7t) -+ * -+ * If the chosen security type is rfbSecTypeTight, the server sends a list of -+ * supported tunneling methods ("tunneling" refers to any additional layer of -+ * data transformation, such as encryption or external compression.) -+ * -+ * nTunnelTypes specifies the number of following rfbCapabilityInfo structures -+ * that list all supported tunneling methods in the order of preference. -+ * -+ * NOTE: If nTunnelTypes is 0, that tells the client that no tunneling can be -+ * used, and the client should not send a response requesting a tunneling -+ * method. -+ */ -+ -+typedef struct _rfbTunnelingCapsMsg { -+ CARD32 nTunnelTypes; -+ /* followed by nTunnelTypes * rfbCapabilityInfo structures */ -+} rfbTunnelingCapsMsg; -+ -+#define sz_rfbTunnelingCapsMsg 4 -+ -+/*----------------------------------------------------------------------------- -+ * Tunneling Method Request (protocol version 3.7t) -+ * -+ * If the list of tunneling capabilities sent by the server was not empty, the -+ * client should reply with a 32-bit code specifying a particular tunneling -+ * method. The following code should be used for no tunneling. -+ */ -+ -+#define rfbNoTunneling 0 -+#define sig_rfbNoTunneling "NOTUNNEL" -+ -+ -+/*----------------------------------------------------------------------------- -+ * Negotiation of Authentication Capabilities (protocol version 3.7t) -+ * -+ * After setting up tunneling, the server sends a list of supported -+ * authentication schemes. -+ * -+ * nAuthTypes specifies the number of following rfbCapabilityInfo structures -+ * that list all supported authentication schemes in the order of preference. -+ * -+ * NOTE: If nAuthTypes is 0, that tells the client that no authentication is -+ * necessary, and the client should not send a response requesting an -+ * authentication scheme. -+ */ -+ -+typedef struct _rfbAuthenticationCapsMsg { -+ CARD32 nAuthTypes; -+ /* followed by nAuthTypes * rfbCapabilityInfo structures */ -+} rfbAuthenticationCapsMsg; -+ -+#define sz_rfbAuthenticationCapsMsg 4 -+ -+/*----------------------------------------------------------------------------- -+ * Authentication Scheme Request (protocol version 3.7t) -+ * -+ * If the list of authentication capabilities sent by the server was not empty, -+ * the client should reply with a 32-bit code specifying a particular -+ * authentication scheme. The following codes are supported. -+ */ -+ -+#define rfbAuthNone 1 -+#define rfbAuthVNC 2 -+#define rfbAuthUnixLogin 129 -+#define rfbAuthExternal 130 -+ -+#define sig_rfbAuthNone "NOAUTH__" -+#define sig_rfbAuthVNC "VNCAUTH_" -+#define sig_rfbAuthUnixLogin "ULGNAUTH" -+#define sig_rfbAuthExternal "XTRNAUTH" -+ -+ -+/*----------------------------------------------------------------------------- -+ * Standard VNC Authentication (all protocol versions) -+ * -+ * Standard authentication result codes are defined below. -+ */ -+ -+#define rfbVncAuthOK 0 -+#define rfbVncAuthFailed 1 -+#define rfbVncAuthTooMany 2 -+ -+ -+/*----------------------------------------------------------------------------- -+ * Client Initialisation Message -+ * -+ * Once the client and server are sure that they're happy to talk to one -+ * another, the client sends an initialisation message. At present this -+ * message only consists of a boolean indicating whether the server should try -+ * to share the desktop by leaving other clients connected, or give exclusive -+ * access to this client by disconnecting all other clients. -+ */ -+ -+typedef struct _rfbClientInitMsg { -+ CARD8 shared; -+} rfbClientInitMsg; -+ -+#define sz_rfbClientInitMsg 1 -+ -+ -+/*----------------------------------------------------------------------------- -+ * Server Initialisation Message -+ * -+ * After the client initialisation message, the server sends one of its own. -+ * This tells the client the width and height of the server's framebuffer, -+ * its pixel format and the name associated with the desktop. -+ */ -+ -+typedef struct _rfbServerInitMsg { -+ CARD16 framebufferWidth; -+ CARD16 framebufferHeight; -+ rfbPixelFormat format; /* the server's preferred pixel format */ -+ CARD32 nameLength; -+ /* followed by char name[nameLength] */ -+} rfbServerInitMsg; -+ -+#define sz_rfbServerInitMsg (8 + sz_rfbPixelFormat) -+ -+ -+/*----------------------------------------------------------------------------- -+ * Server Interaction Capabilities Message (protocol version 3.7t) -+ * -+ * In the protocol version 3.7t, the server informs the client what message -+ * types it supports in addition to ones defined in the protocol version 3.7. -+ * Also, the server sends the list of all supported encodings (note that it's -+ * not necessary to advertise the "raw" encoding sinse it MUST be supported in -+ * RFB 3.x protocols). -+ * -+ * This data immediately follows the server initialisation message. -+ */ -+ -+typedef struct _rfbInteractionCapsMsg { -+ CARD16 nServerMessageTypes; -+ CARD16 nClientMessageTypes; -+ CARD16 nEncodingTypes; -+ CARD16 pad; /* reserved, must be 0 */ -+ /* followed by nServerMessageTypes * rfbCapabilityInfo structures */ -+ /* followed by nClientMessageTypes * rfbCapabilityInfo structures */ -+} rfbInteractionCapsMsg; -+ -+#define sz_rfbInteractionCapsMsg 8 -+ -+ -+/* -+ * Following the server initialisation message it's up to the client to send -+ * whichever protocol messages it wants. Typically it will send a -+ * SetPixelFormat message and a SetEncodings message, followed by a -+ * FramebufferUpdateRequest. From then on the server will send -+ * FramebufferUpdate messages in response to the client's -+ * FramebufferUpdateRequest messages. The client should send -+ * FramebufferUpdateRequest messages with incremental set to true when it has -+ * finished processing one FramebufferUpdate and is ready to process another. -+ * With a fast client, the rate at which FramebufferUpdateRequests are sent -+ * should be regulated to avoid hogging the network. -+ */ -+ -+ -+ -+/***************************************************************************** -+ * -+ * Message types -+ * -+ *****************************************************************************/ -+ -+/* server -> client */ -+ -+#define rfbFramebufferUpdate 0 -+#define rfbSetColourMapEntries 1 -+#define rfbBell 2 -+#define rfbServerCutText 3 -+/* Chromium extensions, use higher values */ -+#define rfbChromiumStart 50 -+#define rfbChromiumMoveResizeWindow 51 -+#define rfbChromiumClipList 52 -+#define rfbChromiumWindowShow 53 -+ -+#define rfbFileListData 130 -+#define rfbFileDownloadData 131 -+#define rfbFileUploadCancel 132 -+#define rfbFileDownloadFailed 133 -+ -+/* signatures for non-standard messages */ -+#define sig_rfbFileListData "FTS_LSDT" -+#define sig_rfbFileDownloadData "FTS_DNDT" -+#define sig_rfbFileUploadCancel "FTS_UPCN" -+#define sig_rfbFileDownloadFailed "FTS_DNFL" -+ -+ -+/* client -> server */ -+ -+#define rfbSetPixelFormat 0 -+#define rfbFixColourMapEntries 1 /* not currently supported */ -+#define rfbSetEncodings 2 -+#define rfbFramebufferUpdateRequest 3 -+#define rfbKeyEvent 4 -+#define rfbPointerEvent 5 -+#define rfbClientCutText 6 -+/* Chromium extensions, use higher values */ -+#define rfbChromiumStop 50 -+#define rfbChromiumExpose 51 -+ -+#define rfbFileListRequest 130 -+#define rfbFileDownloadRequest 131 -+#define rfbFileUploadRequest 132 -+#define rfbFileUploadData 133 -+#define rfbFileDownloadCancel 134 -+#define rfbFileUploadFailed 135 -+#define rfbFileCreateDirRequest 136 -+ -+/* signatures for non-standard messages */ -+#define sig_rfbFileListRequest "FTC_LSRQ" -+#define sig_rfbFileDownloadRequest "FTC_DNRQ" -+#define sig_rfbFileUploadRequest "FTC_UPRQ" -+#define sig_rfbFileUploadData "FTC_UPDT" -+#define sig_rfbFileDownloadCancel "FTC_DNCN" -+#define sig_rfbFileUploadFailed "FTC_UPFL" -+#define sig_rfbFileCreateDirRequest "FTC_FCDR" -+ -+/***************************************************************************** -+ * -+ * Encoding types -+ * -+ *****************************************************************************/ -+ -+#define rfbEncodingRaw 0 -+#define rfbEncodingCopyRect 1 -+#define rfbEncodingRRE 2 -+#define rfbEncodingCoRRE 4 -+#define rfbEncodingHextile 5 -+#define rfbEncodingZlib 6 -+#define rfbEncodingTight 7 -+#define rfbEncodingZlibHex 8 -+ -+/* signatures for basic encoding types */ -+#define sig_rfbEncodingRaw "RAW_____" -+#define sig_rfbEncodingCopyRect "COPYRECT" -+#define sig_rfbEncodingRRE "RRE_____" -+#define sig_rfbEncodingCoRRE "CORRE___" -+#define sig_rfbEncodingHextile "HEXTILE_" -+#define sig_rfbEncodingZlib "ZLIB____" -+#define sig_rfbEncodingTight "TIGHT___" -+#define sig_rfbEncodingZlibHex "ZLIBHEX_" -+#define sig_rfbEncodingChromium "CHROMIUM" -+ -+/* -+ * Special encoding numbers: -+ * 0xFFFFFF00 .. 0xFFFFFF0F -- encoding-specific compression levels; -+ * 0xFFFFFF10 .. 0xFFFFFF1F -- mouse cursor shape data; -+ * 0xFFFFFF20 .. 0xFFFFFF2F -- various protocol extensions; -+ * 0xFFFFFF30 .. 0xFFFFFFDF -- not allocated yet; -+ * 0xFFFFFFE0 .. 0xFFFFFFEF -- quality level for JPEG compressor; -+ * 0xFFFFFFF0 .. 0xFFFFFFFF -- not allocated yet. -+ */ -+ -+#define rfbEncodingCompressLevel0 0xFFFFFF00 -+#define rfbEncodingCompressLevel1 0xFFFFFF01 -+#define rfbEncodingCompressLevel2 0xFFFFFF02 -+#define rfbEncodingCompressLevel3 0xFFFFFF03 -+#define rfbEncodingCompressLevel4 0xFFFFFF04 -+#define rfbEncodingCompressLevel5 0xFFFFFF05 -+#define rfbEncodingCompressLevel6 0xFFFFFF06 -+#define rfbEncodingCompressLevel7 0xFFFFFF07 -+#define rfbEncodingCompressLevel8 0xFFFFFF08 -+#define rfbEncodingCompressLevel9 0xFFFFFF09 -+ -+#define rfbEncodingXCursor 0xFFFFFF10 -+#define rfbEncodingRichCursor 0xFFFFFF11 -+#define rfbEncodingPointerPos 0xFFFFFF18 -+ -+#define rfbEncodingLastRect 0xFFFFFF20 -+#define rfbEncodingNewFBSize 0xFFFFFF21 -+#define rfbEncodingChromium 0xFFFFFF2F -+#define rfbEncodingChromium2 0xFFFFFF30 -+ -+#define rfbEncodingQualityLevel0 0xFFFFFFE0 -+#define rfbEncodingQualityLevel1 0xFFFFFFE1 -+#define rfbEncodingQualityLevel2 0xFFFFFFE2 -+#define rfbEncodingQualityLevel3 0xFFFFFFE3 -+#define rfbEncodingQualityLevel4 0xFFFFFFE4 -+#define rfbEncodingQualityLevel5 0xFFFFFFE5 -+#define rfbEncodingQualityLevel6 0xFFFFFFE6 -+#define rfbEncodingQualityLevel7 0xFFFFFFE7 -+#define rfbEncodingQualityLevel8 0xFFFFFFE8 -+#define rfbEncodingQualityLevel9 0xFFFFFFE9 -+ -+/* signatures for "fake" encoding types */ -+#define sig_rfbEncodingCompressLevel0 "COMPRLVL" -+#define sig_rfbEncodingXCursor "X11CURSR" -+#define sig_rfbEncodingRichCursor "RCHCURSR" -+#define sig_rfbEncodingPointerPos "POINTPOS" -+#define sig_rfbEncodingLastRect "LASTRECT" -+#define sig_rfbEncodingNewFBSize "NEWFBSIZ" -+#define sig_rfbEncodingQualityLevel0 "JPEGQLVL" -+ -+ -+/***************************************************************************** -+ * -+ * Server -> client message definitions -+ * -+ *****************************************************************************/ -+ -+ -+/*----------------------------------------------------------------------------- -+ * FramebufferUpdate - a block of rectangles to be copied to the framebuffer. -+ * -+ * This message consists of a header giving the number of rectangles of pixel -+ * data followed by the rectangles themselves. The header is padded so that -+ * together with the type byte it is an exact multiple of 4 bytes (to help -+ * with alignment of 32-bit pixels): -+ */ -+ -+typedef struct _rfbFramebufferUpdateMsg { -+ CARD8 type; /* always rfbFramebufferUpdate */ -+ CARD8 pad; -+ CARD16 nRects; -+ /* followed by nRects rectangles */ -+} rfbFramebufferUpdateMsg; -+ -+#define sz_rfbFramebufferUpdateMsg 4 -+ -+/* -+ * Each rectangle of pixel data consists of a header describing the position -+ * and size of the rectangle and a type word describing the encoding of the -+ * pixel data, followed finally by the pixel data. Note that if the client has -+ * not sent a SetEncodings message then it will only receive raw pixel data. -+ * Also note again that this structure is a multiple of 4 bytes. -+ */ -+ -+typedef struct _rfbFramebufferUpdateRectHeader { -+ rfbRectangle r; -+ CARD32 encoding; /* one of the encoding types rfbEncoding... */ -+} rfbFramebufferUpdateRectHeader; -+ -+#define sz_rfbFramebufferUpdateRectHeader (sz_rfbRectangle + 4) -+ -+ -+/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+ * Raw Encoding. Pixels are sent in top-to-bottom scanline order, -+ * left-to-right within a scanline with no padding in between. -+ */ -+ -+ -+/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+ * CopyRect Encoding. The pixels are specified simply by the x and y position -+ * of the source rectangle. -+ */ -+ -+typedef struct _rfbCopyRect { -+ CARD16 srcX; -+ CARD16 srcY; -+} rfbCopyRect; -+ -+#define sz_rfbCopyRect 4 -+ -+ -+/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+ * RRE - Rise-and-Run-length Encoding. We have an rfbRREHeader structure -+ * giving the number of subrectangles following. Finally the data follows in -+ * the form [...] where each is -+ * []. -+ */ -+ -+typedef struct _rfbRREHeader { -+ CARD32 nSubrects; -+} rfbRREHeader; -+ -+#define sz_rfbRREHeader 4 -+ -+ -+/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+ * CoRRE - Compact RRE Encoding. We have an rfbRREHeader structure giving -+ * the number of subrectangles following. Finally the data follows in the form -+ * [...] where each is -+ * []. This means that -+ * the whole rectangle must be at most 255x255 pixels. -+ */ -+ -+typedef struct _rfbCoRRERectangle { -+ CARD8 x; -+ CARD8 y; -+ CARD8 w; -+ CARD8 h; -+} rfbCoRRERectangle; -+ -+#define sz_rfbCoRRERectangle 4 -+ -+ -+/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+ * Hextile Encoding. The rectangle is divided up into "tiles" of 16x16 pixels, -+ * starting at the top left going in left-to-right, top-to-bottom order. If -+ * the width of the rectangle is not an exact multiple of 16 then the width of -+ * the last tile in each row will be correspondingly smaller. Similarly if the -+ * height is not an exact multiple of 16 then the height of each tile in the -+ * final row will also be smaller. Each tile begins with a "subencoding" type -+ * byte, which is a mask made up of a number of bits. If the Raw bit is set -+ * then the other bits are irrelevant; w*h pixel values follow (where w and h -+ * are the width and height of the tile). Otherwise the tile is encoded in a -+ * similar way to RRE, except that the position and size of each subrectangle -+ * can be specified in just two bytes. The other bits in the mask are as -+ * follows: -+ * -+ * BackgroundSpecified - if set, a pixel value follows which specifies -+ * the background colour for this tile. The first non-raw tile in a -+ * rectangle must have this bit set. If this bit isn't set then the -+ * background is the same as the last tile. -+ * -+ * ForegroundSpecified - if set, a pixel value follows which specifies -+ * the foreground colour to be used for all subrectangles in this tile. -+ * If this bit is set then the SubrectsColoured bit must be zero. -+ * -+ * AnySubrects - if set, a single byte follows giving the number of -+ * subrectangles following. If not set, there are no subrectangles (i.e. -+ * the whole tile is just solid background colour). -+ * -+ * SubrectsColoured - if set then each subrectangle is preceded by a pixel -+ * value giving the colour of that subrectangle. If not set, all -+ * subrectangles are the same colour, the foreground colour; if the -+ * ForegroundSpecified bit wasn't set then the foreground is the same as -+ * the last tile. -+ * -+ * The position and size of each subrectangle is specified in two bytes. The -+ * Pack macros below can be used to generate the two bytes from x, y, w, h, -+ * and the Extract macros can be used to extract the x, y, w, h values from -+ * the two bytes. -+ */ -+ -+#define rfbHextileRaw (1 << 0) -+#define rfbHextileBackgroundSpecified (1 << 1) -+#define rfbHextileForegroundSpecified (1 << 2) -+#define rfbHextileAnySubrects (1 << 3) -+#define rfbHextileSubrectsColoured (1 << 4) -+ -+#define rfbHextilePackXY(x,y) (((x) << 4) | (y)) -+#define rfbHextilePackWH(w,h) ((((w)-1) << 4) | ((h)-1)) -+#define rfbHextileExtractX(byte) ((byte) >> 4) -+#define rfbHextileExtractY(byte) ((byte) & 0xf) -+#define rfbHextileExtractW(byte) (((byte) >> 4) + 1) -+#define rfbHextileExtractH(byte) (((byte) & 0xf) + 1) -+ -+/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+ * ZLIB - zlib compression Encoding. We have an rfbZlibHeader structure -+ * giving the number of bytes to follow. Finally the data follows in -+ * zlib compressed format. -+ */ -+ -+typedef struct _rfbZlibHeader { -+ CARD32 nBytes; -+} rfbZlibHeader; -+ -+#define sz_rfbZlibHeader 4 -+ -+ -+/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+ * Tight Encoding. -+ * -+ *-- The first byte of each Tight-encoded rectangle is a "compression control -+ * byte". Its format is as follows (bit 0 is the least significant one): -+ * -+ * bit 0: if 1, then compression stream 0 should be reset; -+ * bit 1: if 1, then compression stream 1 should be reset; -+ * bit 2: if 1, then compression stream 2 should be reset; -+ * bit 3: if 1, then compression stream 3 should be reset; -+ * bits 7-4: if 1000 (0x08), then the compression type is "fill", -+ * if 1001 (0x09), then the compression type is "jpeg", -+ * if 0xxx, then the compression type is "basic", -+ * values greater than 1001 are not valid. -+ * -+ * If the compression type is "basic", then bits 6..4 of the -+ * compression control byte (those xxx in 0xxx) specify the following: -+ * -+ * bits 5-4: decimal representation is the index of a particular zlib -+ * stream which should be used for decompressing the data; -+ * bit 6: if 1, then a "filter id" byte is following this byte. -+ * -+ *-- The data that follows after the compression control byte described -+ * above depends on the compression type ("fill", "jpeg" or "basic"). -+ * -+ *-- If the compression type is "fill", then the only pixel value follows, in -+ * client pixel format (see NOTE 1). This value applies to all pixels of the -+ * rectangle. -+ * -+ *-- If the compression type is "jpeg", the following data stream looks like -+ * this: -+ * -+ * 1..3 bytes: data size (N) in compact representation; -+ * N bytes: JPEG image. -+ * -+ * Data size is compactly represented in one, two or three bytes, according -+ * to the following scheme: -+ * -+ * 0xxxxxxx (for values 0..127) -+ * 1xxxxxxx 0yyyyyyy (for values 128..16383) -+ * 1xxxxxxx 1yyyyyyy zzzzzzzz (for values 16384..4194303) -+ * -+ * Here each character denotes one bit, xxxxxxx are the least significant 7 -+ * bits of the value (bits 0-6), yyyyyyy are bits 7-13, and zzzzzzzz are the -+ * most significant 8 bits (bits 14-21). For example, decimal value 10000 -+ * should be represented as two bytes: binary 10010000 01001110, or -+ * hexadecimal 90 4E. -+ * -+ *-- If the compression type is "basic" and bit 6 of the compression control -+ * byte was set to 1, then the next (second) byte specifies "filter id" which -+ * tells the decoder what filter type was used by the encoder to pre-process -+ * pixel data before the compression. The "filter id" byte can be one of the -+ * following: -+ * -+ * 0: no filter ("copy" filter); -+ * 1: "palette" filter; -+ * 2: "gradient" filter. -+ * -+ *-- If bit 6 of the compression control byte is set to 0 (no "filter id" -+ * byte), or if the filter id is 0, then raw pixel values in the client -+ * format (see NOTE 1) will be compressed. See below details on the -+ * compression. -+ * -+ *-- The "gradient" filter pre-processes pixel data with a simple algorithm -+ * which converts each color component to a difference between a "predicted" -+ * intensity and the actual intensity. Such a technique does not affect -+ * uncompressed data size, but helps to compress photo-like images better. -+ * Pseudo-code for converting intensities to differences is the following: -+ * -+ * P[i,j] := V[i-1,j] + V[i,j-1] - V[i-1,j-1]; -+ * if (P[i,j] < 0) then P[i,j] := 0; -+ * if (P[i,j] > MAX) then P[i,j] := MAX; -+ * D[i,j] := V[i,j] - P[i,j]; -+ * -+ * Here V[i,j] is the intensity of a color component for a pixel at -+ * coordinates (i,j). MAX is the maximum value of intensity for a color -+ * component. -+ * -+ *-- The "palette" filter converts true-color pixel data to indexed colors -+ * and a palette which can consist of 2..256 colors. If the number of colors -+ * is 2, then each pixel is encoded in 1 bit, otherwise 8 bits is used to -+ * encode one pixel. 1-bit encoding is performed such way that the most -+ * significant bits correspond to the leftmost pixels, and each raw of pixels -+ * is aligned to the byte boundary. When "palette" filter is used, the -+ * palette is sent before the pixel data. The palette begins with an unsigned -+ * byte which value is the number of colors in the palette minus 1 (i.e. 1 -+ * means 2 colors, 255 means 256 colors in the palette). Then follows the -+ * palette itself which consist of pixel values in client pixel format (see -+ * NOTE 1). -+ * -+ *-- The pixel data is compressed using the zlib library. But if the data -+ * size after applying the filter but before the compression is less then 12, -+ * then the data is sent as is, uncompressed. Four separate zlib streams -+ * (0..3) can be used and the decoder should read the actual stream id from -+ * the compression control byte (see NOTE 2). -+ * -+ * If the compression is not used, then the pixel data is sent as is, -+ * otherwise the data stream looks like this: -+ * -+ * 1..3 bytes: data size (N) in compact representation; -+ * N bytes: zlib-compressed data. -+ * -+ * Data size is compactly represented in one, two or three bytes, just like -+ * in the "jpeg" compression method (see above). -+ * -+ *-- NOTE 1. If the color depth is 24, and all three color components are -+ * 8-bit wide, then one pixel in Tight encoding is always represented by -+ * three bytes, where the first byte is red component, the second byte is -+ * green component, and the third byte is blue component of the pixel color -+ * value. This applies to colors in palettes as well. -+ * -+ *-- NOTE 2. The decoder must reset compression streams' states before -+ * decoding the rectangle, if some of bits 0,1,2,3 in the compression control -+ * byte are set to 1. Note that the decoder must reset zlib streams even if -+ * the compression type is "fill" or "jpeg". -+ * -+ *-- NOTE 3. The "gradient" filter and "jpeg" compression may be used only -+ * when bits-per-pixel value is either 16 or 32, not 8. -+ * -+ *-- NOTE 4. The width of any Tight-encoded rectangle cannot exceed 2048 -+ * pixels. If a rectangle is wider, it must be split into several rectangles -+ * and each one should be encoded separately. -+ * -+ */ -+ -+#define rfbTightExplicitFilter 0x04 -+#define rfbTightFill 0x08 -+#define rfbTightJpeg 0x09 -+#define rfbTightMaxSubencoding 0x09 -+ -+/* Filters to improve compression efficiency */ -+#define rfbTightFilterCopy 0x00 -+#define rfbTightFilterPalette 0x01 -+#define rfbTightFilterGradient 0x02 -+ -+ -+/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+ * ZLIBHEX - zlib compressed Hextile Encoding. Essentially, this is the -+ * hextile encoding with zlib compression on the tiles that can not be -+ * efficiently encoded with one of the other hextile subencodings. The -+ * new zlib subencoding uses two bytes to specify the length of the -+ * compressed tile and then the compressed data follows. As with the -+ * raw sub-encoding, the zlib subencoding invalidates the other -+ * values, if they are also set. -+ */ -+ -+#define rfbHextileZlibRaw (1 << 5) -+#define rfbHextileZlibHex (1 << 6) -+ -+ -+/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+ * XCursor encoding. This is a special encoding used to transmit X-style -+ * cursor shapes from server to clients. Note that for this encoding, -+ * coordinates in rfbFramebufferUpdateRectHeader structure hold hotspot -+ * position (r.x, r.y) and cursor size (r.w, r.h). If (w * h != 0), two RGB -+ * samples are sent after header in the rfbXCursorColors structure. They -+ * denote foreground and background colors of the cursor. If a client -+ * supports only black-and-white cursors, it should ignore these colors and -+ * assume that foreground is black and background is white. Next, two bitmaps -+ * (1 bits per pixel) follow: first one with actual data (value 0 denotes -+ * background color, value 1 denotes foreground color), second one with -+ * transparency data (bits with zero value mean that these pixels are -+ * transparent). Both bitmaps represent cursor data in a byte stream, from -+ * left to right, from top to bottom, and each row is byte-aligned. Most -+ * significant bits correspond to leftmost pixels. The number of bytes in -+ * each row can be calculated as ((w + 7) / 8). If (w * h == 0), cursor -+ * should be hidden (or default local cursor should be set by the client). -+ */ -+ -+typedef struct _rfbXCursorColors { -+ CARD8 foreRed; -+ CARD8 foreGreen; -+ CARD8 foreBlue; -+ CARD8 backRed; -+ CARD8 backGreen; -+ CARD8 backBlue; -+} rfbXCursorColors; -+ -+#define sz_rfbXCursorColors 6 -+ -+ -+/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+ * RichCursor encoding. This is a special encoding used to transmit cursor -+ * shapes from server to clients. It is similar to the XCursor encoding but -+ * uses client pixel format instead of two RGB colors to represent cursor -+ * image. For this encoding, coordinates in rfbFramebufferUpdateRectHeader -+ * structure hold hotspot position (r.x, r.y) and cursor size (r.w, r.h). -+ * After header, two pixmaps follow: first one with cursor image in current -+ * client pixel format (like in raw encoding), second with transparency data -+ * (1 bit per pixel, exactly the same format as used for transparency bitmap -+ * in the XCursor encoding). If (w * h == 0), cursor should be hidden (or -+ * default local cursor should be set by the client). -+ */ -+ -+ -+/*----------------------------------------------------------------------------- -+ * SetColourMapEntries - these messages are only sent if the pixel -+ * format uses a "colour map" (i.e. trueColour false) and the client has not -+ * fixed the entire colour map using FixColourMapEntries. In addition they -+ * will only start being sent after the client has sent its first -+ * FramebufferUpdateRequest. So if the client always tells the server to use -+ * trueColour then it never needs to process this type of message. -+ */ -+ -+typedef struct _rfbSetColourMapEntriesMsg { -+ CARD8 type; /* always rfbSetColourMapEntries */ -+ CARD8 redIndex; /* used to be pad, but used for DirectColor */ -+ CARD16 firstColour; -+ CARD16 nColours; -+ -+ /* Followed by nColours * 3 * CARD16 -+ r1, g1, b1, r2, g2, b2, r3, g3, b3, ..., rn, bn, gn */ -+ -+} rfbSetColourMapEntriesMsg; -+ -+#define sz_rfbSetColourMapEntriesMsg 6 -+ -+ -+ -+/*----------------------------------------------------------------------------- -+ * Bell - ring a bell on the client if it has one. -+ */ -+ -+typedef struct _rfbBellMsg { -+ CARD8 type; /* always rfbBell */ -+} rfbBellMsg; -+ -+#define sz_rfbBellMsg 1 -+ -+ -+ -+/*----------------------------------------------------------------------------- -+ * ServerCutText - the server has new text in its cut buffer. -+ */ -+ -+typedef struct _rfbServerCutTextMsg { -+ CARD8 type; /* always rfbServerCutText */ -+ CARD8 pad1; -+ CARD16 pad2; -+ CARD32 length; -+ /* followed by char text[length] */ -+} rfbServerCutTextMsg; -+ -+#define sz_rfbServerCutTextMsg 8 -+ -+/*----------------------------------------------------------------------------- -+ * ChromiumStart - a port number for the crserver -+ */ -+ -+typedef struct { -+ CARD8 type; /* always rfbChromiumStart */ -+ CARD8 pad1; -+ CARD16 pad2; -+ CARD32 crServerPort; -+ CARD32 mothershipPort; -+} rfbChromiumStartMsg; -+ -+#define sz_rfbChromiumStartMsg 12 -+ -+ -+/*----------------------------------------------------------------------------- -+ * ChromiumMoveResizeWindow - move a chromium window -+ */ -+ -+typedef struct { -+ CARD8 type; /* always rfbChromiumMoveResizeWindow */ -+ CARD8 pad1; -+ CARD16 pad2; -+ CARD32 winid; -+ CARD32 x; -+ CARD32 y; -+ CARD32 w; -+ CARD32 h; -+} rfbChromiumMoveResizeWindowMsg; -+ -+#define sz_rfbChromiumMoveResizeWindowMsg 24 -+ -+/*----------------------------------------------------------------------------- -+ * ChromiumClipList - send clip list -+ */ -+ -+typedef struct { -+ CARD8 type; /* always rfbChromiumClipList */ -+ CARD8 pad1; -+ CARD16 pad2; -+ CARD32 winid; -+ CARD32 length; -+} rfbChromiumClipListMsg; -+ -+#define sz_rfbChromiumClipListMsg 12 -+ -+/*----------------------------------------------------------------------------- -+ * ChromiumWindowShow - map or unmap a window -+ */ -+ -+typedef struct { -+ CARD8 type; /* always rfbChromiumWindowShow */ -+ CARD8 pad1; -+ CARD16 pad2; -+ CARD32 winid; -+ CARD32 show; -+} rfbChromiumWindowShowMsg; -+ -+#define sz_rfbChromiumWindowShowMsg 12 -+ -+/*----------------------------------------------------------------------------- -+ * FileListData -+ */ -+ -+typedef struct _rfbFileListDataMsg { -+ CARD8 type; -+ CARD8 flags; -+ CARD16 numFiles; -+ CARD16 dataSize; -+ CARD16 compressedSize; -+ /* Followed by SizeData[numFiles] */ -+ /* Followed by Filenames[compressedSize] */ -+} rfbFileListDataMsg; -+ -+#define sz_rfbFileListDataMsg 8 -+ -+/*----------------------------------------------------------------------------- -+ * FileDownloadData -+ */ -+ -+typedef struct _rfbFileDownloadDataMsg { -+ CARD8 type; -+ CARD8 compressLevel; -+ CARD16 realSize; -+ CARD16 compressedSize; -+ /* Followed by File[copressedSize] */ -+} rfbFileDownloadDataMsg; -+ -+#define sz_rfbFileDownloadDataMsg 6 -+ -+ -+/*----------------------------------------------------------------------------- -+ * FileUploadCancel -+ */ -+ -+typedef struct _rfbFileUploadCancelMsg { -+ CARD8 type; -+ CARD8 unused; -+ CARD16 reasonLen; -+ /* Followed by reason[reasonLen] */ -+} rfbFileUploadCancelMsg; -+ -+#define sz_rfbFileUploadCancelMsg 4 -+ -+/*----------------------------------------------------------------------------- -+ * FileDownloadFailed -+ */ -+ -+typedef struct _rfbFileDownloadFailedMsg { -+ CARD8 type; -+ CARD8 unused; -+ CARD16 reasonLen; -+ /* Followed by reason[reasonLen] */ -+} rfbFileDownloadFailedMsg; -+ -+#define sz_rfbFileDownloadFailedMsg 4 -+ -+/*----------------------------------------------------------------------------- -+ * Union of all server->client messages. -+ */ -+ -+typedef union _rfbServerToClientMsg { -+ CARD8 type; -+ rfbFramebufferUpdateMsg fu; -+ rfbSetColourMapEntriesMsg scme; -+ rfbBellMsg b; -+ rfbServerCutTextMsg sct; -+ rfbFileListDataMsg fld; -+ rfbFileDownloadDataMsg fdd; -+ rfbFileUploadCancelMsg fuc; -+ rfbFileDownloadFailedMsg fdf; -+ rfbChromiumStartMsg scd; -+ rfbChromiumMoveResizeWindowMsg scm; -+ rfbChromiumClipListMsg sccl; -+ rfbChromiumWindowShowMsg scws; -+} rfbServerToClientMsg; -+ -+ -+ -+/***************************************************************************** -+ * -+ * Message definitions (client -> server) -+ * -+ *****************************************************************************/ -+ -+ -+/*----------------------------------------------------------------------------- -+ * SetPixelFormat - tell the RFB server the format in which the client wants -+ * pixels sent. -+ */ -+ -+typedef struct _rfbSetPixelFormatMsg { -+ CARD8 type; /* always rfbSetPixelFormat */ -+ CARD8 pad1; -+ CARD16 pad2; -+ rfbPixelFormat format; -+} rfbSetPixelFormatMsg; -+ -+#define sz_rfbSetPixelFormatMsg (sz_rfbPixelFormat + 4) -+ -+ -+/*----------------------------------------------------------------------------- -+ * FixColourMapEntries - when the pixel format uses a "colour map", fix -+ * read-only colour map entries. -+ * -+ * ***************** NOT CURRENTLY SUPPORTED ***************** -+ */ -+ -+typedef struct _rfbFixColourMapEntriesMsg { -+ CARD8 type; /* always rfbFixColourMapEntries */ -+ CARD8 pad; -+ CARD16 firstColour; -+ CARD16 nColours; -+ -+ /* Followed by nColours * 3 * CARD16 -+ r1, g1, b1, r2, g2, b2, r3, g3, b3, ..., rn, bn, gn */ -+ -+} rfbFixColourMapEntriesMsg; -+ -+#define sz_rfbFixColourMapEntriesMsg 6 -+ -+ -+/*----------------------------------------------------------------------------- -+ * SetEncodings - tell the RFB server which encoding types we accept. Put them -+ * in order of preference, if we have any. We may always receive raw -+ * encoding, even if we don't specify it here. -+ */ -+ -+typedef struct _rfbSetEncodingsMsg { -+ CARD8 type; /* always rfbSetEncodings */ -+ CARD8 pad; -+ CARD16 nEncodings; -+ /* followed by nEncodings * CARD32 encoding types */ -+} rfbSetEncodingsMsg; -+ -+#define sz_rfbSetEncodingsMsg 4 -+ -+ -+/*----------------------------------------------------------------------------- -+ * FramebufferUpdateRequest - request for a framebuffer update. If incremental -+ * is true then the client just wants the changes since the last update. If -+ * false then it wants the whole of the specified rectangle. -+ */ -+ -+typedef struct _rfbFramebufferUpdateRequestMsg { -+ CARD8 type; /* always rfbFramebufferUpdateRequest */ -+ CARD8 incremental; -+ CARD16 x; -+ CARD16 y; -+ CARD16 w; -+ CARD16 h; -+} rfbFramebufferUpdateRequestMsg; -+ -+#define sz_rfbFramebufferUpdateRequestMsg 10 -+ -+ -+/*----------------------------------------------------------------------------- -+ * KeyEvent - key press or release -+ * -+ * Keys are specified using the "keysym" values defined by the X Window System. -+ * For most ordinary keys, the keysym is the same as the corresponding ASCII -+ * value. Other common keys are: -+ * -+ * BackSpace 0xff08 -+ * Tab 0xff09 -+ * Return or Enter 0xff0d -+ * Escape 0xff1b -+ * Insert 0xff63 -+ * Delete 0xffff -+ * Home 0xff50 -+ * End 0xff57 -+ * Page Up 0xff55 -+ * Page Down 0xff56 -+ * Left 0xff51 -+ * Up 0xff52 -+ * Right 0xff53 -+ * Down 0xff54 -+ * F1 0xffbe -+ * F2 0xffbf -+ * ... ... -+ * F12 0xffc9 -+ * Shift 0xffe1 -+ * Control 0xffe3 -+ * Meta 0xffe7 -+ * Alt 0xffe9 -+ */ -+ -+typedef struct _rfbKeyEventMsg { -+ CARD8 type; /* always rfbKeyEvent */ -+ CARD8 down; /* true if down (press), false if up */ -+ CARD16 pad; -+ CARD32 key; /* key is specified as an X keysym */ -+} rfbKeyEventMsg; -+ -+#define sz_rfbKeyEventMsg 8 -+ -+ -+/*----------------------------------------------------------------------------- -+ * PointerEvent - mouse/pen move and/or button press. -+ */ -+ -+typedef struct _rfbPointerEventMsg { -+ CARD8 type; /* always rfbPointerEvent */ -+ CARD8 buttonMask; /* bits 0-7 are buttons 1-8, 0=up, 1=down */ -+ CARD16 x; -+ CARD16 y; -+} rfbPointerEventMsg; -+ -+#define rfbButton1Mask 1 -+#define rfbButton2Mask 2 -+#define rfbButton3Mask 4 -+#define rfbButton4Mask 8 -+#define rfbButton5Mask 16 -+ -+#define sz_rfbPointerEventMsg 6 -+ -+ -+ -+/*----------------------------------------------------------------------------- -+ * ClientCutText - the client has new text in its cut buffer. -+ */ -+ -+typedef struct _rfbClientCutTextMsg { -+ CARD8 type; /* always rfbClientCutText */ -+ CARD8 pad1; -+ CARD16 pad2; -+ CARD32 length; -+ /* followed by char text[length] */ -+} rfbClientCutTextMsg; -+ -+#define sz_rfbClientCutTextMsg 8 -+ -+/*----------------------------------------------------------------------------- -+ * FileListRequest -+ */ -+ -+typedef struct _rfbFileListRequestMsg { -+ CARD8 type; -+ CARD8 flags; -+ CARD16 dirNameSize; -+ /* Followed by char Dirname[dirNameSize] */ -+} rfbFileListRequestMsg; -+ -+#define sz_rfbFileListRequestMsg 4 -+ -+/*----------------------------------------------------------------------------- -+ * FileDownloadRequest -+ */ -+ -+typedef struct _rfbFileDownloadRequestMsg { -+ CARD8 type; -+ CARD8 compressedLevel; -+ CARD16 fNameSize; -+ CARD32 position; -+ /* Followed by char Filename[fNameSize] */ -+} rfbFileDownloadRequestMsg; -+ -+#define sz_rfbFileDownloadRequestMsg 8 -+ -+/*----------------------------------------------------------------------------- -+ * FileUploadRequest -+ */ -+ -+typedef struct _rfbFileUploadRequestMsg { -+ CARD8 type; -+ CARD8 compressedLevel; -+ CARD16 fNameSize; -+ CARD32 position; -+ /* Followed by char Filename[fNameSize] */ -+} rfbFileUploadRequestMsg; -+ -+#define sz_rfbFileUploadRequestMsg 8 -+ -+ -+/*----------------------------------------------------------------------------- -+ * FileUploadData -+ */ -+ -+typedef struct _rfbFileUploadDataMsg { -+ CARD8 type; -+ CARD8 compressedLevel; -+ CARD16 realSize; -+ CARD16 compressedSize; -+ /* Followed by File[compressedSize] */ -+} rfbFileUploadDataMsg; -+ -+#define sz_rfbFileUploadDataMsg 8 -+ -+/*----------------------------------------------------------------------------- -+ * FileDownloadCancel -+ */ -+ -+typedef struct _rfbFileDownloadCancelMsg { -+ CARD8 type; -+ CARD8 unused; -+ CARD16 reasonLen; -+ /* Followed by reason[reasonLen] */ -+} rfbFileDownloadCancelMsg; -+ -+#define sz_rfbFileDownloadCancelMsg 4 -+ -+/*----------------------------------------------------------------------------- -+ * FileUploadFailed -+ */ -+ -+typedef struct _rfbFileUploadFailedMsg { -+ CARD8 type; -+ CARD8 unused; -+ CARD16 reasonLen; -+ /* Followed by reason[reasonLen] */ -+} rfbFileUploadFailedMsg; -+ -+#define sz_rfbFileUploadFailedMsg 4 -+ -+/*----------------------------------------------------------------------------- -+ * FileCreateDirRequest -+ */ -+ -+typedef struct _rfbFileCreateDirRequestMsg { -+ CARD8 type; -+ CARD8 unused; -+ CARD16 dNameLen; -+ CARD32 dModTime; -+ /* Followed by dName[dNameLen] */ -+} rfbFileCreateDirRequestMsg; -+ -+#define sz_rfbFileCreateDirRequestMsg 8 -+ -+/*----------------------------------------------------------------------------- -+ * ChromiumStop - the client has stopped the GL app. -+ */ -+ -+typedef struct { -+ CARD8 type; /* always rfbChromiumStop */ -+ CARD8 pad1; -+ CARD16 pad2; -+ CARD32 port; -+} rfbChromiumStopMsg; -+ -+#define sz_rfbChromiumStopMsg 8 -+ -+/*----------------------------------------------------------------------------- -+ * ChromiumExpose - redraw the window -+ */ -+ -+typedef struct { -+ CARD8 type; /* always rfbChromiumExpose */ -+ CARD8 pad1; -+ CARD16 pad2; -+ CARD32 winid; -+} rfbChromiumExposeMsg; -+ -+#define sz_rfbChromiumExposeMsg 8 -+ -+/*----------------------------------------------------------------------------- -+ * Union of all client->server messages. -+ */ -+ -+typedef union _rfbClientToServerMsg { -+ CARD8 type; -+ rfbSetPixelFormatMsg spf; -+ rfbFixColourMapEntriesMsg fcme; -+ rfbSetEncodingsMsg se; -+ rfbFramebufferUpdateRequestMsg fur; -+ rfbKeyEventMsg ke; -+ rfbPointerEventMsg pe; -+ rfbClientCutTextMsg cct; -+ rfbFileListRequestMsg flr; -+ rfbFileDownloadRequestMsg fdr; -+ rfbFileUploadRequestMsg fupr; -+ rfbFileUploadDataMsg fud; -+ rfbFileDownloadCancelMsg fdc; -+ rfbFileUploadFailedMsg fuf; -+ rfbFileCreateDirRequestMsg fcdr; -+ rfbChromiumStopMsg csd; -+ rfbChromiumExposeMsg cse; -+} rfbClientToServerMsg; -diff --git a/hw/dmx/vnc/rfbserver.c b/hw/dmx/vnc/rfbserver.c -new file mode 100644 -index 0000000..e48facc ---- /dev/null -+++ b/hw/dmx/vnc/rfbserver.c -@@ -0,0 +1,2265 @@ -+/* -+ * rfbserver.c - deal with server-side of the RFB protocol. -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ */ -+ -+/* -+ * Copyright (C) 2000-2004 Constantin Kaplinsky. All Rights Reserved. -+ * Copyright (C) 2000 Tridia Corporation. All Rights Reserved. -+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. -+ * -+ * This is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This software is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this software; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -+ * USA. -+ */ -+ -+/* Use ``#define CORBA'' to enable CORBA control interface */ -+ -+#include "rfb.h" -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "windowstr.h" -+#include "input.h" -+#include "mipointer.h" -+#if XFREE86VNC -+#include -+#endif -+#ifdef CHROMIUM -+#include "mivalidate.h" -+#endif -+#include "sprite.h" -+#include "propertyst.h" -+#include -+#include -+ -+#ifdef CORBA -+#include -+#endif -+ -+#if 0 -+extern int GenerateVncConnectedEvent(int sock); -+extern int GenerateVncDisconnectedEvent(int sock); -+#endif -+#ifdef CHROMIUM -+extern int GenerateVncChromiumConnectedEvent(int sock); -+struct CRWindowTable *windowTable = NULL; -+#endif -+ -+extern Atom VNC_CONNECT; -+ -+rfbClientPtr rfbClientHead = NULL; -+rfbClientPtr pointerClient = NULL; /* Mutex for pointer events */ -+ -+static rfbClientPtr rfbNewClient(ScreenPtr pScreen, int sock); -+static void rfbProcessClientProtocolVersion(rfbClientPtr cl); -+static void rfbProcessClientInitMessage(rfbClientPtr cl); -+static void rfbSendInteractionCaps(rfbClientPtr cl); -+static void rfbProcessClientNormalMessage(rfbClientPtr cl); -+static Bool rfbSendCopyRegion(rfbClientPtr cl, RegionPtr reg, int dx, int dy); -+static Bool rfbSendLastRectMarker(rfbClientPtr cl); -+ -+static char *text = NULL; -+ -+void -+rfbRootPropertyChange(ScreenPtr pScreen) -+{ -+ PropertyPtr pProp; -+ WindowPtr pWin = WindowTable[pScreen->myNum]; -+ -+ pProp = wUserProps (pWin); -+ -+ while (pProp) { -+ if ((pProp->propertyName == XA_CUT_BUFFER0) && -+ (pProp->type == XA_STRING) && -+ (pProp->format == 8)) -+ { -+ /* Ensure we don't keep re-sending cut buffer */ -+ -+ if ( (text && pProp->data && strncmp(text, pProp->data, pProp->size)) || !text) -+ rfbGotXCutText(pProp->data, pProp->size); -+ -+ if (text) xfree(text); -+ text = xalloc(1 + pProp->size); -+ if (! text) return; -+ if (pProp->data) memcpy(text, pProp->data, pProp->size); -+ text[pProp->size] = '\0'; -+ -+ return; -+ } -+ if ((pProp->propertyName == VNC_CONNECT) && (pProp->type == XA_STRING) -+ && (pProp->format == 8) && (pProp->size > 0)) -+ { -+ 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(pScreen, host, port); -+ -+#ifdef CORBA -+ if (cl != NULL) -+ newConnection(cl, (KEYBOARD_DEVICE|POINTER_DEVICE), 1, 1, 1); -+#endif -+ -+ ChangeWindowProperty(pWin, -+ pProp->propertyName, pProp->type, -+ pProp->format, PropModeReplace, -+ 0, NULL, -+ FALSE -+ ); -+ -+ free(host); -+ } -+ pProp = pProp->next; -+ } -+} -+ -+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; -+} -+ -+void -+rfbUserAllow(int sock, int accept) -+{ -+ rfbClientPtr cl; -+ -+ for (cl = rfbClientHead; cl; cl = cl->next) { -+ if (cl->sock == sock) { -+ cl->userAccepted = accept; -+ } -+ } -+} -+ -+/* -+ * rfbNewClientConnection is called from sockets.c when a new connection -+ * comes in. -+ */ -+ -+void -+rfbNewClientConnection(ScreenPtr pScreen, int sock) -+{ -+ rfbClientPtr cl; -+ -+ cl = rfbNewClient(pScreen, sock); -+ -+#if 0 -+ GenerateVncConnectedEvent(sock); -+#endif -+ -+#if XFREE86VNC -+ /* Someone is connected - disable VT switching */ -+ xf86EnableVTSwitch(FALSE); -+#endif -+ -+#ifdef CORBA -+ if (cl != NULL) -+ newConnection(cl, (KEYBOARD_DEVICE|POINTER_DEVICE), 1, 1, 1); -+#endif -+} -+ -+ -+/* -+ * rfbReverseConnection is called by the CORBA stuff to make an outward -+ * connection to a "listening" RFB client. -+ */ -+ -+rfbClientPtr -+rfbReverseConnection(ScreenPtr pScreen, char *host, int port) -+{ -+ int sock; -+ rfbClientPtr cl; -+ -+ if ((sock = rfbConnect(pScreen, host, port)) < 0) -+ return (rfbClientPtr)NULL; -+ -+ cl = rfbNewClient(pScreen, sock); -+ -+ if (cl) { -+ cl->reverseConnection = TRUE; -+ } -+ -+ return cl; -+} -+ -+ -+#ifdef CHROMIUM -+/* -+ * rfbSetClip -- -+ * Generate expose event. -+ * This function is overkill and should be cleaned up, but it -+ * works for now. -+ */ -+ -+static void -+rfbSetClip(WindowPtr pWin, BOOL enable) -+{ -+ ScreenPtr pScreen = pWin->drawable.pScreen; -+ WindowPtr pChild; -+ Bool WasViewable = (Bool)(pWin->viewable); -+ Bool anyMarked = FALSE; -+ RegionPtr pOldClip = NULL, bsExposed; -+#ifdef DO_SAVE_UNDERS -+ Bool dosave = FALSE; -+#endif -+ WindowPtr pLayerWin; -+ BoxRec box; -+ -+ if (WasViewable) -+ { -+ for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) -+ { -+ (void) (*pScreen->MarkOverlappedWindows)(pChild, -+ pChild, -+ &pLayerWin); -+ } -+ (*pScreen->MarkWindow) (pWin); -+ anyMarked = TRUE; -+ if (pWin->valdata) -+ { -+ if (HasBorder (pWin)) -+ { -+ RegionPtr borderVisible; -+ -+ borderVisible = REGION_CREATE(pScreen, NullBox, 1); -+ REGION_SUBTRACT(pScreen, borderVisible, -+ &pWin->borderClip, &pWin->winSize); -+ pWin->valdata->before.borderVisible = borderVisible; -+ } -+ pWin->valdata->before.resized = TRUE; -+ } -+ } -+ -+ /* -+ * Use REGION_BREAK to avoid optimizations in ValidateTree -+ * that assume the root borderClip can't change well, normally -+ * it doesn't...) -+ */ -+ if (enable) -+ { -+ box.x1 = 0; -+ box.y1 = 0; -+ box.x2 = pScreen->width; -+ box.y2 = pScreen->height; -+ REGION_INIT (pScreen, &pWin->winSize, &box, 1); -+ REGION_INIT (pScreen, &pWin->borderSize, &box, 1); -+ if (WasViewable) -+ REGION_RESET(pScreen, &pWin->borderClip, &box); -+ pWin->drawable.width = pScreen->width; -+ pWin->drawable.height = pScreen->height; -+ REGION_BREAK (pWin->drawable.pScreen, &pWin->clipList); -+ } -+ else -+ { -+ REGION_EMPTY(pScreen, &pWin->borderClip); -+ REGION_BREAK (pWin->drawable.pScreen, &pWin->clipList); -+ } -+ -+ ResizeChildrenWinSize (pWin, 0, 0, 0, 0); -+ -+ if (WasViewable) -+ { -+ if (pWin->backStorage) -+ { -+ pOldClip = REGION_CREATE(pScreen, NullBox, 1); -+ REGION_COPY(pScreen, pOldClip, &pWin->clipList); -+ } -+ -+ if (pWin->firstChild) -+ { -+ anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin->firstChild, -+ pWin->firstChild, -+ (WindowPtr *)NULL); -+ } -+ else -+ { -+ (*pScreen->MarkWindow) (pWin); -+ anyMarked = TRUE; -+ } -+ -+#ifdef DO_SAVE_UNDERS -+ if (DO_SAVE_UNDERS(pWin)) -+ { -+ dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, pLayerWin); -+ } -+#endif /* DO_SAVE_UNDERS */ -+ -+ if (anyMarked) -+ (*pScreen->ValidateTree)(pWin, NullWindow, VTOther); -+ } -+ -+ if (pWin->backStorage && -+ ((pWin->backingStore == Always) || WasViewable)) -+ { -+ if (!WasViewable) -+ pOldClip = &pWin->clipList; /* a convenient empty region */ -+ bsExposed = (*pScreen->TranslateBackingStore) -+ (pWin, 0, 0, pOldClip, -+ pWin->drawable.x, pWin->drawable.y); -+ if (WasViewable) -+ REGION_DESTROY(pScreen, pOldClip); -+ if (bsExposed) -+ { -+ RegionPtr valExposed = NullRegion; -+ -+ if (pWin->valdata) -+ valExposed = &pWin->valdata->after.exposed; -+ (*pScreen->WindowExposures) (pWin, valExposed, bsExposed); -+ if (valExposed) -+ REGION_EMPTY(pScreen, valExposed); -+ REGION_DESTROY(pScreen, bsExposed); -+ } -+ } -+ if (WasViewable) -+ { -+ if (anyMarked) -+ (*pScreen->HandleExposures)(pWin); -+#ifdef DO_SAVE_UNDERS -+ if (dosave) -+ (*pScreen->PostChangeSaveUnder)(pLayerWin, pLayerWin); -+#endif /* DO_SAVE_UNDERS */ -+ if (anyMarked && pScreen->PostValidateTree) -+ (*pScreen->PostValidateTree)(pWin, NullWindow, VTOther); -+ } -+ if (pWin->realized) -+ WindowsRestructured (); -+ FlushAllOutput (); -+} -+#endif /* CHROMIUM */ -+ -+/* -+ * rfbNewClient is called when a new connection has been made by whatever -+ * means. -+ */ -+ -+static rfbClientPtr -+rfbNewClient(ScreenPtr pScreen, int sock) -+{ -+ rfbProtocolVersionMsg pv; -+ rfbClientPtr cl; -+ BoxRec box; -+ struct sockaddr_in addr; -+ SOCKLEN_T addrlen = sizeof(struct sockaddr_in); -+ VNCSCREENPTR(pScreen); -+ int i; -+ -+ if (rfbClientHead == NULL) { -+ /* no other clients - make sure we don't think any keys are pressed */ -+ KbdReleaseAllKeys(); -+ } else { -+ rfbLog(" (other clients"); -+ for (cl = rfbClientHead; cl; cl = cl->next) { -+ rfbLog(" %s",cl->host); -+ } -+ rfbLog(")\n"); -+ } -+ -+ cl = (rfbClientPtr)xalloc(sizeof(rfbClientRec)); -+ -+#ifdef CHROMIUM -+ cl->chromium_port = 0; /* no GL application on this port, yet */ -+#endif -+ cl->userAccepted = 0; /* user hasn't even approached this yet .... */ -+ cl->sock = sock; -+ getpeername(sock, (struct sockaddr *)&addr, &addrlen); -+ cl->host = strdup(inet_ntoa(addr.sin_addr)); -+ cl->login = NULL; -+ -+ /* Dispatch client input to rfbProcessClientProtocolVersion(). */ -+ cl->state = RFB_PROTOCOL_VERSION; -+ -+ cl->viewOnly = FALSE; -+ cl->reverseConnection = FALSE; -+ cl->readyForSetColourMapEntries = FALSE; -+ cl->useCopyRect = FALSE; -+ cl->preferredEncoding = rfbEncodingRaw; -+ cl->correMaxWidth = 48; -+ cl->correMaxHeight = 48; -+ cl->pScreen = pScreen; -+ -+ REGION_NULL(pScreen,&cl->copyRegion); -+ cl->copyDX = 0; -+ cl->copyDY = 0; -+ -+ box.x1 = box.y1 = 0; -+ box.x2 = pVNC->width; -+ box.y2 = pVNC->height; -+ REGION_INIT(pScreen,&cl->modifiedRegion,&box,0); -+ -+ REGION_NULL(pScreen,&cl->requestedRegion); -+ -+ cl->deferredUpdateScheduled = FALSE; -+ cl->deferredUpdateTimer = NULL; -+ -+ cl->format = pVNC->rfbServerFormat; -+ cl->translateFn = rfbTranslateNone; -+ cl->translateLookupTable = NULL; -+ -+ cl->tightCompressLevel = TIGHT_DEFAULT_COMPRESSION; -+ cl->tightQualityLevel = -1; -+ for (i = 0; i < 4; i++) -+ cl->zsActive[i] = FALSE; -+ -+ cl->enableCursorShapeUpdates = FALSE; -+ cl->enableCursorPosUpdates = FALSE; -+ cl->enableLastRectEncoding = FALSE; -+#ifdef CHROMIUM -+ cl->enableChromiumEncoding = FALSE; -+#endif -+ -+ cl->next = rfbClientHead; -+ rfbClientHead = cl; -+ -+ rfbResetStats(cl); -+ -+ cl->compStreamInited = FALSE; -+ cl->compStream.total_in = 0; -+ cl->compStream.total_out = 0; -+ cl->compStream.zalloc = Z_NULL; -+ cl->compStream.zfree = Z_NULL; -+ cl->compStream.opaque = Z_NULL; -+ -+ cl->zlibCompressLevel = 5; -+ -+ sprintf(pv,rfbProtocolVersionFormat,rfbProtocolMajorVersion, -+ rfbProtocolMinorVersion); -+ -+ if (WriteExact(sock, pv, sz_rfbProtocolVersionMsg) < 0) { -+ rfbLogPerror("rfbNewClient: write"); -+ rfbCloseSock(pScreen, sock); -+ return NULL; -+ } -+ -+ return cl; -+} -+ -+ -+/* -+ * rfbClientConnectionGone is called from sockets.c just after a connection -+ * has gone away. -+ */ -+ -+void -+rfbClientConnectionGone(sock) -+ int sock; -+{ -+ rfbClientPtr cl, prev; -+ int i; -+#if XFREE86VNC -+ int allowvt = TRUE; -+#endif -+ -+ for (prev = NULL, cl = rfbClientHead; cl; prev = cl, cl = cl->next) { -+ if (sock == cl->sock) -+ break; -+ } -+ -+ if (!cl) { -+ rfbLog("rfbClientConnectionGone: unknown socket %d\n",sock); -+ return; -+ } -+ -+ if (cl->login != NULL) { -+ rfbLog("Client %s (%s) gone\n", cl->login, cl->host); -+ free(cl->login); -+ } else { -+ rfbLog("Client %s gone\n", cl->host); -+ } -+ free(cl->host); -+ -+ /* Release the compression state structures if any. */ -+ if ( cl->compStreamInited == TRUE ) { -+ deflateEnd( &(cl->compStream) ); -+ } -+ -+ for (i = 0; i < 4; i++) { -+ if (cl->zsActive[i]) -+ deflateEnd(&cl->zsStruct[i]); -+ } -+ -+ if (pointerClient == cl) -+ pointerClient = NULL; -+ -+#ifdef CORBA -+ destroyConnection(cl); -+#endif -+ -+ if (prev) -+ prev->next = cl->next; -+ else -+ rfbClientHead = cl->next; -+ -+ REGION_UNINIT(cl->pScreen,&cl->copyRegion); -+ REGION_UNINIT(cl->pScreen,&cl->modifiedRegion); -+ TimerFree(cl->deferredUpdateTimer); -+ -+ rfbPrintStats(cl); -+ -+ if (cl->translateLookupTable) free(cl->translateLookupTable); -+ -+ xfree(cl); -+ -+#if 0 -+ GenerateVncDisconnectedEvent(sock); -+#endif -+ -+#if XFREE86VNC -+ for (cl = rfbClientHead; cl; cl = cl->next) { -+ /* still someone connected */ -+ allowvt = FALSE; -+ } -+ -+ xf86EnableVTSwitch(allowvt); -+#endif -+} -+ -+ -+/* -+ * rfbProcessClientMessage is called when there is data to read from a client. -+ */ -+ -+void -+rfbProcessClientMessage(ScreenPtr pScreen, int sock) -+{ -+ rfbClientPtr cl; -+ -+ for (cl = rfbClientHead; cl; cl = cl->next) { -+ if (sock == cl->sock) -+ break; -+ } -+ -+ if (!cl) { -+ rfbLog("rfbProcessClientMessage: unknown socket %d\n",sock); -+ rfbCloseSock(pScreen, sock); -+ return; -+ } -+ -+#ifdef CORBA -+ if (isClosePending(cl)) { -+ rfbLog("Closing connection to client %s\n", cl->host); -+ rfbCloseSock(pScreen, sock); -+ return; -+ } -+#endif -+ -+ switch (cl->state) { -+ case RFB_PROTOCOL_VERSION: -+ rfbProcessClientProtocolVersion(cl); -+ break; -+ case RFB_SECURITY_TYPE: /* protocol 3.7 */ -+ rfbProcessClientSecurityType(cl); -+ break; -+ case RFB_TUNNELING_TYPE: /* protocol 3.7t */ -+ rfbProcessClientTunnelingType(cl); -+ break; -+ case RFB_AUTH_TYPE: /* protocol 3.7t */ -+ rfbProcessClientAuthType(cl); -+ break; -+ case RFB_AUTHENTICATION: -+ rfbVncAuthProcessResponse(cl); -+ break; -+ case RFB_INITIALISATION: -+ rfbProcessClientInitMessage(cl); -+ break; -+ default: -+ rfbProcessClientNormalMessage(cl); -+ } -+} -+ -+ -+/* -+ * rfbProcessClientProtocolVersion is called when the client sends its -+ * protocol version. -+ */ -+ -+static void -+rfbProcessClientProtocolVersion(cl) -+ rfbClientPtr cl; -+{ -+ rfbProtocolVersionMsg pv; -+ int n, major, minor; -+ -+ if ((n = ReadExact(cl->sock, pv, sz_rfbProtocolVersionMsg)) <= 0) { -+ if (n == 0) -+ rfbLog("rfbProcessClientProtocolVersion: client gone\n"); -+ else -+ rfbLogPerror("rfbProcessClientProtocolVersion: read"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ pv[sz_rfbProtocolVersionMsg] = 0; -+ if (sscanf(pv,rfbProtocolVersionFormat,&major,&minor) != 2) { -+ rfbLog("rfbProcessClientProtocolVersion: not a valid RFB client\n"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ rfbLog("Using protocol version %d.%d\n", major, minor); -+ -+ if (major != rfbProtocolMajorVersion) { -+ rfbLog("RFB protocol version mismatch - server %d.%d, client %d.%d\n", -+ rfbProtocolMajorVersion,rfbProtocolMinorVersion,major,minor); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ /* Always use one of the two standard versions of the RFB protocol. */ -+ cl->protocol_minor_ver = minor; -+ if (minor > rfbProtocolMinorVersion) { -+ cl->protocol_minor_ver = rfbProtocolMinorVersion; -+ } else if (minor < rfbProtocolMinorVersion) { -+ cl->protocol_minor_ver = rfbProtocolFallbackMinorVersion; -+ } -+ if (minor != rfbProtocolMinorVersion && -+ minor != rfbProtocolFallbackMinorVersion) { -+ rfbLog("Non-standard protocol version %d.%d, using %d.%d instead\n", -+ major, minor, rfbProtocolMajorVersion, cl->protocol_minor_ver); -+ } -+ -+ /* TightVNC protocol extensions are not enabled yet. */ -+ cl->protocol_tightvnc = FALSE; -+ -+ rfbAuthNewClient(cl); -+} -+ -+/* -+ * rfbClientConnFailed is called when a client connection has failed -+ * before the authentication stage. -+ */ -+ -+void -+rfbClientConnFailed(cl, reason) -+ rfbClientPtr cl; -+ char *reason; -+{ -+ int headerLen, reasonLen; -+ char buf[8]; -+ -+ headerLen = (cl->protocol_minor_ver >= 7) ? 1 : 4; -+ reasonLen = strlen(reason); -+ ((CARD32 *)buf)[0] = 0; -+ ((CARD32 *)buf)[1] = Swap32IfLE(reasonLen); -+ -+ if ( WriteExact(cl->sock, buf, headerLen) < 0 || -+ WriteExact(cl->sock, buf + 4, 4) < 0 || -+ WriteExact(cl->sock, reason, reasonLen) < 0 ) { -+ rfbLogPerror("rfbClientConnFailed: write"); -+ } -+ -+ rfbCloseSock(cl->pScreen, cl->sock); -+} -+ -+ -+/* -+ * rfbProcessClientInitMessage is called when the client sends its -+ * initialisation message. -+ */ -+ -+static void -+rfbProcessClientInitMessage(cl) -+ rfbClientPtr cl; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ rfbClientInitMsg ci; -+ char buf[256]; -+ rfbServerInitMsg *si = (rfbServerInitMsg *)buf; -+ struct passwd *user; -+ int len, n; -+ rfbClientPtr otherCl, nextCl; -+ -+ if ((n = ReadExact(cl->sock, (char *)&ci,sz_rfbClientInitMsg)) <= 0) { -+ if (n == 0) -+ rfbLog("rfbProcessClientInitMessage: client gone\n"); -+ else -+ rfbLogPerror("rfbProcessClientInitMessage: read"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ si->framebufferWidth = Swap16IfLE(pVNC->width); -+ si->framebufferHeight = Swap16IfLE(pVNC->height); -+ si->format = pVNC->rfbServerFormat; -+ si->format.redMax = Swap16IfLE(si->format.redMax); -+ si->format.greenMax = Swap16IfLE(si->format.greenMax); -+ si->format.blueMax = Swap16IfLE(si->format.blueMax); -+ -+ user = getpwuid(getuid()); -+ -+ if (strlen(desktopName) > 128) /* sanity check on desktop name len */ -+ desktopName[128] = 0; -+ -+ if (user) { -+ sprintf(buf + sz_rfbServerInitMsg, "%s's %s desktop (%s:%s)", -+ user->pw_name, desktopName, rfbThisHost, display); -+ } else { -+ sprintf(buf + sz_rfbServerInitMsg, "%s desktop (%s:%s)", -+ desktopName, rfbThisHost, display); -+ } -+ len = strlen(buf + sz_rfbServerInitMsg); -+ si->nameLength = Swap32IfLE(len); -+ -+ if (WriteExact(cl->sock, buf, sz_rfbServerInitMsg + len) < 0) { -+ rfbLogPerror("rfbProcessClientInitMessage: write"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ if (cl->protocol_tightvnc) -+ rfbSendInteractionCaps(cl); /* protocol 3.7t */ -+ -+ /* Dispatch client input to rfbProcessClientNormalMessage(). */ -+ cl->state = RFB_NORMAL; -+ -+ if (!cl->reverseConnection && -+ (pVNC->rfbNeverShared || (!pVNC->rfbAlwaysShared && !ci.shared))) { -+ -+ if (pVNC->rfbDontDisconnect) { -+ for (otherCl = rfbClientHead; otherCl; otherCl = otherCl->next) { -+ if ((otherCl != cl) && (otherCl->state == RFB_NORMAL)) { -+ rfbLog("-dontdisconnect: Not shared & existing client\n"); -+ rfbLog(" refusing new client %s\n", cl->host); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ } -+ } else { -+ for (otherCl = rfbClientHead; otherCl; otherCl = nextCl) { -+ nextCl = otherCl->next; -+ if ((otherCl != cl) && (otherCl->state == RFB_NORMAL)) { -+ rfbLog("Not shared - closing connection to client %s\n", -+ otherCl->host); -+ rfbCloseSock(otherCl->pScreen, otherCl->sock); -+ } -+ } -+ } -+ } -+} -+ -+ -+/* -+ * rfbSendInteractionCaps is called after sending the server -+ * initialisation message, only if the protocol version is 3.130. -+ * In this function, we send the lists of supported protocol messages -+ * and encodings. -+ */ -+ -+/* Update these constants on changing capability lists below! */ -+#define N_SMSG_CAPS 0 -+#define N_CMSG_CAPS 0 -+#define N_ENC_CAPS 12 -+ -+void -+rfbSendInteractionCaps(cl) -+ rfbClientPtr cl; -+{ -+ rfbInteractionCapsMsg intr_caps; -+ rfbCapabilityInfo enc_list[N_ENC_CAPS]; -+ int i; -+ -+ /* Fill in the header structure sent prior to capability lists. */ -+ intr_caps.nServerMessageTypes = Swap16IfLE(N_SMSG_CAPS); -+ intr_caps.nClientMessageTypes = Swap16IfLE(N_CMSG_CAPS); -+ intr_caps.nEncodingTypes = Swap16IfLE(N_ENC_CAPS); -+ intr_caps.pad = 0; -+ -+ /* Supported server->client message types. */ -+ /* For future file transfer support: -+ i = 0; -+ SetCapInfo(&smsg_list[i++], rfbFileListData, rfbTightVncVendor); -+ SetCapInfo(&smsg_list[i++], rfbFileDownloadData, rfbTightVncVendor); -+ SetCapInfo(&smsg_list[i++], rfbFileUploadCancel, rfbTightVncVendor); -+ SetCapInfo(&smsg_list[i++], rfbFileDownloadFailed, rfbTightVncVendor); -+ if (i != N_SMSG_CAPS) { -+ rfbLog("rfbSendInteractionCaps: assertion failed, i != N_SMSG_CAPS\n"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ */ -+ -+ /* Supported client->server message types. */ -+ /* For future file transfer support: -+ i = 0; -+ SetCapInfo(&cmsg_list[i++], rfbFileListRequest, rfbTightVncVendor); -+ SetCapInfo(&cmsg_list[i++], rfbFileDownloadRequest, rfbTightVncVendor); -+ SetCapInfo(&cmsg_list[i++], rfbFileUploadRequest, rfbTightVncVendor); -+ SetCapInfo(&cmsg_list[i++], rfbFileUploadData, rfbTightVncVendor); -+ SetCapInfo(&cmsg_list[i++], rfbFileDownloadCancel, rfbTightVncVendor); -+ SetCapInfo(&cmsg_list[i++], rfbFileUploadFailed, rfbTightVncVendor); -+ if (i != N_CMSG_CAPS) { -+ rfbLog("rfbSendInteractionCaps: assertion failed, i != N_CMSG_CAPS\n"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ */ -+ -+ /* Encoding types. */ -+ i = 0; -+ SetCapInfo(&enc_list[i++], rfbEncodingCopyRect, rfbStandardVendor); -+ SetCapInfo(&enc_list[i++], rfbEncodingRRE, rfbStandardVendor); -+ SetCapInfo(&enc_list[i++], rfbEncodingCoRRE, rfbStandardVendor); -+ SetCapInfo(&enc_list[i++], rfbEncodingHextile, rfbStandardVendor); -+ SetCapInfo(&enc_list[i++], rfbEncodingZlib, rfbTridiaVncVendor); -+ SetCapInfo(&enc_list[i++], rfbEncodingTight, rfbTightVncVendor); -+ SetCapInfo(&enc_list[i++], rfbEncodingCompressLevel0, rfbTightVncVendor); -+ SetCapInfo(&enc_list[i++], rfbEncodingQualityLevel0, rfbTightVncVendor); -+ SetCapInfo(&enc_list[i++], rfbEncodingXCursor, rfbTightVncVendor); -+ SetCapInfo(&enc_list[i++], rfbEncodingRichCursor, rfbTightVncVendor); -+ SetCapInfo(&enc_list[i++], rfbEncodingPointerPos, rfbTightVncVendor); -+ SetCapInfo(&enc_list[i++], rfbEncodingLastRect, rfbTightVncVendor); -+ if (i != N_ENC_CAPS) { -+ rfbLog("rfbSendInteractionCaps: assertion failed, i != N_ENC_CAPS\n"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ /* Send header and capability lists */ -+ if (WriteExact(cl->sock, (char *)&intr_caps, -+ sz_rfbInteractionCapsMsg) < 0 || -+ WriteExact(cl->sock, (char *)&enc_list[0], -+ sz_rfbCapabilityInfo * N_ENC_CAPS) < 0) { -+ rfbLogPerror("rfbSendInteractionCaps: write"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ /* Dispatch client input to rfbProcessClientNormalMessage(). */ -+ cl->state = RFB_NORMAL; -+} -+ -+ -+/* -+ * rfbProcessClientNormalMessage is called when the client has sent a normal -+ * protocol message. -+ */ -+ -+static void -+rfbProcessClientNormalMessage(cl) -+ rfbClientPtr cl; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ int n; -+ rfbClientToServerMsg msg; -+ char *str; -+ -+#if 0 -+ if (pVNC->rfbUserAccept) { -+ /* -+ * We've asked for another level of user authentication -+ * If the user has not validated this connected, don't -+ * process it. -+ */ -+ /* -+ * NOTE: we do it here, so the vncviewer knows it's -+ * connected, but waiting for the first screen update -+ */ -+ if (cl->userAccepted == VNC_USER_UNDEFINED) -+ return; -+ if (cl->userAccepted == VNC_USER_DISCONNECT) { -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ } -+#endif -+ -+ if ((n = ReadExact(cl->sock, (char *)&msg, 1)) <= 0) { -+ if (n != 0) -+ rfbLogPerror("rfbProcessClientNormalMessage: read"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ switch (msg.type) { -+ -+ case rfbSetPixelFormat: -+ -+ if ((n = ReadExact(cl->sock, ((char *)&msg) + 1, -+ sz_rfbSetPixelFormatMsg - 1)) <= 0) { -+ if (n != 0) -+ rfbLogPerror("rfbProcessClientNormalMessage: read"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ cl->format.bitsPerPixel = msg.spf.format.bitsPerPixel; -+ cl->format.depth = msg.spf.format.depth; -+ cl->format.bigEndian = (msg.spf.format.bigEndian ? 1 : 0); -+ cl->format.trueColour = (msg.spf.format.trueColour ? 1 : 0); -+ cl->format.redMax = Swap16IfLE(msg.spf.format.redMax); -+ cl->format.greenMax = Swap16IfLE(msg.spf.format.greenMax); -+ cl->format.blueMax = Swap16IfLE(msg.spf.format.blueMax); -+ cl->format.redShift = msg.spf.format.redShift; -+ cl->format.greenShift = msg.spf.format.greenShift; -+ cl->format.blueShift = msg.spf.format.blueShift; -+ -+ cl->readyForSetColourMapEntries = TRUE; -+ -+ rfbSetTranslateFunction(cl); -+ return; -+ -+ -+ case rfbFixColourMapEntries: -+ if ((n = ReadExact(cl->sock, ((char *)&msg) + 1, -+ sz_rfbFixColourMapEntriesMsg - 1)) <= 0) { -+ if (n != 0) -+ rfbLogPerror("rfbProcessClientNormalMessage: read"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ rfbLog("rfbProcessClientNormalMessage: %s", -+ "FixColourMapEntries unsupported\n"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ -+ -+ case rfbSetEncodings: -+ { -+ int i; -+ CARD32 enc; -+ -+ if ((n = ReadExact(cl->sock, ((char *)&msg) + 1, -+ sz_rfbSetEncodingsMsg - 1)) <= 0) { -+ if (n != 0) -+ rfbLogPerror("rfbProcessClientNormalMessage: read"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ msg.se.nEncodings = Swap16IfLE(msg.se.nEncodings); -+ -+ cl->preferredEncoding = -1; -+ cl->useCopyRect = FALSE; -+ cl->enableCursorShapeUpdates = FALSE; -+ cl->enableCursorPosUpdates = FALSE; -+ cl->enableLastRectEncoding = FALSE; -+#ifdef CHROMIUM -+ cl->enableChromiumEncoding = FALSE; -+#endif -+ cl->tightCompressLevel = TIGHT_DEFAULT_COMPRESSION; -+ cl->tightQualityLevel = -1; -+ -+ for (i = 0; i < msg.se.nEncodings; i++) { -+ if ((n = ReadExact(cl->sock, (char *)&enc, 4)) <= 0) { -+ if (n != 0) -+ rfbLogPerror("rfbProcessClientNormalMessage: read"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ enc = Swap32IfLE(enc); -+ -+ switch (enc) { -+ -+ case rfbEncodingCopyRect: -+ cl->useCopyRect = TRUE; -+ rfbLog("Using copyrect encoding for client %s\n", -+ cl->host); -+ break; -+ case rfbEncodingRaw: -+ if (cl->preferredEncoding == -1) { -+ cl->preferredEncoding = enc; -+ rfbLog("Using raw encoding for client %s\n", -+ cl->host); -+ } -+ break; -+ case rfbEncodingRRE: -+ if (cl->preferredEncoding == -1) { -+ cl->preferredEncoding = enc; -+ rfbLog("Using rre encoding for client %s\n", -+ cl->host); -+ } -+ break; -+ case rfbEncodingCoRRE: -+ if (cl->preferredEncoding == -1) { -+ cl->preferredEncoding = enc; -+ rfbLog("Using CoRRE encoding for client %s\n", -+ cl->host); -+ } -+ break; -+ case rfbEncodingHextile: -+ if (cl->preferredEncoding == -1) { -+ cl->preferredEncoding = enc; -+ rfbLog("Using hextile encoding for client %s\n", -+ cl->host); -+ } -+ break; -+ case rfbEncodingZlib: -+ if (cl->preferredEncoding == -1) { -+ cl->preferredEncoding = enc; -+ rfbLog("Using zlib encoding for client %s\n", -+ cl->host); -+ } -+ break; -+ case rfbEncodingTight: -+ if (cl->preferredEncoding == -1) { -+ cl->preferredEncoding = enc; -+ rfbLog("Using tight encoding for client %s\n", -+ cl->host); -+ } -+ break; -+ case rfbEncodingXCursor: -+ rfbLog("Enabling X-style cursor updates for client %s\n", -+ cl->host); -+ cl->enableCursorShapeUpdates = TRUE; -+ cl->useRichCursorEncoding = FALSE; -+ cl->cursorWasChanged = TRUE; -+ break; -+ case rfbEncodingRichCursor: -+ if (!cl->enableCursorShapeUpdates) { -+ rfbLog("Enabling full-color cursor updates for client " -+ "%s\n", cl->host); -+ cl->enableCursorShapeUpdates = TRUE; -+ cl->useRichCursorEncoding = TRUE; -+ cl->cursorWasChanged = TRUE; -+ } -+ break; -+ case rfbEncodingPointerPos: -+ if (!cl->enableCursorPosUpdates) { -+ rfbLog("Enabling cursor position updates for client %s\n", -+ cl->host); -+ cl->enableCursorPosUpdates = TRUE; -+ cl->cursorWasMoved = TRUE; -+ cl->cursorX = -1; -+ cl->cursorY = -1; -+ } -+ break; -+ case rfbEncodingLastRect: -+ if (!cl->enableLastRectEncoding) { -+ rfbLog("Enabling LastRect protocol extension for client " -+ "%s\n", cl->host); -+ cl->enableLastRectEncoding = TRUE; -+ } -+ break; -+#ifdef CHROMIUM -+ case rfbEncodingChromium: -+ if (!cl->enableChromiumEncoding) { -+ WindowPtr pWin = WindowTable[cl->pScreen->myNum]; -+ rfbLog("Enabling Chromium protocol extension for client " -+ "%s\n", cl->host); -+ cl->enableChromiumEncoding = TRUE; -+ /* Now generate an event, so we can start our GL app */ -+ GenerateVncChromiumConnectedEvent(cl->sock); -+ /* Generate exposures for all windows */ -+ rfbSetClip(pWin, 1); -+ } -+ break; -+#endif -+ default: -+ if ( enc >= (CARD32)rfbEncodingCompressLevel0 && -+ enc <= (CARD32)rfbEncodingCompressLevel9 ) { -+ cl->zlibCompressLevel = enc & 0x0F; -+ cl->tightCompressLevel = enc & 0x0F; -+ rfbLog("Using compression level %d for client %s\n", -+ cl->tightCompressLevel, cl->host); -+ } else if ( enc >= (CARD32)rfbEncodingQualityLevel0 && -+ enc <= (CARD32)rfbEncodingQualityLevel9 ) { -+ cl->tightQualityLevel = enc & 0x0F; -+ rfbLog("Using image quality level %d for client %s\n", -+ cl->tightQualityLevel, cl->host); -+ } else { -+ rfbLog("rfbProcessClientNormalMessage: ignoring unknown " -+ "encoding 0x%x\n", (int)enc); -+ } -+ } -+ } -+ -+ if (cl->preferredEncoding == -1) { -+ cl->preferredEncoding = rfbEncodingRaw; -+ rfbLog("No encoding specified - using raw encoding for client %s\n", -+ cl->host); -+ } -+ -+ if (cl->enableCursorPosUpdates && !cl->enableCursorShapeUpdates) { -+ rfbLog("Disabling cursor position updates for client %s\n", -+ cl->host); -+ cl->enableCursorPosUpdates = FALSE; -+ } -+ -+#if XFREE86VNC -+ /* -+ * With XFree86 and the hardware cursor's we need to put up the -+ * cursor again, and if we've detected a cursor shapeless client -+ * we need to disable hardware cursors. -+ */ -+ if (!cl->enableCursorShapeUpdates) -+ pVNC->SWCursor = (Bool *)TRUE; -+ else -+ pVNC->SWCursor = (Bool *)FALSE; -+ -+ { -+ int x, y; -+ miPointerPosition(&x, &y); -+ (*pVNC->spriteFuncs->SetCursor)(cl->pScreen, pVNC->pCurs, x, y); -+ } -+#endif -+ -+ return; -+ } -+ -+ -+ case rfbFramebufferUpdateRequest: -+ { -+ RegionRec tmpRegion; -+ BoxRec box; -+ -+#ifdef CORBA -+ addCapability(cl, DISPLAY_DEVICE); -+#endif -+ -+ if ((n = ReadExact(cl->sock, ((char *)&msg) + 1, -+ sz_rfbFramebufferUpdateRequestMsg-1)) <= 0) { -+ if (n != 0) -+ rfbLogPerror("rfbProcessClientNormalMessage: read"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ box.x1 = Swap16IfLE(msg.fur.x); -+ box.y1 = Swap16IfLE(msg.fur.y); -+ box.x2 = box.x1 + Swap16IfLE(msg.fur.w); -+ box.y2 = box.y1 + Swap16IfLE(msg.fur.h); -+ SAFE_REGION_INIT(cl->pScreen,&tmpRegion,&box,0); -+ -+ REGION_UNION(cl->pScreen, &cl->requestedRegion, &cl->requestedRegion, -+ &tmpRegion); -+ -+ if (!cl->readyForSetColourMapEntries) { -+ /* client hasn't sent a SetPixelFormat so is using server's */ -+ cl->readyForSetColourMapEntries = TRUE; -+ if (!cl->format.trueColour) { -+ if (!rfbSetClientColourMap(cl, 0, 0)) { -+ REGION_UNINIT(cl->pScreen,&tmpRegion); -+ return; -+ } -+ } -+ } -+ -+ if (!msg.fur.incremental) { -+ REGION_UNION(cl->pScreen,&cl->modifiedRegion,&cl->modifiedRegion, -+ &tmpRegion); -+ REGION_SUBTRACT(cl->pScreen,&cl->copyRegion,&cl->copyRegion, -+ &tmpRegion); -+ } -+ -+ if (FB_UPDATE_PENDING(cl)) { -+ rfbSendFramebufferUpdate(cl->pScreen, cl); -+ } -+ -+ REGION_UNINIT(cl->pScreen,&tmpRegion); -+ return; -+ } -+ -+ case rfbKeyEvent: -+ -+ cl->rfbKeyEventsRcvd++; -+ -+ if ((n = ReadExact(cl->sock, ((char *)&msg) + 1, -+ sz_rfbKeyEventMsg - 1)) <= 0) { -+ if (n != 0) -+ rfbLogPerror("rfbProcessClientNormalMessage: read"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+#ifdef CORBA -+ addCapability(cl, KEYBOARD_DEVICE); -+ -+ if (!isKeyboardEnabled(cl)) -+ return; -+#endif -+ if (!pVNC->rfbViewOnly && !cl->viewOnly) { -+ KbdAddEvent(msg.ke.down, (KeySym)Swap32IfLE(msg.ke.key), cl); -+ } -+ return; -+ -+ -+ case rfbPointerEvent: -+ -+ cl->rfbPointerEventsRcvd++; -+ -+ if ((n = ReadExact(cl->sock, ((char *)&msg) + 1, -+ sz_rfbPointerEventMsg - 1)) <= 0) { -+ if (n != 0) -+ rfbLogPerror("rfbProcessClientNormalMessage: read"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+#ifdef CORBA -+ addCapability(cl, POINTER_DEVICE); -+ -+ if (!isPointerEnabled(cl)) -+ return; -+#endif -+ -+ if (pointerClient && (pointerClient != cl)) -+ return; -+ -+ if (msg.pe.buttonMask == 0) -+ pointerClient = NULL; -+ else -+ pointerClient = cl; -+ -+ if (!pVNC->rfbViewOnly && !cl->viewOnly) { -+ cl->cursorX = (int)Swap16IfLE(msg.pe.x); -+ cl->cursorY = (int)Swap16IfLE(msg.pe.y); -+ PtrAddEvent(msg.pe.buttonMask, cl->cursorX, cl->cursorY, cl); -+ } -+ return; -+ -+ -+ case rfbClientCutText: -+ -+ if ((n = ReadExact(cl->sock, ((char *)&msg) + 1, -+ sz_rfbClientCutTextMsg - 1)) <= 0) { -+ if (n != 0) -+ rfbLogPerror("rfbProcessClientNormalMessage: read"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ msg.cct.length = Swap32IfLE(msg.cct.length); -+ -+ str = (char *)xalloc(msg.cct.length); -+ -+ if ((n = ReadExact(cl->sock, str, msg.cct.length)) <= 0) { -+ if (n != 0) -+ rfbLogPerror("rfbProcessClientNormalMessage: read"); -+ xfree(str); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ /* NOTE: We do not accept cut text from a view-only client */ -+ if (!cl->viewOnly) -+ rfbSetXCutText(str, msg.cct.length); -+ -+ xfree(str); -+ return; -+ -+#ifdef CHROMIUM -+ case rfbChromiumStop: -+ -+ if ((n = ReadExact(cl->sock, ((char *)&msg) + 1, -+ sz_rfbChromiumStopMsg - 1)) <= 0) { -+ if (n != 0) -+ rfbLogPerror("rfbProcessClientNormalMessage: read"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ /* would we use msg.csd.port ??? */ -+ -+ cl->chromium_port = 0; -+ -+ /* tear down window information */ -+ { -+ CRWindowTable *wt, *nextWt = NULL; -+ -+ for (wt = windowTable; wt; wt = nextWt) { -+ nextWt = wt->next; -+ xfree(wt); -+ } -+ -+ windowTable = NULL; -+ } -+ -+ return; -+ -+ case rfbChromiumExpose: -+ -+ if ((n = ReadExact(cl->sock, ((char *)&msg) + 1, -+ sz_rfbChromiumExposeMsg - 1)) <= 0) { -+ if (n != 0) -+ rfbLogPerror("rfbProcessClientNormalMessage: read"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ /* find the window and re-expose it */ -+ { -+ CRWindowTable *wt, *nextWt = NULL; -+ -+ for (wt = windowTable; wt; wt = nextWt) { -+ nextWt = wt->next; -+ if (wt->CRwinId == msg.cse.winid) { -+ WindowPtr pWin; -+ pWin = LookupIDByType(wt->XwinId, RT_WINDOW); -+ if (pWin) { -+ miSendExposures(pWin, &pWin->clipList, -+ pWin->drawable.x, -+ pWin->drawable.y); -+ FlushAllOutput(); -+ } -+ } -+ } -+ } -+ -+ return; -+#endif -+ -+ default: -+ -+ rfbLog("rfbProcessClientNormalMessage: unknown message type %d\n", -+ msg.type); -+ rfbLog(" ... closing connection\n"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+} -+ -+ -+ -+/* -+ * rfbSendFramebufferUpdate - send the currently pending framebuffer update to -+ * the RFB client. -+ */ -+ -+Bool -+rfbSendFramebufferUpdate(pScreen, cl) -+ ScreenPtr pScreen; -+ rfbClientPtr cl; -+{ -+ VNCSCREENPTR(pScreen); -+ int i; -+ int nUpdateRegionRects; -+ rfbFramebufferUpdateMsg *fu = (rfbFramebufferUpdateMsg *)pVNC->updateBuf; -+ RegionRec updateRegion, updateCopyRegion; -+ int dx, dy; -+ Bool sendCursorShape = FALSE; -+ Bool sendCursorPos = FALSE; -+ -+ /* -+ * If this client understands cursor shape updates, cursor should be -+ * removed from the framebuffer. Otherwise, make sure it's put up. -+ */ -+ -+#if XFREE86VNC -+ if (cl->enableCursorShapeUpdates) { -+ if (pVNC->cursorIsDrawn) -+ rfbSpriteRemoveCursor(pScreen); -+ if (!pVNC->cursorIsDrawn && cl->cursorWasChanged) -+ sendCursorShape = TRUE; -+ } else { -+ if (!pVNC->cursorIsDrawn) -+ rfbSpriteRestoreCursor(pScreen); -+ } -+#else -+ if (cl->enableCursorShapeUpdates) -+ if (cl->cursorWasChanged) -+ sendCursorShape = TRUE; -+#endif -+ -+ /* -+ * Do we plan to send cursor position update? -+ */ -+ -+ if (cl->enableCursorPosUpdates && cl->cursorWasMoved) -+ sendCursorPos = TRUE; -+ -+ /* -+ * The modifiedRegion may overlap the destination copyRegion. We remove -+ * any overlapping bits from the copyRegion (since they'd only be -+ * overwritten anyway). -+ */ -+ -+ REGION_SUBTRACT(pScreen, &cl->copyRegion, &cl->copyRegion, -+ &cl->modifiedRegion); -+ -+ /* -+ * The client is interested in the region requestedRegion. The region -+ * which should be updated now is the intersection of requestedRegion -+ * and the union of modifiedRegion and copyRegion. If it's empty then -+ * no update is needed. -+ */ -+ -+ REGION_NULL(pScreen,&updateRegion); -+ REGION_UNION(pScreen, &updateRegion, &cl->copyRegion, -+ &cl->modifiedRegion); -+ REGION_INTERSECT(pScreen, &updateRegion, &cl->requestedRegion, -+ &updateRegion); -+ -+ if ( !REGION_NOTEMPTY(pScreen,&updateRegion) && -+ !sendCursorShape && !sendCursorPos ) { -+ REGION_UNINIT(pScreen,&updateRegion); -+ return TRUE; -+ } -+ -+ /* -+ * We assume that the client doesn't have any pixel data outside the -+ * requestedRegion. In other words, both the source and destination of a -+ * copy must lie within requestedRegion. So the region we can send as a -+ * copy is the intersection of the copyRegion with both the requestedRegion -+ * and the requestedRegion translated by the amount of the copy. We set -+ * updateCopyRegion to this. -+ */ -+ -+ REGION_NULL(pScreen,&updateCopyRegion); -+ REGION_INTERSECT(pScreen, &updateCopyRegion, &cl->copyRegion, -+ &cl->requestedRegion); -+ REGION_TRANSLATE(pScreen, &cl->requestedRegion, cl->copyDX, cl->copyDY); -+ REGION_INTERSECT(pScreen, &updateCopyRegion, &updateCopyRegion, -+ &cl->requestedRegion); -+ dx = cl->copyDX; -+ dy = cl->copyDY; -+ -+ /* -+ * Next we remove updateCopyRegion from updateRegion so that updateRegion -+ * is the part of this update which is sent as ordinary pixel data (i.e not -+ * a copy). -+ */ -+ -+ REGION_SUBTRACT(pScreen, &updateRegion, &updateRegion, &updateCopyRegion); -+ -+ /* -+ * Finally we leave modifiedRegion to be the remainder (if any) of parts of -+ * the screen which are modified but outside the requestedRegion. We also -+ * empty both the requestedRegion and the copyRegion - note that we never -+ * carry over a copyRegion for a future update. -+ */ -+ -+ REGION_UNION(pScreen, &cl->modifiedRegion, &cl->modifiedRegion, -+ &cl->copyRegion); -+ REGION_SUBTRACT(pScreen, &cl->modifiedRegion, &cl->modifiedRegion, -+ &updateRegion); -+ REGION_SUBTRACT(pScreen, &cl->modifiedRegion, &cl->modifiedRegion, -+ &updateCopyRegion); -+ -+ REGION_EMPTY(pScreen, &cl->requestedRegion); -+ REGION_EMPTY(pScreen, &cl->copyRegion); -+ cl->copyDX = 0; -+ cl->copyDY = 0; -+ -+ /* -+ * Now send the update. -+ */ -+ -+ cl->rfbFramebufferUpdateMessagesSent++; -+ -+ if (cl->preferredEncoding == rfbEncodingCoRRE) { -+ nUpdateRegionRects = 0; -+ -+ for (i = 0; i < REGION_NUM_RECTS(&updateRegion); i++) { -+ int x = REGION_RECTS(&updateRegion)[i].x1; -+ int y = REGION_RECTS(&updateRegion)[i].y1; -+ int w = REGION_RECTS(&updateRegion)[i].x2 - x; -+ int h = REGION_RECTS(&updateRegion)[i].y2 - y; -+ nUpdateRegionRects += (((w-1) / cl->correMaxWidth + 1) -+ * ((h-1) / cl->correMaxHeight + 1)); -+ } -+ } else if (cl->preferredEncoding == rfbEncodingZlib) { -+ nUpdateRegionRects = 0; -+ -+ for (i = 0; i < REGION_NUM_RECTS(&updateRegion); i++) { -+ int x = REGION_RECTS(&updateRegion)[i].x1; -+ int y = REGION_RECTS(&updateRegion)[i].y1; -+ int w = REGION_RECTS(&updateRegion)[i].x2 - x; -+ int h = REGION_RECTS(&updateRegion)[i].y2 - y; -+ nUpdateRegionRects += (((h-1) / (ZLIB_MAX_SIZE( w ) / w)) + 1); -+ } -+ } else if (cl->preferredEncoding == rfbEncodingTight) { -+ nUpdateRegionRects = 0; -+ -+ for (i = 0; i < REGION_NUM_RECTS(&updateRegion); i++) { -+ int x = REGION_RECTS(&updateRegion)[i].x1; -+ int y = REGION_RECTS(&updateRegion)[i].y1; -+ int w = REGION_RECTS(&updateRegion)[i].x2 - x; -+ int h = REGION_RECTS(&updateRegion)[i].y2 - y; -+ int n = rfbNumCodedRectsTight(cl, x, y, w, h); -+ if (n == 0) { -+ nUpdateRegionRects = 0xFFFF; -+ break; -+ } -+ nUpdateRegionRects += n; -+ } -+ } else { -+ nUpdateRegionRects = REGION_NUM_RECTS(&updateRegion); -+ } -+ -+ fu->type = rfbFramebufferUpdate; -+ if (nUpdateRegionRects != 0xFFFF) { -+ fu->nRects = Swap16IfLE(REGION_NUM_RECTS(&updateCopyRegion) + -+ nUpdateRegionRects + -+ !!sendCursorShape + !!sendCursorPos); -+ } else { -+ fu->nRects = 0xFFFF; -+ } -+ pVNC->ublen = sz_rfbFramebufferUpdateMsg; -+ -+ if (sendCursorShape) { -+ cl->cursorWasChanged = FALSE; -+ if (!rfbSendCursorShape(cl, pScreen)) -+ return FALSE; -+ } -+ -+ if (sendCursorPos) { -+ cl->cursorWasMoved = FALSE; -+ if (!rfbSendCursorPos(cl, pScreen)) -+ return FALSE; -+ } -+ -+ if (REGION_NOTEMPTY(pScreen,&updateCopyRegion)) { -+ if (!rfbSendCopyRegion(cl,&updateCopyRegion,dx,dy)) { -+ REGION_UNINIT(pScreen,&updateRegion); -+ REGION_UNINIT(pScreen,&updateCopyRegion); -+ return FALSE; -+ } -+ } -+ -+ REGION_UNINIT(pScreen,&updateCopyRegion); -+ -+ for (i = 0; i < REGION_NUM_RECTS(&updateRegion); i++) { -+ int x = REGION_RECTS(&updateRegion)[i].x1; -+ int y = REGION_RECTS(&updateRegion)[i].y1; -+ int w = REGION_RECTS(&updateRegion)[i].x2 - x; -+ int h = REGION_RECTS(&updateRegion)[i].y2 - y; -+ -+ cl->rfbRawBytesEquivalent += (sz_rfbFramebufferUpdateRectHeader -+ + w * (cl->format.bitsPerPixel / 8) * h); -+ -+ switch (cl->preferredEncoding) { -+ case rfbEncodingRaw: -+ if (!rfbSendRectEncodingRaw(cl, x, y, w, h)) { -+ REGION_UNINIT(pScreen,&updateRegion); -+ return FALSE; -+ } -+ break; -+ case rfbEncodingRRE: -+ if (!rfbSendRectEncodingRRE(cl, x, y, w, h)) { -+ REGION_UNINIT(pScreen,&updateRegion); -+ return FALSE; -+ } -+ break; -+ case rfbEncodingCoRRE: -+ if (!rfbSendRectEncodingCoRRE(cl, x, y, w, h)) { -+ REGION_UNINIT(pScreen,&updateRegion); -+ return FALSE; -+ } -+ break; -+ case rfbEncodingHextile: -+ if (!rfbSendRectEncodingHextile(cl, x, y, w, h)) { -+ REGION_UNINIT(pScreen,&updateRegion); -+ return FALSE; -+ } -+ break; -+ case rfbEncodingZlib: -+ if (!rfbSendRectEncodingZlib(cl, x, y, w, h)) { -+ REGION_UNINIT(pScreen,&updateRegion); -+ return FALSE; -+ } -+ break; -+ case rfbEncodingTight: -+ if (!rfbSendRectEncodingTight(cl, x, y, w, h)) { -+ REGION_UNINIT(pScreen,&updateRegion); -+ return FALSE; -+ } -+ break; -+ } -+ } -+ -+ REGION_UNINIT(pScreen,&updateRegion); -+ -+ if (nUpdateRegionRects == 0xFFFF && !rfbSendLastRectMarker(cl)) -+ return FALSE; -+ -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ -+ return TRUE; -+} -+ -+ -+ -+/* -+ * Send the copy region as a string of CopyRect encoded rectangles. -+ * The only slightly tricky thing is that we should send the messages in -+ * the correct order so that an earlier CopyRect will not corrupt the source -+ * of a later one. -+ */ -+ -+static Bool -+rfbSendCopyRegion(cl, reg, dx, dy) -+ rfbClientPtr cl; -+ RegionPtr reg; -+ int dx, dy; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ int nrects, nrectsInBand, x_inc, y_inc, thisRect, firstInNextBand; -+ int x, y, w, h; -+ rfbFramebufferUpdateRectHeader rect; -+ rfbCopyRect cr; -+ -+ nrects = REGION_NUM_RECTS(reg); -+ -+ if (dx <= 0) { -+ x_inc = 1; -+ } else { -+ x_inc = -1; -+ } -+ -+ if (dy <= 0) { -+ thisRect = 0; -+ y_inc = 1; -+ } else { -+ thisRect = nrects - 1; -+ y_inc = -1; -+ } -+ -+ while (nrects > 0) { -+ -+ firstInNextBand = thisRect; -+ nrectsInBand = 0; -+ -+ while ((nrects > 0) && -+ (REGION_RECTS(reg)[firstInNextBand].y1 -+ == REGION_RECTS(reg)[thisRect].y1)) -+ { -+ firstInNextBand += y_inc; -+ nrects--; -+ nrectsInBand++; -+ } -+ -+ if (x_inc != y_inc) { -+ thisRect = firstInNextBand - y_inc; -+ } -+ -+ while (nrectsInBand > 0) { -+ if ((pVNC->ublen + sz_rfbFramebufferUpdateRectHeader -+ + sz_rfbCopyRect) > UPDATE_BUF_SIZE) -+ { -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ } -+ -+ x = REGION_RECTS(reg)[thisRect].x1; -+ y = REGION_RECTS(reg)[thisRect].y1; -+ w = REGION_RECTS(reg)[thisRect].x2 - x; -+ h = REGION_RECTS(reg)[thisRect].y2 - y; -+ -+ rect.r.x = Swap16IfLE(x); -+ rect.r.y = Swap16IfLE(y); -+ rect.r.w = Swap16IfLE(w); -+ rect.r.h = Swap16IfLE(h); -+ rect.encoding = Swap32IfLE(rfbEncodingCopyRect); -+ -+ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&rect, -+ sz_rfbFramebufferUpdateRectHeader); -+ pVNC->ublen += sz_rfbFramebufferUpdateRectHeader; -+ -+ cr.srcX = Swap16IfLE(x - dx); -+ cr.srcY = Swap16IfLE(y - dy); -+ -+ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&cr, sz_rfbCopyRect); -+ pVNC->ublen += sz_rfbCopyRect; -+ -+ cl->rfbRectanglesSent[rfbEncodingCopyRect]++; -+ cl->rfbBytesSent[rfbEncodingCopyRect] -+ += sz_rfbFramebufferUpdateRectHeader + sz_rfbCopyRect; -+ -+ thisRect += x_inc; -+ nrectsInBand--; -+ } -+ -+ thisRect = firstInNextBand; -+ } -+ -+ return TRUE; -+} -+ -+ -+/* -+ * Send a given rectangle in raw encoding (rfbEncodingRaw). -+ */ -+ -+Bool -+rfbSendRectEncodingRaw(cl, x, y, w, h) -+ rfbClientPtr cl; -+ int x, y, w, h; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ rfbFramebufferUpdateRectHeader rect; -+ int nlines; -+ int bytesPerLine = w * (cl->format.bitsPerPixel / 8); -+ unsigned char *fbptr = NULL; -+ int newy = 0; -+ -+ if (pVNC->useGetImage) { -+ newy = y; -+ } else { -+ fbptr = (pVNC->pfbMemory + (pVNC->paddedWidthInBytes * y) -+ + (x * (pVNC->bitsPerPixel / 8))); -+ } -+ -+ /* Flush the buffer to guarantee correct alignment for translateFn(). */ -+ if (pVNC->ublen > 0) { -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ } -+ -+ rect.r.x = Swap16IfLE(x); -+ rect.r.y = Swap16IfLE(y); -+ rect.r.w = Swap16IfLE(w); -+ rect.r.h = Swap16IfLE(h); -+ rect.encoding = Swap32IfLE(rfbEncodingRaw); -+ -+ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&rect,sz_rfbFramebufferUpdateRectHeader); -+ pVNC->ublen += sz_rfbFramebufferUpdateRectHeader; -+ -+ cl->rfbRectanglesSent[rfbEncodingRaw]++; -+ cl->rfbBytesSent[rfbEncodingRaw] -+ += sz_rfbFramebufferUpdateRectHeader + bytesPerLine * h; -+ -+ nlines = (UPDATE_BUF_SIZE - pVNC->ublen) / bytesPerLine; -+ -+ while (TRUE) { -+ if (nlines > h) -+ nlines = h; -+ -+ if (pVNC->useGetImage) { -+ (*cl->pScreen->GetImage)((DrawablePtr)WindowTable[cl->pScreen->myNum], x, newy, w, nlines, ZPixmap, ~0, &pVNC->updateBuf[pVNC->ublen]); -+ newy += nlines; -+ } else { -+ (*cl->translateFn)(cl->pScreen, cl->translateLookupTable, &pVNC->rfbServerFormat, -+ &cl->format, fbptr, &pVNC->updateBuf[pVNC->ublen], -+ pVNC->paddedWidthInBytes, w, nlines, x, y); -+ } -+ -+ pVNC->ublen += nlines * bytesPerLine; -+ h -= nlines; -+ -+ if (h == 0) /* rect fitted in buffer, do next one */ -+ return TRUE; -+ -+ /* buffer full - flush partial rect and do another nlines */ -+ -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ -+ if (!pVNC->useGetImage) -+ fbptr += (pVNC->paddedWidthInBytes * nlines); -+ -+ nlines = (UPDATE_BUF_SIZE - pVNC->ublen) / bytesPerLine; -+ if (nlines == 0) { -+ rfbLog("rfbSendRectEncodingRaw: send buffer too small for %d " -+ "bytes per line\n", bytesPerLine); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return FALSE; -+ } -+ } -+} -+ -+ -+/* -+ * Send an empty rectangle with encoding field set to value of -+ * rfbEncodingLastRect to notify client that this is the last -+ * rectangle in framebuffer update ("LastRect" extension of RFB -+ * protocol). -+ */ -+ -+static Bool -+rfbSendLastRectMarker(cl) -+ rfbClientPtr cl; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ rfbFramebufferUpdateRectHeader rect; -+ -+ if (pVNC->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) { -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ } -+ -+ rect.encoding = Swap32IfLE(rfbEncodingLastRect); -+ rect.r.x = 0; -+ rect.r.y = 0; -+ rect.r.w = 0; -+ rect.r.h = 0; -+ -+ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&rect,sz_rfbFramebufferUpdateRectHeader); -+ pVNC->ublen += sz_rfbFramebufferUpdateRectHeader; -+ -+ cl->rfbLastRectMarkersSent++; -+ cl->rfbLastRectBytesSent += sz_rfbFramebufferUpdateRectHeader; -+ -+ return TRUE; -+} -+ -+ -+/* -+ * Send the contents of pVNC->updateBuf. Returns 1 if successful, -1 if -+ * not (errno should be set). -+ */ -+ -+Bool -+rfbSendUpdateBuf(cl) -+ rfbClientPtr cl; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ -+ /* -+ int i; -+ for (i = 0; i < pVNC->ublen; i++) { -+ rfbLog("%02x ",((unsigned char *)pVNC->updateBuf)[i]); -+ } -+ rfbLog("\n"); -+ */ -+ -+ if (pVNC->ublen > 0 && WriteExact(cl->sock, pVNC->updateBuf, pVNC->ublen) < 0) { -+ rfbLogPerror("rfbSendUpdateBuf: write"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return FALSE; -+ } -+ -+ pVNC->ublen = 0; -+ return TRUE; -+} -+ -+ -+ -+/* -+ * rfbSendSetColourMapEntries sends a SetColourMapEntries message to the -+ * client, using values from the currently installed colormap. -+ */ -+ -+Bool -+rfbSendSetColourMapEntries(cl, firstColour, nColours) -+ rfbClientPtr cl; -+ int firstColour; -+ int nColours; -+{ -+#if !XFREE86VNC -+ VNCSCREENPTR(cl->pScreen); -+#endif -+ char buf[sz_rfbSetColourMapEntriesMsg + 256 * 3 * 2]; -+ rfbSetColourMapEntriesMsg *scme = (rfbSetColourMapEntriesMsg *)buf; -+ CARD16 *rgb = (CARD16 *)(&buf[sz_rfbSetColourMapEntriesMsg]); -+ EntryPtr pent; -+ EntryPtr redEntry, greenEntry, blueEntry; -+ unsigned short redPart, greenPart, bluePart; -+ int i, len; -+ -+ scme->type = rfbSetColourMapEntries; -+ scme->nColours = Swap16IfLE(nColours); -+ -+ len = sz_rfbSetColourMapEntriesMsg; -+ -+ /* PseudoColor */ -+#if XFREE86VNC -+ if (miInstalledMaps[cl->pScreen->myNum]->class == PseudoColor) { -+#else -+ if (pVNC->rfbInstalledColormap->class == PseudoColor) { -+#endif -+ scme->firstColour = Swap16IfLE(firstColour); -+#if XFREE86VNC -+ pent = (EntryPtr)&miInstalledMaps[cl->pScreen->myNum]->red[firstColour]; -+#else -+ pent = (EntryPtr)&pVNC->rfbInstalledColormap->red[firstColour]; -+#endif -+ for (i = 0; i < nColours; i++) { -+ if (pent->fShared) { -+ rgb[i*3] = Swap16IfLE(pent->co.shco.red->color); -+ rgb[i*3+1] = Swap16IfLE(pent->co.shco.green->color); -+ rgb[i*3+2] = Swap16IfLE(pent->co.shco.blue->color); -+ } else { -+ rgb[i*3] = Swap16IfLE(pent->co.local.red); -+ rgb[i*3+1] = Swap16IfLE(pent->co.local.green); -+ rgb[i*3+2] = Swap16IfLE(pent->co.local.blue); -+ } -+ pent++; -+ } -+ } -+ -+ else { -+ -+ /* Break the DirectColor pixel into its r/g/b components */ -+#if XFREE86VNC -+ redPart = (firstColour & miInstalledMaps[cl->pScreen->myNum]->pVisual->redMask) -+ >> miInstalledMaps[cl->pScreen->myNum]->pVisual->offsetRed; -+ greenPart = (firstColour & miInstalledMaps[cl->pScreen->myNum]->pVisual->greenMask) -+ >> miInstalledMaps[cl->pScreen->myNum]->pVisual->offsetGreen; -+ bluePart = (firstColour & miInstalledMaps[cl->pScreen->myNum]->pVisual->blueMask) -+ >> miInstalledMaps[cl->pScreen->myNum]->pVisual->offsetBlue; -+#else -+ redPart = (firstColour & pVNC->rfbInstalledColormap->pVisual->redMask) -+ >> pVNC->rfbInstalledColormap->pVisual->offsetRed; -+ greenPart = (firstColour & pVNC->rfbInstalledColormap->pVisual->greenMask) -+ >> pVNC->rfbInstalledColormap->pVisual->offsetGreen; -+ bluePart = (firstColour & pVNC->rfbInstalledColormap->pVisual->blueMask) -+ >> pVNC->rfbInstalledColormap->pVisual->offsetBlue; -+#endif -+ -+ /* -+ * The firstColour field is only 16 bits. To support 24-bit pixels we -+ * sneak the red component in the 8-bit padding field which we renamed -+ * to redIndex. Green and blue are in firstColour (MSB, LSB respectively). -+ */ -+ scme->redIndex = Swap16IfLE(redPart); -+ scme->firstColour = Swap16IfLE((greenPart << 8) | bluePart); -+ -+#if XFREE86VNC -+ redEntry = (EntryPtr)&miInstalledMaps[cl->pScreen->myNum]->red[redPart]; -+ greenEntry = (EntryPtr)&miInstalledMaps[cl->pScreen->myNum]->green[greenPart]; -+ blueEntry = (EntryPtr)&miInstalledMaps[cl->pScreen->myNum]->blue[bluePart]; -+#else -+ redEntry = (EntryPtr)&pVNC->rfbInstalledColormap->red[redPart]; -+ greenEntry = (EntryPtr)&pVNC->rfbInstalledColormap->green[greenPart]; -+ blueEntry = (EntryPtr)&pVNC->rfbInstalledColormap->blue[bluePart]; -+#endif -+ for (i = 0; i < nColours; i++) { -+ if (redEntry->fShared) -+ rgb[i*3] = Swap16IfLE(redEntry->co.shco.red->color); -+ else -+ rgb[i*3] = Swap16IfLE(redEntry->co.local.red); -+ -+ if (greenEntry->fShared) -+ rgb[i*3+1] = Swap16IfLE(greenEntry->co.shco.green->color); -+ else -+ rgb[i*3+1] = Swap16IfLE(greenEntry->co.local.green); -+ -+ if (blueEntry->fShared) -+ rgb[i*3+2] = Swap16IfLE(blueEntry->co.shco.blue->color); -+ else -+ rgb[i*3+2] = Swap16IfLE(blueEntry->co.local.blue); -+ -+ redEntry++; -+ greenEntry++; -+ blueEntry++; -+ } -+ } -+ -+ len += nColours * 3 * 2; -+ -+ if (WriteExact(cl->sock, buf, len) < 0) { -+ rfbLogPerror("rfbSendSetColourMapEntries: write"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return FALSE; -+ } -+ return TRUE; -+} -+ -+ -+/* -+ * rfbSendBell sends a Bell message to all the clients. -+ */ -+ -+void -+rfbSendBell() -+{ -+ rfbClientPtr cl, nextCl; -+ rfbBellMsg b; -+ -+ for (cl = rfbClientHead; cl; cl = nextCl) { -+ nextCl = cl->next; -+ b.type = rfbBell; -+ if (WriteExact(cl->sock, (char *)&b, sz_rfbBellMsg) < 0) { -+ rfbLogPerror("rfbSendBell: write"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ } -+ } -+} -+ -+#ifdef CHROMIUM -+#ifdef sun -+extern int inet_aton(const char *cp, struct in_addr *inp); -+#endif -+ -+/** -+ * Tell the VNC viewers to start a new crserver process. -+ */ -+void -+rfbSendChromiumStart(unsigned int ipaddress, unsigned int port) -+{ -+ rfbClientPtr cl, nextCl; -+ rfbChromiumStartMsg scd; -+ struct in_addr ip; -+ unsigned int vncipaddress; -+ -+ for (cl = rfbClientHead; cl; cl = nextCl) { -+ nextCl = cl->next; -+ if (!cl->enableChromiumEncoding) -+ continue; -+ inet_aton(cl->host, &ip); -+ memcpy(&vncipaddress, &ip, sizeof(unsigned int)); -+ if (ipaddress == vncipaddress && !cl->chromium_port) { -+ cl->chromium_port = port; -+ scd.type = rfbChromiumStart; -+ scd.port = port; -+ if (WriteExact(cl->sock, (char *)&scd, -+ sz_rfbChromiumStartMsg) < 0) { -+ rfbLogPerror("rfbSendChromiumStart: write"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ } -+ /* We only start one client at at time, so break now! */ -+ break; -+ } -+ } -+} -+ -+/** -+ * Begin tracking the size, position, visibility and cliprect info for the -+ * given Chromium/X window. -+ */ -+void -+rfbChromiumMonitorWindowID(unsigned int cr_windowid, unsigned long windowid) -+{ -+ CRWindowTable *nextRec; -+ CRWindowTable *wt, *nextWt = NULL; -+ -+ /* See if we're already managing this window */ -+ for (wt = windowTable; wt; wt = nextWt) { -+ nextWt = wt->next; -+ /* and if so, update it's window ID */ -+ if (wt->CRwinId == cr_windowid) { -+ wt->XwinId = windowid; -+ return; -+ } -+ } -+ -+ /* o.k, new window so create new slot information */ -+ nextRec = (CRWindowTable *)xalloc(sizeof(CRWindowTable)); -+ -+ if (!nextRec) -+ { -+ rfbLog("OUCH, Chromium can't monitor window ID\n"); -+ return; -+ } -+ -+ nextRec->next = NULL; -+ nextRec->CRwinId = cr_windowid; -+ nextRec->XwinId = windowid; -+ nextRec->clipRects = NULL; -+ nextRec->numRects = 0; -+ -+ if (!windowTable) -+ windowTable = nextRec; -+ else -+ { -+ for (wt = windowTable; wt; wt = nextWt) { -+ nextWt = wt->next; -+ if (!wt->next) /* found the next slot */ -+ wt->next = nextRec; -+ } -+ } -+} -+ -+/** -+ * Send new window position/size info to all VNC clients who want this info. -+ */ -+void -+rfbSendChromiumMoveResizeWindow(unsigned int winid, int x, int y, unsigned int w, unsigned int h) -+{ -+ rfbClientPtr cl, nextCl; -+ rfbChromiumMoveResizeWindowMsg scm; -+ -+ for (cl = rfbClientHead; cl; cl = nextCl) { -+ nextCl = cl->next; -+ if (!cl->enableChromiumEncoding) -+ continue; -+ if (cl->chromium_port) { -+ scm.type = rfbChromiumMoveResizeWindow; -+ scm.winid = winid; -+ scm.x = x; -+ scm.y = y; -+ scm.w = w; -+ scm.h = h; -+ if (WriteExact(cl->sock, (char *)&scm, -+ sz_rfbChromiumMoveResizeWindowMsg) < 0) { -+ rfbLogPerror("rfbSendChromiumMoveResizeWindow: write"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ continue; -+ } -+ } -+ } -+} -+ -+/** -+ * Send the new cliprect info for the given window to all VNC clients who -+ * want this info. -+ */ -+void -+rfbSendChromiumClipList(unsigned int winid, BoxPtr pClipRects, int numClipRects) -+{ -+ rfbClientPtr cl, nextCl; -+ rfbChromiumClipListMsg sccl; -+ int len = sizeof(BoxRec) * numClipRects; -+ -+ for (cl = rfbClientHead; cl; cl = nextCl) { -+ nextCl = cl->next; -+ if (!cl->enableChromiumEncoding) -+ continue; -+ if (cl->chromium_port) { -+ sccl.type = rfbChromiumClipList; -+ sccl.winid = winid; -+ sccl.length = Swap32IfLE(len); -+ if (WriteExact(cl->sock, (char *)&sccl, -+ sz_rfbChromiumClipListMsg) < 0) { -+ rfbLogPerror("rfbSendChromiumClipList: write"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ continue; -+ } -+ if (WriteExact(cl->sock, (char *)pClipRects, len) < 0) { -+ rfbLogPerror("rfbSendChromiumClipList: write"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ continue; -+ } -+ } -+ } -+} -+ -+/** -+ * Tell VNC clients about the visibility status of given window. -+ */ -+void -+rfbSendChromiumWindowShow(unsigned int winid, unsigned int show) -+{ -+ rfbClientPtr cl, nextCl; -+ rfbChromiumWindowShowMsg scws; -+ -+ for (cl = rfbClientHead; cl; cl = nextCl) { -+ nextCl = cl->next; -+ if (!cl->enableChromiumEncoding) -+ continue; -+ if (cl->chromium_port) { -+ scws.type = rfbChromiumWindowShow; -+ scws.winid = winid; -+ scws.show = show; -+ if (WriteExact(cl->sock, (char *)&scws, -+ sz_rfbChromiumWindowShowMsg) < 0) { -+ rfbLogPerror("rfbSendChromiumWindowShow: write"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ continue; -+ } -+ } -+ } -+} -+#endif /* CHROMIUM */ -+ -+/* -+ * rfbSendServerCutText sends a ServerCutText message to all the clients. -+ */ -+ -+void -+rfbSendServerCutText(char *str, int len) -+{ -+ rfbClientPtr cl, nextCl = NULL; -+ rfbServerCutTextMsg sct; -+ -+ for (cl = rfbClientHead; cl; cl = nextCl) { -+ if (cl->state != RFB_NORMAL) continue; -+ nextCl = cl->next; -+ sct.type = rfbServerCutText; -+ sct.length = Swap32IfLE(len); -+ if (WriteExact(cl->sock, (char *)&sct, -+ sz_rfbServerCutTextMsg) < 0) { -+ rfbLogPerror("rfbSendServerCutText: write"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ continue; -+ } -+ if (WriteExact(cl->sock, str, len) < 0) { -+ rfbLogPerror("rfbSendServerCutText: write"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ } -+ } -+} -+ -+ -+ -+ -+/***************************************************************************** -+ * -+ * UDP can be used for keyboard and pointer events when the underlying -+ * network is highly reliable. This is really here to support ORL's -+ * videotile, whose TCP implementation doesn't like sending lots of small -+ * packets (such as 100s of pen readings per second!). -+ */ -+ -+void -+rfbNewUDPConnection(sock) -+ int sock; -+{ -+ if (write(sock, &ptrAcceleration, 1) < 0) { -+ rfbLogPerror("rfbNewUDPConnection: write"); -+ } -+} -+ -+/* -+ * Because UDP is a message based service, we can't read the first byte and -+ * then the rest of the packet separately like we do with TCP. We will always -+ * get a whole packet delivered in one go, so we ask read() for the maximum -+ * number of bytes we can possibly get. -+ */ -+ -+void -+rfbProcessUDPInput(ScreenPtr pScreen, int sock) -+{ -+ VNCSCREENPTR(pScreen); -+ int n; -+ rfbClientToServerMsg msg; -+ -+ if ((n = read(sock, (char *)&msg, sizeof(msg))) <= 0) { -+ if (n < 0) { -+ rfbLogPerror("rfbProcessUDPInput: read"); -+ } -+ rfbDisconnectUDPSock(pScreen); -+ return; -+ } -+ -+ switch (msg.type) { -+ -+ case rfbKeyEvent: -+ if (n != sz_rfbKeyEventMsg) { -+ rfbLog("rfbProcessUDPInput: key event incorrect length\n"); -+ rfbDisconnectUDPSock(pScreen); -+ return; -+ } -+ if (!pVNC->rfbViewOnly) { -+ KbdAddEvent(msg.ke.down, (KeySym)Swap32IfLE(msg.ke.key), 0); -+ } -+ break; -+ -+ case rfbPointerEvent: -+ if (n != sz_rfbPointerEventMsg) { -+ rfbLog("rfbProcessUDPInput: ptr event incorrect length\n"); -+ rfbDisconnectUDPSock(pScreen); -+ return; -+ } -+ if (!pVNC->rfbViewOnly) { -+ PtrAddEvent(msg.pe.buttonMask, -+ Swap16IfLE(msg.pe.x), Swap16IfLE(msg.pe.y), 0); -+ } -+ break; -+ -+ default: -+ rfbLog("rfbProcessUDPInput: unknown message type %d\n", -+ msg.type); -+ rfbDisconnectUDPSock(pScreen); -+ } -+} -diff --git a/hw/dmx/vnc/rre.c b/hw/dmx/vnc/rre.c -new file mode 100644 -index 0000000..9e63ed7 ---- /dev/null -+++ b/hw/dmx/vnc/rre.c -@@ -0,0 +1,325 @@ -+/* -+ * rre.c -+ * -+ * Routines to implement Rise-and-Run-length Encoding (RRE). This -+ * code is based on krw's original javatel rfbserver. -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ */ -+ -+/* -+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. -+ * -+ * This is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This software is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this software; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -+ * USA. -+ */ -+ -+#include -+#include -+#include -+#include "rfb.h" -+ -+/* -+ * rreBeforeBuf contains pixel data in the client's format. -+ * rreAfterBuf contains the RRE encoded version. If the RRE encoded version is -+ * larger than the raw data or if it exceeds rreAfterBufSize then -+ * raw encoding is used instead. -+ */ -+ -+static int rreBeforeBufSize = 0; -+static char *rreBeforeBuf = NULL; -+ -+static int rreAfterBufSize = 0; -+static char *rreAfterBuf = NULL; -+static int rreAfterBufLen; -+ -+static int subrectEncode8(CARD8 *data, int w, int h); -+static int subrectEncode16(CARD16 *data, int w, int h); -+static int subrectEncode32(CARD32 *data, int w, int h); -+static CARD32 getBgColour(char *data, int size, int bpp); -+ -+ -+/* -+ * rfbSendRectEncodingRRE - send a given rectangle using RRE encoding. -+ */ -+ -+Bool -+rfbSendRectEncodingRRE(cl, x, y, w, h) -+ rfbClientPtr cl; -+ int x, y, w, h; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ rfbFramebufferUpdateRectHeader rect; -+ rfbRREHeader hdr; -+ int nSubrects; -+ int i; -+ unsigned char *fbptr = (pVNC->pfbMemory + (pVNC->paddedWidthInBytes * y) -+ + (x * (pVNC->bitsPerPixel / 8))); -+ -+ int maxRawSize = (pVNC->width * pVNC->height -+ * (cl->format.bitsPerPixel / 8)); -+ -+ if (rreBeforeBufSize < maxRawSize) { -+ rreBeforeBufSize = maxRawSize; -+ if (rreBeforeBuf == NULL) -+ rreBeforeBuf = (char *)xalloc(rreBeforeBufSize); -+ else -+ rreBeforeBuf = (char *)xrealloc(rreBeforeBuf, rreBeforeBufSize); -+ } -+ -+ if (rreAfterBufSize < maxRawSize) { -+ rreAfterBufSize = maxRawSize; -+ if (rreAfterBuf == NULL) -+ rreAfterBuf = (char *)xalloc(rreAfterBufSize); -+ else -+ rreAfterBuf = (char *)xrealloc(rreAfterBuf, rreAfterBufSize); -+ } -+ -+ (*cl->translateFn)(cl->pScreen, cl->translateLookupTable, -+ &pVNC->rfbServerFormat, -+ &cl->format, fbptr, rreBeforeBuf, -+ pVNC->paddedWidthInBytes, w, h, x, y); -+ -+ switch (cl->format.bitsPerPixel) { -+ case 8: -+ nSubrects = subrectEncode8((CARD8 *)rreBeforeBuf, w, h); -+ break; -+ case 16: -+ nSubrects = subrectEncode16((CARD16 *)rreBeforeBuf, w, h); -+ break; -+ case 32: -+ nSubrects = subrectEncode32((CARD32 *)rreBeforeBuf, w, h); -+ break; -+ default: -+ rfbLog("getBgColour: bpp %d?\n",cl->format.bitsPerPixel); -+ exit(1); -+ } -+ -+ if (nSubrects < 0) { -+ -+ /* RRE encoding was too large, use raw */ -+ -+ return rfbSendRectEncodingRaw(cl, x, y, w, h); -+ } -+ -+ cl->rfbRectanglesSent[rfbEncodingRRE]++; -+ cl->rfbBytesSent[rfbEncodingRRE] += (sz_rfbFramebufferUpdateRectHeader -+ + sz_rfbRREHeader + rreAfterBufLen); -+ -+ if (pVNC->ublen + sz_rfbFramebufferUpdateRectHeader + sz_rfbRREHeader -+ > UPDATE_BUF_SIZE) -+ { -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ } -+ -+ rect.r.x = Swap16IfLE(x); -+ rect.r.y = Swap16IfLE(y); -+ rect.r.w = Swap16IfLE(w); -+ rect.r.h = Swap16IfLE(h); -+ rect.encoding = Swap32IfLE(rfbEncodingRRE); -+ -+ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&rect, -+ sz_rfbFramebufferUpdateRectHeader); -+ pVNC->ublen += sz_rfbFramebufferUpdateRectHeader; -+ -+ hdr.nSubrects = Swap32IfLE(nSubrects); -+ -+ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&hdr, sz_rfbRREHeader); -+ pVNC->ublen += sz_rfbRREHeader; -+ -+ for (i = 0; i < rreAfterBufLen;) { -+ -+ int bytesToCopy = UPDATE_BUF_SIZE - pVNC->ublen; -+ -+ if (i + bytesToCopy > rreAfterBufLen) { -+ bytesToCopy = rreAfterBufLen - i; -+ } -+ -+ memcpy(&pVNC->updateBuf[pVNC->ublen], &rreAfterBuf[i], bytesToCopy); -+ -+ pVNC->ublen += bytesToCopy; -+ i += bytesToCopy; -+ -+ if (pVNC->ublen == UPDATE_BUF_SIZE) { -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ } -+ } -+ -+ return TRUE; -+} -+ -+ -+ -+/* -+ * subrectEncode() encodes the given multicoloured rectangle as a background -+ * colour overwritten by single-coloured rectangles. It returns the number -+ * of subrectangles in the encoded buffer, or -1 if subrect encoding won't -+ * fit in the buffer. It puts the encoded rectangles in rreAfterBuf. The -+ * single-colour rectangle partition is not optimal, but does find the biggest -+ * horizontal or vertical rectangle top-left anchored to each consecutive -+ * coordinate position. -+ * -+ * The coding scheme is simply [...] where each -+ * is []. -+ */ -+ -+#define DEFINE_SUBRECT_ENCODE(bpp) \ -+static int \ -+subrectEncode##bpp(data,w,h) \ -+ CARD##bpp *data; \ -+ int w; \ -+ int h; \ -+{ \ -+ CARD##bpp cl; \ -+ rfbRectangle subrect; \ -+ int x,y; \ -+ int i,j; \ -+ int hx=0,hy,vx=0,vy; \ -+ int hyflag; \ -+ CARD##bpp *seg; \ -+ CARD##bpp *line; \ -+ int hw,hh,vw,vh; \ -+ int thex,they,thew,theh; \ -+ int numsubs = 0; \ -+ int newLen; \ -+ CARD##bpp bg = (CARD##bpp)getBgColour((char*)data,w*h,bpp); \ -+ \ -+ *((CARD##bpp*)rreAfterBuf) = bg; \ -+ \ -+ rreAfterBufLen = (bpp/8); \ -+ \ -+ for (y=0; y 0) && (i >= hx)) {hy += 1;} else {hyflag = 0;} \ -+ } \ -+ vy = j-1; \ -+ \ -+ /* We now have two possible subrects: (x,y,hx,hy) and (x,y,vx,vy) \ -+ * We'll choose the bigger of the two. \ -+ */ \ -+ hw = hx-x+1; \ -+ hh = hy-y+1; \ -+ vw = vx-x+1; \ -+ vh = vy-y+1; \ -+ \ -+ thex = x; \ -+ they = y; \ -+ \ -+ if ((hw*hh) > (vw*vh)) { \ -+ thew = hw; \ -+ theh = hh; \ -+ } else { \ -+ thew = vw; \ -+ theh = vh; \ -+ } \ -+ \ -+ subrect.x = Swap16IfLE(thex); \ -+ subrect.y = Swap16IfLE(they); \ -+ subrect.w = Swap16IfLE(thew); \ -+ subrect.h = Swap16IfLE(theh); \ -+ \ -+ newLen = rreAfterBufLen + (bpp/8) + sz_rfbRectangle; \ -+ if ((newLen > (w * h * (bpp/8))) || (newLen > rreAfterBufSize)) \ -+ return -1; \ -+ \ -+ numsubs += 1; \ -+ *((CARD##bpp*)(rreAfterBuf + rreAfterBufLen)) = cl; \ -+ rreAfterBufLen += (bpp/8); \ -+ memcpy(&rreAfterBuf[rreAfterBufLen],&subrect,sz_rfbRectangle); \ -+ rreAfterBufLen += sz_rfbRectangle; \ -+ \ -+ /* \ -+ * Now mark the subrect as done. \ -+ */ \ -+ for (j=they; j < (they+theh); j++) { \ -+ for (i=thex; i < (thex+thew); i++) { \ -+ data[j*w+i] = bg; \ -+ } \ -+ } \ -+ } \ -+ } \ -+ } \ -+ \ -+ return numsubs; \ -+} -+ -+DEFINE_SUBRECT_ENCODE(8) -+DEFINE_SUBRECT_ENCODE(16) -+DEFINE_SUBRECT_ENCODE(32) -+ -+ -+/* -+ * getBgColour() gets the most prevalent colour in a byte array. -+ */ -+static CARD32 -+getBgColour(data,size,bpp) -+ char *data; -+ int size; -+ int bpp; -+{ -+ -+#define NUMCLRS 256 -+ -+ static int counts[NUMCLRS]; -+ int i,j,k; -+ -+ int maxcount = 0; -+ CARD8 maxclr = 0; -+ -+ if (bpp != 8) { -+ if (bpp == 16) { -+ return ((CARD16 *)data)[0]; -+ } else if (bpp == 32) { -+ return ((CARD32 *)data)[0]; -+ } else { -+ rfbLog("getBgColour: bpp %d?\n",bpp); -+ exit(1); -+ } -+ } -+ -+ for (i=0; i= NUMCLRS) { -+ rfbLog("getBgColour: unusual colour = %d\n", k); -+ exit(1); -+ } -+ counts[k] += 1; -+ if (counts[k] > maxcount) { -+ maxcount = counts[k]; -+ maxclr = ((CARD8 *)data)[j]; -+ } -+ } -+ -+ return maxclr; -+} -diff --git a/hw/dmx/vnc/sockets.c b/hw/dmx/vnc/sockets.c -new file mode 100644 -index 0000000..6d33435 ---- /dev/null -+++ b/hw/dmx/vnc/sockets.c -@@ -0,0 +1,656 @@ -+/* -+ * sockets.c - deal with TCP & UDP sockets. -+ * -+ * This code should be independent of any changes in the RFB protocol. It just -+ * deals with the X server scheduling stuff, calling rfbNewClientConnection and -+ * rfbProcessClientMessage to actually deal with the protocol. If a socket -+ * needs to be closed for any reason then rfbCloseSock should be called, and -+ * this in turn will call rfbClientConnectionGone. To make an active -+ * connection out, call rfbConnect - note that this does _not_ call -+ * rfbNewClientConnection. -+ * -+ * This file is divided into two types of function. Those beginning with -+ * "rfb" are specific to sockets using the RFB protocol. Those without the -+ * "rfb" prefix are more general socket routines (which are used by the http -+ * code). -+ * -+ * Thanks to Karl Hakimian for pointing out that some platforms return EAGAIN -+ * not EWOULDBLOCK. -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ */ -+ -+/* -+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. -+ * -+ * This is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This software is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this software; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -+ * USA. -+ */ -+ -+#if HAVE_DMX_CONFIG_H -+#include "dmx-config.h" -+#endif -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "windowstr.h" -+ -+#ifndef USE_LIBWRAP -+#define USE_LIBWRAP 0 -+#endif -+#if USE_LIBWRAP -+#include -+#include -+int allow_severity = LOG_INFO; -+int deny_severity = LOG_WARNING; -+#endif -+ -+#include "rfb.h" -+ -+int rfbMaxClientWait = 20000; /* time (ms) after which we decide client has -+ gone away - needed to stop us hanging */ -+ -+static struct sockaddr_in udpRemoteAddr; -+ -+/* -+ * rfbInitSockets sets up the TCP and UDP sockets to listen for RFB -+ * connections. It does nothing if called again. -+ */ -+ -+Bool -+rfbInitSockets(ScreenPtr pScreen) -+{ -+ VNCSCREENPTR(pScreen); -+ -+ if (inetdSock != -1) { -+ const int one = 1; -+ -+ if (fcntl(inetdSock, F_SETFL, O_NONBLOCK) < 0) { -+ rfbLogPerror("fcntl"); -+ return FALSE; -+ } -+ -+ if (setsockopt(inetdSock, IPPROTO_TCP, TCP_NODELAY, -+ (char *)&one, sizeof(one)) < 0) { -+ rfbLogPerror("setsockopt"); -+ return FALSE; -+ } -+ -+ AddEnabledDevice(inetdSock); -+ FD_ZERO(&pVNC->allFds); -+ FD_SET(inetdSock, &pVNC->allFds); -+ pVNC->maxFd = inetdSock; -+ return TRUE; -+ } -+ -+ if (pVNC->rfbPort == 0) { -+ pVNC->rfbPort = 5900 + atoi(display) + pScreen->myNum; -+ } -+ -+ if ((pVNC->rfbListenSock = ListenOnTCPPort(pScreen, pVNC->rfbPort)) < 0) { -+ rfbLogPerror("ListenOnTCPPort"); -+ pVNC->rfbPort = 0; -+ return FALSE; -+ } -+ -+ rfbLog("Listening for VNC connections on TCP port %d\n", pVNC->rfbPort); -+ -+ AddEnabledDevice(pVNC->rfbListenSock); -+ -+ FD_ZERO(&pVNC->allFds); -+ FD_SET(pVNC->rfbListenSock, &pVNC->allFds); -+ pVNC->maxFd = pVNC->rfbListenSock; -+ -+ if (pVNC->udpPort != 0) { -+ rfbLog("rfbInitSockets: listening for input on UDP port %d\n",pVNC->udpPort); -+ -+ if ((pVNC->udpSock = ListenOnUDPPort(pScreen, pVNC->udpPort)) < 0) { -+ rfbLogPerror("ListenOnUDPPort"); -+ return FALSE; -+ } -+ AddEnabledDevice(pVNC->udpSock); -+ FD_SET(pVNC->udpSock, &pVNC->allFds); -+ pVNC->maxFd = max(pVNC->udpSock,pVNC->maxFd); -+ } -+ -+ return TRUE; -+} -+ -+ -+/* -+ * rfbCheckFds is called from ProcessInputEvents to check for input on the RFB -+ * socket(s). If there is input to process, the appropriate function in the -+ * RFB server code will be called (rfbNewClientConnection, -+ * rfbProcessClientMessage, etc). -+ */ -+ -+void -+rfbCheckFds(ScreenPtr pScreen) -+{ -+ VNCSCREENPTR(pScreen); -+#if XFREE86VNC -+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; -+#endif -+ int nfds; -+ fd_set fds; -+ struct timeval tv; -+ struct sockaddr_in addr; -+ SOCKLEN_T addrlen = sizeof(addr); -+ char buf[6]; -+ const int one = 1; -+ int sock; -+ static Bool inetdInitDone = FALSE; -+ -+ if (!inetdInitDone && inetdSock != -1) { -+ rfbNewClientConnection(pScreen, inetdSock); -+ inetdInitDone = TRUE; -+ } -+ -+ memcpy((char *)&fds, (char *)&pVNC->allFds, sizeof(fd_set)); -+ tv.tv_sec = 0; -+ tv.tv_usec = 0; -+ nfds = select(pVNC->maxFd + 1, &fds, NULL, NULL, &tv); -+ if (nfds == 0) { -+ return; -+ } -+ if (nfds < 0) { -+ if (errno != EINTR) -+ rfbLogPerror("rfbCheckFds: select"); -+ return; -+ } -+ -+ if (pVNC->rfbListenSock != -1 && FD_ISSET(pVNC->rfbListenSock, &fds)) { -+ -+ if ((sock = accept(pVNC->rfbListenSock, -+ (struct sockaddr *)&addr, &addrlen)) < 0) { -+ rfbLogPerror("rfbCheckFds: accept"); -+ return; -+ } -+ -+ if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) { -+ rfbLogPerror("rfbCheckFds: fcntl"); -+ close(sock); -+ return; -+ } -+ -+ if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, -+ (char *)&one, sizeof(one)) < 0) { -+ rfbLogPerror("rfbCheckFds: setsockopt"); -+ close(sock); -+ return; -+ } -+ -+ rfbLog("\n"); -+ -+#if USE_LIBWRAP -+ if (!hosts_ctl("Xvnc", STRING_UNKNOWN, inet_ntoa(addr.sin_addr), -+ STRING_UNKNOWN)) { -+ rfbLog("Rejected connection from client %s\n", -+ inet_ntoa(addr.sin_addr)); -+ close(sock); -+ return; -+ } -+#endif -+ -+ rfbLog("Got VNC connection from client %s\n", inet_ntoa(addr.sin_addr)); -+ -+ AddEnabledDevice(sock); -+ FD_SET(sock, &pVNC->allFds); -+ pVNC->maxFd = max(sock,pVNC->maxFd); -+ -+ rfbNewClientConnection(pScreen, sock); -+ -+ FD_CLR(pVNC->rfbListenSock, &fds); -+ if (--nfds == 0) -+ return; -+ } -+ -+ if ((pVNC->udpSock != -1) && FD_ISSET(pVNC->udpSock, &fds)) { -+ -+ if (recvfrom(pVNC->udpSock, buf, 1, MSG_PEEK, -+ (struct sockaddr *)&addr, &addrlen) < 0) { -+ -+ rfbLogPerror("rfbCheckFds: UDP: recvfrom"); -+ rfbDisconnectUDPSock(pScreen); -+ -+ } else { -+ -+ if (!pVNC->udpSockConnected || -+ (memcmp(&addr, &udpRemoteAddr, addrlen) != 0)) -+ { -+ /* new remote end */ -+ rfbLog("rfbCheckFds: UDP: got connection\n"); -+ -+ memcpy(&udpRemoteAddr, &addr, addrlen); -+ pVNC->udpSockConnected = TRUE; -+ -+ if (connect(pVNC->udpSock, -+ (struct sockaddr *)&addr, addrlen) < 0) { -+ rfbLogPerror("rfbCheckFds: UDP: connect"); -+ rfbDisconnectUDPSock(pScreen); -+ return; -+ } -+ -+ rfbNewUDPConnection(pVNC->udpSock); -+ } -+ -+ rfbProcessUDPInput(pScreen, pVNC->udpSock); -+ } -+ -+ FD_CLR(pVNC->udpSock, &fds); -+ if (--nfds == 0) -+ return; -+ } -+ -+ for (sock = 0; sock <= pVNC->maxFd; sock++) { -+ if (FD_ISSET(sock, &fds) && FD_ISSET(sock, &pVNC->allFds)) { -+#if XFREE86VNC -+ if (!pScrn->vtSema) -+ rfbCloseSock(pScreen, sock); -+ else -+#endif -+ rfbProcessClientMessage(pScreen, sock); -+ } -+ } -+} -+ -+ -+void -+rfbDisconnectUDPSock(ScreenPtr pScreen) -+{ -+ VNCSCREENPTR(pScreen); -+ pVNC->udpSockConnected = FALSE; -+} -+ -+ -+void -+rfbCloseSock(ScreenPtr pScreen, int sock) -+{ -+ VNCSCREENPTR(pScreen); -+ close(sock); -+ RemoveEnabledDevice(sock); -+ FD_CLR(sock, &pVNC->allFds); -+ rfbClientConnectionGone(sock); -+ if (sock == inetdSock) -+ GiveUp(0); -+} -+ -+#if 0 -+/* -+ * rfbWaitForClient can be called to wait for the RFB client to send us a -+ * message. When one is received it is processed by calling -+ * rfbProcessClientMessage(). -+ */ -+ -+void -+rfbWaitForClient(sock) -+ int sock; -+{ -+ int n; -+ fd_set fds; -+ struct timeval tv; -+ -+ FD_ZERO(&fds); -+ FD_SET(sock, &fds); -+ tv.tv_sec = rfbMaxClientWait / 1000; -+ tv.tv_usec = (rfbMaxClientWait % 1000) * 1000; -+ n = select(sock+1, &fds, NULL, NULL, &tv); -+ if (n < 0) { -+ rfbLogPerror("rfbWaitForClient: select"); -+ exit(1); -+ } -+ if (n == 0) { -+ rfbCloseSock(sock); -+ return; -+ } -+ -+ rfbProcessClientMessage(sock); -+} -+#endif -+ -+/* -+ * rfbConnect is called to make a connection out to a given TCP address. -+ */ -+ -+int -+rfbConnect(ScreenPtr pScreen, char *host, int port) -+{ -+ VNCSCREENPTR(pScreen); -+ int sock; -+ int one = 1; -+ -+ rfbLog("\n"); -+ rfbLog("Making connection to client on host %s port %d\n", -+ host,port); -+ -+ if ((sock = ConnectToTcpAddr(host, port)) < 0) { -+ rfbLogPerror("connection failed"); -+ return -1; -+ } -+ -+ if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) { -+ rfbLogPerror("fcntl failed"); -+ close(sock); -+ return -1; -+ } -+ -+ if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, -+ (char *)&one, sizeof(one)) < 0) { -+ rfbLogPerror("setsockopt failed"); -+ close(sock); -+ return -1; -+ } -+ -+ AddEnabledDevice(sock); -+ FD_SET(sock, &pVNC->allFds); -+ pVNC->maxFd = max(sock,pVNC->maxFd); -+ -+ return sock; -+} -+ -+ -+ -+ -+/* -+ * ReadExact reads an exact number of bytes on a TCP socket. Returns 1 if -+ * those bytes have been read, 0 if the other end has closed, or -1 if an error -+ * occurred (errno is set to ETIMEDOUT if it timed out). -+ */ -+ -+int -+ReadExact(sock, buf, len) -+ int sock; -+ char *buf; -+ int len; -+{ -+ int n; -+ fd_set fds; -+ int tries = 5; -+ struct timeval tv; -+ -+ while (len > 0) { -+ n = read(sock, buf, len); -+ -+ if (n > 0) { -+ -+ buf += n; -+ len -= n; -+ -+ } else if (n == 0) { -+ -+ return 0; -+ -+ } else { -+ if (errno != EWOULDBLOCK && errno != EAGAIN) { -+ return n; -+ } -+ -+ do { -+ FD_ZERO(&fds); -+ FD_SET(sock, &fds); -+ tv.tv_sec = rfbMaxClientWait / 1000; -+ tv.tv_usec = (rfbMaxClientWait % 1000) * 1000; -+ n = select(sock+1, &fds, NULL, NULL, &tv); -+ tries--; -+ -+ /* We really need to retry if we get EINTR, so spin */ -+ /* If after 5 attempts we're still broke, abort.... */ -+ -+ } while ((n < 0 && errno == EINTR) && tries > 0); -+ -+ if (n < 0) { -+ rfbLogPerror("ReadExact: select"); -+ return n; -+ } -+ if (n == 0) { -+ errno = ETIMEDOUT; -+ return -1; -+ } -+ } -+ } -+ return 1; -+} -+ -+ -+ -+/* -+ * WriteExact writes an exact number of bytes on a TCP socket. Returns 1 if -+ * those bytes have been written, or -1 if an error occurred (errno is set to -+ * ETIMEDOUT if it timed out). -+ */ -+ -+int -+WriteExact(sock, buf, len) -+ int sock; -+ char *buf; -+ int len; -+{ -+ int n; -+ fd_set fds; -+ struct timeval tv; -+ int totalTimeWaited = 0; -+ -+ while (len > 0) { -+ n = write(sock, buf, len); -+ -+ if (n > 0) { -+ -+ buf += n; -+ len -= n; -+ -+ } else if (n == 0) { -+ -+ rfbLog("WriteExact: write returned 0?\n"); -+ return -1; -+ -+ } else { -+ if (errno != EWOULDBLOCK && errno != EAGAIN) { -+ return n; -+ } -+ -+#if 0 -+ /* Retry every 5 seconds until we exceed rfbMaxClientWait. We -+ need to do this because select doesn't necessarily return -+ immediately when the other end has gone away */ -+ -+ FD_ZERO(&fds); -+ FD_SET(sock, &fds); -+ tv.tv_sec = 5; -+ tv.tv_usec = 0; -+#else -+ /* We're in the WakeupHandler now, so don't wait */ -+ -+ FD_ZERO(&fds); -+ FD_SET(sock, &fds); -+ tv.tv_sec = 0; -+ tv.tv_usec = 0; -+#endif -+ n = select(sock+1, NULL, &fds, NULL, &tv); -+#if 0 -+ if (n < 0) { -+ rfbLogPerror("WriteExact: select"); -+ return n; -+ } -+ if (n == 0) { -+ totalTimeWaited += 5000; -+ if (totalTimeWaited >= rfbMaxClientWait) { -+ errno = ETIMEDOUT; -+ return -1; -+ } -+ } else { -+ totalTimeWaited = 0; -+ } -+#endif -+ } -+ } -+ return 1; -+} -+ -+ -+int -+ListenOnTCPPort(ScreenPtr pScreen, int port) -+{ -+ VNCSCREENPTR(pScreen); -+ struct sockaddr_in addr; -+ int sock; -+ int one = 1; -+ -+ memset(&addr, 0, sizeof(addr)); -+ addr.sin_family = AF_INET; -+ addr.sin_port = htons(port); -+ addr.sin_addr.s_addr = pVNC->interface.s_addr; -+ -+ if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { -+ return -1; -+ } -+ if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, -+ (char *)&one, sizeof(one)) < 0) { -+ close(sock); -+ return -1; -+ } -+ if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { -+ close(sock); -+ return -1; -+ } -+ if (listen(sock, 5) < 0) { -+ close(sock); -+ return -1; -+ } -+ -+ return sock; -+} -+ -+ -+int -+ConnectToTcpAddr(host, port) -+ char *host; -+ int port; -+{ -+ struct hostent *hp; -+ int sock, n; -+ struct sockaddr_in addr; -+ int tries = 5; -+ -+ memset(&addr, 0, sizeof(addr)); -+ addr.sin_family = AF_INET; -+ addr.sin_port = htons(port); -+ -+ if ((addr.sin_addr.s_addr = inet_addr(host)) == -1) -+ { -+ if (!(hp = gethostbyname(host))) { -+ errno = EINVAL; -+ return -1; -+ } -+ addr.sin_addr.s_addr = *(unsigned long *)hp->h_addr; -+ } -+ -+ if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { -+ return -1; -+ } -+ -+ do { -+ sock = socket(AF_INET, SOCK_STREAM, 0); -+ tries--; -+ -+ /* We really need to retry if we get EINTR, so spin */ -+ /* If after 5 attempts we're still broke, abort.... */ -+ -+ } while ((sock < 0 && errno == EINTR) && tries > 0); -+ -+ if (sock < 0) { -+ return -1; -+ } -+ -+ tries = 5; -+ -+ do { -+ n = connect(sock, (struct sockaddr *)&addr, (sizeof(addr))); -+ tries--; -+ -+ /* We really need to retry if we get EINTR, so spin */ -+ /* If after 5 attempts we're still broke, abort.... */ -+ -+ } while ((n < 0 && errno == EINTR) && tries > 0); -+ -+ if (n < 0) { -+ close(sock); -+ return -1; -+ } -+ -+ return sock; -+} -+ -+ -+int -+ListenOnUDPPort(ScreenPtr pScreen, int port) -+{ -+ VNCSCREENPTR(pScreen); -+ struct sockaddr_in addr; -+ int sock; -+ int one = 1; -+ -+ memset(&addr, 0, sizeof(addr)); -+ addr.sin_family = AF_INET; -+ addr.sin_port = htons(port); -+ addr.sin_addr.s_addr = pVNC->interface.s_addr; -+ -+ if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { -+ return -1; -+ } -+ if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, -+ (char *)&one, sizeof(one)) < 0) { -+ return -1; -+ } -+ if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { -+ return -1; -+ } -+ -+ return sock; -+} -+ -+#if 0 -+/* -+ * rdpInitSockets sets up the TCP for RDP -+ * connections. It does nothing if called again. -+ */ -+ -+Bool -+rdpInitSockets(ScreenPtr pScreen) -+{ -+ VNCSCREENPTR(pScreen); -+ -+ if ((pVNC->rdpListenSock = ListenOnTCPPort(pScreen, pVNC->rdpPort)) < 0) { -+ rfbLogPerror("ListenOnTCPPort"); -+ pVNC->rdpPort = 0; -+ return FALSE; -+ } -+ -+ rfbLog("Listening for RDP connections on TCP port %d\n", pVNC->rdpPort); -+ -+ AddEnabledDevice(pVNC->rdpListenSock); -+ -+ return TRUE; -+} -+#endif -diff --git a/hw/dmx/vnc/sprite.c b/hw/dmx/vnc/sprite.c -new file mode 100644 -index 0000000..6be60b6 ---- /dev/null -+++ b/hw/dmx/vnc/sprite.c -@@ -0,0 +1,2491 @@ -+/* -+ * sprite.c -+ * -+ * software sprite routines - based on misprite -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ */ -+ -+/* -+ * 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. -+ */ -+ -+/* $XConsortium: misprite.c,v 5.47 94/04/17 20:27:53 dpw Exp $ */ -+ -+/* -+ -+Copyright (c) 1989 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 "rfb.h" -+# include "X11/X.h" -+# include "X11/Xproto.h" -+# include "misc.h" -+# include "pixmapstr.h" -+# include "input.h" -+# include "mi.h" -+# include "cursorstr.h" -+/*# include "font.h"*/ -+# include "scrnintstr.h" -+# include "colormapst.h" -+# include "windowstr.h" -+# include "gcstruct.h" -+# include "mipointer.h" -+# include "spritest.h" -+# include "dixfontstr.h" -+/*# include "fontstruct.h"*/ -+#ifdef RENDER -+# include "mipict.h" -+#endif -+ -+/* -+ * screen wrappers -+ */ -+ -+static int rfbSpriteScreenIndex; -+static unsigned long rfbSpriteGeneration = 0; -+ -+static Bool rfbSpriteCloseScreen(int i, ScreenPtr pScreen); -+static void rfbSpriteGetImage(DrawablePtr pDrawable, int sx, int sy, -+ int w, int h, unsigned int format, -+ unsigned long planemask, char *pdstLine); -+static void rfbSpriteGetSpans(DrawablePtr pDrawable, int wMax, -+ DDXPointPtr ppt, int *pwidth, int nspans, -+ char *pdstStart); -+static void rfbSpriteSourceValidate(DrawablePtr pDrawable, int x, int y, -+ int width, int height); -+static Bool rfbSpriteCreateGC(GCPtr pGC); -+static void rfbSpriteBlockHandler(int i, pointer blockData, -+ pointer pTimeout, -+ pointer pReadMask); -+static void rfbSpriteInstallColormap(ColormapPtr pMap); -+static void rfbSpriteStoreColors(ColormapPtr pMap, int ndef, -+ xColorItem *pdef); -+ -+static void rfbSpritePaintWindowBackground(WindowPtr pWin, -+ RegionPtr pRegion, int what); -+static void rfbSpritePaintWindowBorder(WindowPtr pWin, -+ RegionPtr pRegion, int what); -+static void rfbSpriteCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, -+ RegionPtr pRegion); -+static void rfbSpriteClearToBackground(WindowPtr pWin, int x, int y, -+ int w, int h, -+ Bool generateExposures); -+ -+#ifdef RENDER -+static void rfbSpriteComposite(CARD8 op, -+ PicturePtr pSrc, -+ PicturePtr pMask, -+ PicturePtr pDst, -+ INT16 xSrc, -+ INT16 ySrc, -+ INT16 xMask, -+ INT16 yMask, -+ INT16 xDst, -+ INT16 yDst, -+ CARD16 width, -+ CARD16 height); -+ -+static void rfbSpriteGlyphs(CARD8 op, -+ PicturePtr pSrc, -+ PicturePtr pDst, -+ PictFormatPtr maskFormat, -+ INT16 xSrc, -+ INT16 ySrc, -+ int nlist, -+ GlyphListPtr list, -+ GlyphPtr *glyphs); -+#endif -+ -+static void rfbSpriteSaveDoomedAreas(WindowPtr pWin, -+ RegionPtr pObscured, int dx, -+ int dy); -+static RegionPtr rfbSpriteRestoreAreas(WindowPtr pWin, RegionPtr pRgnExposed); -+static void rfbSpriteComputeSaved(ScreenPtr pScreen); -+ -+#define SCREEN_PROLOGUE(pScreen, field)\ -+ ((pScreen)->field = \ -+ ((rfbSpriteScreenPtr) (pScreen)->devPrivates[rfbSpriteScreenIndex].ptr)->field) -+ -+#define SCREEN_EPILOGUE(pScreen, field, wrapper)\ -+ ((pScreen)->field = wrapper) -+ -+/* -+ * GC func wrappers -+ */ -+ -+static int rfbSpriteGCIndex; -+ -+static void rfbSpriteValidateGC(GCPtr pGC, unsigned long stateChanges, -+ DrawablePtr pDrawable); -+static void rfbSpriteCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst); -+static void rfbSpriteDestroyGC(GCPtr pGC); -+static void rfbSpriteChangeGC(GCPtr pGC, unsigned long mask); -+static void rfbSpriteChangeClip(GCPtr pGC, int type, pointer pvalue, int nrects); -+static void rfbSpriteDestroyClip(GCPtr pGC); -+static void rfbSpriteCopyClip(GCPtr pgcDst, GCPtr pgcSrc); -+ -+static GCFuncs rfbSpriteGCFuncs = { -+ rfbSpriteValidateGC, -+ rfbSpriteChangeGC, -+ rfbSpriteCopyGC, -+ rfbSpriteDestroyGC, -+ rfbSpriteChangeClip, -+ rfbSpriteDestroyClip, -+ rfbSpriteCopyClip, -+}; -+ -+#define GC_FUNC_PROLOGUE(pGC) \ -+ rfbSpriteGCPtr pGCPriv = \ -+ (rfbSpriteGCPtr) (pGC)->devPrivates[rfbSpriteGCIndex].ptr;\ -+ (pGC)->funcs = pGCPriv->wrapFuncs; \ -+ if (pGCPriv->wrapOps) \ -+ (pGC)->ops = pGCPriv->wrapOps; -+ -+#define GC_FUNC_EPILOGUE(pGC) \ -+ pGCPriv->wrapFuncs = (pGC)->funcs; \ -+ (pGC)->funcs = &rfbSpriteGCFuncs; \ -+ if (pGCPriv->wrapOps) \ -+ { \ -+ pGCPriv->wrapOps = (pGC)->ops; \ -+ (pGC)->ops = &rfbSpriteGCOps; \ -+ } -+ -+/* -+ * GC op wrappers -+ */ -+ -+static void rfbSpriteFillSpans(DrawablePtr pDrawable, GCPtr pGC, -+ int nInit, DDXPointPtr pptInit, -+ int *pwidthInit, int fSorted); -+static void rfbSpriteSetSpans(DrawablePtr pDrawable, GCPtr pGC, -+ char *psrc, DDXPointPtr ppt, int *pwidth, -+ int nspans, int fSorted); -+static void rfbSpritePutImage(DrawablePtr pDrawable, GCPtr pGC, -+ int depth, int x, int y, int w, int h, -+ int leftPad, int format, char *pBits); -+static RegionPtr rfbSpriteCopyArea(DrawablePtr pSrc, DrawablePtr pDst, -+ GCPtr pGC, int srcx, int srcy, int w, -+ int h, int dstx, int dsty); -+static RegionPtr rfbSpriteCopyPlane(DrawablePtr pSrc, DrawablePtr pDst, -+ GCPtr pGC, int srcx, int srcy, int w, -+ int h, int dstx, int dsty, -+ unsigned long plane); -+static void rfbSpritePolyPoint(DrawablePtr pDrawable, GCPtr pGC, -+ int mode, int npt, xPoint *pptInit); -+static void rfbSpritePolylines(DrawablePtr pDrawable, GCPtr pGC, -+ int mode, int npt, DDXPointPtr pptInit); -+static void rfbSpritePolySegment(DrawablePtr pDrawable, GCPtr pGC, -+ int nseg, xSegment *pSegs); -+static void rfbSpritePolyRectangle(DrawablePtr pDrawable, GCPtr pGC, -+ int nrects, xRectangle *pRects); -+static void rfbSpritePolyArc(DrawablePtr pDrawable, GCPtr pGC, -+ int narcs, xArc *parcs); -+static void rfbSpriteFillPolygon(DrawablePtr pDrawable, GCPtr pGC, -+ int shape, int mode, int count, -+ DDXPointPtr pPts); -+static void rfbSpritePolyFillRect(DrawablePtr pDrawable, GCPtr pGC, -+ int nrectFill, xRectangle *prectInit); -+static void rfbSpritePolyFillArc(DrawablePtr pDrawable, GCPtr pGC, -+ int narcs, xArc *parcs); -+static int rfbSpritePolyText8(DrawablePtr pDrawable, GCPtr pGC, -+ int x, int y, int count, char *chars); -+static int rfbSpritePolyText16(DrawablePtr pDrawable, GCPtr pGC, -+ int x, int y, int count, -+ unsigned short *chars); -+static void rfbSpriteImageText8(DrawablePtr pDrawable, GCPtr pGC, -+ int x, int y, int count, char *chars); -+static void rfbSpriteImageText16(DrawablePtr pDrawable, GCPtr pGC, -+ int x, int y, int count, -+ unsigned short *chars); -+static void rfbSpriteImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, -+ int x, int y, unsigned int nglyph, -+ CharInfoPtr *ppci, -+ pointer pglyphBase); -+static void rfbSpritePolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, -+ int x, int y, unsigned int nglyph, -+ CharInfoPtr *ppci, -+ pointer pglyphBase); -+static void rfbSpritePushPixels(GCPtr pGC, PixmapPtr pBitMap, -+ DrawablePtr pDst, int w, int h, -+ int x, int y); -+#ifdef NEED_LINEHELPER -+static void rfbSpriteLineHelper(); -+#endif -+ -+static GCOps rfbSpriteGCOps = { -+ rfbSpriteFillSpans, rfbSpriteSetSpans, rfbSpritePutImage, -+ rfbSpriteCopyArea, rfbSpriteCopyPlane, rfbSpritePolyPoint, -+ rfbSpritePolylines, rfbSpritePolySegment, rfbSpritePolyRectangle, -+ rfbSpritePolyArc, rfbSpriteFillPolygon, rfbSpritePolyFillRect, -+ rfbSpritePolyFillArc, rfbSpritePolyText8, rfbSpritePolyText16, -+ rfbSpriteImageText8, rfbSpriteImageText16, rfbSpriteImageGlyphBlt, -+ rfbSpritePolyGlyphBlt, rfbSpritePushPixels -+#ifdef NEED_LINEHELPER -+ , rfbSpriteLineHelper -+#endif -+}; -+ -+/* -+ * testing only -- remove cursor for every draw. Eventually, -+ * each draw operation will perform a bounding box check against -+ * the saved cursor area -+ */ -+ -+#define GC_SETUP_CHEAP(pDrawable) \ -+ rfbSpriteScreenPtr pScreenPriv = (rfbSpriteScreenPtr) \ -+ (pDrawable)->pScreen->devPrivates[rfbSpriteScreenIndex].ptr; \ -+ -+#define GC_SETUP(pDrawable, pGC) \ -+ GC_SETUP_CHEAP(pDrawable) \ -+ rfbSpriteGCPtr pGCPrivate = (rfbSpriteGCPtr) \ -+ (pGC)->devPrivates[rfbSpriteGCIndex].ptr; \ -+ GCFuncs *oldFuncs = pGC->funcs; -+ -+#define GC_SETUP_AND_CHECK(pDrawable, pGC) \ -+ GC_SETUP(pDrawable, pGC); \ -+ if (GC_CHECK((WindowPtr)pDrawable)) \ -+ rfbSpriteRemoveCursor (pDrawable->pScreen); -+ -+#define GC_CHECK(pWin) \ -+ (pVNC->cursorIsDrawn && \ -+ (pScreenPriv->pCacheWin == pWin ? \ -+ pScreenPriv->isInCacheWin : ( \ -+ (pScreenPriv->pCacheWin = (pWin)) , \ -+ (pScreenPriv->isInCacheWin = \ -+ (pWin)->drawable.x < pScreenPriv->saved.x2 && \ -+ pScreenPriv->saved.x1 < (pWin)->drawable.x + \ -+ (int) (pWin)->drawable.width && \ -+ (pWin)->drawable.y < pScreenPriv->saved.y2 && \ -+ pScreenPriv->saved.y1 < (pWin)->drawable.y + \ -+ (int) (pWin)->drawable.height &&\ -+ RECT_IN_REGION((pWin)->drawable.pScreen, &(pWin)->borderClip, \ -+ &pScreenPriv->saved) != rgnOUT)))) -+ -+#define GC_OP_PROLOGUE(pGC) { \ -+ (pGC)->funcs = pGCPrivate->wrapFuncs; \ -+ (pGC)->ops = pGCPrivate->wrapOps; \ -+ } -+ -+#define GC_OP_EPILOGUE(pGC) { \ -+ pGCPrivate->wrapOps = (pGC)->ops; \ -+ (pGC)->funcs = oldFuncs; \ -+ (pGC)->ops = &rfbSpriteGCOps; \ -+ } -+ -+/* -+ * pointer-sprite method table -+ */ -+ -+static Bool rfbSpriteRealizeCursor (), rfbSpriteUnrealizeCursor (); -+static void rfbSpriteSetCursor (), rfbSpriteMoveCursor (); -+ -+miPointerSpriteFuncRec rfbSpritePointerFuncs = { -+ rfbSpriteRealizeCursor, -+ rfbSpriteUnrealizeCursor, -+ rfbSpriteSetCursor, -+ rfbSpriteMoveCursor, -+}; -+ -+/* -+ * other misc functions -+ */ -+ -+static Bool rfbDisplayCursor (ScreenPtr pScreen, CursorPtr pCursor); -+ -+ -+/* -+ * rfbSpriteInitialize -- called from device-dependent screen -+ * initialization proc after all of the function pointers have -+ * been stored in the screen structure. -+ */ -+ -+Bool -+rfbSpriteInitialize (pScreen, cursorFuncs, screenFuncs) -+ ScreenPtr pScreen; -+ rfbSpriteCursorFuncPtr cursorFuncs; -+ miPointerScreenFuncPtr screenFuncs; -+{ -+ rfbSpriteScreenPtr pPriv; -+ VisualPtr pVisual; -+#ifdef RENDER -+ PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); -+#endif -+ -+ if (rfbSpriteGeneration != serverGeneration) -+ { -+ rfbSpriteScreenIndex = AllocateScreenPrivateIndex (); -+ if (rfbSpriteScreenIndex < 0) -+ return FALSE; -+ rfbSpriteGeneration = serverGeneration; -+ rfbSpriteGCIndex = AllocateGCPrivateIndex (); -+ } -+ if (!AllocateGCPrivate(pScreen, rfbSpriteGCIndex, sizeof(rfbSpriteGCRec))) -+ return FALSE; -+ pPriv = (rfbSpriteScreenPtr) xalloc (sizeof (rfbSpriteScreenRec)); -+ if (!pPriv) -+ return FALSE; -+ if (!miPointerInitialize (pScreen, &rfbSpritePointerFuncs, screenFuncs,TRUE)) -+ { -+ xfree ((pointer) pPriv); -+ return FALSE; -+ } -+ for (pVisual = pScreen->visuals; -+ pVisual->vid != pScreen->rootVisual; -+ pVisual++) -+ ; -+ pPriv->pVisual = pVisual; -+ pPriv->CloseScreen = pScreen->CloseScreen; -+ pPriv->GetImage = pScreen->GetImage; -+ pPriv->GetSpans = pScreen->GetSpans; -+ pPriv->SourceValidate = pScreen->SourceValidate; -+ pPriv->CreateGC = pScreen->CreateGC; -+#if 0 -+ pPriv->BlockHandler = pScreen->BlockHandler; -+#endif -+ pPriv->InstallColormap = pScreen->InstallColormap; -+ pPriv->StoreColors = pScreen->StoreColors; -+ pPriv->DisplayCursor = pScreen->DisplayCursor; -+ -+ pPriv->PaintWindowBackground = pScreen->PaintWindowBackground; -+ pPriv->PaintWindowBorder = pScreen->PaintWindowBorder; -+ pPriv->CopyWindow = pScreen->CopyWindow; -+ pPriv->ClearToBackground = pScreen->ClearToBackground; -+ -+ pPriv->SaveDoomedAreas = pScreen->SaveDoomedAreas; -+ pPriv->RestoreAreas = pScreen->RestoreAreas; -+#ifdef RENDER -+ if (ps) -+ { -+ pPriv->Composite = ps->Composite; -+ pPriv->Glyphs = ps->Glyphs; -+ } -+#endif -+ -+ pPriv->pCursor = NULL; -+ pPriv->x = 0; -+ pPriv->y = 0; -+ pPriv->shouldBeUp = FALSE; -+ pPriv->pCacheWin = NullWindow; -+ pPriv->isInCacheWin = FALSE; -+ pPriv->checkPixels = TRUE; -+ pPriv->pInstalledMap = NULL; -+ pPriv->pColormap = NULL; -+ pPriv->funcs = cursorFuncs; -+ pPriv->colors[SOURCE_COLOR].red = 0; -+ pPriv->colors[SOURCE_COLOR].green = 0; -+ pPriv->colors[SOURCE_COLOR].blue = 0; -+ pPriv->colors[MASK_COLOR].red = 0; -+ pPriv->colors[MASK_COLOR].green = 0; -+ pPriv->colors[MASK_COLOR].blue = 0; -+ pScreen->devPrivates[rfbSpriteScreenIndex].ptr = (pointer) pPriv; -+ pScreen->CloseScreen = rfbSpriteCloseScreen; -+ pScreen->GetImage = rfbSpriteGetImage; -+ pScreen->GetSpans = rfbSpriteGetSpans; -+ pScreen->SourceValidate = rfbSpriteSourceValidate; -+ pScreen->CreateGC = rfbSpriteCreateGC; -+#if 0 -+ pScreen->BlockHandler = rfbSpriteBlockHandler; -+#endif -+ pScreen->InstallColormap = rfbSpriteInstallColormap; -+ pScreen->StoreColors = rfbSpriteStoreColors; -+ -+ pScreen->PaintWindowBackground = rfbSpritePaintWindowBackground; -+ pScreen->PaintWindowBorder = rfbSpritePaintWindowBorder; -+ pScreen->CopyWindow = rfbSpriteCopyWindow; -+ pScreen->ClearToBackground = rfbSpriteClearToBackground; -+ -+ pScreen->SaveDoomedAreas = rfbSpriteSaveDoomedAreas; -+ pScreen->RestoreAreas = rfbSpriteRestoreAreas; -+ -+ pScreen->DisplayCursor = rfbDisplayCursor; -+#ifdef RENDER -+ if (ps) -+ { -+ ps->Composite = rfbSpriteComposite; -+ ps->Glyphs = rfbSpriteGlyphs; -+ } -+#endif -+ -+ return TRUE; -+} -+ -+/* -+ * Screen wrappers -+ */ -+ -+/* -+ * CloseScreen wrapper -- unwrap everything, free the private data -+ * and call the wrapped function -+ */ -+ -+static Bool -+rfbSpriteCloseScreen (i, pScreen) -+ ScreenPtr pScreen; -+{ -+ rfbSpriteScreenPtr pScreenPriv; -+#ifdef RENDER -+ PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); -+#endif -+ -+ pScreenPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr; -+ -+ pScreen->CloseScreen = pScreenPriv->CloseScreen; -+ pScreen->GetImage = pScreenPriv->GetImage; -+ pScreen->GetSpans = pScreenPriv->GetSpans; -+ pScreen->SourceValidate = pScreenPriv->SourceValidate; -+ pScreen->CreateGC = pScreenPriv->CreateGC; -+#if 0 -+ pScreen->BlockHandler = pScreenPriv->BlockHandler; -+#endif -+ pScreen->InstallColormap = pScreenPriv->InstallColormap; -+ pScreen->StoreColors = pScreenPriv->StoreColors; -+ -+ pScreen->PaintWindowBackground = pScreenPriv->PaintWindowBackground; -+ pScreen->PaintWindowBorder = pScreenPriv->PaintWindowBorder; -+ pScreen->CopyWindow = pScreenPriv->CopyWindow; -+ pScreen->ClearToBackground = pScreenPriv->ClearToBackground; -+ -+ pScreen->SaveDoomedAreas = pScreenPriv->SaveDoomedAreas; -+ pScreen->RestoreAreas = pScreenPriv->RestoreAreas; -+#ifdef RENDER -+ if (ps) -+ { -+ ps->Composite = pScreenPriv->Composite; -+ ps->Glyphs = pScreenPriv->Glyphs; -+ } -+#endif -+ -+ xfree ((pointer) pScreenPriv); -+ -+ return (*pScreen->CloseScreen) (i, pScreen); -+} -+ -+static void -+rfbSpriteGetImage (pDrawable, sx, sy, w, h, format, planemask, pdstLine) -+ DrawablePtr pDrawable; -+ int sx, sy, w, h; -+ unsigned int format; -+ unsigned long planemask; -+ char *pdstLine; -+{ -+ ScreenPtr pScreen = pDrawable->pScreen; -+ rfbSpriteScreenPtr pScreenPriv; -+ VNCSCREENPTR(pScreen); -+ -+ SCREEN_PROLOGUE (pScreen, GetImage); -+ -+ pScreenPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr; -+ -+ if (pDrawable->type == DRAWABLE_WINDOW && -+ pVNC->cursorIsDrawn && -+ ORG_OVERLAP(&pScreenPriv->saved,pDrawable->x,pDrawable->y, sx, sy, w, h)) -+ { -+ rfbSpriteRemoveCursor (pScreen); -+ } -+ -+ (*pScreen->GetImage) (pDrawable, sx, sy, w, h, -+ format, planemask, pdstLine); -+ -+ SCREEN_EPILOGUE (pScreen, GetImage, rfbSpriteGetImage); -+} -+ -+static void -+rfbSpriteGetSpans (pDrawable, wMax, ppt, pwidth, nspans, pdstStart) -+ DrawablePtr pDrawable; -+ int wMax; -+ DDXPointPtr ppt; -+ int *pwidth; -+ int nspans; -+ char *pdstStart; -+{ -+ ScreenPtr pScreen = pDrawable->pScreen; -+ rfbSpriteScreenPtr pScreenPriv; -+ VNCSCREENPTR(pScreen); -+ -+ SCREEN_PROLOGUE (pScreen, GetSpans); -+ -+ pScreenPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr; -+ -+ if (pDrawable->type == DRAWABLE_WINDOW && pVNC->cursorIsDrawn) -+ { -+ register DDXPointPtr pts; -+ register int *widths; -+ register int nPts; -+ register int xorg, -+ yorg; -+ -+ xorg = pDrawable->x; -+ yorg = pDrawable->y; -+ -+ for (pts = ppt, widths = pwidth, nPts = nspans; -+ nPts--; -+ pts++, widths++) -+ { -+ if (SPN_OVERLAP(&pScreenPriv->saved,pts->y+yorg, -+ pts->x+xorg,*widths)) -+ { -+ rfbSpriteRemoveCursor (pScreen); -+ break; -+ } -+ } -+ } -+ -+ (*pScreen->GetSpans) (pDrawable, wMax, ppt, pwidth, nspans, pdstStart); -+ -+ SCREEN_EPILOGUE (pScreen, GetSpans, rfbSpriteGetSpans); -+} -+ -+static void -+rfbSpriteSourceValidate (pDrawable, x, y, width, height) -+ DrawablePtr pDrawable; -+ int x, y, width, height; -+{ -+ ScreenPtr pScreen = pDrawable->pScreen; -+ rfbSpriteScreenPtr pScreenPriv; -+ VNCSCREENPTR(pScreen); -+ -+ SCREEN_PROLOGUE (pScreen, SourceValidate); -+ -+ pScreenPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr; -+ -+ if (pDrawable->type == DRAWABLE_WINDOW && pVNC->cursorIsDrawn && -+ ORG_OVERLAP(&pScreenPriv->saved, pDrawable->x, pDrawable->y, -+ x, y, width, height)) -+ { -+ rfbSpriteRemoveCursor (pScreen); -+ } -+ -+ if (pScreen->SourceValidate) -+ (*pScreen->SourceValidate) (pDrawable, x, y, width, height); -+ -+ SCREEN_EPILOGUE (pScreen, SourceValidate, rfbSpriteSourceValidate); -+} -+ -+static Bool -+rfbSpriteCreateGC (pGC) -+ GCPtr pGC; -+{ -+ ScreenPtr pScreen = pGC->pScreen; -+ Bool ret; -+ rfbSpriteGCPtr pPriv; -+ -+ SCREEN_PROLOGUE (pScreen, CreateGC); -+ -+ pPriv = (rfbSpriteGCPtr)pGC->devPrivates[rfbSpriteGCIndex].ptr; -+ -+ ret = (*pScreen->CreateGC) (pGC); -+ -+ pPriv->wrapOps = NULL; -+ pPriv->wrapFuncs = pGC->funcs; -+ pGC->funcs = &rfbSpriteGCFuncs; -+ -+ SCREEN_EPILOGUE (pScreen, CreateGC, rfbSpriteCreateGC); -+ -+ return ret; -+} -+ -+static void -+rfbSpriteBlockHandler (i, blockData, pTimeout, pReadmask) -+ int i; -+ pointer blockData; -+ pointer pTimeout; -+ pointer pReadmask; -+{ -+ ScreenPtr pScreen = screenInfo.screens[i]; -+ rfbSpriteScreenPtr pPriv; -+ VNCSCREENPTR(pScreen); -+ -+ pPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr; -+ -+ SCREEN_PROLOGUE(pScreen, BlockHandler); -+ -+ (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask); -+ -+ SCREEN_EPILOGUE(pScreen, BlockHandler, rfbSpriteBlockHandler); -+ -+ if (!pVNC->cursorIsDrawn && pPriv->shouldBeUp) -+ rfbSpriteRestoreCursor (pScreen); -+} -+ -+static void -+rfbSpriteInstallColormap (pMap) -+ ColormapPtr pMap; -+{ -+ ScreenPtr pScreen = pMap->pScreen; -+ rfbSpriteScreenPtr pPriv; -+ VNCSCREENPTR(pScreen); -+ -+ pPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr; -+ -+ SCREEN_PROLOGUE(pScreen, InstallColormap); -+ -+ (*pScreen->InstallColormap) (pMap); -+ -+ SCREEN_EPILOGUE(pScreen, InstallColormap, rfbSpriteInstallColormap); -+ -+ pPriv->pInstalledMap = pMap; -+ if (pPriv->pColormap != pMap) -+ { -+ pPriv->checkPixels = TRUE; -+ if (pVNC->cursorIsDrawn) -+ rfbSpriteRemoveCursor (pScreen); -+ } -+} -+ -+static void -+rfbSpriteStoreColors (pMap, ndef, pdef) -+ ColormapPtr pMap; -+ int ndef; -+ xColorItem *pdef; -+{ -+ ScreenPtr pScreen = pMap->pScreen; -+ rfbSpriteScreenPtr pPriv; -+ int i; -+ int updated; -+ VisualPtr pVisual; -+ VNCSCREENPTR(pScreen); -+ -+ pPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr; -+ -+ SCREEN_PROLOGUE(pScreen, StoreColors); -+ -+ (*pScreen->StoreColors) (pMap, ndef, pdef); -+ -+ SCREEN_EPILOGUE(pScreen, StoreColors, rfbSpriteStoreColors); -+ -+ if (pPriv->pColormap == pMap) -+ { -+ updated = 0; -+ pVisual = pMap->pVisual; -+ if (pVisual->class == DirectColor) -+ { -+ /* Direct color - match on any of the subfields */ -+ -+#define MaskMatch(a,b,mask) ((a) & ((pVisual->mask) == (b)) & (pVisual->mask)) -+ -+#define UpdateDAC(plane,dac,mask) {\ -+ if (MaskMatch (pPriv->colors[plane].pixel,pdef[i].pixel,mask)) {\ -+ pPriv->colors[plane].dac = pdef[i].dac; \ -+ updated = 1; \ -+ } \ -+} -+ -+#define CheckDirect(plane) \ -+ UpdateDAC(plane,red,redMask) \ -+ UpdateDAC(plane,green,greenMask) \ -+ UpdateDAC(plane,blue,blueMask) -+ -+ for (i = 0; i < ndef; i++) -+ { -+ CheckDirect (SOURCE_COLOR) -+ CheckDirect (MASK_COLOR) -+ } -+ } -+ else -+ { -+ /* PseudoColor/GrayScale - match on exact pixel */ -+ for (i = 0; i < ndef; i++) -+ { -+ if (pdef[i].pixel == pPriv->colors[SOURCE_COLOR].pixel) -+ { -+ pPriv->colors[SOURCE_COLOR] = pdef[i]; -+ if (++updated == 2) -+ break; -+ } -+ if (pdef[i].pixel == pPriv->colors[MASK_COLOR].pixel) -+ { -+ pPriv->colors[MASK_COLOR] = pdef[i]; -+ if (++updated == 2) -+ break; -+ } -+ } -+ } -+ if (updated) -+ { -+ pPriv->checkPixels = TRUE; -+ if (pVNC->cursorIsDrawn) -+ rfbSpriteRemoveCursor (pScreen); -+ } -+ } -+} -+ -+static void -+rfbSpriteFindColors (pScreen) -+ ScreenPtr pScreen; -+{ -+ rfbSpriteScreenPtr pScreenPriv = (rfbSpriteScreenPtr) -+ pScreen->devPrivates[rfbSpriteScreenIndex].ptr; -+ CursorPtr pCursor; -+ xColorItem *sourceColor, *maskColor; -+ -+ pCursor = pScreenPriv->pCursor; -+ sourceColor = &pScreenPriv->colors[SOURCE_COLOR]; -+ maskColor = &pScreenPriv->colors[MASK_COLOR]; -+ if (pScreenPriv->pColormap != pScreenPriv->pInstalledMap || -+ !(pCursor->foreRed == sourceColor->red && -+ pCursor->foreGreen == sourceColor->green && -+ pCursor->foreBlue == sourceColor->blue && -+ pCursor->backRed == maskColor->red && -+ pCursor->backGreen == maskColor->green && -+ pCursor->backBlue == maskColor->blue)) -+ { -+ pScreenPriv->pColormap = pScreenPriv->pInstalledMap; -+ sourceColor->red = pCursor->foreRed; -+ sourceColor->green = pCursor->foreGreen; -+ sourceColor->blue = pCursor->foreBlue; -+ FakeAllocColor (pScreenPriv->pColormap, sourceColor); -+ maskColor->red = pCursor->backRed; -+ maskColor->green = pCursor->backGreen; -+ maskColor->blue = pCursor->backBlue; -+ FakeAllocColor (pScreenPriv->pColormap, maskColor); -+ /* "free" the pixels right away, don't let this confuse you */ -+ FakeFreeColor(pScreenPriv->pColormap, sourceColor->pixel); -+ FakeFreeColor(pScreenPriv->pColormap, maskColor->pixel); -+ } -+ pScreenPriv->checkPixels = FALSE; -+} -+ -+/* -+ * BackingStore wrappers -+ */ -+ -+static void -+rfbSpriteSaveDoomedAreas (pWin, pObscured, dx, dy) -+ WindowPtr pWin; -+ RegionPtr pObscured; -+ int dx, dy; -+{ -+ ScreenPtr pScreen = pWin->drawable.pScreen; -+ rfbSpriteScreenPtr pScreenPriv; -+ BoxRec cursorBox; -+ VNCSCREENPTR(pScreen); -+ -+ SCREEN_PROLOGUE (pScreen, SaveDoomedAreas); -+ -+ pScreenPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr; -+ if (pVNC->cursorIsDrawn) -+ { -+ cursorBox = pScreenPriv->saved; -+ -+ if (dx || dy) -+ { -+ cursorBox.x1 += dx; -+ cursorBox.y1 += dy; -+ cursorBox.x2 += dx; -+ cursorBox.y2 += dy; -+ } -+ if (RECT_IN_REGION( pScreen, pObscured, &cursorBox) != rgnOUT) -+ rfbSpriteRemoveCursor (pScreen); -+ } -+ -+ (*pScreen->SaveDoomedAreas) (pWin, pObscured, dx, dy); -+ -+ SCREEN_EPILOGUE (pScreen, SaveDoomedAreas, rfbSpriteSaveDoomedAreas); -+} -+ -+static RegionPtr -+rfbSpriteRestoreAreas (pWin, prgnExposed) -+ WindowPtr pWin; -+ RegionPtr prgnExposed; -+{ -+ ScreenPtr pScreen = pWin->drawable.pScreen; -+ rfbSpriteScreenPtr pScreenPriv; -+ RegionPtr result; -+ VNCSCREENPTR(pScreen); -+ -+ SCREEN_PROLOGUE (pScreen, RestoreAreas); -+ -+ pScreenPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr; -+ if (pVNC->cursorIsDrawn) -+ { -+ if (RECT_IN_REGION( pScreen, prgnExposed, &pScreenPriv->saved) != rgnOUT) -+ rfbSpriteRemoveCursor (pScreen); -+ } -+ -+ result = (*pScreen->RestoreAreas) (pWin, prgnExposed); -+ -+ SCREEN_EPILOGUE (pScreen, RestoreAreas, rfbSpriteRestoreAreas); -+ -+ return result; -+} -+ -+/* -+ * Window wrappers -+ */ -+ -+static void -+rfbSpritePaintWindowBackground (pWin, pRegion, what) -+ WindowPtr pWin; -+ RegionPtr pRegion; -+ int what; -+{ -+ ScreenPtr pScreen = pWin->drawable.pScreen; -+ rfbSpriteScreenPtr pScreenPriv; -+ VNCSCREENPTR(pScreen); -+ -+ SCREEN_PROLOGUE (pScreen, PaintWindowBackground); -+ -+ pScreenPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr; -+ if (pVNC->cursorIsDrawn) -+ { -+ /* -+ * If the cursor is on the same screen as the window, check the -+ * region to paint for the cursor and remove it as necessary -+ */ -+ if (RECT_IN_REGION( pScreen, pRegion, &pScreenPriv->saved) != rgnOUT) -+ rfbSpriteRemoveCursor (pScreen); -+ } -+ -+ (*pScreen->PaintWindowBackground) (pWin, pRegion, what); -+ -+ SCREEN_EPILOGUE (pScreen, PaintWindowBackground, rfbSpritePaintWindowBackground); -+} -+ -+static void -+rfbSpritePaintWindowBorder (pWin, pRegion, what) -+ WindowPtr pWin; -+ RegionPtr pRegion; -+ int what; -+{ -+ ScreenPtr pScreen = pWin->drawable.pScreen; -+ rfbSpriteScreenPtr pScreenPriv; -+ VNCSCREENPTR(pScreen); -+ -+ SCREEN_PROLOGUE (pScreen, PaintWindowBorder); -+ -+ pScreenPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr; -+ if (pVNC->cursorIsDrawn) -+ { -+ /* -+ * If the cursor is on the same screen as the window, check the -+ * region to paint for the cursor and remove it as necessary -+ */ -+ if (RECT_IN_REGION( pScreen, pRegion, &pScreenPriv->saved) != rgnOUT) -+ rfbSpriteRemoveCursor (pScreen); -+ } -+ -+ (*pScreen->PaintWindowBorder) (pWin, pRegion, what); -+ -+ SCREEN_EPILOGUE (pScreen, PaintWindowBorder, rfbSpritePaintWindowBorder); -+} -+ -+static void -+rfbSpriteCopyWindow (pWin, ptOldOrg, pRegion) -+ WindowPtr pWin; -+ DDXPointRec ptOldOrg; -+ RegionPtr pRegion; -+{ -+ ScreenPtr pScreen = pWin->drawable.pScreen; -+ rfbSpriteScreenPtr pScreenPriv; -+ BoxRec cursorBox; -+ int dx, dy; -+ VNCSCREENPTR(pScreen); -+ -+ SCREEN_PROLOGUE (pScreen, CopyWindow); -+ -+ pScreenPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr; -+ if (pVNC->cursorIsDrawn) -+ { -+ /* -+ * check both the source and the destination areas. The given -+ * region is source relative, so offset the cursor box by -+ * the delta position -+ */ -+ cursorBox = pScreenPriv->saved; -+ dx = pWin->drawable.x - ptOldOrg.x; -+ dy = pWin->drawable.y - ptOldOrg.y; -+ cursorBox.x1 -= dx; -+ cursorBox.x2 -= dx; -+ cursorBox.y1 -= dy; -+ cursorBox.y2 -= dy; -+ if (RECT_IN_REGION( pScreen, pRegion, &pScreenPriv->saved) != rgnOUT || -+ RECT_IN_REGION( pScreen, pRegion, &cursorBox) != rgnOUT) -+ rfbSpriteRemoveCursor (pScreen); -+ } -+ -+ (*pScreen->CopyWindow) (pWin, ptOldOrg, pRegion); -+ -+ SCREEN_EPILOGUE (pScreen, CopyWindow, rfbSpriteCopyWindow); -+} -+ -+static void -+rfbSpriteClearToBackground (pWin, x, y, w, h, generateExposures) -+ WindowPtr pWin; -+ short x,y; -+ unsigned short w,h; -+ Bool generateExposures; -+{ -+ ScreenPtr pScreen = pWin->drawable.pScreen; -+ rfbSpriteScreenPtr pScreenPriv; -+ int realw, realh; -+ VNCSCREENPTR(pScreen); -+ -+ SCREEN_PROLOGUE (pScreen, ClearToBackground); -+ -+ pScreenPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr; -+ if (GC_CHECK(pWin)) -+ { -+ if (!(realw = w)) -+ realw = (int) pWin->drawable.width - x; -+ if (!(realh = h)) -+ realh = (int) pWin->drawable.height - y; -+ if (ORG_OVERLAP(&pScreenPriv->saved, pWin->drawable.x, pWin->drawable.y, -+ x, y, realw, realh)) -+ { -+ rfbSpriteRemoveCursor (pScreen); -+ } -+ } -+ -+ (*pScreen->ClearToBackground) (pWin, x, y, w, h, generateExposures); -+ -+ SCREEN_EPILOGUE (pScreen, ClearToBackground, rfbSpriteClearToBackground); -+} -+ -+/* -+ * GC Func wrappers -+ */ -+ -+static void -+rfbSpriteValidateGC (pGC, changes, pDrawable) -+ GCPtr pGC; -+ unsigned long changes; -+ DrawablePtr pDrawable; -+{ -+ GC_FUNC_PROLOGUE (pGC); -+ -+ (*pGC->funcs->ValidateGC) (pGC, changes, pDrawable); -+ -+ pGCPriv->wrapOps = NULL; -+ if (pDrawable->type == DRAWABLE_WINDOW && ((WindowPtr) pDrawable)->viewable) -+ { -+ WindowPtr pWin; -+ RegionPtr pRegion; -+ -+ pWin = (WindowPtr) pDrawable; -+ pRegion = &pWin->clipList; -+ if (pGC->subWindowMode == IncludeInferiors) -+ pRegion = &pWin->borderClip; -+ if (REGION_NOTEMPTY(pDrawable->pScreen, pRegion)) -+ pGCPriv->wrapOps = pGC->ops; -+ } -+ -+ GC_FUNC_EPILOGUE (pGC); -+} -+ -+static void -+rfbSpriteChangeGC (pGC, mask) -+ GCPtr pGC; -+ unsigned long mask; -+{ -+ GC_FUNC_PROLOGUE (pGC); -+ -+ (*pGC->funcs->ChangeGC) (pGC, mask); -+ -+ GC_FUNC_EPILOGUE (pGC); -+} -+ -+static void -+rfbSpriteCopyGC (pGCSrc, mask, pGCDst) -+ GCPtr pGCSrc, pGCDst; -+ unsigned long mask; -+{ -+ GC_FUNC_PROLOGUE (pGCDst); -+ -+ (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst); -+ -+ GC_FUNC_EPILOGUE (pGCDst); -+} -+ -+static void -+rfbSpriteDestroyGC (pGC) -+ GCPtr pGC; -+{ -+ GC_FUNC_PROLOGUE (pGC); -+ -+ (*pGC->funcs->DestroyGC) (pGC); -+ -+ GC_FUNC_EPILOGUE (pGC); -+} -+ -+static void -+rfbSpriteChangeClip (pGC, type, pvalue, nrects) -+ GCPtr pGC; -+ int type; -+ pointer pvalue; -+ int nrects; -+{ -+ GC_FUNC_PROLOGUE (pGC); -+ -+ (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects); -+ -+ GC_FUNC_EPILOGUE (pGC); -+} -+ -+static void -+rfbSpriteCopyClip(pgcDst, pgcSrc) -+ GCPtr pgcDst, pgcSrc; -+{ -+ GC_FUNC_PROLOGUE (pgcDst); -+ -+ (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc); -+ -+ GC_FUNC_EPILOGUE (pgcDst); -+} -+ -+static void -+rfbSpriteDestroyClip(pGC) -+ GCPtr pGC; -+{ -+ GC_FUNC_PROLOGUE (pGC); -+ -+ (* pGC->funcs->DestroyClip)(pGC); -+ -+ GC_FUNC_EPILOGUE (pGC); -+} -+ -+/* -+ * GC Op wrappers -+ */ -+ -+static void -+rfbSpriteFillSpans(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted) -+ DrawablePtr pDrawable; -+ GCPtr pGC; -+ int nInit; /* number of spans to fill */ -+ DDXPointPtr pptInit; /* pointer to list of start points */ -+ int *pwidthInit; /* pointer to list of n widths */ -+ int fSorted; -+{ -+ ScreenPtr pScreen = pDrawable->pScreen; -+ VNCSCREENPTR(pScreen); -+ -+ GC_SETUP(pDrawable, pGC); -+ -+ if (GC_CHECK((WindowPtr) pDrawable)) -+ { -+ register DDXPointPtr pts; -+ register int *widths; -+ register int nPts; -+ -+ for (pts = pptInit, widths = pwidthInit, nPts = nInit; -+ nPts--; -+ pts++, widths++) -+ { -+ if (SPN_OVERLAP(&pScreenPriv->saved,pts->y,pts->x,*widths)) -+ { -+ rfbSpriteRemoveCursor (pDrawable->pScreen); -+ break; -+ } -+ } -+ } -+ -+ GC_OP_PROLOGUE (pGC); -+ -+ (*pGC->ops->FillSpans) (pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted); -+ -+ GC_OP_EPILOGUE (pGC); -+} -+ -+static void -+rfbSpriteSetSpans(pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted) -+ DrawablePtr pDrawable; -+ GCPtr pGC; -+ char *psrc; -+ register DDXPointPtr ppt; -+ int *pwidth; -+ int nspans; -+ int fSorted; -+{ -+ ScreenPtr pScreen = pDrawable->pScreen; -+ VNCSCREENPTR(pScreen); -+ -+ GC_SETUP(pDrawable, pGC); -+ -+ if (GC_CHECK((WindowPtr) pDrawable)) -+ { -+ register DDXPointPtr pts; -+ register int *widths; -+ register int nPts; -+ -+ for (pts = ppt, widths = pwidth, nPts = nspans; -+ nPts--; -+ pts++, widths++) -+ { -+ if (SPN_OVERLAP(&pScreenPriv->saved,pts->y,pts->x,*widths)) -+ { -+ rfbSpriteRemoveCursor(pDrawable->pScreen); -+ break; -+ } -+ } -+ } -+ -+ GC_OP_PROLOGUE (pGC); -+ -+ (*pGC->ops->SetSpans) (pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted); -+ -+ GC_OP_EPILOGUE (pGC); -+} -+ -+static void -+rfbSpritePutImage(pDrawable, pGC, depth, x, y, w, h, leftPad, format, pBits) -+ DrawablePtr pDrawable; -+ GCPtr pGC; -+ int depth; -+ int x; -+ int y; -+ int w; -+ int h; -+ int format; -+ char *pBits; -+{ -+ ScreenPtr pScreen = pDrawable->pScreen; -+ VNCSCREENPTR(pScreen); -+ -+ GC_SETUP(pDrawable, pGC); -+ -+ if (GC_CHECK((WindowPtr) pDrawable)) -+ { -+ if (ORG_OVERLAP(&pScreenPriv->saved,pDrawable->x,pDrawable->y, -+ x,y,w,h)) -+ { -+ rfbSpriteRemoveCursor (pDrawable->pScreen); -+ } -+ } -+ -+ GC_OP_PROLOGUE (pGC); -+ -+ (*pGC->ops->PutImage) (pDrawable, pGC, depth, x, y, w, h, leftPad, format, pBits); -+ -+ GC_OP_EPILOGUE (pGC); -+} -+ -+static RegionPtr -+rfbSpriteCopyArea (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty) -+ DrawablePtr pSrc; -+ DrawablePtr pDst; -+ GCPtr pGC; -+ int srcx; -+ int srcy; -+ int w; -+ int h; -+ int dstx; -+ int dsty; -+{ -+ RegionPtr rgn; -+ ScreenPtr pScreen = pGC->pScreen; -+ VNCSCREENPTR(pScreen); -+ -+ GC_SETUP(pDst, pGC); -+ -+ /* check destination/source overlap. */ -+ if (GC_CHECK((WindowPtr) pDst) && -+ (ORG_OVERLAP(&pScreenPriv->saved,pDst->x,pDst->y,dstx,dsty,w,h) || -+ ((pDst == pSrc) && -+ ORG_OVERLAP(&pScreenPriv->saved,pSrc->x,pSrc->y,srcx,srcy,w,h)))) -+ { -+ rfbSpriteRemoveCursor (pDst->pScreen); -+ } -+ -+ GC_OP_PROLOGUE (pGC); -+ -+ rgn = (*pGC->ops->CopyArea) (pSrc, pDst, pGC, srcx, srcy, w, h, -+ dstx, dsty); -+ -+ GC_OP_EPILOGUE (pGC); -+ -+ return rgn; -+} -+ -+static RegionPtr -+rfbSpriteCopyPlane (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty, plane) -+ DrawablePtr pSrc; -+ DrawablePtr pDst; -+ register GCPtr pGC; -+ int srcx, -+ srcy; -+ int w, -+ h; -+ int dstx, -+ dsty; -+ unsigned long plane; -+{ -+ RegionPtr rgn; -+ ScreenPtr pScreen = pGC->pScreen; -+ VNCSCREENPTR(pScreen); -+ -+ GC_SETUP(pDst, pGC); -+ -+ /* -+ * check destination/source for overlap. -+ */ -+ if (GC_CHECK((WindowPtr) pDst) && -+ (ORG_OVERLAP(&pScreenPriv->saved,pDst->x,pDst->y,dstx,dsty,w,h) || -+ ((pDst == pSrc) && -+ ORG_OVERLAP(&pScreenPriv->saved,pSrc->x,pSrc->y,srcx,srcy,w,h)))) -+ { -+ rfbSpriteRemoveCursor (pDst->pScreen); -+ } -+ -+ GC_OP_PROLOGUE (pGC); -+ -+ rgn = (*pGC->ops->CopyPlane) (pSrc, pDst, pGC, srcx, srcy, w, h, -+ dstx, dsty, plane); -+ -+ GC_OP_EPILOGUE (pGC); -+ -+ return rgn; -+} -+ -+static void -+rfbSpritePolyPoint (pDrawable, pGC, mode, npt, pptInit) -+ DrawablePtr pDrawable; -+ GCPtr pGC; -+ int mode; /* Origin or Previous */ -+ int npt; -+ xPoint *pptInit; -+{ -+ xPoint t; -+ int n; -+ BoxRec cursor; -+ register xPoint *pts; -+ ScreenPtr pScreen = pDrawable->pScreen; -+ VNCSCREENPTR(pScreen); -+ -+ GC_SETUP (pDrawable, pGC); -+ -+ if (npt && GC_CHECK((WindowPtr) pDrawable)) -+ { -+ cursor.x1 = pScreenPriv->saved.x1 - pDrawable->x; -+ cursor.y1 = pScreenPriv->saved.y1 - pDrawable->y; -+ cursor.x2 = pScreenPriv->saved.x2 - pDrawable->x; -+ cursor.y2 = pScreenPriv->saved.y2 - pDrawable->y; -+ -+ if (mode == CoordModePrevious) -+ { -+ t.x = 0; -+ t.y = 0; -+ for (pts = pptInit, n = npt; n--; pts++) -+ { -+ t.x += pts->x; -+ t.y += pts->y; -+ if (cursor.x1 <= t.x && t.x <= cursor.x2 && -+ cursor.y1 <= t.y && t.y <= cursor.y2) -+ { -+ rfbSpriteRemoveCursor (pDrawable->pScreen); -+ break; -+ } -+ } -+ } -+ else -+ { -+ for (pts = pptInit, n = npt; n--; pts++) -+ { -+ if (cursor.x1 <= pts->x && pts->x <= cursor.x2 && -+ cursor.y1 <= pts->y && pts->y <= cursor.y2) -+ { -+ rfbSpriteRemoveCursor (pDrawable->pScreen); -+ break; -+ } -+ } -+ } -+ } -+ -+ GC_OP_PROLOGUE (pGC); -+ -+ (*pGC->ops->PolyPoint) (pDrawable, pGC, mode, npt, pptInit); -+ -+ GC_OP_EPILOGUE (pGC); -+} -+ -+static void -+rfbSpritePolylines (pDrawable, pGC, mode, npt, pptInit) -+ DrawablePtr pDrawable; -+ GCPtr pGC; -+ int mode; -+ int npt; -+ DDXPointPtr pptInit; -+{ -+ BoxPtr cursor; -+ register DDXPointPtr pts; -+ int n; -+ int x, y, x1, y1, x2, y2; -+ int lw; -+ int extra; -+ ScreenPtr pScreen = pDrawable->pScreen; -+ VNCSCREENPTR(pScreen); -+ -+ GC_SETUP (pDrawable, pGC); -+ -+ if (npt && GC_CHECK((WindowPtr) pDrawable)) -+ { -+ cursor = &pScreenPriv->saved; -+ lw = pGC->lineWidth; -+ x = pptInit->x + pDrawable->x; -+ y = pptInit->y + pDrawable->y; -+ -+ if (npt == 1) -+ { -+ extra = lw >> 1; -+ if (LINE_OVERLAP(cursor, x, y, x, y, extra)) -+ rfbSpriteRemoveCursor (pDrawable->pScreen); -+ } -+ else -+ { -+ extra = lw >> 1; -+ /* -+ * mitered joins can project quite a way from -+ * the line end; the 11 degree miter limit limits -+ * this extension to 10.43 * lw / 2, rounded up -+ * and converted to int yields 6 * lw -+ */ -+ if (pGC->joinStyle == JoinMiter) -+ extra = 6 * lw; -+ else if (pGC->capStyle == CapProjecting) -+ extra = lw; -+ for (pts = pptInit + 1, n = npt - 1; n--; pts++) -+ { -+ x1 = x; -+ y1 = y; -+ if (mode == CoordModeOrigin) -+ { -+ x2 = pDrawable->x + pts->x; -+ y2 = pDrawable->y + pts->y; -+ } -+ else -+ { -+ x2 = x + pts->x; -+ y2 = y + pts->y; -+ } -+ x = x2; -+ y = y2; -+ LINE_SORT(x1, y1, x2, y2); -+ if (LINE_OVERLAP(cursor, x1, y1, x2, y2, extra)) -+ { -+ rfbSpriteRemoveCursor (pDrawable->pScreen); -+ break; -+ } -+ } -+ } -+ } -+ GC_OP_PROLOGUE (pGC); -+ -+ (*pGC->ops->Polylines) (pDrawable, pGC, mode, npt, pptInit); -+ -+ GC_OP_EPILOGUE (pGC); -+} -+ -+static void -+rfbSpritePolySegment(pDrawable, pGC, nseg, pSegs) -+ DrawablePtr pDrawable; -+ GCPtr pGC; -+ int nseg; -+ xSegment *pSegs; -+{ -+ int n; -+ register xSegment *segs; -+ BoxPtr cursor; -+ int x1, y1, x2, y2; -+ int extra; -+ ScreenPtr pScreen = pDrawable->pScreen; -+ VNCSCREENPTR(pScreen); -+ -+ GC_SETUP(pDrawable, pGC); -+ -+ if (nseg && GC_CHECK((WindowPtr) pDrawable)) -+ { -+ cursor = &pScreenPriv->saved; -+ extra = pGC->lineWidth >> 1; -+ if (pGC->capStyle == CapProjecting) -+ extra = pGC->lineWidth; -+ for (segs = pSegs, n = nseg; n--; segs++) -+ { -+ x1 = segs->x1 + pDrawable->x; -+ y1 = segs->y1 + pDrawable->y; -+ x2 = segs->x2 + pDrawable->x; -+ y2 = segs->y2 + pDrawable->y; -+ LINE_SORT(x1, y1, x2, y2); -+ if (LINE_OVERLAP(cursor, x1, y1, x2, y2, extra)) -+ { -+ rfbSpriteRemoveCursor (pDrawable->pScreen); -+ break; -+ } -+ } -+ } -+ -+ GC_OP_PROLOGUE (pGC); -+ -+ (*pGC->ops->PolySegment) (pDrawable, pGC, nseg, pSegs); -+ -+ GC_OP_EPILOGUE (pGC); -+} -+ -+static void -+rfbSpritePolyRectangle(pDrawable, pGC, nrects, pRects) -+ DrawablePtr pDrawable; -+ GCPtr pGC; -+ int nrects; -+ xRectangle *pRects; -+{ -+ register xRectangle *rects; -+ BoxPtr cursor; -+ int lw; -+ int n; -+ int x1, y1, x2, y2; -+ ScreenPtr pScreen = pDrawable->pScreen; -+ VNCSCREENPTR(pScreen); -+ -+ GC_SETUP (pDrawable, pGC); -+ -+ if (GC_CHECK((WindowPtr) pDrawable)) -+ { -+ lw = pGC->lineWidth >> 1; -+ cursor = &pScreenPriv->saved; -+ for (rects = pRects, n = nrects; n--; rects++) -+ { -+ x1 = rects->x + pDrawable->x; -+ y1 = rects->y + pDrawable->y; -+ x2 = x1 + (int)rects->width; -+ y2 = y1 + (int)rects->height; -+ if (LINE_OVERLAP(cursor, x1, y1, x2, y1, lw) || -+ LINE_OVERLAP(cursor, x2, y1, x2, y2, lw) || -+ LINE_OVERLAP(cursor, x1, y2, x2, y2, lw) || -+ LINE_OVERLAP(cursor, x1, y1, x1, y2, lw)) -+ { -+ rfbSpriteRemoveCursor (pDrawable->pScreen); -+ break; -+ } -+ } -+ } -+ -+ GC_OP_PROLOGUE (pGC); -+ -+ (*pGC->ops->PolyRectangle) (pDrawable, pGC, nrects, pRects); -+ -+ GC_OP_EPILOGUE (pGC); -+} -+ -+static void -+rfbSpritePolyArc(pDrawable, pGC, narcs, parcs) -+ DrawablePtr pDrawable; -+ register GCPtr pGC; -+ int narcs; -+ xArc *parcs; -+{ -+ BoxPtr cursor; -+ int lw; -+ int n; -+ register xArc *arcs; -+ ScreenPtr pScreen = pDrawable->pScreen; -+ VNCSCREENPTR(pScreen); -+ -+ GC_SETUP (pDrawable, pGC); -+ -+ if (GC_CHECK((WindowPtr) pDrawable)) -+ { -+ lw = pGC->lineWidth >> 1; -+ cursor = &pScreenPriv->saved; -+ for (arcs = parcs, n = narcs; n--; arcs++) -+ { -+ if (ORG_OVERLAP (cursor, pDrawable->x, pDrawable->y, -+ arcs->x - lw, arcs->y - lw, -+ (int) arcs->width + pGC->lineWidth, -+ (int) arcs->height + pGC->lineWidth)) -+ { -+ rfbSpriteRemoveCursor (pDrawable->pScreen); -+ break; -+ } -+ } -+ } -+ -+ GC_OP_PROLOGUE (pGC); -+ -+ (*pGC->ops->PolyArc) (pDrawable, pGC, narcs, parcs); -+ -+ GC_OP_EPILOGUE (pGC); -+} -+ -+static void -+rfbSpriteFillPolygon(pDrawable, pGC, shape, mode, count, pPts) -+ register DrawablePtr pDrawable; -+ register GCPtr pGC; -+ int shape, mode; -+ int count; -+ DDXPointPtr pPts; -+{ -+ int x, y, minx, miny, maxx, maxy; -+ register DDXPointPtr pts; -+ int n; -+ ScreenPtr pScreen = pDrawable->pScreen; -+ VNCSCREENPTR(pScreen); -+ -+ GC_SETUP (pDrawable, pGC); -+ -+ if (count && GC_CHECK((WindowPtr) pDrawable)) -+ { -+ x = pDrawable->x; -+ y = pDrawable->y; -+ pts = pPts; -+ minx = maxx = pts->x; -+ miny = maxy = pts->y; -+ pts++; -+ n = count - 1; -+ -+ if (mode == CoordModeOrigin) -+ { -+ for (; n--; pts++) -+ { -+ if (pts->x < minx) -+ minx = pts->x; -+ else if (pts->x > maxx) -+ maxx = pts->x; -+ if (pts->y < miny) -+ miny = pts->y; -+ else if (pts->y > maxy) -+ maxy = pts->y; -+ } -+ minx += x; -+ miny += y; -+ maxx += x; -+ maxy += y; -+ } -+ else -+ { -+ x += minx; -+ y += miny; -+ minx = maxx = x; -+ miny = maxy = y; -+ for (; n--; pts++) -+ { -+ x += pts->x; -+ y += pts->y; -+ if (x < minx) -+ minx = x; -+ else if (x > maxx) -+ maxx = x; -+ if (y < miny) -+ miny = y; -+ else if (y > maxy) -+ maxy = y; -+ } -+ } -+ if (BOX_OVERLAP(&pScreenPriv->saved,minx,miny,maxx,maxy)) -+ rfbSpriteRemoveCursor (pDrawable->pScreen); -+ } -+ -+ GC_OP_PROLOGUE (pGC); -+ -+ (*pGC->ops->FillPolygon) (pDrawable, pGC, shape, mode, count, pPts); -+ -+ GC_OP_EPILOGUE (pGC); -+} -+ -+static void -+rfbSpritePolyFillRect(pDrawable, pGC, nrectFill, prectInit) -+ DrawablePtr pDrawable; -+ GCPtr pGC; -+ int nrectFill; /* number of rectangles to fill */ -+ xRectangle *prectInit; /* Pointer to first rectangle to fill */ -+{ -+ ScreenPtr pScreen = pDrawable->pScreen; -+ VNCSCREENPTR(pScreen); -+ -+ GC_SETUP(pDrawable, pGC); -+ -+ if (GC_CHECK((WindowPtr) pDrawable)) -+ { -+ register int nRect; -+ register xRectangle *pRect; -+ register int xorg, yorg; -+ -+ xorg = pDrawable->x; -+ yorg = pDrawable->y; -+ -+ for (nRect = nrectFill, pRect = prectInit; nRect--; pRect++) { -+ if (ORGRECT_OVERLAP(&pScreenPriv->saved,xorg,yorg,pRect)){ -+ rfbSpriteRemoveCursor(pDrawable->pScreen); -+ break; -+ } -+ } -+ } -+ -+ GC_OP_PROLOGUE (pGC); -+ -+ (*pGC->ops->PolyFillRect) (pDrawable, pGC, nrectFill, prectInit); -+ -+ GC_OP_EPILOGUE (pGC); -+} -+ -+static void -+rfbSpritePolyFillArc(pDrawable, pGC, narcs, parcs) -+ DrawablePtr pDrawable; -+ GCPtr pGC; -+ int narcs; -+ xArc *parcs; -+{ -+ ScreenPtr pScreen = pDrawable->pScreen; -+ VNCSCREENPTR(pScreen); -+ -+ GC_SETUP(pDrawable, pGC); -+ -+ if (GC_CHECK((WindowPtr) pDrawable)) -+ { -+ register int n; -+ BoxPtr cursor; -+ register xArc *arcs; -+ -+ cursor = &pScreenPriv->saved; -+ -+ for (arcs = parcs, n = narcs; n--; arcs++) -+ { -+ if (ORG_OVERLAP(cursor, pDrawable->x, pDrawable->y, -+ arcs->x, arcs->y, -+ (int) arcs->width, (int) arcs->height)) -+ { -+ rfbSpriteRemoveCursor (pDrawable->pScreen); -+ break; -+ } -+ } -+ } -+ -+ GC_OP_PROLOGUE (pGC); -+ -+ (*pGC->ops->PolyFillArc) (pDrawable, pGC, narcs, parcs); -+ -+ GC_OP_EPILOGUE (pGC); -+} -+ -+/* -+ * general Poly/Image text function. Extract glyph information, -+ * compute bounding box and remove cursor if it is overlapped. -+ */ -+ -+static Bool -+rfbSpriteTextOverlap (pDraw, font, x, y, n, charinfo, imageblt, w, cursorBox) -+ DrawablePtr pDraw; -+ FontPtr font; -+ int x, y; -+ unsigned int n; -+ CharInfoPtr *charinfo; -+ Bool imageblt; -+ unsigned int w; -+ BoxPtr cursorBox; -+{ -+ ExtentInfoRec extents; -+ -+ x += pDraw->x; -+ y += pDraw->y; -+ -+ if (FONTMINBOUNDS(font,characterWidth) >= 0) -+ { -+ /* compute an approximate (but covering) bounding box */ -+ if (!imageblt || (charinfo[0]->metrics.leftSideBearing < 0)) -+ extents.overallLeft = charinfo[0]->metrics.leftSideBearing; -+ else -+ extents.overallLeft = 0; -+ if (w) -+ extents.overallRight = w - charinfo[n-1]->metrics.characterWidth; -+ else -+ extents.overallRight = FONTMAXBOUNDS(font,characterWidth) -+ * (n - 1); -+ if (imageblt && (charinfo[n-1]->metrics.characterWidth > -+ charinfo[n-1]->metrics.rightSideBearing)) -+ extents.overallRight += charinfo[n-1]->metrics.characterWidth; -+ else -+ extents.overallRight += charinfo[n-1]->metrics.rightSideBearing; -+ if (imageblt && FONTASCENT(font) > FONTMAXBOUNDS(font,ascent)) -+ extents.overallAscent = FONTASCENT(font); -+ else -+ extents.overallAscent = FONTMAXBOUNDS(font, ascent); -+ if (imageblt && FONTDESCENT(font) > FONTMAXBOUNDS(font,descent)) -+ extents.overallDescent = FONTDESCENT(font); -+ else -+ extents.overallDescent = FONTMAXBOUNDS(font,descent); -+ if (!BOX_OVERLAP(cursorBox, -+ x + extents.overallLeft, -+ y - extents.overallAscent, -+ x + extents.overallRight, -+ y + extents.overallDescent)) -+ return FALSE; -+ else if (imageblt && w) -+ return TRUE; -+ /* if it does overlap, fall through and compute exactly, because -+ * taking down the cursor is expensive enough to make this worth it -+ */ -+ } -+ QueryGlyphExtents(font, charinfo, n, &extents); -+ if (imageblt) -+ { -+ if (extents.overallWidth > extents.overallRight) -+ extents.overallRight = extents.overallWidth; -+ if (extents.overallWidth < extents.overallLeft) -+ extents.overallLeft = extents.overallWidth; -+ if (extents.overallLeft > 0) -+ extents.overallLeft = 0; -+ if (extents.fontAscent > extents.overallAscent) -+ extents.overallAscent = extents.fontAscent; -+ if (extents.fontDescent > extents.overallDescent) -+ extents.overallDescent = extents.fontDescent; -+ } -+ return (BOX_OVERLAP(cursorBox, -+ x + extents.overallLeft, -+ y - extents.overallAscent, -+ x + extents.overallRight, -+ y + extents.overallDescent)); -+} -+ -+/* -+ * values for textType: -+ */ -+#define TT_POLY8 0 -+#define TT_IMAGE8 1 -+#define TT_POLY16 2 -+#define TT_IMAGE16 3 -+ -+static int -+rfbSpriteText (pDraw, pGC, x, y, count, chars, fontEncoding, textType, cursorBox) -+ DrawablePtr pDraw; -+ GCPtr pGC; -+ int x, -+ y; -+ unsigned long count; -+ char *chars; -+ FontEncoding fontEncoding; -+ Bool textType; -+ BoxPtr cursorBox; -+{ -+ CharInfoPtr *charinfo; -+ register CharInfoPtr *info; -+ unsigned long i; -+ unsigned int n; -+ int w; -+ void (*drawFunc)() = NULL; -+ -+ Bool imageblt; -+ -+ imageblt = (textType == TT_IMAGE8) || (textType == TT_IMAGE16); -+ -+ charinfo = (CharInfoPtr *) ALLOCATE_LOCAL(count * sizeof(CharInfoPtr)); -+ if (!charinfo) -+ return x; -+ -+ GetGlyphs(pGC->font, count, (unsigned char *)chars, -+ fontEncoding, &i, charinfo); -+ n = (unsigned int)i; -+ w = 0; -+ if (!imageblt) -+ for (info = charinfo; i--; info++) -+ w += (*info)->metrics.characterWidth; -+ -+ if (n != 0) { -+ if (rfbSpriteTextOverlap(pDraw, pGC->font, x, y, n, charinfo, imageblt, w, cursorBox)) -+ rfbSpriteRemoveCursor(pDraw->pScreen); -+ -+#ifdef AVOID_GLYPHBLT -+ /* -+ * On displays like Apollos, which do not optimize the GlyphBlt functions because they -+ * convert fonts to their internal form in RealizeFont and optimize text directly, we -+ * want to invoke the text functions here, not the GlyphBlt functions. -+ */ -+ switch (textType) -+ { -+ case TT_POLY8: -+ drawFunc = (void (*)())pGC->ops->PolyText8; -+ break; -+ case TT_IMAGE8: -+ drawFunc = pGC->ops->ImageText8; -+ break; -+ case TT_POLY16: -+ drawFunc = (void (*)())pGC->ops->PolyText16; -+ break; -+ case TT_IMAGE16: -+ drawFunc = pGC->ops->ImageText16; -+ break; -+ } -+ (*drawFunc) (pDraw, pGC, x, y, (int) count, chars); -+#else /* don't AVOID_GLYPHBLT */ -+ /* -+ * On the other hand, if the device does use GlyphBlt ultimately to do text, we -+ * don't want to slow it down by invoking the text functions and having them call -+ * GetGlyphs all over again, so we go directly to the GlyphBlt functions here. -+ */ -+ drawFunc = imageblt ? pGC->ops->ImageGlyphBlt : pGC->ops->PolyGlyphBlt; -+ (*drawFunc) (pDraw, pGC, x, y, n, charinfo, FONTGLYPHS(pGC->font)); -+#endif /* AVOID_GLYPHBLT */ -+ } -+ DEALLOCATE_LOCAL(charinfo); -+ return x + w; -+} -+ -+static int -+rfbSpritePolyText8(pDrawable, pGC, x, y, count, chars) -+ DrawablePtr pDrawable; -+ GCPtr pGC; -+ int x, y; -+ int count; -+ char *chars; -+{ -+ int ret; -+ ScreenPtr pScreen = pDrawable->pScreen; -+ VNCSCREENPTR(pScreen); -+ -+ GC_SETUP (pDrawable, pGC); -+ -+ GC_OP_PROLOGUE (pGC); -+ -+ if (GC_CHECK((WindowPtr) pDrawable)) -+ ret = rfbSpriteText (pDrawable, pGC, x, y, (unsigned long)count, chars, -+ Linear8Bit, TT_POLY8, &pScreenPriv->saved); -+ else -+ ret = (*pGC->ops->PolyText8) (pDrawable, pGC, x, y, count, chars); -+ -+ GC_OP_EPILOGUE (pGC); -+ return ret; -+} -+ -+static int -+rfbSpritePolyText16(pDrawable, pGC, x, y, count, chars) -+ DrawablePtr pDrawable; -+ GCPtr pGC; -+ int x, y; -+ int count; -+ unsigned short *chars; -+{ -+ int ret; -+ ScreenPtr pScreen = pDrawable->pScreen; -+ VNCSCREENPTR(pScreen); -+ -+ GC_SETUP(pDrawable, pGC); -+ -+ GC_OP_PROLOGUE (pGC); -+ -+ if (GC_CHECK((WindowPtr) pDrawable)) -+ ret = rfbSpriteText (pDrawable, pGC, x, y, (unsigned long)count, -+ (char *)chars, -+ FONTLASTROW(pGC->font) == 0 ? -+ Linear16Bit : TwoD16Bit, TT_POLY16, &pScreenPriv->saved); -+ else -+ ret = (*pGC->ops->PolyText16) (pDrawable, pGC, x, y, count, chars); -+ -+ GC_OP_EPILOGUE (pGC); -+ return ret; -+} -+ -+static void -+rfbSpriteImageText8(pDrawable, pGC, x, y, count, chars) -+ DrawablePtr pDrawable; -+ GCPtr pGC; -+ int x, y; -+ int count; -+ char *chars; -+{ -+ ScreenPtr pScreen = pDrawable->pScreen; -+ VNCSCREENPTR(pScreen); -+ -+ GC_SETUP(pDrawable, pGC); -+ -+ GC_OP_PROLOGUE (pGC); -+ -+ if (GC_CHECK((WindowPtr) pDrawable)) -+ (void) rfbSpriteText (pDrawable, pGC, x, y, (unsigned long)count, -+ chars, Linear8Bit, TT_IMAGE8, &pScreenPriv->saved); -+ else -+ (*pGC->ops->ImageText8) (pDrawable, pGC, x, y, count, chars); -+ -+ GC_OP_EPILOGUE (pGC); -+} -+ -+static void -+rfbSpriteImageText16(pDrawable, pGC, x, y, count, chars) -+ DrawablePtr pDrawable; -+ GCPtr pGC; -+ int x, y; -+ int count; -+ unsigned short *chars; -+{ -+ ScreenPtr pScreen = pDrawable->pScreen; -+ VNCSCREENPTR(pScreen); -+ -+ GC_SETUP(pDrawable, pGC); -+ -+ GC_OP_PROLOGUE (pGC); -+ -+ if (GC_CHECK((WindowPtr) pDrawable)) -+ (void) rfbSpriteText (pDrawable, pGC, x, y, (unsigned long)count, -+ (char *)chars, -+ FONTLASTROW(pGC->font) == 0 ? -+ Linear16Bit : TwoD16Bit, TT_IMAGE16, &pScreenPriv->saved); -+ else -+ (*pGC->ops->ImageText16) (pDrawable, pGC, x, y, count, chars); -+ -+ GC_OP_EPILOGUE (pGC); -+} -+ -+static void -+rfbSpriteImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase) -+ DrawablePtr pDrawable; -+ GCPtr pGC; -+ int x, y; -+ unsigned int nglyph; -+ CharInfoPtr *ppci; /* array of character info */ -+ pointer pglyphBase; /* start of array of glyphs */ -+{ -+ ScreenPtr pScreen = pDrawable->pScreen; -+ VNCSCREENPTR(pScreen); -+ -+ GC_SETUP(pDrawable, pGC); -+ -+ GC_OP_PROLOGUE (pGC); -+ -+ if (GC_CHECK((WindowPtr) pDrawable) && -+ rfbSpriteTextOverlap (pDrawable, pGC->font, x, y, nglyph, ppci, TRUE, 0, &pScreenPriv->saved)) -+ { -+ rfbSpriteRemoveCursor(pDrawable->pScreen); -+ } -+ (*pGC->ops->ImageGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); -+ -+ GC_OP_EPILOGUE (pGC); -+} -+ -+static void -+rfbSpritePolyGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase) -+ DrawablePtr pDrawable; -+ GCPtr pGC; -+ int x, y; -+ unsigned int nglyph; -+ CharInfoPtr *ppci; /* array of character info */ -+ pointer pglyphBase; /* start of array of glyphs */ -+{ -+ ScreenPtr pScreen = pDrawable->pScreen; -+ VNCSCREENPTR(pScreen); -+ -+ GC_SETUP (pDrawable, pGC); -+ -+ GC_OP_PROLOGUE (pGC); -+ -+ if (GC_CHECK((WindowPtr) pDrawable) && -+ rfbSpriteTextOverlap (pDrawable, pGC->font, x, y, nglyph, ppci, FALSE, 0, &pScreenPriv->saved)) -+ { -+ rfbSpriteRemoveCursor(pDrawable->pScreen); -+ } -+ (*pGC->ops->PolyGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); -+ -+ GC_OP_EPILOGUE (pGC); -+} -+ -+static void -+rfbSpritePushPixels(pGC, pBitMap, pDrawable, w, h, x, y) -+ GCPtr pGC; -+ PixmapPtr pBitMap; -+ DrawablePtr pDrawable; -+ int w, h, x, y; -+{ -+ VNCSCREENPTR(pGC->pScreen); -+ GC_SETUP(pDrawable, pGC); -+ -+ if (GC_CHECK((WindowPtr) pDrawable) && -+ ORG_OVERLAP(&pScreenPriv->saved,pDrawable->x,pDrawable->y,x,y,w,h)) -+ { -+ rfbSpriteRemoveCursor (pDrawable->pScreen); -+ } -+ -+ GC_OP_PROLOGUE (pGC); -+ -+ (*pGC->ops->PushPixels) (pGC, pBitMap, pDrawable, w, h, x, y); -+ -+ GC_OP_EPILOGUE (pGC); -+} -+ -+#ifdef NEED_LINEHELPER -+/* -+ * I don't expect this routine will ever be called, as the GC -+ * will have been unwrapped for the line drawing -+ */ -+ -+static void -+rfbSpriteLineHelper() -+{ -+ FatalError("rfbSpriteLineHelper called\n"); -+} -+#endif -+ -+#ifdef RENDER -+ -+# define mod(a,b) ((b) == 1 ? 0 : (a) >= 0 ? (a) % (b) : (b) - (-a) % (b)) -+ -+static void -+rfbSpritePictureOverlap (PicturePtr pPict, -+ INT16 x, -+ INT16 y, -+ CARD16 w, -+ CARD16 h) -+{ -+ VNCSCREENPTR(pPict->pDrawable->pScreen); -+ -+ if (pPict->pDrawable->type == DRAWABLE_WINDOW) -+ { -+ WindowPtr pWin = (WindowPtr) (pPict->pDrawable); -+ rfbSpriteScreenPtr pScreenPriv = (rfbSpriteScreenPtr) -+ pPict->pDrawable->pScreen->devPrivates[rfbSpriteScreenIndex].ptr; -+ if (GC_CHECK(pWin)) -+ { -+ if (pPict->repeat) -+ { -+ x = mod(x,pWin->drawable.width); -+ y = mod(y,pWin->drawable.height); -+ } -+ if (ORG_OVERLAP (&pScreenPriv->saved, pWin->drawable.x, pWin->drawable.y, -+ x, y, w, h)) -+ rfbSpriteRemoveCursor (pWin->drawable.pScreen); -+ } -+ } -+} -+ -+#define PICTURE_PROLOGUE(ps, pScreenPriv, field) \ -+ ps->field = pScreenPriv->field -+ -+#define PICTURE_EPILOGUE(ps, field, wrap) \ -+ ps->field = wrap -+ -+static void -+rfbSpriteComposite(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; -+ PictureScreenPtr ps = GetPictureScreen(pScreen); -+ rfbSpriteScreenPtr pScreenPriv; -+ -+ pScreenPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr; -+ PICTURE_PROLOGUE(ps, pScreenPriv, Composite); -+ rfbSpritePictureOverlap (pSrc, xSrc, ySrc, width, height); -+ if (pMask) -+ rfbSpritePictureOverlap (pMask, xMask, yMask, width, height); -+ rfbSpritePictureOverlap (pDst, xDst, yDst, width, height); -+ -+ (*ps->Composite) (op, -+ pSrc, -+ pMask, -+ pDst, -+ xSrc, -+ ySrc, -+ xMask, -+ yMask, -+ xDst, -+ yDst, -+ width, -+ height); -+ -+ PICTURE_EPILOGUE(ps, Composite, rfbSpriteComposite); -+} -+ -+static void -+rfbSpriteGlyphs(CARD8 op, -+ PicturePtr pSrc, -+ PicturePtr pDst, -+ PictFormatPtr maskFormat, -+ INT16 xSrc, -+ INT16 ySrc, -+ int nlist, -+ GlyphListPtr list, -+ GlyphPtr *glyphs) -+{ -+ ScreenPtr pScreen = pDst->pDrawable->pScreen; -+ VNCSCREENPTR(pScreen); -+ PictureScreenPtr ps = GetPictureScreen(pScreen); -+ rfbSpriteScreenPtr pScreenPriv; -+ -+ pScreenPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr; -+ PICTURE_PROLOGUE(ps, pScreenPriv, Glyphs); -+ if (pSrc->pDrawable->type == DRAWABLE_WINDOW) -+ { -+ WindowPtr pSrcWin = (WindowPtr) (pSrc->pDrawable); -+ -+ if (GC_CHECK(pSrcWin)) -+ rfbSpriteRemoveCursor (pScreen); -+ } -+ if (pDst->pDrawable->type == DRAWABLE_WINDOW) -+ { -+ WindowPtr pDstWin = (WindowPtr) (pDst->pDrawable); -+ -+ if (GC_CHECK(pDstWin)) -+ { -+ BoxRec extents; -+ -+ miGlyphExtents (nlist, list, glyphs, &extents); -+ if (BOX_OVERLAP(&pScreenPriv->saved, -+ extents.x1 + pDstWin->drawable.x, -+ extents.y1 + pDstWin->drawable.y, -+ extents.x2 + pDstWin->drawable.x, -+ extents.y2 + pDstWin->drawable.y)) -+ { -+ rfbSpriteRemoveCursor (pScreen); -+ } -+ } -+ } -+ -+ (*ps->Glyphs) (op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs); -+ -+ PICTURE_EPILOGUE (ps, Glyphs, rfbSpriteGlyphs); -+} -+#endif -+ -+/* -+ * miPointer interface routines -+ */ -+ -+#define SPRITE_PAD 8 -+ -+static Bool -+rfbSpriteRealizeCursor (pScreen, pCursor) -+ ScreenPtr pScreen; -+ CursorPtr pCursor; -+{ -+ rfbSpriteScreenPtr pScreenPriv; -+ -+ pScreenPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr; -+ if (pCursor == pScreenPriv->pCursor) -+ pScreenPriv->checkPixels = TRUE; -+ return (*pScreenPriv->funcs->RealizeCursor) (pScreen, pCursor); -+} -+ -+static Bool -+rfbSpriteUnrealizeCursor (pScreen, pCursor) -+ ScreenPtr pScreen; -+ CursorPtr pCursor; -+{ -+ rfbSpriteScreenPtr pScreenPriv; -+ -+ pScreenPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr; -+ return (*pScreenPriv->funcs->UnrealizeCursor) (pScreen, pCursor); -+} -+ -+static void -+rfbSpriteSetCursor (pScreen, pCursor, x, y) -+ ScreenPtr pScreen; -+ CursorPtr pCursor; -+{ -+ rfbSpriteScreenPtr pScreenPriv; -+ rfbClientPtr cl, nextCl; -+ VNCSCREENPTR(pScreen); -+ -+ pScreenPriv -+ = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr; -+ if (!pCursor) -+ { -+ pScreenPriv->shouldBeUp = FALSE; -+ if (pVNC->cursorIsDrawn) -+ rfbSpriteRemoveCursor (pScreen); -+ pScreenPriv->pCursor = 0; -+ return; -+ } -+ pScreenPriv->shouldBeUp = TRUE; -+ if (pScreenPriv->x == x && -+ pScreenPriv->y == y && -+ pScreenPriv->pCursor == pCursor && -+ !pScreenPriv->checkPixels) -+ { -+ return; -+ } -+ pScreenPriv->x = x; -+ pScreenPriv->y = y; -+ pScreenPriv->pCacheWin = NullWindow; -+ if (pScreenPriv->checkPixels || pScreenPriv->pCursor != pCursor) -+ { -+ pScreenPriv->pCursor = pCursor; -+ rfbSpriteFindColors (pScreen); -+ } -+ if (pVNC->cursorIsDrawn) { -+ int sx, sy; -+ /* -+ * check to see if the old saved region -+ * encloses the new sprite, in which case we use -+ * the flicker-free MoveCursor primitive. -+ */ -+ sx = pScreenPriv->x - (int)pCursor->bits->xhot; -+ sy = pScreenPriv->y - (int)pCursor->bits->yhot; -+ if (sx + (int) pCursor->bits->width >= pScreenPriv->saved.x1 && -+ sx < pScreenPriv->saved.x2 && -+ sy + (int) pCursor->bits->height >= pScreenPriv->saved.y1 && -+ sy < pScreenPriv->saved.y2 && -+ (int) pCursor->bits->width + (2 * SPRITE_PAD) == -+ pScreenPriv->saved.x2 - pScreenPriv->saved.x1 && -+ (int) pCursor->bits->height + (2 * SPRITE_PAD) == -+ pScreenPriv->saved.y2 - pScreenPriv->saved.y1 -+ ) -+ { -+ pVNC->cursorIsDrawn = FALSE; -+ if (!(sx >= pScreenPriv->saved.x1 && -+ sx + (int)pCursor->bits->width < pScreenPriv->saved.x2 && -+ sy >= pScreenPriv->saved.y1 && -+ sy + (int)pCursor->bits->height < pScreenPriv->saved.y2)) -+ { -+ int oldx1, oldy1, dx, dy; -+ -+ oldx1 = pScreenPriv->saved.x1; -+ oldy1 = pScreenPriv->saved.y1; -+ dx = oldx1 - (sx - SPRITE_PAD); -+ dy = oldy1 - (sy - SPRITE_PAD); -+ pScreenPriv->saved.x1 -= dx; -+ pScreenPriv->saved.y1 -= dy; -+ pScreenPriv->saved.x2 -= dx; -+ pScreenPriv->saved.y2 -= dy; -+ (void) (*pScreenPriv->funcs->ChangeSave) (pScreen, -+ pScreenPriv->saved.x1, -+ pScreenPriv->saved.y1, -+ pScreenPriv->saved.x2 - pScreenPriv->saved.x1, -+ pScreenPriv->saved.y2 - pScreenPriv->saved.y1, -+ dx, dy); -+ } -+ (void) (*pScreenPriv->funcs->MoveCursor) (pScreen, pCursor, -+ pScreenPriv->saved.x1, -+ pScreenPriv->saved.y1, -+ pScreenPriv->saved.x2 - pScreenPriv->saved.x1, -+ pScreenPriv->saved.y2 - pScreenPriv->saved.y1, -+ sx - pScreenPriv->saved.x1, -+ sy - pScreenPriv->saved.y1, -+ pScreenPriv->colors[SOURCE_COLOR].pixel, -+ pScreenPriv->colors[MASK_COLOR].pixel); -+ pVNC->cursorIsDrawn = TRUE; -+ } -+ else -+ { -+ rfbSpriteRemoveCursor (pScreen); -+ } -+ } -+#if 0 -+ if (!pVNC->cursorIsDrawn && pScreenPriv->pCursor) -+ rfbSpriteRestoreCursor (pScreen); -+#endif -+ if (pVNC->cursorIsDrawn) -+ rfbSpriteRemoveCursor (pScreen); -+ -+ for (cl = rfbClientHead; cl; cl = nextCl) { -+ nextCl = cl->next; -+ if (cl->enableCursorPosUpdates) { -+ if (x == cl->cursorX && y == cl->cursorY) { -+ cl->cursorWasMoved = FALSE; -+ continue; -+ } -+ cl->cursorWasMoved = TRUE; -+ } -+ if (REGION_NOTEMPTY(pScreen,&cl->requestedRegion)) { -+ /* cursorIsDrawn is guaranteed to be FALSE here, so we definitely -+ want to send a screen update to the client, even if that's only -+ putting up the cursor */ -+ rfbSendFramebufferUpdate(pScreen, cl); -+ } -+ } -+} -+ -+static void -+rfbSpriteMoveCursor (pScreen, x, y) -+ ScreenPtr pScreen; -+ int x, y; -+{ -+ rfbSpriteScreenPtr pScreenPriv; -+ -+ pScreenPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr; -+ rfbSpriteSetCursor (pScreen, pScreenPriv->pCursor, x, y); -+} -+ -+/* -+ * undraw/draw cursor -+ */ -+ -+void -+rfbSpriteRemoveCursor (pScreen) -+ ScreenPtr pScreen; -+{ -+ rfbSpriteScreenPtr pScreenPriv; -+ VNCSCREENPTR(pScreen); -+ -+ if (!pVNC->cursorIsDrawn) -+ return; -+ -+ pScreenPriv -+ = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr; -+ -+ pVNC->dontSendFramebufferUpdate = TRUE; -+ pVNC->cursorIsDrawn = FALSE; -+ pScreenPriv->pCacheWin = NullWindow; -+ if (!(*pScreenPriv->funcs->RestoreUnderCursor) (pScreen, -+ pScreenPriv->saved.x1, -+ pScreenPriv->saved.y1, -+ pScreenPriv->saved.x2 - pScreenPriv->saved.x1, -+ pScreenPriv->saved.y2 - pScreenPriv->saved.y1)) -+ { -+ pVNC->cursorIsDrawn = TRUE; -+ } -+ pVNC->dontSendFramebufferUpdate = FALSE; -+} -+ -+ -+void -+rfbSpriteRestoreCursor (pScreen) -+ ScreenPtr pScreen; -+{ -+ rfbSpriteScreenPtr pScreenPriv; -+ int x, y; -+ CursorPtr pCursor; -+ VNCSCREENPTR(pScreen); -+ -+ pScreenPriv -+ = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr; -+ pCursor = pScreenPriv->pCursor; -+ -+ if (pVNC->cursorIsDrawn || !pCursor) -+ return; -+ -+ pVNC->dontSendFramebufferUpdate = TRUE; -+ -+ rfbSpriteComputeSaved (pScreen); -+ -+ x = pScreenPriv->x - (int)pCursor->bits->xhot; -+ y = pScreenPriv->y - (int)pCursor->bits->yhot; -+ if ((*pScreenPriv->funcs->SaveUnderCursor) (pScreen, -+ pScreenPriv->saved.x1, -+ pScreenPriv->saved.y1, -+ pScreenPriv->saved.x2 - pScreenPriv->saved.x1, -+ pScreenPriv->saved.y2 - pScreenPriv->saved.y1)) -+ { -+ if (pScreenPriv->checkPixels) -+ rfbSpriteFindColors (pScreen); -+ if ((*pScreenPriv->funcs->PutUpCursor) (pScreen, pCursor, x, y, -+ pScreenPriv->colors[SOURCE_COLOR].pixel, -+ pScreenPriv->colors[MASK_COLOR].pixel)) -+ pVNC->cursorIsDrawn = TRUE; -+ } -+ -+ pVNC->dontSendFramebufferUpdate = FALSE; -+} -+ -+/* -+ * compute the desired area of the screen to save -+ */ -+ -+static void -+rfbSpriteComputeSaved (pScreen) -+ ScreenPtr pScreen; -+{ -+ rfbSpriteScreenPtr pScreenPriv; -+ int x, y, w, h; -+ int wpad, hpad; -+ CursorPtr pCursor; -+ -+ pScreenPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr; -+ pCursor = pScreenPriv->pCursor; -+ x = pScreenPriv->x - (int)pCursor->bits->xhot; -+ y = pScreenPriv->y - (int)pCursor->bits->yhot; -+ w = pCursor->bits->width; -+ h = pCursor->bits->height; -+ wpad = SPRITE_PAD; -+ hpad = SPRITE_PAD; -+ pScreenPriv->saved.x1 = x - wpad; -+ pScreenPriv->saved.y1 = y - hpad; -+ pScreenPriv->saved.x2 = pScreenPriv->saved.x1 + w + wpad * 2; -+ pScreenPriv->saved.y2 = pScreenPriv->saved.y1 + h + hpad * 2; -+} -+ -+ -+/* -+ * this function is called when the cursor shape is being changed -+ */ -+ -+static Bool -+rfbDisplayCursor(pScreen, pCursor) -+ ScreenPtr pScreen; -+ CursorPtr pCursor; -+{ -+ rfbClientPtr cl; -+ rfbSpriteScreenPtr pPriv; -+ -+ for (cl = rfbClientHead; cl ; cl = cl->next) { -+ if (cl->enableCursorShapeUpdates) -+ cl->cursorWasChanged = TRUE; -+ } -+ -+ pPriv = (rfbSpriteScreenPtr)pScreen->devPrivates[rfbSpriteScreenIndex].ptr; -+ return (*pPriv->DisplayCursor)(pScreen, pCursor); -+} -+ -+ -+/* -+ * obtain current cursor pointer -+ */ -+ -+CursorPtr -+rfbSpriteGetCursorPtr (pScreen) -+ ScreenPtr pScreen; -+{ -+ rfbSpriteScreenPtr pScreenPriv; -+ -+ pScreenPriv = (rfbSpriteScreenPtr) -+ pScreen->devPrivates[rfbSpriteScreenIndex].ptr; -+ -+ return pScreenPriv->pCursor; -+} -+ -+/* -+ * obtain current cursor position -+ */ -+ -+void -+rfbSpriteGetCursorPos (pScreen, px, py) -+ ScreenPtr pScreen; -+ int *px, *py; -+{ -+ rfbSpriteScreenPtr pScreenPriv; -+ -+ pScreenPriv = (rfbSpriteScreenPtr) -+ pScreen->devPrivates[rfbSpriteScreenIndex].ptr; -+ -+ *px = pScreenPriv->x; -+ *py = pScreenPriv->y; -+} -+ -diff --git a/hw/dmx/vnc/sprite.h b/hw/dmx/vnc/sprite.h -new file mode 100644 -index 0000000..ed34726 ---- /dev/null -+++ b/hw/dmx/vnc/sprite.h -@@ -0,0 +1,141 @@ -+/* -+ * sprite.h -+ * -+ * software-sprite/sprite drawing - based on misprite -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ */ -+ -+/* -+ * 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) 1989 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. -+*/ -+ -+typedef struct { -+ Bool (*RealizeCursor)( -+ ScreenPtr /*pScreen*/, -+ CursorPtr /*pCursor*/ -+); -+ Bool (*UnrealizeCursor)( -+ ScreenPtr /*pScreen*/, -+ CursorPtr /*pCursor*/ -+); -+ Bool (*PutUpCursor)( -+ ScreenPtr /*pScreen*/, -+ CursorPtr /*pCursor*/, -+ int /*x*/, -+ int /*y*/, -+ unsigned long /*source*/, -+ unsigned long /*mask*/ -+); -+ Bool (*SaveUnderCursor)( -+ ScreenPtr /*pScreen*/, -+ int /*x*/, -+ int /*y*/, -+ int /*w*/, -+ int /*h*/ -+); -+ Bool (*RestoreUnderCursor)( -+ ScreenPtr /*pScreen*/, -+ int /*x*/, -+ int /*y*/, -+ int /*w*/, -+ int /*h*/ -+); -+ Bool (*MoveCursor)( -+ ScreenPtr /*pScreen*/, -+ CursorPtr /*pCursor*/, -+ int /*x*/, -+ int /*y*/, -+ int /*w*/, -+ int /*h*/, -+ int /*dx*/, -+ int /*dy*/, -+ unsigned long /*source*/, -+ unsigned long /*mask*/ -+); -+ Bool (*ChangeSave)( -+ ScreenPtr /*pScreen*/, -+ int /*x*/, -+ int /*y*/, -+ int /*w*/, -+ int /*h*/, -+ int /*dx*/, -+ int /*dy*/ -+); -+ -+} rfbSpriteCursorFuncRec, *rfbSpriteCursorFuncPtr; -+ -+extern Bool rfbSpriteInitialize( -+#if NeedFunctionPrototypes -+ ScreenPtr /*pScreen*/, -+ rfbSpriteCursorFuncPtr /*cursorFuncs*/, -+ miPointerScreenFuncPtr /*screenFuncs*/ -+#endif -+); -+ -+extern void rfbSpriteRestoreCursor( -+#if NeedFunctionPrototypes -+ ScreenPtr /*pScreen*/ -+#endif -+); -+ -+extern void rfbSpriteRemoveCursor( -+#if NeedFunctionPrototypes -+ ScreenPtr /*pScreen*/ -+#endif -+); -+ -+extern CursorPtr rfbSpriteGetCursorPtr( -+#if NeedFunctionPrototypes -+ ScreenPtr /*pScreen*/ -+#endif -+); -+ -+extern void rfbSpriteGetCursorPos( -+#if NeedFunctionPrototypes -+ ScreenPtr /*pScreen*/, -+ int * /*px*/, -+ int * /*py*/ -+#endif -+); -diff --git a/hw/dmx/vnc/spritest.h b/hw/dmx/vnc/spritest.h -new file mode 100644 -index 0000000..8593ee0 ---- /dev/null -+++ b/hw/dmx/vnc/spritest.h -@@ -0,0 +1,138 @@ -+/* -+ * spritest.h -+ * -+ * sprite structures - based on misprite -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ */ -+ -+/* -+ * 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) 1989 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 "sprite.h" -+ -+#ifdef RENDER -+# include "picturestr.h" -+#endif -+ -+/* -+ * per screen information -+ */ -+ -+typedef struct { -+ CloseScreenProcPtr CloseScreen; -+ GetImageProcPtr GetImage; -+ GetSpansProcPtr GetSpans; -+ SourceValidateProcPtr SourceValidate; -+ CreateGCProcPtr CreateGC; -+ ScreenBlockHandlerProcPtr BlockHandler; -+ InstallColormapProcPtr InstallColormap; -+ StoreColorsProcPtr StoreColors; -+ PaintWindowBackgroundProcPtr PaintWindowBackground; -+ PaintWindowBorderProcPtr PaintWindowBorder; -+ CopyWindowProcPtr CopyWindow; -+ ClearToBackgroundProcPtr ClearToBackground; -+ SaveDoomedAreasProcPtr SaveDoomedAreas; -+ RestoreAreasProcPtr RestoreAreas; -+ DisplayCursorProcPtr DisplayCursor; -+#ifdef RENDER -+ CompositeProcPtr Composite; -+ GlyphsProcPtr Glyphs; -+#endif -+ -+ CursorPtr pCursor; -+ int x; -+ int y; -+ Bool shouldBeUp; -+ BoxRec saved; -+ WindowPtr pCacheWin; -+ Bool isInCacheWin; -+ Bool checkPixels; -+ xColorItem colors[2]; -+ ColormapPtr pInstalledMap; -+ ColormapPtr pColormap; -+ VisualPtr pVisual; -+ rfbSpriteCursorFuncPtr funcs; -+} rfbSpriteScreenRec, *rfbSpriteScreenPtr; -+ -+#define SOURCE_COLOR 0 -+#define MASK_COLOR 1 -+ -+typedef struct { -+ GCFuncs *wrapFuncs; -+ GCOps *wrapOps; -+} rfbSpriteGCRec, *rfbSpriteGCPtr; -+ -+/* -+ * Overlap BoxPtr and Box elements -+ */ -+#define BOX_OVERLAP(pCbox,X1,Y1,X2,Y2) \ -+ (((pCbox)->x1 <= (X2)) && ((X1) <= (pCbox)->x2) && \ -+ ((pCbox)->y1 <= (Y2)) && ((Y1) <= (pCbox)->y2)) -+ -+/* -+ * Overlap BoxPtr, origins, and rectangle -+ */ -+#define ORG_OVERLAP(pCbox,xorg,yorg,x,y,w,h) \ -+ BOX_OVERLAP((pCbox),(x)+(xorg),(y)+(yorg),(x)+(xorg)+(w),(y)+(yorg)+(h)) -+ -+/* -+ * Overlap BoxPtr, origins and RectPtr -+ */ -+#define ORGRECT_OVERLAP(pCbox,xorg,yorg,pRect) \ -+ ORG_OVERLAP((pCbox),(xorg),(yorg),(pRect)->x,(pRect)->y, \ -+ (int)((pRect)->width), (int)((pRect)->height)) -+/* -+ * Overlap BoxPtr and horizontal span -+ */ -+#define SPN_OVERLAP(pCbox,y,x,w) BOX_OVERLAP((pCbox),(x),(y),(x)+(w),(y)) -+ -+#define LINE_SORT(x1,y1,x2,y2) \ -+{ int _t; \ -+ if (x1 > x2) { _t = x1; x1 = x2; x2 = _t; } \ -+ if (y1 > y2) { _t = y1; y1 = y2; y2 = _t; } } -+ -+#define LINE_OVERLAP(pCbox,x1,y1,x2,y2,lw2) \ -+ BOX_OVERLAP((pCbox), (x1)-(lw2), (y1)-(lw2), (x2)+(lw2), (y2)+(lw2)) -diff --git a/hw/dmx/vnc/stats.c b/hw/dmx/vnc/stats.c -new file mode 100644 -index 0000000..53017ee ---- /dev/null -+++ b/hw/dmx/vnc/stats.c -@@ -0,0 +1,113 @@ -+/* -+ * stats.c -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ */ -+ -+/* -+ * Copyright (C) 2002 Constantin Kaplinsky. All Rights Reserved. -+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. -+ * -+ * This is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This software is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this software; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -+ * USA. -+ */ -+ -+#include -+#include -+#include "rfb.h" -+ -+static char* encNames[] = { -+ "raw", "copyRect", "RRE", "[encoding 3]", "CoRRE", "hextile", -+ "zlib", "tight", "[encoding 8]", "[encoding 9]" -+}; -+ -+ -+void -+rfbResetStats(rfbClientPtr cl) -+{ -+ int i; -+ for (i = 0; i < MAX_ENCODINGS; i++) { -+ cl->rfbBytesSent[i] = 0; -+ cl->rfbRectanglesSent[i] = 0; -+ } -+ cl->rfbLastRectMarkersSent = 0; -+ cl->rfbLastRectBytesSent = 0; -+ cl->rfbCursorShapeBytesSent = 0; -+ cl->rfbCursorShapeUpdatesSent = 0; -+ cl->rfbCursorPosBytesSent = 0; -+ cl->rfbCursorPosUpdatesSent = 0; -+ cl->rfbFramebufferUpdateMessagesSent = 0; -+ cl->rfbRawBytesEquivalent = 0; -+ cl->rfbKeyEventsRcvd = 0; -+ cl->rfbPointerEventsRcvd = 0; -+} -+ -+void -+rfbPrintStats(rfbClientPtr cl) -+{ -+ int i; -+ int totalRectanglesSent = 0; -+ int totalBytesSent = 0; -+ -+ rfbLog("Statistics:\n"); -+ -+ if ((cl->rfbKeyEventsRcvd != 0) || (cl->rfbPointerEventsRcvd != 0)) -+ rfbLog(" key events received %d, pointer events %d\n", -+ cl->rfbKeyEventsRcvd, cl->rfbPointerEventsRcvd); -+ -+ for (i = 0; i < MAX_ENCODINGS; i++) { -+ totalRectanglesSent += cl->rfbRectanglesSent[i]; -+ totalBytesSent += cl->rfbBytesSent[i]; -+ } -+ totalRectanglesSent += (cl->rfbCursorShapeUpdatesSent + -+ cl->rfbCursorPosUpdatesSent + -+ cl->rfbLastRectMarkersSent); -+ totalBytesSent += (cl->rfbCursorShapeBytesSent + -+ cl->rfbCursorPosBytesSent + -+ cl->rfbLastRectBytesSent); -+ -+ rfbLog(" framebuffer updates %d, rectangles %d, bytes %d\n", -+ cl->rfbFramebufferUpdateMessagesSent, totalRectanglesSent, -+ totalBytesSent); -+ -+ if (cl->rfbLastRectMarkersSent != 0) -+ rfbLog(" LastRect markers %d, bytes %d\n", -+ cl->rfbLastRectMarkersSent, cl->rfbLastRectBytesSent); -+ -+ if (cl->rfbCursorShapeUpdatesSent != 0) -+ rfbLog(" cursor shape updates %d, bytes %d\n", -+ cl->rfbCursorShapeUpdatesSent, cl->rfbCursorShapeBytesSent); -+ -+ if (cl->rfbCursorPosUpdatesSent != 0) -+ rfbLog(" cursor position updates %d, bytes %d\n", -+ cl->rfbCursorPosUpdatesSent, cl->rfbCursorPosBytesSent); -+ -+ for (i = 0; i < MAX_ENCODINGS; i++) { -+ if (cl->rfbRectanglesSent[i] != 0) -+ rfbLog(" %s rectangles %d, bytes %d\n", -+ encNames[i], cl->rfbRectanglesSent[i], cl->rfbBytesSent[i]); -+ } -+ -+ if ((totalBytesSent - cl->rfbBytesSent[rfbEncodingCopyRect]) != 0) { -+ rfbLog(" raw bytes equivalent %d, compression ratio %f\n", -+ cl->rfbRawBytesEquivalent, -+ (double)cl->rfbRawBytesEquivalent -+ / (double)(totalBytesSent - -+ cl->rfbBytesSent[rfbEncodingCopyRect] - -+ cl->rfbCursorShapeBytesSent - -+ cl->rfbCursorPosBytesSent - -+ cl->rfbLastRectBytesSent)); -+ } -+} -diff --git a/hw/dmx/vnc/tableinitcmtemplate.c b/hw/dmx/vnc/tableinitcmtemplate.c -new file mode 100644 -index 0000000..8a757e5 ---- /dev/null -+++ b/hw/dmx/vnc/tableinitcmtemplate.c -@@ -0,0 +1,89 @@ -+/* -+ * tableinitcmtemplate.c - template for initialising lookup tables for -+ * translation from a colour map to true colour. -+ * -+ * This file shouldn't be compiled. It is included multiple times by -+ * translate.c, each time with a different definition of the macro OUT. -+ * For each value of OUT, this file defines a function which allocates an -+ * appropriately sized lookup table and initialises it. -+ * -+ * I know this code isn't nice to read because of all the macros, but -+ * efficiency is important here. -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ */ -+ -+/* -+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. -+ * -+ * This is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This software is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this software; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -+ * USA. -+ */ -+ -+#if !defined(OUT) -+#error "This file shouldn't be compiled." -+#error "It is included as part of translate.c" -+#endif -+ -+#define OUT_T CONCAT2E(CARD,OUT) -+#define SwapOUT(x) CONCAT2E(Swap,OUT(x)) -+#define rfbInitColourMapSingleTableOUT \ -+ CONCAT2E(rfbInitColourMapSingleTable,OUT) -+ -+static void -+rfbInitColourMapSingleTableOUT (ScreenPtr pScreen, char **table, rfbPixelFormat *in, -+ rfbPixelFormat *out) -+{ -+ VNCSCREENPTR(pScreen); -+ int i, r, g, b; -+ OUT_T *t; -+ EntryPtr pent; -+ int nEntries = 1 << in->bitsPerPixel; -+ -+ if (*table) free(*table); -+ *table = (char *)malloc(nEntries * sizeof(OUT_T)); -+ t = (OUT_T *)*table; -+ -+#if XFREE86VNC -+ pent = (EntryPtr)&miInstalledMaps[pScreen->myNum]->red[0]; -+#else -+ pent = (EntryPtr)&pVNC->rfbInstalledColormap->red[0]; -+#endif -+ -+ for (i = 0; i < nEntries; i++) { -+ 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; -+ } -+ t[i] = ((((r * out->redMax + 32767) / 65535) << out->redShift) | -+ (((g * out->greenMax + 32767) / 65535) << out->greenShift) | -+ (((b * out->blueMax + 32767) / 65535) << out->blueShift)); -+#if (OUT != 8) -+ if (out->bigEndian != in->bigEndian) { -+ t[i] = SwapOUT(t[i]); -+ } -+#endif -+ pent++; -+ } -+} -+ -+#undef OUT_T -+#undef SwapOUT -+#undef rfbInitColourMapSingleTableOUT -diff --git a/hw/dmx/vnc/tableinittctemplate.c b/hw/dmx/vnc/tableinittctemplate.c -new file mode 100644 -index 0000000..da8ae01 ---- /dev/null -+++ b/hw/dmx/vnc/tableinittctemplate.c -@@ -0,0 +1,142 @@ -+/* -+ * tableinittctemplate.c - template for initialising lookup tables for -+ * truecolour to truecolour translation. -+ * -+ * This file shouldn't be compiled. It is included multiple times by -+ * translate.c, each time with a different definition of the macro OUT. -+ * For each value of OUT, this file defines two functions for initialising -+ * lookup tables. One is for truecolour translation using a single lookup -+ * table, the other is for truecolour translation using three separate -+ * lookup tables for the red, green and blue values. -+ * -+ * I know this code isn't nice to read because of all the macros, but -+ * efficiency is important here. -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ */ -+ -+/* -+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. -+ * -+ * This is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This software is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this software; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -+ * USA. -+ */ -+ -+#if !defined(OUT) -+#error "This file shouldn't be compiled." -+#error "It is included as part of translate.c" -+#endif -+ -+#define OUT_T CONCAT2E(CARD,OUT) -+#define SwapOUT(x) CONCAT2E(Swap,OUT(x)) -+#define rfbInitTrueColourSingleTableOUT \ -+ CONCAT2E(rfbInitTrueColourSingleTable,OUT) -+#define rfbInitTrueColourRGBTablesOUT CONCAT2E(rfbInitTrueColourRGBTables,OUT) -+#define rfbInitOneRGBTableOUT CONCAT2E(rfbInitOneRGBTable,OUT) -+ -+static void -+rfbInitOneRGBTableOUT (OUT_T *table, int inMax, int outMax, int outShift, -+ int swap); -+ -+ -+/* -+ * rfbInitTrueColourSingleTable sets up a single lookup table for truecolour -+ * translation. -+ */ -+ -+static void -+rfbInitTrueColourSingleTableOUT (ScreenPtr pScreen, char **table, rfbPixelFormat *in, -+ rfbPixelFormat *out) -+{ -+ int i; -+ int inRed, inGreen, inBlue, outRed, outGreen, outBlue; -+ OUT_T *t; -+ int nEntries = 1 << in->bitsPerPixel; -+ -+ if (*table) free(*table); -+ *table = (char *)malloc(nEntries * sizeof(OUT_T)); -+ t = (OUT_T *)*table; -+ -+ for (i = 0; i < nEntries; i++) { -+ inRed = (i >> in->redShift) & in->redMax; -+ inGreen = (i >> in->greenShift) & in->greenMax; -+ inBlue = (i >> in->blueShift) & in->blueMax; -+ -+ outRed = (inRed * out->redMax + in->redMax / 2) / in->redMax; -+ outGreen = (inGreen * out->greenMax + in->greenMax / 2) / in->greenMax; -+ outBlue = (inBlue * out->blueMax + in->blueMax / 2) / in->blueMax; -+ -+ t[i] = ((outRed << out->redShift) | -+ (outGreen << out->greenShift) | -+ (outBlue << out->blueShift)); -+#if (OUT != 8) -+ if (out->bigEndian != in->bigEndian) { -+ t[i] = SwapOUT(t[i]); -+ } -+#endif -+ } -+} -+ -+ -+/* -+ * rfbInitTrueColourRGBTables sets up three separate lookup tables for the -+ * red, green and blue values. -+ */ -+ -+static void -+rfbInitTrueColourRGBTablesOUT (ScreenPtr pScreen, char **table, rfbPixelFormat *in, -+ rfbPixelFormat *out) -+{ -+ OUT_T *redTable; -+ OUT_T *greenTable; -+ OUT_T *blueTable; -+ -+ if (*table) free(*table); -+ *table = (char *)malloc((in->redMax + in->greenMax + in->blueMax + 3) -+ * sizeof(OUT_T)); -+ redTable = (OUT_T *)*table; -+ greenTable = redTable + in->redMax + 1; -+ blueTable = greenTable + in->greenMax + 1; -+ -+ rfbInitOneRGBTableOUT (redTable, in->redMax, out->redMax, -+ out->redShift, (out->bigEndian != in->bigEndian)); -+ rfbInitOneRGBTableOUT (greenTable, in->greenMax, out->greenMax, -+ out->greenShift, (out->bigEndian != in->bigEndian)); -+ rfbInitOneRGBTableOUT (blueTable, in->blueMax, out->blueMax, -+ out->blueShift, (out->bigEndian != in->bigEndian)); -+} -+ -+static void -+rfbInitOneRGBTableOUT (OUT_T *table, int inMax, int outMax, int outShift, -+ int swap) -+{ -+ int i; -+ int nEntries = inMax + 1; -+ -+ for (i = 0; i < nEntries; i++) { -+ table[i] = ((i * outMax + inMax / 2) / inMax) << outShift; -+#if (OUT != 8) -+ if (swap) { -+ table[i] = SwapOUT(table[i]); -+ } -+#endif -+ } -+} -+ -+#undef OUT_T -+#undef SwapOUT -+#undef rfbInitTrueColourSingleTableOUT -+#undef rfbInitTrueColourRGBTablesOUT -+#undef rfbInitOneRGBTableOUT -diff --git a/hw/dmx/vnc/tabletranstemplate.c b/hw/dmx/vnc/tabletranstemplate.c -new file mode 100644 -index 0000000..87cfcba ---- /dev/null -+++ b/hw/dmx/vnc/tabletranstemplate.c -@@ -0,0 +1,119 @@ -+/* -+ * tabletranstemplate.c - template for translation using lookup tables. -+ * -+ * This file shouldn't be compiled. It is included multiple times by -+ * translate.c, each time with different definitions of the macros IN and OUT. -+ * -+ * For each pair of values IN and OUT, this file defines two functions for -+ * translating a given rectangle of pixel data. One uses a single lookup -+ * table, and the other uses three separate lookup tables for the red, green -+ * and blue values. -+ * -+ * I know this code isn't nice to read because of all the macros, but -+ * efficiency is important here. -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ */ -+ -+/* -+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. -+ * -+ * This is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This software is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this software; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -+ * USA. -+ */ -+ -+#if !defined(IN) || !defined(OUT) -+#error "This file shouldn't be compiled." -+#error "It is included as part of translate.c" -+#endif -+ -+#define IN_T CONCAT2E(CARD,IN) -+#define OUT_T CONCAT2E(CARD,OUT) -+#define rfbTranslateWithSingleTableINtoOUT \ -+ CONCAT4E(rfbTranslateWithSingleTable,IN,to,OUT) -+#define rfbTranslateWithRGBTablesINtoOUT \ -+ CONCAT4E(rfbTranslateWithRGBTables,IN,to,OUT) -+ -+/* -+ * rfbTranslateWithSingleTableINtoOUT translates a rectangle of pixel data -+ * using a single lookup table. -+ */ -+ -+static void -+rfbTranslateWithSingleTableINtoOUT (ScreenPtr pScreen, char *table, rfbPixelFormat *in, -+ rfbPixelFormat *out, -+ unsigned char *iptr, char *optr, -+ int bytesBetweenInputLines, -+ int width, int height, -+ int x, int y) -+{ -+ IN_T *ip = (IN_T *)iptr; -+ OUT_T *op = (OUT_T *)optr; -+ int ipextra = bytesBetweenInputLines / sizeof(IN_T) - width; -+ OUT_T *opLineEnd; -+ OUT_T *t = (OUT_T *)table; -+ -+ while (height > 0) { -+ opLineEnd = op + width; -+ -+ while (op < opLineEnd) { -+ *(op++) = t[*(ip++)]; -+ } -+ -+ ip += ipextra; -+ height--; -+ } -+} -+ -+ -+/* -+ * rfbTranslateWithRGBTablesINtoOUT translates a rectangle of pixel data -+ * using three separate lookup tables for the red, green and blue values. -+ */ -+ -+static void -+rfbTranslateWithRGBTablesINtoOUT (ScreenPtr pScreen, char *table, rfbPixelFormat *in, -+ rfbPixelFormat *out, -+ unsigned char *iptr, char *optr, -+ int bytesBetweenInputLines, -+ int width, int height, -+ int x, int y) -+{ -+ IN_T *ip = (IN_T *)iptr; -+ OUT_T *op = (OUT_T *)optr; -+ int ipextra = bytesBetweenInputLines / sizeof(IN_T) - width; -+ OUT_T *opLineEnd; -+ OUT_T *redTable = (OUT_T *)table; -+ OUT_T *greenTable = redTable + in->redMax + 1; -+ OUT_T *blueTable = greenTable + in->greenMax + 1; -+ -+ while (height > 0) { -+ opLineEnd = op + width; -+ -+ while (op < opLineEnd) { -+ *(op++) = (redTable[(*ip >> in->redShift) & in->redMax] | -+ greenTable[(*ip >> in->greenShift) & in->greenMax] | -+ blueTable[(*ip >> in->blueShift) & in->blueMax]); -+ ip++; -+ } -+ ip += ipextra; -+ height--; -+ } -+} -+ -+#undef IN_T -+#undef OUT_T -+#undef rfbTranslateWithSingleTableINtoOUT -+#undef rfbTranslateWithRGBTablesINtoOUT -diff --git a/hw/dmx/vnc/tight.c b/hw/dmx/vnc/tight.c -new file mode 100644 -index 0000000..3dfd8a1 ---- /dev/null -+++ b/hw/dmx/vnc/tight.c -@@ -0,0 +1,1827 @@ -+/* -+ * tight.c -+ * -+ * Routines to implement Tight Encoding -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ */ -+ -+/* -+ * Copyright (C) 2000, 2001 Const Kaplinsky. All Rights Reserved. -+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. -+ * -+ * This is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This software is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this software; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -+ * USA. -+ */ -+ -+#include -+#include -+#include -+#include -+#include "rfb.h" -+#include -+ -+ -+/* Note: The following constant should not be changed. */ -+#define TIGHT_MIN_TO_COMPRESS 12 -+ -+/* The parameters below may be adjusted. */ -+#define MIN_SPLIT_RECT_SIZE 4096 -+#define MIN_SOLID_SUBRECT_SIZE 2048 -+#define MAX_SPLIT_TILE_SIZE 16 -+ -+/* May be set to TRUE with "-lazytight" Xvnc option. */ -+Bool rfbTightDisableGradient = FALSE; -+ -+/* This variable is set on every rfbSendRectEncodingTight() call. */ -+static Bool usePixelFormat24; -+ -+ -+/* Compression level stuff. The following array contains various -+ encoder parameters for each of 10 compression levels (0..9). -+ Last three parameters correspond to JPEG quality levels (0..9). */ -+ -+typedef struct TIGHT_CONF_s { -+ int maxRectSize, maxRectWidth; -+ int monoMinRectSize, gradientMinRectSize; -+ int idxZlibLevel, monoZlibLevel, rawZlibLevel, gradientZlibLevel; -+ int gradientThreshold, gradientThreshold24; -+ int idxMaxColorsDivisor; -+ int jpegQuality, jpegThreshold, jpegThreshold24; -+} TIGHT_CONF; -+ -+static TIGHT_CONF tightConf[10] = { -+ { 512, 32, 6, 65536, 0, 0, 0, 0, 0, 0, 4, 5, 10000, 23000 }, -+ { 2048, 128, 6, 65536, 1, 1, 1, 0, 0, 0, 8, 10, 8000, 18000 }, -+ { 6144, 256, 8, 65536, 3, 3, 2, 0, 0, 0, 24, 15, 6500, 15000 }, -+ { 10240, 1024, 12, 65536, 5, 5, 3, 0, 0, 0, 32, 25, 5000, 12000 }, -+ { 16384, 2048, 12, 65536, 6, 6, 4, 0, 0, 0, 32, 37, 4000, 10000 }, -+ { 32768, 2048, 12, 4096, 7, 7, 5, 4, 150, 380, 32, 50, 3000, 8000 }, -+ { 65536, 2048, 16, 4096, 7, 7, 6, 4, 170, 420, 48, 60, 2000, 5000 }, -+ { 65536, 2048, 16, 4096, 8, 8, 7, 5, 180, 450, 64, 70, 1000, 2500 }, -+ { 65536, 2048, 32, 8192, 9, 9, 8, 6, 190, 475, 64, 75, 500, 1200 }, -+ { 65536, 2048, 32, 8192, 9, 9, 9, 6, 200, 500, 96, 80, 200, 500 } -+}; -+ -+/* Stuff dealing with palettes. */ -+ -+typedef struct COLOR_LIST_s { -+ struct COLOR_LIST_s *next; -+ int idx; -+ CARD32 rgb; -+} COLOR_LIST; -+ -+typedef struct PALETTE_ENTRY_s { -+ COLOR_LIST *listNode; -+ int numPixels; -+} PALETTE_ENTRY; -+ -+typedef struct PALETTE_s { -+ PALETTE_ENTRY entry[256]; -+ COLOR_LIST *hash[256]; -+ COLOR_LIST list[256]; -+} PALETTE; -+ -+static int paletteNumColors, paletteMaxColors; -+static CARD32 monoBackground, monoForeground; -+static PALETTE palette; -+ -+/* Pointers to dynamically-allocated buffers. */ -+ -+static int tightBeforeBufSize = 0; -+static char *tightBeforeBuf = NULL; -+ -+static int tightAfterBufSize = 0; -+static char *tightAfterBuf = NULL; -+ -+static int *prevRowBuf = NULL; -+ -+ -+/* Prototypes for static functions. */ -+ -+static void FindBestSolidArea (ScreenPtr pScreen, int x, int y, int w, int h, -+ CARD32 colorValue, int *w_ptr, int *h_ptr); -+static void ExtendSolidArea (ScreenPtr pScreen, int x, int y, int w, int h, -+ CARD32 colorValue, -+ int *x_ptr, int *y_ptr, int *w_ptr, int *h_ptr); -+static Bool CheckSolidTile (ScreenPtr pScreen, int x, int y, int w, int h, -+ CARD32 *colorPtr, Bool needSameColor); -+static Bool CheckSolidTile8 (ScreenPtr pScreen, int x, int y, int w, int h, -+ CARD32 *colorPtr, Bool needSameColor); -+static Bool CheckSolidTile16 (ScreenPtr pScreen, int x, int y, int w, int h, -+ CARD32 *colorPtr, Bool needSameColor); -+static Bool CheckSolidTile32 (ScreenPtr pScreen, int x, int y, int w, int h, -+ CARD32 *colorPtr, Bool needSameColor); -+ -+static Bool SendRectSimple (rfbClientPtr cl, int x, int y, int w, int h); -+static Bool SendSubrect (rfbClientPtr cl, int x, int y, int w, int h); -+static Bool SendTightHeader (rfbClientPtr cl, int x, int y, int w, int h); -+ -+static Bool SendSolidRect (rfbClientPtr cl); -+static Bool SendMonoRect (rfbClientPtr cl, int w, int h); -+static Bool SendIndexedRect (rfbClientPtr cl, int w, int h); -+static Bool SendFullColorRect (rfbClientPtr cl, int w, int h); -+static Bool SendGradientRect (rfbClientPtr cl, int w, int h); -+ -+static Bool CompressData(rfbClientPtr cl, int streamId, int dataLen, -+ int zlibLevel, int zlibStrategy); -+static Bool SendCompressedData(rfbClientPtr cl, int compressedLen); -+ -+static void FillPalette8(int count); -+static void FillPalette16(int count); -+static void FillPalette32(int count); -+ -+static void PaletteReset(void); -+static int PaletteInsert(CARD32 rgb, int numPixels, int bpp); -+ -+static void Pack24(ScreenPtr pScreen, char *buf, rfbPixelFormat *fmt, int count); -+ -+static void EncodeIndexedRect16(CARD8 *buf, int count); -+static void EncodeIndexedRect32(CARD8 *buf, int count); -+ -+static void EncodeMonoRect8(CARD8 *buf, int w, int h); -+static void EncodeMonoRect16(CARD8 *buf, int w, int h); -+static void EncodeMonoRect32(CARD8 *buf, int w, int h); -+ -+static void FilterGradient24(ScreenPtr pScreen, char *buf, rfbPixelFormat *fmt, int w, int h); -+static void FilterGradient16(ScreenPtr pScreen, CARD16 *buf, rfbPixelFormat *fmt, int w, int h); -+static void FilterGradient32(ScreenPtr pScreen, CARD32 *buf, rfbPixelFormat *fmt, int w, int h); -+ -+static int DetectSmoothImage(rfbClientPtr cl, rfbPixelFormat *fmt, int w, int h); -+static unsigned long DetectSmoothImage24(rfbClientPtr cl, rfbPixelFormat *fmt, int w, int h); -+static unsigned long DetectSmoothImage16(rfbClientPtr cl, rfbPixelFormat *fmt, int w, int h); -+static unsigned long DetectSmoothImage32(rfbClientPtr cl, rfbPixelFormat *fmt, int w, int h); -+ -+static Bool SendJpegRect(rfbClientPtr cl, int x, int y, int w, int h, -+ int quality); -+static void PrepareRowForJpeg(ScreenPtr pScreen, CARD8 *dst, int x, int y, int count); -+static void PrepareRowForJpeg24(ScreenPtr pScreen, CARD8 *dst, int x, int y, int count); -+static void PrepareRowForJpeg16(ScreenPtr pScreen, CARD8 *dst, int x, int y, int count); -+static void PrepareRowForJpeg32(ScreenPtr pScreen, CARD8 *dst, int x, int y, int count); -+ -+static void JpegInitDestination(j_compress_ptr cinfo); -+static boolean JpegEmptyOutputBuffer(j_compress_ptr cinfo); -+static void JpegTermDestination(j_compress_ptr cinfo); -+static void JpegSetDstManager(j_compress_ptr cinfo); -+ -+ -+/* -+ * Tight encoding implementation. -+ */ -+ -+int -+rfbNumCodedRectsTight(cl, x, y, w, h) -+ rfbClientPtr cl; -+ int x, y, w, h; -+{ -+ int maxRectSize, maxRectWidth; -+ int subrectMaxWidth, subrectMaxHeight; -+ -+ /* No matter how many rectangles we will send if LastRect markers -+ are used to terminate rectangle stream. */ -+ if (cl->enableLastRectEncoding && w * h >= MIN_SPLIT_RECT_SIZE) -+ return 0; -+ -+ maxRectSize = tightConf[cl->tightCompressLevel].maxRectSize; -+ maxRectWidth = tightConf[cl->tightCompressLevel].maxRectWidth; -+ -+ if (w > maxRectWidth || w * h > maxRectSize) { -+ subrectMaxWidth = (w > maxRectWidth) ? maxRectWidth : w; -+ subrectMaxHeight = maxRectSize / subrectMaxWidth; -+ return (((w - 1) / maxRectWidth + 1) * -+ ((h - 1) / subrectMaxHeight + 1)); -+ } else { -+ return 1; -+ } -+} -+ -+Bool -+rfbSendRectEncodingTight(cl, x, y, w, h) -+ rfbClientPtr cl; -+ int x, y, w, h; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ int nMaxRows; -+ CARD32 colorValue; -+ int dx, dy, dw, dh; -+ int x_best, y_best, w_best, h_best; -+ unsigned char *fbptr; -+ -+ if ( cl->format.depth == 24 && cl->format.redMax == 0xFF && -+ cl->format.greenMax == 0xFF && cl->format.blueMax == 0xFF ) { -+ usePixelFormat24 = TRUE; -+ } else { -+ usePixelFormat24 = FALSE; -+ } -+ -+ if (!cl->enableLastRectEncoding || w * h < MIN_SPLIT_RECT_SIZE) -+ return SendRectSimple(cl, x, y, w, h); -+ -+ /* Make sure we can write at least one pixel into tightBeforeBuf. */ -+ -+ if (tightBeforeBufSize < 4) { -+ tightBeforeBufSize = 4; -+ if (tightBeforeBuf == NULL) -+ tightBeforeBuf = (char *)xalloc(tightBeforeBufSize); -+ else -+ tightBeforeBuf = (char *)xrealloc(tightBeforeBuf, -+ tightBeforeBufSize); -+ } -+ -+ /* Calculate maximum number of rows in one non-solid rectangle. */ -+ -+ { -+ int maxRectSize, maxRectWidth, nMaxWidth; -+ -+ maxRectSize = tightConf[cl->tightCompressLevel].maxRectSize; -+ maxRectWidth = tightConf[cl->tightCompressLevel].maxRectWidth; -+ nMaxWidth = (w > maxRectWidth) ? maxRectWidth : w; -+ nMaxRows = maxRectSize / nMaxWidth; -+ } -+ -+ /* Try to find large solid-color areas and send them separately. */ -+ -+ for (dy = y; dy < y + h; dy += MAX_SPLIT_TILE_SIZE) { -+ -+ /* If a rectangle becomes too large, send its upper part now. */ -+ -+ if (dy - y >= nMaxRows) { -+ if (!SendRectSimple(cl, x, y, w, nMaxRows)) -+ return 0; -+ y += nMaxRows; -+ h -= nMaxRows; -+ } -+ -+ dh = (dy + MAX_SPLIT_TILE_SIZE <= y + h) ? -+ MAX_SPLIT_TILE_SIZE : (y + h - dy); -+ -+ for (dx = x; dx < x + w; dx += MAX_SPLIT_TILE_SIZE) { -+ -+ dw = (dx + MAX_SPLIT_TILE_SIZE <= x + w) ? -+ MAX_SPLIT_TILE_SIZE : (x + w - dx); -+ -+ if (CheckSolidTile(cl->pScreen, dx, dy, dw, dh, &colorValue, FALSE)) { -+ -+ /* Get dimensions of solid-color area. */ -+ -+ FindBestSolidArea(cl->pScreen, dx, dy, w - (dx - x), h - (dy - y), -+ colorValue, &w_best, &h_best); -+ -+ /* Make sure a solid rectangle is large enough -+ (or the whole rectangle is of the same color). */ -+ -+ if ( w_best * h_best != w * h && -+ w_best * h_best < MIN_SOLID_SUBRECT_SIZE ) -+ continue; -+ -+ /* Try to extend solid rectangle to maximum size. */ -+ -+ x_best = dx; y_best = dy; -+ ExtendSolidArea(cl->pScreen, x, y, w, h, colorValue, -+ &x_best, &y_best, &w_best, &h_best); -+ -+ /* Send rectangles at top and left to solid-color area. */ -+ -+ if ( y_best != y && -+ !SendRectSimple(cl, x, y, w, y_best-y) ) -+ return FALSE; -+ if ( x_best != x && -+ !rfbSendRectEncodingTight(cl, x, y_best, -+ x_best-x, h_best) ) -+ return FALSE; -+ -+ /* Send solid-color rectangle. */ -+ -+ if (!SendTightHeader(cl, x_best, y_best, w_best, h_best)) -+ return FALSE; -+ -+ fbptr = (pVNC->pfbMemory + -+ (pVNC->paddedWidthInBytes * y_best) + -+ (x_best * (pVNC->bitsPerPixel / 8))); -+ -+ (*cl->translateFn)(cl->pScreen, cl->translateLookupTable, -+ &pVNC->rfbServerFormat, -+ &cl->format, fbptr, tightBeforeBuf, -+ pVNC->paddedWidthInBytes, 1, 1, -+ x_best, y_best); -+ -+ if (!SendSolidRect(cl)) -+ return FALSE; -+ -+ /* Send remaining rectangles (at right and bottom). */ -+ -+ if ( x_best + w_best != x + w && -+ !rfbSendRectEncodingTight(cl, x_best+w_best, y_best, -+ w-(x_best-x)-w_best, h_best) ) -+ return FALSE; -+ if ( y_best + h_best != y + h && -+ !rfbSendRectEncodingTight(cl, x, y_best+h_best, -+ w, h-(y_best-y)-h_best) ) -+ return FALSE; -+ -+ /* Return after all recursive calls are done. */ -+ -+ return TRUE; -+ } -+ -+ } -+ -+ } -+ -+ /* No suitable solid-color rectangles found. */ -+ -+ return SendRectSimple(cl, x, y, w, h); -+} -+ -+static void -+FindBestSolidArea(pScreen, x, y, w, h, colorValue, w_ptr, h_ptr) -+ ScreenPtr pScreen; -+ int x, y, w, h; -+ CARD32 colorValue; -+ int *w_ptr, *h_ptr; -+{ -+ int dx, dy, dw, dh; -+ int w_prev; -+ int w_best = 0, h_best = 0; -+ -+ w_prev = w; -+ -+ for (dy = y; dy < y + h; dy += MAX_SPLIT_TILE_SIZE) { -+ -+ dh = (dy + MAX_SPLIT_TILE_SIZE <= y + h) ? -+ MAX_SPLIT_TILE_SIZE : (y + h - dy); -+ dw = (w_prev > MAX_SPLIT_TILE_SIZE) ? -+ MAX_SPLIT_TILE_SIZE : w_prev; -+ -+ if (!CheckSolidTile(pScreen, x, dy, dw, dh, &colorValue, TRUE)) -+ break; -+ -+ for (dx = x + dw; dx < x + w_prev;) { -+ dw = (dx + MAX_SPLIT_TILE_SIZE <= x + w_prev) ? -+ MAX_SPLIT_TILE_SIZE : (x + w_prev - dx); -+ if (!CheckSolidTile(pScreen, dx, dy, dw, dh, &colorValue, TRUE)) -+ break; -+ dx += dw; -+ } -+ -+ w_prev = dx - x; -+ if (w_prev * (dy + dh - y) > w_best * h_best) { -+ w_best = w_prev; -+ h_best = dy + dh - y; -+ } -+ } -+ -+ *w_ptr = w_best; -+ *h_ptr = h_best; -+} -+ -+static void -+ExtendSolidArea(pScreen, x, y, w, h, colorValue, x_ptr, y_ptr, w_ptr, h_ptr) -+ ScreenPtr pScreen; -+ int x, y, w, h; -+ CARD32 colorValue; -+ int *x_ptr, *y_ptr, *w_ptr, *h_ptr; -+{ -+ int cx, cy; -+ -+ /* Try to extend the area upwards. */ -+ for ( cy = *y_ptr - 1; -+ cy >= y && CheckSolidTile(pScreen, *x_ptr, cy, *w_ptr, 1, &colorValue, TRUE); -+ cy-- ); -+ *h_ptr += *y_ptr - (cy + 1); -+ *y_ptr = cy + 1; -+ -+ /* ... downwards. */ -+ for ( cy = *y_ptr + *h_ptr; -+ cy < y + h && -+ CheckSolidTile(pScreen, *x_ptr, cy, *w_ptr, 1, &colorValue, TRUE); -+ cy++ ); -+ *h_ptr += cy - (*y_ptr + *h_ptr); -+ -+ /* ... to the left. */ -+ for ( cx = *x_ptr - 1; -+ cx >= x && CheckSolidTile(pScreen, cx, *y_ptr, 1, *h_ptr, &colorValue, TRUE); -+ cx-- ); -+ *w_ptr += *x_ptr - (cx + 1); -+ *x_ptr = cx + 1; -+ -+ /* ... to the right. */ -+ for ( cx = *x_ptr + *w_ptr; -+ cx < x + w && -+ CheckSolidTile(pScreen, cx, *y_ptr, 1, *h_ptr, &colorValue, TRUE); -+ cx++ ); -+ *w_ptr += cx - (*x_ptr + *w_ptr); -+} -+ -+/* -+ * Check if a rectangle is all of the same color. If needSameColor is -+ * set to non-zero, then also check that its color equals to the -+ * *colorPtr value. The result is 1 if the test is successfull, and in -+ * that case new color will be stored in *colorPtr. -+ */ -+ -+static Bool -+CheckSolidTile(pScreen, x, y, w, h, colorPtr, needSameColor) -+ ScreenPtr pScreen; -+ int x, y, w, h; -+ CARD32 *colorPtr; -+ Bool needSameColor; -+{ -+ VNCSCREENPTR(pScreen); -+ switch(pVNC->rfbServerFormat.bitsPerPixel) { -+ case 32: -+ return CheckSolidTile32(pScreen, x, y, w, h, colorPtr, needSameColor); -+ case 16: -+ return CheckSolidTile16(pScreen, x, y, w, h, colorPtr, needSameColor); -+ default: -+ return CheckSolidTile8(pScreen, x, y, w, h, colorPtr, needSameColor); -+ } -+} -+ -+#define DEFINE_CHECK_SOLID_FUNCTION(bpp) \ -+ \ -+static Bool \ -+CheckSolidTile##bpp(pScreen, x, y, w, h, colorPtr, needSameColor) \ -+ ScreenPtr pScreen; \ -+ int x, y; \ -+ CARD32 *colorPtr; \ -+ Bool needSameColor; \ -+{ \ -+ VNCSCREENPTR(pScreen); \ -+ CARD##bpp *fbptr; \ -+ CARD##bpp colorValue; \ -+ int dx, dy; \ -+ \ -+ fbptr = (CARD##bpp *) \ -+ &pVNC->pfbMemory[y * pVNC->paddedWidthInBytes + x * (bpp/8)]; \ -+ \ -+ colorValue = *fbptr; \ -+ if (needSameColor && (CARD32)colorValue != *colorPtr) \ -+ return FALSE; \ -+ \ -+ for (dy = 0; dy < h; dy++) { \ -+ for (dx = 0; dx < w; dx++) { \ -+ if (colorValue != fbptr[dx]) \ -+ return FALSE; \ -+ } \ -+ fbptr = (CARD##bpp *)((CARD8 *)fbptr + pVNC->paddedWidthInBytes); \ -+ } \ -+ \ -+ *colorPtr = (CARD32)colorValue; \ -+ return TRUE; \ -+} -+ -+DEFINE_CHECK_SOLID_FUNCTION(8) -+DEFINE_CHECK_SOLID_FUNCTION(16) -+DEFINE_CHECK_SOLID_FUNCTION(32) -+ -+static Bool -+SendRectSimple(cl, x, y, w, h) -+ rfbClientPtr cl; -+ int x, y, w, h; -+{ -+ int maxBeforeSize, maxAfterSize; -+ int maxRectSize, maxRectWidth; -+ int subrectMaxWidth, subrectMaxHeight; -+ int dx, dy; -+ int rw, rh; -+ -+ maxRectSize = tightConf[cl->tightCompressLevel].maxRectSize; -+ maxRectWidth = tightConf[cl->tightCompressLevel].maxRectWidth; -+ -+ maxBeforeSize = maxRectSize * (cl->format.bitsPerPixel / 8); -+ maxAfterSize = maxBeforeSize + (maxBeforeSize + 99) / 100 + 12; -+ -+ if (tightBeforeBufSize < maxBeforeSize) { -+ tightBeforeBufSize = maxBeforeSize; -+ if (tightBeforeBuf == NULL) -+ tightBeforeBuf = (char *)xalloc(tightBeforeBufSize); -+ else -+ tightBeforeBuf = (char *)xrealloc(tightBeforeBuf, -+ tightBeforeBufSize); -+ } -+ -+ if (tightAfterBufSize < maxAfterSize) { -+ tightAfterBufSize = maxAfterSize; -+ if (tightAfterBuf == NULL) -+ tightAfterBuf = (char *)xalloc(tightAfterBufSize); -+ else -+ tightAfterBuf = (char *)xrealloc(tightAfterBuf, -+ tightAfterBufSize); -+ } -+ -+ if (w > maxRectWidth || w * h > maxRectSize) { -+ subrectMaxWidth = (w > maxRectWidth) ? maxRectWidth : w; -+ subrectMaxHeight = maxRectSize / subrectMaxWidth; -+ -+ for (dy = 0; dy < h; dy += subrectMaxHeight) { -+ for (dx = 0; dx < w; dx += maxRectWidth) { -+ rw = (dx + maxRectWidth < w) ? maxRectWidth : w - dx; -+ rh = (dy + subrectMaxHeight < h) ? subrectMaxHeight : h - dy; -+ if (!SendSubrect(cl, x+dx, y+dy, rw, rh)) -+ return FALSE; -+ } -+ } -+ } else { -+ if (!SendSubrect(cl, x, y, w, h)) -+ return FALSE; -+ } -+ -+ return TRUE; -+} -+ -+static Bool -+SendSubrect(cl, x, y, w, h) -+ rfbClientPtr cl; -+ int x, y, w, h; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ unsigned char *fbptr; -+ Bool success = FALSE; -+ -+ /* Send pending data if there is more than 128 bytes. */ -+ if (pVNC->ublen > 128) { -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ } -+ -+ if (!SendTightHeader(cl, x, y, w, h)) -+ return FALSE; -+ -+ fbptr = (pVNC->pfbMemory + (pVNC->paddedWidthInBytes * y) -+ + (x * (pVNC->bitsPerPixel / 8))); -+ -+ (*cl->translateFn)(cl->pScreen, cl->translateLookupTable, &pVNC->rfbServerFormat, -+ &cl->format, fbptr, tightBeforeBuf, -+ pVNC->paddedWidthInBytes, w, h, x, y); -+ -+ paletteMaxColors = w * h / tightConf[cl->tightCompressLevel].idxMaxColorsDivisor; -+ if ( paletteMaxColors < 2 && -+ w * h >= tightConf[cl->tightCompressLevel].monoMinRectSize ) { -+ paletteMaxColors = 2; -+ } -+ switch (cl->format.bitsPerPixel) { -+ case 8: -+ FillPalette8(w * h); -+ break; -+ case 16: -+ FillPalette16(w * h); -+ break; -+ default: -+ FillPalette32(w * h); -+ } -+ -+ switch (paletteNumColors) { -+ case 0: -+ /* Truecolor image */ -+ if (DetectSmoothImage(cl, &cl->format, w, h)) { -+ if (cl->tightQualityLevel != -1) { -+ success = SendJpegRect(cl, x, y, w, h, -+ tightConf[cl->tightQualityLevel].jpegQuality); -+ } else { -+ success = SendGradientRect(cl, w, h); -+ } -+ } else { -+ success = SendFullColorRect(cl, w, h); -+ } -+ break; -+ case 1: -+ /* Solid rectangle */ -+ success = SendSolidRect(cl); -+ break; -+ case 2: -+ /* Two-color rectangle */ -+ success = SendMonoRect(cl, w, h); -+ break; -+ default: -+ /* Up to 256 different colors */ -+ if ( paletteNumColors > 96 && -+ cl->tightQualityLevel != -1 && cl->tightQualityLevel <= 3 && -+ DetectSmoothImage(cl, &cl->format, w, h) ) { -+ success = SendJpegRect(cl, x, y, w, h, -+ tightConf[cl->tightQualityLevel].jpegQuality); -+ } else { -+ success = SendIndexedRect(cl, w, h); -+ } -+ } -+ return success; -+} -+ -+static Bool -+SendTightHeader(cl, x, y, w, h) -+ rfbClientPtr cl; -+ int x, y, w, h; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ rfbFramebufferUpdateRectHeader rect; -+ -+ if (pVNC->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) { -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ } -+ -+ rect.r.x = Swap16IfLE(x); -+ rect.r.y = Swap16IfLE(y); -+ rect.r.w = Swap16IfLE(w); -+ rect.r.h = Swap16IfLE(h); -+ rect.encoding = Swap32IfLE(rfbEncodingTight); -+ -+ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&rect, -+ sz_rfbFramebufferUpdateRectHeader); -+ pVNC->ublen += sz_rfbFramebufferUpdateRectHeader; -+ -+ cl->rfbRectanglesSent[rfbEncodingTight]++; -+ cl->rfbBytesSent[rfbEncodingTight] += sz_rfbFramebufferUpdateRectHeader; -+ -+ return TRUE; -+} -+ -+/* -+ * Subencoding implementations. -+ */ -+ -+static Bool -+SendSolidRect(cl) -+ rfbClientPtr cl; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ int len; -+ -+ if (usePixelFormat24) { -+ Pack24(cl->pScreen, tightBeforeBuf, &cl->format, 1); -+ len = 3; -+ } else -+ len = cl->format.bitsPerPixel / 8; -+ -+ if (pVNC->ublen + 1 + len > UPDATE_BUF_SIZE) { -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ } -+ -+ pVNC->updateBuf[pVNC->ublen++] = (char)(rfbTightFill << 4); -+ memcpy (&pVNC->updateBuf[pVNC->ublen], tightBeforeBuf, len); -+ pVNC->ublen += len; -+ -+ cl->rfbBytesSent[rfbEncodingTight] += len + 1; -+ -+ return TRUE; -+} -+ -+static Bool -+SendMonoRect(cl, w, h) -+ rfbClientPtr cl; -+ int w, h; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ int streamId = 1; -+ int paletteLen, dataLen; -+ -+ if ( (pVNC->ublen + TIGHT_MIN_TO_COMPRESS + 6 + -+ 2 * cl->format.bitsPerPixel / 8) > UPDATE_BUF_SIZE ) { -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ } -+ -+ /* Prepare tight encoding header. */ -+ dataLen = (w + 7) / 8; -+ dataLen *= h; -+ -+ pVNC->updateBuf[pVNC->ublen++] = (streamId | rfbTightExplicitFilter) << 4; -+ pVNC->updateBuf[pVNC->ublen++] = rfbTightFilterPalette; -+ pVNC->updateBuf[pVNC->ublen++] = 1; -+ -+ /* Prepare palette, convert image. */ -+ switch (cl->format.bitsPerPixel) { -+ -+ case 32: -+ EncodeMonoRect32((CARD8 *)tightBeforeBuf, w, h); -+ -+ ((CARD32 *)tightAfterBuf)[0] = monoBackground; -+ ((CARD32 *)tightAfterBuf)[1] = monoForeground; -+ if (usePixelFormat24) { -+ Pack24(cl->pScreen, tightAfterBuf, &cl->format, 2); -+ paletteLen = 6; -+ } else -+ paletteLen = 8; -+ -+ memcpy(&pVNC->updateBuf[pVNC->ublen], tightAfterBuf, paletteLen); -+ pVNC->ublen += paletteLen; -+ cl->rfbBytesSent[rfbEncodingTight] += 3 + paletteLen; -+ break; -+ -+ case 16: -+ EncodeMonoRect16((CARD8 *)tightBeforeBuf, w, h); -+ -+ ((CARD16 *)tightAfterBuf)[0] = (CARD16)monoBackground; -+ ((CARD16 *)tightAfterBuf)[1] = (CARD16)monoForeground; -+ -+ memcpy(&pVNC->updateBuf[pVNC->ublen], tightAfterBuf, 4); -+ pVNC->ublen += 4; -+ cl->rfbBytesSent[rfbEncodingTight] += 7; -+ break; -+ -+ default: -+ EncodeMonoRect8((CARD8 *)tightBeforeBuf, w, h); -+ -+ pVNC->updateBuf[pVNC->ublen++] = (char)monoBackground; -+ pVNC->updateBuf[pVNC->ublen++] = (char)monoForeground; -+ cl->rfbBytesSent[rfbEncodingTight] += 5; -+ } -+ -+ return CompressData(cl, streamId, dataLen, -+ tightConf[cl->tightCompressLevel].monoZlibLevel, -+ Z_DEFAULT_STRATEGY); -+} -+ -+static Bool -+SendIndexedRect(cl, w, h) -+ rfbClientPtr cl; -+ int w, h; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ int streamId = 2; -+ int i, entryLen; -+ -+ if ( (pVNC->ublen + TIGHT_MIN_TO_COMPRESS + 6 + -+ paletteNumColors * cl->format.bitsPerPixel / 8) > UPDATE_BUF_SIZE ) { -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ } -+ -+ /* Prepare tight encoding header. */ -+ pVNC->updateBuf[pVNC->ublen++] = (streamId | rfbTightExplicitFilter) << 4; -+ pVNC->updateBuf[pVNC->ublen++] = rfbTightFilterPalette; -+ pVNC->updateBuf[pVNC->ublen++] = (char)(paletteNumColors - 1); -+ -+ /* Prepare palette, convert image. */ -+ switch (cl->format.bitsPerPixel) { -+ -+ case 32: -+ EncodeIndexedRect32((CARD8 *)tightBeforeBuf, w * h); -+ -+ for (i = 0; i < paletteNumColors; i++) { -+ ((CARD32 *)tightAfterBuf)[i] = -+ palette.entry[i].listNode->rgb; -+ } -+ if (usePixelFormat24) { -+ Pack24(cl->pScreen, tightAfterBuf, &cl->format, paletteNumColors); -+ entryLen = 3; -+ } else -+ entryLen = 4; -+ -+ memcpy(&pVNC->updateBuf[pVNC->ublen], tightAfterBuf, paletteNumColors * entryLen); -+ pVNC->ublen += paletteNumColors * entryLen; -+ cl->rfbBytesSent[rfbEncodingTight] += 3 + paletteNumColors * entryLen; -+ break; -+ -+ case 16: -+ EncodeIndexedRect16((CARD8 *)tightBeforeBuf, w * h); -+ -+ for (i = 0; i < paletteNumColors; i++) { -+ ((CARD16 *)tightAfterBuf)[i] = -+ (CARD16)palette.entry[i].listNode->rgb; -+ } -+ -+ memcpy(&pVNC->updateBuf[pVNC->ublen], tightAfterBuf, paletteNumColors * 2); -+ pVNC->ublen += paletteNumColors * 2; -+ cl->rfbBytesSent[rfbEncodingTight] += 3 + paletteNumColors * 2; -+ break; -+ -+ default: -+ return FALSE; /* Should never happen. */ -+ } -+ -+ return CompressData(cl, streamId, w * h, -+ tightConf[cl->tightCompressLevel].idxZlibLevel, -+ Z_DEFAULT_STRATEGY); -+} -+ -+static Bool -+SendFullColorRect(cl, w, h) -+ rfbClientPtr cl; -+ int w, h; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ int streamId = 0; -+ int len; -+ -+ if (pVNC->ublen + TIGHT_MIN_TO_COMPRESS + 1 > UPDATE_BUF_SIZE) { -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ } -+ -+ pVNC->updateBuf[pVNC->ublen++] = 0x00; /* stream id = 0, no flushing, no filter */ -+ cl->rfbBytesSent[rfbEncodingTight]++; -+ -+ if (usePixelFormat24) { -+ Pack24(cl->pScreen, tightBeforeBuf, &cl->format, w * h); -+ len = 3; -+ } else -+ len = cl->format.bitsPerPixel / 8; -+ -+ return CompressData(cl, streamId, w * h * len, -+ tightConf[cl->tightCompressLevel].rawZlibLevel, -+ Z_DEFAULT_STRATEGY); -+} -+ -+static Bool -+SendGradientRect(cl, w, h) -+ rfbClientPtr cl; -+ int w, h; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ int streamId = 3; -+ int len; -+ -+ if (cl->format.bitsPerPixel == 8) -+ return SendFullColorRect(cl, w, h); -+ -+ if (pVNC->ublen + TIGHT_MIN_TO_COMPRESS + 2 > UPDATE_BUF_SIZE) { -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ } -+ -+ if (prevRowBuf == NULL) -+ prevRowBuf = (int *)xalloc(2048 * 3 * sizeof(int)); -+ -+ pVNC->updateBuf[pVNC->ublen++] = (streamId | rfbTightExplicitFilter) << 4; -+ pVNC->updateBuf[pVNC->ublen++] = rfbTightFilterGradient; -+ cl->rfbBytesSent[rfbEncodingTight] += 2; -+ -+ if (usePixelFormat24) { -+ FilterGradient24(cl->pScreen, tightBeforeBuf, &cl->format, w, h); -+ len = 3; -+ } else if (cl->format.bitsPerPixel == 32) { -+ FilterGradient32(cl->pScreen, (CARD32 *)tightBeforeBuf, &cl->format, w, h); -+ len = 4; -+ } else { -+ FilterGradient16(cl->pScreen, (CARD16 *)tightBeforeBuf, &cl->format, w, h); -+ len = 2; -+ } -+ -+ return CompressData(cl, streamId, w * h * len, -+ tightConf[cl->tightCompressLevel].gradientZlibLevel, -+ Z_FILTERED); -+} -+ -+static Bool -+CompressData(cl, streamId, dataLen, zlibLevel, zlibStrategy) -+ rfbClientPtr cl; -+ int streamId, dataLen, zlibLevel, zlibStrategy; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ z_streamp pz; -+ int err; -+ -+ if (dataLen < TIGHT_MIN_TO_COMPRESS) { -+ memcpy(&pVNC->updateBuf[pVNC->ublen], tightBeforeBuf, dataLen); -+ pVNC->ublen += dataLen; -+ cl->rfbBytesSent[rfbEncodingTight] += dataLen; -+ return TRUE; -+ } -+ -+ pz = &cl->zsStruct[streamId]; -+ -+ /* Initialize compression stream if needed. */ -+ if (!cl->zsActive[streamId]) { -+ pz->zalloc = Z_NULL; -+ pz->zfree = Z_NULL; -+ pz->opaque = Z_NULL; -+ -+ err = deflateInit2 (pz, zlibLevel, Z_DEFLATED, MAX_WBITS, -+ MAX_MEM_LEVEL, zlibStrategy); -+ if (err != Z_OK) -+ return FALSE; -+ -+ cl->zsActive[streamId] = TRUE; -+ cl->zsLevel[streamId] = zlibLevel; -+ } -+ -+ /* Prepare buffer pointers. */ -+ pz->next_in = (Bytef *)tightBeforeBuf; -+ pz->avail_in = dataLen; -+ pz->next_out = (Bytef *)tightAfterBuf; -+ pz->avail_out = tightAfterBufSize; -+ -+ /* Change compression parameters if needed. */ -+ if (zlibLevel != cl->zsLevel[streamId]) { -+ if (deflateParams (pz, zlibLevel, zlibStrategy) != Z_OK) { -+ return FALSE; -+ } -+ cl->zsLevel[streamId] = zlibLevel; -+ } -+ -+ /* Actual compression. */ -+ if ( deflate (pz, Z_SYNC_FLUSH) != Z_OK || -+ pz->avail_in != 0 || pz->avail_out == 0 ) { -+ return FALSE; -+ } -+ -+ return SendCompressedData(cl, tightAfterBufSize - pz->avail_out); -+} -+ -+static Bool SendCompressedData(cl, compressedLen) -+ rfbClientPtr cl; -+ int compressedLen; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ int i, portionLen; -+ -+ pVNC->updateBuf[pVNC->ublen++] = compressedLen & 0x7F; -+ cl->rfbBytesSent[rfbEncodingTight]++; -+ if (compressedLen > 0x7F) { -+ pVNC->updateBuf[pVNC->ublen-1] |= 0x80; -+ pVNC->updateBuf[pVNC->ublen++] = compressedLen >> 7 & 0x7F; -+ cl->rfbBytesSent[rfbEncodingTight]++; -+ if (compressedLen > 0x3FFF) { -+ pVNC->updateBuf[pVNC->ublen-1] |= 0x80; -+ pVNC->updateBuf[pVNC->ublen++] = compressedLen >> 14 & 0xFF; -+ cl->rfbBytesSent[rfbEncodingTight]++; -+ } -+ } -+ -+ portionLen = UPDATE_BUF_SIZE; -+ for (i = 0; i < compressedLen; i += portionLen) { -+ if (i + portionLen > compressedLen) { -+ portionLen = compressedLen - i; -+ } -+ if (pVNC->ublen + portionLen > UPDATE_BUF_SIZE) { -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ } -+ memcpy(&pVNC->updateBuf[pVNC->ublen], &tightAfterBuf[i], portionLen); -+ pVNC->ublen += portionLen; -+ } -+ cl->rfbBytesSent[rfbEncodingTight] += compressedLen; -+ return TRUE; -+} -+ -+/* -+ * Code to determine how many different colors used in rectangle. -+ */ -+ -+static void -+FillPalette8(count) -+ int count; -+{ -+ CARD8 *data = (CARD8 *)tightBeforeBuf; -+ CARD8 c0, c1; -+ int i, n0, n1; -+ -+ paletteNumColors = 0; -+ -+ c0 = data[0]; -+ for (i = 1; i < count && data[i] == c0; i++); -+ if (i == count) { -+ paletteNumColors = 1; -+ return; /* Solid rectangle */ -+ } -+ -+ if (paletteMaxColors < 2) -+ return; -+ -+ n0 = i; -+ c1 = data[i]; -+ n1 = 0; -+ for (i++; i < count; i++) { -+ if (data[i] == c0) { -+ n0++; -+ } else if (data[i] == c1) { -+ n1++; -+ } else -+ break; -+ } -+ if (i == count) { -+ if (n0 > n1) { -+ monoBackground = (CARD32)c0; -+ monoForeground = (CARD32)c1; -+ } else { -+ monoBackground = (CARD32)c1; -+ monoForeground = (CARD32)c0; -+ } -+ paletteNumColors = 2; /* Two colors */ -+ } -+} -+ -+#define DEFINE_FILL_PALETTE_FUNCTION(bpp) \ -+ \ -+static void \ -+FillPalette##bpp(count) \ -+ int count; \ -+{ \ -+ CARD##bpp *data = (CARD##bpp *)tightBeforeBuf; \ -+ CARD##bpp c0, c1, ci = 0; \ -+ int i, n0, n1, ni; \ -+ \ -+ c0 = data[0]; \ -+ for (i = 1; i < count && data[i] == c0; i++); \ -+ if (i >= count) { \ -+ paletteNumColors = 1; /* Solid rectangle */ \ -+ return; \ -+ } \ -+ \ -+ if (paletteMaxColors < 2) { \ -+ paletteNumColors = 0; /* Full-color encoding preferred */ \ -+ return; \ -+ } \ -+ \ -+ n0 = i; \ -+ c1 = data[i]; \ -+ n1 = 0; \ -+ for (i++; i < count; i++) { \ -+ ci = data[i]; \ -+ if (ci == c0) { \ -+ n0++; \ -+ } else if (ci == c1) { \ -+ n1++; \ -+ } else \ -+ break; \ -+ } \ -+ if (i >= count) { \ -+ if (n0 > n1) { \ -+ monoBackground = (CARD32)c0; \ -+ monoForeground = (CARD32)c1; \ -+ } else { \ -+ monoBackground = (CARD32)c1; \ -+ monoForeground = (CARD32)c0; \ -+ } \ -+ paletteNumColors = 2; /* Two colors */ \ -+ return; \ -+ } \ -+ \ -+ PaletteReset(); \ -+ PaletteInsert (c0, (CARD32)n0, bpp); \ -+ PaletteInsert (c1, (CARD32)n1, bpp); \ -+ \ -+ ni = 1; \ -+ for (i++; i < count; i++) { \ -+ if (data[i] == ci) { \ -+ ni++; \ -+ } else { \ -+ if (!PaletteInsert (ci, (CARD32)ni, bpp)) \ -+ return; \ -+ ci = data[i]; \ -+ ni = 1; \ -+ } \ -+ } \ -+ PaletteInsert (ci, (CARD32)ni, bpp); \ -+} -+ -+DEFINE_FILL_PALETTE_FUNCTION(16) -+DEFINE_FILL_PALETTE_FUNCTION(32) -+ -+ -+/* -+ * Functions to operate with palette structures. -+ */ -+ -+#define HASH_FUNC16(rgb) ((int)((((rgb) >> 8) + (rgb)) & 0xFF)) -+#define HASH_FUNC32(rgb) ((int)((((rgb) >> 16) + ((rgb) >> 8)) & 0xFF)) -+ -+static void -+PaletteReset(void) -+{ -+ paletteNumColors = 0; -+ memset(palette.hash, 0, 256 * sizeof(COLOR_LIST *)); -+} -+ -+static int -+PaletteInsert(CARD32 rgb, int numPixels, int bpp) -+{ -+ COLOR_LIST *pnode; -+ COLOR_LIST *prev_pnode = NULL; -+ int hash_key, idx, new_idx, count; -+ -+ hash_key = (bpp == 16) ? HASH_FUNC16(rgb) : HASH_FUNC32(rgb); -+ -+ pnode = palette.hash[hash_key]; -+ -+ while (pnode != NULL) { -+ if (pnode->rgb == rgb) { -+ /* Such palette entry already exists. */ -+ new_idx = idx = pnode->idx; -+ count = palette.entry[idx].numPixels + numPixels; -+ if (new_idx && palette.entry[new_idx-1].numPixels < count) { -+ do { -+ palette.entry[new_idx] = palette.entry[new_idx-1]; -+ palette.entry[new_idx].listNode->idx = new_idx; -+ new_idx--; -+ } -+ while (new_idx && palette.entry[new_idx-1].numPixels < count); -+ palette.entry[new_idx].listNode = pnode; -+ pnode->idx = new_idx; -+ } -+ palette.entry[new_idx].numPixels = count; -+ return paletteNumColors; -+ } -+ prev_pnode = pnode; -+ pnode = pnode->next; -+ } -+ -+ /* Check if palette is full. */ -+ if (paletteNumColors == 256 || paletteNumColors == paletteMaxColors) { -+ paletteNumColors = 0; -+ return 0; -+ } -+ -+ /* Move palette entries with lesser pixel counts. */ -+ for ( idx = paletteNumColors; -+ idx > 0 && palette.entry[idx-1].numPixels < numPixels; -+ idx-- ) { -+ palette.entry[idx] = palette.entry[idx-1]; -+ palette.entry[idx].listNode->idx = idx; -+ } -+ -+ /* Add new palette entry into the freed slot. */ -+ pnode = &palette.list[paletteNumColors]; -+ if (prev_pnode != NULL) { -+ prev_pnode->next = pnode; -+ } else { -+ palette.hash[hash_key] = pnode; -+ } -+ pnode->next = NULL; -+ pnode->idx = idx; -+ pnode->rgb = rgb; -+ palette.entry[idx].listNode = pnode; -+ palette.entry[idx].numPixels = numPixels; -+ -+ return (++paletteNumColors); -+} -+ -+ -+/* -+ * Converting 32-bit color samples into 24-bit colors. -+ * Should be called only when redMax, greenMax and blueMax are 255. -+ * Color components assumed to be byte-aligned. -+ */ -+ -+static void Pack24(pScreen, buf, fmt, count) -+ ScreenPtr pScreen; -+ char *buf; -+ rfbPixelFormat *fmt; -+ int count; -+{ -+ VNCSCREENPTR(pScreen); -+ CARD32 *buf32; -+ CARD32 pix; -+ int r_shift, g_shift, b_shift; -+ -+ buf32 = (CARD32 *)buf; -+ -+ if (!pVNC->rfbServerFormat.bigEndian == !fmt->bigEndian) { -+ r_shift = fmt->redShift; -+ g_shift = fmt->greenShift; -+ b_shift = fmt->blueShift; -+ } else { -+ r_shift = 24 - fmt->redShift; -+ g_shift = 24 - fmt->greenShift; -+ b_shift = 24 - fmt->blueShift; -+ } -+ -+ while (count--) { -+ pix = *buf32++; -+ *buf++ = (char)(pix >> r_shift); -+ *buf++ = (char)(pix >> g_shift); -+ *buf++ = (char)(pix >> b_shift); -+ } -+} -+ -+ -+/* -+ * Converting truecolor samples into palette indices. -+ */ -+ -+#define DEFINE_IDX_ENCODE_FUNCTION(bpp) \ -+ \ -+static void \ -+EncodeIndexedRect##bpp(buf, count) \ -+ CARD8 *buf; \ -+ int count; \ -+{ \ -+ COLOR_LIST *pnode; \ -+ CARD##bpp *src; \ -+ CARD##bpp rgb; \ -+ int rep = 0; \ -+ \ -+ src = (CARD##bpp *) buf; \ -+ \ -+ while (count--) { \ -+ rgb = *src++; \ -+ while (count && *src == rgb) { \ -+ rep++, src++, count--; \ -+ } \ -+ pnode = palette.hash[HASH_FUNC##bpp(rgb)]; \ -+ while (pnode != NULL) { \ -+ if ((CARD##bpp)pnode->rgb == rgb) { \ -+ *buf++ = (CARD8)pnode->idx; \ -+ while (rep) { \ -+ *buf++ = (CARD8)pnode->idx; \ -+ rep--; \ -+ } \ -+ break; \ -+ } \ -+ pnode = pnode->next; \ -+ } \ -+ } \ -+} -+ -+DEFINE_IDX_ENCODE_FUNCTION(16) -+DEFINE_IDX_ENCODE_FUNCTION(32) -+ -+#define DEFINE_MONO_ENCODE_FUNCTION(bpp) \ -+ \ -+static void \ -+EncodeMonoRect##bpp(buf, w, h) \ -+ CARD8 *buf; \ -+ int w, h; \ -+{ \ -+ CARD##bpp *ptr; \ -+ CARD##bpp bg; \ -+ unsigned int value, mask; \ -+ int aligned_width; \ -+ int x, y, bg_bits; \ -+ \ -+ ptr = (CARD##bpp *) buf; \ -+ bg = (CARD##bpp) monoBackground; \ -+ aligned_width = w - w % 8; \ -+ \ -+ for (y = 0; y < h; y++) { \ -+ for (x = 0; x < aligned_width; x += 8) { \ -+ for (bg_bits = 0; bg_bits < 8; bg_bits++) { \ -+ if (*ptr++ != bg) \ -+ break; \ -+ } \ -+ if (bg_bits == 8) { \ -+ *buf++ = 0; \ -+ continue; \ -+ } \ -+ mask = 0x80 >> bg_bits; \ -+ value = mask; \ -+ for (bg_bits++; bg_bits < 8; bg_bits++) { \ -+ mask >>= 1; \ -+ if (*ptr++ != bg) { \ -+ value |= mask; \ -+ } \ -+ } \ -+ *buf++ = (CARD8)value; \ -+ } \ -+ \ -+ mask = 0x80; \ -+ value = 0; \ -+ if (x >= w) \ -+ continue; \ -+ \ -+ for (; x < w; x++) { \ -+ if (*ptr++ != bg) { \ -+ value |= mask; \ -+ } \ -+ mask >>= 1; \ -+ } \ -+ *buf++ = (CARD8)value; \ -+ } \ -+} -+ -+DEFINE_MONO_ENCODE_FUNCTION(8) -+DEFINE_MONO_ENCODE_FUNCTION(16) -+DEFINE_MONO_ENCODE_FUNCTION(32) -+ -+ -+/* -+ * ``Gradient'' filter for 24-bit color samples. -+ * Should be called only when redMax, greenMax and blueMax are 255. -+ * Color components assumed to be byte-aligned. -+ */ -+ -+static void -+FilterGradient24(pScreen, buf, fmt, w, h) -+ ScreenPtr pScreen; -+ char *buf; -+ rfbPixelFormat *fmt; -+ int w, h; -+{ -+ VNCSCREENPTR(pScreen); -+ CARD32 *buf32; -+ CARD32 pix32; -+ int *prevRowPtr; -+ int shiftBits[3]; -+ int pixHere[3], pixUpper[3], pixLeft[3], pixUpperLeft[3]; -+ int prediction; -+ int x, y, c; -+ -+ buf32 = (CARD32 *)buf; -+ memset (prevRowBuf, 0, w * 3 * sizeof(int)); -+ -+ if (!pVNC->rfbServerFormat.bigEndian == !fmt->bigEndian) { -+ shiftBits[0] = fmt->redShift; -+ shiftBits[1] = fmt->greenShift; -+ shiftBits[2] = fmt->blueShift; -+ } else { -+ shiftBits[0] = 24 - fmt->redShift; -+ shiftBits[1] = 24 - fmt->greenShift; -+ shiftBits[2] = 24 - fmt->blueShift; -+ } -+ -+ for (y = 0; y < h; y++) { -+ for (c = 0; c < 3; c++) { -+ pixUpper[c] = 0; -+ pixHere[c] = 0; -+ } -+ prevRowPtr = prevRowBuf; -+ for (x = 0; x < w; x++) { -+ pix32 = *buf32++; -+ for (c = 0; c < 3; c++) { -+ pixUpperLeft[c] = pixUpper[c]; -+ pixLeft[c] = pixHere[c]; -+ pixUpper[c] = *prevRowPtr; -+ pixHere[c] = (int)(pix32 >> shiftBits[c] & 0xFF); -+ *prevRowPtr++ = pixHere[c]; -+ -+ prediction = pixLeft[c] + pixUpper[c] - pixUpperLeft[c]; -+ if (prediction < 0) { -+ prediction = 0; -+ } else if (prediction > 0xFF) { -+ prediction = 0xFF; -+ } -+ *buf++ = (char)(pixHere[c] - prediction); -+ } -+ } -+ } -+} -+ -+ -+/* -+ * ``Gradient'' filter for other color depths. -+ */ -+ -+#define DEFINE_GRADIENT_FILTER_FUNCTION(bpp) \ -+ \ -+static void \ -+FilterGradient##bpp(pScreen, buf, fmt, w, h) \ -+ ScreenPtr pScreen; \ -+ CARD##bpp *buf; \ -+ rfbPixelFormat *fmt; \ -+ int w, h; \ -+{ \ -+ VNCSCREENPTR(pScreen); \ -+ CARD##bpp pix, diff; \ -+ Bool endianMismatch; \ -+ int *prevRowPtr; \ -+ int maxColor[3], shiftBits[3]; \ -+ int pixHere[3], pixUpper[3], pixLeft[3], pixUpperLeft[3]; \ -+ int prediction; \ -+ int x, y, c; \ -+ \ -+ memset (prevRowBuf, 0, w * 3 * sizeof(int)); \ -+ \ -+ endianMismatch = (!pVNC->rfbServerFormat.bigEndian != !fmt->bigEndian); \ -+ \ -+ maxColor[0] = fmt->redMax; \ -+ maxColor[1] = fmt->greenMax; \ -+ maxColor[2] = fmt->blueMax; \ -+ shiftBits[0] = fmt->redShift; \ -+ shiftBits[1] = fmt->greenShift; \ -+ shiftBits[2] = fmt->blueShift; \ -+ \ -+ for (y = 0; y < h; y++) { \ -+ for (c = 0; c < 3; c++) { \ -+ pixUpper[c] = 0; \ -+ pixHere[c] = 0; \ -+ } \ -+ prevRowPtr = prevRowBuf; \ -+ for (x = 0; x < w; x++) { \ -+ pix = *buf; \ -+ if (endianMismatch) { \ -+ pix = Swap##bpp(pix); \ -+ } \ -+ diff = 0; \ -+ for (c = 0; c < 3; c++) { \ -+ pixUpperLeft[c] = pixUpper[c]; \ -+ pixLeft[c] = pixHere[c]; \ -+ pixUpper[c] = *prevRowPtr; \ -+ pixHere[c] = (int)(pix >> shiftBits[c] & maxColor[c]); \ -+ *prevRowPtr++ = pixHere[c]; \ -+ \ -+ prediction = pixLeft[c] + pixUpper[c] - pixUpperLeft[c]; \ -+ if (prediction < 0) { \ -+ prediction = 0; \ -+ } else if (prediction > maxColor[c]) { \ -+ prediction = maxColor[c]; \ -+ } \ -+ diff |= ((pixHere[c] - prediction) & maxColor[c]) \ -+ << shiftBits[c]; \ -+ } \ -+ if (endianMismatch) { \ -+ diff = Swap##bpp(diff); \ -+ } \ -+ *buf++ = diff; \ -+ } \ -+ } \ -+} -+ -+DEFINE_GRADIENT_FILTER_FUNCTION(16) -+DEFINE_GRADIENT_FILTER_FUNCTION(32) -+ -+ -+/* -+ * Code to guess if given rectangle is suitable for smooth image -+ * compression (by applying "gradient" filter or JPEG coder). -+ */ -+ -+#define JPEG_MIN_RECT_SIZE 4096 -+ -+#define DETECT_SUBROW_WIDTH 7 -+#define DETECT_MIN_WIDTH 8 -+#define DETECT_MIN_HEIGHT 8 -+ -+static int -+DetectSmoothImage (cl, fmt, w, h) -+ rfbClientPtr cl; -+ rfbPixelFormat *fmt; -+ int w, h; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ unsigned long avgError; -+ -+ if ( pVNC->rfbServerFormat.bitsPerPixel == 8 || fmt->bitsPerPixel == 8 || -+ w < DETECT_MIN_WIDTH || h < DETECT_MIN_HEIGHT ) { -+ return 0; -+ } -+ -+ if (cl->tightQualityLevel != -1) { -+ if (w * h < JPEG_MIN_RECT_SIZE) { -+ return 0; -+ } -+ } else { -+ if ( rfbTightDisableGradient || -+ w * h < tightConf[cl->tightCompressLevel].gradientMinRectSize ) { -+ return 0; -+ } -+ } -+ -+ if (fmt->bitsPerPixel == 32) { -+ if (usePixelFormat24) { -+ avgError = DetectSmoothImage24(cl, fmt, w, h); -+ if (cl->tightQualityLevel != -1) { -+ return (avgError < tightConf[cl->tightQualityLevel].jpegThreshold24); -+ } -+ return (avgError < tightConf[cl->tightCompressLevel].gradientThreshold24); -+ } else { -+ avgError = DetectSmoothImage32(cl, fmt, w, h); -+ } -+ } else { -+ avgError = DetectSmoothImage16(cl, fmt, w, h); -+ } -+ if (cl->tightQualityLevel != -1) { -+ return (avgError < tightConf[cl->tightQualityLevel].jpegThreshold); -+ } -+ return (avgError < tightConf[cl->tightCompressLevel].gradientThreshold); -+} -+ -+static unsigned long -+DetectSmoothImage24 (cl, fmt, w, h) -+ rfbClientPtr cl; -+ rfbPixelFormat *fmt; -+ int w, h; -+{ -+ int off; -+ int x, y, d, dx, c; -+ int diffStat[256]; -+ int pixelCount = 0; -+ int pix, left[3]; -+ unsigned long avgError; -+ -+ /* If client is big-endian, color samples begin from the second -+ byte (offset 1) of a 32-bit pixel value. */ -+ off = (fmt->bigEndian != 0); -+ -+ memset(diffStat, 0, 256*sizeof(int)); -+ -+ y = 0, x = 0; -+ while (y < h && x < w) { -+ for (d = 0; d < h - y && d < w - x - DETECT_SUBROW_WIDTH; d++) { -+ for (c = 0; c < 3; c++) { -+ left[c] = (int)tightBeforeBuf[((y+d)*w+x+d)*4+off+c] & 0xFF; -+ } -+ for (dx = 1; dx <= DETECT_SUBROW_WIDTH; dx++) { -+ for (c = 0; c < 3; c++) { -+ pix = (int)tightBeforeBuf[((y+d)*w+x+d+dx)*4+off+c] & 0xFF; -+ diffStat[abs(pix - left[c])]++; -+ left[c] = pix; -+ } -+ pixelCount++; -+ } -+ } -+ if (w > h) { -+ x += h; -+ y = 0; -+ } else { -+ x = 0; -+ y += w; -+ } -+ } -+ -+ if (diffStat[0] * 33 / pixelCount >= 95) -+ return 0; -+ -+ avgError = 0; -+ for (c = 1; c < 8; c++) { -+ avgError += (unsigned long)diffStat[c] * (unsigned long)(c * c); -+ if (diffStat[c] == 0 || diffStat[c] > diffStat[c-1] * 2) -+ return 0; -+ } -+ for (; c < 256; c++) { -+ avgError += (unsigned long)diffStat[c] * (unsigned long)(c * c); -+ } -+ avgError /= (pixelCount * 3 - diffStat[0]); -+ -+ return avgError; -+} -+ -+#define DEFINE_DETECT_FUNCTION(bpp) \ -+ \ -+static unsigned long \ -+DetectSmoothImage##bpp (cl, fmt, w, h) \ -+ rfbClientPtr cl; \ -+ rfbPixelFormat *fmt; \ -+ int w, h; \ -+{ \ -+ VNCSCREENPTR(cl->pScreen); \ -+ Bool endianMismatch; \ -+ CARD##bpp pix; \ -+ int maxColor[3], shiftBits[3]; \ -+ int x, y, d, dx, c; \ -+ int diffStat[256]; \ -+ int pixelCount = 0; \ -+ int sample, sum, left[3]; \ -+ unsigned long avgError; \ -+ \ -+ endianMismatch = (!pVNC->rfbServerFormat.bigEndian != !fmt->bigEndian); \ -+ \ -+ maxColor[0] = fmt->redMax; \ -+ maxColor[1] = fmt->greenMax; \ -+ maxColor[2] = fmt->blueMax; \ -+ shiftBits[0] = fmt->redShift; \ -+ shiftBits[1] = fmt->greenShift; \ -+ shiftBits[2] = fmt->blueShift; \ -+ \ -+ memset(diffStat, 0, 256*sizeof(int)); \ -+ \ -+ y = 0, x = 0; \ -+ while (y < h && x < w) { \ -+ for (d = 0; d < h - y && d < w - x - DETECT_SUBROW_WIDTH; d++) { \ -+ pix = ((CARD##bpp *)tightBeforeBuf)[(y+d)*w+x+d]; \ -+ if (endianMismatch) { \ -+ pix = Swap##bpp(pix); \ -+ } \ -+ for (c = 0; c < 3; c++) { \ -+ left[c] = (int)(pix >> shiftBits[c] & maxColor[c]); \ -+ } \ -+ for (dx = 1; dx <= DETECT_SUBROW_WIDTH; dx++) { \ -+ pix = ((CARD##bpp *)tightBeforeBuf)[(y+d)*w+x+d+dx]; \ -+ if (endianMismatch) { \ -+ pix = Swap##bpp(pix); \ -+ } \ -+ sum = 0; \ -+ for (c = 0; c < 3; c++) { \ -+ sample = (int)(pix >> shiftBits[c] & maxColor[c]); \ -+ sum += abs(sample - left[c]); \ -+ left[c] = sample; \ -+ } \ -+ if (sum > 255) \ -+ sum = 255; \ -+ diffStat[sum]++; \ -+ pixelCount++; \ -+ } \ -+ } \ -+ if (w > h) { \ -+ x += h; \ -+ y = 0; \ -+ } else { \ -+ x = 0; \ -+ y += w; \ -+ } \ -+ } \ -+ \ -+ if ((diffStat[0] + diffStat[1]) * 100 / pixelCount >= 90) \ -+ return 0; \ -+ \ -+ avgError = 0; \ -+ for (c = 1; c < 8; c++) { \ -+ avgError += (unsigned long)diffStat[c] * (unsigned long)(c * c); \ -+ if (diffStat[c] == 0 || diffStat[c] > diffStat[c-1] * 2) \ -+ return 0; \ -+ } \ -+ for (; c < 256; c++) { \ -+ avgError += (unsigned long)diffStat[c] * (unsigned long)(c * c); \ -+ } \ -+ avgError /= (pixelCount - diffStat[0]); \ -+ \ -+ return avgError; \ -+} -+ -+DEFINE_DETECT_FUNCTION(16) -+DEFINE_DETECT_FUNCTION(32) -+ -+ -+/* -+ * JPEG compression stuff. -+ */ -+ -+static struct jpeg_destination_mgr jpegDstManager; -+static Bool jpegError; -+static int jpegDstDataLen; -+ -+static Bool -+SendJpegRect(cl, x, y, w, h, quality) -+ rfbClientPtr cl; -+ int x, y, w, h; -+ int quality; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ struct jpeg_compress_struct cinfo; -+ struct jpeg_error_mgr jerr; -+ CARD8 *srcBuf; -+ JSAMPROW rowPointer[1]; -+ int dy; -+ -+ if (pVNC->rfbServerFormat.bitsPerPixel == 8) -+ return SendFullColorRect(cl, w, h); -+ -+ srcBuf = (CARD8 *)xalloc(w * 3); -+ if (srcBuf == NULL) { -+ return SendFullColorRect(cl, w, h); -+ } -+ rowPointer[0] = srcBuf; -+ -+ cinfo.err = jpeg_std_error(&jerr); -+ jpeg_create_compress(&cinfo); -+ -+ cinfo.image_width = w; -+ cinfo.image_height = h; -+ cinfo.input_components = 3; -+ cinfo.in_color_space = JCS_RGB; -+ -+ jpeg_set_defaults(&cinfo); -+ jpeg_set_quality(&cinfo, quality, TRUE); -+ -+ JpegSetDstManager (&cinfo); -+ -+ jpeg_start_compress(&cinfo, TRUE); -+ -+ for (dy = 0; dy < h; dy++) { -+ PrepareRowForJpeg(cl->pScreen, srcBuf, x, y + dy, w); -+ jpeg_write_scanlines(&cinfo, rowPointer, 1); -+ if (jpegError) -+ break; -+ } -+ -+ if (!jpegError) -+ jpeg_finish_compress(&cinfo); -+ -+ jpeg_destroy_compress(&cinfo); -+ xfree((char *)srcBuf); -+ -+ if (jpegError) -+ return SendFullColorRect(cl, w, h); -+ -+ if (pVNC->ublen + TIGHT_MIN_TO_COMPRESS + 1 > UPDATE_BUF_SIZE) { -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ } -+ -+ pVNC->updateBuf[pVNC->ublen++] = (char)(rfbTightJpeg << 4); -+ cl->rfbBytesSent[rfbEncodingTight]++; -+ -+ return SendCompressedData(cl, jpegDstDataLen); -+} -+ -+static void -+PrepareRowForJpeg(pScreen, dst, x, y, count) -+ ScreenPtr pScreen; -+ CARD8 *dst; -+ int x, y, count; -+{ -+ VNCSCREENPTR(pScreen); -+ if (pVNC->rfbServerFormat.bitsPerPixel == 32) { -+ if ( pVNC->rfbServerFormat.redMax == 0xFF && -+ pVNC->rfbServerFormat.greenMax == 0xFF && -+ pVNC->rfbServerFormat.blueMax == 0xFF ) { -+ PrepareRowForJpeg24(pScreen, dst, x, y, count); -+ } else { -+ PrepareRowForJpeg32(pScreen, dst, x, y, count); -+ } -+ } else { -+ /* 16 bpp assumed. */ -+ PrepareRowForJpeg16(pScreen, dst, x, y, count); -+ } -+} -+ -+static void -+PrepareRowForJpeg24(pScreen, dst, x, y, count) -+ ScreenPtr pScreen; -+ CARD8 *dst; -+ int x, y, count; -+{ -+ VNCSCREENPTR(pScreen); -+ CARD32 *fbptr; -+ CARD32 pix; -+ -+ fbptr = (CARD32 *) -+ &pVNC->pfbMemory[y * pVNC->paddedWidthInBytes + x * 4]; -+ -+ while (count--) { -+ pix = *fbptr++; -+ *dst++ = (CARD8)(pix >> pVNC->rfbServerFormat.redShift); -+ *dst++ = (CARD8)(pix >> pVNC->rfbServerFormat.greenShift); -+ *dst++ = (CARD8)(pix >> pVNC->rfbServerFormat.blueShift); -+ } -+} -+ -+#define DEFINE_JPEG_GET_ROW_FUNCTION(bpp) \ -+ \ -+static void \ -+PrepareRowForJpeg##bpp(pScreen, dst, x, y, count) \ -+ ScreenPtr pScreen; \ -+ CARD8 *dst; \ -+ int x, y, count; \ -+{ \ -+ VNCSCREENPTR(pScreen); \ -+ CARD##bpp *fbptr; \ -+ CARD##bpp pix; \ -+ int inRed, inGreen, inBlue; \ -+ \ -+ fbptr = (CARD##bpp *) \ -+ &pVNC->pfbMemory[y * pVNC->paddedWidthInBytes + \ -+ x * (bpp / 8)]; \ -+ \ -+ while (count--) { \ -+ pix = *fbptr++; \ -+ \ -+ inRed = (int) \ -+ (pix >> pVNC->rfbServerFormat.redShift & pVNC->rfbServerFormat.redMax); \ -+ inGreen = (int) \ -+ (pix >> pVNC->rfbServerFormat.greenShift & pVNC->rfbServerFormat.greenMax); \ -+ inBlue = (int) \ -+ (pix >> pVNC->rfbServerFormat.blueShift & pVNC->rfbServerFormat.blueMax); \ -+ \ -+ *dst++ = (CARD8)((inRed * 255 + pVNC->rfbServerFormat.redMax / 2) / \ -+ pVNC->rfbServerFormat.redMax); \ -+ *dst++ = (CARD8)((inGreen * 255 + pVNC->rfbServerFormat.greenMax / 2) / \ -+ pVNC->rfbServerFormat.greenMax); \ -+ *dst++ = (CARD8)((inBlue * 255 + pVNC->rfbServerFormat.blueMax / 2) / \ -+ pVNC->rfbServerFormat.blueMax); \ -+ } \ -+} -+ -+DEFINE_JPEG_GET_ROW_FUNCTION(16) -+DEFINE_JPEG_GET_ROW_FUNCTION(32) -+ -+/* -+ * Destination manager implementation for JPEG library. -+ */ -+ -+static void -+JpegInitDestination(j_compress_ptr cinfo) -+{ -+ jpegError = FALSE; -+ jpegDstManager.next_output_byte = (JOCTET *)tightAfterBuf; -+ jpegDstManager.free_in_buffer = (size_t)tightAfterBufSize; -+} -+ -+static boolean -+JpegEmptyOutputBuffer(j_compress_ptr cinfo) -+{ -+ jpegError = TRUE; -+ jpegDstManager.next_output_byte = (JOCTET *)tightAfterBuf; -+ jpegDstManager.free_in_buffer = (size_t)tightAfterBufSize; -+ -+ return TRUE; -+} -+ -+static void -+JpegTermDestination(j_compress_ptr cinfo) -+{ -+ jpegDstDataLen = tightAfterBufSize - jpegDstManager.free_in_buffer; -+} -+ -+static void -+JpegSetDstManager(j_compress_ptr cinfo) -+{ -+ jpegDstManager.init_destination = JpegInitDestination; -+ jpegDstManager.empty_output_buffer = JpegEmptyOutputBuffer; -+ jpegDstManager.term_destination = JpegTermDestination; -+ cinfo->dest = &jpegDstManager; -+} -+ -diff --git a/hw/dmx/vnc/translate.c b/hw/dmx/vnc/translate.c -new file mode 100644 -index 0000000..eb9bcb0 ---- /dev/null -+++ b/hw/dmx/vnc/translate.c -@@ -0,0 +1,496 @@ -+/* -+ * translate.c - translate between different pixel formats -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ */ -+ -+/* -+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. -+ * -+ * This is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This software is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this software; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -+ * USA. -+ */ -+ -+#include -+#include "rfb.h" -+#if XFREE86VNC -+#include -+#endif -+ -+static void PrintPixelFormat(rfbPixelFormat *pf); -+static Bool rfbSetClientColourMapBGR233(); -+ -+Bool rfbEconomicTranslate = FALSE; -+ -+/* -+ * Some standard pixel formats. -+ */ -+ -+static const rfbPixelFormat BGR233Format = { -+ 8, 8, 0, 1, 7, 7, 3, 0, 3, 6 -+}; -+ -+ -+/* -+ * Macro to compare pixel formats. -+ */ -+ -+#define PF_EQ(x,y) \ -+ ((x.bitsPerPixel == y.bitsPerPixel) && \ -+ (x.depth == y.depth) && \ -+ ((x.bigEndian == y.bigEndian) || (x.bitsPerPixel == 8)) && \ -+ (x.trueColour == y.trueColour) && \ -+ (!x.trueColour || ((x.redMax == y.redMax) && \ -+ (x.greenMax == y.greenMax) && \ -+ (x.blueMax == y.blueMax) && \ -+ (x.redShift == y.redShift) && \ -+ (x.greenShift == y.greenShift) && \ -+ (x.blueShift == y.blueShift)))) -+ -+#define CONCAT2(a,b) a##b -+#define CONCAT2E(a,b) CONCAT2(a,b) -+#define CONCAT4(a,b,c,d) a##b##c##d -+#define CONCAT4E(a,b,c,d) CONCAT4(a,b,c,d) -+ -+#define OUT 8 -+#include "tableinittctemplate.c" -+#include "tableinitcmtemplate.c" -+#define IN 8 -+#include "tabletranstemplate.c" -+#undef IN -+#define IN 16 -+#include "tabletranstemplate.c" -+#undef IN -+#define IN 32 -+#include "tabletranstemplate.c" -+#undef IN -+#undef OUT -+ -+#define OUT 16 -+#include "tableinittctemplate.c" -+#include "tableinitcmtemplate.c" -+#define IN 8 -+#include "tabletranstemplate.c" -+#undef IN -+#define IN 16 -+#include "tabletranstemplate.c" -+#undef IN -+#define IN 32 -+#include "tabletranstemplate.c" -+#undef IN -+#undef OUT -+ -+#define OUT 32 -+#include "tableinittctemplate.c" -+#include "tableinitcmtemplate.c" -+#define IN 8 -+#include "tabletranstemplate.c" -+#undef IN -+#define IN 16 -+#include "tabletranstemplate.c" -+#undef IN -+#define IN 32 -+#include "tabletranstemplate.c" -+#undef IN -+#undef OUT -+ -+typedef void (*rfbInitTableFnType)(ScreenPtr pScreen, char **table, rfbPixelFormat *in, -+ rfbPixelFormat *out); -+ -+rfbInitTableFnType rfbInitTrueColourSingleTableFns[3] = { -+ rfbInitTrueColourSingleTable8, -+ rfbInitTrueColourSingleTable16, -+ rfbInitTrueColourSingleTable32 -+}; -+ -+rfbInitTableFnType rfbInitColourMapSingleTableFns[3] = { -+ rfbInitColourMapSingleTable8, -+ rfbInitColourMapSingleTable16, -+ rfbInitColourMapSingleTable32 -+}; -+ -+rfbInitTableFnType rfbInitTrueColourRGBTablesFns[3] = { -+ rfbInitTrueColourRGBTables8, -+ rfbInitTrueColourRGBTables16, -+ rfbInitTrueColourRGBTables32 -+}; -+ -+rfbTranslateFnType rfbTranslateWithSingleTableFns[3][3] = { -+ { rfbTranslateWithSingleTable8to8, -+ rfbTranslateWithSingleTable8to16, -+ rfbTranslateWithSingleTable8to32 }, -+ { rfbTranslateWithSingleTable16to8, -+ rfbTranslateWithSingleTable16to16, -+ rfbTranslateWithSingleTable16to32 }, -+ { rfbTranslateWithSingleTable32to8, -+ rfbTranslateWithSingleTable32to16, -+ rfbTranslateWithSingleTable32to32 } -+}; -+ -+rfbTranslateFnType rfbTranslateWithRGBTablesFns[3][3] = { -+ { rfbTranslateWithRGBTables8to8, -+ rfbTranslateWithRGBTables8to16, -+ rfbTranslateWithRGBTables8to32 }, -+ { rfbTranslateWithRGBTables16to8, -+ rfbTranslateWithRGBTables16to16, -+ rfbTranslateWithRGBTables16to32 }, -+ { rfbTranslateWithRGBTables32to8, -+ rfbTranslateWithRGBTables32to16, -+ rfbTranslateWithRGBTables32to32 } -+}; -+ -+ -+ -+/* -+ * rfbTranslateNone is used when no translation is required. -+ */ -+ -+void -+rfbTranslateNone(ScreenPtr pScreen, char *table, rfbPixelFormat *in, rfbPixelFormat *out, -+ unsigned char *iptr, char *optr, int bytesBetweenInputLines, -+ int width, int height, int x, int y) -+{ -+ VNCSCREENPTR(pScreen); -+ int bytesPerOutputLine = width * (out->bitsPerPixel / 8); -+ -+ if (pVNC->useGetImage) { -+ DrawablePtr pDraw = (DrawablePtr)WindowTable[pScreen->myNum]; -+ -+ /* catch all for other TranslateNone cases - hextile, corre, rre, etc.*/ -+ (*pScreen->GetImage)(pDraw, x, y, width, height, ZPixmap, ~0, optr); -+ } else { -+ while (height > 0) { -+ memcpy(optr, iptr, bytesPerOutputLine); -+ iptr += bytesBetweenInputLines; -+ optr += bytesPerOutputLine; -+ height--; -+ } -+ } -+} -+ -+ -+/* -+ * rfbSetTranslateFunction sets the translation function. -+ */ -+ -+Bool -+rfbSetTranslateFunction(cl) -+ rfbClientPtr cl; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ rfbLog("Pixel format for client %s:\n",cl->host); -+ PrintPixelFormat(&cl->format); -+ -+ /* -+ * Check that bits per pixel values are valid -+ */ -+ -+ if ((pVNC->rfbServerFormat.bitsPerPixel != 8) && -+ (pVNC->rfbServerFormat.bitsPerPixel != 16) && -+ (pVNC->rfbServerFormat.bitsPerPixel != 32)) -+ { -+ rfbLog("%s: server bits per pixel not 8, 16 or 32\n", -+ "rfbSetTranslateFunction"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return FALSE; -+ } -+ -+ if ((cl->format.bitsPerPixel != 8) && -+ (cl->format.bitsPerPixel != 16) && -+ (cl->format.bitsPerPixel != 32)) -+ { -+ rfbLog("%s: client bits per pixel not 8, 16 or 32\n", -+ "rfbSetTranslateFunction"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return FALSE; -+ } -+ -+ if (!pVNC->rfbServerFormat.trueColour && -+ (pVNC->rfbServerFormat.bitsPerPixel != 8) && -+#if XFREE86VNC -+ (miInstalledMaps[cl->pScreen->myNum]->class == PseudoColor)) { -+#else -+ (pVNC->rfbInstalledColormap->class == PseudoColor)) { -+#endif -+ rfbLog("rfbSetTranslateFunction: server has colour map " -+ "but %d-bit - can only cope with 8-bit colour maps\n", -+ pVNC->rfbServerFormat.bitsPerPixel); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return FALSE; -+ } -+ -+ if (!cl->format.trueColour && -+ (cl->format.bitsPerPixel != 8) && -+#if XFREE86VNC -+ (miInstalledMaps[cl->pScreen->myNum]->class == PseudoColor)) { -+#else -+ (pVNC->rfbInstalledColormap->class == PseudoColor) ) { -+#endif -+ rfbLog("rfbSetTranslateFunction: client has colour map " -+ "but %d-bit - can only cope with 8-bit colour maps\n", -+ cl->format.bitsPerPixel); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return FALSE; -+ } -+ -+ /* -+ * bpp is valid, now work out how to translate -+ */ -+ -+ if (!cl->format.trueColour) { -+ -+ /* ? -> colour map */ -+ -+ if (!pVNC->rfbServerFormat.trueColour) { -+ -+ /* colour map -> colour map */ -+ -+#if XFREE86VNC -+ if (miInstalledMaps[cl->pScreen->myNum]->class == DirectColor) { -+#else -+ if (pVNC->rfbInstalledColormap->class == DirectColor) { -+#endif -+ rfbLog("rfbSetTranslateFunction: client is %d-bit DirectColor," -+ " client has colour map\n",cl->format.bitsPerPixel); -+ -+ cl->translateFn = rfbTranslateWithRGBTablesFns -+ [pVNC->rfbServerFormat.bitsPerPixel / 16] -+ [cl->format.bitsPerPixel / 16]; -+ -+ (*rfbInitTrueColourRGBTablesFns [cl->format.bitsPerPixel / 16]) -+ (cl->pScreen, &cl->translateLookupTable, -+ &pVNC->rfbServerFormat, &cl->format); -+ -+ return rfbSetClientColourMap(cl, 0, 0); -+ -+ /* PseudoColor colormap */ -+ -+ } else { -+ rfbLog("rfbSetTranslateFunction: both 8-bit colour map: " -+ "no translation needed\n"); -+ cl->translateFn = rfbTranslateNone; -+ return rfbSetClientColourMap(cl, 0, 0); -+ } -+ } -+ -+ /* -+ * truecolour -> colour map -+ * -+ * Set client's colour map to BGR233, then effectively it's -+ * truecolour as well -+ */ -+ -+ if (!rfbSetClientColourMapBGR233(cl)) -+ return FALSE; -+ -+ cl->format = BGR233Format; -+ } -+ -+ /* ? -> truecolour */ -+ -+ if (!pVNC->rfbServerFormat.trueColour) { -+ -+ /* colour map -> truecolour */ -+ -+ rfbLog("rfbSetTranslateFunction: client is %d-bit trueColour," -+ " server has colour map\n",cl->format.bitsPerPixel); -+ -+ cl->translateFn = rfbTranslateWithSingleTableFns -+ [pVNC->rfbServerFormat.bitsPerPixel / 16] -+ [cl->format.bitsPerPixel / 16]; -+ -+ return rfbSetClientColourMap(cl, 0, 0); -+ } -+ -+ /* truecolour -> truecolour */ -+ -+ if (PF_EQ(cl->format,pVNC->rfbServerFormat)) { -+ -+ /* client & server the same */ -+ -+ rfbLog(" no translation needed\n"); -+ cl->translateFn = rfbTranslateNone; -+ return TRUE; -+ } -+ -+ if ((pVNC->rfbServerFormat.bitsPerPixel < 16) || -+ (!rfbEconomicTranslate && (pVNC->rfbServerFormat.bitsPerPixel == 16))) { -+ -+ /* we can use a single lookup table for <= 16 bpp */ -+ -+ cl->translateFn = rfbTranslateWithSingleTableFns -+ [pVNC->rfbServerFormat.bitsPerPixel / 16] -+ [cl->format.bitsPerPixel / 16]; -+ -+ (*rfbInitTrueColourSingleTableFns -+ [cl->format.bitsPerPixel / 16]) (cl->pScreen, -+ &cl->translateLookupTable, -+ &pVNC->rfbServerFormat, &cl->format); -+ -+ } else { -+ -+ /* otherwise we use three separate tables for red, green and blue */ -+ -+ cl->translateFn = rfbTranslateWithRGBTablesFns -+ [pVNC->rfbServerFormat.bitsPerPixel / 16] -+ [cl->format.bitsPerPixel / 16]; -+ -+ (*rfbInitTrueColourRGBTablesFns -+ [cl->format.bitsPerPixel / 16]) (cl->pScreen, -+ &cl->translateLookupTable, -+ &pVNC->rfbServerFormat, &cl->format); -+ } -+ -+ return TRUE; -+} -+ -+ -+ -+/* -+ * rfbSetClientColourMapBGR233 sets the client's colour map so that it's -+ * just like an 8-bit BGR233 true colour client. -+ */ -+ -+static Bool -+rfbSetClientColourMapBGR233(cl) -+ rfbClientPtr cl; -+{ -+ char buf[sz_rfbSetColourMapEntriesMsg + 256 * 3 * 2]; -+ rfbSetColourMapEntriesMsg *scme = (rfbSetColourMapEntriesMsg *)buf; -+ CARD16 *rgb = (CARD16 *)(&buf[sz_rfbSetColourMapEntriesMsg]); -+ int i, len; -+ int r, g, b; -+ -+ if (cl->format.bitsPerPixel != 8) { -+ rfbLog("%s: client not 8 bits per pixel\n", -+ "rfbSetClientColourMapBGR233"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return FALSE; -+ } -+ -+ scme->type = rfbSetColourMapEntries; -+ -+ scme->firstColour = Swap16IfLE(0); -+ scme->nColours = Swap16IfLE(256); -+ -+ len = sz_rfbSetColourMapEntriesMsg; -+ -+ i = 0; -+ -+ for (b = 0; b < 4; b++) { -+ for (g = 0; g < 8; g++) { -+ for (r = 0; r < 8; r++) { -+ rgb[i++] = Swap16IfLE(r * 65535 / 7); -+ rgb[i++] = Swap16IfLE(g * 65535 / 7); -+ rgb[i++] = Swap16IfLE(b * 65535 / 3); -+ } -+ } -+ } -+ -+ len += 256 * 3 * 2; -+ -+ if (WriteExact(cl->sock, buf, len) < 0) { -+ rfbLogPerror("rfbSetClientColourMapBGR233: write"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return FALSE; -+ } -+ return TRUE; -+} -+ -+ -+/* -+ * rfbSetClientColourMap is called to set the client's colour map. If the -+ * client is a true colour client, we simply update our own translation table -+ * and mark the whole screen as having been modified. -+ */ -+ -+Bool -+rfbSetClientColourMap(cl, firstColour, nColours) -+ rfbClientPtr cl; -+ int firstColour; -+ int nColours; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ BoxRec box; -+ -+ if (nColours == 0) { -+#if XFREE86VNC -+ nColours = miInstalledMaps[cl->pScreen->myNum]->pVisual->ColormapEntries; -+#else -+ nColours = pVNC->rfbInstalledColormap->pVisual->ColormapEntries; -+#endif -+ } -+ -+ if (pVNC->rfbServerFormat.trueColour || !cl->readyForSetColourMapEntries) { -+ return TRUE; -+ } -+ -+ if (cl->format.trueColour) { -+ (*rfbInitColourMapSingleTableFns -+ [cl->format.bitsPerPixel / 16]) (cl->pScreen, -+ &cl->translateLookupTable, -+ &pVNC->rfbServerFormat, &cl->format); -+ -+ REGION_UNINIT(cl->pScreen,&cl->modifiedRegion); -+ box.x1 = box.y1 = 0; -+ box.x2 = pVNC->width; -+ box.y2 = pVNC->height; -+ REGION_INIT(cl->pScreen,&cl->modifiedRegion,&box,0); -+ -+ return TRUE; -+ } -+ -+ return rfbSendSetColourMapEntries(cl, firstColour, nColours); -+} -+ -+ -+/* -+ * rfbSetClientColourMaps sets the colour map for each RFB client. -+ */ -+ -+void -+rfbSetClientColourMaps(firstColour, nColours) -+ int firstColour; -+ int nColours; -+{ -+ rfbClientPtr cl, nextCl; -+ -+ for (cl = rfbClientHead; cl; cl = nextCl) { -+ nextCl = cl->next; -+ rfbSetClientColourMap(cl, firstColour, nColours); -+ } -+} -+ -+ -+static void -+PrintPixelFormat(pf) -+ rfbPixelFormat *pf; -+{ -+ if (pf->bitsPerPixel == 1) { -+ rfbLog(" 1 bpp, %s sig bit in each byte is leftmost on the screen.\n", -+ (pf->bigEndian ? "most" : "least")); -+ } else { -+ rfbLog(" %d bpp, depth %d%s\n",pf->bitsPerPixel,pf->depth, -+ ((pf->bitsPerPixel == 8) ? "" -+ : (pf->bigEndian ? ", big endian" : ", little endian"))); -+ if (pf->trueColour) { -+ rfbLog(" true colour: max r %d g %d b %d, shift r %d g %d b %d\n", -+ pf->redMax, pf->greenMax, pf->blueMax, -+ pf->redShift, pf->greenShift, pf->blueShift); -+ } else { -+ rfbLog(" uses a colour map (not true colour).\n"); -+ } -+ } -+} -diff --git a/hw/dmx/vnc/vncInit.c b/hw/dmx/vnc/vncInit.c -new file mode 100644 -index 0000000..679cecc ---- /dev/null -+++ b/hw/dmx/vnc/vncInit.c -@@ -0,0 +1,436 @@ -+/* -+ * Copyright (C) 2002 Alan Hourihane. 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. -+ * -+ * Author: Alan Hourihane -+ */ -+ -+#include "rfb.h" -+ -+#if DMXVNC -+#include "../dmx.h" -+#include "../dmxcb.h" -+#endif -+ -+#include -+#include "fb.h" -+ -+#include "dixstruct.h" -+#include "compiler.h" -+ -+#include "mipointer.h" -+#include "mibstore.h" -+ -+#include "globals.h" -+#define DPMS_SERVER -+#include -+ -+#include -+ -+int vncScreenPrivateIndex = -1; -+int rfbGCIndex = -1; -+int inetdSock = -1; -+Atom VNC_LAST_CLIENT_ID = 0; -+Atom VNC_CONNECT = 0; -+char *desktopName = "x11"; -+char rfbThisHost[256]; -+ -+extern void VncExtensionInit(void); -+ -+extern void vncInitMouse(void); -+extern void vncInitKeyb(void); -+Bool VNCInit(ScreenPtr pScreen, DMXScreenInfo *dmxScreen); -+ -+#ifndef XFree86LOADER -+static unsigned long VNCGeneration = 0; -+#endif -+static void rfbWakeupHandler (int i, pointer blockData, unsigned long err, pointer pReadmask); -+ -+/* -+ * 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 %H:%M:%S ", localtime(&clock)); -+ fprintf(stderr, buf); -+ -+ vfprintf(stderr, format, args); -+ fflush(stderr); -+ -+ va_end(args); -+} -+ -+void rfbLogPerror(char *str) -+{ -+ rfbLog(""); -+ perror(str); -+} -+ -+ -+static ScreenPtr TheVNCScreen = NULL; -+ -+ -+static void -+nopGetImage(DrawablePtr pDrawable, int sx, int sy, -+ int w, int h, unsigned int format, -+ unsigned long planemask, char *pdstLine) -+{ -+ int i, j; -+ -+ for (i = 0; i < 1; i++) { -+ unsigned int *dst = (unsigned int *) pdstLine; -+ for (j = 0; j < w*h; j++) { -+ dst[j] = 0xff00ff; -+ } -+ } -+ -+ /* Eventually, call the DMX/Xinerama GetImage function */ -+} -+ -+/* -+ * Called by DMX's InitOutput() -+ */ -+void -+VNCInit2(void) -+{ -+ vncScreenPtr pScreenPriv; -+ VisualPtr v = NULL; -+ int i; -+ -+ rfbLog("DMXVNC: Enter VNCInit2\n"); -+ -+ pScreenPriv = xalloc(sizeof(vncScreenRec)); -+ pScreenPriv->width = dmxGlobalWidth; -+ pScreenPriv->height = dmxGlobalHeight; -+ pScreenPriv->rfbAuthTries = 0; -+ pScreenPriv->rfbAuthTooManyTries = FALSE; -+ pScreenPriv->timer = NULL; -+ pScreenPriv->udpPort = 0; -+ pScreenPriv->rfbListenSock = -1; -+ pScreenPriv->udpSock = -1; -+ pScreenPriv->udpSockConnected = FALSE; -+ pScreenPriv->httpListenSock = -1; -+ pScreenPriv->httpSock = -1; -+ pScreenPriv->maxFd = 0; -+ pScreenPriv->rfbAuthPasswdFile = NULL; -+ pScreenPriv->httpDir = NULL; -+ pScreenPriv->rfbInstalledColormap = NULL; -+ pScreenPriv->interface.s_addr = htonl (INADDR_ANY); -+ -+ pScreenPriv->rfbPort = 0; -+ pScreenPriv->httpPort = 0; -+ pScreenPriv->rfbAuthPasswdFile = NULL; -+ pScreenPriv->httpDir = NULL; -+ pScreenPriv->rfbAlwaysShared = FALSE; -+ pScreenPriv->rfbNeverShared = FALSE; -+ pScreenPriv->rfbUserAccept = FALSE; -+ pScreenPriv->useGetImage = TRUE; /* For DMX */ -+ pScreenPriv->rfbViewOnly = FALSE; -+ pScreenPriv->rfbDontDisconnect = FALSE; -+ pScreenPriv->loginAuthEnabled = FALSE; -+ -+ /* Find the root window's visual. -+ * XXX this might be the wrong info to use below. -+ */ -+ for (i = 0; i < screenInfo.screens[0]->numVisuals; i++) { -+ v = screenInfo.screens[0]->visuals + i; -+ if (v->vid == screenInfo.screens[0]->rootVisual) { -+ break; -+ } -+ } -+ -+ /* XXX is this the right depth and bpp? */ -+ /* With DMX, screenInfo.screens[0]->rootDepth is 24 and that doesn't -+ * work in translate.c! We're just using 32. -+ */ -+ pScreenPriv->rfbServerFormat.bitsPerPixel = 32; -+ pScreenPriv->rfbServerFormat.depth = 32; -+ pScreenPriv->rfbServerFormat.bigEndian = 0; -+ pScreenPriv->rfbServerFormat.trueColour = (v->class == TrueColor); -+ if (pScreenPriv->rfbServerFormat.trueColour) { -+ pScreenPriv->rfbServerFormat.redMax = v->redMask >> v->offsetRed; -+ pScreenPriv->rfbServerFormat.greenMax = v->greenMask >> v->offsetGreen; -+ pScreenPriv->rfbServerFormat.blueMax = v->blueMask >> v->offsetBlue; -+ pScreenPriv->rfbServerFormat.redShift = v->offsetRed; -+ pScreenPriv->rfbServerFormat.greenShift = v->offsetGreen; -+ pScreenPriv->rfbServerFormat.blueShift = v->offsetBlue; -+ } else { -+ pScreenPriv->rfbServerFormat.redMax -+ = pScreenPriv->rfbServerFormat.greenMax -+ = pScreenPriv->rfbServerFormat.blueMax = 0; -+ pScreenPriv->rfbServerFormat.redShift -+ = pScreenPriv->rfbServerFormat.greenShift -+ = pScreenPriv->rfbServerFormat.blueShift = 0; -+ } -+ -+ /* Allocate/init TheVNCScreen object */ -+ vncScreenPrivateIndex = 0; -+ assert(!TheVNCScreen); -+ TheVNCScreen = (ScreenPtr) Xcalloc(1, sizeof(struct _Screen)); -+ TheVNCScreen->devPrivates = (DevUnion *) Xcalloc(1, sizeof(DevUnion)); -+ TheVNCScreen->devPrivates[vncScreenPrivateIndex].ptr = pScreenPriv; -+ TheVNCScreen->GetImage = nopGetImage; -+ -+ rfbInitSockets(TheVNCScreen); -+ if (inetdSock == -1) -+ httpInitSockets(TheVNCScreen); -+} -+ -+ -+Bool -+VNCInit(ScreenPtr pScreen, DMXScreenInfo *pScrn) -+{ -+ VisualPtr visual; -+ vncScreenPtr pScreenPriv; -+#if 0 -+ char *interface_str = NULL; -+#endif -+#ifdef RENDER -+ PictureScreenPtr ps; -+#endif -+ -+ rfbLog("DMXVNC: Enter VNCInit\n"); -+ -+#ifndef XFree86LOADER -+ if (VNCGeneration != serverGeneration) { -+ VNCGeneration = serverGeneration; -+ if ( ((vncScreenPrivateIndex = AllocateScreenPrivateIndex()) < 0) || -+ ((rfbGCIndex = AllocateGCPrivateIndex()) < 0) ) -+ return FALSE; -+ } -+#endif -+ -+ if (!AllocateGCPrivate(pScreen, rfbGCIndex, sizeof(rfbGCRec))) { -+ ErrorF("VNCInit(): failed to allocate GCIndex\n"); -+ return FALSE; -+ } -+ -+ if (!(pScreenPriv = xalloc(sizeof(vncScreenRec)))) -+ return FALSE; -+ -+ pScreen->devPrivates[vncScreenPrivateIndex].ptr = (pointer)pScreenPriv; -+ -+ pScreenPriv->rfbAuthTries = 0; -+ pScreenPriv->rfbAuthTooManyTries = FALSE; -+ pScreenPriv->timer = NULL; -+ pScreenPriv->udpPort = 0; -+ pScreenPriv->rfbListenSock = -1; -+ pScreenPriv->udpSock = -1; -+ pScreenPriv->udpSockConnected = FALSE; -+ pScreenPriv->httpListenSock = -1; -+ pScreenPriv->httpSock = -1; -+ pScreenPriv->maxFd = 0; -+ pScreenPriv->rfbAuthPasswdFile = NULL; -+ pScreenPriv->httpDir = NULL; -+ pScreenPriv->rfbInstalledColormap = NULL; -+ pScreenPriv->interface.s_addr = htonl (INADDR_ANY); -+ -+ pScreenPriv->rfbPort = 0; -+ pScreenPriv->httpPort = 0; -+ pScreenPriv->rfbAuthPasswdFile = NULL; -+ pScreenPriv->httpDir = NULL; -+ pScreenPriv->rfbAlwaysShared = FALSE; -+ pScreenPriv->rfbNeverShared = FALSE; -+ pScreenPriv->rfbUserAccept = FALSE; -+ pScreenPriv->useGetImage = TRUE; /* For DMX */ -+ pScreenPriv->rfbViewOnly = FALSE; -+ pScreenPriv->rfbDontDisconnect = FALSE; -+ pScreenPriv->loginAuthEnabled = FALSE; -+ -+#if 0 -+ if (xf86ReturnOptValBool(options, OPTION_LOCALHOST, FALSE)) -+ pScreenPriv->interface.s_addr = htonl (INADDR_LOOPBACK); -+ -+ interface_str = xf86GetOptValString(options, OPTION_INTERFACE); -+ -+ if (interface_str && pScreenPriv->interface.s_addr == htonl(INADDR_ANY)) { -+ Bool failed = FALSE; -+ struct in_addr got; -+ unsigned long octet; -+ char *p = interface_str, *end; -+ int q; -+ -+ for (q = 0; q < 4; q++) { -+ octet = strtoul (p, &end, 10); -+ -+ if (p == end || octet > 255) -+ failed = TRUE; -+ -+ if ((q < 3 && *end != '.') || -+ (q == 3 && *end != '\0')) -+ failed = TRUE; -+ -+ got.s_addr = (got.s_addr << 8) | octet; -+ p = end + 1; -+ } -+ -+ if (!failed) -+ pScreenPriv->interface.s_addr = htonl (got.s_addr); -+ else -+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VNC interface option malformed, not using.\n"); -+ } -+#endif -+ -+ if (!VNC_LAST_CLIENT_ID) -+ VNC_LAST_CLIENT_ID = MakeAtom("VNC_LAST_CLIENT_ID", -+ strlen("VNC_LAST_CLIENT_ID"), TRUE); -+ if (!VNC_CONNECT) -+ VNC_CONNECT = MakeAtom("VNC_CONNECT", strlen("VNC_CONNECT"), TRUE); -+ -+ rfbInitSockets(pScreen); -+ if (inetdSock == -1) -+ httpInitSockets(pScreen); -+ -+#ifdef CORBA -+ initialiseCORBA(argc, argv, desktopName); -+#endif -+ -+ pScreenPriv->width = pScrn->scrnWidth; -+ pScreenPriv->height = pScrn->scrnHeight; -+ pScreenPriv->depth = pScrn->beDepth; -+ pScreenPriv->paddedWidthInBytes = PixmapBytePad(pScrn->scrnWidth, pScrn->beDepth); -+ pScreenPriv->bitsPerPixel = rfbBitsPerPixel(pScrn->beDepth); -+ pScreenPriv->pfbMemory = NULL; -+ pScreenPriv->oldpfbMemory = NULL; -+ -+ pScreenPriv->cursorIsDrawn = TRUE; -+ pScreenPriv->dontSendFramebufferUpdate = FALSE; -+ -+ pScreenPriv->CloseScreen = pScreen->CloseScreen; -+ pScreenPriv->CreateGC = pScreen->CreateGC; -+ pScreenPriv->PaintWindowBackground = pScreen->PaintWindowBackground; -+ pScreenPriv->PaintWindowBorder = pScreen->PaintWindowBorder; -+ pScreenPriv->CopyWindow = pScreen->CopyWindow; -+ pScreenPriv->ClearToBackground = pScreen->ClearToBackground; -+ pScreenPriv->RestoreAreas = pScreen->RestoreAreas; -+ pScreenPriv->WakeupHandler = pScreen->WakeupHandler; -+ pScreenPriv->InstallColormap = pScreen->InstallColormap; -+ pScreenPriv->UninstallColormap = pScreen->UninstallColormap; -+ pScreenPriv->ListInstalledColormaps = pScreen->ListInstalledColormaps; -+ pScreenPriv->StoreColors = pScreen->StoreColors; -+#ifdef CHROMIUM -+ pScreenPriv->RealizeWindow = pScreen->RealizeWindow; -+ pScreenPriv->UnrealizeWindow = pScreen->UnrealizeWindow; -+ pScreenPriv->DestroyWindow = pScreen->DestroyWindow; -+ pScreenPriv->PositionWindow = pScreen->PositionWindow; -+ pScreenPriv->ResizeWindow = pScreen->ResizeWindow; -+ pScreenPriv->ClipNotify = pScreen->ClipNotify; -+#endif -+#ifdef RENDER -+ ps = GetPictureScreenIfSet(pScreen); -+ if (ps) -+ pScreenPriv->Composite = ps->Composite; -+#endif -+ pScreen->CloseScreen = rfbCloseScreen; -+ pScreen->CreateGC = rfbCreateGC; -+ pScreen->PaintWindowBackground = rfbPaintWindowBackground; -+ pScreen->PaintWindowBorder = rfbPaintWindowBorder; -+ pScreen->CopyWindow = rfbCopyWindow; -+ pScreen->ClearToBackground = rfbClearToBackground; -+ pScreen->RestoreAreas = rfbRestoreAreas; -+ pScreen->WakeupHandler = rfbWakeupHandler; -+ pScreen->InstallColormap = rfbInstallColormap; -+ pScreen->UninstallColormap = rfbUninstallColormap; -+ pScreen->ListInstalledColormaps = rfbListInstalledColormaps; -+ pScreen->StoreColors = rfbStoreColors; -+ -+#ifdef CHROMIUM -+ pScreen->RealizeWindow = rfbRealizeWindow; -+ pScreen->UnrealizeWindow = rfbUnrealizeWindow; -+ pScreen->DestroyWindow = rfbDestroyWindow; -+ pScreen->PositionWindow = rfbPositionWindow; -+ pScreen->ResizeWindow = rfbResizeWindow; -+ pScreen->ClipNotify = rfbClipNotify; -+#endif -+#ifdef RENDER -+ if (ps) -+ ps->Composite = rfbComposite; -+#endif -+ -+ for (visual = pScreen->visuals; visual->vid != pScreen->rootVisual; visual++) -+ ; -+ -+ if (!visual) { -+ ErrorF("rfbScreenInit: couldn't find root visual\n"); -+ return FALSE; -+ } -+ -+ pScreenPriv->rfbServerFormat.bitsPerPixel = pScrn->beBPP; -+ pScreenPriv->rfbServerFormat.depth = pScrn->beDepth; -+ pScreenPriv->rfbServerFormat.bigEndian = !(*(char *)&rfbEndianTest); -+ pScreenPriv->rfbServerFormat.trueColour = (visual->class == TrueColor); -+ if (pScreenPriv->rfbServerFormat.trueColour) { -+ pScreenPriv->rfbServerFormat.redMax = visual->redMask >> visual->offsetRed; -+ pScreenPriv->rfbServerFormat.greenMax = visual->greenMask >> visual->offsetGreen; -+ pScreenPriv->rfbServerFormat.blueMax = visual->blueMask >> visual->offsetBlue; -+ pScreenPriv->rfbServerFormat.redShift = visual->offsetRed; -+ pScreenPriv->rfbServerFormat.greenShift = visual->offsetGreen; -+ pScreenPriv->rfbServerFormat.blueShift = visual->offsetBlue; -+ } else { -+ pScreenPriv->rfbServerFormat.redMax -+ = pScreenPriv->rfbServerFormat.greenMax -+ = pScreenPriv->rfbServerFormat.blueMax = 0; -+ pScreenPriv->rfbServerFormat.redShift -+ = pScreenPriv->rfbServerFormat.greenShift -+ = pScreenPriv->rfbServerFormat.blueShift = 0; -+ } -+ -+ return TRUE; -+} -+ -+static void -+rfbWakeupHandler ( -+ int i, -+ pointer blockData, -+ unsigned long err, -+ pointer pReadmask -+){ -+ ScreenPtr pScreen = screenInfo.screens[i]; -+ vncScreenPtr pScreenPriv = VNCPTR(pScreen); -+ /*DMXScreenInfo *pScrn = &dmxScreens[pScreen->myNum];*/ -+ -+ rfbRootPropertyChange(pScreen); /* Check clipboard */ -+ -+ rfbCheckFds(pScreen); -+ httpCheckFds(pScreen); -+#ifdef CORBA -+ corbaCheckFds(); -+#endif -+ -+ pScreen->WakeupHandler = pScreenPriv->WakeupHandler; -+ (*pScreen->WakeupHandler) (i, blockData, err, pReadmask); -+ pScreen->WakeupHandler = rfbWakeupHandler; -+} -+ -+ -+/*BP*/ -+void -+rfbWakeupHandler2(void) -+{ -+ ScreenPtr pScreen = TheVNCScreen; -+ rfbRootPropertyChange(pScreen); /* Check clipboard */ -+ rfbCheckFds(pScreen); -+ httpCheckFds(pScreen); -+} -diff --git a/hw/dmx/vnc/vncauth.c b/hw/dmx/vnc/vncauth.c -new file mode 100644 -index 0000000..9adae0d ---- /dev/null -+++ b/hw/dmx/vnc/vncauth.c -@@ -0,0 +1,239 @@ -+/* -+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. -+ * -+ * This is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This software is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -+ * USA. -+ */ -+ -+/* -+ * vncauth.c - Functions for VNC password management and authentication. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include "vncauth.h" -+#include "d3des.h" -+ -+ -+/* -+ * Make sure we call srandom() only once. -+ */ -+ -+static int s_srandom_called = 0; -+ -+/* -+ * We use a fixed key to store passwords, since we assume that our local -+ * file system is secure but nonetheless don't want to store passwords -+ * as plaintext. -+ */ -+ -+static unsigned char s_fixedkey[8] = {23,82,107,6,35,78,88,7}; -+ -+ -+/* -+ * Encrypt a password and store it in a file. Returns 0 if successful, -+ * 1 if the file could not be written. -+ * -+ * NOTE: This function is preserved only for compatibility with the original -+ * AT&T VNC software. Use vncEncryptAndStorePasswd2() instead. -+ */ -+ -+int -+vncEncryptAndStorePasswd(char *passwd, char *fname) -+{ -+ return (vncEncryptAndStorePasswd2(passwd, NULL, fname) == 0); -+} -+ -+/* -+ * Encrypt one or two passwords and store them in a file. Returns 1 if -+ * successful, 0 if the file could not be written (note that the original -+ * vncEncryptAndStorePasswd() function returns inverse values). The -+ * passwdViewOnly pointer may be NULL. -+ */ -+ -+int -+vncEncryptAndStorePasswd2(char *passwd, char *passwdViewOnly, char *fname) -+{ -+ FILE *fp; -+ int i, bytesToWrite, bytesWrote; -+ unsigned char encryptedPasswd[16] = { -+ 0,0,0,0,0,0,0,0, -+ 0,0,0,0,0,0,0,0 -+ }; -+ -+ fp = fopen(fname,"w"); -+ if (fp == NULL) -+ return 0; -+ -+ chmod(fname, S_IRUSR|S_IWUSR); -+ -+ strncpy(encryptedPasswd, passwd, 8); -+ if (passwdViewOnly != NULL) -+ strncpy(encryptedPasswd + 8, passwdViewOnly, 8); -+ -+ /* Do encryption in-place - this way we overwrite our copies of -+ plaintext passwords. */ -+ -+ deskey(s_fixedkey, EN0); -+ des(encryptedPasswd, encryptedPasswd); -+ if (passwdViewOnly != NULL) -+ des(encryptedPasswd + 8, encryptedPasswd + 8); -+ -+ bytesToWrite = (passwdViewOnly == NULL) ? 8 : 16; -+ bytesWrote = fwrite(encryptedPasswd, 1, bytesToWrite, fp); -+ -+ fclose(fp); -+ return (bytesWrote == bytesToWrite); -+} -+ -+ -+/* -+ * Decrypt a password from a file. Returns a pointer to a newly allocated -+ * string containing the password or a null pointer if the password could -+ * not be retrieved for some reason. -+ * -+ * NOTE: This function is preserved only for compatibility with the original -+ * AT&T VNC software. Use vncDecryptPasswdFromFile2() instead. -+ */ -+ -+char * -+vncDecryptPasswdFromFile(char *fname) -+{ -+ char *passwd; -+ -+ passwd = malloc(9); -+ -+ if (passwd != NULL) { -+ if (vncDecryptPasswdFromFile2(fname, passwd, NULL) == 0) { -+ free(passwd); -+ passwd = NULL; -+ } -+ } -+ -+ return passwd; -+} -+ -+/* -+ * Decrypt one or two passwords from a file. Returns the number of -+ * passwords read (1, 2, or 0 on error). On success, the passwords are -+ * written into buffers passwdFullControl[] and passwdViewOnly[] if -+ * they are not NULL. If the pointers to buffers are not NULL, then -+ * the buffers should be at least of 9 bytes length. -+ */ -+ -+int -+vncDecryptPasswdFromFile2(char *fname, -+ char *passwdFullControl, char *passwdViewOnly) -+{ -+ FILE *fp; -+ int i, ch; -+ char passwd[16]; -+ -+ if (strcmp(fname, "-") != 0) { -+ if ((fp = fopen(fname,"r")) == NULL) -+ return 0; /* Could not open the file */ -+ } else { -+ fp = stdin; -+ } -+ -+ for (i = 0; i < 16; i++) { -+ ch = getc(fp); -+ if (ch == EOF) -+ break; -+ passwd[i] = ch; -+ } -+ -+ if (fp != stdin) -+ fclose(fp); -+ -+ if (i < 8) -+ return 0; /* Could not read eight bytes */ -+ -+ deskey(s_fixedkey, DE1); -+ -+ /* Decoding first (full-control) password */ -+ if (passwdFullControl != NULL) { -+ des(passwd, passwd); -+ memcpy(passwdFullControl, passwd, 8); -+ passwdFullControl[8] = '\0'; -+ } -+ -+ /* Decoding second (view-only) password if available */ -+ if (i == 16 && passwdViewOnly != NULL) { -+ des(&passwd[8], &passwd[8]); -+ memcpy(passwdViewOnly, &passwd[8], 8); -+ passwdViewOnly[8] = '\0'; -+ } -+ -+ /* Destroying our copy of clear-text passwords */ -+ memset(passwd, 0, 16); -+ -+ return (i < 16) ? 1 : 2; -+} -+ -+ -+/* -+ * Generate CHALLENGESIZE random bytes for use in challenge-response -+ * authentication. -+ */ -+ -+void -+vncRandomBytes(unsigned char *bytes) -+{ -+ int i; -+ unsigned int seed; -+ -+ if (!s_srandom_called) { -+ seed = (unsigned int)time(0) ^ (unsigned int)getpid(); -+ srandom(seed); -+ s_srandom_called = 1; -+ } -+ -+ for (i = 0; i < CHALLENGESIZE; i++) { -+ bytes[i] = (unsigned char)(random() & 255); -+ } -+} -+ -+ -+/* -+ * Encrypt CHALLENGESIZE bytes in memory using a password. -+ */ -+ -+void -+vncEncryptBytes(unsigned char *bytes, char *passwd) -+{ -+ unsigned char key[8]; -+ int i; -+ -+ /* key is simply password padded with nulls */ -+ -+ for (i = 0; i < 8; i++) { -+ if (i < strlen(passwd)) { -+ key[i] = passwd[i]; -+ } else { -+ key[i] = 0; -+ } -+ } -+ -+ deskey(key, EN0); -+ -+ for (i = 0; i < CHALLENGESIZE; i += 8) { -+ des(bytes+i, bytes+i); -+ } -+} -diff --git a/hw/dmx/vnc/vncauth.h b/hw/dmx/vnc/vncauth.h -new file mode 100644 -index 0000000..5ece2e1 ---- /dev/null -+++ b/hw/dmx/vnc/vncauth.h -@@ -0,0 +1,34 @@ -+/* -+ * 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. -+ */ -+ -+/* -+ * vncauth.h - describes the functions provided by the vncauth library. -+ */ -+ -+#define MAXPWLEN 8 -+#define CHALLENGESIZE 16 -+ -+extern int vncEncryptAndStorePasswd(char *passwd, char *fname); -+extern char *vncDecryptPasswdFromFile(char *fname); -+extern void vncRandomBytes(unsigned char *bytes); -+extern void vncEncryptBytes(unsigned char *bytes, char *passwd); -+ -+extern int vncEncryptAndStorePasswd2(char *passwd, char *passwdViewOnly, char *fname); -+extern int vncDecryptPasswdFromFile2(char *fname, char *passwdFullControl, char *passwdViewOnly); -+ -diff --git a/hw/dmx/vnc/vncext.c b/hw/dmx/vnc/vncext.c -new file mode 100644 -index 0000000..0bcd109 ---- /dev/null -+++ b/hw/dmx/vnc/vncext.c -@@ -0,0 +1,689 @@ -+/* -+ * Copyright (C) 2002 Alan Hourihane. 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. -+ * -+ * Author: Alan Hourihane -+ */ -+ -+#include "rfb.h" -+#include "extnsionst.h" -+#define _VNC_SERVER -+#include -+#include "../dmx.h" -+ -+#include -+#include -+#include -+#include -+ -+#ifdef CHROMIUM -+extern void rfbSendChromiumStart(unsigned int ipaddress, unsigned int port); -+extern void rfbChromiumMonitorWindowID(unsigned int cr_windowid, unsigned long windowid); -+int GenerateVncChromiumConnectedEvent(int sock); -+#endif -+ -+/*extern void rfbUserAllow(int sock, int accept);*/ -+ -+int VncSelectNotify(ClientPtr client, BOOL onoff); -+int GenerateVncConnectedEvent(int sock); -+int GenerateVncDisconnectedEvent(int sock); -+void VncExtensionInit(void); -+ -+static int VncErrorBase; /* first vnc error number */ -+static int VncEventBase; /* first vnc event number */ -+ -+unsigned long VncResourceGeneration = 0; -+ -+static RESTYPE VncNotifyList; -+ -+static XID faked; -+ -+typedef struct _VncNotifyListRec { -+ struct _VncNotifyListRec *next; -+ ClientPtr client; -+} VncNotifyListRec, *VncNotifyListPtr; -+ -+static int -+ProcVncQueryVersion(ClientPtr client) -+{ -+ xVncQueryVersionReply rep; -+ -+ REQUEST_SIZE_MATCH(xVncQueryVersionReq); -+ rep.type = X_Reply; -+ rep.sequenceNumber = client->sequence; -+ rep.length = 0; -+ rep.majorVersion = VNC_MAJOR_VERSION; -+ rep.minorVersion = VNC_MINOR_VERSION; -+ if(client->swapped) -+ { -+ register char n; -+ swaps(&rep.sequenceNumber, n); -+ swaps(&rep.majorVersion, n); -+ swaps(&rep.minorVersion, n); -+ } -+ (void)WriteToClient(client, SIZEOF(xVncQueryVersionReply), -+ (char *)&rep); -+ return (client->noClientException); -+} /* ProcVncQueryVersion */ -+ -+static int -+ProcVncConnection(ClientPtr client) -+{ -+ REQUEST(xVncConnectionReq); -+ xVncConnectionReply rep; -+ -+ rfbUserAllow( stuff->sock, stuff->accept ); -+ -+ REQUEST_SIZE_MATCH(xVncConnectionReq); -+ rep.type = X_Reply; -+ rep.sequenceNumber = client->sequence; -+ rep.length = 0; -+ rep.sock = 0; -+ rep.accept = 0; -+ if(client->swapped) -+ { -+ register char n; -+ swaps(&rep.sequenceNumber, n); -+ swaps(&rep.sock, n); -+ swaps(&rep.accept, n); -+ } -+ (void)WriteToClient(client, SIZEOF(xVncConnectionReply), -+ (char *)&rep); -+ return (client->noClientException); -+} /* ProcVncConnection */ -+ -+static int -+ProcVncSelectNotify(ClientPtr client) -+{ -+ REQUEST(xVncSelectNotifyReq); -+ xVncSelectNotifyReply rep; -+ -+ VncSelectNotify(client, stuff->onoff); -+ -+ REQUEST_SIZE_MATCH(xVncSelectNotifyReq); -+ rep.type = X_Reply; -+ rep.sequenceNumber = client->sequence; -+ rep.length = 0; -+ if(client->swapped) -+ { -+ register char n; -+ swaps(&rep.sequenceNumber, n); -+ } -+ (void)WriteToClient(client, SIZEOF(xVncSelectNotifyReply), -+ (char *)&rep); -+ return (client->noClientException); -+ -+} -+ -+static int -+ProcVncListConnections(ClientPtr client) -+{ -+ xVncListConnectionsReply rep; -+ rfbClientPtr cl; -+ int count = 0; -+ struct in_addr ipaddress; -+ xVncConnectionListInfo Info; -+ -+ /* count connections */ -+ for (cl = rfbClientHead; cl; cl = cl->next) -+#ifdef CHROMIUM -+ /* -+ * Fix this, as it should be generic, but we're only using it -+ * for Chromium at the moment, so we only list the connections -+ * that have a valid chromium encoding. We should be able to list -+ * any type requested. FIXME! XXXX -+ * See furthur down this function too!!! -+ */ -+ if (cl->enableChromiumEncoding) -+#endif -+ count++; -+ -+ REQUEST_SIZE_MATCH(xVncListConnectionsReq); -+ rep.type = X_Reply; -+ rep.sequenceNumber = client->sequence; -+ rep.count = count; -+ rep.length = count * sizeof(xVncConnectionListInfo) >> 2; -+ if(client->swapped) -+ { -+ register char n; -+ swaps(&rep.sequenceNumber, n); -+ swaps(&rep.count, n); -+ } -+ (void)WriteToClient(client, SIZEOF(xVncListConnectionsReply), -+ (char *)&rep); -+ -+ for (cl = rfbClientHead; cl; cl = cl->next) { -+#ifdef CHROMIUM -+ /* -+ * Fix this, as it should be generic, but we're only using it -+ * for Chromium at the moment, so we only list the connections -+ * that have a valid chromium encoding. We should be able to list -+ * any type requested. FIXME! XXXX -+ */ -+ if (!cl->enableChromiumEncoding) -+ continue; -+#endif -+ inet_aton(cl->host, &ipaddress); -+ memcpy(&Info, &ipaddress, sizeof(struct in_addr)); -+ WriteToClient(client, SIZEOF(xVncConnectionListInfo), (char*)&Info); -+ } -+ -+ return (client->noClientException); -+} /* ProcVncListConnections */ -+ -+#ifdef CHROMIUM -+static int -+ProcVncChromiumStart(ClientPtr client) -+{ -+ REQUEST(xVncChromiumStartReq); -+ xVncChromiumStartReply rep; -+ -+ rfbSendChromiumStart(stuff->ipaddress, stuff->port); -+ -+ REQUEST_SIZE_MATCH(xVncChromiumStartReq); -+ rep.type = X_Reply; -+ rep.sequenceNumber = client->sequence; -+ rep.length = 0; -+ if(client->swapped) -+ { -+ register char n; -+ swaps(&rep.sequenceNumber, n); -+ } -+ (void)WriteToClient(client, SIZEOF(xVncChromiumStartReply), -+ (char *)&rep); -+ return (client->noClientException); -+} /* ProcVncChromiumStart */ -+ -+static int -+ProcVncChromiumMonitor(ClientPtr client) -+{ -+ REQUEST(xVncChromiumMonitorReq); -+ xVncChromiumMonitorReply rep; -+ -+ rfbChromiumMonitorWindowID(stuff->cr_windowid, stuff->windowid); -+ -+ REQUEST_SIZE_MATCH(xVncChromiumMonitorReq); -+ rep.type = X_Reply; -+ rep.sequenceNumber = client->sequence; -+ rep.length = 0; -+ if(client->swapped) -+ { -+ register char n; -+ swaps(&rep.sequenceNumber, n); -+ } -+ (void)WriteToClient(client, SIZEOF(xVncChromiumMonitorReply), -+ (char *)&rep); -+ return (client->noClientException); -+} /* ProcVncChromiumMonitor */ -+#endif /* CHROMIUM */ -+ -+static int -+ProcVncDispatch(ClientPtr client) -+{ -+ REQUEST(xReq); -+ -+ switch (stuff->data) -+ { -+ case X_VncQueryVersion: -+ return ProcVncQueryVersion(client); -+ case X_VncSelectNotify: -+ return ProcVncSelectNotify(client); -+ case X_VncConnection: -+ return ProcVncConnection(client); -+ case X_VncListConnections: -+ return ProcVncListConnections(client); -+#ifdef CHROMIUM -+ case X_VncChromiumStart: -+ return ProcVncChromiumStart(client); -+ case X_VncChromiumMonitor: -+ return ProcVncChromiumMonitor(client); -+#endif -+ default: -+ return BadRequest; -+ } -+} /* ProcVncDispatch */ -+ -+static int -+SProcVncQueryVersion(ClientPtr client) -+{ -+ REQUEST(xVncQueryVersionReq); -+ register char n; -+ -+ swaps(&stuff->length, n); -+ REQUEST_SIZE_MATCH(xVncQueryVersionReq); -+ swaps(&stuff->majorVersion, n); -+ swaps(&stuff->minorVersion,n); -+ return ProcVncQueryVersion(client); -+} /* SProcVncQueryVersion */ -+ -+static int -+SProcVncSelectNotify(ClientPtr client) -+{ -+ REQUEST(xVncSelectNotifyReq); -+ register char n; -+ -+ swaps(&stuff->length, n); -+ REQUEST_SIZE_MATCH(xVncSelectNotifyReq); -+ return ProcVncSelectNotify(client); -+} /* SProcVncSelectNotify */ -+ -+static int -+SProcVncListConnections(ClientPtr client) -+{ -+ REQUEST(xVncListConnectionsReq); -+ register char n; -+ -+ swaps(&stuff->length, n); -+ REQUEST_SIZE_MATCH(xVncListConnectionsReq); -+ return ProcVncListConnections(client); -+} /* SProcVncListConnections */ -+ -+#ifdef CHROMIUM -+static int -+SProcVncChromiumStart(ClientPtr client) -+{ -+ REQUEST(xVncChromiumStartReq); -+ register char n; -+ -+ swaps(&stuff->ipaddress, n); -+ swaps(&stuff->port, n); -+ swaps(&stuff->length, n); -+ REQUEST_SIZE_MATCH(xVncChromiumStartReq); -+ return ProcVncChromiumStart(client); -+} /* SProcVncChromiumStart */ -+ -+static int -+SProcVncChromiumMonitor(ClientPtr client) -+{ -+ REQUEST(xVncChromiumMonitorReq); -+ register char n; -+ -+ swaps(&stuff->length, n); -+ swaps(&stuff->windowid, n); -+ swaps(&stuff->cr_windowid, n); -+ REQUEST_SIZE_MATCH(xVncChromiumMonitorReq); -+ return ProcVncChromiumMonitor(client); -+} /* SProcVncChromiumMonitor */ -+#endif /* CHROMIUM */ -+ -+static int -+SProcVncConnection(ClientPtr client) -+{ -+ REQUEST(xVncConnectionReq); -+ register char n; -+ -+ -+ swaps(&stuff->length, n); -+ REQUEST_SIZE_MATCH(xVncConnectionReq); -+ swaps(&stuff->sock, n); -+ swaps(&stuff->accept,n); -+ return ProcVncConnection(client); -+} /* SProcVncConnection */ -+ -+static int -+SProcVncDispatch(ClientPtr client) -+{ -+ REQUEST(xReq); -+ -+ switch (stuff->data) -+ { -+ case X_VncQueryVersion: -+ return SProcVncQueryVersion(client); -+ case X_VncSelectNotify: -+ return SProcVncSelectNotify(client); -+ case X_VncConnection: -+ return SProcVncConnection(client); -+ case X_VncListConnections: -+ return SProcVncListConnections(client); -+#ifdef CHROMIUM -+ case X_VncChromiumStart: -+ return SProcVncChromiumStart(client); -+ case X_VncChromiumMonitor: -+ return SProcVncChromiumMonitor(client); -+#endif -+ default: -+ return BadRequest; -+ } -+} /* SProcVncDispatch */ -+ -+static void -+SwapVncConnectedEvent(xVncConnectedEvent *from, xVncConnectedEvent *to) -+{ -+ to->type = from->type; -+ to->detail = from->detail; -+ cpswaps(from->sequenceNumber, to->sequenceNumber); -+ cpswapl(from->connected, to->connected); -+} -+ -+#ifdef CHROMIUM -+static void -+SwapVncChromiumConnectedEvent(xVncConnectedEvent *from, xVncConnectedEvent *to) -+{ -+ to->type = from->type; -+ to->detail = from->detail; -+ cpswaps(from->sequenceNumber, to->sequenceNumber); -+ cpswapl(from->connected, to->connected); -+} -+#endif -+ -+static void -+SwapVncDisconnectedEvent(xVncConnectedEvent *from, xVncConnectedEvent *to) -+{ -+ to->type = from->type; -+ to->detail = from->detail; -+ cpswaps(from->sequenceNumber, to->sequenceNumber); -+ cpswapl(from->connected, to->connected); -+} -+ -+int -+GenerateVncConnectedEvent(int sock) -+{ -+ VncNotifyListPtr pn; -+ -+ pn = (VncNotifyListPtr)LookupIDByType(faked, VncNotifyList); -+ -+ while (pn) -+ { -+ if (pn->client) -+ { -+ xVncConnectedEvent conn; -+ SOCKLEN_T peer_len; -+ struct sockaddr_in peer; -+ -+ conn.type = VncEventBase + XVncConnected; -+ conn.sequenceNumber = pn->client->sequence; -+ conn.connected = sock; -+ -+ peer_len = sizeof(peer); -+ if (getpeername(sock, (struct sockaddr *) &peer, &peer_len) == -1) -+ conn.ipaddress = 0; -+ else -+ conn.ipaddress = (CARD32)peer.sin_addr.s_addr; -+ -+ (void) TryClientEvents(pn->client, (xEventPtr)&conn, 1, NoEventMask, -+ NoEventMask, NullGrab); -+ } -+ pn = pn->next; -+ } -+ -+ return 1; -+} -+ -+#ifdef CHROMIUM -+int -+GenerateVncChromiumConnectedEvent(int sock) -+{ -+ VncNotifyListPtr pn; -+ -+ pn = (VncNotifyListPtr)LookupIDByType(faked, VncNotifyList); -+ -+ while (pn) -+ { -+ if (pn->client) -+ { -+ xVncConnectedEvent conn; -+ SOCKLEN_T peer_len; -+ struct sockaddr_in peer; -+ -+ conn.type = VncEventBase + XVncChromiumConnected; -+ conn.sequenceNumber = pn->client->sequence; -+ conn.connected = sock; -+ -+ peer_len = sizeof(peer); -+ if (getpeername(sock, (struct sockaddr *)&peer, &peer_len) == -1) -+ conn.ipaddress = 0; -+ else -+ conn.ipaddress = (CARD32)peer.sin_addr.s_addr; -+ -+ (void) TryClientEvents(pn->client, (xEventPtr)&conn, 1, NoEventMask, -+ NoEventMask, NullGrab); -+ } -+ pn = pn->next; -+ } -+ -+ return 1; -+} -+#endif /* CHROMIUM */ -+ -+int -+GenerateVncDisconnectedEvent(int sock) -+{ -+ VncNotifyListPtr pn; -+ -+ pn = (VncNotifyListPtr)LookupIDByType(faked, VncNotifyList); -+ -+ while (pn) -+ { -+ if (pn->client) -+ { -+ xVncDisconnectedEvent conn; -+ conn.type = VncEventBase + XVncDisconnected; -+ conn.sequenceNumber = pn->client->sequence; -+ conn.connected = sock; -+ (void) TryClientEvents(pn->client, (xEventPtr)&conn, 1, NoEventMask, -+ NoEventMask, NullGrab); -+ } -+ pn = pn->next; -+ } -+ -+ return 1; -+} -+ -+static void -+VncResetProc(ExtensionEntry *extEntry) -+{ -+} /* VncResetProc */ -+ -+int -+VncSelectNotify( -+ ClientPtr client, -+ BOOL onoff -+){ -+ VncNotifyListPtr pn,tpn,fpn; -+ -+ if (!faked) -+ faked = FakeClientID(client->index); -+ -+ pn = (VncNotifyListPtr)LookupIDByType(faked, VncNotifyList); -+ -+ if (!onoff && !pn) return Success; -+ -+ if (!pn) -+ { -+ if (!(tpn = (VncNotifyListPtr)xalloc(sizeof(VncNotifyListRec)))) -+ return BadAlloc; -+ tpn->next = (VncNotifyListPtr)NULL; -+ tpn->client = (ClientPtr)NULL; -+ if (!AddResource(faked, VncNotifyList, tpn)) -+ { -+ xfree(tpn); -+ return BadAlloc; -+ } -+ } -+ else -+ { -+ fpn = (VncNotifyListPtr)NULL; -+ tpn = pn; -+ -+ /* FIXME - NEED TO HAVE AN OPTION FOR SINGLE CLIENT ONLY!!! */ -+ -+ while (tpn) -+ { -+ if (tpn->client == client) -+ { -+ if (!onoff) tpn->client = (ClientPtr)NULL; -+ return Success; -+ } -+ if (!tpn->client) fpn = tpn; /* TAKE NOTE OF FREE ENTRY */ -+ tpn = tpn->next; -+ } -+ -+ /* IF TUNNING OFF, THEN JUST RETURN */ -+ -+ if (!onoff) return Success; -+ -+ /* IF ONE ISN'T FOUND THEN ALLOCATE ONE AND LINK IT INTO THE LIST */ -+ -+ if (fpn) -+ { -+ tpn = fpn; -+ } -+ else -+ { -+ if (!(tpn = (VncNotifyListPtr)xalloc(sizeof(VncNotifyListRec)))) -+ return BadAlloc; -+ tpn->next = pn->next; -+ pn->next = tpn; -+ } -+ } -+ -+ /* INIT CLIENT PTR IN CASE WE CAN'T ADD RESOURCE */ -+ /* ADD RESOURCE SO THAT IF CLIENT EXITS THE CLIENT PTR WILL BE CLEARED */ -+ -+ tpn->client = (ClientPtr)NULL; -+ -+ AddResource(faked, VncNotifyList, tpn); -+ -+ tpn->client = client; -+ return Success; -+ -+} -+ -+static int -+VncDestroyNotifyList(pointer pn, XID id) -+{ -+ VncNotifyListPtr cpn = (VncNotifyListPtr) pn; -+ -+ cpn->client = NULL; -+ -+ return Success; -+} -+ -+static Bool -+CreateResourceTypes(void) -+{ -+ if (VncResourceGeneration == serverGeneration) return TRUE; -+ -+ VncResourceGeneration = serverGeneration; -+ -+ if (!(VncNotifyList = CreateNewResourceType(VncDestroyNotifyList))) -+ { -+ ErrorF("CreateResourceTypes: failed to allocate vnc notify list resource.\n"); -+ return FALSE; -+ } -+ -+ return TRUE; -+ -+} -+ -+static unsigned long vncCreateScreenResourcesIndex; -+static unsigned long vncExtGeneration = 0; -+extern Bool VNCInit(ScreenPtr pScreen, unsigned char *FBStart); -+ -+/* copied from miscrinit.c */ -+typedef struct -+{ -+ pointer pbits; /* pointer to framebuffer */ -+ int width; /* delta to add to a framebuffer addr to move one row down */ -+} miScreenInitParmsRec, *miScreenInitParmsPtr; -+ -+#if 0 -+static Bool -+vncCreateScreenResources(ScreenPtr pScreen) -+{ -+ int ret = TRUE; -+ CreateScreenResourcesProcPtr CreateScreenResources = -+ (CreateScreenResourcesProcPtr)(pScreen->devPrivates[vncCreateScreenResourcesIndex].ptr); -+ miScreenInitParmsPtr pScrInitParms; -+ -+ pScrInitParms = (miScreenInitParmsPtr)pScreen->devPrivate; -+ -+ if ( pScreen->CreateScreenResources != vncCreateScreenResources ) { -+ /* Can't find hook we are hung on */ -+ xf86DrvMsg(pScreen->myNum, X_WARNING /* X_ERROR */, -+ "vncCreateScreenResources %p called when not in pScreen->CreateScreenResources %p n", -+ vncCreateScreenResources, pScreen->CreateScreenResources ); -+ } -+ -+ /* Now do our stuff */ -+ VNCInit(pScreen, pScrInitParms->pbits); -+ -+ /* Unhook this function ... */ -+ pScreen->CreateScreenResources = CreateScreenResources; -+ pScreen->devPrivates[vncCreateScreenResourcesIndex].ptr = NULL; -+ -+ /* ... and call the previous CreateScreenResources fuction, if any */ -+ if (NULL!=pScreen->CreateScreenResources) { -+ ret = (*pScreen->CreateScreenResources)(pScreen); -+ } -+ -+#ifdef DEBUG -+ ErrorF("vncCreateScreenResources() returns %d\n", ret); -+#endif -+ return (ret); -+} -+#endif -+ -+void -+VncExtensionInit(void) -+{ -+ ExtensionEntry *extEntry; -+ -+ErrorF("INIT1\n"); -+ if (vncExtGeneration != serverGeneration) { -+ unsigned int i; -+ -+ vncExtGeneration = serverGeneration; -+ -+ if ( ((vncCreateScreenResourcesIndex = AllocateScreenPrivateIndex()) < 0) ) -+ return; -+ -+#if 0 -+ for (i = 0 ; i < screenInfo.numScreens; i++) -+ { -+ screenInfo.screens[i]->devPrivates[vncCreateScreenResourcesIndex].ptr -+ = (void*)(&dmxScreens[i]->pScreen->CreateScreenResources); -+ dmxScreens[i].pScreen->CreateScreenResources = vncCreateScreenResources; -+ } -+#endif -+ -+ gethostname(rfbThisHost, 255); -+ } -+ -+ErrorF("INIT2\n"); -+ if (!CreateResourceTypes()) -+ return; -+ErrorF("INIT3\n"); -+ -+ extEntry = AddExtension(VNC_EXTENSION_NAME, -+ XVncNumberEvents, XVncNumberErrors, -+ ProcVncDispatch, SProcVncDispatch, -+ VncResetProc, StandardMinorOpcode); -+ -+ VncErrorBase = extEntry->errorBase; -+ VncEventBase = extEntry->eventBase; -+ -+ EventSwapVector[VncEventBase + XVncConnected] = -+ (EventSwapPtr)SwapVncConnectedEvent; -+ EventSwapVector[VncEventBase + XVncDisconnected] = -+ (EventSwapPtr)SwapVncDisconnectedEvent; -+#ifdef CHROMIUM -+ EventSwapVector[VncEventBase + XVncChromiumConnected] = -+ (EventSwapPtr)SwapVncChromiumConnectedEvent; -+#endif -+ErrorF("INIT EXT\n"); -+} /* VncExtensionInit */ -diff --git a/hw/dmx/vnc/vncint.h b/hw/dmx/vnc/vncint.h -new file mode 100644 -index 0000000..39728eb ---- /dev/null -+++ b/hw/dmx/vnc/vncint.h -@@ -0,0 +1,154 @@ -+/* -+ * Copyright (C) 2002 Alan Hourihane. 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. -+ * -+ * Author: Alan Hourihane -+ */ -+ -+#ifndef _VNCINT_H_ -+#define _VNCINT_H_ -+ -+#include -+ -+extern int vncScreenPrivateIndex; -+ -+#define VNCPTR(pScreen)\ -+ (vncScreenPtr)((pScreen)->devPrivates[vncScreenPrivateIndex].ptr) -+ -+typedef struct { -+ int rfbPort; -+ int rdpPort; -+ int udpPort; -+ int rfbListenSock; -+ int rdpListenSock; -+ int udpSock; -+ int httpPort; -+ int httpListenSock; -+ int httpSock; -+ char * httpDir; -+ char buf[HTTP_BUF_SIZE]; -+ Bool udpSockConnected; -+ char * rfbAuthPasswdFile; -+ size_t buf_filled; -+ int maxFd; -+ fd_set allFds; -+ unsigned char * oldpfbMemory; -+ Bool useGetImage; -+ Bool rfbAlwaysShared; -+ Bool rfbNeverShared; -+ Bool rfbDontDisconnect; -+ Bool rfbUserAccept; -+ Bool rfbViewOnly; -+ unsigned char * pfbMemory; -+ int paddedWidthInBytes; -+ ColormapPtr rfbInstalledColormap; -+ ColormapPtr savedColormap; -+ rfbPixelFormat rfbServerFormat; -+ Bool rfbAuthTooManyTries; -+ int rfbAuthTries; -+ Bool loginAuthEnabled; -+ struct in_addr interface; -+ OsTimerPtr timer; -+ char updateBuf[UPDATE_BUF_SIZE]; -+ int ublen; -+ int width; -+ int height; -+ int depth; -+ int bitsPerPixel; -+ -+ /* The following two members are used to minimise the amount of unnecessary -+ drawing caused by cursor movement. Whenever any drawing affects the -+ part of the screen where the cursor is, the cursor is removed first and -+ then the drawing is done (this is what the sprite routines test for). -+ Afterwards, however, we do not replace the cursor, even when the cursor -+ is logically being moved across the screen. We only draw the cursor -+ again just as we are about to send the client a framebuffer update. -+ -+ We need to be careful when removing and drawing the cursor because of -+ their relationship with the normal drawing routines. The drawing -+ routines can invoke the cursor routines, but also the cursor routines -+ themselves end up invoking drawing routines. -+ -+ Removing the cursor (rfbSpriteRemoveCursor) is eventually achieved by -+ doing a CopyArea from a pixmap to the screen, where the pixmap contains -+ the saved contents of the screen under the cursor. Before doing this, -+ however, we set cursorIsDrawn to FALSE. Then, when CopyArea is called, -+ it sees that cursorIsDrawn is FALSE and so doesn't feel the need to -+ (recursively!) remove the cursor before doing it. -+ -+ Putting up the cursor (rfbSpriteRestoreCursor) involves a call to -+ PushPixels. While this is happening, cursorIsDrawn must be FALSE so -+ that PushPixels doesn't think it has to remove the cursor first. -+ Obviously cursorIsDrawn is set to TRUE afterwards. -+ -+ Another problem we face is that drawing routines sometimes cause a -+ framebuffer update to be sent to the RFB client. When the RFB client is -+ already waiting for a framebuffer update and some drawing to the -+ framebuffer then happens, the drawing routine sees that the client is -+ ready, so it calls rfbSendFramebufferUpdate. If the cursor is not drawn -+ at this stage, it must be put up, and so rfbSpriteRestoreCursor is -+ called. However, if the original drawing routine was actually called -+ from within rfbSpriteRestoreCursor or rfbSpriteRemoveCursor we don't -+ want this to happen. So both the cursor routines set -+ dontSendFramebufferUpdate to TRUE, and all the drawing routines check -+ this before calling rfbSendFramebufferUpdate. */ -+ -+ Bool cursorIsDrawn; /* TRUE if the cursor is currently drawn */ -+ Bool dontSendFramebufferUpdate; /* TRUE while removing or drawing the -+ cursor */ -+ -+ /* wrapped screen functions */ -+ -+ CloseScreenProcPtr CloseScreen; -+ CreateGCProcPtr CreateGC; -+ PaintWindowBackgroundProcPtr PaintWindowBackground; -+ PaintWindowBorderProcPtr PaintWindowBorder; -+ CopyWindowProcPtr CopyWindow; -+ ClearToBackgroundProcPtr ClearToBackground; -+ RestoreAreasProcPtr RestoreAreas; -+ ScreenWakeupHandlerProcPtr WakeupHandler; -+ InstallColormapProcPtr InstallColormap; -+ UninstallColormapProcPtr UninstallColormap; -+ ListInstalledColormapsProcPtr ListInstalledColormaps; -+ StoreColorsProcPtr StoreColors; -+ DisplayCursorProcPtr DisplayCursor; -+ CursorPtr pCurs; -+ Bool (*UseHWCursor)(ScreenPtr, CursorPtr); -+ Bool (*UseHWCursorARGB)(ScreenPtr, CursorPtr); -+ Bool *SWCursor; -+#ifdef CHROMIUM -+ RealizeWindowProcPtr RealizeWindow; -+ UnrealizeWindowProcPtr UnrealizeWindow; -+ DestroyWindowProcPtr DestroyWindow; -+ ResizeWindowProcPtr ResizeWindow; -+ PositionWindowProcPtr PositionWindow; -+ ClipNotifyProcPtr ClipNotify; -+#endif -+#ifdef RENDER -+ CompositeProcPtr Composite; -+#endif -+ -+} vncScreenRec, *vncScreenPtr; -+ -+extern Bool vncUseHWCursor(ScreenPtr pScreen, CursorPtr pCurs); -+extern Bool vncUseHWCursorARGB(ScreenPtr pScreen, CursorPtr pCurs); -+ -+extern void -+rfbSendChromiumStart(unsigned int ipaddress, unsigned int port); -+ -+#endif /* _VNCINT_H_ */ -+ -diff --git a/hw/dmx/vnc/xistubs.c b/hw/dmx/vnc/xistubs.c -new file mode 100644 -index 0000000..c25f6d9 ---- /dev/null -+++ b/hw/dmx/vnc/xistubs.c -@@ -0,0 +1,319 @@ -+/* $Xorg: stubs.c,v 1.4 2001/02/09 02:04:35 xorgcvs Exp $ */ -+ -+/************************************************************ -+ -+Copyright 1989, 1998 The Open Group -+ -+Permission to use, copy, modify, distribute, and sell this software and its -+documentation for any purpose is hereby granted without fee, provided that -+the above copyright notice appear in all copies and that both that -+copyright notice and this permission notice appear in supporting -+documentation. -+ -+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 -+OPEN GROUP 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 Open Group 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 Open Group. -+ -+Copyright 1989 by Hewlett-Packard Company, Palo Alto, California. -+ -+ All Rights Reserved -+ -+Permission to use, copy, modify, and distribute this software and its -+documentation for any purpose and without fee is hereby granted, -+provided that the above copyright notice appear in all copies and that -+both that copyright notice and this permission notice appear in -+supporting documentation, and that the name of Hewlett-Packard not be -+used in advertising or publicity pertaining to distribution of the -+software without specific, written prior permission. -+ -+HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL -+HEWLETT-PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS -+SOFTWARE. -+ -+********************************************************/ -+/* $XFree86: xc/programs/Xserver/Xi/stubs.c,v 3.3 2001/01/17 22:13:26 dawes Exp $ */ -+ -+/* -+ * stubs.c -- stub routines for the X server side of the XINPUT -+ * extension. This file is mainly to be used only as documentation. -+ * There is not much code here, and you can't get a working XINPUT -+ * server just using this. -+ * The Xvfb server uses this file so it will compile with the same -+ * object files as the real X server for a platform that has XINPUT. -+ * Xnest could do the same thing. -+ */ -+ -+#define NEED_EVENTS -+#include "X11/X.h" -+#include "X11/Xproto.h" -+#include "inputstr.h" -+#include -+#include -+/*#include "XIstubs.h"*/ -+ -+/*********************************************************************** -+ * -+ * Caller: ProcXChangeKeyboardDevice -+ * -+ * This procedure does the implementation-dependent portion of the work -+ * needed to change the keyboard device. -+ * -+ * The X keyboard device has a FocusRec. If the device that has been -+ * made into the new X keyboard did not have a FocusRec, -+ * ProcXChangeKeyboardDevice will allocate one for it. -+ * -+ * If you do not want clients to be able to focus the old X keyboard -+ * device, call DeleteFocusClassDeviceStruct to free the FocusRec. -+ * -+ * If you support input devices with keys that you do not want to be -+ * used as the X keyboard, you need to check for them here and return -+ * a BadDevice error. -+ * -+ * The default implementation is to do nothing (assume you do want -+ * clients to be able to focus the old X keyboard). The commented-out -+ * sample code shows what you might do if you don't want the default. -+ * -+ */ -+ -+int -+ChangeKeyboardDevice (old_dev, new_dev) -+ DeviceIntPtr old_dev; -+ DeviceIntPtr new_dev; -+ { -+ /*********************************************************************** -+ DeleteFocusClassDeviceStruct(old_dev); * defined in xchgptr.c * -+ **********************************************************************/ -+ return BadMatch; -+ } -+ -+ -+/*********************************************************************** -+ * -+ * Caller: ProcXChangePointerDevice -+ * -+ * This procedure does the implementation-dependent portion of the work -+ * needed to change the pointer device. -+ * -+ * The X pointer device does not have a FocusRec. If the device that -+ * has been made into the new X pointer had a FocusRec, -+ * ProcXChangePointerDevice will free it. -+ * -+ * If you want clients to be able to focus the old pointer device that -+ * has now become accessible through the input extension, you need to -+ * add a FocusRec to it here. -+ * -+ * The XChangePointerDevice protocol request also allows the client -+ * to choose which axes of the new pointer device are used to move -+ * the X cursor in the X- and Y- directions. If the axes are different -+ * than the default ones, you need to keep track of that here. -+ * -+ * If you support input devices with valuators that you do not want to be -+ * used as the X pointer, you need to check for them here and return a -+ * BadDevice error. -+ * -+ * The default implementation is to do nothing (assume you don't want -+ * clients to be able to focus the old X pointer). The commented-out -+ * sample code shows what you might do if you don't want the default. -+ * -+ */ -+ -+int -+#if NeedFunctionPrototypes -+ChangePointerDevice ( -+ DeviceIntPtr old_dev, -+ DeviceIntPtr new_dev, -+ unsigned char x, -+ unsigned char y) -+#else -+ChangePointerDevice (old_dev, new_dev, x, y) -+ DeviceIntPtr old_dev, new_dev; -+ unsigned char x, y; -+#endif -+ { -+ /*********************************************************************** -+ InitFocusClassDeviceStruct(old_dev); * allow focusing old ptr* -+ -+ x_axis = x; * keep track of new x-axis* -+ y_axis = y; * keep track of new y-axis* -+ if (x_axis != 0 || y_axis != 1) -+ axes_changed = TRUE; * remember axes have changed* -+ else -+ axes_changed = FALSE; -+ *************************************************************************/ -+ return BadMatch; -+ } -+ -+/*********************************************************************** -+ * -+ * Caller: ProcXCloseDevice -+ * -+ * Take care of implementation-dependent details of closing a device. -+ * Some implementations may actually close the device, others may just -+ * remove this clients interest in that device. -+ * -+ * The default implementation is to do nothing (assume all input devices -+ * are initialized during X server initialization and kept open). -+ * -+ */ -+ -+void -+CloseInputDevice (d, client) -+ DeviceIntPtr d; -+ ClientPtr client; -+ { -+ } -+ -+/*********************************************************************** -+ * -+ * Caller: ProcXListInputDevices -+ * -+ * This is the implementation-dependent routine to initialize an input -+ * device to the point that information about it can be listed. -+ * Some implementations open all input devices when the server is first -+ * initialized, and never close them. Other implementations open only -+ * the X pointer and keyboard devices during server initialization, -+ * and only open other input devices when some client makes an -+ * XOpenDevice request. If some other process has the device open, the -+ * server may not be able to get information about the device to list it. -+ * -+ * This procedure should be used by implementations that do not initialize -+ * all input devices at server startup. It should do device-dependent -+ * initialization for any devices not previously initialized, and call -+ * AddInputDevice for each of those devices so that a DeviceIntRec will be -+ * created for them. -+ * -+ * The default implementation is to do nothing (assume all input devices -+ * are initialized during X server initialization and kept open). -+ * The commented-out sample code shows what you might do if you don't want -+ * the default. -+ * -+ */ -+ -+void -+AddOtherInputDevices () -+ { -+ /********************************************************************** -+ for each uninitialized device, do something like: -+ -+ DeviceIntPtr dev; -+ DeviceProc deviceProc; -+ pointer private; -+ -+ dev = (DeviceIntPtr) AddInputDevice(deviceProc, TRUE); -+ dev->public.devicePrivate = private; -+ RegisterOtherDevice(dev); -+ dev->inited = ((*dev->deviceProc)(dev, DEVICE_INIT) == Success); -+ ************************************************************************/ -+ -+ } -+ -+/*********************************************************************** -+ * -+ * Caller: ProcXOpenDevice -+ * -+ * This is the implementation-dependent routine to open an input device. -+ * Some implementations open all input devices when the server is first -+ * initialized, and never close them. Other implementations open only -+ * the X pointer and keyboard devices during server initialization, -+ * and only open other input devices when some client makes an -+ * XOpenDevice request. This entry point is for the latter type of -+ * implementation. -+ * -+ * If the physical device is not already open, do it here. In this case, -+ * you need to keep track of the fact that one or more clients has the -+ * device open, and physically close it when the last client that has -+ * it open does an XCloseDevice. -+ * -+ * The default implementation is to do nothing (assume all input devices -+ * are opened during X server initialization and kept open). -+ * -+ */ -+ -+void -+OpenInputDevice (dev, client, status) -+ DeviceIntPtr dev; -+ ClientPtr client; -+ int *status; -+ { -+ } -+ -+/**************************************************************************** -+ * -+ * Caller: ProcXSetDeviceMode -+ * -+ * Change the mode of an extension device. -+ * This function is used to change the mode of a device from reporting -+ * relative motion to reporting absolute positional information, and -+ * vice versa. -+ * The default implementation below is that no such devices are supported. -+ * -+ */ -+ -+int -+SetDeviceMode (client, dev, mode) -+ register ClientPtr client; -+ DeviceIntPtr dev; -+ int mode; -+ { -+ return BadMatch; -+ } -+ -+/**************************************************************************** -+ * -+ * Caller: ProcXSetDeviceValuators -+ * -+ * Set the value of valuators on an extension input device. -+ * This function is used to set the initial value of valuators on -+ * those input devices that are capable of reporting either relative -+ * motion or an absolute position, and allow an initial position to be set. -+ * The default implementation below is that no such devices are supported. -+ * -+ */ -+ -+int -+SetDeviceValuators (client, dev, valuators, first_valuator, num_valuators) -+ register ClientPtr client; -+ DeviceIntPtr dev; -+ int *valuators; -+ int first_valuator; -+ int num_valuators; -+ { -+ return BadMatch; -+ } -+ -+/**************************************************************************** -+ * -+ * Caller: ProcXChangeDeviceControl -+ * -+ * Change the specified device controls on an extension input device. -+ * -+ */ -+ -+int -+ChangeDeviceControl (client, dev, control) -+ register ClientPtr client; -+ DeviceIntPtr dev; -+ xDeviceCtl *control; -+ { -+ switch (control->control) -+ { -+ case DEVICE_RESOLUTION: -+ return (BadMatch); -+ default: -+ return (BadMatch); -+ } -+ } -diff --git a/hw/dmx/vnc/zlib.c b/hw/dmx/vnc/zlib.c -new file mode 100644 -index 0000000..edc4467 ---- /dev/null -+++ b/hw/dmx/vnc/zlib.c -@@ -0,0 +1,306 @@ -+/* -+ * zlib.c -+ * -+ * Routines to implement zlib based encoding (deflate). -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ */ -+ -+/* -+ * Copyright (C) 2000 Tridia Corporation. All Rights Reserved. -+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. -+ * -+ * This is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This software is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this software; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -+ * USA. -+ * -+ * For the latest source code, please check: -+ * -+ * http://www.developVNC.org/ -+ * -+ * or send email to feedback@developvnc.org. -+ */ -+ -+#include -+#include -+#include "rfb.h" -+ -+/* -+ * zlibBeforeBuf contains pixel data in the client's format. -+ * zlibAfterBuf contains the zlib (deflated) encoding version. -+ * If the zlib compressed/encoded version is -+ * larger than the raw data or if it exceeds zlibAfterBufSize then -+ * raw encoding is used instead. -+ */ -+ -+static int zlibBeforeBufSize = 0; -+static char *zlibBeforeBuf = NULL; -+ -+static int zlibAfterBufSize = 0; -+static char *zlibAfterBuf = NULL; -+static int zlibAfterBufLen; -+ -+/* -+ * rfbSendOneRectEncodingZlib - send a given rectangle using one Zlib -+ * rectangle encoding. -+ */ -+ -+static Bool -+rfbSendOneRectEncodingZlib(rfbClientPtr cl, int x, int y, int w, int h) -+{ -+ VNCSCREENPTR(cl->pScreen); -+ rfbFramebufferUpdateRectHeader rect; -+ rfbZlibHeader hdr; -+ int deflateResult; -+ int previousOut; -+ int i; -+ unsigned char *fbptr = (pVNC->pfbMemory + (pVNC->paddedWidthInBytes * y) -+ + (x * (pVNC->bitsPerPixel / 8))); -+ -+ int maxRawSize; -+ int maxCompSize; -+ -+ maxRawSize = (pVNC->width * pVNC->height -+ * (cl->format.bitsPerPixel / 8)); -+ -+ if (zlibBeforeBufSize < maxRawSize) { -+ zlibBeforeBufSize = maxRawSize; -+ if (zlibBeforeBuf == NULL) -+ zlibBeforeBuf = (char *)xalloc(zlibBeforeBufSize); -+ else -+ zlibBeforeBuf = (char *)xrealloc(zlibBeforeBuf, zlibBeforeBufSize); -+ } -+ -+ /* zlib compression is not useful for very small data sets. -+ * So, we just send these raw without any compression. -+ */ -+ if (( w * h * (pVNC->bitsPerPixel / 8)) < -+ VNC_ENCODE_ZLIB_MIN_COMP_SIZE ) { -+ -+ int result; -+ -+ /* The translation function (used also by the in raw encoding) -+ * requires 4/2/1 byte alignment in the output buffer (which is -+ * pVNC->updateBuf for the raw encoding) based on the bitsPerPixel of -+ * the viewer/client. This prevents SIGBUS errors on some -+ * architectures like SPARC, PARISC... -+ */ -+ if (( cl->format.bitsPerPixel > 8 ) && -+ ( pVNC->ublen % ( cl->format.bitsPerPixel / 8 )) != 0 ) { -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ } -+ -+ result = rfbSendRectEncodingRaw(cl, x, y, w, h); -+ -+ return result; -+ -+ } -+ -+ /* -+ * zlib requires output buffer to be slightly larger than the input -+ * buffer, in the worst case. -+ */ -+ maxCompSize = maxRawSize + (( maxRawSize + 99 ) / 100 ) + 12; -+ -+ if (zlibAfterBufSize < maxCompSize) { -+ zlibAfterBufSize = maxCompSize; -+ if (zlibAfterBuf == NULL) -+ zlibAfterBuf = (char *)xalloc(zlibAfterBufSize); -+ else -+ zlibAfterBuf = (char *)xrealloc(zlibAfterBuf, zlibAfterBufSize); -+ } -+ -+ /* -+ * Convert pixel data to client format. -+ */ -+ (*cl->translateFn)(cl->pScreen, cl->translateLookupTable, -+ &pVNC->rfbServerFormat, -+ &cl->format, fbptr, zlibBeforeBuf, -+ pVNC->paddedWidthInBytes, w, h, x, y); -+ -+ cl->compStream.next_in = ( Bytef * )zlibBeforeBuf; -+ cl->compStream.avail_in = w * h * (cl->format.bitsPerPixel / 8); -+ cl->compStream.next_out = ( Bytef * )zlibAfterBuf; -+ cl->compStream.avail_out = maxCompSize; -+ cl->compStream.data_type = Z_BINARY; -+ -+ /* Initialize the deflation state. */ -+ if ( cl->compStreamInited == FALSE ) { -+ -+ cl->compStream.total_in = 0; -+ cl->compStream.total_out = 0; -+ cl->compStream.zalloc = Z_NULL; -+ cl->compStream.zfree = Z_NULL; -+ cl->compStream.opaque = Z_NULL; -+ -+ deflateInit2( &(cl->compStream), -+ cl->zlibCompressLevel, -+ Z_DEFLATED, -+ MAX_WBITS, -+ MAX_MEM_LEVEL, -+ Z_DEFAULT_STRATEGY ); -+ /* deflateInit( &(cl->compStream), Z_BEST_COMPRESSION ); */ -+ /* deflateInit( &(cl->compStream), Z_BEST_SPEED ); */ -+ cl->compStreamInited = TRUE; -+ -+ } -+ -+ previousOut = cl->compStream.total_out; -+ -+ /* Perform the compression here. */ -+ deflateResult = deflate( &(cl->compStream), Z_SYNC_FLUSH ); -+ -+ /* Find the total size of the resulting compressed data. */ -+ zlibAfterBufLen = cl->compStream.total_out - previousOut; -+ -+ if ( deflateResult != Z_OK ) { -+ rfbLog("zlib deflation error: %s\n", cl->compStream.msg); -+ return FALSE; -+ } -+ -+ /* Note that it is not possible to switch zlib parameters based on -+ * the results of the compression pass. The reason is -+ * that we rely on the compressor and decompressor states being -+ * in sync. Compressing and then discarding the results would -+ * cause lose of synchronization. -+ */ -+ -+ /* Update statics */ -+ cl->rfbRectanglesSent[rfbEncodingZlib]++; -+ cl->rfbBytesSent[rfbEncodingZlib] += (sz_rfbFramebufferUpdateRectHeader -+ + sz_rfbZlibHeader + zlibAfterBufLen); -+ -+ if (pVNC->ublen + sz_rfbFramebufferUpdateRectHeader + sz_rfbZlibHeader -+ > UPDATE_BUF_SIZE) -+ { -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ } -+ -+ rect.r.x = Swap16IfLE(x); -+ rect.r.y = Swap16IfLE(y); -+ rect.r.w = Swap16IfLE(w); -+ rect.r.h = Swap16IfLE(h); -+ rect.encoding = Swap32IfLE(rfbEncodingZlib); -+ -+ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&rect, -+ sz_rfbFramebufferUpdateRectHeader); -+ pVNC->ublen += sz_rfbFramebufferUpdateRectHeader; -+ -+ hdr.nBytes = Swap32IfLE(zlibAfterBufLen); -+ -+ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&hdr, sz_rfbZlibHeader); -+ pVNC->ublen += sz_rfbZlibHeader; -+ -+ for (i = 0; i < zlibAfterBufLen;) { -+ -+ int bytesToCopy = UPDATE_BUF_SIZE - pVNC->ublen; -+ -+ if (i + bytesToCopy > zlibAfterBufLen) { -+ bytesToCopy = zlibAfterBufLen - i; -+ } -+ -+ memcpy(&pVNC->updateBuf[pVNC->ublen], &zlibAfterBuf[i], bytesToCopy); -+ -+ pVNC->ublen += bytesToCopy; -+ i += bytesToCopy; -+ -+ if (pVNC->ublen == UPDATE_BUF_SIZE) { -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ } -+ } -+ -+ return TRUE; -+ -+} -+ -+ -+/* -+ * rfbSendRectEncodingZlib - send a given rectangle using one or more -+ * Zlib encoding rectangles. -+ */ -+ -+Bool -+rfbSendRectEncodingZlib(rfbClientPtr cl, int x, int y, int w, int h) -+{ -+ VNCSCREENPTR(cl->pScreen); -+ int maxLines; -+ int linesRemaining; -+ rfbRectangle partialRect; -+ -+ partialRect.x = x; -+ partialRect.y = y; -+ partialRect.w = w; -+ partialRect.h = h; -+ -+ /* Determine maximum pixel/scan lines allowed per rectangle. */ -+ maxLines = ( ZLIB_MAX_SIZE(w) / w ); -+ -+ /* Initialize number of scan lines left to do. */ -+ linesRemaining = h; -+ -+ /* Loop until all work is done. */ -+ while ( linesRemaining > 0 ) { -+ -+ int linesToComp; -+ -+ if ( maxLines < linesRemaining ) -+ linesToComp = maxLines; -+ else -+ linesToComp = linesRemaining; -+ -+ partialRect.h = linesToComp; -+ -+ /* Encode (compress) and send the next rectangle. */ -+ if ( ! rfbSendOneRectEncodingZlib( cl, -+ partialRect.x, -+ partialRect.y, -+ partialRect.w, -+ partialRect.h )) { -+ -+ return FALSE; -+ } -+ -+ /* Technically, flushing the buffer here is not extrememly -+ * efficient. However, this improves the overall throughput -+ * of the system over very slow networks. By flushing -+ * the buffer with every maximum size zlib rectangle, we -+ * improve the pipelining usage of the server CPU, network, -+ * and viewer CPU components. Insuring that these components -+ * are working in parallel actually improves the performance -+ * seen by the user. -+ * Since, zlib is most useful for slow networks, this flush -+ * is appropriate for the desired behavior of the zlib encoding. -+ */ -+ if (( pVNC->ublen > 0 ) && -+ ( linesToComp == maxLines )) { -+ if (!rfbSendUpdateBuf(cl)) { -+ -+ return FALSE; -+ } -+ } -+ -+ /* Update remaining and incremental rectangle location. */ -+ linesRemaining -= linesToComp; -+ partialRect.y += linesToComp; -+ -+ } -+ -+ return TRUE; -+ -+} -+ -+ -diff --git a/hw/vnc/LICENCE.TXT b/hw/vnc/LICENCE.TXT -new file mode 100644 -index 0000000..ae3b531 ---- /dev/null -+++ b/hw/vnc/LICENCE.TXT -@@ -0,0 +1,340 @@ -+ GNU GENERAL PUBLIC LICENSE -+ Version 2, June 1991 -+ -+ Copyright (C) 1989, 1991 Free Software Foundation, Inc. -+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA -+ Everyone is permitted to copy and distribute verbatim copies -+ of this license document, but changing it is not allowed. -+ -+ Preamble -+ -+ The licenses for most software are designed to take away your -+freedom to share and change it. By contrast, the GNU General Public -+License is intended to guarantee your freedom to share and change free -+software--to make sure the software is free for all its users. This -+General Public License applies to most of the Free Software -+Foundation's software and to any other program whose authors commit to -+using it. (Some other Free Software Foundation software is covered by -+the GNU Library General Public License instead.) You can apply it to -+your programs, too. -+ -+ When we speak of free software, we are referring to freedom, not -+price. Our General Public Licenses are designed to make sure that you -+have the freedom to distribute copies of free software (and charge for -+this service if you wish), that you receive source code or can get it -+if you want it, that you can change the software or use pieces of it -+in new free programs; and that you know you can do these things. -+ -+ To protect your rights, we need to make restrictions that forbid -+anyone to deny you these rights or to ask you to surrender the rights. -+These restrictions translate to certain responsibilities for you if you -+distribute copies of the software, or if you modify it. -+ -+ For example, if you distribute copies of such a program, whether -+gratis or for a fee, you must give the recipients all the rights that -+you have. You must make sure that they, too, receive or can get the -+source code. And you must show them these terms so they know their -+rights. -+ -+ We protect your rights with two steps: (1) copyright the software, and -+(2) offer you this license which gives you legal permission to copy, -+distribute and/or modify the software. -+ -+ Also, for each author's protection and ours, we want to make certain -+that everyone understands that there is no warranty for this free -+software. If the software is modified by someone else and passed on, we -+want its recipients to know that what they have is not the original, so -+that any problems introduced by others will not reflect on the original -+authors' reputations. -+ -+ Finally, any free program is threatened constantly by software -+patents. We wish to avoid the danger that redistributors of a free -+program will individually obtain patent licenses, in effect making the -+program proprietary. To prevent this, we have made it clear that any -+patent must be licensed for everyone's free use or not licensed at all. -+ -+ The precise terms and conditions for copying, distribution and -+modification follow. -+ -+ GNU GENERAL PUBLIC LICENSE -+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION -+ -+ 0. This License applies to any program or other work which contains -+a notice placed by the copyright holder saying it may be distributed -+under the terms of this General Public License. The "Program", below, -+refers to any such program or work, and a "work based on the Program" -+means either the Program or any derivative work under copyright law: -+that is to say, a work containing the Program or a portion of it, -+either verbatim or with modifications and/or translated into another -+language. (Hereinafter, translation is included without limitation in -+the term "modification".) Each licensee is addressed as "you". -+ -+Activities other than copying, distribution and modification are not -+covered by this License; they are outside its scope. The act of -+running the Program is not restricted, and the output from the Program -+is covered only if its contents constitute a work based on the -+Program (independent of having been made by running the Program). -+Whether that is true depends on what the Program does. -+ -+ 1. You may copy and distribute verbatim copies of the Program's -+source code as you receive it, in any medium, provided that you -+conspicuously and appropriately publish on each copy an appropriate -+copyright notice and disclaimer of warranty; keep intact all the -+notices that refer to this License and to the absence of any warranty; -+and give any other recipients of the Program a copy of this License -+along with the Program. -+ -+You may charge a fee for the physical act of transferring a copy, and -+you may at your option offer warranty protection in exchange for a fee. -+ -+ 2. You may modify your copy or copies of the Program or any portion -+of it, thus forming a work based on the Program, and copy and -+distribute such modifications or work under the terms of Section 1 -+above, provided that you also meet all of these conditions: -+ -+ a) You must cause the modified files to carry prominent notices -+ stating that you changed the files and the date of any change. -+ -+ b) You must cause any work that you distribute or publish, that in -+ whole or in part contains or is derived from the Program or any -+ part thereof, to be licensed as a whole at no charge to all third -+ parties under the terms of this License. -+ -+ c) If the modified program normally reads commands interactively -+ when run, you must cause it, when started running for such -+ interactive use in the most ordinary way, to print or display an -+ announcement including an appropriate copyright notice and a -+ notice that there is no warranty (or else, saying that you provide -+ a warranty) and that users may redistribute the program under -+ these conditions, and telling the user how to view a copy of this -+ License. (Exception: if the Program itself is interactive but -+ does not normally print such an announcement, your work based on -+ the Program is not required to print an announcement.) -+ -+These requirements apply to the modified work as a whole. If -+identifiable sections of that work are not derived from the Program, -+and can be reasonably considered independent and separate works in -+themselves, then this License, and its terms, do not apply to those -+sections when you distribute them as separate works. But when you -+distribute the same sections as part of a whole which is a work based -+on the Program, the distribution of the whole must be on the terms of -+this License, whose permissions for other licensees extend to the -+entire whole, and thus to each and every part regardless of who wrote it. -+ -+Thus, it is not the intent of this section to claim rights or contest -+your rights to work written entirely by you; rather, the intent is to -+exercise the right to control the distribution of derivative or -+collective works based on the Program. -+ -+In addition, mere aggregation of another work not based on the Program -+with the Program (or with a work based on the Program) on a volume of -+a storage or distribution medium does not bring the other work under -+the scope of this License. -+ -+ 3. You may copy and distribute the Program (or a work based on it, -+under Section 2) in object code or executable form under the terms of -+Sections 1 and 2 above provided that you also do one of the following: -+ -+ a) Accompany it with the complete corresponding machine-readable -+ source code, which must be distributed under the terms of Sections -+ 1 and 2 above on a medium customarily used for software interchange; or, -+ -+ b) Accompany it with a written offer, valid for at least three -+ years, to give any third party, for a charge no more than your -+ cost of physically performing source distribution, a complete -+ machine-readable copy of the corresponding source code, to be -+ distributed under the terms of Sections 1 and 2 above on a medium -+ customarily used for software interchange; or, -+ -+ c) Accompany it with the information you received as to the offer -+ to distribute corresponding source code. (This alternative is -+ allowed only for noncommercial distribution and only if you -+ received the program in object code or executable form with such -+ an offer, in accord with Subsection b above.) -+ -+The source code for a work means the preferred form of the work for -+making modifications to it. For an executable work, complete source -+code means all the source code for all modules it contains, plus any -+associated interface definition files, plus the scripts used to -+control compilation and installation of the executable. However, as a -+special exception, the source code distributed need not include -+anything that is normally distributed (in either source or binary -+form) with the major components (compiler, kernel, and so on) of the -+operating system on which the executable runs, unless that component -+itself accompanies the executable. -+ -+If distribution of executable or object code is made by offering -+access to copy from a designated place, then offering equivalent -+access to copy the source code from the same place counts as -+distribution of the source code, even though third parties are not -+compelled to copy the source along with the object code. -+ -+ 4. You may not copy, modify, sublicense, or distribute the Program -+except as expressly provided under this License. Any attempt -+otherwise to copy, modify, sublicense or distribute the Program is -+void, and will automatically terminate your rights under this License. -+However, parties who have received copies, or rights, from you under -+this License will not have their licenses terminated so long as such -+parties remain in full compliance. -+ -+ 5. You are not required to accept this License, since you have not -+signed it. However, nothing else grants you permission to modify or -+distribute the Program or its derivative works. These actions are -+prohibited by law if you do not accept this License. Therefore, by -+modifying or distributing the Program (or any work based on the -+Program), you indicate your acceptance of this License to do so, and -+all its terms and conditions for copying, distributing or modifying -+the Program or works based on it. -+ -+ 6. Each time you redistribute the Program (or any work based on the -+Program), the recipient automatically receives a license from the -+original licensor to copy, distribute or modify the Program subject to -+these terms and conditions. You may not impose any further -+restrictions on the recipients' exercise of the rights granted herein. -+You are not responsible for enforcing compliance by third parties to -+this License. -+ -+ 7. If, as a consequence of a court judgment or allegation of patent -+infringement or for any other reason (not limited to patent issues), -+conditions are imposed on you (whether by court order, agreement or -+otherwise) that contradict the conditions of this License, they do not -+excuse you from the conditions of this License. If you cannot -+distribute so as to satisfy simultaneously your obligations under this -+License and any other pertinent obligations, then as a consequence you -+may not distribute the Program at all. For example, if a patent -+license would not permit royalty-free redistribution of the Program by -+all those who receive copies directly or indirectly through you, then -+the only way you could satisfy both it and this License would be to -+refrain entirely from distribution of the Program. -+ -+If any portion of this section is held invalid or unenforceable under -+any particular circumstance, the balance of the section is intended to -+apply and the section as a whole is intended to apply in other -+circumstances. -+ -+It is not the purpose of this section to induce you to infringe any -+patents or other property right claims or to contest validity of any -+such claims; this section has the sole purpose of protecting the -+integrity of the free software distribution system, which is -+implemented by public license practices. Many people have made -+generous contributions to the wide range of software distributed -+through that system in reliance on consistent application of that -+system; it is up to the author/donor to decide if he or she is willing -+to distribute software through any other system and a licensee cannot -+impose that choice. -+ -+This section is intended to make thoroughly clear what is believed to -+be a consequence of the rest of this License. -+ -+ 8. If the distribution and/or use of the Program is restricted in -+certain countries either by patents or by copyrighted interfaces, the -+original copyright holder who places the Program under this License -+may add an explicit geographical distribution limitation excluding -+those countries, so that distribution is permitted only in or among -+countries not thus excluded. In such case, this License incorporates -+the limitation as if written in the body of this License. -+ -+ 9. The Free Software Foundation may publish revised and/or new versions -+of the General Public License from time to time. Such new versions will -+be similar in spirit to the present version, but may differ in detail to -+address new problems or concerns. -+ -+Each version is given a distinguishing version number. If the Program -+specifies a version number of this License which applies to it and "any -+later version", you have the option of following the terms and conditions -+either of that version or of any later version published by the Free -+Software Foundation. If the Program does not specify a version number of -+this License, you may choose any version ever published by the Free Software -+Foundation. -+ -+ 10. If you wish to incorporate parts of the Program into other free -+programs whose distribution conditions are different, write to the author -+to ask for permission. For software which is copyrighted by the Free -+Software Foundation, write to the Free Software Foundation; we sometimes -+make exceptions for this. Our decision will be guided by the two goals -+of preserving the free status of all derivatives of our free software and -+of promoting the sharing and reuse of software generally. -+ -+ NO WARRANTY -+ -+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -+REPAIR OR CORRECTION. -+ -+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -+POSSIBILITY OF SUCH DAMAGES. -+ -+ END OF TERMS AND CONDITIONS -+ -+ Appendix: How to Apply These Terms to Your New Programs -+ -+ If you develop a new program, and you want it to be of the greatest -+possible use to the public, the best way to achieve this is to make it -+free software which everyone can redistribute and change under these terms. -+ -+ To do so, attach the following notices to the program. It is safest -+to attach them to the start of each source file to most effectively -+convey the exclusion of warranty; and each file should have at least -+the "copyright" line and a pointer to where the full notice is found. -+ -+ -+ Copyright (C) 19yy -+ -+ This program is free software; you can redistribute it and/or modify -+ it under the terms of the GNU General Public License as published by -+ the Free Software Foundation; either version 2 of the License, or -+ (at your option) any later version. -+ -+ This program is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ GNU General Public License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with this program; if not, write to the Free Software -+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -+ USA. -+ -+Also add information on how to contact you by electronic and paper mail. -+ -+If the program is interactive, make it output a short notice like this -+when it starts in an interactive mode: -+ -+ Gnomovision version 69, Copyright (C) 19yy name of author -+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. -+ This is free software, and you are welcome to redistribute it -+ under certain conditions; type `show c' for details. -+ -+The hypothetical commands `show w' and `show c' should show the appropriate -+parts of the General Public License. Of course, the commands you use may -+be called something other than `show w' and `show c'; they could even be -+mouse-clicks or menu items--whatever suits your program. -+ -+You should also get your employer (if you work as a programmer) or your -+school, if any, to sign a "copyright disclaimer" for the program, if -+necessary. Here is a sample; alter the names: -+ -+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program -+ `Gnomovision' (which makes passes at compilers) written by James Hacker. -+ -+ , 1 April 1989 -+ Ty Coon, President of Vice -+ -+This General Public License does not permit incorporating your program into -+proprietary programs. If your program is a subroutine library, you may -+consider it more useful to permit linking proprietary applications with the -+library. If this is what you want to do, use the GNU Library General -+Public License instead of this License. -diff --git a/hw/vnc/Makefile.am b/hw/vnc/Makefile.am -new file mode 100644 -index 0000000..82dca75 ---- /dev/null -+++ b/hw/vnc/Makefile.am -@@ -0,0 +1,54 @@ -+# XXX This Makefile.am probably needs some work. -+ -+bin_PROGRAMS = Xvnc -+ -+Xvnc_SOURCES = \ -+ $(top_srcdir)/fb/fbcmap.c \ -+ $(top_srcdir)/mi/miinitext.c \ -+ auth.c \ -+ cmap.c \ -+ corre.c \ -+ cursor.c \ -+ cutpaste.c \ -+ d3des.c \ -+ dispcur.c \ -+ dpmsstubs.c \ -+ draw.c \ -+ hextile.c \ -+ httpd.c \ -+ init.c \ -+ kbdptr.c \ -+ loginauth.c \ -+ rfbkeyb.c \ -+ rfbmouse.c \ -+ rfbserver.c \ -+ rre.c \ -+ sprite.c \ -+ sockets.c \ -+ stats.c \ -+ tight.c \ -+ translate.c \ -+ $(top_srcdir)/hw/dmx/vnc/vncauth.c \ -+ vncext.c \ -+ xistubs.c \ -+ zlib.c -+ -+ -+JPEG_LIBS = -ljpeg -+CRYPT_LIBS = -lcrypt -+FB_LIBS = ../../fb/.libs/libfb.a -+ -+AM_CFLAGS = $(DIX_CFLAGS) $(XVNC_CFLAGS) -I$(top_srcdir)/hw/dmx/vnc \ -+ -I$(top_srcdir)/mfb -+ -+Xvnc_LDFLAGS = $(LD_EXPORT_SYMBOLS_FLAG) -+Xvnc_LDADD = \ -+ $(XORG_CORE_LIBS) \ -+ $(XVNC_LIBS) \ -+ $(JPEG_LIBS) \ -+ $(CRYPT_LIBS) \ -+ $(VNCMODULES_LIBS) -+ -+ -+relink: -+ rm -f Xvnc && $(MAKE) Xvnc -diff --git a/hw/vnc/README b/hw/vnc/README -new file mode 100644 -index 0000000..d65d560 ---- /dev/null -+++ b/hw/vnc/README -@@ -0,0 +1,14 @@ -+ -+This is the directory containing the code specific to the TightVNC X server (Xvnc). -+Note that within this directory the name RFB is still used instead of VNC. -+ -+NOTE: -+ -+The is the new XFree86 v4 architecture VNC server code. -+ -+Modified entirely by Alan Hourihane -+ -+For information please visit http://xf4vnc.sourceforge.net -+ -+Moved to X.org modular tree by Brian Paul. -+ -diff --git a/hw/vnc/auth.c b/hw/vnc/auth.c -new file mode 100644 -index 0000000..06b6b51 ---- /dev/null -+++ b/hw/vnc/auth.c -@@ -0,0 +1,562 @@ -+/* -+ * auth.c - deal with authentication. -+ * -+ * This file implements authentication when setting up an RFB connection. -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ */ -+ -+/* -+ * Copyright (C) 2003-2004 Constantin Kaplinsky. All Rights Reserved. -+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. -+ * -+ * This is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This software is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this software; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -+ * USA. -+ */ -+ -+#include "rfb.h" -+#include "windowstr.h" -+ -+static void rfbSendSecurityType(rfbClientPtr cl, int securityType); -+static void rfbSendSecurityTypeList(rfbClientPtr cl, int primaryType); -+static void rfbSendTunnelingCaps(rfbClientPtr cl); -+static void rfbSendAuthCaps(rfbClientPtr cl); -+static void rfbVncAuthSendChallenge(rfbClientPtr cl); -+ -+/* -+ * rfbAuthNewClient is called right after negotiating the protocol -+ * version. Depending on the protocol version, we send either a code -+ * for authentication scheme to be used (protocol 3.3), or a list of -+ * possible "security types" (protocol 3.7). -+ */ -+ -+void -+rfbAuthNewClient(cl) -+ rfbClientPtr cl; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ int securityType = rfbSecTypeInvalid; -+ -+ if ((!pVNC->rfbAuthPasswdFile && !pVNC->loginAuthEnabled) || cl->reverseConnection) { -+ securityType = rfbSecTypeNone; -+ } else { -+ if (rfbAuthIsBlocked(cl)) { -+ rfbLog("Too many authentication failures - client rejected\n"); -+ rfbClientConnFailed(cl, "Too many authentication failures"); -+ return; -+ } -+ if (pVNC->rfbAuthPasswdFile) -+ securityType = rfbSecTypeVncAuth; -+ } -+ -+ if (cl->protocol_minor_ver < 7) { -+ /* Make sure we use only RFB 3.3 compatible security types. */ -+ if (securityType == rfbSecTypeInvalid) { -+ rfbLog("VNC authentication disabled - RFB 3.3 client rejected\n"); -+ rfbClientConnFailed(cl, "Your viewer cannot handle required " -+ "authentication methods"); -+ return; -+ } -+ rfbSendSecurityType(cl, securityType); -+ } else { -+ /* Here it's ok when securityType is set to rfbSecTypeInvalid. */ -+ rfbSendSecurityTypeList(cl, securityType); -+ } -+} -+ -+ -+/* -+ * Tell the client what security type will be used (protocol 3.3). -+ */ -+ -+static void -+rfbSendSecurityType(cl, securityType) -+ rfbClientPtr cl; -+ int securityType; -+{ -+ CARD32 value32; -+ -+ /* Send the value. */ -+ value32 = Swap32IfLE(securityType); -+ if (WriteExact(cl->sock, (char *)&value32, 4) < 0) { -+ rfbLogPerror("rfbSendSecurityType: write"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ /* Decide what to do next. */ -+ switch (securityType) { -+ case rfbSecTypeNone: -+ /* Dispatch client input to rfbProcessClientInitMessage. */ -+ cl->state = RFB_INITIALISATION; -+ break; -+ case rfbSecTypeVncAuth: -+ /* Begin the standard VNC authentication procedure. */ -+ rfbVncAuthSendChallenge(cl); -+ break; -+ default: -+ /* Impossible case (hopefully). */ -+ rfbLogPerror("rfbSendSecurityType: assertion failed"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ } -+} -+ -+ -+/* -+ * Advertise our supported security types (protocol 3.7). The list -+ * will include one standard security type (if primaryType is not set -+ * to rfbSecTypeInvalid), and then one more value telling the client -+ * that we support TightVNC protocol extensions. Thus, currently, -+ * there will be either 1 or 2 items in the list. -+ */ -+ -+static void -+rfbSendSecurityTypeList(cl, primaryType) -+ rfbClientPtr cl; -+ int primaryType; -+{ -+ int count = 1; -+ -+ /* Fill in the list of security types in the client structure. */ -+ if (primaryType != rfbSecTypeInvalid) { -+ cl->securityTypes[count++] = (CARD8)primaryType; -+ } -+ cl->securityTypes[count] = (CARD8)rfbSecTypeTight; -+ cl->securityTypes[0] = (CARD8)count++; -+ -+ /* Send the list. */ -+ if (WriteExact(cl->sock, (char *)cl->securityTypes, count) < 0) { -+ rfbLogPerror("rfbSendSecurityTypeList: write"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ /* Dispatch client input to rfbProcessClientSecurityType. */ -+ cl->state = RFB_SECURITY_TYPE; -+} -+ -+ -+/* -+ * Read the security type chosen by the client (protocol 3.7). -+ */ -+ -+void -+rfbProcessClientSecurityType(cl) -+ rfbClientPtr cl; -+{ -+ int n, count, i; -+ CARD8 chosenType; -+ -+ /* Read the security type. */ -+ n = ReadExact(cl->sock, (char *)&chosenType, 1); -+ if (n <= 0) { -+ if (n == 0) -+ rfbLog("rfbProcessClientSecurityType: client gone\n"); -+ else -+ rfbLogPerror("rfbProcessClientSecurityType: read"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ /* Make sure it was present in the list sent by the server. */ -+ count = (int)cl->securityTypes[0]; -+ for (i = 1; i <= count; i++) { -+ if (chosenType == cl->securityTypes[i]) -+ break; -+ } -+ if (i > count) { -+ rfbLog("rfbProcessClientSecurityType: " -+ "wrong security type requested\n"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ /* Now go to the proper authentication procedure. */ -+ switch (chosenType) { -+ case rfbSecTypeNone: -+ /* Dispatch client input to rfbProcessClientInitMessage. */ -+ cl->state = RFB_INITIALISATION; -+ break; -+ case rfbSecTypeVncAuth: -+ /* Begin the standard VNC authentication procedure. */ -+ rfbVncAuthSendChallenge(cl); -+ break; -+ case rfbSecTypeTight: -+ /* We are lucky: the viewer supports TightVNC extensions. */ -+ rfbLog("Enabling TightVNC protocol extensions\n"); -+ /* Switch to the protocol 3.7t. */ -+ cl->protocol_tightvnc = TRUE; -+ /* Advertise our tunneling capabilities. */ -+ rfbSendTunnelingCaps(cl); -+ break; -+ default: -+ /* Impossible case (hopefully). */ -+ rfbLog("rfbProcessClientSecurityType: " -+ "unknown authentication scheme\n"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ } -+} -+ -+ -+/* -+ * Send the list of our tunneling capabilities (protocol 3.7t). -+ */ -+ -+static void -+rfbSendTunnelingCaps(cl) -+ rfbClientPtr cl; -+{ -+ rfbTunnelingCapsMsg caps; -+ CARD32 nTypes = 0; /* we don't support tunneling yet */ -+ -+ caps.nTunnelTypes = Swap32IfLE(nTypes); -+ if (WriteExact(cl->sock, (char *)&caps, sz_rfbTunnelingCapsMsg) < 0) { -+ rfbLogPerror("rfbSendTunnelingCaps: write"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ if (nTypes) { -+ /* Dispatch client input to rfbProcessClientTunnelingType(). */ -+ cl->state = RFB_TUNNELING_TYPE; -+ } else { -+ rfbSendAuthCaps(cl); -+ } -+} -+ -+ -+/* -+ * Read tunneling type requested by the client (protocol 3.7t). -+ * NOTE: Currently, we don't support tunneling, and this function -+ * can never be called. -+ */ -+ -+void -+rfbProcessClientTunnelingType(cl) -+ rfbClientPtr cl; -+{ -+ /* If we were called, then something's really wrong. */ -+ rfbLog("rfbProcessClientTunnelingType: not implemented\n"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+} -+ -+ -+/* -+ * Send the list of our authentication capabilities to the client -+ * (protocol 3.7t). -+ */ -+ -+static void -+rfbSendAuthCaps(cl) -+ rfbClientPtr cl; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ Bool authRequired; -+ rfbAuthenticationCapsMsg caps; -+ rfbCapabilityInfo caplist[MAX_AUTH_CAPS]; -+ int count = 0; -+ -+ authRequired = ((pVNC->rfbAuthPasswdFile != NULL || pVNC->loginAuthEnabled) && -+ !cl->reverseConnection); -+ -+ if (authRequired) { -+ if (pVNC->loginAuthEnabled) { -+ SetCapInfo(&caplist[count], rfbAuthUnixLogin, rfbTightVncVendor); -+ cl->authCaps[count++] = rfbAuthUnixLogin; -+ } -+ if (pVNC->rfbAuthPasswdFile != NULL) { -+ SetCapInfo(&caplist[count], rfbAuthVNC, rfbStandardVendor); -+ cl->authCaps[count++] = rfbAuthVNC; -+ } -+ if (count == 0) { -+ /* Should never happen. */ -+ rfbLog("rfbSendAuthCaps: assertion failed\n"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ } -+ -+ cl->nAuthCaps = count; -+ caps.nAuthTypes = Swap32IfLE((CARD32)count); -+ if (WriteExact(cl->sock, (char *)&caps, sz_rfbAuthenticationCapsMsg) < 0) { -+ rfbLogPerror("rfbSendAuthCaps: write"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ if (count) { -+ if (WriteExact(cl->sock, (char *)&caplist[0], -+ count * sz_rfbCapabilityInfo) < 0) { -+ rfbLogPerror("rfbSendAuthCaps: write"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ /* Dispatch client input to rfbProcessClientAuthType. */ -+ cl->state = RFB_AUTH_TYPE; -+ } else { -+ /* Dispatch client input to rfbProcessClientInitMessage. */ -+ cl->state = RFB_INITIALISATION; -+ } -+} -+ -+ -+/* -+ * Read client's preferred authentication type (protocol 3.7t). -+ */ -+ -+void -+rfbProcessClientAuthType(cl) -+ rfbClientPtr cl; -+{ -+ CARD32 auth_type; -+ int n, i; -+ -+ /* Read authentication type selected by the client. */ -+ n = ReadExact(cl->sock, (char *)&auth_type, sizeof(auth_type)); -+ if (n <= 0) { -+ if (n == 0) -+ rfbLog("rfbProcessClientAuthType: client gone\n"); -+ else -+ rfbLogPerror("rfbProcessClientAuthType: read"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ auth_type = Swap32IfLE(auth_type); -+ -+ /* Make sure it was present in the list sent by the server. */ -+ for (i = 0; i < cl->nAuthCaps; i++) { -+ if (auth_type == cl->authCaps[i]) -+ break; -+ } -+ if (i >= cl->nAuthCaps) { -+ rfbLog("rfbProcessClientAuthType: " -+ "wrong authentication type requested\n"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ switch (auth_type) { -+ case rfbAuthNone: -+ /* Dispatch client input to rfbProcessClientInitMessage. */ -+ cl->state = RFB_INITIALISATION; -+ break; -+ case rfbAuthVNC: -+ rfbVncAuthSendChallenge(cl); -+ break; -+ case rfbAuthUnixLogin: -+ /* FIXME: Do (cl->state = RFB_LOGIN_AUTH) instead? */ -+ rfbLoginAuthProcessClientMessage(cl); -+ break; -+ default: -+ rfbLog("rfbProcessClientAuthType: unknown authentication scheme\n"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ } -+} -+ -+ -+/* -+ * Send the authentication challenge. -+ */ -+ -+static void -+rfbVncAuthSendChallenge(cl) -+ rfbClientPtr cl; -+{ -+ vncRandomBytes(cl->authChallenge); -+ if (WriteExact(cl->sock, (char *)cl->authChallenge, CHALLENGESIZE) < 0) { -+ rfbLogPerror("rfbVncAuthSendChallenge: write"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ /* Dispatch client input to rfbVncAuthProcessResponse. */ -+ cl->state = RFB_AUTHENTICATION; -+} -+ -+/* -+ * rfbVncAuthProcessResponse is called when the client sends its -+ * authentication response. -+ */ -+ -+void -+rfbVncAuthProcessResponse(cl) -+ rfbClientPtr cl; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ char passwdFullControl[9]; -+ char passwdViewOnly[9]; -+ int numPasswords; -+ Bool ok; -+ int n; -+ CARD8 encryptedChallenge1[CHALLENGESIZE]; -+ CARD8 encryptedChallenge2[CHALLENGESIZE]; -+ CARD8 response[CHALLENGESIZE]; -+ CARD32 authResult; -+ -+ n = ReadExact(cl->sock, (char *)response, CHALLENGESIZE); -+ if (n <= 0) { -+ if (n != 0) -+ rfbLogPerror("rfbVncAuthProcessResponse: read"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ numPasswords = vncDecryptPasswdFromFile2(pVNC->rfbAuthPasswdFile, -+ passwdFullControl, -+ passwdViewOnly); -+ if (numPasswords == 0) { -+ rfbLog("rfbVncAuthProcessResponse: could not get password from %s\n", -+ pVNC->rfbAuthPasswdFile); -+ -+ authResult = Swap32IfLE(rfbVncAuthFailed); -+ -+ if (WriteExact(cl->sock, (char *)&authResult, 4) < 0) { -+ rfbLogPerror("rfbVncAuthProcessResponse: write"); -+ } -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ memcpy(encryptedChallenge1, cl->authChallenge, CHALLENGESIZE); -+ vncEncryptBytes(encryptedChallenge1, passwdFullControl); -+ memcpy(encryptedChallenge2, cl->authChallenge, CHALLENGESIZE); -+ vncEncryptBytes(encryptedChallenge2, -+ (numPasswords == 2) ? passwdViewOnly : passwdFullControl); -+ -+ /* Lose the passwords from memory */ -+ memset(passwdFullControl, 0, 9); -+ memset(passwdViewOnly, 0, 9); -+ -+ ok = FALSE; -+ if (memcmp(encryptedChallenge1, response, CHALLENGESIZE) == 0) { -+ rfbLog("Full-control authentication passed by %s\n", cl->host); -+ ok = TRUE; -+ cl->viewOnly = FALSE; -+ } else if (memcmp(encryptedChallenge2, response, CHALLENGESIZE) == 0) { -+ rfbLog("View-only authentication passed by %s\n", cl->host); -+ ok = TRUE; -+ cl->viewOnly = TRUE; -+ } -+ -+ if (!ok) { -+ rfbLog("rfbVncAuthProcessResponse: authentication failed from %s\n", -+ cl->host); -+ -+ if (rfbAuthConsiderBlocking(cl)) { -+ authResult = Swap32IfLE(rfbVncAuthTooMany); -+ } else { -+ authResult = Swap32IfLE(rfbVncAuthFailed); -+ } -+ -+ if (WriteExact(cl->sock, (char *)&authResult, 4) < 0) { -+ rfbLogPerror("rfbVncAuthProcessResponse: write"); -+ } -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ rfbAuthUnblock(cl); -+ -+ authResult = Swap32IfLE(rfbVncAuthOK); -+ -+ if (WriteExact(cl->sock, (char *)&authResult, 4) < 0) { -+ rfbLogPerror("rfbVncAuthProcessResponse: write"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ /* Dispatch client input to rfbProcessClientInitMessage(). */ -+ cl->state = RFB_INITIALISATION; -+} -+ -+ -+/* -+ * Functions to prevent too many successive authentication failures. -+ * FIXME: This should be performed separately per each client IP. -+ */ -+ -+/* Maximum authentication failures before blocking connections */ -+#define MAX_AUTH_TRIES 5 -+ -+/* Delay in ms, doubles for each failure over MAX_AUTH_TRIES */ -+#define AUTH_TOO_MANY_BASE_DELAY 10 * 1000 -+ -+/* -+ * This function should not be called directly, it is called by -+ * setting a timer in rfbAuthConsiderBlocking(). -+ */ -+ -+static CARD32 -+rfbAuthReenable(OsTimerPtr timer, CARD32 now, pointer arg) -+{ -+ rfbClientPtr cl = (rfbClientPtr) arg; -+ VNCSCREENPTR(cl->pScreen); -+ pVNC->rfbAuthTooManyTries = FALSE; -+ return 0; -+} -+ -+/* -+ * This function should be called after each authentication failure. -+ * The return value will be true if there was too many failures. -+ */ -+ -+Bool -+rfbAuthConsiderBlocking(rfbClientPtr cl) -+{ -+ VNCSCREENPTR(cl->pScreen); -+ int i; -+ -+ pVNC->rfbAuthTries++; -+ -+ if (pVNC->rfbAuthTries >= MAX_AUTH_TRIES) { -+ CARD32 delay = AUTH_TOO_MANY_BASE_DELAY; -+ for (i = MAX_AUTH_TRIES; i < pVNC->rfbAuthTries; i++) -+ delay *= 2; -+ pVNC->timer = TimerSet(pVNC->timer, 0, delay, rfbAuthReenable, NULL); -+ pVNC->rfbAuthTooManyTries = TRUE; -+ return TRUE; -+ } -+ -+ return FALSE; -+} -+ -+/* -+ * This function should be called after successful authentication. -+ * It resets the counter of authentication failures. Note that it's -+ * not necessary to clear the rfbAuthTooManyTries flag as it will be -+ * reset by the timer function. -+ */ -+ -+void -+rfbAuthUnblock(rfbClientPtr cl) -+{ -+ VNCSCREENPTR(cl->pScreen); -+ pVNC->rfbAuthTries = 0; -+} -+ -+/* -+ * This function should be called before authentication process. -+ * The return value will be true if there was too many authentication -+ * failures, and the server should not allow another try. -+ */ -+ -+Bool -+rfbAuthIsBlocked(rfbClientPtr cl) -+{ -+ VNCSCREENPTR(cl->pScreen); -+ return pVNC->rfbAuthTooManyTries; -+} -+ -diff --git a/hw/vnc/cmap.c b/hw/vnc/cmap.c -new file mode 100644 -index 0000000..88aad12 ---- /dev/null -+++ b/hw/vnc/cmap.c -@@ -0,0 +1,163 @@ -+/* -+ * cmap.c -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ */ -+ -+/* -+ * 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 "rfb.h" -+ -+int -+rfbListInstalledColormaps(pScreen, pmaps) -+ ScreenPtr pScreen; -+ Colormap *pmaps; -+{ -+ VNCSCREENPTR(pScreen); -+ /* By the time we are processing requests, we can guarantee that there -+ * is always a colormap installed */ -+ if (pVNC->rfbInstalledColormap) -+ *pmaps = pVNC->rfbInstalledColormap->mid; -+ -+#if XFREE86VNC -+ pScreen->ListInstalledColormaps = pVNC->ListInstalledColormaps; -+ (*pScreen->ListInstalledColormaps)(pScreen, pmaps); -+ pScreen->ListInstalledColormaps = rfbListInstalledColormaps; -+#endif -+ -+ return (1); -+} -+ -+ -+void -+rfbInstallColormap(pmap) -+ ColormapPtr pmap; -+{ -+ VNCSCREENPTR(pmap->pScreen); -+ -+ if (pmap != pVNC->rfbInstalledColormap) { -+ -+ if(pVNC->rfbInstalledColormap != (ColormapPtr)None) -+ WalkTree(pmap->pScreen, TellLostMap, -+ (char *)&pVNC->rfbInstalledColormap->mid); -+ /* Install pmap */ -+ pVNC->rfbInstalledColormap = pmap; -+ WalkTree(pmap->pScreen, TellGainedMap, (char *)&pmap->mid); -+ -+ rfbSetClientColourMaps(0, 0); -+ } -+#if XFREE86VNC -+ pmap->pScreen->InstallColormap = pVNC->InstallColormap; -+ (*pmap->pScreen->InstallColormap)(pmap); -+ pmap->pScreen->InstallColormap = rfbInstallColormap; -+#endif -+} -+ -+void -+rfbUninstallColormap(pmap) -+ ColormapPtr pmap; -+{ -+ VNCSCREENPTR(pmap->pScreen); -+ -+ if(pmap == pVNC->rfbInstalledColormap) -+ { -+ if (pmap->mid != pmap->pScreen->defColormap) -+ { -+ pVNC->rfbInstalledColormap = -+ (ColormapPtr) LookupIDByType(pmap->pScreen->defColormap, -+ RT_COLORMAP); -+ (*pmap->pScreen->InstallColormap)(pVNC->rfbInstalledColormap); -+ } -+ } -+#if XFREE86VNC -+ pmap->pScreen->UninstallColormap = pVNC->UninstallColormap; -+ (*pmap->pScreen->UninstallColormap)(pmap); -+ pmap->pScreen->UninstallColormap = rfbUninstallColormap; -+#endif -+} -+ -+ -+/* -+ * rfbStoreColors. We have a set of pixels but they may be in any order. -+ * If some of them happen to be in continuous ascending order then we can -+ * group them together into a single call to rfbSetClientColourMaps. -+ */ -+ -+void -+rfbStoreColors(pmap, ndef, pdefs) -+ ColormapPtr pmap; -+ int ndef; -+ xColorItem *pdefs; -+{ -+ VNCSCREENPTR(pmap->pScreen); -+ int i; -+ int first = -1; -+ int n = 0; -+ -+ if (pmap == pVNC->rfbInstalledColormap) { -+ for (i = 0; i < ndef; i++) { -+ if ((first != -1) && (first + n == pdefs[i].pixel)) { -+ n++; -+ } else { -+ if (first != -1) { -+ rfbSetClientColourMaps(first, n); -+ } -+ first = pdefs[i].pixel; -+ n = 1; -+ } -+ } -+ rfbSetClientColourMaps(first, n); -+ } -+#if XFREE86VNC -+ pmap->pScreen->StoreColors = pVNC->StoreColors; -+ (*pmap->pScreen->StoreColors)(pmap, ndef, pdefs); -+ pmap->pScreen->StoreColors = rfbStoreColors; -+#endif -+} -diff --git a/hw/vnc/corre.c b/hw/vnc/corre.c -new file mode 100644 -index 0000000..f5da8bb ---- /dev/null -+++ b/hw/vnc/corre.c -@@ -0,0 +1,353 @@ -+/* -+ * corre.c -+ * -+ * Routines to implement Compact Rise-and-Run-length Encoding (CoRRE). This -+ * code is based on krw's original javatel rfbserver. -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ */ -+ -+/* -+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. -+ * -+ * This is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This software is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this software; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -+ * USA. -+ */ -+ -+#include -+#include "rfb.h" -+ -+/* -+ * rreBeforeBuf contains pixel data in the client's format. -+ * rreAfterBuf contains the RRE encoded version. If the RRE encoded version is -+ * larger than the raw data or if it exceeds rreAfterBufSize then -+ * raw encoding is used instead. -+ */ -+ -+static int rreBeforeBufSize = 0; -+static char *rreBeforeBuf = NULL; -+ -+static int rreAfterBufSize = 0; -+static char *rreAfterBuf = NULL; -+static int rreAfterBufLen; -+ -+static int subrectEncode8(CARD8 *data, int w, int h); -+static int subrectEncode16(CARD16 *data, int w, int h); -+static int subrectEncode32(CARD32 *data, int w, int h); -+static CARD32 getBgColour(char *data, int size, int bpp); -+static Bool rfbSendSmallRectEncodingCoRRE(rfbClientPtr cl, int x, int y, -+ int w, int h); -+ -+ -+/* -+ * rfbSendRectEncodingCoRRE - send an arbitrary size rectangle using CoRRE -+ * encoding. -+ */ -+ -+Bool -+rfbSendRectEncodingCoRRE(cl, x, y, w, h) -+ rfbClientPtr cl; -+ int x, y, w, h; -+{ -+ if (h > cl->correMaxHeight) { -+ return (rfbSendRectEncodingCoRRE(cl, x, y, w, cl->correMaxHeight) && -+ rfbSendRectEncodingCoRRE(cl, x, y + cl->correMaxHeight, -+ w, h - cl->correMaxHeight)); -+ } -+ -+ if (w > cl->correMaxWidth) { -+ return (rfbSendRectEncodingCoRRE(cl, x, y, cl->correMaxWidth, h) && -+ rfbSendRectEncodingCoRRE(cl, x + cl->correMaxWidth, y, -+ w - cl->correMaxWidth, h)); -+ } -+ -+ return rfbSendSmallRectEncodingCoRRE(cl, x, y, w, h); -+} -+ -+ -+ -+/* -+ * rfbSendSmallRectEncodingCoRRE - send a small (guaranteed < 256x256) -+ * rectangle using CoRRE encoding. -+ */ -+ -+static Bool -+rfbSendSmallRectEncodingCoRRE(cl, x, y, w, h) -+ rfbClientPtr cl; -+ int x, y, w, h; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ rfbFramebufferUpdateRectHeader rect; -+ rfbRREHeader hdr; -+ int nSubrects; -+ int i; -+ unsigned char *fbptr = (pVNC->pfbMemory + (pVNC->paddedWidthInBytes * y) -+ + (x * (pVNC->bitsPerPixel / 8))); -+ -+ int maxRawSize = (pVNC->width * pVNC->height -+ * (cl->format.bitsPerPixel / 8)); -+ -+ if (rreBeforeBufSize < maxRawSize) { -+ rreBeforeBufSize = maxRawSize; -+ if (rreBeforeBuf == NULL) -+ rreBeforeBuf = (char *)xalloc(rreBeforeBufSize); -+ else -+ rreBeforeBuf = (char *)xrealloc(rreBeforeBuf, rreBeforeBufSize); -+ } -+ -+ if (rreAfterBufSize < maxRawSize) { -+ rreAfterBufSize = maxRawSize; -+ if (rreAfterBuf == NULL) -+ rreAfterBuf = (char *)xalloc(rreAfterBufSize); -+ else -+ rreAfterBuf = (char *)xrealloc(rreAfterBuf, rreAfterBufSize); -+ } -+ -+ (*cl->translateFn)(cl->pScreen, cl->translateLookupTable, -+ &pVNC->rfbServerFormat, -+ &cl->format, fbptr, rreBeforeBuf, -+ pVNC->paddedWidthInBytes, w, h, x, y); -+ -+ switch (cl->format.bitsPerPixel) { -+ case 8: -+ nSubrects = subrectEncode8((CARD8 *)rreBeforeBuf, w, h); -+ break; -+ case 16: -+ nSubrects = subrectEncode16((CARD16 *)rreBeforeBuf, w, h); -+ break; -+ case 32: -+ nSubrects = subrectEncode32((CARD32 *)rreBeforeBuf, w, h); -+ break; -+ default: -+ rfbLog("getBgColour: bpp %d?\n",cl->format.bitsPerPixel); -+ exit(1); -+ } -+ -+ if (nSubrects < 0) { -+ -+ /* RRE encoding was too large, use raw */ -+ -+ return rfbSendRectEncodingRaw(cl, x, y, w, h); -+ } -+ -+ cl->rfbRectanglesSent[rfbEncodingCoRRE]++; -+ cl->rfbBytesSent[rfbEncodingCoRRE] += (sz_rfbFramebufferUpdateRectHeader -+ + sz_rfbRREHeader + rreAfterBufLen); -+ -+ if (pVNC->ublen + sz_rfbFramebufferUpdateRectHeader + sz_rfbRREHeader -+ > UPDATE_BUF_SIZE) -+ { -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ } -+ -+ rect.r.x = Swap16IfLE(x); -+ rect.r.y = Swap16IfLE(y); -+ rect.r.w = Swap16IfLE(w); -+ rect.r.h = Swap16IfLE(h); -+ rect.encoding = Swap32IfLE(rfbEncodingCoRRE); -+ -+ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&rect, -+ sz_rfbFramebufferUpdateRectHeader); -+ pVNC->ublen += sz_rfbFramebufferUpdateRectHeader; -+ -+ hdr.nSubrects = Swap32IfLE(nSubrects); -+ -+ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&hdr, sz_rfbRREHeader); -+ pVNC->ublen += sz_rfbRREHeader; -+ -+ for (i = 0; i < rreAfterBufLen;) { -+ -+ int bytesToCopy = UPDATE_BUF_SIZE - pVNC->ublen; -+ -+ if (i + bytesToCopy > rreAfterBufLen) { -+ bytesToCopy = rreAfterBufLen - i; -+ } -+ -+ memcpy(&pVNC->updateBuf[pVNC->ublen], &rreAfterBuf[i], bytesToCopy); -+ -+ pVNC->ublen += bytesToCopy; -+ i += bytesToCopy; -+ -+ if (pVNC->ublen == UPDATE_BUF_SIZE) { -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ } -+ } -+ -+ return TRUE; -+} -+ -+ -+ -+/* -+ * subrectEncode() encodes the given multicoloured rectangle as a background -+ * colour overwritten by single-coloured rectangles. It returns the number -+ * of subrectangles in the encoded buffer, or -1 if subrect encoding won't -+ * fit in the buffer. It puts the encoded rectangles in rreAfterBuf. The -+ * single-colour rectangle partition is not optimal, but does find the biggest -+ * horizontal or vertical rectangle top-left anchored to each consecutive -+ * coordinate position. -+ * -+ * The coding scheme is simply [...] where each -+ * is []. -+ */ -+ -+#define DEFINE_SUBRECT_ENCODE(bpp) \ -+static int \ -+subrectEncode##bpp(data,w,h) \ -+ CARD##bpp *data; \ -+ int w; \ -+ int h; \ -+{ \ -+ CARD##bpp cl; \ -+ rfbCoRRERectangle subrect; \ -+ int x,y; \ -+ int i,j; \ -+ int hx=0,hy,vx=0,vy; \ -+ int hyflag; \ -+ CARD##bpp *seg; \ -+ CARD##bpp *line; \ -+ int hw,hh,vw,vh; \ -+ int thex,they,thew,theh; \ -+ int numsubs = 0; \ -+ int newLen; \ -+ CARD##bpp bg = (CARD##bpp)getBgColour((char*)data,w*h,bpp); \ -+ \ -+ *((CARD##bpp*)rreAfterBuf) = bg; \ -+ \ -+ rreAfterBufLen = (bpp/8); \ -+ \ -+ for (y=0; y 0) && (i >= hx)) {hy += 1;} else {hyflag = 0;} \ -+ } \ -+ vy = j-1; \ -+ \ -+ /* We now have two possible subrects: (x,y,hx,hy) and (x,y,vx,vy) \ -+ * We'll choose the bigger of the two. \ -+ */ \ -+ hw = hx-x+1; \ -+ hh = hy-y+1; \ -+ vw = vx-x+1; \ -+ vh = vy-y+1; \ -+ \ -+ thex = x; \ -+ they = y; \ -+ \ -+ if ((hw*hh) > (vw*vh)) { \ -+ thew = hw; \ -+ theh = hh; \ -+ } else { \ -+ thew = vw; \ -+ theh = vh; \ -+ } \ -+ \ -+ subrect.x = thex; \ -+ subrect.y = they; \ -+ subrect.w = thew; \ -+ subrect.h = theh; \ -+ \ -+ newLen = rreAfterBufLen + (bpp/8) + sz_rfbCoRRERectangle; \ -+ if ((newLen > (w * h * (bpp/8))) || (newLen > rreAfterBufSize)) \ -+ return -1; \ -+ \ -+ numsubs += 1; \ -+ *((CARD##bpp*)(rreAfterBuf + rreAfterBufLen)) = cl; \ -+ rreAfterBufLen += (bpp/8); \ -+ memcpy(&rreAfterBuf[rreAfterBufLen],&subrect,sz_rfbCoRRERectangle); \ -+ rreAfterBufLen += sz_rfbCoRRERectangle; \ -+ \ -+ /* \ -+ * Now mark the subrect as done. \ -+ */ \ -+ for (j=they; j < (they+theh); j++) { \ -+ for (i=thex; i < (thex+thew); i++) { \ -+ data[j*w+i] = bg; \ -+ } \ -+ } \ -+ } \ -+ } \ -+ } \ -+ \ -+ return numsubs; \ -+} -+ -+DEFINE_SUBRECT_ENCODE(8) -+DEFINE_SUBRECT_ENCODE(16) -+DEFINE_SUBRECT_ENCODE(32) -+ -+ -+/* -+ * getBgColour() gets the most prevalent colour in a byte array. -+ */ -+static CARD32 -+getBgColour(data,size,bpp) -+ char *data; -+ int size; -+ int bpp; -+{ -+ -+#define NUMCLRS 256 -+ -+ static int counts[NUMCLRS]; -+ int i,j,k; -+ -+ int maxcount = 0; -+ CARD8 maxclr = 0; -+ -+ if (bpp != 8) { -+ if (bpp == 16) { -+ return ((CARD16 *)data)[0]; -+ } else if (bpp == 32) { -+ return ((CARD32 *)data)[0]; -+ } else { -+ rfbLog("getBgColour: bpp %d?\n",bpp); -+ exit(1); -+ } -+ } -+ -+ for (i=0; i= NUMCLRS) { -+ rfbLog("getBgColour: unusual colour = %d\n", k); -+ exit(1); -+ } -+ counts[k] += 1; -+ if (counts[k] > maxcount) { -+ maxcount = counts[k]; -+ maxclr = ((CARD8 *)data)[j]; -+ } -+ } -+ -+ return maxclr; -+} -diff --git a/hw/vnc/cursor.c b/hw/vnc/cursor.c -new file mode 100644 -index 0000000..d25109c ---- /dev/null -+++ b/hw/vnc/cursor.c -@@ -0,0 +1,404 @@ -+/* -+ * cursor.c - support for cursor shape updates. -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ */ -+ -+/* -+ * Copyright (C) 2000, 2001 Const Kaplinsky. All Rights Reserved. -+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. -+ * -+ * This is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This software is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this software; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -+ * USA. -+ */ -+ -+#include -+#include "rfb.h" -+#include "mipointer.h" -+#include "sprite.h" -+#include "cursorstr.h" -+#include "servermd.h" -+ -+ -+/* Copied from Xvnc/lib/font/util/utilbitmap.c */ -+static unsigned char _reverse_byte[0x100] = { -+ 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 -+}; -+ -+ -+static int EncodeRichCursorData8 (char *buf, rfbPixelFormat *fmt, -+ CursorPtr pCursor); -+static int EncodeRichCursorData16 (ScreenPtr pScreen, -+ char *buf, rfbPixelFormat *fmt, -+ CursorPtr pCursor); -+static int EncodeRichCursorData32 (ScreenPtr pScreen, -+ char *buf, rfbPixelFormat *fmt, -+ CursorPtr pCursor); -+ -+ -+/* -+ * Send cursor shape either in X-style format or in client pixel format. -+ */ -+ -+Bool -+rfbSendCursorShape(cl, pScreen) -+ rfbClientPtr cl; -+ ScreenPtr pScreen; -+{ -+ VNCSCREENPTR(pScreen); -+ CursorPtr pCursor; -+ rfbFramebufferUpdateRectHeader rect; -+ rfbXCursorColors colors; -+ int saved_ublen; -+ int bitmapRowBytes, paddedRowBytes, maskBytes, dataBytes; -+ int i, j; -+ CARD8 *bitmapData; -+ CARD8 bitmapByte; -+ -+ if (cl->useRichCursorEncoding) { -+ rect.encoding = Swap32IfLE(rfbEncodingRichCursor); -+ } else { -+ rect.encoding = Swap32IfLE(rfbEncodingXCursor); -+ } -+ -+#if XFREE86VNC -+ pCursor = pVNC->pCurs; -+#else -+ pCursor = rfbSpriteGetCursorPtr(pScreen); -+#endif -+ -+ /* If there is no cursor, send update with empty cursor data. */ -+ -+ if ( pCursor != NULL && -+ pCursor->bits->width == 1 && -+ pCursor->bits->height == 1 && -+ pCursor->bits->mask[0] == 0 ) { -+ pCursor = NULL; -+ } -+ -+ if (pCursor == NULL) { -+ if (pVNC->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE ) { -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ } -+ rect.r.x = rect.r.y = 0; -+ rect.r.w = rect.r.h = 0; -+ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&rect, -+ sz_rfbFramebufferUpdateRectHeader); -+ pVNC->ublen += sz_rfbFramebufferUpdateRectHeader; -+ -+ cl->rfbCursorShapeBytesSent += sz_rfbFramebufferUpdateRectHeader; -+ cl->rfbCursorShapeUpdatesSent++; -+ -+ return TRUE; -+ } -+ -+ /* Calculate data sizes. */ -+ -+ bitmapRowBytes = (pCursor->bits->width + 7) / 8; -+ paddedRowBytes = PixmapBytePad(pCursor->bits->width, 1); -+ maskBytes = bitmapRowBytes * pCursor->bits->height; -+ dataBytes = (cl->useRichCursorEncoding) ? -+ (pCursor->bits->width * pCursor->bits->height * -+ (cl->format.bitsPerPixel / 8)) : maskBytes; -+ -+ /* Send buffer contents if needed. */ -+ -+ if ( pVNC->ublen + sz_rfbFramebufferUpdateRectHeader + -+ sz_rfbXCursorColors + maskBytes + dataBytes > UPDATE_BUF_SIZE ) { -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ } -+ -+ if ( pVNC->ublen + sz_rfbFramebufferUpdateRectHeader + -+ sz_rfbXCursorColors + maskBytes + dataBytes > UPDATE_BUF_SIZE ) { -+ return FALSE; /* FIXME. */ -+ } -+ -+ saved_ublen = pVNC->ublen; -+ -+ /* Prepare rectangle header. */ -+ -+ rect.r.x = Swap16IfLE(pCursor->bits->xhot); -+ rect.r.y = Swap16IfLE(pCursor->bits->yhot); -+ rect.r.w = Swap16IfLE(pCursor->bits->width); -+ rect.r.h = Swap16IfLE(pCursor->bits->height); -+ -+ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&rect,sz_rfbFramebufferUpdateRectHeader); -+ pVNC->ublen += sz_rfbFramebufferUpdateRectHeader; -+ -+ /* Prepare actual cursor data (depends on encoding used). */ -+ -+ if (!cl->useRichCursorEncoding) { -+ /* XCursor encoding. */ -+ colors.foreRed = (char)(pCursor->foreRed >> 8); -+ colors.foreGreen = (char)(pCursor->foreGreen >> 8); -+ colors.foreBlue = (char)(pCursor->foreBlue >> 8); -+ colors.backRed = (char)(pCursor->backRed >> 8); -+ colors.backGreen = (char)(pCursor->backGreen >> 8); -+ colors.backBlue = (char)(pCursor->backBlue >> 8); -+ -+ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&colors, sz_rfbXCursorColors); -+ pVNC->ublen += sz_rfbXCursorColors; -+ -+ bitmapData = (CARD8 *)pCursor->bits->source; -+ -+ for (i = 0; i < pCursor->bits->height; i++) { -+ for (j = 0; j < bitmapRowBytes; j++) { -+ bitmapByte = bitmapData[i * paddedRowBytes + j]; -+ if (screenInfo.bitmapBitOrder == LSBFirst) { -+ bitmapByte = _reverse_byte[bitmapByte]; -+ } -+ pVNC->updateBuf[pVNC->ublen++] = (char)bitmapByte; -+ } -+ } -+ } else { -+ /* RichCursor encoding. */ -+ switch (cl->format.bitsPerPixel) { -+ case 8: -+ pVNC->ublen += EncodeRichCursorData8(&pVNC->updateBuf[pVNC->ublen], -+ &cl->format, pCursor); -+ break; -+ case 16: -+ pVNC->ublen += EncodeRichCursorData16(pScreen, &pVNC->updateBuf[pVNC->ublen], -+ &cl->format, pCursor); -+ break; -+ case 32: -+ pVNC->ublen += EncodeRichCursorData32(pScreen, &pVNC->updateBuf[pVNC->ublen], -+ &cl->format, pCursor); -+ break; -+ default: -+ return FALSE; -+ } -+ } -+ -+ /* Prepare transparency mask. */ -+ -+ bitmapData = (CARD8 *)pCursor->bits->mask; -+ -+ for (i = 0; i < pCursor->bits->height; i++) { -+ for (j = 0; j < bitmapRowBytes; j++) { -+ bitmapByte = bitmapData[i * paddedRowBytes + j]; -+ if (screenInfo.bitmapBitOrder == LSBFirst) { -+ bitmapByte = _reverse_byte[bitmapByte]; -+ } -+ pVNC->updateBuf[pVNC->ublen++] = (char)bitmapByte; -+ } -+ } -+ -+ /* Update statistics. */ -+ -+ cl->rfbCursorShapeBytesSent += (pVNC->ublen - saved_ublen); -+ cl->rfbCursorShapeUpdatesSent++; -+ -+ return TRUE; -+} -+ -+/* -+ * Send cursor position (PointerPos pseudo-encoding). -+ */ -+Bool -+rfbSendCursorPos(cl, pScreen) -+ rfbClientPtr cl; -+ ScreenPtr pScreen; -+{ -+ VNCSCREENPTR(pScreen); -+ rfbFramebufferUpdateRectHeader rect; -+#if XFREE86VNC -+ ScreenPtr pCursorScreen = miPointerCurrentScreen(); -+#endif -+ int x, y; -+ -+ if (pVNC->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) { -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ } -+ -+#if XFREE86VNC -+ if (pScreen == pCursorScreen) -+ miPointerPosition(&x, &y); -+#else -+ rfbSpriteGetCursorPos(pScreen, &x, &y); -+#endif -+ -+ rect.encoding = Swap32IfLE(rfbEncodingPointerPos); -+ rect.r.x = Swap16IfLE((CARD16)x); -+ rect.r.y = Swap16IfLE((CARD16)y); -+ rect.r.w = 0; -+ rect.r.h = 0; -+ -+ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&rect, -+ sz_rfbFramebufferUpdateRectHeader); -+ pVNC->ublen += sz_rfbFramebufferUpdateRectHeader; -+ -+ cl->rfbCursorPosBytesSent += sz_rfbFramebufferUpdateRectHeader; -+ cl->rfbCursorPosUpdatesSent++; -+ -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ -+ cl->cursorX = x; -+ cl->cursorY = y; -+ -+ return TRUE; -+} -+ -+/* -+ * Code to convert cursor source bitmap to the desired pixel format. -+ */ -+ -+#define RGB48_TO_PIXEL(fmt,r,g,b) \ -+ (((CARD32)(r) * ((fmt)->redMax + 1) >> 16) << (fmt)->redShift | \ -+ ((CARD32)(g) * ((fmt)->greenMax + 1) >> 16) << (fmt)->greenShift | \ -+ ((CARD32)(b) * ((fmt)->blueMax + 1) >> 16) << (fmt)->blueShift) -+ -+static int -+EncodeRichCursorData8(buf, fmt, pCursor) -+ char *buf; -+ rfbPixelFormat *fmt; -+ CursorPtr pCursor; -+{ -+ int widthPixels, widthBytes; -+ int x, y, b; -+ CARD8 *src; -+ char pix[2]; -+ CARD8 bitmapByte; -+ -+ pix[0] = (char)RGB48_TO_PIXEL(fmt, pCursor->backRed, pCursor->backGreen, -+ pCursor->backBlue); -+ pix[1] = (char)RGB48_TO_PIXEL(fmt, pCursor->foreRed, pCursor->foreGreen, -+ pCursor->foreBlue); -+ -+ src = (CARD8 *)pCursor->bits->source; -+ widthPixels = pCursor->bits->width; -+ widthBytes = PixmapBytePad(widthPixels, 1); -+ -+ for (y = 0; y < pCursor->bits->height; y++) { -+ for (x = 0; x < widthPixels / 8; x++) { -+ bitmapByte = src[y * widthBytes + x]; -+ if (screenInfo.bitmapBitOrder == LSBFirst) { -+ bitmapByte = _reverse_byte[bitmapByte]; -+ } -+ for (b = 7; b >= 0; b--) { -+ *buf++ = pix[bitmapByte >> b & 1]; -+ } -+ } -+ if (widthPixels % 8) { -+ bitmapByte = src[y * widthBytes + x]; -+ if (screenInfo.bitmapBitOrder == LSBFirst) { -+ bitmapByte = _reverse_byte[bitmapByte]; -+ } -+ for (b = 7; b > 7 - widthPixels % 8; b--) { -+ *buf++ = pix[bitmapByte >> b & 1]; -+ } -+ } -+ } -+ -+ return (widthPixels * pCursor->bits->height); -+} -+ -+#define DEFINE_RICH_ENCODE(bpp) \ -+ \ -+static int \ -+EncodeRichCursorData##bpp(pScreen, buf, fmt, pCursor) \ -+ ScreenPtr pScreen; \ -+ char *buf; \ -+ rfbPixelFormat *fmt; \ -+ CursorPtr pCursor; \ -+{ \ -+ VNCSCREENPTR(pScreen); \ -+ int widthPixels, widthBytes; \ -+ int x, y, b; \ -+ CARD8 *src; \ -+ CARD##bpp pix[2]; \ -+ CARD8 bitmapByte; \ -+ \ -+ pix[0] = (CARD##bpp)RGB48_TO_PIXEL(fmt, pCursor->backRed, \ -+ pCursor->backGreen, \ -+ pCursor->backBlue); \ -+ pix[1] = (CARD##bpp)RGB48_TO_PIXEL(fmt, pCursor->foreRed, \ -+ pCursor->foreGreen, \ -+ pCursor->foreBlue); \ -+ if (!pVNC->rfbServerFormat.bigEndian != !fmt->bigEndian) { \ -+ pix[0] = Swap##bpp(pix[0]); \ -+ pix[1] = Swap##bpp(pix[1]); \ -+ } \ -+ \ -+ src = (CARD8 *)pCursor->bits->source; \ -+ widthPixels = pCursor->bits->width; \ -+ widthBytes = PixmapBytePad(widthPixels, 1); \ -+ \ -+ for (y = 0; y < pCursor->bits->height; y++) { \ -+ for (x = 0; x < widthPixels / 8; x++) { \ -+ bitmapByte = src[y * widthBytes + x]; \ -+ if (screenInfo.bitmapBitOrder == LSBFirst) { \ -+ bitmapByte = _reverse_byte[bitmapByte]; \ -+ } \ -+ for (b = 7; b >= 0; b--) { \ -+ memcpy (buf, (char *)&pix[bitmapByte >> b & 1], \ -+ sizeof(CARD##bpp)); \ -+ buf += sizeof(CARD##bpp); \ -+ } \ -+ } \ -+ if (widthPixels % 8) { \ -+ bitmapByte = src[y * widthBytes + x]; \ -+ if (screenInfo.bitmapBitOrder == LSBFirst) { \ -+ bitmapByte = _reverse_byte[bitmapByte]; \ -+ } \ -+ for (b = 7; b > 7 - widthPixels % 8; b--) { \ -+ memcpy (buf, (char *)&pix[bitmapByte >> b & 1], \ -+ sizeof(CARD##bpp)); \ -+ buf += sizeof(CARD##bpp); \ -+ } \ -+ } \ -+ } \ -+ \ -+ return (widthPixels * pCursor->bits->height * (bpp / 8)); \ -+} -+ -+DEFINE_RICH_ENCODE(16) -+DEFINE_RICH_ENCODE(32) -+ -diff --git a/hw/vnc/cutpaste.c b/hw/vnc/cutpaste.c -new file mode 100644 -index 0000000..13aebbb ---- /dev/null -+++ b/hw/vnc/cutpaste.c -@@ -0,0 +1,87 @@ -+/* -+ * cutpaste.c - routines to deal with cut & paste buffers / selection. -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ */ -+ -+/* -+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. -+ * -+ * This is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This software is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this software; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -+ * USA. -+ */ -+ -+#include -+#define NEED_EVENTS -+#include -+#include -+#include -+#include "rfb.h" -+#include "selection.h" -+#include "input.h" -+ -+extern Selection *CurrentSelections; -+extern int NumCurrentSelections; -+ -+ -+static Bool inSetXCutText = FALSE; -+ -+/* -+ * rfbSetXCutText sets the cut buffer to be the given string. We also clear -+ * the primary selection. Ideally we'd like to set it to the same thing, but I -+ * can't work out how to do that without some kind of helper X client. -+ */ -+ -+void -+rfbSetXCutText(char *str, int len) -+{ -+ int i = 0; -+ -+ inSetXCutText = TRUE; -+ ChangeWindowProperty(WindowTable[0], XA_CUT_BUFFER0, XA_STRING, -+ 8, PropModeReplace, len, -+ (pointer)str, TRUE); -+ -+ while ((i < NumCurrentSelections) && -+ CurrentSelections[i].selection != XA_PRIMARY) -+ i++; -+ -+ if (i < NumCurrentSelections) { -+ xEvent event; -+ -+ if (CurrentSelections[i].client) { -+ event.u.u.type = SelectionClear; -+ event.u.selectionClear.time = GetTimeInMillis(); -+ event.u.selectionClear.window = CurrentSelections[i].window; -+ event.u.selectionClear.atom = CurrentSelections[i].selection; -+ (void) TryClientEvents (CurrentSelections[i].client, &event, 1, -+ NoEventMask, NoEventMask /* CantBeFiltered */, -+ NullGrab); -+ } -+ -+ CurrentSelections[i].window = None; -+ CurrentSelections[i].pWin = NULL; -+ CurrentSelections[i].client = NullClient; -+ } -+ -+ inSetXCutText = FALSE; -+} -+ -+ -+void rfbGotXCutText(char *str, int len) -+{ -+ if (!inSetXCutText) -+ rfbSendServerCutText(str, len); -+} -diff --git a/hw/vnc/d3des.c b/hw/vnc/d3des.c -new file mode 100644 -index 0000000..9227ddd ---- /dev/null -+++ b/hw/vnc/d3des.c -@@ -0,0 +1,434 @@ -+/* -+ * This is D3DES (V5.09) by Richard Outerbridge with the double and -+ * triple-length support removed for use in VNC. Also the bytebit[] array -+ * has been reversed so that the most significant bit in each byte of the -+ * key is ignored, not the least significant. -+ * -+ * These changes are: -+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. -+ * -+ * This software is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -+ */ -+ -+/* D3DES (V5.09) - -+ * -+ * A portable, public domain, version of the Data Encryption Standard. -+ * -+ * Written with Symantec's THINK (Lightspeed) C by Richard Outerbridge. -+ * Thanks to: Dan Hoey for his excellent Initial and Inverse permutation -+ * code; Jim Gillogly & Phil Karn for the DES key schedule code; Dennis -+ * Ferguson, Eric Young and Dana How for comparing notes; and Ray Lau, -+ * for humouring me on. -+ * -+ * Copyright (c) 1988,1989,1990,1991,1992 by Richard Outerbridge. -+ * (GEnie : OUTER; CIS : [71755,204]) Graven Imagery, 1992. -+ */ -+ -+#include "d3des.h" -+ -+static void scrunch(unsigned char *, unsigned long *); -+static void unscrun(unsigned long *, unsigned char *); -+static void desfunc(unsigned long *, unsigned long *); -+static void cookey(unsigned long *); -+ -+static unsigned long KnL[32] = { 0L }; -+ -+static unsigned short bytebit[8] = { -+ 01, 02, 04, 010, 020, 040, 0100, 0200 }; -+ -+static unsigned long bigbyte[24] = { -+ 0x800000L, 0x400000L, 0x200000L, 0x100000L, -+ 0x80000L, 0x40000L, 0x20000L, 0x10000L, -+ 0x8000L, 0x4000L, 0x2000L, 0x1000L, -+ 0x800L, 0x400L, 0x200L, 0x100L, -+ 0x80L, 0x40L, 0x20L, 0x10L, -+ 0x8L, 0x4L, 0x2L, 0x1L }; -+ -+/* Use the key schedule specified in the Standard (ANSI X3.92-1981). */ -+ -+static unsigned char pc1[56] = { -+ 56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17, -+ 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35, -+ 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21, -+ 13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3 }; -+ -+static unsigned char totrot[16] = { -+ 1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28 }; -+ -+static unsigned char pc2[48] = { -+ 13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9, -+ 22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1, -+ 40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47, -+ 43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31 }; -+ -+void deskey(key, edf) /* Thanks to James Gillogly & Phil Karn! */ -+unsigned char *key; -+int edf; -+{ -+ register int i, j, l, m, n; -+ unsigned char pc1m[56], pcr[56]; -+ unsigned long kn[32]; -+ -+ for ( j = 0; j < 56; j++ ) { -+ l = pc1[j]; -+ m = l & 07; -+ pc1m[j] = (key[l >> 3] & bytebit[m]) ? 1 : 0; -+ } -+ for( i = 0; i < 16; i++ ) { -+ if( edf == DE1 ) m = (15 - i) << 1; -+ else m = i << 1; -+ n = m + 1; -+ kn[m] = kn[n] = 0L; -+ for( j = 0; j < 28; j++ ) { -+ l = j + totrot[i]; -+ if( l < 28 ) pcr[j] = pc1m[l]; -+ else pcr[j] = pc1m[l - 28]; -+ } -+ for( j = 28; j < 56; j++ ) { -+ l = j + totrot[i]; -+ if( l < 56 ) pcr[j] = pc1m[l]; -+ else pcr[j] = pc1m[l - 28]; -+ } -+ for( j = 0; j < 24; j++ ) { -+ if( pcr[pc2[j]] ) kn[m] |= bigbyte[j]; -+ if( pcr[pc2[j+24]] ) kn[n] |= bigbyte[j]; -+ } -+ } -+ cookey(kn); -+ return; -+ } -+ -+static void cookey(raw1) -+register unsigned long *raw1; -+{ -+ register unsigned long *cook, *raw0; -+ unsigned long dough[32]; -+ register int i; -+ -+ cook = dough; -+ for( i = 0; i < 16; i++, raw1++ ) { -+ raw0 = raw1++; -+ *cook = (*raw0 & 0x00fc0000L) << 6; -+ *cook |= (*raw0 & 0x00000fc0L) << 10; -+ *cook |= (*raw1 & 0x00fc0000L) >> 10; -+ *cook++ |= (*raw1 & 0x00000fc0L) >> 6; -+ *cook = (*raw0 & 0x0003f000L) << 12; -+ *cook |= (*raw0 & 0x0000003fL) << 16; -+ *cook |= (*raw1 & 0x0003f000L) >> 4; -+ *cook++ |= (*raw1 & 0x0000003fL); -+ } -+ usekey(dough); -+ return; -+ } -+ -+void cpkey(into) -+register unsigned long *into; -+{ -+ register unsigned long *from, *endp; -+ -+ from = KnL, endp = &KnL[32]; -+ while( from < endp ) *into++ = *from++; -+ return; -+ } -+ -+void usekey(from) -+register unsigned long *from; -+{ -+ register unsigned long *to, *endp; -+ -+ to = KnL, endp = &KnL[32]; -+ while( to < endp ) *to++ = *from++; -+ return; -+ } -+ -+void des(inblock, outblock) -+unsigned char *inblock, *outblock; -+{ -+ unsigned long work[2]; -+ -+ scrunch(inblock, work); -+ desfunc(work, KnL); -+ unscrun(work, outblock); -+ return; -+ } -+ -+static void scrunch(outof, into) -+register unsigned char *outof; -+register unsigned long *into; -+{ -+ *into = (*outof++ & 0xffL) << 24; -+ *into |= (*outof++ & 0xffL) << 16; -+ *into |= (*outof++ & 0xffL) << 8; -+ *into++ |= (*outof++ & 0xffL); -+ *into = (*outof++ & 0xffL) << 24; -+ *into |= (*outof++ & 0xffL) << 16; -+ *into |= (*outof++ & 0xffL) << 8; -+ *into |= (*outof & 0xffL); -+ return; -+ } -+ -+static void unscrun(outof, into) -+register unsigned long *outof; -+register unsigned char *into; -+{ -+ *into++ = (*outof >> 24) & 0xffL; -+ *into++ = (*outof >> 16) & 0xffL; -+ *into++ = (*outof >> 8) & 0xffL; -+ *into++ = *outof++ & 0xffL; -+ *into++ = (*outof >> 24) & 0xffL; -+ *into++ = (*outof >> 16) & 0xffL; -+ *into++ = (*outof >> 8) & 0xffL; -+ *into = *outof & 0xffL; -+ return; -+ } -+ -+static unsigned long SP1[64] = { -+ 0x01010400L, 0x00000000L, 0x00010000L, 0x01010404L, -+ 0x01010004L, 0x00010404L, 0x00000004L, 0x00010000L, -+ 0x00000400L, 0x01010400L, 0x01010404L, 0x00000400L, -+ 0x01000404L, 0x01010004L, 0x01000000L, 0x00000004L, -+ 0x00000404L, 0x01000400L, 0x01000400L, 0x00010400L, -+ 0x00010400L, 0x01010000L, 0x01010000L, 0x01000404L, -+ 0x00010004L, 0x01000004L, 0x01000004L, 0x00010004L, -+ 0x00000000L, 0x00000404L, 0x00010404L, 0x01000000L, -+ 0x00010000L, 0x01010404L, 0x00000004L, 0x01010000L, -+ 0x01010400L, 0x01000000L, 0x01000000L, 0x00000400L, -+ 0x01010004L, 0x00010000L, 0x00010400L, 0x01000004L, -+ 0x00000400L, 0x00000004L, 0x01000404L, 0x00010404L, -+ 0x01010404L, 0x00010004L, 0x01010000L, 0x01000404L, -+ 0x01000004L, 0x00000404L, 0x00010404L, 0x01010400L, -+ 0x00000404L, 0x01000400L, 0x01000400L, 0x00000000L, -+ 0x00010004L, 0x00010400L, 0x00000000L, 0x01010004L }; -+ -+static unsigned long SP2[64] = { -+ 0x80108020L, 0x80008000L, 0x00008000L, 0x00108020L, -+ 0x00100000L, 0x00000020L, 0x80100020L, 0x80008020L, -+ 0x80000020L, 0x80108020L, 0x80108000L, 0x80000000L, -+ 0x80008000L, 0x00100000L, 0x00000020L, 0x80100020L, -+ 0x00108000L, 0x00100020L, 0x80008020L, 0x00000000L, -+ 0x80000000L, 0x00008000L, 0x00108020L, 0x80100000L, -+ 0x00100020L, 0x80000020L, 0x00000000L, 0x00108000L, -+ 0x00008020L, 0x80108000L, 0x80100000L, 0x00008020L, -+ 0x00000000L, 0x00108020L, 0x80100020L, 0x00100000L, -+ 0x80008020L, 0x80100000L, 0x80108000L, 0x00008000L, -+ 0x80100000L, 0x80008000L, 0x00000020L, 0x80108020L, -+ 0x00108020L, 0x00000020L, 0x00008000L, 0x80000000L, -+ 0x00008020L, 0x80108000L, 0x00100000L, 0x80000020L, -+ 0x00100020L, 0x80008020L, 0x80000020L, 0x00100020L, -+ 0x00108000L, 0x00000000L, 0x80008000L, 0x00008020L, -+ 0x80000000L, 0x80100020L, 0x80108020L, 0x00108000L }; -+ -+static unsigned long SP3[64] = { -+ 0x00000208L, 0x08020200L, 0x00000000L, 0x08020008L, -+ 0x08000200L, 0x00000000L, 0x00020208L, 0x08000200L, -+ 0x00020008L, 0x08000008L, 0x08000008L, 0x00020000L, -+ 0x08020208L, 0x00020008L, 0x08020000L, 0x00000208L, -+ 0x08000000L, 0x00000008L, 0x08020200L, 0x00000200L, -+ 0x00020200L, 0x08020000L, 0x08020008L, 0x00020208L, -+ 0x08000208L, 0x00020200L, 0x00020000L, 0x08000208L, -+ 0x00000008L, 0x08020208L, 0x00000200L, 0x08000000L, -+ 0x08020200L, 0x08000000L, 0x00020008L, 0x00000208L, -+ 0x00020000L, 0x08020200L, 0x08000200L, 0x00000000L, -+ 0x00000200L, 0x00020008L, 0x08020208L, 0x08000200L, -+ 0x08000008L, 0x00000200L, 0x00000000L, 0x08020008L, -+ 0x08000208L, 0x00020000L, 0x08000000L, 0x08020208L, -+ 0x00000008L, 0x00020208L, 0x00020200L, 0x08000008L, -+ 0x08020000L, 0x08000208L, 0x00000208L, 0x08020000L, -+ 0x00020208L, 0x00000008L, 0x08020008L, 0x00020200L }; -+ -+static unsigned long SP4[64] = { -+ 0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L, -+ 0x00802080L, 0x00800081L, 0x00800001L, 0x00002001L, -+ 0x00000000L, 0x00802000L, 0x00802000L, 0x00802081L, -+ 0x00000081L, 0x00000000L, 0x00800080L, 0x00800001L, -+ 0x00000001L, 0x00002000L, 0x00800000L, 0x00802001L, -+ 0x00000080L, 0x00800000L, 0x00002001L, 0x00002080L, -+ 0x00800081L, 0x00000001L, 0x00002080L, 0x00800080L, -+ 0x00002000L, 0x00802080L, 0x00802081L, 0x00000081L, -+ 0x00800080L, 0x00800001L, 0x00802000L, 0x00802081L, -+ 0x00000081L, 0x00000000L, 0x00000000L, 0x00802000L, -+ 0x00002080L, 0x00800080L, 0x00800081L, 0x00000001L, -+ 0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L, -+ 0x00802081L, 0x00000081L, 0x00000001L, 0x00002000L, -+ 0x00800001L, 0x00002001L, 0x00802080L, 0x00800081L, -+ 0x00002001L, 0x00002080L, 0x00800000L, 0x00802001L, -+ 0x00000080L, 0x00800000L, 0x00002000L, 0x00802080L }; -+ -+static unsigned long SP5[64] = { -+ 0x00000100L, 0x02080100L, 0x02080000L, 0x42000100L, -+ 0x00080000L, 0x00000100L, 0x40000000L, 0x02080000L, -+ 0x40080100L, 0x00080000L, 0x02000100L, 0x40080100L, -+ 0x42000100L, 0x42080000L, 0x00080100L, 0x40000000L, -+ 0x02000000L, 0x40080000L, 0x40080000L, 0x00000000L, -+ 0x40000100L, 0x42080100L, 0x42080100L, 0x02000100L, -+ 0x42080000L, 0x40000100L, 0x00000000L, 0x42000000L, -+ 0x02080100L, 0x02000000L, 0x42000000L, 0x00080100L, -+ 0x00080000L, 0x42000100L, 0x00000100L, 0x02000000L, -+ 0x40000000L, 0x02080000L, 0x42000100L, 0x40080100L, -+ 0x02000100L, 0x40000000L, 0x42080000L, 0x02080100L, -+ 0x40080100L, 0x00000100L, 0x02000000L, 0x42080000L, -+ 0x42080100L, 0x00080100L, 0x42000000L, 0x42080100L, -+ 0x02080000L, 0x00000000L, 0x40080000L, 0x42000000L, -+ 0x00080100L, 0x02000100L, 0x40000100L, 0x00080000L, -+ 0x00000000L, 0x40080000L, 0x02080100L, 0x40000100L }; -+ -+static unsigned long SP6[64] = { -+ 0x20000010L, 0x20400000L, 0x00004000L, 0x20404010L, -+ 0x20400000L, 0x00000010L, 0x20404010L, 0x00400000L, -+ 0x20004000L, 0x00404010L, 0x00400000L, 0x20000010L, -+ 0x00400010L, 0x20004000L, 0x20000000L, 0x00004010L, -+ 0x00000000L, 0x00400010L, 0x20004010L, 0x00004000L, -+ 0x00404000L, 0x20004010L, 0x00000010L, 0x20400010L, -+ 0x20400010L, 0x00000000L, 0x00404010L, 0x20404000L, -+ 0x00004010L, 0x00404000L, 0x20404000L, 0x20000000L, -+ 0x20004000L, 0x00000010L, 0x20400010L, 0x00404000L, -+ 0x20404010L, 0x00400000L, 0x00004010L, 0x20000010L, -+ 0x00400000L, 0x20004000L, 0x20000000L, 0x00004010L, -+ 0x20000010L, 0x20404010L, 0x00404000L, 0x20400000L, -+ 0x00404010L, 0x20404000L, 0x00000000L, 0x20400010L, -+ 0x00000010L, 0x00004000L, 0x20400000L, 0x00404010L, -+ 0x00004000L, 0x00400010L, 0x20004010L, 0x00000000L, -+ 0x20404000L, 0x20000000L, 0x00400010L, 0x20004010L }; -+ -+static unsigned long SP7[64] = { -+ 0x00200000L, 0x04200002L, 0x04000802L, 0x00000000L, -+ 0x00000800L, 0x04000802L, 0x00200802L, 0x04200800L, -+ 0x04200802L, 0x00200000L, 0x00000000L, 0x04000002L, -+ 0x00000002L, 0x04000000L, 0x04200002L, 0x00000802L, -+ 0x04000800L, 0x00200802L, 0x00200002L, 0x04000800L, -+ 0x04000002L, 0x04200000L, 0x04200800L, 0x00200002L, -+ 0x04200000L, 0x00000800L, 0x00000802L, 0x04200802L, -+ 0x00200800L, 0x00000002L, 0x04000000L, 0x00200800L, -+ 0x04000000L, 0x00200800L, 0x00200000L, 0x04000802L, -+ 0x04000802L, 0x04200002L, 0x04200002L, 0x00000002L, -+ 0x00200002L, 0x04000000L, 0x04000800L, 0x00200000L, -+ 0x04200800L, 0x00000802L, 0x00200802L, 0x04200800L, -+ 0x00000802L, 0x04000002L, 0x04200802L, 0x04200000L, -+ 0x00200800L, 0x00000000L, 0x00000002L, 0x04200802L, -+ 0x00000000L, 0x00200802L, 0x04200000L, 0x00000800L, -+ 0x04000002L, 0x04000800L, 0x00000800L, 0x00200002L }; -+ -+static unsigned long SP8[64] = { -+ 0x10001040L, 0x00001000L, 0x00040000L, 0x10041040L, -+ 0x10000000L, 0x10001040L, 0x00000040L, 0x10000000L, -+ 0x00040040L, 0x10040000L, 0x10041040L, 0x00041000L, -+ 0x10041000L, 0x00041040L, 0x00001000L, 0x00000040L, -+ 0x10040000L, 0x10000040L, 0x10001000L, 0x00001040L, -+ 0x00041000L, 0x00040040L, 0x10040040L, 0x10041000L, -+ 0x00001040L, 0x00000000L, 0x00000000L, 0x10040040L, -+ 0x10000040L, 0x10001000L, 0x00041040L, 0x00040000L, -+ 0x00041040L, 0x00040000L, 0x10041000L, 0x00001000L, -+ 0x00000040L, 0x10040040L, 0x00001000L, 0x00041040L, -+ 0x10001000L, 0x00000040L, 0x10000040L, 0x10040000L, -+ 0x10040040L, 0x10000000L, 0x00040000L, 0x10001040L, -+ 0x00000000L, 0x10041040L, 0x00040040L, 0x10000040L, -+ 0x10040000L, 0x10001000L, 0x10001040L, 0x00000000L, -+ 0x10041040L, 0x00041000L, 0x00041000L, 0x00001040L, -+ 0x00001040L, 0x00040040L, 0x10000000L, 0x10041000L }; -+ -+static void desfunc(block, keys) -+register unsigned long *block, *keys; -+{ -+ register unsigned long fval, work, right, leftt; -+ register int round; -+ -+ leftt = block[0]; -+ right = block[1]; -+ work = ((leftt >> 4) ^ right) & 0x0f0f0f0fL; -+ right ^= work; -+ leftt ^= (work << 4); -+ work = ((leftt >> 16) ^ right) & 0x0000ffffL; -+ right ^= work; -+ leftt ^= (work << 16); -+ work = ((right >> 2) ^ leftt) & 0x33333333L; -+ leftt ^= work; -+ right ^= (work << 2); -+ work = ((right >> 8) ^ leftt) & 0x00ff00ffL; -+ leftt ^= work; -+ right ^= (work << 8); -+ right = ((right << 1) | ((right >> 31) & 1L)) & 0xffffffffL; -+ work = (leftt ^ right) & 0xaaaaaaaaL; -+ leftt ^= work; -+ right ^= work; -+ leftt = ((leftt << 1) | ((leftt >> 31) & 1L)) & 0xffffffffL; -+ -+ for( round = 0; round < 8; round++ ) { -+ work = (right << 28) | (right >> 4); -+ work ^= *keys++; -+ fval = SP7[ work & 0x3fL]; -+ fval |= SP5[(work >> 8) & 0x3fL]; -+ fval |= SP3[(work >> 16) & 0x3fL]; -+ fval |= SP1[(work >> 24) & 0x3fL]; -+ work = right ^ *keys++; -+ fval |= SP8[ work & 0x3fL]; -+ fval |= SP6[(work >> 8) & 0x3fL]; -+ fval |= SP4[(work >> 16) & 0x3fL]; -+ fval |= SP2[(work >> 24) & 0x3fL]; -+ leftt ^= fval; -+ work = (leftt << 28) | (leftt >> 4); -+ work ^= *keys++; -+ fval = SP7[ work & 0x3fL]; -+ fval |= SP5[(work >> 8) & 0x3fL]; -+ fval |= SP3[(work >> 16) & 0x3fL]; -+ fval |= SP1[(work >> 24) & 0x3fL]; -+ work = leftt ^ *keys++; -+ fval |= SP8[ work & 0x3fL]; -+ fval |= SP6[(work >> 8) & 0x3fL]; -+ fval |= SP4[(work >> 16) & 0x3fL]; -+ fval |= SP2[(work >> 24) & 0x3fL]; -+ right ^= fval; -+ } -+ -+ right = (right << 31) | (right >> 1); -+ work = (leftt ^ right) & 0xaaaaaaaaL; -+ leftt ^= work; -+ right ^= work; -+ leftt = (leftt << 31) | (leftt >> 1); -+ work = ((leftt >> 8) ^ right) & 0x00ff00ffL; -+ right ^= work; -+ leftt ^= (work << 8); -+ work = ((leftt >> 2) ^ right) & 0x33333333L; -+ right ^= work; -+ leftt ^= (work << 2); -+ work = ((right >> 16) ^ leftt) & 0x0000ffffL; -+ leftt ^= work; -+ right ^= (work << 16); -+ work = ((right >> 4) ^ leftt) & 0x0f0f0f0fL; -+ leftt ^= work; -+ right ^= (work << 4); -+ *block++ = right; -+ *block = leftt; -+ return; -+ } -+ -+/* Validation sets: -+ * -+ * Single-length key, single-length plaintext - -+ * Key : 0123 4567 89ab cdef -+ * Plain : 0123 4567 89ab cde7 -+ * Cipher : c957 4425 6a5e d31d -+ * -+ * Double-length key, single-length plaintext - -+ * Key : 0123 4567 89ab cdef fedc ba98 7654 3210 -+ * Plain : 0123 4567 89ab cde7 -+ * Cipher : 7f1d 0a77 826b 8aff -+ * -+ * Double-length key, double-length plaintext - -+ * Key : 0123 4567 89ab cdef fedc ba98 7654 3210 -+ * Plain : 0123 4567 89ab cdef 0123 4567 89ab cdff -+ * Cipher : 27a0 8440 406a df60 278f 47cf 42d6 15d7 -+ * -+ * Triple-length key, single-length plaintext - -+ * Key : 0123 4567 89ab cdef fedc ba98 7654 3210 89ab cdef 0123 4567 -+ * Plain : 0123 4567 89ab cde7 -+ * Cipher : de0b 7c06 ae5e 0ed5 -+ * -+ * Triple-length key, double-length plaintext - -+ * Key : 0123 4567 89ab cdef fedc ba98 7654 3210 89ab cdef 0123 4567 -+ * Plain : 0123 4567 89ab cdef 0123 4567 89ab cdff -+ * Cipher : ad0d 1b30 ac17 cf07 0ed1 1c63 81e4 4de5 -+ * -+ * d3des V5.0a rwo 9208.07 18:44 Graven Imagery -+ **********************************************************************/ -diff --git a/hw/vnc/dispcur.c b/hw/vnc/dispcur.c -new file mode 100644 -index 0000000..b278ed2 ---- /dev/null -+++ b/hw/vnc/dispcur.c -@@ -0,0 +1,804 @@ -+/* -+ * dispcur.c -+ * -+ * cursor display routines - based on midispcur.c -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ */ -+ -+/* -+ * 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) 1989 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. -+*/ -+ -+#if HAVE_DIX_CONFIG_H -+#include "dix-config.h" -+#endif -+ -+#define NEED_EVENTS -+# include -+# include "misc.h" -+# include "input.h" -+# include "cursorstr.h" -+# include "windowstr.h" -+# include "regionstr.h" -+# include "dixstruct.h" -+# include "scrnintstr.h" -+# include "servermd.h" -+# include "mipointer.h" -+# include "sprite.h" -+# include "gcstruct.h" -+ -+#ifdef ARGB_CURSOR -+# include "picturestr.h" -+#endif -+ -+/* per-screen private data */ -+ -+static int rfbDCScreenIndex; -+static unsigned long rfbDCGeneration = 0; -+ -+static Bool rfbDCCloseScreen(int index, ScreenPtr pScreen); -+ -+typedef struct { -+ GCPtr pSourceGC, pMaskGC; -+ GCPtr pSaveGC, pRestoreGC; -+ GCPtr pMoveGC; -+ GCPtr pPixSourceGC, pPixMaskGC; -+ CloseScreenProcPtr CloseScreen; -+ PixmapPtr pSave, pTemp; -+#ifdef ARGB_CURSOR -+ PicturePtr pRootPicture; -+ PicturePtr pTempPicture; -+#endif -+} rfbDCScreenRec, *rfbDCScreenPtr; -+ -+/* per-cursor per-screen private data */ -+typedef struct { -+ PixmapPtr sourceBits; /* source bits */ -+ PixmapPtr maskBits; /* mask bits */ -+#ifdef ARGB_CURSOR -+ PicturePtr pPicture; -+#endif -+} rfbDCCursorRec, *rfbDCCursorPtr; -+ -+/* -+ * sprite/cursor method table -+ */ -+ -+static Bool rfbDCRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor); -+static Bool rfbDCUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCursor); -+static Bool rfbDCPutUpCursor(ScreenPtr pScreen, CursorPtr pCursor, -+ int x, int y, unsigned long source, -+ unsigned long mask); -+static Bool rfbDCSaveUnderCursor(ScreenPtr pScreen, int x, int y, -+ int w, int h); -+static Bool rfbDCRestoreUnderCursor(ScreenPtr pScreen, int x, int y, -+ int w, int h); -+static Bool rfbDCMoveCursor(ScreenPtr pScreen, CursorPtr pCursor, -+ int x, int y, int w, int h, int dx, int dy, -+ unsigned long source, unsigned long mask); -+static Bool rfbDCChangeSave(ScreenPtr pScreen, int x, int y, int w, int h, -+ int dx, int dy); -+ -+static rfbSpriteCursorFuncRec rfbDCFuncs = { -+ rfbDCRealizeCursor, -+ rfbDCUnrealizeCursor, -+ rfbDCPutUpCursor, -+ rfbDCSaveUnderCursor, -+ rfbDCRestoreUnderCursor, -+ rfbDCMoveCursor, -+ rfbDCChangeSave, -+}; -+ -+Bool -+rfbDCInitialize (pScreen, screenFuncs) -+ ScreenPtr pScreen; -+ miPointerScreenFuncPtr screenFuncs; -+{ -+ rfbDCScreenPtr pScreenPriv; -+ -+ if (rfbDCGeneration != serverGeneration) -+ { -+ rfbDCScreenIndex = AllocateScreenPrivateIndex (); -+ if (rfbDCScreenIndex < 0) -+ return FALSE; -+ rfbDCGeneration = serverGeneration; -+ } -+ pScreenPriv = (rfbDCScreenPtr) xalloc (sizeof (rfbDCScreenRec)); -+ if (!pScreenPriv) -+ return FALSE; -+ -+ /* -+ * initialize the entire private structure to zeros -+ */ -+ -+ pScreenPriv->pSourceGC = -+ pScreenPriv->pMaskGC = -+ pScreenPriv->pSaveGC = -+ pScreenPriv->pRestoreGC = -+ pScreenPriv->pMoveGC = -+ pScreenPriv->pPixSourceGC = -+ pScreenPriv->pPixMaskGC = NULL; -+#ifdef ARGB_CURSOR -+ pScreenPriv->pRootPicture = NULL; -+ pScreenPriv->pTempPicture = NULL; -+#endif -+ -+ pScreenPriv->pSave = pScreenPriv->pTemp = NULL; -+ -+ pScreenPriv->CloseScreen = pScreen->CloseScreen; -+ pScreen->CloseScreen = rfbDCCloseScreen; -+ -+ pScreen->devPrivates[rfbDCScreenIndex].ptr = (pointer) pScreenPriv; -+ -+ if (!rfbSpriteInitialize (pScreen, &rfbDCFuncs, screenFuncs)) -+ { -+ xfree ((pointer) pScreenPriv); -+ return FALSE; -+ } -+ return TRUE; -+} -+ -+#define tossGC(gc) (gc ? FreeGC (gc, (GContext) 0) : 0) -+#define tossPix(pix) (pix ? (*pScreen->DestroyPixmap) (pix) : TRUE) -+#define tossPict(pict) (pict ? FreePicture (pict, 0) : 0) -+ -+static Bool -+rfbDCCloseScreen (index, pScreen) -+ ScreenPtr pScreen; -+{ -+ rfbDCScreenPtr pScreenPriv; -+ -+ pScreenPriv = (rfbDCScreenPtr) pScreen->devPrivates[rfbDCScreenIndex].ptr; -+ pScreen->CloseScreen = pScreenPriv->CloseScreen; -+ tossGC (pScreenPriv->pSourceGC); -+ tossGC (pScreenPriv->pMaskGC); -+ tossGC (pScreenPriv->pSaveGC); -+ tossGC (pScreenPriv->pRestoreGC); -+ tossGC (pScreenPriv->pMoveGC); -+ tossGC (pScreenPriv->pPixSourceGC); -+ tossGC (pScreenPriv->pPixMaskGC); -+ tossPix (pScreenPriv->pSave); -+ tossPix (pScreenPriv->pTemp); -+#ifdef ARGB_CURSOR -+ tossPict (pScreenPriv->pRootPicture); -+ tossPict (pScreenPriv->pTempPicture); -+#endif -+ xfree ((pointer) pScreenPriv); -+ return (*pScreen->CloseScreen) (index, pScreen); -+} -+ -+static Bool -+rfbDCRealizeCursor (pScreen, pCursor) -+ ScreenPtr pScreen; -+ CursorPtr pCursor; -+{ -+ if (pCursor->bits->refcnt <= 1) -+ pCursor->bits->devPriv[pScreen->myNum] = (pointer)NULL; -+ return TRUE; -+} -+ -+#ifdef ARGB_CURSOR -+#define EnsurePicture(picture,draw,win) (picture || rfbDCMakePicture(&picture,draw,win)) -+ -+static VisualPtr -+rfbDCGetWindowVisual (WindowPtr pWin) -+{ -+ ScreenPtr pScreen = pWin->drawable.pScreen; -+ VisualID vid = wVisual (pWin); -+ int i; -+ -+ for (i = 0; i < pScreen->numVisuals; i++) -+ if (pScreen->visuals[i].vid == vid) -+ return &pScreen->visuals[i]; -+ return 0; -+} -+ -+static PicturePtr -+rfbDCMakePicture (PicturePtr *ppPicture, DrawablePtr pDraw, WindowPtr pWin) -+{ -+ ScreenPtr pScreen = pDraw->pScreen; -+ VisualPtr pVisual; -+ PictFormatPtr pFormat; -+ XID subwindow_mode = IncludeInferiors; -+ PicturePtr pPicture; -+ int error; -+ -+ pVisual = rfbDCGetWindowVisual (pWin); -+ if (!pVisual) -+ return 0; -+ pFormat = PictureMatchVisual (pScreen, pDraw->depth, pVisual); -+ if (!pFormat) -+ return 0; -+ pPicture = CreatePicture (0, pDraw, pFormat, -+ CPSubwindowMode, &subwindow_mode, -+ serverClient, &error); -+ *ppPicture = pPicture; -+ return pPicture; -+} -+#endif -+ -+static rfbDCCursorPtr -+rfbDCRealize (pScreen, pCursor) -+ ScreenPtr pScreen; -+ CursorPtr pCursor; -+{ -+ rfbDCCursorPtr pPriv; -+ GCPtr pGC; -+ XID gcvals[3]; -+ -+ pPriv = (rfbDCCursorPtr) xalloc (sizeof (rfbDCCursorRec)); -+ if (!pPriv) -+ return (rfbDCCursorPtr)NULL; -+#ifdef ARGB_CURSOR -+ if (pCursor->bits->argb) -+ { -+ PixmapPtr pPixmap; -+ PictFormatPtr pFormat; -+ int error; -+ -+ pFormat = PictureMatchFormat (pScreen, 32, PICT_a8r8g8b8); -+ if (!pFormat) -+ { -+ xfree ((pointer) pPriv); -+ return (rfbDCCursorPtr)NULL; -+ } -+ -+ pPriv->sourceBits = 0; -+ pPriv->maskBits = 0; -+ pPixmap = (*pScreen->CreatePixmap) (pScreen, pCursor->bits->width, -+ pCursor->bits->height, 32); -+ if (!pPixmap) -+ { -+ xfree ((pointer) pPriv); -+ return (rfbDCCursorPtr)NULL; -+ } -+ pGC = GetScratchGC (32, pScreen); -+ if (!pGC) -+ { -+ (*pScreen->DestroyPixmap) (pPixmap); -+ xfree ((pointer) pPriv); -+ return (rfbDCCursorPtr)NULL; -+ } -+ ValidateGC (&pPixmap->drawable, pGC); -+ (*pGC->ops->PutImage) (&pPixmap->drawable, pGC, 32, -+ 0, 0, pCursor->bits->width, -+ pCursor->bits->height, -+ 0, ZPixmap, (char *) pCursor->bits->argb); -+ FreeScratchGC (pGC); -+ pPriv->pPicture = CreatePicture (0, &pPixmap->drawable, -+ pFormat, 0, 0, serverClient, &error); -+ (*pScreen->DestroyPixmap) (pPixmap); -+ if (!pPriv->pPicture) -+ { -+ xfree ((pointer) pPriv); -+ return (rfbDCCursorPtr)NULL; -+ } -+ pCursor->bits->devPriv[pScreen->myNum] = (pointer) pPriv; -+ return pPriv; -+ } -+ pPriv->pPicture = 0; -+#endif -+ pPriv->sourceBits = (*pScreen->CreatePixmap) (pScreen, pCursor->bits->width, pCursor->bits->height, 1); -+ if (!pPriv->sourceBits) -+ { -+ xfree ((pointer) pPriv); -+ return (rfbDCCursorPtr)NULL; -+ } -+ pPriv->maskBits = (*pScreen->CreatePixmap) (pScreen, pCursor->bits->width, pCursor->bits->height, 1); -+ if (!pPriv->maskBits) -+ { -+ (*pScreen->DestroyPixmap) (pPriv->sourceBits); -+ xfree ((pointer) pPriv); -+ return (rfbDCCursorPtr)NULL; -+ } -+ pCursor->bits->devPriv[pScreen->myNum] = (pointer) pPriv; -+ -+ /* create the two sets of bits, clipping as appropriate */ -+ -+ pGC = GetScratchGC (1, pScreen); -+ if (!pGC) -+ { -+ (void) rfbDCUnrealizeCursor (pScreen, pCursor); -+ return (rfbDCCursorPtr)NULL; -+ } -+ -+ ValidateGC ((DrawablePtr)pPriv->sourceBits, pGC); -+ (*pGC->ops->PutImage) ((DrawablePtr)pPriv->sourceBits, pGC, 1, -+ 0, 0, pCursor->bits->width, pCursor->bits->height, -+ 0, XYPixmap, (char *)pCursor->bits->source); -+ gcvals[0] = GXand; -+ ChangeGC (pGC, GCFunction, gcvals); -+ ValidateGC ((DrawablePtr)pPriv->sourceBits, pGC); -+ (*pGC->ops->PutImage) ((DrawablePtr)pPriv->sourceBits, pGC, 1, -+ 0, 0, pCursor->bits->width, pCursor->bits->height, -+ 0, XYPixmap, (char *)pCursor->bits->mask); -+ -+ /* mask bits -- pCursor->mask & ~pCursor->source */ -+ gcvals[0] = GXcopy; -+ ChangeGC (pGC, GCFunction, gcvals); -+ ValidateGC ((DrawablePtr)pPriv->maskBits, pGC); -+ (*pGC->ops->PutImage) ((DrawablePtr)pPriv->maskBits, pGC, 1, -+ 0, 0, pCursor->bits->width, pCursor->bits->height, -+ 0, XYPixmap, (char *)pCursor->bits->mask); -+ gcvals[0] = GXandInverted; -+ ChangeGC (pGC, GCFunction, gcvals); -+ ValidateGC ((DrawablePtr)pPriv->maskBits, pGC); -+ (*pGC->ops->PutImage) ((DrawablePtr)pPriv->maskBits, pGC, 1, -+ 0, 0, pCursor->bits->width, pCursor->bits->height, -+ 0, XYPixmap, (char *)pCursor->bits->source); -+ FreeScratchGC (pGC); -+ return pPriv; -+} -+ -+static Bool -+rfbDCUnrealizeCursor (pScreen, pCursor) -+ ScreenPtr pScreen; -+ CursorPtr pCursor; -+{ -+ rfbDCCursorPtr pPriv; -+ -+ pPriv = (rfbDCCursorPtr) pCursor->bits->devPriv[pScreen->myNum]; -+ if (pPriv && (pCursor->bits->refcnt <= 1)) -+ { -+ if (pPriv->sourceBits) -+ (*pScreen->DestroyPixmap) (pPriv->sourceBits); -+ if (pPriv->maskBits) -+ (*pScreen->DestroyPixmap) (pPriv->maskBits); -+#ifdef ARGB_CURSOR -+ if (pPriv->pPicture) -+ FreePicture (pPriv->pPicture, 0); -+#endif -+ xfree ((pointer) pPriv); -+ pCursor->bits->devPriv[pScreen->myNum] = (pointer)NULL; -+ } -+ return TRUE; -+} -+ -+static void -+rfbDCPutBits (pDrawable, pPriv, sourceGC, maskGC, x, y, w, h, source, mask) -+ DrawablePtr pDrawable; -+ GCPtr sourceGC, maskGC; -+ int x, y; -+ unsigned w, h; -+ rfbDCCursorPtr pPriv; -+ unsigned long source, mask; -+{ -+ XID gcvals[1]; -+ -+ if (sourceGC->fgPixel != source) -+ { -+ gcvals[0] = source; -+ DoChangeGC (sourceGC, GCForeground, gcvals, 0); -+ } -+ if (sourceGC->serialNumber != pDrawable->serialNumber) -+ ValidateGC (pDrawable, sourceGC); -+ (*sourceGC->ops->PushPixels) (sourceGC, pPriv->sourceBits, pDrawable, w, h, x, y); -+ if (maskGC->fgPixel != mask) -+ { -+ gcvals[0] = mask; -+ DoChangeGC (maskGC, GCForeground, gcvals, 0); -+ } -+ if (maskGC->serialNumber != pDrawable->serialNumber) -+ ValidateGC (pDrawable, maskGC); -+ (*maskGC->ops->PushPixels) (maskGC, pPriv->maskBits, pDrawable, w, h, x, y); -+} -+ -+#define EnsureGC(gc,win) (gc || rfbDCMakeGC(&gc, win)) -+ -+static GCPtr -+rfbDCMakeGC(ppGC, pWin) -+ GCPtr *ppGC; -+ WindowPtr pWin; -+{ -+ GCPtr pGC; -+ int status; -+ XID gcvals[2]; -+ -+ gcvals[0] = IncludeInferiors; -+ gcvals[1] = FALSE; -+ pGC = CreateGC((DrawablePtr)pWin, -+ GCSubwindowMode|GCGraphicsExposures, gcvals, &status); -+ if (pGC && pWin->drawable.pScreen->DrawGuarantee) -+ (*pWin->drawable.pScreen->DrawGuarantee) (pWin, pGC, GuaranteeVisBack); -+ *ppGC = pGC; -+ return pGC; -+} -+ -+static Bool -+rfbDCPutUpCursor (pScreen, pCursor, x, y, source, mask) -+ ScreenPtr pScreen; -+ CursorPtr pCursor; -+ int x, y; -+ unsigned long source, mask; -+{ -+ rfbDCScreenPtr pScreenPriv; -+ rfbDCCursorPtr pPriv; -+ WindowPtr pWin; -+ -+ pPriv = (rfbDCCursorPtr) pCursor->bits->devPriv[pScreen->myNum]; -+ if (!pPriv) -+ { -+ pPriv = rfbDCRealize(pScreen, pCursor); -+ if (!pPriv) -+ return FALSE; -+ } -+ pScreenPriv = (rfbDCScreenPtr) pScreen->devPrivates[rfbDCScreenIndex].ptr; -+ pWin = WindowTable[pScreen->myNum]; -+#ifdef ARGB_CURSOR -+ if (pPriv->pPicture) -+ { -+ if (!EnsurePicture(pScreenPriv->pRootPicture, &pWin->drawable, pWin)) -+ return FALSE; -+ CompositePicture (PictOpOver, -+ pPriv->pPicture, -+ NULL, -+ pScreenPriv->pRootPicture, -+ 0, 0, 0, 0, -+ x, y, -+ pCursor->bits->width, -+ pCursor->bits->height); -+ } -+ else -+#endif -+ { -+ if (!EnsureGC(pScreenPriv->pSourceGC, pWin)) -+ return FALSE; -+ if (!EnsureGC(pScreenPriv->pMaskGC, pWin)) -+ { -+ FreeGC (pScreenPriv->pSourceGC, (GContext) 0); -+ pScreenPriv->pSourceGC = 0; -+ return FALSE; -+ } -+ rfbDCPutBits ((DrawablePtr)pWin, pPriv, -+ pScreenPriv->pSourceGC, pScreenPriv->pMaskGC, -+ x, y, pCursor->bits->width, pCursor->bits->height, -+ source, mask); -+ } -+ return TRUE; -+} -+ -+static Bool -+rfbDCSaveUnderCursor (pScreen, x, y, w, h) -+ ScreenPtr pScreen; -+ int x, y, w, h; -+{ -+ rfbDCScreenPtr pScreenPriv; -+ PixmapPtr pSave; -+ WindowPtr pWin; -+ GCPtr pGC; -+ -+ pScreenPriv = (rfbDCScreenPtr) pScreen->devPrivates[rfbDCScreenIndex].ptr; -+ pSave = pScreenPriv->pSave; -+ pWin = WindowTable[pScreen->myNum]; -+ if (!pSave || pSave->drawable.width < w || pSave->drawable.height < h) -+ { -+ if (pSave) -+ (*pScreen->DestroyPixmap) (pSave); -+ pScreenPriv->pSave = pSave = -+ (*pScreen->CreatePixmap) (pScreen, w, h, pScreen->rootDepth); -+ if (!pSave) -+ return FALSE; -+ } -+ if (!EnsureGC(pScreenPriv->pSaveGC, pWin)) -+ return FALSE; -+ pGC = pScreenPriv->pSaveGC; -+ if (pSave->drawable.serialNumber != pGC->serialNumber) -+ ValidateGC ((DrawablePtr) pSave, pGC); -+ (*pGC->ops->CopyArea) ((DrawablePtr) pWin, (DrawablePtr) pSave, pGC, -+ x, y, w, h, 0, 0); -+ return TRUE; -+} -+ -+static Bool -+rfbDCRestoreUnderCursor (pScreen, x, y, w, h) -+ ScreenPtr pScreen; -+ int x, y, w, h; -+{ -+ rfbDCScreenPtr pScreenPriv; -+ PixmapPtr pSave; -+ WindowPtr pWin; -+ GCPtr pGC; -+ -+ pScreenPriv = (rfbDCScreenPtr) pScreen->devPrivates[rfbDCScreenIndex].ptr; -+ pSave = pScreenPriv->pSave; -+ pWin = WindowTable[pScreen->myNum]; -+ if (!pSave) -+ return FALSE; -+ if (!EnsureGC(pScreenPriv->pRestoreGC, pWin)) -+ return FALSE; -+ pGC = pScreenPriv->pRestoreGC; -+ if (pWin->drawable.serialNumber != pGC->serialNumber) -+ ValidateGC ((DrawablePtr) pWin, pGC); -+ (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC, -+ 0, 0, w, h, x, y); -+ return TRUE; -+} -+ -+static Bool -+rfbDCChangeSave (pScreen, x, y, w, h, dx, dy) -+ ScreenPtr pScreen; -+ int x, y, w, h, dx, dy; -+{ -+ rfbDCScreenPtr pScreenPriv; -+ PixmapPtr pSave; -+ WindowPtr pWin; -+ GCPtr pGC; -+ int sourcex, sourcey, destx, desty, copyw, copyh; -+ -+ pScreenPriv = (rfbDCScreenPtr) pScreen->devPrivates[rfbDCScreenIndex].ptr; -+ pSave = pScreenPriv->pSave; -+ pWin = WindowTable[pScreen->myNum]; -+ /* -+ * restore the bits which are about to get trashed -+ */ -+ if (!pSave) -+ return FALSE; -+ if (!EnsureGC(pScreenPriv->pRestoreGC, pWin)) -+ return FALSE; -+ pGC = pScreenPriv->pRestoreGC; -+ if (pWin->drawable.serialNumber != pGC->serialNumber) -+ ValidateGC ((DrawablePtr) pWin, pGC); -+ /* -+ * copy the old bits to the screen. -+ */ -+ if (dy > 0) -+ { -+ (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC, -+ 0, h - dy, w, dy, x + dx, y + h); -+ } -+ else if (dy < 0) -+ { -+ (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC, -+ 0, 0, w, -dy, x + dx, y + dy); -+ } -+ if (dy >= 0) -+ { -+ desty = y + dy; -+ sourcey = 0; -+ copyh = h - dy; -+ } -+ else -+ { -+ desty = y; -+ sourcey = - dy; -+ copyh = h + dy; -+ } -+ if (dx > 0) -+ { -+ (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC, -+ w - dx, sourcey, dx, copyh, x + w, desty); -+ } -+ else if (dx < 0) -+ { -+ (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC, -+ 0, sourcey, -dx, copyh, x + dx, desty); -+ } -+ if (!EnsureGC(pScreenPriv->pSaveGC, pWin)) -+ return FALSE; -+ pGC = pScreenPriv->pSaveGC; -+ if (pSave->drawable.serialNumber != pGC->serialNumber) -+ ValidateGC ((DrawablePtr) pSave, pGC); -+ /* -+ * move the bits that are still valid within the pixmap -+ */ -+ if (dx >= 0) -+ { -+ sourcex = 0; -+ destx = dx; -+ copyw = w - dx; -+ } -+ else -+ { -+ destx = 0; -+ sourcex = - dx; -+ copyw = w + dx; -+ } -+ if (dy >= 0) -+ { -+ sourcey = 0; -+ desty = dy; -+ copyh = h - dy; -+ } -+ else -+ { -+ desty = 0; -+ sourcey = -dy; -+ copyh = h + dy; -+ } -+ (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pSave, pGC, -+ sourcex, sourcey, copyw, copyh, destx, desty); -+ /* -+ * copy the new bits from the screen into the remaining areas of the -+ * pixmap -+ */ -+ if (dy > 0) -+ { -+ (*pGC->ops->CopyArea) ((DrawablePtr) pWin, (DrawablePtr) pSave, pGC, -+ x, y, w, dy, 0, 0); -+ } -+ else if (dy < 0) -+ { -+ (*pGC->ops->CopyArea) ((DrawablePtr) pWin, (DrawablePtr) pSave, pGC, -+ x, y + h + dy, w, -dy, 0, h + dy); -+ } -+ if (dy >= 0) -+ { -+ desty = dy; -+ sourcey = y + dy; -+ copyh = h - dy; -+ } -+ else -+ { -+ desty = 0; -+ sourcey = y; -+ copyh = h + dy; -+ } -+ if (dx > 0) -+ { -+ (*pGC->ops->CopyArea) ((DrawablePtr) pWin, (DrawablePtr) pSave, pGC, -+ x, sourcey, dx, copyh, 0, desty); -+ } -+ else if (dx < 0) -+ { -+ (*pGC->ops->CopyArea) ((DrawablePtr) pWin, (DrawablePtr) pSave, pGC, -+ x + w + dx, sourcey, -dx, copyh, w + dx, desty); -+ } -+ return TRUE; -+} -+ -+static Bool -+rfbDCMoveCursor (pScreen, pCursor, x, y, w, h, dx, dy, source, mask) -+ ScreenPtr pScreen; -+ CursorPtr pCursor; -+ int x, y, w, h, dx, dy; -+ unsigned long source, mask; -+{ -+ rfbDCCursorPtr pPriv; -+ rfbDCScreenPtr pScreenPriv; -+ int status; -+ WindowPtr pWin; -+ GCPtr pGC; -+ XID gcval = FALSE; -+ PixmapPtr pTemp; -+ -+ pPriv = (rfbDCCursorPtr) pCursor->bits->devPriv[pScreen->myNum]; -+ if (!pPriv) -+ { -+ pPriv = rfbDCRealize(pScreen, pCursor); -+ if (!pPriv) -+ return FALSE; -+ } -+ pScreenPriv = (rfbDCScreenPtr) pScreen->devPrivates[rfbDCScreenIndex].ptr; -+ pWin = WindowTable[pScreen->myNum]; -+ pTemp = pScreenPriv->pTemp; -+ if (!pTemp || -+ pTemp->drawable.width != pScreenPriv->pSave->drawable.width || -+ pTemp->drawable.height != pScreenPriv->pSave->drawable.height) -+ { -+ if (pTemp) -+ (*pScreen->DestroyPixmap) (pTemp); -+#ifdef ARGB_CURSOR -+ if (pScreenPriv->pTempPicture) -+ { -+ FreePicture (pScreenPriv->pTempPicture, 0); -+ pScreenPriv->pTempPicture = 0; -+ } -+#endif -+ pScreenPriv->pTemp = pTemp = (*pScreen->CreatePixmap) -+ (pScreen, w, h, pScreenPriv->pSave->drawable.depth); -+ if (!pTemp) -+ return FALSE; -+ } -+ if (!pScreenPriv->pMoveGC) -+ { -+ pScreenPriv->pMoveGC = CreateGC ((DrawablePtr)pTemp, -+ GCGraphicsExposures, &gcval, &status); -+ if (!pScreenPriv->pMoveGC) -+ return FALSE; -+ } -+ /* -+ * copy the saved area to a temporary pixmap -+ */ -+ pGC = pScreenPriv->pMoveGC; -+ if (pGC->serialNumber != pTemp->drawable.serialNumber) -+ ValidateGC ((DrawablePtr) pTemp, pGC); -+ (*pGC->ops->CopyArea)((DrawablePtr)pScreenPriv->pSave, -+ (DrawablePtr)pTemp, pGC, 0, 0, w, h, 0, 0); -+ -+ /* -+ * draw the cursor in the temporary pixmap -+ */ -+#ifdef ARGB_CURSOR -+ if (pPriv->pPicture) -+ { -+ if (!EnsurePicture(pScreenPriv->pTempPicture, &pTemp->drawable, pWin)) -+ return FALSE; -+ CompositePicture (PictOpOver, -+ pPriv->pPicture, -+ NULL, -+ pScreenPriv->pTempPicture, -+ 0, 0, 0, 0, -+ dx, dy, -+ pCursor->bits->width, -+ pCursor->bits->height); -+ } -+ else -+#endif -+ { -+ if (!pScreenPriv->pPixSourceGC) -+ { -+ pScreenPriv->pPixSourceGC = CreateGC ((DrawablePtr)pTemp, -+ GCGraphicsExposures, &gcval, &status); -+ if (!pScreenPriv->pPixSourceGC) -+ return FALSE; -+ } -+ if (!pScreenPriv->pPixMaskGC) -+ { -+ pScreenPriv->pPixMaskGC = CreateGC ((DrawablePtr)pTemp, -+ GCGraphicsExposures, &gcval, &status); -+ if (!pScreenPriv->pPixMaskGC) -+ return FALSE; -+ } -+ rfbDCPutBits ((DrawablePtr)pTemp, pPriv, -+ pScreenPriv->pPixSourceGC, pScreenPriv->pPixMaskGC, -+ dx, dy, pCursor->bits->width, pCursor->bits->height, -+ source, mask); -+ } -+ -+ /* -+ * copy the temporary pixmap onto the screen -+ */ -+ -+ if (!EnsureGC(pScreenPriv->pRestoreGC, pWin)) -+ return FALSE; -+ pGC = pScreenPriv->pRestoreGC; -+ if (pWin->drawable.serialNumber != pGC->serialNumber) -+ ValidateGC ((DrawablePtr) pWin, pGC); -+ -+ (*pGC->ops->CopyArea) ((DrawablePtr) pTemp, (DrawablePtr) pWin, -+ pGC, -+ 0, 0, w, h, x, y); -+ return TRUE; -+} -diff --git a/hw/vnc/dpmsstubs.c b/hw/vnc/dpmsstubs.c -new file mode 100644 -index 0000000..e121cf5 ---- /dev/null -+++ b/hw/vnc/dpmsstubs.c -@@ -0,0 +1,48 @@ -+/* $Xorg: dpmsstubs.c,v 1.3 2000/08/17 19:47:56 cpqbld Exp $ */ -+/***************************************************************** -+ -+Copyright (c) 1996 Digital Equipment Corporation, Maynard, Massachusetts. -+ -+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. -+ -+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 -+DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING, -+BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL 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 Digital Equipment Corporation -+shall not be used in advertising or otherwise to promote the sale, use or other -+dealings in this Software without prior written authorization from Digital -+Equipment Corporation. -+ -+******************************************************************/ -+/* $XFree86: xc/programs/Xserver/Xext/dpmsstubs.c,v 3.3 1999/12/16 02:26:23 robin Exp $ */ -+ -+typedef int Bool; -+ -+#define FALSE 0 -+ -+Bool DPMSSupported(void) -+{ -+ return FALSE; -+} -+ -+int DPSMGet(int *level) -+{ -+ return -1; -+} -+ -+void DPMSSet(int level) -+{ -+ -+} -diff --git a/hw/vnc/draw.c b/hw/vnc/draw.c -new file mode 100644 -index 0000000..889db6f ---- /dev/null -+++ b/hw/vnc/draw.c -@@ -0,0 +1,2108 @@ -+/* -+ * draw.c - drawing routines for the RFB X server. This is a set of -+ * wrappers around the standard MI/MFB/CFB drawing routines which work out -+ * to a fair approximation the region of the screen being modified by the -+ * drawing. If the RFB client is ready then the modified region of the screen -+ * is sent to the client, otherwise the modified region will simply grow with -+ * each drawing request until the client is ready. -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ */ -+ -+/* -+ * 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) 1989 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 "rfb.h" -+ -+int rfbDeferUpdateTime = 40; /* ms */ -+ -+ -+/****************************************************************************/ -+/* -+ * Macro definitions -+ */ -+/****************************************************************************/ -+ -+#define TRC(x) /* (rfbLog x) */ -+ -+/* ADD_TO_MODIFIED_REGION adds the given region to the modified region for each -+ client */ -+ -+#define ADD_TO_MODIFIED_REGION(pScreen,reg) \ -+ { \ -+ rfbClientPtr cl; \ -+ for (cl = rfbClientHead; cl; cl = cl->next) { \ -+ REGION_UNION((pScreen),&cl->modifiedRegion,&cl->modifiedRegion,reg);\ -+ } \ -+ } -+ -+/* SCHEDULE_FB_UPDATE is used at the end of each drawing routine to schedule an -+ update to be sent to each client if there is one pending and the client is -+ ready for it. */ -+ -+#define SCHEDULE_FB_UPDATE(pScreen,pVNC) \ -+ if (!pVNC->dontSendFramebufferUpdate) { \ -+ rfbClientPtr cl, nextCl; \ -+ for (cl = rfbClientHead; cl; cl = nextCl) { \ -+ nextCl = cl->next; \ -+ if (!cl->deferredUpdateScheduled && FB_UPDATE_PENDING(cl) && \ -+ REGION_NOTEMPTY(pScreen,&cl->requestedRegion)) \ -+ { \ -+ rfbScheduleDeferredUpdate(pScreen, cl); \ -+ } \ -+ } \ -+ } -+ -+/* function prototypes */ -+ -+static void rfbScheduleDeferredUpdate(ScreenPtr pScreen, rfbClientPtr cl); -+static void rfbCopyRegion(ScreenPtr pScreen, rfbClientPtr cl, -+ RegionPtr src, RegionPtr dst, int dx, int dy); -+#ifdef DEBUG -+static void PrintRegion(ScreenPtr pScreen, RegionPtr reg); -+#endif -+ -+/* GC funcs */ -+ -+static void rfbValidateGC(GCPtr, unsigned long /*changes*/, DrawablePtr); -+static void rfbChangeGC(GCPtr, unsigned long /*mask*/); -+static void rfbCopyGC(GCPtr /*src*/, unsigned long /*mask*/, GCPtr /*dst*/); -+static void rfbDestroyGC(GCPtr); -+static void rfbChangeClip(GCPtr, int /*type*/, pointer /*pValue*/, -+ int /*nrects*/); -+static void rfbDestroyClip(GCPtr); -+static void rfbCopyClip(GCPtr /*dst*/, GCPtr /*src*/); -+ -+/* GC ops */ -+ -+static void rfbFillSpans(DrawablePtr pDrawable, GCPtr pGC, int nInit, DDXPointPtr pptInit, int *pwidthInit, int fSorted); -+static void rfbSetSpans(DrawablePtr pDrawable, -+ GCPtr pGC, -+ char *psrc, -+ register DDXPointPtr ppt, -+ int *pwidth, -+ int nspans, -+ int fSorted); -+static void rfbPutImage(); -+static RegionPtr rfbCopyArea(); -+static RegionPtr rfbCopyPlane(); -+static void rfbPolyPoint(); -+static void rfbPolylines (DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, DDXPointPtr ppts); -+static void rfbPolySegment(); -+static void rfbPolyRectangle(); -+static void rfbPolyArc(); -+static void rfbFillPolygon(); -+static void rfbPolyFillRect(); -+static void rfbPolyFillArc(); -+static int rfbPolyText8(); -+static int rfbPolyText16(); -+static void rfbImageText8(); -+static void rfbImageText16(); -+static void rfbImageGlyphBlt(); -+static void rfbPolyGlyphBlt(); -+static void rfbPushPixels(); -+ -+ -+static GCFuncs rfbGCFuncs = { -+ rfbValidateGC, -+ rfbChangeGC, -+ rfbCopyGC, -+ rfbDestroyGC, -+ rfbChangeClip, -+ rfbDestroyClip, -+ rfbCopyClip, -+}; -+ -+ -+static GCOps rfbGCOps = { -+ rfbFillSpans, rfbSetSpans, rfbPutImage, -+ rfbCopyArea, rfbCopyPlane, rfbPolyPoint, -+ rfbPolylines, rfbPolySegment, rfbPolyRectangle, -+ rfbPolyArc, rfbFillPolygon, rfbPolyFillRect, -+ rfbPolyFillArc, rfbPolyText8, rfbPolyText16, -+ rfbImageText8, rfbImageText16, rfbImageGlyphBlt, -+ rfbPolyGlyphBlt, rfbPushPixels -+}; -+ -+ -+ -+/****************************************************************************/ -+/* -+ * Screen functions wrapper stuff -+ */ -+/****************************************************************************/ -+ -+#define SCREEN_PROLOGUE(scrn, field) \ -+ ScreenPtr pScreen = scrn; \ -+ VNCSCREENPTR(pScreen); \ -+ pScreen->field = pVNC->field; -+ -+#define SCREEN_EPILOGUE(field, wrapper) \ -+ pScreen->field = wrapper; -+ -+ -+/* -+ * CloseScreen wrapper -- unwrap everything, free the private data -+ * and call the wrapped CloseScreen function. -+ */ -+ -+Bool -+rfbCloseScreen (int i, ScreenPtr pScreen) -+{ -+ VNCSCREENPTR(pScreen); -+#if XFREE86VNC -+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; -+#endif -+ int sock; -+ -+ for (sock = 0; sock <= pVNC->maxFd; sock++) { -+ if (FD_ISSET(sock, &pVNC->allFds)) -+ if (sock != pVNC->rfbListenSock && sock != pVNC->httpListenSock) { -+ rfbCloseSock(pScreen, sock); -+ } -+ } -+ -+ if (pVNC->rfbListenSock > 0) -+ if (close(pVNC->rfbListenSock)) -+ ErrorF("Close of port %d failed\n",pVNC->rfbPort); -+ -+ if (pVNC->httpListenSock > 0) -+ if (close(pVNC->httpListenSock)) -+ ErrorF("Close of port %d failed\n",pVNC->httpPort); -+ -+ pScreen->CloseScreen = pVNC->CloseScreen; -+ pScreen->CreateGC = pVNC->CreateGC; -+ pScreen->PaintWindowBackground = pVNC->PaintWindowBackground; -+ pScreen->PaintWindowBorder = pVNC->PaintWindowBorder; -+ pScreen->CopyWindow = pVNC->CopyWindow; -+ pScreen->ClearToBackground = pVNC->ClearToBackground; -+ pScreen->RestoreAreas = pVNC->RestoreAreas; -+ pScreen->WakeupHandler = pVNC->WakeupHandler; -+ -+#if XFREE86VNC -+ pScreen->InstallColormap = pVNC->InstallColormap; -+ pScreen->UninstallColormap = pVNC->UninstallColormap; -+ pScreen->ListInstalledColormaps = pVNC->ListInstalledColormaps; -+ pScreen->StoreColors = pVNC->StoreColors; -+ pScrn->EnableDisableFBAccess = pVNC->EnableDisableFBAccess; -+ -+ xfree(pVNC); -+#endif -+ -+ TRC((stderr,"Unwrapped screen functions\n")); -+ -+ return (*pScreen->CloseScreen) (i, pScreen); -+} -+ -+#if XFREE86VNC -+void -+rfbEnableDisableFBAccess (int index, Bool enable) -+{ -+ ScrnInfoPtr pScrn = xf86Screens[index]; -+ VNCSCREENPTR(pScrn->pScreen); -+ -+ /* -+ * Blank the screen for security while inputs are disabled. -+ * When VT switching is fixed, we might be able to allow -+ * control even when switched away. -+ */ -+ if (!enable) { -+ WindowPtr pWin = WindowTable[index]; -+ ScreenPtr pScreen = pWin->drawable.pScreen; -+ GCPtr pGC; -+ xRectangle rect; -+ -+ rect.x = 0; -+ rect.y = 0; -+ rect.width = pScrn->virtualX; -+ rect.height = pScrn->virtualY; -+ -+ if (!(pGC = GetScratchGC(pScreen->rootDepth, pScreen))) { -+ ErrorF("Couldn't blank screen"); -+ } else { -+ CARD32 attributes[2]; -+ attributes[0] = pScreen->whitePixel; -+ attributes[1] = pScreen->blackPixel; -+ (void)ChangeGC(pGC, GCForeground | GCBackground, attributes); -+ -+ ValidateGC((DrawablePtr)pWin, pGC); -+ -+ (*pGC->ops->PolyFillRect)((DrawablePtr)pWin, pGC, 1, &rect); -+ -+ FreeScratchGC(pGC); -+ -+ /* Flush pending packets */ -+ rfbCheckFds(pScreen); -+ httpCheckFds(pScreen); -+ } -+ } -+ -+ pScrn->EnableDisableFBAccess = pVNC->EnableDisableFBAccess; -+ (*pScrn->EnableDisableFBAccess)(index, enable); -+ pScrn->EnableDisableFBAccess = rfbEnableDisableFBAccess; -+} -+#endif -+ -+/* -+ * CreateGC - wrap the GC funcs (the GC ops will be wrapped when the GC -+ * func "ValidateGC" is called). -+ */ -+ -+Bool -+rfbCreateGC (GCPtr pGC) -+{ -+ Bool ret; -+ rfbGCPtr pGCPriv; -+ -+ SCREEN_PROLOGUE(pGC->pScreen,CreateGC); -+ -+ pGCPriv = (rfbGCPtr)pGC->devPrivates[rfbGCIndex].ptr; -+ -+ ret = (*pScreen->CreateGC) (pGC); -+ -+ TRC((stderr,"rfbCreateGC called\n")); -+ -+ pGCPriv->wrapOps = NULL; -+ pGCPriv->wrapFuncs = pGC->funcs; -+ pGC->funcs = &rfbGCFuncs; -+ -+ SCREEN_EPILOGUE(CreateGC,rfbCreateGC); -+ -+ return ret; -+} -+ -+/* -+ * PaintWindowBackground - the region being modified is just the given region. -+ */ -+ -+void -+rfbPaintWindowBackground (WindowPtr pWin, RegionPtr pRegion, int what) -+{ -+ SCREEN_PROLOGUE(pWin->drawable.pScreen,PaintWindowBackground); -+ -+ TRC((stderr,"rfbPaintWindowBackground called\n")); -+ -+ ADD_TO_MODIFIED_REGION(pScreen,pRegion); -+ -+ (*pScreen->PaintWindowBackground) (pWin, pRegion, what); -+ -+ SCHEDULE_FB_UPDATE(pScreen, pVNC); -+ -+ SCREEN_EPILOGUE(PaintWindowBackground,rfbPaintWindowBackground); -+} -+ -+/* -+ * PaintWindowBorder - the region being modified is just the given region. -+ */ -+ -+void -+rfbPaintWindowBorder (WindowPtr pWin, RegionPtr pRegion, int what) -+{ -+ SCREEN_PROLOGUE(pWin->drawable.pScreen,PaintWindowBorder); -+ -+ TRC((stderr,"rfbPaintWindowBorder called\n")); -+ -+ ADD_TO_MODIFIED_REGION(pScreen,pRegion); -+ -+ (*pScreen->PaintWindowBorder) (pWin, pRegion, what); -+ -+ SCHEDULE_FB_UPDATE(pScreen, pVNC); -+ -+ SCREEN_EPILOGUE(PaintWindowBorder,rfbPaintWindowBorder); -+} -+ -+#ifdef CHROMIUM -+Bool -+rfbRealizeWindow(WindowPtr pWin) -+{ -+ CRWindowTable *wt = NULL, *nextWt = NULL; -+ Bool ret; -+ SCREEN_PROLOGUE(pWin->drawable.pScreen,RealizeWindow); -+ -+ for (wt = windowTable; wt; wt = nextWt) { -+ nextWt = wt->next; -+ if (wt->XwinId == pWin->drawable.id) { -+ rfbSendChromiumWindowShow(wt->CRwinId, 1); -+ } -+ } -+ -+ ret = (*pScreen->RealizeWindow)(pWin); -+ -+ SCREEN_EPILOGUE(RealizeWindow,rfbRealizeWindow); -+ -+ return ret; -+} -+ -+Bool -+rfbUnrealizeWindow(WindowPtr pWin) -+{ -+ CRWindowTable *wt = NULL, *nextWt = NULL; -+ Bool ret; -+ SCREEN_PROLOGUE(pWin->drawable.pScreen,UnrealizeWindow); -+ -+ for (wt = windowTable; wt; wt = nextWt) { -+ nextWt = wt->next; -+ if (wt->XwinId == pWin->drawable.id) { -+ rfbSendChromiumWindowShow(wt->CRwinId, 0); -+ } -+ } -+ -+ ret = (*pScreen->UnrealizeWindow)(pWin); -+ -+ SCREEN_EPILOGUE(UnrealizeWindow,rfbUnrealizeWindow); -+ -+ return ret; -+} -+ -+Bool -+rfbDestroyWindow(WindowPtr pWin) -+{ -+ CRWindowTable *wt = NULL, *nextWt = NULL; -+ Bool ret; -+ SCREEN_PROLOGUE(pWin->drawable.pScreen,DestroyWindow); -+ -+ for (wt = windowTable; wt; wt = nextWt) { -+ nextWt = wt->next; -+ if (wt->XwinId == pWin->drawable.id) { -+ rfbSendChromiumWindowShow(wt->CRwinId, 0); -+ } -+ } -+ -+ ret = (*pScreen->DestroyWindow)(pWin); -+ -+ SCREEN_EPILOGUE(DestroyWindow,rfbDestroyWindow); -+ -+ return ret; -+} -+ -+void -+rfbResizeWindow(WindowPtr pWin, int x, int y, unsigned int w, unsigned int h, WindowPtr pSib) -+{ -+ CRWindowTable *wt = NULL, *nextWt = NULL; -+ SCREEN_PROLOGUE(pWin->drawable.pScreen,ResizeWindow); -+ -+ for (wt = windowTable; wt; wt = nextWt) { -+ nextWt = wt->next; -+ if (wt->XwinId == pWin->drawable.id) { -+ rfbSendChromiumMoveResizeWindow(wt->CRwinId, pWin->drawable.x, pWin->drawable.y, w, h); -+ } -+ } -+ -+ (*pScreen->ResizeWindow)(pWin, x, y, w, h, pSib); -+ -+ SCREEN_EPILOGUE(ResizeWindow,rfbResizeWindow); -+} -+ -+Bool -+rfbPositionWindow(WindowPtr pWin, int x, int y) -+{ -+ Bool ret; -+ CRWindowTable *wt, *nextWt; -+ SCREEN_PROLOGUE(pWin->drawable.pScreen,PositionWindow); -+ -+ for (wt = windowTable; wt; wt = nextWt) { -+ nextWt = wt->next; -+ if (wt->XwinId == pWin->drawable.id) { -+ rfbSendChromiumMoveResizeWindow(wt->CRwinId, x, y, pWin->drawable.width, pWin->drawable.height); -+ } -+ } -+ -+ ret = (*pScreen->PositionWindow)(pWin, x, y); -+ -+ SCREEN_EPILOGUE(PositionWindow,rfbPositionWindow); -+ -+ return ret; -+} -+ -+void -+rfbClipNotify(WindowPtr pWin, int x, int y) -+{ -+ CRWindowTable *wt, *nextWt; -+ SCREEN_PROLOGUE(pWin->drawable.pScreen,ClipNotify); -+ -+ for (wt = windowTable; wt; wt = nextWt) { -+ nextWt = wt->next; -+ if (wt->XwinId == pWin->drawable.id) { -+ int numClipRects = REGION_NUM_RECTS(&pWin->clipList); -+ BoxPtr pClipRects = REGION_RECTS(&pWin->clipList); -+ -+ /* Possible optimization - has the cliplist really? changed */ -+ -+ rfbSendChromiumClipList(wt->CRwinId, pClipRects, numClipRects); -+ } -+ } -+ -+ if (*pScreen->ClipNotify) -+ (*pScreen->ClipNotify)(pWin, x, y); -+ -+ SCREEN_EPILOGUE(ClipNotify,rfbClipNotify); -+} -+#endif /* CHROMIUM */ -+ -+/* -+ * CopyWindow - the region being modified is the translation of the old -+ * region, clipped to the border clip region of the window. Note that any -+ * parts of the window which have become newly-visible will not be affected by -+ * this call - a separate PaintWindowBackground/Border will be called to do -+ * that. If the client will accept CopyRect messages then use rfbCopyRegion to -+ * optimise the pending screen changes into a single "copy region" plus the -+ * ordinary modified region. -+ */ -+ -+void -+rfbCopyWindow (WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr pOldRegion) -+{ -+ rfbClientPtr cl; -+ RegionRec srcRegion, dstRegion; -+ SCREEN_PROLOGUE(pWin->drawable.pScreen,CopyWindow); -+ -+ TRC((stderr,"rfbCopyWindow called\n")); -+ -+ REGION_NULL(pScreen,&dstRegion); -+ REGION_COPY(pScreen,&dstRegion,pOldRegion); -+ REGION_TRANSLATE(pWin->drawable.pScreen, &dstRegion, -+ pWin->drawable.x - ptOldOrg.x, -+ pWin->drawable.y - ptOldOrg.y); -+ REGION_INTERSECT(pWin->drawable.pScreen, &dstRegion, &dstRegion, -+ &pWin->borderClip); -+ -+ for (cl = rfbClientHead; cl; cl = cl->next) { -+ if (cl->useCopyRect) { -+ REGION_NULL(pScreen,&srcRegion); -+ REGION_COPY(pScreen,&srcRegion,pOldRegion); -+ -+ rfbCopyRegion(pScreen, cl, &srcRegion, &dstRegion, -+ pWin->drawable.x - ptOldOrg.x, -+ pWin->drawable.y - ptOldOrg.y); -+ -+ REGION_UNINIT(pScreen, &srcRegion); -+ -+ } else { -+ -+ REGION_UNION(pScreen, &cl->modifiedRegion, &cl->modifiedRegion, -+ &dstRegion); -+ } -+ } -+ -+ REGION_UNINIT(pScreen, &dstRegion); -+ -+ (*pScreen->CopyWindow) (pWin, ptOldOrg, pOldRegion); -+ -+ SCHEDULE_FB_UPDATE(pScreen, pVNC); -+ -+ SCREEN_EPILOGUE(CopyWindow,rfbCopyWindow); -+} -+ -+/* -+ * ClearToBackground - when generateExposures is false, the region being -+ * modified is the given rectangle (clipped to the "window clip region"). -+ */ -+ -+void -+rfbClearToBackground (WindowPtr pWin, int x, int y, int w, int h, -+ Bool generateExposures) -+{ -+ RegionRec tmpRegion; -+ BoxRec box; -+ SCREEN_PROLOGUE(pWin->drawable.pScreen,ClearToBackground); -+ -+ TRC((stderr,"rfbClearToBackground called\n")); -+ -+ if (!generateExposures) { -+ 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); -+ -+ SAFE_REGION_INIT(pScreen, &tmpRegion, &box, 0); -+ -+ REGION_INTERSECT(pScreen, &tmpRegion, &tmpRegion, &pWin->clipList); -+ -+ ADD_TO_MODIFIED_REGION(pScreen, &tmpRegion); -+ -+ REGION_UNINIT(pScreen, &tmpRegion); -+ } -+ -+ (*pScreen->ClearToBackground) (pWin, x, y, w, h, generateExposures); -+ -+ if (!generateExposures) { -+ SCHEDULE_FB_UPDATE(pScreen, pVNC); -+ } -+ -+ SCREEN_EPILOGUE(ClearToBackground,rfbClearToBackground); -+} -+ -+/* -+ * RestoreAreas - just be safe here - the region being modified is the whole -+ * exposed region. -+ */ -+ -+RegionPtr -+rfbRestoreAreas (WindowPtr pWin, RegionPtr prgnExposed) -+{ -+ RegionPtr result; -+ SCREEN_PROLOGUE(pWin->drawable.pScreen,RestoreAreas); -+ -+ TRC((stderr,"rfbRestoreAreas called\n")); -+ -+ ADD_TO_MODIFIED_REGION(pScreen, prgnExposed); -+ -+ result = (*pScreen->RestoreAreas) (pWin, prgnExposed); -+ -+ SCHEDULE_FB_UPDATE(pScreen, pVNC); -+ -+ SCREEN_EPILOGUE(RestoreAreas,rfbRestoreAreas); -+ -+ return result; -+} -+ -+ -+ -+/****************************************************************************/ -+/* -+ * GC funcs wrapper stuff -+ * -+ * We only really want to wrap the GC ops, but to do this we need to wrap -+ * ValidateGC and so all the other GC funcs must be wrapped as well. -+ */ -+/****************************************************************************/ -+ -+#define GC_FUNC_PROLOGUE(pGC) \ -+ rfbGCPtr pGCPriv = (rfbGCPtr) (pGC)->devPrivates[rfbGCIndex].ptr; \ -+ (pGC)->funcs = pGCPriv->wrapFuncs; \ -+ if (pGCPriv->wrapOps) \ -+ (pGC)->ops = pGCPriv->wrapOps; -+ -+#define GC_FUNC_EPILOGUE(pGC) \ -+ pGCPriv->wrapFuncs = (pGC)->funcs; \ -+ (pGC)->funcs = &rfbGCFuncs; \ -+ if (pGCPriv->wrapOps) { \ -+ pGCPriv->wrapOps = (pGC)->ops; \ -+ (pGC)->ops = &rfbGCOps; \ -+ } -+ -+ -+/* -+ * ValidateGC - call the wrapped ValidateGC, then wrap the resulting GC ops if -+ * the drawing will be to a viewable window. -+ */ -+ -+static void -+rfbValidateGC (GCPtr pGC, unsigned long changes, DrawablePtr pDrawable) -+{ -+ VNCSCREENPTR(pGC->pScreen); -+ GC_FUNC_PROLOGUE(pGC); -+ -+ TRC((stderr,"rfbValidateGC called\n")); -+ -+ (*pGC->funcs->ValidateGC) (pGC, changes, pDrawable); -+ -+ pGCPriv->wrapOps = NULL; -+ 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)) { -+ pGCPriv->wrapOps = pGC->ops; -+ TRC((stderr,"rfbValidateGC: wrapped GC ops\n")); -+ } -+ } -+ -+ GC_FUNC_EPILOGUE(pGC); -+} -+ -+/* -+ * All other GC funcs simply unwrap the GC funcs and ops, call the wrapped -+ * function and then rewrap the funcs and ops. -+ */ -+ -+static void -+rfbChangeGC (pGC, mask) -+ GCPtr pGC; -+ unsigned long mask; -+{ -+ GC_FUNC_PROLOGUE(pGC); -+ (*pGC->funcs->ChangeGC) (pGC, mask); -+ GC_FUNC_EPILOGUE(pGC); -+} -+ -+static void -+rfbCopyGC (pGCSrc, mask, pGCDst) -+ GCPtr pGCSrc, pGCDst; -+ unsigned long mask; -+{ -+ GC_FUNC_PROLOGUE(pGCDst); -+ (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst); -+ GC_FUNC_EPILOGUE(pGCDst); -+} -+ -+static void -+rfbDestroyGC (pGC) -+ GCPtr pGC; -+{ -+ GC_FUNC_PROLOGUE(pGC); -+ (*pGC->funcs->DestroyGC) (pGC); -+ GC_FUNC_EPILOGUE(pGC); -+} -+ -+static void -+rfbChangeClip (pGC, type, pvalue, nrects) -+ GCPtr pGC; -+ int type; -+ pointer pvalue; -+ int nrects; -+{ -+ GC_FUNC_PROLOGUE(pGC); -+ (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects); -+ GC_FUNC_EPILOGUE(pGC); -+} -+ -+static void -+rfbDestroyClip(pGC) -+ GCPtr pGC; -+{ -+ GC_FUNC_PROLOGUE(pGC); -+ (* pGC->funcs->DestroyClip)(pGC); -+ GC_FUNC_EPILOGUE(pGC); -+} -+ -+static void -+rfbCopyClip(pgcDst, pgcSrc) -+ GCPtr pgcDst, pgcSrc; -+{ -+ GC_FUNC_PROLOGUE(pgcDst); -+ (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc); -+ GC_FUNC_EPILOGUE(pgcDst); -+} -+ -+ -+/****************************************************************************/ -+/* -+ * GC ops wrapper stuff -+ * -+ * Note that these routines will only have been wrapped for drawing to -+ * viewable windows so we don't need to check each time that the drawable -+ * is a viewable window. -+ */ -+/****************************************************************************/ -+ -+#define GC_OP_PROLOGUE(pDrawable,pGC) \ -+ ScreenPtr pScreen = pGC->pScreen; \ -+ VNCSCREENPTR(pScreen); \ -+ rfbGCPtr pGCPrivate = (rfbGCPtr) (pGC)->devPrivates[rfbGCIndex].ptr; \ -+ GCFuncs *oldFuncs = pGC->funcs; \ -+ (void) pScreen; /* silence compiler */ \ -+ (pGC)->funcs = pGCPrivate->wrapFuncs; \ -+ (pGC)->ops = pGCPrivate->wrapOps; -+ -+#define GC_OP_EPILOGUE(pGC) \ -+ pGCPrivate->wrapOps = (pGC)->ops; \ -+ (pGC)->funcs = oldFuncs; \ -+ (pGC)->ops = &rfbGCOps; -+ -+ -+/* -+ * FillSpans - being very safe - the region being modified is the border clip -+ * region of the window. -+ */ -+ -+static void -+rfbFillSpans(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted) -+ DrawablePtr pDrawable; -+ GCPtr pGC; -+ int nInit; /* number of spans to fill */ -+ DDXPointPtr pptInit; /* pointer to list of start points */ -+ int *pwidthInit; /* pointer to list of n widths */ -+ int fSorted; -+{ -+ GC_OP_PROLOGUE(pDrawable,pGC); -+ -+ TRC((stderr,"rfbFillSpans called\n")); -+ -+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, -+ &((WindowPtr)pDrawable)->borderClip); -+ -+ (*pGC->ops->FillSpans) (pDrawable, pGC, nInit, pptInit,pwidthInit,fSorted); -+ -+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); -+ -+ GC_OP_EPILOGUE(pGC); -+} -+ -+/* -+ * SetSpans - being very safe - the region being modified is the border clip -+ * region of the window. -+ */ -+ -+static void -+rfbSetSpans(DrawablePtr pDrawable, -+ GCPtr pGC, -+ char *psrc, -+ register DDXPointPtr ppt, -+ int *pwidth, -+ int nspans, -+ int fSorted) -+{ -+ GC_OP_PROLOGUE(pDrawable,pGC); -+ -+ TRC((stderr,"rfbSetSpans called\n")); -+ -+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, -+ &((WindowPtr)pDrawable)->borderClip); -+ -+ (*pGC->ops->SetSpans) (pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted); -+ -+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); -+ -+ GC_OP_EPILOGUE(pGC); -+} -+ -+/* -+ * PutImage - the region being modified is the rectangle of the -+ * PutImage (clipped to the window clip region). -+ */ -+ -+static void -+rfbPutImage(pDrawable, pGC, depth, x, y, w, h, leftPad, format, pBits) -+ DrawablePtr pDrawable; -+ GCPtr pGC; -+ int depth; -+ int x; -+ int y; -+ int w; -+ int h; -+ int leftPad; -+ int format; -+ char *pBits; -+{ -+ RegionRec tmpRegion; -+ BoxRec box; -+ GC_OP_PROLOGUE(pDrawable, pGC); -+ -+ TRC((stderr,"rfbPutImage called\n")); -+ -+ box.x1 = x + pDrawable->x; -+ box.y1 = y + pDrawable->y; -+ box.x2 = box.x1 + w; -+ box.y2 = box.y1 + h; -+ -+ SAFE_REGION_INIT(pDrawable->pScreen, &tmpRegion, &box, 0); -+ -+ REGION_INTERSECT(pDrawable->pScreen, &tmpRegion, &tmpRegion, -+ pGC->pCompositeClip); -+ -+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, &tmpRegion); -+ -+ REGION_UNINIT(pDrawable->pScreen, &tmpRegion); -+ -+ (*pGC->ops->PutImage) (pDrawable, pGC, depth, x, y, w, h, -+ leftPad, format, pBits); -+ -+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); -+ -+ GC_OP_EPILOGUE(pGC); -+} -+ -+/* -+ * CopyArea - the region being modified is the destination rectangle (clipped -+ * to the window clip region). -+ * If the client will accept CopyRect messages then use rfbCopyRegion -+ * to optimise the pending screen changes into a single "copy region" plus -+ * the ordinary modified region. -+ */ -+ -+static RegionPtr -+rfbCopyArea (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty) -+ DrawablePtr pSrc; -+ DrawablePtr pDst; -+ GCPtr pGC; -+ int srcx; -+ int srcy; -+ int w; -+ int h; -+ int dstx; -+ int dsty; -+{ -+ rfbClientPtr cl; -+ RegionPtr rgn; -+ RegionRec srcRegion, dstRegion; -+ BoxRec box; -+ GC_OP_PROLOGUE(pDst, pGC); -+ -+ TRC((stderr,"rfbCopyArea called\n")); -+ -+ box.x1 = dstx + pDst->x; -+ box.y1 = dsty + pDst->y; -+ box.x2 = box.x1 + w; -+ box.y2 = box.y1 + h; -+ -+ SAFE_REGION_INIT(pDst->pScreen, &dstRegion, &box, 0); -+ REGION_INTERSECT(pDst->pScreen, &dstRegion, &dstRegion, -+ pGC->pCompositeClip); -+ -+ if ((pSrc->type == DRAWABLE_WINDOW) && (pSrc->pScreen == pDst->pScreen)) { -+ box.x1 = srcx + pSrc->x; -+ box.y1 = srcy + pSrc->y; -+ box.x2 = box.x1 + w; -+ box.y2 = box.y1 + h; -+ -+ for (cl = rfbClientHead; cl; cl = cl->next) { -+ if (cl->useCopyRect) { -+ SAFE_REGION_INIT(pSrc->pScreen, &srcRegion, &box, 0); -+ REGION_INTERSECT(pSrc->pScreen, &srcRegion, &srcRegion, -+ &((WindowPtr)pSrc)->clipList); -+ -+ rfbCopyRegion(pSrc->pScreen, cl, &srcRegion, &dstRegion, -+ dstx + pDst->x - srcx - pSrc->x, -+ dsty + pDst->y - srcy - pSrc->y); -+ -+ REGION_UNINIT(pSrc->pScreen, &srcRegion); -+ -+ } else { -+ -+ REGION_UNION(pScreen, &cl->modifiedRegion, &cl->modifiedRegion, -+ &dstRegion); -+ } -+ } -+ -+ } else { -+ -+ ADD_TO_MODIFIED_REGION(pDst->pScreen, &dstRegion); -+ } -+ -+ REGION_UNINIT(pDst->pScreen, &dstRegion); -+ -+ rgn = (*pGC->ops->CopyArea) (pSrc, pDst, pGC, srcx, srcy, w, h, -+ dstx, dsty); -+ -+ SCHEDULE_FB_UPDATE(pDst->pScreen, pVNC); -+ -+ GC_OP_EPILOGUE(pGC); -+ -+ return rgn; -+} -+ -+ -+/* -+ * CopyPlane - the region being modified is the destination rectangle (clipped -+ * to the window clip region). -+ */ -+ -+static RegionPtr -+rfbCopyPlane (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty, plane) -+ DrawablePtr pSrc; -+ DrawablePtr pDst; -+ register GCPtr pGC; -+ int srcx, -+ srcy; -+ int w, -+ h; -+ int dstx, -+ dsty; -+ unsigned long plane; -+{ -+ RegionPtr rgn; -+ RegionRec tmpRegion; -+ BoxRec box; -+ GC_OP_PROLOGUE(pDst, pGC); -+ -+ TRC((stderr,"rfbCopyPlane called\n")); -+ -+ box.x1 = dstx + pDst->x; -+ box.y1 = dsty + pDst->y; -+ box.x2 = box.x1 + w; -+ box.y2 = box.y1 + h; -+ -+ SAFE_REGION_INIT(pDst->pScreen, &tmpRegion, &box, 0); -+ -+ REGION_INTERSECT(pDst->pScreen, &tmpRegion, &tmpRegion, -+ pGC->pCompositeClip); -+ -+ ADD_TO_MODIFIED_REGION(pDst->pScreen, &tmpRegion); -+ -+ REGION_UNINIT(pDst->pScreen, &tmpRegion); -+ -+ rgn = (*pGC->ops->CopyPlane) (pSrc, pDst, pGC, srcx, srcy, w, h, -+ dstx, dsty, plane); -+ -+ SCHEDULE_FB_UPDATE(pDst->pScreen, pVNC); -+ -+ GC_OP_EPILOGUE(pGC); -+ -+ return rgn; -+} -+ -+/* -+ * PolyPoint - find the smallest rectangle which encloses the points drawn -+ * (and clip). -+ */ -+ -+static void -+rfbPolyPoint (pDrawable, pGC, mode, npt, pts) -+ DrawablePtr pDrawable; -+ GCPtr pGC; -+ int mode; /* Origin or Previous */ -+ int npt; -+ xPoint *pts; -+{ -+ int i; -+ RegionRec tmpRegion; -+ BoxRec box; -+ GC_OP_PROLOGUE(pDrawable, pGC); -+ -+ TRC((stderr,"rfbPolyPoint called\n")); -+ -+ if (npt) { -+ int minX = pts[0].x, maxX = pts[0].x; -+ int minY = pts[0].y, maxY = pts[0].y; -+ -+ if (mode == CoordModePrevious) -+ { -+ int x = pts[0].x, y = pts[0].y; -+ -+ for (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 (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; -+ } -+ } -+ -+ box.x1 = minX + pDrawable->x; -+ box.y1 = minY + pDrawable->y; -+ box.x2 = maxX + 1 + pDrawable->x; -+ box.y2 = maxY + 1 + pDrawable->y; -+ -+ SAFE_REGION_INIT(pDrawable->pScreen, &tmpRegion, &box, 0); -+ -+ REGION_INTERSECT(pDrawable->pScreen, &tmpRegion, &tmpRegion, -+ pGC->pCompositeClip); -+ -+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, &tmpRegion); -+ -+ REGION_UNINIT(pDrawable->pScreen, &tmpRegion); -+ } -+ -+ (*pGC->ops->PolyPoint) (pDrawable, pGC, mode, npt, pts); -+ -+ if (npt) { -+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); -+ } -+ -+ GC_OP_EPILOGUE(pGC); -+} -+ -+/* -+ * PolyLines - take the union of bounding boxes around each line (and clip). -+ */ -+ -+static void -+rfbPolylines (DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, DDXPointPtr ppts) -+{ -+ RegionPtr tmpRegion; -+ xRectangle *rects; -+ int i, extra, nlines, lw; -+ int x1, x2, y1, y2; -+ GC_OP_PROLOGUE(pDrawable, pGC); -+ -+ TRC((stderr,"rfbPolylines called\n")); -+ -+ if (npt) { -+ lw = pGC->lineWidth; -+ if (lw == 0) -+ lw = 1; -+ -+ if (npt == 1) -+ { -+ nlines = 1; -+ rects = (xRectangle *)xalloc(sizeof(xRectangle)); -+ if (!rects) { -+ FatalError("rfbPolylines: xalloc failed\n"); -+ } -+ -+ rects[0].x = ppts[0].x - lw + pDrawable->x; /* being safe here */ -+ rects[0].y = ppts[0].y - lw + pDrawable->y; -+ rects[0].width = 2*lw; -+ rects[0].height = 2*lw; -+ } -+ else -+ { -+ nlines = npt - 1; -+ rects = (xRectangle *)xalloc(nlines*sizeof(xRectangle)); -+ if (!rects) { -+ FatalError("rfbPolylines: xalloc failed\n"); -+ } -+ -+ /* -+ * 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 -+ */ -+ -+ if (pGC->joinStyle == JoinMiter) { -+ extra = 6 * lw; -+ } else { -+ extra = lw / 2; -+ } -+ -+ x1 = ppts[0].x + pDrawable->x; -+ y1 = ppts[0].y + pDrawable->y; -+ -+ for (i = 0; i < nlines; i++) { -+ if (mode == CoordModeOrigin) { -+ x2 = pDrawable->x + ppts[i+1].x; -+ y2 = pDrawable->y + ppts[i+1].y; -+ } else { -+ x2 = x1 + ppts[i+1].x; -+ y2 = y1 + ppts[i+1].y; -+ } -+ -+ if (x1 > x2) { -+ rects[i].x = x2 - extra; -+ rects[i].width = x1 - x2 + 1 + 2 * extra; -+ } else { -+ rects[i].x = x1 - extra; -+ rects[i].width = x2 - x1 + 1 + 2 * extra; -+ } -+ -+ if (y1 > y2) { -+ rects[i].y = y2 - extra; -+ rects[i].height = y1 - y2 + 1 + 2 * extra; -+ } else { -+ rects[i].y = y1 - extra; -+ rects[i].height = y2 - y1 + 1 + 2 * extra; -+ } -+ -+ x1 = x2; -+ y1 = y2; -+ } -+ } -+ tmpRegion = RECTS_TO_REGION(pDrawable->pScreen, nlines, rects,CT_NONE); -+ REGION_INTERSECT(pDrawable->pScreen, tmpRegion, tmpRegion, -+ pGC->pCompositeClip); -+ -+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, tmpRegion); -+ -+ REGION_DESTROY(pDrawable->pScreen, tmpRegion); -+ xfree((char *)rects); -+ } -+ -+ (*pGC->ops->Polylines) (pDrawable, pGC, mode, npt, ppts); -+ -+ if (npt) { -+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); -+ } -+ -+ GC_OP_EPILOGUE(pGC); -+} -+ -+/* -+ * PolySegment - take the union of bounding boxes around each segment (and -+ * clip). -+ */ -+ -+static void -+rfbPolySegment(pDrawable, pGC, nseg, segs) -+ DrawablePtr pDrawable; -+ GCPtr pGC; -+ int nseg; -+ xSegment *segs; -+{ -+ RegionPtr tmpRegion; -+ xRectangle *rects; -+ int i, extra, lw; -+ -+ GC_OP_PROLOGUE(pDrawable, pGC); -+ -+ TRC((stderr,"rfbPolySegment called\n")); -+ -+ if (nseg) { -+ rects = (xRectangle *)xalloc(nseg*sizeof(xRectangle)); -+ if (!rects) { -+ FatalError("rfbPolySegment: xalloc failed\n"); -+ } -+ -+ lw = pGC->lineWidth; -+ if (lw == 0) -+ lw = 1; -+ -+ extra = lw / 2; -+ -+ for (i = 0; i < nseg; i++) -+ { -+ if (segs[i].x1 > segs[i].x2) { -+ rects[i].x = segs[i].x2 - extra + pDrawable->x; -+ rects[i].width = segs[i].x1 - segs[i].x2 + 1 + 2 * extra; -+ } else { -+ rects[i].x = segs[i].x1 - extra + pDrawable->x; -+ rects[i].width = segs[i].x2 - segs[i].x1 + 1 + 2 * extra; -+ } -+ -+ if (segs[i].y1 > segs[i].y2) { -+ rects[i].y = segs[i].y2 - extra + pDrawable->y; -+ rects[i].height = segs[i].y1 - segs[i].y2 + 1 + 2 * extra; -+ } else { -+ rects[i].y = segs[i].y1 - extra + pDrawable->y; -+ rects[i].height = segs[i].y2 - segs[i].y1 + 1 + 2 * extra; -+ } -+ } -+ -+ tmpRegion = RECTS_TO_REGION(pDrawable->pScreen, nseg, rects, CT_NONE); -+ REGION_INTERSECT(pDrawable->pScreen, tmpRegion, tmpRegion, -+ pGC->pCompositeClip); -+ -+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, tmpRegion); -+ -+ REGION_DESTROY(pDrawable->pScreen, tmpRegion); -+ xfree((char *)rects); -+ } -+ -+ (*pGC->ops->PolySegment) (pDrawable, pGC, nseg, segs); -+ -+ if (nseg) { -+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); -+ } -+ -+ GC_OP_EPILOGUE(pGC); -+} -+ -+/* -+ * PolyRectangle (rectangle outlines) - take the union of bounding boxes -+ * around each line (and clip). -+ */ -+ -+static void -+rfbPolyRectangle(pDrawable, pGC, nrects, rects) -+ DrawablePtr pDrawable; -+ GCPtr pGC; -+ int nrects; -+ xRectangle *rects; -+{ -+ int i, extra, lw; -+ RegionPtr tmpRegion; -+ xRectangle *regRects; -+ GC_OP_PROLOGUE(pDrawable, pGC); -+ -+ TRC((stderr,"rfbPolyRectangle called\n")); -+ -+ if (nrects) { -+ regRects = (xRectangle *)xalloc(nrects*4*sizeof(xRectangle)); -+ if (!regRects) { -+ FatalError("rfbPolyRectangle: xalloc failed\n"); -+ } -+ -+ lw = pGC->lineWidth; -+ if (lw == 0) -+ lw = 1; -+ -+ extra = lw / 2; -+ -+ for (i = 0; i < nrects; i++) -+ { -+ 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; -+ } -+ -+ tmpRegion = RECTS_TO_REGION(pDrawable->pScreen, nrects*4, -+ regRects, CT_NONE); -+ REGION_INTERSECT(pDrawable->pScreen, tmpRegion, tmpRegion, -+ pGC->pCompositeClip); -+ -+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, tmpRegion); -+ -+ REGION_DESTROY(pDrawable->pScreen, tmpRegion); -+ xfree((char *)regRects); -+ } -+ -+ (*pGC->ops->PolyRectangle) (pDrawable, pGC, nrects, rects); -+ -+ if (nrects) { -+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); -+ } -+ -+ GC_OP_EPILOGUE(pGC); -+} -+ -+/* -+ * PolyArc - take the union of bounding boxes around each arc (and clip). -+ * Bounding boxes assume each is a full circle / ellipse. -+ */ -+ -+static void -+rfbPolyArc(pDrawable, pGC, narcs, arcs) -+ DrawablePtr pDrawable; -+ register GCPtr pGC; -+ int narcs; -+ xArc *arcs; -+{ -+ int i, extra, lw; -+ RegionPtr tmpRegion; -+ xRectangle *rects; -+ GC_OP_PROLOGUE(pDrawable, pGC); -+ -+ TRC((stderr,"rfbPolyArc called\n")); -+ -+ if (narcs) { -+ rects = (xRectangle *)xalloc(narcs*sizeof(xRectangle)); -+ if (!rects) { -+ FatalError("rfbPolyArc: xalloc failed\n"); -+ } -+ -+ lw = pGC->lineWidth; -+ if (lw == 0) -+ lw = 1; -+ -+ extra = lw / 2; -+ -+ for (i = 0; i < narcs; i++) -+ { -+ rects[i].x = arcs[i].x - extra + pDrawable->x; -+ rects[i].y = arcs[i].y - extra + pDrawable->y; -+ rects[i].width = arcs[i].width + lw; -+ rects[i].height = arcs[i].height + lw; -+ } -+ -+ tmpRegion = RECTS_TO_REGION(pDrawable->pScreen, narcs, rects, CT_NONE); -+ REGION_INTERSECT(pDrawable->pScreen, tmpRegion, tmpRegion, -+ pGC->pCompositeClip); -+ -+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, tmpRegion); -+ -+ REGION_DESTROY(pDrawable->pScreen, tmpRegion); -+ xfree((char *)rects); -+ } -+ -+ (*pGC->ops->PolyArc) (pDrawable, pGC, narcs, arcs); -+ -+ if (narcs) { -+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); -+ } -+ -+ GC_OP_EPILOGUE(pGC); -+} -+ -+/* -+ * FillPolygon - take bounding box around polygon (and clip). -+ */ -+ -+static void -+rfbFillPolygon(pDrawable, pGC, shape, mode, count, pts) -+ register DrawablePtr pDrawable; -+ register GCPtr pGC; -+ int shape, mode; -+ int count; -+ DDXPointPtr pts; -+{ -+ int i; -+ RegionRec tmpRegion; -+ BoxRec box; -+ GC_OP_PROLOGUE(pDrawable, pGC); -+ -+ TRC((stderr,"rfbFillPolygon called\n")); -+ -+ if (count) { -+ int minX = pts[0].x, maxX = pts[0].x; -+ int minY = pts[0].y, maxY = pts[0].y; -+ -+ if (mode == CoordModePrevious) -+ { -+ int x = pts[0].x, y = pts[0].y; -+ -+ for (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 (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; -+ } -+ } -+ -+ box.x1 = minX + pDrawable->x; -+ box.y1 = minY + pDrawable->y; -+ box.x2 = maxX + 1 + pDrawable->x; -+ box.y2 = maxY + 1 + pDrawable->y; -+ -+ SAFE_REGION_INIT(pDrawable->pScreen, &tmpRegion, &box, 0); -+ -+ REGION_INTERSECT(pDrawable->pScreen, &tmpRegion, &tmpRegion, -+ pGC->pCompositeClip); -+ -+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, &tmpRegion); -+ -+ REGION_UNINIT(pDrawable->pScreen, &tmpRegion); -+ } -+ -+ (*pGC->ops->FillPolygon) (pDrawable, pGC, shape, mode, count, pts); -+ -+ if (count) { -+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); -+ } -+ -+ GC_OP_EPILOGUE(pGC); -+} -+ -+/* -+ * PolyFillRect - take the union of the given rectangles (and clip). -+ */ -+ -+static void -+rfbPolyFillRect(pDrawable, pGC, nrects, rects) -+ DrawablePtr pDrawable; -+ GCPtr pGC; -+ int nrects; -+ xRectangle *rects; -+{ -+ RegionPtr tmpRegion; -+ xRectangle *regRects; -+ int i; -+ GC_OP_PROLOGUE(pDrawable, pGC); -+ -+ TRC((stderr,"rfbPolyFillRect called\n")); -+ -+ if (nrects) { -+ regRects = (xRectangle *)xalloc(nrects*sizeof(xRectangle)); -+ if (!regRects) { -+ FatalError("rfbPolyFillRect: xalloc failed\n"); -+ } -+ -+ for (i = 0; i < nrects; i++) { -+ 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; -+ } -+ -+ tmpRegion = RECTS_TO_REGION(pDrawable->pScreen, nrects, regRects, -+ CT_NONE); -+ REGION_INTERSECT(pDrawable->pScreen, tmpRegion, tmpRegion, -+ pGC->pCompositeClip); -+ -+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, tmpRegion); -+ -+ REGION_DESTROY(pDrawable->pScreen, tmpRegion); -+ xfree((char *)regRects); -+ } -+ -+ (*pGC->ops->PolyFillRect) (pDrawable, pGC, nrects, rects); -+ -+ if (nrects) { -+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); -+ } -+ -+ GC_OP_EPILOGUE(pGC); -+} -+ -+/* -+ * PolyFillArc - take the union of bounding boxes around each arc (and clip). -+ * Bounding boxes assume each is a full circle / ellipse. -+ */ -+ -+static void -+rfbPolyFillArc(pDrawable, pGC, narcs, arcs) -+ DrawablePtr pDrawable; -+ GCPtr pGC; -+ int narcs; -+ xArc *arcs; -+{ -+ int i, extra, lw; -+ RegionPtr tmpRegion; -+ xRectangle *rects; -+ GC_OP_PROLOGUE(pDrawable, pGC); -+ -+ TRC((stderr,"rfbPolyFillArc called\n")); -+ -+ if (narcs) { -+ rects = (xRectangle *)xalloc(narcs*sizeof(xRectangle)); -+ if (!rects) { -+ FatalError("rfbPolyFillArc: xalloc failed\n"); -+ } -+ -+ lw = pGC->lineWidth; -+ if (lw == 0) -+ lw = 1; -+ -+ extra = lw / 2; -+ -+ for (i = 0; i < narcs; i++) -+ { -+ rects[i].x = arcs[i].x - extra + pDrawable->x; -+ rects[i].y = arcs[i].y - extra + pDrawable->y; -+ rects[i].width = arcs[i].width + lw; -+ rects[i].height = arcs[i].height + lw; -+ } -+ -+ tmpRegion = RECTS_TO_REGION(pDrawable->pScreen, narcs, rects, CT_NONE); -+ REGION_INTERSECT(pDrawable->pScreen, tmpRegion, tmpRegion, -+ pGC->pCompositeClip); -+ -+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, tmpRegion); -+ -+ REGION_DESTROY(pDrawable->pScreen, tmpRegion); -+ xfree((char *)rects); -+ } -+ -+ (*pGC->ops->PolyFillArc) (pDrawable, pGC, narcs, arcs); -+ -+ if (narcs) { -+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); -+ } -+ -+ GC_OP_EPILOGUE(pGC); -+} -+ -+/* -+ * Get a rough bounding box around n characters of the given font. -+ */ -+ -+static void GetTextBoundingBox(pDrawable, font, x, y, n, pbox) -+ DrawablePtr pDrawable; -+ FontPtr font; -+ int x, y, n; -+ BoxPtr pbox; -+{ -+ int maxAscent, maxDescent, maxCharWidth; -+ -+ if (FONTASCENT(font) > FONTMAXBOUNDS(font,ascent)) -+ maxAscent = FONTASCENT(font); -+ else -+ maxAscent = FONTMAXBOUNDS(font,ascent); -+ -+ if (FONTDESCENT(font) > FONTMAXBOUNDS(font,descent)) -+ maxDescent = FONTDESCENT(font); -+ else -+ maxDescent = FONTMAXBOUNDS(font,descent); -+ -+ if (FONTMAXBOUNDS(font,rightSideBearing) > FONTMAXBOUNDS(font,characterWidth)) -+ maxCharWidth = FONTMAXBOUNDS(font,rightSideBearing); -+ else -+ maxCharWidth = FONTMAXBOUNDS(font,characterWidth); -+ -+ pbox->x1 = pDrawable->x + x; -+ pbox->y1 = pDrawable->y + y - maxAscent; -+ pbox->x2 = pbox->x1 + maxCharWidth * n; -+ pbox->y2 = pbox->y1 + maxAscent + maxDescent; -+ -+ if (FONTMINBOUNDS(font,leftSideBearing) < 0) { -+ pbox->x1 += FONTMINBOUNDS(font,leftSideBearing); -+ } -+} -+ -+ -+/* -+ * PolyText8 - use rough bounding box. -+ */ -+ -+static int -+rfbPolyText8(pDrawable, pGC, x, y, count, chars) -+ DrawablePtr pDrawable; -+ GCPtr pGC; -+ int x, y; -+ int count; -+ char *chars; -+{ -+ int ret; -+ RegionRec tmpRegion; -+ BoxRec box; -+ GC_OP_PROLOGUE(pDrawable, pGC); -+ -+ TRC((stderr,"rfbPolyText8 called '%.*s'\n",count,chars)); -+ -+ if (count) { -+ GetTextBoundingBox(pDrawable, pGC->font, x, y, count, &box); -+ -+ SAFE_REGION_INIT(pDrawable->pScreen, &tmpRegion, &box, 0); -+ -+ REGION_INTERSECT(pDrawable->pScreen, &tmpRegion, &tmpRegion, -+ pGC->pCompositeClip); -+ -+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, &tmpRegion); -+ -+ REGION_UNINIT(pDrawable->pScreen, &tmpRegion); -+ } -+ -+ ret = (*pGC->ops->PolyText8) (pDrawable, pGC, x, y, count, chars); -+ -+ if (count) { -+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); -+ } -+ -+ GC_OP_EPILOGUE(pGC); -+ return ret; -+} -+ -+/* -+ * PolyText16 - use rough bounding box. -+ */ -+ -+static int -+rfbPolyText16(pDrawable, pGC, x, y, count, chars) -+ DrawablePtr pDrawable; -+ GCPtr pGC; -+ int x, y; -+ int count; -+ unsigned short *chars; -+{ -+ int ret; -+ RegionRec tmpRegion; -+ BoxRec box; -+ GC_OP_PROLOGUE(pDrawable, pGC); -+ -+ TRC((stderr,"rfbPolyText16 called\n")); -+ -+ if (count) { -+ GetTextBoundingBox(pDrawable, pGC->font, x, y, count, &box); -+ -+ SAFE_REGION_INIT(pDrawable->pScreen, &tmpRegion, &box, 0); -+ -+ REGION_INTERSECT(pDrawable->pScreen, &tmpRegion, &tmpRegion, -+ pGC->pCompositeClip); -+ -+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, &tmpRegion); -+ -+ REGION_UNINIT(pDrawable->pScreen, &tmpRegion); -+ } -+ -+ ret = (*pGC->ops->PolyText16) (pDrawable, pGC, x, y, count, chars); -+ -+ if (count) { -+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); -+ } -+ -+ GC_OP_EPILOGUE(pGC); -+ return ret; -+} -+ -+/* -+ * ImageText8 - use rough bounding box. -+ */ -+ -+static void -+rfbImageText8(pDrawable, pGC, x, y, count, chars) -+ DrawablePtr pDrawable; -+ GCPtr pGC; -+ int x, y; -+ int count; -+ char *chars; -+{ -+ RegionRec tmpRegion; -+ BoxRec box; -+ GC_OP_PROLOGUE(pDrawable, pGC); -+ -+ TRC((stderr,"rfbImageText8 called '%.*s'\n",count,chars)); -+ -+ if (count) { -+ GetTextBoundingBox(pDrawable, pGC->font, x, y, count, &box); -+ -+ SAFE_REGION_INIT(pDrawable->pScreen, &tmpRegion, &box, 0); -+ -+ REGION_INTERSECT(pDrawable->pScreen, &tmpRegion, &tmpRegion, -+ pGC->pCompositeClip); -+ -+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, &tmpRegion); -+ -+ REGION_UNINIT(pDrawable->pScreen, &tmpRegion); -+ } -+ -+ (*pGC->ops->ImageText8) (pDrawable, pGC, x, y, count, chars); -+ -+ if (count) { -+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); -+ } -+ -+ GC_OP_EPILOGUE(pGC); -+} -+ -+/* -+ * ImageText16 - use rough bounding box. -+ */ -+ -+static void -+rfbImageText16(pDrawable, pGC, x, y, count, chars) -+ DrawablePtr pDrawable; -+ GCPtr pGC; -+ int x, y; -+ int count; -+ unsigned short *chars; -+{ -+ RegionRec tmpRegion; -+ BoxRec box; -+ GC_OP_PROLOGUE(pDrawable, pGC); -+ -+ TRC((stderr,"rfbImageText16 called\n")); -+ -+ if (count) { -+ GetTextBoundingBox(pDrawable, pGC->font, x, y, count, &box); -+ -+ SAFE_REGION_INIT(pDrawable->pScreen, &tmpRegion, &box, 0); -+ -+ REGION_INTERSECT(pDrawable->pScreen, &tmpRegion, &tmpRegion, -+ pGC->pCompositeClip); -+ -+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, &tmpRegion); -+ -+ REGION_UNINIT(pDrawable->pScreen, &tmpRegion); -+ } -+ -+ (*pGC->ops->ImageText16) (pDrawable, pGC, x, y, count, chars); -+ -+ if (count) { -+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); -+ } -+ -+ GC_OP_EPILOGUE(pGC); -+} -+ -+/* -+ * ImageGlyphBlt - use rough bounding box. -+ */ -+ -+static void -+rfbImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase) -+ DrawablePtr pDrawable; -+ GCPtr pGC; -+ int x, y; -+ unsigned int nglyph; -+ CharInfoPtr *ppci; /* array of character info */ -+ pointer pglyphBase; /* start of array of glyphs */ -+{ -+ RegionRec tmpRegion; -+ BoxRec box; -+ GC_OP_PROLOGUE(pDrawable, pGC); -+ -+ TRC((stderr,"rfbImageGlyphBlt called\n")); -+ -+ if (nglyph) { -+ GetTextBoundingBox(pDrawable, pGC->font, x, y, nglyph, &box); -+ -+ SAFE_REGION_INIT(pDrawable->pScreen, &tmpRegion, &box, 0); -+ -+ REGION_INTERSECT(pDrawable->pScreen, &tmpRegion, &tmpRegion, -+ pGC->pCompositeClip); -+ -+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, &tmpRegion); -+ -+ REGION_UNINIT(pDrawable->pScreen, &tmpRegion); -+ } -+ -+ (*pGC->ops->ImageGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci,pglyphBase); -+ -+ if (nglyph) { -+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); -+ } -+ -+ GC_OP_EPILOGUE(pGC); -+} -+ -+/* -+ * PolyGlyphBlt - use rough bounding box. -+ */ -+ -+static void -+rfbPolyGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase) -+ DrawablePtr pDrawable; -+ GCPtr pGC; -+ int x, y; -+ unsigned int nglyph; -+ CharInfoPtr *ppci; /* array of character info */ -+ pointer pglyphBase; /* start of array of glyphs */ -+{ -+ RegionRec tmpRegion; -+ BoxRec box; -+ GC_OP_PROLOGUE(pDrawable, pGC); -+ -+ TRC((stderr,"rfbPolyGlyphBlt called\n")); -+ -+ if (nglyph) { -+ GetTextBoundingBox(pDrawable, pGC->font, x, y, nglyph, &box); -+ -+ SAFE_REGION_INIT(pDrawable->pScreen, &tmpRegion, &box, 0); -+ -+ REGION_INTERSECT(pDrawable->pScreen, &tmpRegion, &tmpRegion, -+ pGC->pCompositeClip); -+ -+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, &tmpRegion); -+ -+ REGION_UNINIT(pDrawable->pScreen, &tmpRegion); -+ } -+ -+ (*pGC->ops->PolyGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); -+ -+ if (nglyph) { -+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); -+ } -+ -+ GC_OP_EPILOGUE(pGC); -+} -+ -+/* -+ * PushPixels - be fairly safe - region modified is intersection of the given -+ * rectangle with the window clip region. -+ */ -+ -+static void -+rfbPushPixels(pGC, pBitMap, pDrawable, w, h, x, y) -+ GCPtr pGC; -+ PixmapPtr pBitMap; -+ DrawablePtr pDrawable; -+ int w, h, x, y; -+{ -+ RegionRec tmpRegion; -+ BoxRec box; -+ GC_OP_PROLOGUE(pDrawable, pGC); -+ -+ TRC((stderr,"rfbPushPixels called\n")); -+ -+ box.x1 = x + pDrawable->x; -+ box.y1 = y + pDrawable->y; -+ box.x2 = box.x1 + w; -+ box.y2 = box.y1 + h; -+ -+ SAFE_REGION_INIT(pDrawable->pScreen, &tmpRegion, &box, 0); -+ -+ REGION_INTERSECT(pDrawable->pScreen, &tmpRegion, &tmpRegion, -+ pGC->pCompositeClip); -+ -+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, &tmpRegion); -+ -+ REGION_UNINIT(pDrawable->pScreen, &tmpRegion); -+ -+ (*pGC->ops->PushPixels) (pGC, pBitMap, pDrawable, w, h, x, y); -+ -+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); -+ -+ GC_OP_EPILOGUE(pGC); -+} -+ -+#ifdef RENDER -+void -+rfbComposite( -+ 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; -+ VNCSCREENPTR(pScreen); -+ RegionRec tmpRegion; -+ BoxRec box; -+ PictureScreenPtr ps = GetPictureScreen(pScreen); -+ -+ box.x1 = pDst->pDrawable->x + xDst; -+ box.y1 = pDst->pDrawable->y + yDst; -+ box.x2 = box.x1 + width; -+ box.y2 = box.y1 + height; -+ -+ REGION_INIT(pScreen, &tmpRegion, &box, 0); -+ -+ ADD_TO_MODIFIED_REGION(pScreen, &tmpRegion); -+ -+ ps->Composite = pVNC->Composite; -+ (*ps->Composite)(op, pSrc, pMask, pDst, xSrc, ySrc, -+ xMask, yMask, xDst, yDst, width, height); -+ ps->Composite = rfbComposite; -+ -+ SCHEDULE_FB_UPDATE(pScreen, pVNC); -+ -+ REGION_UNINIT(pScreen, &tmpRegion); -+} -+#endif /* RENDER */ -+ -+/****************************************************************************/ -+/* -+ * Other functions -+ */ -+/****************************************************************************/ -+ -+/* -+ * rfbCopyRegion. Args are src and dst regions plus a translation (dx,dy). -+ * Takes these args together with the existing modified region and possibly an -+ * existing copy region and translation. Produces a combined modified region -+ * plus copy region and translation. Note that the copy region is the -+ * destination of the copy. -+ * -+ * First we trim parts of src which are invalid (ie in the modified region). -+ * Then we see if there is any overlap between the src and the existing copy -+ * region. If not then the two copies cannot be combined, so we choose -+ * whichever is bigger to form the basis of a new copy, while the other copy is -+ * just done the hard way by being added to the modified region. So if the -+ * existing copy is bigger then we simply add the destination of the new copy -+ * to the modified region and we're done. If the new copy is bigger, we add -+ * the old copy region to the modified region and behave as though there is no -+ * existing copy region. -+ * -+ * At this stage we now know that either the two copies can be combined, or -+ * that there is no existing copy. We temporarily add both the existing copy -+ * region and dst to the modified region (this is the entire area of the screen -+ * affected in any way). Finally we calculate the new copy region, and remove -+ * it from the modified region. -+ * -+ * Note: -+ * 1. The src region is modified by this routine. -+ * 2. When the copy region is empty, copyDX and copyDY MUST be set to zero. -+ */ -+ -+static void -+rfbCopyRegion(pScreen, cl, src, dst, dx, dy) -+ ScreenPtr pScreen; -+ rfbClientPtr cl; -+ RegionPtr src; -+ RegionPtr dst; -+ int dx, dy; -+{ -+ RegionRec tmp; -+ -+ /* src = src - modifiedRegion */ -+ -+ REGION_SUBTRACT(pScreen, src, src, &cl->modifiedRegion); -+ -+ if (REGION_NOTEMPTY(pScreen, &cl->copyRegion)) { -+ -+ REGION_NULL(pScreen, &tmp); -+ REGION_INTERSECT(pScreen, &tmp, src, &cl->copyRegion); -+ -+ if (REGION_NOTEMPTY(pScreen, &tmp)) { -+ -+ /* if src and copyRegion overlap: -+ src = src intersect copyRegion */ -+ -+ REGION_COPY(pScreen, src, &tmp); -+ -+ } else { -+ -+ /* if no overlap, find bigger region */ -+ -+ int newArea = (((REGION_EXTENTS(pScreen,src))->x2 -+ - (REGION_EXTENTS(pScreen,src))->x1) -+ * ((REGION_EXTENTS(pScreen,src))->y2 -+ - (REGION_EXTENTS(pScreen,src))->y1)); -+ -+ int oldArea = (((REGION_EXTENTS(pScreen,&cl->copyRegion))->x2 -+ - (REGION_EXTENTS(pScreen,&cl->copyRegion))->x1) -+ * ((REGION_EXTENTS(pScreen,&cl->copyRegion))->y2 -+ - (REGION_EXTENTS(pScreen,&cl->copyRegion))->y1)); -+ -+ if (oldArea > newArea) { -+ -+ /* existing copy is bigger: -+ modifiedRegion = modifiedRegion union dst -+ copyRegion = copyRegion - dst -+ return */ -+ -+ REGION_UNION(pScreen, &cl->modifiedRegion, &cl->modifiedRegion, -+ dst); -+ REGION_SUBTRACT(pScreen, &cl->copyRegion, &cl->copyRegion, -+ dst); -+ if (!REGION_NOTEMPTY(pScreen, &cl->copyRegion)) { -+ cl->copyDX = 0; -+ cl->copyDY = 0; -+ } -+ return; -+ } -+ -+ /* new copy is bigger: -+ modifiedRegion = modifiedRegion union copyRegion -+ copyRegion = empty */ -+ -+ REGION_UNION(pScreen, &cl->modifiedRegion, &cl->modifiedRegion, -+ &cl->copyRegion); -+ REGION_EMPTY(pScreen, &cl->copyRegion); -+ cl->copyDX = cl->copyDY = 0; -+ } -+ } -+ -+ -+ /* modifiedRegion = modifiedRegion union dst union copyRegion */ -+ -+ REGION_UNION(pScreen, &cl->modifiedRegion, &cl->modifiedRegion, dst); -+ REGION_UNION(pScreen, &cl->modifiedRegion, &cl->modifiedRegion, -+ &cl->copyRegion); -+ -+ /* copyRegion = T(src) intersect dst */ -+ -+ REGION_TRANSLATE(pScreen, src, dx, dy); -+ REGION_INTERSECT(pScreen, &cl->copyRegion, src, dst); -+ -+ /* modifiedRegion = modifiedRegion - copyRegion */ -+ -+ REGION_SUBTRACT(pScreen, &cl->modifiedRegion, &cl->modifiedRegion, -+ &cl->copyRegion); -+ -+ /* combine new translation T with existing translation */ -+ -+ if (REGION_NOTEMPTY(pScreen, &cl->copyRegion)) { -+ cl->copyDX += dx; -+ cl->copyDY += dy; -+ } else { -+ cl->copyDX = 0; -+ cl->copyDY = 0; -+ } -+} -+ -+ -+/* -+ * rfbDeferredUpdateCallback() is called when a client's deferredUpdateTimer -+ * goes off. -+ */ -+ -+static CARD32 -+rfbDeferredUpdateCallback(OsTimerPtr timer, CARD32 now, pointer arg) -+{ -+ rfbClientPtr cl = (rfbClientPtr)arg; -+ -+ rfbSendFramebufferUpdate(cl->pScreen, cl); -+ -+ cl->deferredUpdateScheduled = FALSE; -+ return 0; -+} -+ -+ -+/* -+ * rfbScheduleDeferredUpdate() is called from the SCHEDULE_FB_UPDATE macro -+ * to schedule an update. -+ */ -+ -+static void -+rfbScheduleDeferredUpdate(ScreenPtr pScreen, rfbClientPtr cl) -+{ -+ if (rfbDeferUpdateTime != 0) { -+ cl->deferredUpdateTimer = TimerSet(cl->deferredUpdateTimer, 0, -+ rfbDeferUpdateTime, -+ rfbDeferredUpdateCallback, cl); -+ cl->deferredUpdateScheduled = TRUE; -+ } else { -+ rfbSendFramebufferUpdate(pScreen, cl); -+ } -+} -+ -+ -+/* -+ * PrintRegion is useful for debugging. -+ */ -+ -+#ifdef DEBUG -+static void -+PrintRegion(ScreenPtr pScreen, RegionPtr reg) -+{ -+ int nrects = REGION_NUM_RECTS(reg); -+ int i; -+ -+ ErrorF("Region num rects %d extents %d,%d %d,%d\n",nrects, -+ (REGION_EXTENTS(pScreen,reg))->x1, -+ (REGION_EXTENTS(pScreen,reg))->y1, -+ (REGION_EXTENTS(pScreen,reg))->x2, -+ (REGION_EXTENTS(pScreen,reg))->y2); -+ -+ for (i = 0; i < nrects; i++) { -+ ErrorF(" rect %d,%d %dx%d\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); -+ } -+} -+#endif -+ -+ -+/** -+ * Allow scheduling updates from other functions in other files. -+ */ -+void -+rfbScheduleUpdate(ScreenPtr pScreen) -+{ -+ VNCSCREENPTR(pScreen); -+ SCHEDULE_FB_UPDATE(pScreen, pVNC); -+} -diff --git a/hw/vnc/hextile.c b/hw/vnc/hextile.c -new file mode 100644 -index 0000000..df0d86e ---- /dev/null -+++ b/hw/vnc/hextile.c -@@ -0,0 +1,351 @@ -+/* -+ * hextile.c -+ * -+ * Routines to implement Hextile Encoding -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ */ -+ -+/* -+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. -+ * -+ * This is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This software is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this software; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -+ * USA. -+ */ -+ -+#include -+#include "rfb.h" -+ -+static Bool sendHextiles8(rfbClientPtr cl, int x, int y, int w, int h); -+static Bool sendHextiles16(rfbClientPtr cl, int x, int y, int w, int h); -+static Bool sendHextiles32(rfbClientPtr cl, int x, int y, int w, int h); -+ -+ -+/* -+ * rfbSendRectEncodingHextile - send a rectangle using hextile encoding. -+ */ -+ -+Bool -+rfbSendRectEncodingHextile(cl, x, y, w, h) -+ rfbClientPtr cl; -+ int x, y, w, h; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ rfbFramebufferUpdateRectHeader rect; -+ -+ if (pVNC->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) { -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ } -+ -+ rect.r.x = Swap16IfLE(x); -+ rect.r.y = Swap16IfLE(y); -+ rect.r.w = Swap16IfLE(w); -+ rect.r.h = Swap16IfLE(h); -+ rect.encoding = Swap32IfLE(rfbEncodingHextile); -+ -+ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&rect, -+ sz_rfbFramebufferUpdateRectHeader); -+ pVNC->ublen += sz_rfbFramebufferUpdateRectHeader; -+ -+ cl->rfbRectanglesSent[rfbEncodingHextile]++; -+ cl->rfbBytesSent[rfbEncodingHextile] += sz_rfbFramebufferUpdateRectHeader; -+ -+ switch (cl->format.bitsPerPixel) { -+ case 8: -+ return sendHextiles8(cl, x, y, w, h); -+ case 16: -+ return sendHextiles16(cl, x, y, w, h); -+ case 32: -+ return sendHextiles32(cl, x, y, w, h); -+ } -+ -+ rfbLog("rfbSendRectEncodingHextile: bpp %d?\n", cl->format.bitsPerPixel); -+ return FALSE; -+} -+ -+ -+#define PUT_PIXEL8(pix) (pVNC->updateBuf[pVNC->ublen++] = (pix)) -+ -+#define PUT_PIXEL16(pix) (pVNC->updateBuf[pVNC->ublen++] = ((char*)&(pix))[0], \ -+ pVNC->updateBuf[pVNC->ublen++] = ((char*)&(pix))[1]) -+ -+#define PUT_PIXEL32(pix) (pVNC->updateBuf[pVNC->ublen++] = ((char*)&(pix))[0], \ -+ pVNC->updateBuf[pVNC->ublen++] = ((char*)&(pix))[1], \ -+ pVNC->updateBuf[pVNC->ublen++] = ((char*)&(pix))[2], \ -+ pVNC->updateBuf[pVNC->ublen++] = ((char*)&(pix))[3]) -+ -+ -+#define DEFINE_SEND_HEXTILES(bpp) \ -+ \ -+ \ -+static Bool subrectEncode##bpp(ScreenPtr pScreen, CARD##bpp *data, int w, \ -+ int h, CARD##bpp bg, \ -+ CARD##bpp fg, Bool mono); \ -+static void testColours##bpp(CARD##bpp *data, int size, Bool *mono, \ -+ Bool *solid, CARD##bpp *bg, CARD##bpp *fg); \ -+ \ -+ \ -+/* \ -+ * rfbSendHextiles \ -+ */ \ -+ \ -+static Bool \ -+sendHextiles##bpp(cl, rx, ry, rw, rh) \ -+ rfbClientPtr cl; \ -+ int rx, ry, rw, rh; \ -+{ \ -+ VNCSCREENPTR(cl->pScreen); \ -+ int x, y, w, h; \ -+ int startUblen; \ -+ unsigned char *fbptr; \ -+ CARD##bpp bg = 0, fg = 0, newBg, newFg; \ -+ Bool mono, solid; \ -+ Bool validBg = FALSE; \ -+ Bool validFg = FALSE; \ -+ CARD##bpp clientPixelData[16*16*(bpp/8)]; \ -+ \ -+ for (y = ry; y < ry+rh; y += 16) { \ -+ for (x = rx; x < rx+rw; x += 16) { \ -+ w = h = 16; \ -+ if (rx+rw - x < 16) \ -+ w = rx+rw - x; \ -+ if (ry+rh - y < 16) \ -+ h = ry+rh - y; \ -+ \ -+ if ((pVNC->ublen + 1 + (2 + 16 * 16) * (bpp/8)) > UPDATE_BUF_SIZE) { \ -+ if (!rfbSendUpdateBuf(cl)) \ -+ return FALSE; \ -+ } \ -+ \ -+ fbptr = (pVNC->pfbMemory + (pVNC->paddedWidthInBytes * y) \ -+ + (x * (pVNC->bitsPerPixel / 8))); \ -+ \ -+ (*cl->translateFn)(cl->pScreen, cl->translateLookupTable, \ -+ &pVNC->rfbServerFormat, \ -+ &cl->format, fbptr, (char *)clientPixelData, \ -+ pVNC->paddedWidthInBytes, w, h, x, y); \ -+ \ -+ startUblen = pVNC->ublen; \ -+ pVNC->updateBuf[startUblen] = 0; \ -+ pVNC->ublen++; \ -+ \ -+ testColours##bpp(clientPixelData, w * h, \ -+ &mono, &solid, &newBg, &newFg); \ -+ \ -+ if (!validBg || (newBg != bg)) { \ -+ validBg = TRUE; \ -+ bg = newBg; \ -+ pVNC->updateBuf[startUblen] |= rfbHextileBackgroundSpecified; \ -+ PUT_PIXEL##bpp(bg); \ -+ } \ -+ \ -+ if (solid) { \ -+ cl->rfbBytesSent[rfbEncodingHextile] += pVNC->ublen - startUblen; \ -+ continue; \ -+ } \ -+ \ -+ pVNC->updateBuf[startUblen] |= rfbHextileAnySubrects; \ -+ \ -+ if (mono) { \ -+ if (!validFg || (newFg != fg)) { \ -+ validFg = TRUE; \ -+ fg = newFg; \ -+ pVNC->updateBuf[startUblen] |= rfbHextileForegroundSpecified; \ -+ PUT_PIXEL##bpp(fg); \ -+ } \ -+ } else { \ -+ validFg = FALSE; \ -+ pVNC->updateBuf[startUblen] |= rfbHextileSubrectsColoured; \ -+ } \ -+ \ -+ if (!subrectEncode##bpp(cl->pScreen, clientPixelData, w, h, bg, fg, mono)) { \ -+ /* encoding was too large, use raw */ \ -+ validBg = FALSE; \ -+ validFg = FALSE; \ -+ pVNC->ublen = startUblen; \ -+ pVNC->updateBuf[pVNC->ublen++] = rfbHextileRaw; \ -+ (*cl->translateFn)(cl->pScreen, cl->translateLookupTable, \ -+ &pVNC->rfbServerFormat, &cl->format, fbptr,\ -+ (char *)clientPixelData, \ -+ pVNC->paddedWidthInBytes, w, h, x, y); \ -+ \ -+ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)clientPixelData,\ -+ w * h * (bpp/8)); \ -+ \ -+ pVNC->ublen += w * h * (bpp/8); \ -+ } \ -+ \ -+ cl->rfbBytesSent[rfbEncodingHextile] += pVNC->ublen - startUblen; \ -+ } \ -+ } \ -+ \ -+ return TRUE; \ -+} \ -+ \ -+ \ -+static Bool \ -+subrectEncode##bpp(ScreenPtr pScreen, CARD##bpp *data, int w, int h, \ -+ CARD##bpp bg, CARD##bpp fg, Bool mono) \ -+{ \ -+ VNCSCREENPTR(pScreen); \ -+ CARD##bpp clientdata; \ -+ int x,y; \ -+ int i,j; \ -+ int hx=0,hy,vx=0,vy; \ -+ int hyflag; \ -+ CARD##bpp *seg; \ -+ CARD##bpp *line; \ -+ int hw,hh,vw,vh; \ -+ int thex,they,thew,theh; \ -+ int numsubs = 0; \ -+ int newLen; \ -+ int nSubrectsUblen; \ -+ \ -+ nSubrectsUblen = pVNC->ublen; \ -+ pVNC->ublen++; \ -+ \ -+ for (y=0; y 0) && (i >= hx)) { \ -+ hy += 1; \ -+ } else { \ -+ hyflag = 0; \ -+ } \ -+ } \ -+ vy = j-1; \ -+ \ -+ /* We now have two possible subrects: (x,y,hx,hy) and \ -+ * (x,y,vx,vy). We'll choose the bigger of the two. \ -+ */ \ -+ hw = hx-x+1; \ -+ hh = hy-y+1; \ -+ vw = vx-x+1; \ -+ vh = vy-y+1; \ -+ \ -+ thex = x; \ -+ they = y; \ -+ \ -+ if ((hw*hh) > (vw*vh)) { \ -+ thew = hw; \ -+ theh = hh; \ -+ } else { \ -+ thew = vw; \ -+ theh = vh; \ -+ } \ -+ \ -+ if (mono) { \ -+ newLen = pVNC->ublen - nSubrectsUblen + 2; \ -+ } else { \ -+ newLen = pVNC->ublen - nSubrectsUblen + bpp/8 + 2; \ -+ } \ -+ \ -+ if (newLen > (w * h * (bpp/8))) \ -+ return FALSE; \ -+ \ -+ numsubs += 1; \ -+ \ -+ if (!mono) PUT_PIXEL##bpp(clientdata); \ -+ \ -+ pVNC->updateBuf[pVNC->ublen++] = rfbHextilePackXY(thex,they); \ -+ pVNC->updateBuf[pVNC->ublen++] = rfbHextilePackWH(thew,theh); \ -+ \ -+ /* \ -+ * Now mark the subrect as done. \ -+ */ \ -+ for (j=they; j < (they+theh); j++) { \ -+ for (i=thex; i < (thex+thew); i++) { \ -+ data[j*w+i] = bg; \ -+ } \ -+ } \ -+ } \ -+ } \ -+ } \ -+ \ -+ pVNC->updateBuf[nSubrectsUblen] = numsubs; \ -+ \ -+ return TRUE; \ -+} \ -+ \ -+ \ -+/* \ -+ * testColours() tests if there are one (solid), two (mono) or more \ -+ * colours in a tile and gets a reasonable guess at the best background \ -+ * pixel, and the foreground pixel for mono. \ -+ */ \ -+ \ -+static void \ -+testColours##bpp(data,size,mono,solid,bg,fg) \ -+ CARD##bpp *data; \ -+ int size; \ -+ Bool *mono; \ -+ Bool *solid; \ -+ CARD##bpp *bg; \ -+ CARD##bpp *fg; \ -+{ \ -+ CARD##bpp colour1 = 0, colour2 = 0; \ -+ int n1 = 0, n2 = 0; \ -+ *mono = TRUE; \ -+ *solid = TRUE; \ -+ \ -+ for (; size > 0; size--, data++) { \ -+ \ -+ if (n1 == 0) \ -+ colour1 = *data; \ -+ \ -+ if (*data == colour1) { \ -+ n1++; \ -+ continue; \ -+ } \ -+ \ -+ if (n2 == 0) { \ -+ *solid = FALSE; \ -+ colour2 = *data; \ -+ } \ -+ \ -+ if (*data == colour2) { \ -+ n2++; \ -+ continue; \ -+ } \ -+ \ -+ *mono = FALSE; \ -+ break; \ -+ } \ -+ \ -+ if (n1 > n2) { \ -+ *bg = colour1; \ -+ *fg = colour2; \ -+ } else { \ -+ *bg = colour2; \ -+ *fg = colour1; \ -+ } \ -+} -+ -+DEFINE_SEND_HEXTILES(8) -+DEFINE_SEND_HEXTILES(16) -+DEFINE_SEND_HEXTILES(32) -diff --git a/hw/vnc/httpd.c b/hw/vnc/httpd.c -new file mode 100644 -index 0000000..db13a06 ---- /dev/null -+++ b/hw/vnc/httpd.c -@@ -0,0 +1,516 @@ -+/* -+ * httpd.c - a simple HTTP server -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ */ -+ -+/* -+ * Copyright (C) 2002 Constantin Kaplinsky. All Rights Reserved. -+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. -+ * -+ * This is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This software is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this software; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -+ * USA. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#ifndef USE_LIBWRAP -+#define USE_LIBWRAP 0 -+#endif -+#if USE_LIBWRAP -+#include -+#endif -+ -+#include "rfb.h" -+ -+#define NOT_FOUND_STR "HTTP/1.0 404 Not found\r\n\r\n" \ -+ "File Not Found\n" \ -+ "

File Not Found

\n" -+ -+#define OK_STR "HTTP/1.0 200 OK\r\n\r\n" -+ -+static void httpProcessInput(ScreenPtr pScreen); -+static Bool compareAndSkip(char **ptr, const char *str); -+static Bool parseParams(const char *request, char *result, int max_bytes); -+static Bool validateString(char *str); -+ -+/* -+ * httpInitSockets sets up the TCP socket to listen for HTTP connections. -+ */ -+ -+Bool -+httpInitSockets(ScreenPtr pScreen) -+{ -+ VNCSCREENPTR(pScreen); -+ -+ if (!pVNC->httpDir) -+ return FALSE; -+ -+ pVNC->buf_filled = 0; -+ -+ if (pVNC->httpPort == 0) { -+ pVNC->httpPort = 5800 + atoi(display) + pScreen->myNum; -+ } -+ -+ if ((pVNC->httpListenSock = ListenOnTCPPort(pScreen, pVNC->httpPort)) < 0) { -+ rfbLog("ListenOnTCPPort %d failed\n",pVNC->httpPort); -+ pVNC->httpPort = 0; -+ return FALSE; -+ } -+ -+ rfbLog("Listening for HTTP connections on TCP port %d\n", pVNC->httpPort); -+ rfbLog(" URL http://%s:%d\n",rfbThisHost,pVNC->httpPort); -+ -+ AddEnabledDevice(pVNC->httpListenSock); -+ -+ return TRUE; -+} -+ -+ -+/* -+ * httpCheckFds is called from ProcessInputEvents to check for input on the -+ * HTTP socket(s). If there is input to process, httpProcessInput is called. -+ */ -+ -+void -+httpCheckFds(ScreenPtr pScreen) -+{ -+ VNCSCREENPTR(pScreen); -+ int nfds; -+ fd_set fds; -+ struct timeval tv; -+ struct sockaddr_in addr; -+ SOCKLEN_T addrlen = sizeof(addr); -+ -+ if (!pVNC->httpDir) -+ return; -+ -+ FD_ZERO(&fds); -+ FD_SET(pVNC->httpListenSock, &fds); -+ if (pVNC->httpSock >= 0) { -+ FD_SET(pVNC->httpSock, &fds); -+ } -+ tv.tv_sec = 0; -+ tv.tv_usec = 0; -+ nfds = select(max(pVNC->httpSock,pVNC->httpListenSock) + 1, &fds, NULL, NULL, &tv); -+ if (nfds == 0) { -+ return; -+ } -+ if (nfds < 0) { -+ if (errno != EINTR) -+ rfbLogPerror("httpCheckFds: select"); -+ return; -+ } -+ -+ if ((pVNC->httpSock >= 0) && FD_ISSET(pVNC->httpSock, &fds)) { -+ httpProcessInput(pScreen); -+ } -+ -+ if (FD_ISSET(pVNC->httpListenSock, &fds)) { -+ int flags; -+ -+ if (pVNC->httpSock >= 0) close(pVNC->httpSock); -+ -+ if ((pVNC->httpSock = accept(pVNC->httpListenSock, -+ (struct sockaddr *)&addr, &addrlen)) < 0) { -+ rfbLogPerror("httpCheckFds: accept"); -+ return; -+ } -+ -+#if USE_LIBWRAP -+ if (!hosts_ctl("Xvnc", STRING_UNKNOWN, inet_ntoa(addr.sin_addr), -+ STRING_UNKNOWN)) { -+ rfbLog("Rejected HTTP connection from client %s\n", -+ inet_ntoa(addr.sin_addr)); -+ close(pVNC->httpSock); -+ pVNC->httpSock = -1; -+ return; -+ } -+#endif -+ -+ flags = fcntl (pVNC->httpSock, F_GETFL); -+ -+ if (flags == -1 || -+ fcntl (pVNC->httpSock, F_SETFL, flags | O_NONBLOCK) == -1) { -+ rfbLogPerror("httpCheckFds: fcntl"); -+ close (pVNC->httpSock); -+ pVNC->httpSock = -1; -+ return; -+ } -+ -+ AddEnabledDevice(pVNC->httpSock); -+ } -+} -+ -+ -+static void -+httpCloseSock(ScreenPtr pScreen) -+{ -+ VNCSCREENPTR(pScreen); -+ close(pVNC->httpSock); -+ RemoveEnabledDevice(pVNC->httpSock); -+ pVNC->httpSock = -1; -+ pVNC->buf_filled = 0; -+} -+ -+ -+/* -+ * httpProcessInput is called when input is received on the HTTP socket. -+ */ -+ -+static void -+httpProcessInput(ScreenPtr pScreen) -+{ -+ VNCSCREENPTR(pScreen); -+ struct sockaddr_in addr; -+ SOCKLEN_T addrlen = sizeof(addr); -+ char fullFname[512]; -+ char params[1024]; -+ char *ptr; -+ char *fname; -+ int maxFnameLen; -+ int fd; -+ Bool performSubstitutions = FALSE; -+ char str[256]; -+ struct passwd *user = getpwuid(getuid()); -+ -+ if (strlen(pVNC->httpDir) > 255) { -+ rfbLog("-httpd directory too long\n"); -+ httpCloseSock(pScreen); -+ return; -+ } -+ strcpy(fullFname, pVNC->httpDir); -+ fname = &fullFname[strlen(fullFname)]; -+ maxFnameLen = 511 - strlen(fullFname); -+ -+ /* Read data from the HTTP client until we get a complete request. */ -+ while (1) { -+ ssize_t got = read (pVNC->httpSock, pVNC->buf + pVNC->buf_filled, -+ sizeof (pVNC->buf) - pVNC->buf_filled - 1); -+ -+ if (got <= 0) { -+ if (got == 0) { -+ rfbLog("httpd: premature connection close\n"); -+ } else { -+ if (errno == EAGAIN) { -+ return; -+ } -+ rfbLogPerror("httpProcessInput: read"); -+ } -+ httpCloseSock(pScreen); -+ return; -+ } -+ -+ pVNC->buf_filled += got; -+ pVNC->buf[pVNC->buf_filled] = '\0'; -+ -+ /* Is it complete yet (is there a blank line)? */ -+ if (strstr (pVNC->buf, "\r\r") || strstr (pVNC->buf, "\n\n") || -+ strstr (pVNC->buf, "\r\n\r\n") || strstr (pVNC->buf, "\n\r\n\r")) -+ break; -+ } -+ -+ /* Process the request. */ -+ if (strncmp(pVNC->buf, "GET ", 4)) { -+ rfbLog("httpd: no GET line\n"); -+ httpCloseSock(pScreen); -+ return; -+ } else { -+ /* Only use the first line. */ -+ pVNC->buf[strcspn(pVNC->buf, "\n\r")] = '\0'; -+ } -+ -+ if (strlen(pVNC->buf) > maxFnameLen) { -+ rfbLog("httpd: GET line too long\n"); -+ httpCloseSock(pScreen); -+ return; -+ } -+ -+ if (sscanf(pVNC->buf, "GET %s HTTP/1.0", fname) != 1) { -+ rfbLog("httpd: couldn't parse GET line\n"); -+ httpCloseSock(pScreen); -+ return; -+ } -+ -+ if (fname[0] != '/') { -+ rfbLog("httpd: filename didn't begin with '/'\n"); -+ WriteExact(pVNC->httpSock, NOT_FOUND_STR, strlen(NOT_FOUND_STR)); -+ httpCloseSock(pScreen); -+ return; -+ } -+ -+ if (strchr(fname+1, '/') != NULL) { -+ rfbLog("httpd: asking for file in other directory\n"); -+ WriteExact(pVNC->httpSock, NOT_FOUND_STR, strlen(NOT_FOUND_STR)); -+ httpCloseSock(pScreen); -+ return; -+ } -+ -+ getpeername(pVNC->httpSock, (struct sockaddr *)&addr, &addrlen); -+ rfbLog("httpd: get '%s' for %s\n", fname+1, -+ inet_ntoa(addr.sin_addr)); -+ -+ /* Extract parameters from the URL string if necessary */ -+ -+ params[0] = '\0'; -+ ptr = strchr(fname, '?'); -+ if (ptr != NULL) { -+ *ptr = '\0'; -+ if (!parseParams(&ptr[1], params, 1024)) { -+ params[0] = '\0'; -+ rfbLog("httpd: bad parameters in the URL\n"); -+ } -+ } -+ -+ /* If we were asked for '/', actually read the file index.vnc */ -+ -+ if (strcmp(fname, "/") == 0) { -+ strcpy(fname, "/index.vnc"); -+ rfbLog("httpd: defaulting to '%s'\n", fname+1); -+ } -+ -+ /* Substitutions are performed on files ending .vnc */ -+ -+ if (strlen(fname) >= 4 && strcmp(&fname[strlen(fname)-4], ".vnc") == 0) { -+ performSubstitutions = TRUE; -+ } -+ -+ /* Open the file */ -+ -+ if ((fd = open(fullFname, O_RDONLY)) < 0) { -+ rfbLogPerror("httpProcessInput: open"); -+ WriteExact(pVNC->httpSock, NOT_FOUND_STR, strlen(NOT_FOUND_STR)); -+ httpCloseSock(pScreen); -+ return; -+ } -+ -+ WriteExact(pVNC->httpSock, OK_STR, strlen(OK_STR)); -+ -+ while (1) { -+ int n = read(fd, pVNC->buf, HTTP_BUF_SIZE-1); -+ if (n < 0) { -+ rfbLogPerror("httpProcessInput: read"); -+ close(fd); -+ httpCloseSock(pScreen); -+ return; -+ } -+ -+ if (n == 0) -+ break; -+ -+ if (performSubstitutions) { -+ -+ /* Substitute $WIDTH, $HEIGHT, etc with the appropriate values. -+ This won't quite work properly if the .vnc file is longer than -+ HTTP_BUF_SIZE, but it's reasonable to assume that .vnc files will -+ always be short. */ -+ -+ char *ptr = pVNC->buf; -+ char *dollar; -+ pVNC->buf[n] = 0; /* make sure it's null-terminated */ -+ -+ while ((dollar = strchr(ptr, '$'))) { -+ WriteExact(pVNC->httpSock, ptr, (dollar - ptr)); -+ -+ ptr = dollar; -+ -+ if (compareAndSkip(&ptr, "$WIDTH")) { -+ -+ sprintf(str, "%d", pVNC->width); -+ WriteExact(pVNC->httpSock, str, strlen(str)); -+ -+ } else if (compareAndSkip(&ptr, "$HEIGHT")) { -+ -+ sprintf(str, "%d", pVNC->height); -+ WriteExact(pVNC->httpSock, str, strlen(str)); -+ -+ } else if (compareAndSkip(&ptr, "$APPLETWIDTH")) { -+ -+ sprintf(str, "%d", pVNC->width); -+ WriteExact(pVNC->httpSock, str, strlen(str)); -+ -+ } else if (compareAndSkip(&ptr, "$APPLETHEIGHT")) { -+ -+ sprintf(str, "%d", pVNC->height + 32); -+ WriteExact(pVNC->httpSock, str, strlen(str)); -+ -+ } else if (compareAndSkip(&ptr, "$PORT")) { -+ -+ sprintf(str, "%d", pVNC->rfbPort); -+ WriteExact(pVNC->httpSock, str, strlen(str)); -+ -+ } else if (compareAndSkip(&ptr, "$DESKTOP")) { -+ -+ WriteExact(pVNC->httpSock, desktopName, strlen(desktopName)); -+ -+ } else if (compareAndSkip(&ptr, "$DISPLAY")) { -+ -+ sprintf(str, "%s:%s", rfbThisHost, display); -+ WriteExact(pVNC->httpSock, str, strlen(str)); -+ -+ } else if (compareAndSkip(&ptr, "$USER")) { -+ -+ if (user) { -+ WriteExact(pVNC->httpSock, user->pw_name, -+ strlen(user->pw_name)); -+ } else { -+ WriteExact(pVNC->httpSock, "?", 1); -+ } -+ -+ } else if (compareAndSkip(&ptr, "$PARAMS")) { -+ -+ if (params[0] != '\0') -+ WriteExact(pVNC->httpSock, params, strlen(params)); -+ -+ } else { -+ if (!compareAndSkip(&ptr, "$$")) -+ ptr++; -+ -+ if (WriteExact(pVNC->httpSock, "$", 1) < 0) { -+ close(fd); -+ httpCloseSock(pScreen); -+ return; -+ } -+ } -+ } -+ if (WriteExact(pVNC->httpSock, ptr, (&pVNC->buf[n] - ptr)) < 0) -+ break; -+ -+ } else { -+ -+ /* For files not ending .vnc, just write out the buffer */ -+ -+ if (WriteExact(pVNC->httpSock, pVNC->buf, n) < 0) -+ break; -+ } -+ } -+ -+ close(fd); -+ httpCloseSock(pScreen); -+} -+ -+ -+static Bool -+compareAndSkip(char **ptr, const char *str) -+{ -+ if (strncmp(*ptr, str, strlen(str)) == 0) { -+ *ptr += strlen(str); -+ return TRUE; -+ } -+ -+ return FALSE; -+} -+ -+/* -+ * Parse the request tail after the '?' character, and format a sequence -+ * of tags for inclusion into an HTML page with embedded applet. -+ */ -+ -+static Bool -+parseParams(const char *request, char *result, int max_bytes) -+{ -+ char param_request[128]; -+ char param_formatted[196]; -+ const char *tail; -+ char *delim_ptr; -+ char *value_str; -+ int cur_bytes, len; -+ -+ result[0] = '\0'; -+ cur_bytes = 0; -+ -+ tail = request; -+ for (;;) { -+ /* Copy individual "name=value" string into a buffer */ -+ delim_ptr = strchr((char *)tail, '&'); -+ if (delim_ptr == NULL) { -+ if (strlen(tail) >= sizeof(param_request)) { -+ return FALSE; -+ } -+ strcpy(param_request, tail); -+ } else { -+ len = delim_ptr - tail; -+ if (len >= sizeof(param_request)) { -+ return FALSE; -+ } -+ memcpy(param_request, tail, len); -+ param_request[len] = '\0'; -+ } -+ -+ /* Split the request into parameter name and value */ -+ value_str = strchr(¶m_request[1], '='); -+ if (value_str == NULL) { -+ return FALSE; -+ } -+ *value_str++ = '\0'; -+ if (strlen(value_str) == 0) { -+ return FALSE; -+ } -+ -+ /* Validate both parameter name and value */ -+ if (!validateString(param_request) || !validateString(value_str)) { -+ return FALSE; -+ } -+ -+ /* Prepare HTML-formatted representation of the name=value pair */ -+ len = sprintf(param_formatted, -+ "\n", -+ param_request, value_str); -+ if (cur_bytes + len + 1 > max_bytes) { -+ return FALSE; -+ } -+ strcat(result, param_formatted); -+ cur_bytes += len; -+ -+ /* Go to the next parameter */ -+ if (delim_ptr == NULL) { -+ break; -+ } -+ tail = delim_ptr + 1; -+ } -+ return TRUE; -+} -+ -+/* -+ * Check if the string consists only of alphanumeric characters, '+' -+ * signs, underscores, and dots. Replace all '+' signs with spaces. -+ */ -+ -+static Bool -+validateString(char *str) -+{ -+ char *ptr; -+ -+ for (ptr = str; *ptr != '\0'; ptr++) { -+ if (!isalnum(*ptr) && *ptr != '_' && *ptr != '.') { -+ if (*ptr == '+') { -+ *ptr = ' '; -+ } else { -+ return FALSE; -+ } -+ } -+ } -+ return TRUE; -+} -+ -diff --git a/hw/vnc/init.c b/hw/vnc/init.c -new file mode 100644 -index 0000000..5856734 ---- /dev/null -+++ b/hw/vnc/init.c -@@ -0,0 +1,1066 @@ -+/* -+ * init.c -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ */ -+ -+/* -+ * 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. -+ -+*/ -+ -+/* Use ``#define CORBA'' to enable CORBA control interface */ -+ -+/* XXX this definition should probably go elsewhere */ -+#ifndef XVNCRELEASE -+#define XVNCRELEASE "X.org/xf4vnc custom version" -+#endif -+ -+#include "rfb.h" -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "X11/X.h" -+#define NEED_EVENTS -+#include "X11/Xproto.h" -+#include "X11/Xos.h" -+#include -+#include "scrnintstr.h" -+#include "servermd.h" -+#include "fb.h" -+#include "mfb.h" -+#include "mibstore.h" -+#include "colormapst.h" -+#include "gcstruct.h" -+#include "input.h" -+#include "mipointer.h" -+#include "dixstruct.h" -+#include -+#include -+#include "dix.h" -+#include "micmap.h" -+ -+#ifdef CORBA -+#include -+#endif -+ -+#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 -+ -+static unsigned long VNCGeneration = 0; -+rfbScreenInfo rfbScreen; -+int rfbGCIndex; -+extern char dispatchExceptionAtReset; -+ -+extern void VncExtensionInit(void); -+extern Bool rfbDCInitialize(ScreenPtr, miPointerScreenFuncPtr); -+ -+static Bool initOutputCalled = FALSE; -+static Bool noCursor = FALSE; -+char *desktopName = "x11"; -+ -+char rfbThisHost[256]; -+ -+Atom VNC_LAST_CLIENT_ID; -+Atom VNC_CONNECT; -+ -+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(void); -+static unsigned char *rfbAllocateFramebufferMemory(rfbScreenInfoPtr prfb); -+static Bool rfbCursorOffScreen(ScreenPtr *ppScreen, int *x, int *y); -+static void rfbCrossScreen(ScreenPtr pScreen, Bool entering); -+ -+static miPointerScreenFuncRec rfbPointerCursorFuncs = { -+ rfbCursorOffScreen, -+ rfbCrossScreen, -+ miPointerWarpCursor -+}; -+ -+ -+int inetdSock = -1; -+static char inetdDisplayNumStr[10]; -+ -+/* -+ * 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; -+{ -+ ScreenPtr pScreen = screenInfo.screens[i]; -+ VNCSCREENPTR(pScreen); -+ static Bool firstTime = TRUE; -+ -+ if (firstTime) -+ { -+ pVNC->width = RFB_DEFAULT_WIDTH; -+ pVNC->height = RFB_DEFAULT_HEIGHT; -+ pVNC->depth = RFB_DEFAULT_DEPTH; -+ pVNC->blackPixel = RFB_DEFAULT_BLACKPIXEL; -+ pVNC->whitePixel = RFB_DEFAULT_WHITEPIXEL; -+ pVNC->pfbMemory = NULL; -+ pVNC->httpPort = 0; -+ pVNC->httpDir = NULL; -+ pVNC->rfbAuthPasswdFile = NULL; -+ pVNC->udpPort = 0; -+ pVNC->rfbPort = 0; -+ pVNC->rdpPort = 3389; -+ noCursor = FALSE; -+ pVNC->loginAuthEnabled = FALSE; -+ pVNC->rfbAlwaysShared = FALSE; -+ pVNC->rfbNeverShared = FALSE; -+ pVNC->rfbDontDisconnect = FALSE; -+ pVNC->rfbViewOnly = FALSE; -+ pVNC->useGetImage = FALSE; -+ -+ gethostname(rfbThisHost, 255); -+ pVNC->interface.s_addr = htonl (INADDR_ANY); -+ firstTime = FALSE; -+ } -+ -+ if (strcmp (argv[i], "-geometry") == 0) /* -geometry WxH */ -+ { -+ if (i + 1 >= argc) UseMsg(); -+ if (sscanf(argv[i+1],"%dx%d", -+ &pVNC->width,&pVNC->height) != 2) { -+ ErrorF("Invalid geometry %s\n", argv[i+1]); -+ UseMsg(); -+ } -+#ifdef CORBA -+ screenWidth= pVNC->width; -+ screenHeight= pVNC->height; -+#endif -+ return 2; -+ } -+ -+ if (strcmp (argv[i], "-depth") == 0) /* -depth D */ -+ { -+ if (i + 1 >= argc) UseMsg(); -+ pVNC->depth = atoi(argv[i+1]); -+#ifdef CORBA -+ screenDepth= pVNC->depth; -+#endif -+ return 2; -+ } -+ -+ if (strcmp (argv[i], "-pixelformat") == 0) { -+ if (i + 1 >= argc) UseMsg(); -+ if (sscanf(argv[i+1], "%3s", primaryOrder) < 1) { -+ ErrorF("Invalid pixel format %s\n", argv[i+1]); -+ UseMsg(); -+ } -+ -+ return 2; -+ } -+ -+ if (strcmp (argv[i], "-blackpixel") == 0) { /* -blackpixel n */ -+ if (i + 1 >= argc) UseMsg(); -+ pVNC->blackPixel = atoi(argv[i+1]); -+ return 2; -+ } -+ -+ if (strcmp (argv[i], "-whitepixel") == 0) { /* -whitepixel n */ -+ if (i + 1 >= argc) UseMsg(); -+ pVNC->whitePixel = atoi(argv[i+1]); -+ return 2; -+ } -+ -+ if (strcmp (argv[i], "-usegetimage") == 0) { -+ pVNC->useGetImage = TRUE; -+ return 1; -+ } -+ -+ if (strcmp(argv[i], "-udpinputport") == 0) { /* -udpinputport port */ -+ if (i + 1 >= argc) UseMsg(); -+ pVNC->udpPort = atoi(argv[i+1]); -+ return 2; -+ } -+ -+ if (strcmp(argv[i], "-rfbport") == 0) { /* -rfbport port */ -+ if (i + 1 >= argc) UseMsg(); -+ pVNC->rfbPort = atoi(argv[i+1]); -+ return 2; -+ } -+ -+ if (strcmp(argv[i], "-rfbwait") == 0) { /* -rfbwait ms */ -+ if (i + 1 >= argc) UseMsg(); -+ rfbMaxClientWait = atoi(argv[i+1]); -+ return 2; -+ } -+ -+ if (strcmp(argv[i], "-nocursor") == 0) { -+ noCursor = TRUE; -+ return 1; -+ } -+ -+ if (strcmp(argv[i], "-rfbauth") == 0) { /* -rfbauth passwd-file */ -+ if (i + 1 >= argc) UseMsg(); -+ pVNC->rfbAuthPasswdFile = argv[i+1]; -+ return 2; -+ } -+ -+ if (strcmp(argv[i], "-loginauth") == 0) { -+ if (geteuid() == 0) { -+ /* Only when run as root! */ -+ pVNC->loginAuthEnabled = TRUE; -+ } -+ return 1; -+ } -+ -+ if (strcmp(argv[i], "-httpd") == 0) { -+ if (i + 1 >= argc) UseMsg(); -+ pVNC->httpDir = argv[i+1]; -+ return 2; -+ } -+ -+ if (strcmp(argv[i], "-httpport") == 0) { -+ if (i + 1 >= argc) UseMsg(); -+ pVNC->httpPort = atoi(argv[i+1]); -+ return 2; -+ } -+ -+ if (strcmp(argv[i], "-deferupdate") == 0) { /* -deferupdate ms */ -+ if (i + 1 >= argc) UseMsg(); -+ rfbDeferUpdateTime = atoi(argv[i+1]); -+ return 2; -+ } -+ -+ if (strcmp(argv[i], "-economictranslate") == 0) { -+ rfbEconomicTranslate = TRUE; -+ return 1; -+ } -+ -+ if (strcmp(argv[i], "-lazytight") == 0) { -+ rfbTightDisableGradient = TRUE; -+ return 1; -+ } -+ -+ if (strcmp(argv[i], "-desktop") == 0) { /* -desktop desktop-name */ -+ if (i + 1 >= argc) UseMsg(); -+ desktopName = argv[i+1]; -+ return 2; -+ } -+ -+#if 0 /* not deemed useful on standalone server - leave for completeness */ -+ if (strcmp(argv[i], "-useraccept") == 0) { -+ pVNC->rfbUserAccept = TRUE; -+ return 1; -+ } -+#endif -+ -+ if (strcmp(argv[i], "-alwaysshared") == 0) { -+ pVNC->rfbAlwaysShared = TRUE; -+ return 1; -+ } -+ -+ if (strcmp(argv[i], "-nevershared") == 0) { -+ pVNC->rfbNeverShared = TRUE; -+ return 1; -+ } -+ -+ if (strcmp(argv[i], "-dontdisconnect") == 0) { -+ pVNC->rfbDontDisconnect = TRUE; -+ return 1; -+ } -+ -+ /* Run server in view-only mode - Ehud Karni SW */ -+ if (strcmp(argv[i], "-viewonly") == 0) { -+ pVNC->rfbViewOnly = TRUE; -+ return 1; -+ } -+ -+ if (strcmp(argv[i], "-localhost") == 0) { -+ pVNC->interface.s_addr = htonl (INADDR_LOOPBACK); -+ return 1; -+ } -+ -+ if (strcmp(argv[i], "-interface") == 0) { /* -interface ipaddr */ -+ struct in_addr got; -+ unsigned long octet; -+ char *p, *end; -+ int q; -+ if (i + 1 >= argc) { -+ UseMsg(); -+ return 2; -+ } -+ if (pVNC->interface.s_addr != htonl (INADDR_ANY)) { -+ /* Already set (-localhost?). */ -+ return 2; -+ } -+ p = argv[i + 1]; -+ for (q = 0; q < 4; q++) { -+ octet = strtoul (p, &end, 10); -+ if (p == end || octet > 255) { -+ UseMsg (); -+ return 2; -+ } -+ if ((q < 3 && *end != '.') || -+ (q == 3 && *end != '\0')) { -+ UseMsg (); -+ return 2; -+ } -+ got.s_addr = (got.s_addr << 8) | octet; -+ p = end + 1; -+ } -+ pVNC->interface.s_addr = htonl (got.s_addr); -+ return 2; -+ } -+ -+ if (strcmp(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 (strcmp(argv[i], "-version") == 0) { -+ ErrorF("Xvnc version %s\n", XVNCRELEASE); -+ exit(0); -+ } -+ -+ 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 (FIXME - but we only ever have one), -+ * and in turn this will call rfbScreenInit. -+ */ -+ -+/* Common pixmap formats */ -+ -+static PixmapFormatRec formats[MAXFORMATS] = { -+ { 1, 1, BITMAP_SCANLINE_PAD }, -+ { 4, 8, BITMAP_SCANLINE_PAD }, -+ { 8, 8, BITMAP_SCANLINE_PAD }, -+ { 15, 16, BITMAP_SCANLINE_PAD }, -+ { 16, 16, BITMAP_SCANLINE_PAD }, -+ { 24, 32, BITMAP_SCANLINE_PAD }, -+#ifdef RENDER -+ { 32, 32, BITMAP_SCANLINE_PAD }, -+#endif -+}; -+#ifdef RENDER -+static int numFormats = 7; -+#else -+static int numFormats = 6; -+#endif -+ -+void -+InitOutput(screenInfo, argc, argv) -+ ScreenInfo *screenInfo; -+ int argc; -+ char **argv; -+{ -+ int i; -+ initOutputCalled = TRUE; -+ -+ rfbLog("Xvnc version %s\n", XVNCRELEASE); -+ rfbLog("Copyright (C) 2001-2004 Alan Hourihane.\n"); -+ rfbLog("Copyright (C) 2000-2004 Constantin Kaplinsky\n"); -+ rfbLog("Copyright (C) 1999 AT&T Laboratories Cambridge\n"); -+ rfbLog("All Rights Reserved.\n"); -+ rfbLog("See http://www.tightvnc.com/ for information on TightVNC\n"); -+ rfbLog("See http://xf4vnc.sf.net for xf4vnc-specific information\n"); -+ rfbLog("Desktop name '%s' (%s:%s)\n",desktopName,rfbThisHost,display); -+ rfbLog("Protocol versions supported: %d.%d, %d.%d\n", -+ rfbProtocolMajorVersion, rfbProtocolMinorVersion, -+ rfbProtocolMajorVersion, rfbProtocolFallbackMinorVersion); -+ -+ VNC_LAST_CLIENT_ID = MakeAtom("VNC_LAST_CLIENT_ID", -+ strlen("VNC_LAST_CLIENT_ID"), TRUE); -+ VNC_CONNECT = MakeAtom("VNC_CONNECT", strlen("VNC_CONNECT"), TRUE); -+ -+ /* 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 = numFormats; -+ for (i = 0; i < numFormats; i++) -+ screenInfo->formats[i] = formats[i]; -+ -+ rfbGCIndex = AllocateGCPrivateIndex(); -+ if (rfbGCIndex < 0) { -+ FatalError("InitOutput: AllocateGCPrivateIndex failed\n"); -+ } -+ -+ /* initialize screen */ -+ -+ if (AddScreen(rfbScreenInit, argc, argv) == -1) { -+ FatalError("Couldn't add screen"); -+ } -+ -+#ifdef CORBA -+ initialiseCORBA(argc, argv, desktopName); -+#endif -+} -+ -+static void -+rfbWakeupHandler ( -+ int i, -+ pointer blockData, -+ unsigned long err, -+ pointer pReadmask -+){ -+ ScreenPtr pScreen = screenInfo.screens[i]; -+ VNCSCREENPTR(pScreen); -+ int e = (int)err; -+ -+ if (e < 0) -+ goto SKIPME; -+ -+ rfbRootPropertyChange(pScreen); -+ -+#if XFREE86VNC -+ if (pScrn->vtSema) { -+ rfbCheckFds(pScreen); -+ httpCheckFds(pScreen); -+#if 0 -+ rdpCheckFds(pScreen); -+#endif -+#ifdef CORBA -+ corbaCheckFds(); -+#endif -+ } else { -+ rfbCheckFds(pScreen); -+#if 0 -+ rdpCheckFds(pScreen); -+#endif -+ } -+#else -+ rfbCheckFds(pScreen); -+ httpCheckFds(pScreen); -+#if 0 -+ rdpCheckFds(pScreen); -+#endif -+#ifdef CORBA -+ corbaCheckFds(); -+#endif -+#endif -+ -+SKIPME: -+ -+ pScreen->WakeupHandler = pVNC->WakeupHandler; -+ (*pScreen->WakeupHandler) (i, blockData, err, pReadmask); -+ pScreen->WakeupHandler = rfbWakeupHandler; -+} -+ -+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; -+ unsigned char *pbits; -+ VisualPtr vis; -+#ifdef RENDER -+ PictureScreenPtr ps; -+#endif -+ -+ if (VNCGeneration != serverGeneration) { -+ VncExtensionInit(); -+ VNCGeneration = serverGeneration; -+ } -+ -+ if (monitorResolution != 0) { -+ dpix = monitorResolution; -+ dpiy = monitorResolution; -+ } -+ -+ prfb->rfbAuthTries = 0; -+ prfb->rfbAuthTooManyTries = FALSE; -+ prfb->rfbUserAccept = FALSE; -+ prfb->udpSockConnected = FALSE; -+ prfb->timer = NULL; -+ prfb->httpListenSock = -1; -+ prfb->httpSock = -1; -+ prfb->rfbListenSock = -1; -+ prfb->rdpListenSock = -1; -+ prfb->paddedWidthInBytes = PixmapBytePad(prfb->width, prfb->depth); -+ prfb->bitsPerPixel = rfbBitsPerPixel(prfb->depth); -+ pbits = rfbAllocateFramebufferMemory(prfb); -+ if (!pbits) return FALSE; -+ -+ miClearVisualTypes(); -+ -+ if (defaultColorVisualClass == -1) -+ defaultColorVisualClass = TrueColor; -+ -+ if (!miSetVisualTypes(prfb->depth, miGetDefaultVisualMask(prfb->depth), 8, -+ defaultColorVisualClass) ) -+ return FALSE; -+ -+ miSetPixmapDepths(); -+ -+ switch (prfb->bitsPerPixel) -+ { -+ case 1: -+ ret = mfbScreenInit(pScreen, pbits, prfb->width, prfb->height, -+ dpix, dpiy, prfb->paddedWidthInBytes * 8); -+ break; -+ case 8: -+ ret = fbScreenInit(pScreen, pbits, prfb->width, prfb->height, -+ dpix, dpiy, prfb->paddedWidthInBytes, 8); -+ break; -+ case 16: -+ ret = fbScreenInit(pScreen, pbits, prfb->width, prfb->height, -+ dpix, dpiy, prfb->paddedWidthInBytes / 2, 16); -+ if (prfb->depth == 15) { -+ blueBits = 5; greenBits = 5; redBits = 5; -+ } else { -+ blueBits = 5; greenBits = 6; redBits = 5; -+ } -+ break; -+ case 32: -+ ret = fbScreenInit(pScreen, pbits, prfb->width, prfb->height, -+ dpix, dpiy, prfb->paddedWidthInBytes / 4, 32); -+ blueBits = 8; greenBits = 8; redBits = 8; -+ break; -+ default: -+ return FALSE; -+ } -+ -+ if (!ret) return FALSE; -+ -+ miInitializeBackingStore(pScreen); -+ -+ if (prfb->bitsPerPixel > 8) { -+ if (strcasecmp(primaryOrder, "bgr") == 0) { -+ rfbLog("BGR format %d %d %d\n", blueBits, greenBits, redBits); -+ vis = pScreen->visuals + pScreen->numVisuals; -+ while (--vis >= pScreen->visuals) { -+ if ((vis->class | DynamicClass) == DirectColor) { -+ vis->offsetRed = 0; -+ vis->redMask = (1 << redBits) - 1; -+ vis->offsetGreen = redBits; -+ vis->greenMask = ((1 << greenBits) - 1) << vis->offsetGreen; -+ vis->offsetBlue = redBits + greenBits; -+ vis->blueMask = ((1 << blueBits) - 1) << vis->offsetBlue; -+ } -+ } -+ } else { -+ rfbLog("RGB format %d %d %d\n", blueBits, greenBits, redBits); -+ vis = pScreen->visuals + pScreen->numVisuals; -+ while (--vis >= pScreen->visuals) { -+ if ((vis->class | DynamicClass) == DirectColor) { -+ vis->offsetBlue = 0; -+ vis->blueMask = (1 << blueBits) - 1; -+ vis->offsetGreen = blueBits; -+ vis->greenMask = ((1 << greenBits) - 1) << vis->offsetGreen; -+ vis->offsetRed = blueBits + greenBits; -+ vis->redMask = ((1 << redBits) - 1) << vis->offsetRed; -+ } -+ } -+ } -+ } -+ -+ if (prfb->bitsPerPixel > 4) -+ fbPictureInit(pScreen, 0, 0); -+ -+ if (!AllocateGCPrivate(pScreen, rfbGCIndex, sizeof(rfbGCRec))) { -+ FatalError("rfbScreenInit: AllocateGCPrivate failed\n"); -+ } -+ -+ prfb->cursorIsDrawn = FALSE; -+ prfb->dontSendFramebufferUpdate = FALSE; -+ -+ prfb->CloseScreen = pScreen->CloseScreen; -+ prfb->WakeupHandler = pScreen->WakeupHandler; -+ prfb->CreateGC = pScreen->CreateGC; -+ prfb->PaintWindowBackground = pScreen->PaintWindowBackground; -+ prfb->PaintWindowBorder = pScreen->PaintWindowBorder; -+ prfb->CopyWindow = pScreen->CopyWindow; -+ prfb->ClearToBackground = pScreen->ClearToBackground; -+ prfb->RestoreAreas = pScreen->RestoreAreas; -+#ifdef CHROMIUM -+ prfb->RealizeWindow = pScreen->RealizeWindow; -+ prfb->UnrealizeWindow = pScreen->UnrealizeWindow; -+ prfb->DestroyWindow = pScreen->DestroyWindow; -+ prfb->PositionWindow = pScreen->PositionWindow; -+ prfb->ResizeWindow = pScreen->ResizeWindow; -+ prfb->ClipNotify = pScreen->ClipNotify; -+#endif -+#ifdef RENDER -+ ps = GetPictureScreenIfSet(pScreen); -+ if (ps) -+ prfb->Composite = ps->Composite; -+#endif -+ pScreen->CloseScreen = rfbCloseScreen; -+ pScreen->WakeupHandler = rfbWakeupHandler; -+ pScreen->CreateGC = rfbCreateGC; -+ pScreen->PaintWindowBackground = rfbPaintWindowBackground; -+ pScreen->PaintWindowBorder = rfbPaintWindowBorder; -+ pScreen->CopyWindow = rfbCopyWindow; -+ pScreen->ClearToBackground = rfbClearToBackground; -+ pScreen->RestoreAreas = rfbRestoreAreas; -+#ifdef CHROMIUM -+ pScreen->RealizeWindow = rfbRealizeWindow; -+ pScreen->UnrealizeWindow = rfbUnrealizeWindow; -+ pScreen->DestroyWindow = rfbDestroyWindow; -+ pScreen->PositionWindow = rfbPositionWindow; -+ pScreen->ResizeWindow = rfbResizeWindow; -+ pScreen->ClipNotify = rfbClipNotify; -+#endif -+#ifdef RENDER -+ if (ps) -+ ps->Composite = rfbComposite; -+#endif -+ -+ 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; -+ -+ prfb->rfbServerFormat.bitsPerPixel = prfb->bitsPerPixel; -+ prfb->rfbServerFormat.depth = prfb->depth; -+ prfb->rfbServerFormat.bigEndian = !(*(char *)&rfbEndianTest); -+ -+ /* Find the root visual and set the server format */ -+ for (vis = pScreen->visuals; vis->vid != pScreen->rootVisual; vis++) -+ ; -+ prfb->rfbServerFormat.trueColour = (vis->class == TrueColor); -+ -+ if ( (vis->class == TrueColor) || (vis->class == DirectColor) ) { -+ prfb->rfbServerFormat.redMax = vis->redMask >> vis->offsetRed; -+ prfb->rfbServerFormat.greenMax = vis->greenMask >> vis->offsetGreen; -+ prfb->rfbServerFormat.blueMax = vis->blueMask >> vis->offsetBlue; -+ prfb->rfbServerFormat.redShift = vis->offsetRed; -+ prfb->rfbServerFormat.greenShift = vis->offsetGreen; -+ prfb->rfbServerFormat.blueShift = vis->offsetBlue; -+ } else { -+ prfb->rfbServerFormat.redMax -+ = prfb->rfbServerFormat.greenMax -+ = prfb->rfbServerFormat.blueMax = 0; -+ prfb->rfbServerFormat.redShift -+ = prfb->rfbServerFormat.greenShift -+ = prfb->rfbServerFormat.blueShift = 0; -+ } -+ -+ if (prfb->bitsPerPixel == 1) -+ { -+ ret = mfbCreateDefColormap(pScreen); -+ } -+ else -+ { -+ ret = fbCreateDefColormap(pScreen); -+ } -+ -+ rfbInitSockets(pScreen); -+#if 0 -+ rdpInitSockets(pScreen); -+#endif -+ if (inetdSock == -1) -+ httpInitSockets(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); -+ (void)mieqInit ((DevicePtr)k, (DevicePtr)p); -+#if 0 -+ mieqCheckForInput[0] = checkForInput[0]; -+ mieqCheckForInput[1] = checkForInput[1]; -+ SetInputCheck(&alwaysCheckForInput[0], &alwaysCheckForInput[1]); -+#endif -+} -+ -+ -+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() -+{ -+#if 0 -+ if (*mieqCheckForInput[0] != *mieqCheckForInput[1]) { -+#endif -+ mieqProcessInputEvents(); -+ miPointerUpdate(); -+#if 0 -+ } -+#endif -+} -+ -+ -+static Bool CheckDisplayNumber(int n) -+{ -+ char fname[32]; -+ int sock; -+ struct sockaddr_in addr; -+ -+ sock = socket(AF_INET, SOCK_STREAM, 0); -+ -+ memset(&addr, 0, sizeof(addr)); -+ 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; -+ -+ return TRUE; -+} -+ -+static Bool -+rfbAlwaysTrue(void) -+{ -+ return TRUE; -+} -+ -+ -+static unsigned char * -+rfbAllocateFramebufferMemory(prfb) -+ rfbScreenInfoPtr prfb; -+{ -+ if (prfb->pfbMemory) return prfb->pfbMemory; /* already done */ -+ -+ prfb->sizeInBytes = (prfb->paddedWidthInBytes * prfb->height); -+ -+ prfb->pfbMemory = (unsigned 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; -+{ -+} -+ -+void -+ddxGiveUp() -+{ -+ Xfree(rfbScreen.pfbMemory); -+ if (initOutputCalled) { -+ char unixSocketName[32]; -+ sprintf(unixSocketName,"/tmp/.X11-unix/X%s",display); -+ unlink(unixSocketName); -+#ifdef CORBA -+ shutdownCORBA(); -+#endif -+ } -+} -+ -+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("-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("-udpinputport port UDP port for keyboard/pointer data\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("-loginauth use login-style Unix authentication\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("-lazytight disable \"gradient\" filter in tight " -+ "encoding\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" -+ " to the vnc ports. Use -nolisten tcp to disable\n" -+ " remote X clients as well.\n"); -+ ErrorF("-viewonly let clients only view the desktop\n"); -+ ErrorF("-interface ipaddr only bind to specified interface " -+ "address\n"); -+ ErrorF("-inetd Xvnc is launched by inetd\n"); -+ exit(1); -+} -+ -+ -+void ddxInitGlobals(void) -+{ -+ /* dummy function called by InitGlobals in os/utils.c */ -+} -+ -+ -+/* -+ * 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 %H:%M:%S ", localtime(&clock)); -+ fprintf(stderr, buf); -+ -+ vfprintf(stderr, format, args); -+ fflush(stderr); -+ -+ va_end(args); -+} -+ -+void rfbLogPerror(char *str) -+{ -+ rfbLog(""); -+ perror(str); -+} -diff --git a/hw/vnc/kbdptr.c b/hw/vnc/kbdptr.c -new file mode 100644 -index 0000000..46e8f2d ---- /dev/null -+++ b/hw/vnc/kbdptr.c -@@ -0,0 +1,425 @@ -+/* -+ * kbdptr.c - deal with keyboard and pointer device over TCP & UDP. -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ * -+ */ -+ -+/* -+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. -+ * -+ * This is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This software is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this software; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -+ * USA. -+ */ -+ -+#include "rfb.h" -+#include -+#define NEED_EVENTS -+#include -+#include "inputstr.h" -+#define XK_CYRILLIC -+#include -+#include -+#include "mi.h" -+#include "mipointer.h" -+ -+#if XFREE86VNC -+#ifdef XINPUT -+#include "xf86Xinput.h" -+#define Enqueue(ev) xf86eqEnqueue(ev) -+#else -+#define Enqueue(ev) mieqEnqueue(ev) -+#endif -+#else -+#define Enqueue(ev) mieqEnqueue(ev) -+#endif -+ -+#define KEY_IS_PRESSED(keycode) \ -+ (kbdDevice->key->down[(keycode) >> 3] & (1 << ((keycode) & 7))) -+ -+static void XConvertCase(KeySym sym, KeySym *lower, KeySym *upper); -+ -+DeviceIntPtr kbdDevice; -+ -+#include "keyboard.h" -+ -+/* -+ * Called when the rfbserver receives a rfbKeyEvent event from a client. -+ * Put an X keyboard event into the event queue. -+ */ -+void -+KbdAddEvent(Bool down, KeySym keySym, rfbClientPtr cl) -+{ -+ xEvent ev, fake; -+ KeySymsPtr keySyms; -+ int i; -+ int keyCode = 0; -+ int freeIndex = -1; -+ unsigned long time; -+ Bool fakeShiftPress = FALSE; -+ Bool fakeShiftLRelease = FALSE; -+ Bool fakeShiftRRelease = FALSE; -+ Bool shiftMustBeReleased = FALSE; -+ Bool shiftMustBePressed = FALSE; -+ -+ if (!kbdDevice) return; -+ -+ keySyms = &kbdDevice->key->curKeySyms; -+ -+#ifdef CORBA -+ if (cl) { -+ CARD32 clientId = cl->sock; -+ ChangeWindowProperty(WindowTable[0], VNC_LAST_CLIENT_ID, XA_INTEGER, -+ 32, PropModeReplace, 1, (pointer)&clientId, TRUE); -+ } -+#endif -+ -+ if (down) { -+ ev.u.u.type = KeyPress; -+ } else { -+ ev.u.u.type = KeyRelease; -+ } -+ -+ /* NOTE: This is where it gets hairy for XFree86 servers. -+ * I think the best way to deal with this is invent a new protocol -+ * to send over the wire the remote keyboard type and correctly -+ * handle that as XINPUT extension device (we're part of the way -+ * there for that. -+ * -+ * Alan. -+ */ -+#if !XFREE86VNC -+ /* First check if it's one of our predefined keys. If so then we can make -+ some attempt at allowing an xmodmap inside a VNC desktop behave -+ something like you'd expect - e.g. if keys A & B are swapped over and -+ the VNC client sends an A, then map it to a B when generating the X -+ event. We don't attempt to do this for keycodes which we make up on the -+ fly because it's too hard... */ -+ -+ for (i = 0; i < N_PREDEFINED_KEYS * GLYPHS_PER_KEY; i++) { -+ if (keySym == map[i]) { -+ keyCode = MIN_KEY_CODE + i / GLYPHS_PER_KEY; -+ -+ if (map[(i/GLYPHS_PER_KEY) * GLYPHS_PER_KEY + 1] != NoSymbol) { -+ -+ /* this keycode has more than one symbol associated with it, -+ so shift state is important */ -+ -+ if ((i % GLYPHS_PER_KEY) == 0) -+ shiftMustBeReleased = TRUE; -+ else -+ shiftMustBePressed = TRUE; -+ } -+ break; -+ } -+ } -+#endif -+ -+ if (!keyCode) { -+ -+ /* not one of our predefined keys - see if it's in the current keyboard -+ mapping (i.e. we've already allocated an extra keycode for it) */ -+ -+ if (keySyms->mapWidth < 2) { -+ ErrorF("KbdAddEvent: Sanity check failed - Keyboard mapping has " -+ "less than 2 keysyms per keycode (KeySym 0x%x)\n", keySym); -+ return; -+ } -+ -+ for (i = 0; i < NO_OF_KEYS * keySyms->mapWidth; i++) { -+ if (keySym == keySyms->map[i]) { -+ keyCode = MIN_KEY_CODE + i / keySyms->mapWidth; -+ -+ if (keySyms->map[(i / keySyms->mapWidth) -+ * keySyms->mapWidth + 1] != NoSymbol) { -+ -+ /* this keycode has more than one symbol associated with -+ it, so shift state is important */ -+ -+ if ((i % keySyms->mapWidth) == 0) -+ shiftMustBeReleased = TRUE; -+ else -+ shiftMustBePressed = TRUE; -+ } -+ break; -+ } -+ if ((freeIndex == -1) && (keySyms->map[i] == NoSymbol) -+ && (i % keySyms->mapWidth) == 0) -+ { -+ freeIndex = i; -+ } -+ } -+ } -+ -+ if (!keyCode) { -+ KeySym lower, upper; -+ -+ /* we don't have an existing keycode - make one up on the fly and add -+ it to the keyboard mapping. Thanks to Vlad Harchev for pointing -+ out problems with non-ascii capitalisation. */ -+ -+ if (freeIndex == -1) { -+ ErrorF("KbdAddEvent: ignoring KeySym 0x%x - no free KeyCodes\n", -+ keySym); -+ return; -+ } -+ -+ keyCode = MIN_KEY_CODE + freeIndex / keySyms->mapWidth; -+ -+ XConvertCase(keySym, &lower, &upper); -+ -+ if (lower == upper) { -+ keySyms->map[freeIndex] = keySym; -+ -+ } else { -+ keySyms->map[freeIndex] = lower; -+ keySyms->map[freeIndex+1] = upper; -+ -+ if (keySym == lower) -+ shiftMustBeReleased = TRUE; -+ else -+ shiftMustBePressed = TRUE; -+ } -+ -+ SendMappingNotify(MappingKeyboard, keyCode, 1, serverClient); -+ -+ ErrorF("KbdAddEvent: unknown KeySym 0x%x - allocating KeyCode %d\n", -+ keySym, keyCode); -+ } -+ -+ time = GetTimeInMillis(); -+ -+ if (down) { -+ if (shiftMustBePressed && !(kbdDevice->key->state & ShiftMask)) { -+ fakeShiftPress = TRUE; -+ fake.u.u.type = KeyPress; -+ fake.u.u.detail = SHIFT_L_KEY_CODE; -+ fake.u.keyButtonPointer.time = time; -+ Enqueue(&fake); -+ } -+ if (shiftMustBeReleased && (kbdDevice->key->state & ShiftMask)) { -+ if (KEY_IS_PRESSED(SHIFT_L_KEY_CODE)) { -+ fakeShiftLRelease = TRUE; -+ fake.u.u.type = KeyRelease; -+ fake.u.u.detail = SHIFT_L_KEY_CODE; -+ fake.u.keyButtonPointer.time = time; -+ Enqueue(&fake); -+ } -+ if (KEY_IS_PRESSED(SHIFT_R_KEY_CODE)) { -+ fakeShiftRRelease = TRUE; -+ fake.u.u.type = KeyRelease; -+ fake.u.u.detail = SHIFT_R_KEY_CODE; -+ fake.u.keyButtonPointer.time = time; -+ Enqueue(&fake); -+ } -+ } -+ } -+ -+ ev.u.u.detail = keyCode; -+ ev.u.keyButtonPointer.time = time; -+ Enqueue(&ev); -+ -+ if (fakeShiftPress) { -+ fake.u.u.type = KeyRelease; -+ fake.u.u.detail = SHIFT_L_KEY_CODE; -+ fake.u.keyButtonPointer.time = time; -+ Enqueue(&fake); -+ } -+ if (fakeShiftLRelease) { -+ fake.u.u.type = KeyPress; -+ fake.u.u.detail = SHIFT_L_KEY_CODE; -+ fake.u.keyButtonPointer.time = time; -+ Enqueue(&fake); -+ } -+ if (fakeShiftRRelease) { -+ fake.u.u.type = KeyPress; -+ fake.u.u.detail = SHIFT_R_KEY_CODE; -+ fake.u.keyButtonPointer.time = time; -+ Enqueue(&fake); -+ } -+} -+ -+/* -+ * Called when the rfbserver receives a rfbPointerEvent event from a client. -+ * Put an X mouse event into the event queue. -+ */ -+void -+PtrAddEvent(buttonMask, x, y, cl) -+ int buttonMask; -+ int x; -+ int y; -+ rfbClientPtr cl; -+{ -+ xEvent ev; -+ int i; -+ unsigned long time; -+ static int oldButtonMask = 0; -+ -+#ifdef CORBA -+ if (cl) { -+ CARD32 clientId = cl->sock; -+ ChangeWindowProperty(WindowTable[0], VNC_LAST_CLIENT_ID, XA_INTEGER, -+ 32, PropModeReplace, 1, (pointer)&clientId, TRUE); -+ } -+#endif -+ -+ time = GetTimeInMillis(); -+ -+ miPointerAbsoluteCursor(x, y, time); -+ -+ for (i = 0; i < 5; i++) { -+ if ((buttonMask ^ oldButtonMask) & (1<key->down[i] != 0) { -+ for (j = 0; j < 8; j++) { -+ if (kbdDevice->key->down[i] & (1 << j)) { -+ ev.u.u.type = KeyRelease; -+ ev.u.u.detail = (i << 3) | j; -+ ev.u.keyButtonPointer.time = time; -+ Enqueue(&ev); -+ } -+ } -+ } -+ } -+} -+ -+ -+/* copied from Xlib source */ -+ -+static 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; -+ } -+} -diff --git a/hw/vnc/keyboard.h b/hw/vnc/keyboard.h -new file mode 100644 -index 0000000..ab5b1b3 ---- /dev/null -+++ b/hw/vnc/keyboard.h -@@ -0,0 +1,167 @@ -+/* -+ * Copyright (C) 2002 Alan Hourihane. 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. -+ * -+ * Author: Alan Hourihane -+ */ -+ -+#define MIN_KEY_CODE 8 -+#define MAX_KEY_CODE 255 -+#define NO_OF_KEYS (MAX_KEY_CODE - MIN_KEY_CODE + 1) -+#define GLYPHS_PER_KEY 4 -+ -+#define CONTROL_L_KEY_CODE (MIN_KEY_CODE + 29) -+#define CONTROL_R_KEY_CODE (MIN_KEY_CODE + 101) -+#define SHIFT_L_KEY_CODE (MIN_KEY_CODE + 42) -+#define SHIFT_R_KEY_CODE (MIN_KEY_CODE + 54) -+#define META_L_KEY_CODE (MIN_KEY_CODE + 107) -+#define META_R_KEY_CODE (MIN_KEY_CODE + 108) -+#define ALT_L_KEY_CODE (MIN_KEY_CODE + 56) -+#define ALT_R_KEY_CODE (MIN_KEY_CODE + 105) -+ -+static KeySym map[MAX_KEY_CODE * GLYPHS_PER_KEY] = { -+ /* 0x00 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x01 */ XK_Escape, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x02 */ XK_1, XK_exclam, NoSymbol, NoSymbol, -+ /* 0x03 */ XK_2, XK_at, NoSymbol, NoSymbol, -+ /* 0x04 */ XK_3, XK_numbersign, NoSymbol, NoSymbol, -+ /* 0x05 */ XK_4, XK_dollar, NoSymbol, NoSymbol, -+ /* 0x06 */ XK_5, XK_percent, NoSymbol, NoSymbol, -+ /* 0x07 */ XK_6, XK_asciicircum, NoSymbol, NoSymbol, -+ /* 0x08 */ XK_7, XK_ampersand, NoSymbol, NoSymbol, -+ /* 0x09 */ XK_8, XK_asterisk, NoSymbol, NoSymbol, -+ /* 0x0a */ XK_9, XK_parenleft, NoSymbol, NoSymbol, -+ /* 0x0b */ XK_0, XK_parenright, NoSymbol, NoSymbol, -+ /* 0x0c */ XK_minus, XK_underscore, NoSymbol, NoSymbol, -+ /* 0x0d */ XK_equal, XK_plus, NoSymbol, NoSymbol, -+ /* 0x0e */ XK_BackSpace, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x0f */ XK_Tab, XK_ISO_Left_Tab,NoSymbol, NoSymbol, -+ /* 0x10 */ XK_q, XK_Q, NoSymbol, NoSymbol, -+ /* 0x11 */ XK_w, XK_W, NoSymbol, NoSymbol, -+ /* 0x12 */ XK_e, XK_E, NoSymbol, NoSymbol, -+ /* 0x13 */ XK_r, XK_R, NoSymbol, NoSymbol, -+ /* 0x14 */ XK_t, XK_T, NoSymbol, NoSymbol, -+ /* 0x15 */ XK_y, XK_Y, NoSymbol, NoSymbol, -+ /* 0x16 */ XK_u, XK_U, NoSymbol, NoSymbol, -+ /* 0x17 */ XK_i, XK_I, NoSymbol, NoSymbol, -+ /* 0x18 */ XK_o, XK_O, NoSymbol, NoSymbol, -+ /* 0x19 */ XK_p, XK_P, NoSymbol, NoSymbol, -+ /* 0x1a */ XK_bracketleft, XK_braceleft, NoSymbol, NoSymbol, -+ /* 0x1b */ XK_bracketright,XK_braceright, NoSymbol, NoSymbol, -+ /* 0x1c */ XK_Return, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x1d */ XK_Control_L, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x1e */ XK_a, XK_A, NoSymbol, NoSymbol, -+ /* 0x1f */ XK_s, XK_S, NoSymbol, NoSymbol, -+ /* 0x20 */ XK_d, XK_D, NoSymbol, NoSymbol, -+ /* 0x21 */ XK_f, XK_F, NoSymbol, NoSymbol, -+ /* 0x22 */ XK_g, XK_G, NoSymbol, NoSymbol, -+ /* 0x23 */ XK_h, XK_H, NoSymbol, NoSymbol, -+ /* 0x24 */ XK_j, XK_J, NoSymbol, NoSymbol, -+ /* 0x25 */ XK_k, XK_K, NoSymbol, NoSymbol, -+ /* 0x26 */ XK_l, XK_L, NoSymbol, NoSymbol, -+ /* 0x27 */ XK_semicolon, XK_colon, NoSymbol, NoSymbol, -+ /* 0x28 */ XK_quoteright, XK_quotedbl, NoSymbol, NoSymbol, -+ /* 0x29 */ XK_quoteleft, XK_asciitilde, NoSymbol, NoSymbol, -+ /* 0x2a */ XK_Shift_L, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x2b */ XK_backslash, XK_bar, NoSymbol, NoSymbol, -+ /* 0x2c */ XK_z, XK_Z, NoSymbol, NoSymbol, -+ /* 0x2d */ XK_x, XK_X, NoSymbol, NoSymbol, -+ /* 0x2e */ XK_c, XK_C, NoSymbol, NoSymbol, -+ /* 0x2f */ XK_v, XK_V, NoSymbol, NoSymbol, -+ /* 0x30 */ XK_b, XK_B, NoSymbol, NoSymbol, -+ /* 0x31 */ XK_n, XK_N, NoSymbol, NoSymbol, -+ /* 0x32 */ XK_m, XK_M, NoSymbol, NoSymbol, -+ /* 0x33 */ XK_comma, XK_less, NoSymbol, NoSymbol, -+ /* 0x34 */ XK_period, XK_greater, NoSymbol, NoSymbol, -+ /* 0x35 */ XK_slash, XK_question, NoSymbol, NoSymbol, -+ /* 0x36 */ XK_Shift_R, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x37 */ XK_KP_Multiply, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x38 */ XK_Alt_L, XK_Meta_L, NoSymbol, NoSymbol, -+ /* 0x39 */ XK_space, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x3a */ XK_Caps_Lock, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x3b */ XK_F1, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x3c */ XK_F2, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x3d */ XK_F3, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x3e */ XK_F4, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x3f */ XK_F5, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x40 */ XK_F6, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x41 */ XK_F7, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x42 */ XK_F8, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x43 */ XK_F9, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x44 */ XK_F10, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x45 */ XK_Num_Lock, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x46 */ XK_Scroll_Lock, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x47 */ XK_KP_Home, XK_KP_7, NoSymbol, NoSymbol, -+ /* 0x48 */ XK_KP_Up, XK_KP_8, NoSymbol, NoSymbol, -+ /* 0x49 */ XK_KP_Prior, XK_KP_9, NoSymbol, NoSymbol, -+ /* 0x4a */ XK_KP_Subtract, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x4b */ XK_KP_Left, XK_KP_4, NoSymbol, NoSymbol, -+ /* 0x4c */ XK_KP_Begin, XK_KP_5, NoSymbol, NoSymbol, -+ /* 0x4d */ XK_KP_Right, XK_KP_6, NoSymbol, NoSymbol, -+ /* 0x4e */ XK_KP_Add, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x4f */ XK_KP_End, XK_KP_1, NoSymbol, NoSymbol, -+ /* 0x50 */ XK_KP_Down, XK_KP_2, NoSymbol, NoSymbol, -+ /* 0x51 */ XK_KP_Next, XK_KP_3, NoSymbol, NoSymbol, -+ /* 0x52 */ XK_KP_Insert, XK_KP_0, NoSymbol, NoSymbol, -+ /* 0x53 */ XK_KP_Delete, XK_KP_Decimal, NoSymbol, NoSymbol, -+ /* 0x54 */ XK_Sys_Req, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x55 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x56 */ XK_less, XK_greater, NoSymbol, NoSymbol, -+ /* 0x57 */ XK_F11, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x58 */ XK_F12, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x59 */ XK_Home, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x5a */ XK_Up, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x5b */ XK_Prior, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x5c */ XK_Left, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x5d */ XK_Begin, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x5e */ XK_Right, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x5f */ XK_End, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x60 */ XK_Down, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x61 */ XK_Next, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x62 */ XK_Insert, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x63 */ XK_Delete, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x64 */ XK_KP_Enter, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x65 */ XK_Control_R, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x66 */ XK_Pause, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x67 */ XK_Print, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x68 */ XK_KP_Divide, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x69 */ XK_Alt_R, XK_Meta_R, NoSymbol, NoSymbol, -+ /* 0x6a */ XK_Break, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x6b */ XK_Meta_L, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x6c */ XK_Meta_R, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x6d */ XK_Menu, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x6e */ XK_F13, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x6f */ XK_F14, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x70 */ XK_F15, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x71 */ XK_F16, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x72 */ XK_F17, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x73 */ XK_backslash, XK_underscore, NoSymbol, NoSymbol, -+ /* 0x74 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x75 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x76 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x77 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x78 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x79 */ XK_Henkan, XK_Mode_switch, NoSymbol, NoSymbol, -+ /* 0x7a */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x7b */ XK_Muhenkan, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x7c */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x7d */ XK_backslash, XK_bar, NoSymbol, NoSymbol, -+ /* 0x7e */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x7f */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, -+}; -+ -+#define N_PREDEFINED_KEYS (sizeof(map) / (sizeof(KeySym) * GLYPHS_PER_KEY)) -diff --git a/hw/vnc/loginauth.c b/hw/vnc/loginauth.c -new file mode 100644 -index 0000000..2915c4f ---- /dev/null -+++ b/hw/vnc/loginauth.c -@@ -0,0 +1,138 @@ -+/* -+ * loginauth.c - deal with login-style Unix authentication. -+ * -+ * This file implements the UnixLogin authentication protocol when setting up -+ * an RFB connection. -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ */ -+ -+/* -+ * Copyright (C) 2003 Constantin Kaplinsky. 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. -+ */ -+ -+#ifdef linux -+#include /* XXX xserver has a shadow.h file too */ -+#endif -+#include -+#include -+#include -+#include -+#include -+#include "rfb.h" -+ -+void rfbLoginAuthProcessClientMessage(rfbClientPtr cl) -+{ -+ int n1 = 0, n2 = 0; -+ CARD32 loginLen, passwdLen, authResult; -+ char *loginBuf, *passwdBuf; -+ struct passwd *ps; -+ char *encPasswd1, *encPasswd2; -+ Bool ok; -+ -+ if ((n1 = ReadExact(cl->sock, (char *)&loginLen, -+ sizeof(loginLen))) <= 0 || -+ (n2 = ReadExact(cl->sock, (char *)&passwdLen, -+ sizeof(passwdLen))) <= 0) { -+ if (n1 != 0 || n2 != 0) -+ rfbLogPerror("rfbLoginAuthProcessClientMessage: read"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ loginLen = Swap32IfLE(loginLen); -+ passwdLen = Swap32IfLE(passwdLen); -+ loginBuf = (char *)xalloc(loginLen + 1); -+ passwdBuf = (char *)xalloc(passwdLen + 1); -+ -+ n1 = n2 = 0; -+ if ((n1 = ReadExact(cl->sock, loginBuf, loginLen)) <= 0 || -+ (n2 = ReadExact(cl->sock, passwdBuf, passwdLen)) <= 0) { -+ if (n1 != 0 || n2 != 0) -+ rfbLogPerror("rfbLoginAuthProcessClientMessage: read"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ loginBuf[loginLen] = '\0'; -+ passwdBuf[passwdLen] = '\0'; -+ -+ encPasswd1 = encPasswd2 = NULL; -+ -+ ps = getpwnam(loginBuf); -+ if (ps == NULL) { -+ rfbLog("rfbLoginAuthProcessClientMessage: " -+ "Cannot get password file entry for \"%s\"\n", loginBuf); -+ } else { -+ encPasswd1 = ps->pw_passwd; -+#ifdef linux -+ if (strlen(ps->pw_passwd) == 1) { -+ struct spwd *sps; -+ -+ sps = getspnam(loginBuf); -+ if (sps == NULL) { -+ rfbLog("rfbLoginAuthProcessClientMessage:" -+ " getspnam() failed for user \"%s\"\n", loginBuf); -+ } else { -+ encPasswd1 = sps->sp_pwdp; -+ } -+ } -+#endif -+ encPasswd2 = crypt(passwdBuf, encPasswd1); -+ memset(passwdBuf, 0, strlen(passwdBuf)); -+ } -+ -+ ok = FALSE; -+ if (encPasswd1 != NULL && encPasswd2 != NULL) { -+ if (strcmp(encPasswd1, encPasswd2) == 0) -+ ok = TRUE; -+ } -+ -+ if (!ok) { -+ rfbLog("rfbAuthProcessClientMessage: authentication failed from %s\n", -+ cl->host); -+ -+ if (rfbAuthConsiderBlocking(cl)) { -+ authResult = Swap32IfLE(rfbVncAuthTooMany); -+ } else { -+ authResult = Swap32IfLE(rfbVncAuthFailed); -+ } -+ -+ if (WriteExact(cl->sock, (char *)&authResult, -+ sizeof(authResult)) < 0) { -+ rfbLogPerror("rfbLoginAuthProcessClientMessage: write"); -+ } -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ rfbAuthUnblock(cl); -+ -+ cl->login = strdup(loginBuf); -+ rfbLog("Login-style authentication passed for user %s at %s\n", -+ cl->login, cl->host); -+ -+ authResult = Swap32IfLE(rfbVncAuthOK); -+ -+ if (WriteExact(cl->sock, (char *)&authResult, sizeof(authResult)) < 0) { -+ rfbLogPerror("rfbLoginAuthProcessClientMessage: write"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ cl->state = RFB_INITIALISATION; -+} -+ -diff --git a/hw/vnc/rdp.c b/hw/vnc/rdp.c -new file mode 100644 -index 0000000..cd9aedb ---- /dev/null -+++ b/hw/vnc/rdp.c -@@ -0,0 +1,142 @@ -+/* -+ * Copyright (C) 2004 Alan Hourihane. 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 -+#include -+#include -+#include -+#include -+#include "rfb.h" -+ -+typedef struct rdpClientRec { -+ ScreenPtr pScreen; -+} rdpClientRec, *rdpClientPtr; -+ -+typedef struct rdpInRec { -+ char version; -+ char pad; -+ short length; -+ char hdrlen; -+ unsigned char pdu; -+} rdpInRec, *rdpInPtr; -+ -+static void -+rdpCloseSock(ScreenPtr pScreen) -+{ -+ VNCSCREENPTR(pScreen); -+ close(pVNC->rdpListenSock); -+ RemoveEnabledDevice(pVNC->rdpListenSock); -+ pVNC->rdpListenSock = -1; -+} -+ -+/* -+ * rdpNewClient is called when a new connection has been made by whatever -+ * means. -+ */ -+ -+static rdpClientPtr -+rdpNewClient(ScreenPtr pScreen, int sock) -+{ -+ rdpInRec in; -+ rdpClientPtr cl; -+ BoxRec box; -+ struct sockaddr_in addr; -+ SOCKLEN_T addrlen = sizeof(struct sockaddr_in); -+ VNCSCREENPTR(pScreen); -+ int i; -+ -+ cl = (rdpClientPtr)xalloc(sizeof(rdpClientRec)); -+ -+ cl->pScreen = pScreen; -+ -+ in.version = 3; -+ in.pad = 0; -+ in.length = 0x600; /* big endian */ -+ in.hdrlen = 0x00; -+ in.pdu = 0xCC; -+ -+ if (WriteExact(sock, (char *)&in, sizeof(rdpInRec)) < 0) { -+ rfbLogPerror("rfbNewClient: write"); -+ rdpCloseSock(pScreen); -+ return NULL; -+ } -+ -+ return cl; -+} -+/* -+ * rdpCheckFds is called from ProcessInputEvents to check for input on the -+ * HTTP socket(s). If there is input to process, rdpProcessInput is called. -+ */ -+ -+void -+rdpCheckFds(ScreenPtr pScreen) -+{ -+ VNCSCREENPTR(pScreen); -+ int nfds; -+ fd_set fds; -+ struct timeval tv; -+ struct sockaddr_in addr; -+ int sock; -+ const int one =1; -+ SOCKLEN_T addrlen = sizeof(addr); -+ -+ FD_ZERO(&fds); -+ FD_SET(pVNC->rdpListenSock, &fds); -+ tv.tv_sec = 0; -+ tv.tv_usec = 0; -+ nfds = select(pVNC->rdpListenSock + 1, &fds, NULL, NULL, &tv); -+ if (nfds == 0) { -+ return; -+ } -+ if (nfds < 0) { -+ if (errno != EINTR) -+ rfbLogPerror("httpCheckFds: select"); -+ return; -+ } -+ -+ if (pVNC->rdpListenSock != -1 && FD_ISSET(pVNC->rdpListenSock, &fds)) { -+ -+ if ((sock = accept(pVNC->rdpListenSock, -+ (struct sockaddr *)&addr, &addrlen)) < 0) { -+ rfbLogPerror("rdpCheckFds: accept"); -+ return; -+ } -+ -+ if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) { -+ rfbLogPerror("rdpCheckFds: fcntl"); -+ close(sock); -+ return; -+ } -+ -+ if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, -+ (char *)&one, sizeof(one)) < 0) { -+ rfbLogPerror("rdpCheckFds: setsockopt"); -+ close(sock); -+ return; -+ } -+ -+ rfbLog("\n"); -+ -+ rfbLog("Got RDP connection from client %s\n", inet_ntoa(addr.sin_addr)); -+ -+ AddEnabledDevice(sock); -+ -+ rdpNewClient(pScreen, sock); -+ } -+} -diff --git a/hw/vnc/rfb.h b/hw/vnc/rfb.h -new file mode 100644 -index 0000000..ccb0411 ---- /dev/null -+++ b/hw/vnc/rfb.h -@@ -0,0 +1,725 @@ -+/* -+ * rfb.h - header file for RFB DDX implementation. -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ */ -+ -+/* -+ * Copyright (C) 2000-2004 Const Kaplinsky. All Rights Reserved. -+ * Copyright (C) 2000 Tridia Corporation. All Rights Reserved. -+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. -+ * -+ * This is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This software is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this software; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -+ * USA. -+ */ -+ -+#if HAVE_DIX_CONFIG_H -+#include "dix-config.h" -+#endif -+ -+#include -+#if 0 && XFREE86VNC /* not yet */ -+#include "xf86.h" -+#include "xf86_OSproc.h" -+#include "xf86_ansic.h" -+#endif -+#include "scrnintstr.h" -+#include "colormapst.h" -+#include "dixstruct.h" -+#include "gcstruct.h" -+#include "regionstr.h" -+#include "windowstr.h" -+#include "dixfontstr.h" -+#if 1 /* && !XFREE86VNC */ -+/*#include "osdep.h"*/ -+#endif -+#include -+#include -+#define _VNC_SERVER -+#include -+#if 1/*def RENDER*/ -+#include "picturestr.h" -+#endif -+ -+#if defined(sun) || defined(hpux) -+#define SOCKLEN_T int -+#else -+#define SOCKLEN_T socklen_t -+#endif -+ -+/* It's a good idea to keep these values a bit greater than required. */ -+#define MAX_ENCODINGS 10 -+#define MAX_SECURITY_TYPES 4 -+#define MAX_TUNNELING_CAPS 16 -+#define MAX_AUTH_CAPS 16 -+ -+/* -+ * HTTP_BUF_SIZE for http transfers -+ */ -+#define HTTP_BUF_SIZE 32768 -+ -+/* -+ * UPDATE_BUF_SIZE must be big enough to send at least one whole line of the -+ * framebuffer. So for a max screen width of say 2K with 32-bit pixels this -+ * means 8K minimum. -+ */ -+#define UPDATE_BUF_SIZE 30000 -+ -+#if XFREE86VNC -+#include "xf86.h" -+#include "vnc.h" -+#define VNCSCREENPTR(ptr) \ -+ vncScreenPtr pVNC = VNCPTR(ptr) -+#else -+#define VNCSCREENPTR(ptr) \ -+/* Soon \ -+ rfbScreenInfoPtr pVNC = rfbScreen[ptr->myNum] \ -+*/ \ -+ rfbScreenInfoPtr pVNC = &rfbScreen -+#endif -+ -+/* -+ * Per-screen (framebuffer) structure. There is only one of these, since we -+ * don't allow the X server to have multiple screens. -+ */ -+ -+typedef struct -+{ -+ int rfbPort; -+ int rdpPort; -+ int udpPort; -+ int rfbListenSock; -+ int rdpListenSock; -+ int udpSock; -+ int httpPort; -+ int httpListenSock; -+ int httpSock; -+ char * httpDir; -+ char buf[HTTP_BUF_SIZE]; -+ Bool udpSockConnected; -+ char * rfbAuthPasswdFile; -+ size_t buf_filled; -+ int maxFd; -+ fd_set allFds; -+ Bool useGetImage; -+ Bool noCursor; -+ Bool rfbAlwaysShared; -+ Bool rfbNeverShared; -+ Bool rfbDontDisconnect; -+ Bool rfbUserAccept; -+ Bool rfbViewOnly; -+ ColormapPtr savedColormap; -+ ColormapPtr rfbInstalledColormap; -+ rfbPixelFormat rfbServerFormat; -+ Bool rfbAuthTooManyTries; -+ int rfbAuthTries; -+ Bool loginAuthEnabled; -+ struct in_addr interface; -+ OsTimerPtr timer; -+ char updateBuf[UPDATE_BUF_SIZE]; -+ int ublen; -+ int width; -+ int paddedWidthInBytes; -+ int height; -+ int depth; -+ int bitsPerPixel; -+ int sizeInBytes; -+ unsigned char *pfbMemory; -+ Pixel blackPixel; -+ Pixel whitePixel; -+ -+ /* The following two members are used to minimise the amount of unnecessary -+ drawing caused by cursor movement. Whenever any drawing affects the -+ part of the screen where the cursor is, the cursor is removed first and -+ then the drawing is done (this is what the sprite routines test for). -+ Afterwards, however, we do not replace the cursor, even when the cursor -+ is logically being moved across the screen. We only draw the cursor -+ again just as we are about to send the client a framebuffer update. -+ -+ We need to be careful when removing and drawing the cursor because of -+ their relationship with the normal drawing routines. The drawing -+ routines can invoke the cursor routines, but also the cursor routines -+ themselves end up invoking drawing routines. -+ -+ Removing the cursor (rfbSpriteRemoveCursor) is eventually achieved by -+ doing a CopyArea from a pixmap to the screen, where the pixmap contains -+ the saved contents of the screen under the cursor. Before doing this, -+ however, we set cursorIsDrawn to FALSE. Then, when CopyArea is called, -+ it sees that cursorIsDrawn is FALSE and so doesn't feel the need to -+ (recursively!) remove the cursor before doing it. -+ -+ Putting up the cursor (rfbSpriteRestoreCursor) involves a call to -+ PushPixels. While this is happening, cursorIsDrawn must be FALSE so -+ that PushPixels doesn't think it has to remove the cursor first. -+ Obviously cursorIsDrawn is set to TRUE afterwards. -+ -+ Another problem we face is that drawing routines sometimes cause a -+ framebuffer update to be sent to the RFB client. When the RFB client is -+ already waiting for a framebuffer update and some drawing to the -+ framebuffer then happens, the drawing routine sees that the client is -+ ready, so it calls rfbSendFramebufferUpdate. If the cursor is not drawn -+ at this stage, it must be put up, and so rfbSpriteRestoreCursor is -+ called. However, if the original drawing routine was actually called -+ from within rfbSpriteRestoreCursor or rfbSpriteRemoveCursor we don't -+ want this to happen. So both the cursor routines set -+ dontSendFramebufferUpdate to TRUE, and all the drawing routines check -+ this before calling rfbSendFramebufferUpdate. */ -+ -+ Bool cursorIsDrawn; /* TRUE if the cursor is currently drawn */ -+ Bool dontSendFramebufferUpdate; /* TRUE while removing or drawing the -+ cursor */ -+ -+ /* wrapped screen functions */ -+ -+ CloseScreenProcPtr CloseScreen; -+ CreateGCProcPtr CreateGC; -+ PaintWindowBackgroundProcPtr PaintWindowBackground; -+ PaintWindowBorderProcPtr PaintWindowBorder; -+ CopyWindowProcPtr CopyWindow; -+ ClearToBackgroundProcPtr ClearToBackground; -+ RestoreAreasProcPtr RestoreAreas; -+ ScreenWakeupHandlerProcPtr WakeupHandler; -+#ifdef CHROMIUM -+ RealizeWindowProcPtr RealizeWindow; -+ UnrealizeWindowProcPtr UnrealizeWindow; -+ DestroyWindowProcPtr DestroyWindow; -+ ResizeWindowProcPtr ResizeWindow; -+ PositionWindowProcPtr PositionWindow; -+ ClipNotifyProcPtr ClipNotify; -+#endif -+#ifdef RENDER -+ CompositeProcPtr Composite; -+#endif -+ -+} rfbScreenInfo, *rfbScreenInfoPtr; -+ -+ -+/* -+ * rfbTranslateFnType is the type of translation functions. -+ */ -+ -+struct rfbClientRec; -+typedef void (*rfbTranslateFnType)(ScreenPtr pScreen, -+ char *table, rfbPixelFormat *in, -+ rfbPixelFormat *out, -+ unsigned char *iptr, char *optr, -+ int bytesBetweenInputLines, -+ int width, int height, -+ int x, int y); -+ -+ -+/* -+ * Per-client structure. -+ */ -+ -+typedef struct rfbClientRec { -+ int sock; -+ char *host; -+ char *login; -+ -+ int protocol_minor_ver; /* RFB protocol minor version in use. */ -+ Bool protocol_tightvnc; /* TightVNC protocol extensions enabled */ -+ -+ /* Possible client states: */ -+ -+ enum { -+ RFB_PROTOCOL_VERSION, /* establishing protocol version */ -+ RFB_SECURITY_TYPE, /* negotiating security (RFB v.3.7) */ -+ RFB_TUNNELING_TYPE, /* establishing tunneling (RFB v.3.7t) */ -+ RFB_AUTH_TYPE, /* negotiating authentication (RFB v.3.7t) */ -+ RFB_AUTHENTICATION, /* authenticating (VNC authentication) */ -+ RFB_INITIALISATION, /* sending initialisation messages */ -+ RFB_NORMAL /* normal protocol messages */ -+ } state; -+ -+ Bool viewOnly; /* Do not accept input from this client. */ -+ -+ Bool reverseConnection; -+ -+ Bool readyForSetColourMapEntries; -+ -+ Bool useCopyRect; -+ int preferredEncoding; -+ int correMaxWidth, correMaxHeight; -+ -+ /* The list of security types sent to this client (protocol 3.7). -+ Note that the first entry is the number of list items following. */ -+ -+ CARD8 securityTypes[MAX_SECURITY_TYPES + 1]; -+ -+ /* Lists of capability codes sent to clients. We remember these -+ lists to restrict clients from choosing those tunneling and -+ authentication types that were not advertised. */ -+ -+ int nAuthCaps; -+ CARD32 authCaps[MAX_AUTH_CAPS]; -+ -+ /* This is not useful while we don't support tunneling: -+ int nTunnelingCaps; -+ CARD32 tunnelingCaps[MAX_TUNNELING_CAPS]; */ -+ -+ /* The following member is only used during VNC authentication */ -+ -+ CARD8 authChallenge[CHALLENGESIZE]; -+ -+ /* The following members represent the update needed to get the client's -+ framebuffer from its present state to the current state of our -+ framebuffer. -+ -+ If the client does not accept CopyRect encoding then the update is -+ simply represented as the region of the screen which has been modified -+ (modifiedRegion). -+ -+ If the client does accept CopyRect encoding, then the update consists of -+ two parts. First we have a single copy from one region of the screen to -+ another (the destination of the copy is copyRegion), and second we have -+ the region of the screen which has been modified in some other way -+ (modifiedRegion). -+ -+ Although the copy is of a single region, this region may have many -+ rectangles. When sending an update, the copyRegion is always sent -+ before the modifiedRegion. This is because the modifiedRegion may -+ overlap parts of the screen which are in the source of the copy. -+ -+ In fact during normal processing, the modifiedRegion may even overlap -+ the destination copyRegion. Just before an update is sent we remove -+ from the copyRegion anything in the modifiedRegion. */ -+ -+ RegionRec copyRegion; /* the destination region of the copy */ -+ int copyDX, copyDY; /* the translation by which the copy happens */ -+ -+ RegionRec modifiedRegion; /* the region of the screen modified in any -+ other way */ -+ -+ /* As part of the FramebufferUpdateRequest, a client can express interest -+ in a subrectangle of the whole framebuffer. This is stored in the -+ requestedRegion member. In the normal case this is the whole -+ framebuffer if the client is ready, empty if it's not. */ -+ -+ RegionRec requestedRegion; -+ -+ /* The following members represent the state of the "deferred update" timer -+ - when the framebuffer is modified and the client is ready, in most -+ cases it is more efficient to defer sending the update by a few -+ milliseconds so that several changes to the framebuffer can be combined -+ into a single update. */ -+ -+ Bool deferredUpdateScheduled; -+ OsTimerPtr deferredUpdateTimer; -+ -+ /* translateFn points to the translation function which is used to copy -+ and translate a rectangle from the framebuffer to an output buffer. */ -+ -+ rfbTranslateFnType translateFn; -+ -+ char *translateLookupTable; -+ -+ rfbPixelFormat format; -+ -+ /* statistics */ -+ -+ int rfbBytesSent[MAX_ENCODINGS]; -+ int rfbRectanglesSent[MAX_ENCODINGS]; -+ int rfbLastRectMarkersSent; -+ int rfbLastRectBytesSent; -+ int rfbCursorShapeBytesSent; -+ int rfbCursorShapeUpdatesSent; -+ int rfbCursorPosBytesSent; -+ int rfbCursorPosUpdatesSent; -+ int rfbFramebufferUpdateMessagesSent; -+ int rfbRawBytesEquivalent; -+ int rfbKeyEventsRcvd; -+ int rfbPointerEventsRcvd; -+ -+ /* zlib encoding -- necessary compression state info per client */ -+ -+ struct z_stream_s compStream; -+ Bool compStreamInited; -+ -+ CARD32 zlibCompressLevel; -+ -+ /* tight encoding -- preserve zlib streams' state for each client */ -+ -+ z_stream zsStruct[4]; -+ Bool zsActive[4]; -+ int zsLevel[4]; -+ int tightCompressLevel; -+ int tightQualityLevel; -+ -+ Bool enableLastRectEncoding; /* client supports LastRect encoding */ -+ Bool enableCursorShapeUpdates; /* client supports cursor shape updates */ -+ Bool enableCursorPosUpdates; /* client supports PointerPos updates */ -+#ifdef CHROMIUM -+ Bool enableChromiumEncoding; /* client supports Chromium encoding */ -+#endif -+ Bool useRichCursorEncoding; /* rfbEncodingRichCursor is preferred */ -+ Bool cursorWasChanged; /* cursor shape update should be sent */ -+ Bool cursorWasMoved; /* cursor position update should be sent */ -+ -+ int cursorX, cursorY; /* client's cursor position */ -+ -+ struct rfbClientRec *next; -+ -+ ScreenPtr pScreen; -+ int userAccepted; -+ -+#ifdef CHROMIUM -+ unsigned int chromium_port; -+ unsigned int chromium_msport; -+#endif -+} rfbClientRec, *rfbClientPtr; -+ -+#ifdef CHROMIUM -+typedef struct CRWindowTable { -+ unsigned long CRwinId; -+ unsigned long XwinId; -+ BoxPtr clipRects; -+ int numRects; -+ struct CRWindowTable *next; -+} CRWindowTable, *CRWindowTablePtr; -+ -+extern struct CRWindowTable *windowTable; -+#endif -+ -+/* -+ * This macro is used to test whether there is a framebuffer update needing to -+ * be sent to the client. -+ */ -+ -+#define FB_UPDATE_PENDING(cl) \ -+ ((!(cl)->enableCursorShapeUpdates && !pVNC->cursorIsDrawn) || \ -+ ((cl)->enableCursorShapeUpdates && (cl)->cursorWasChanged) || \ -+ ((cl)->enableCursorPosUpdates && (cl)->cursorWasMoved) || \ -+ REGION_NOTEMPTY(((cl)->pScreen),&(cl)->copyRegion) || \ -+ REGION_NOTEMPTY(((cl)->pScreen),&(cl)->modifiedRegion)) -+ -+/* -+ * This macro creates an empty region (ie. a region with no areas) if it is -+ * given a rectangle with a width or height of zero. It appears that -+ * REGION_INTERSECT does not quite do the right thing with zero-width -+ * rectangles, but it should with completely empty regions. -+ */ -+ -+#define SAFE_REGION_INIT(pscreen, preg, rect, size) \ -+{ \ -+ if ( ( (rect) ) && \ -+ ( ( (rect)->x2 == (rect)->x1 ) || \ -+ ( (rect)->y2 == (rect)->y1 ) ) ) { \ -+ REGION_NULL( (pscreen), (preg) ); \ -+ } else { \ -+ REGION_INIT( (pscreen), (preg), (rect), (size) ); \ -+ } \ -+} -+ -+/* -+ * An rfbGCRec is where we store the pointers to the original GC funcs and ops -+ * which we wrap (NULL means not wrapped). -+ */ -+ -+typedef struct { -+ GCFuncs *wrapFuncs; -+ GCOps *wrapOps; -+} rfbGCRec, *rfbGCPtr; -+ -+ -+ -+/* -+ * Macros for endian swapping. -+ */ -+ -+#define Swap16(s) ((((s) & 0xff) << 8) | (((s) >> 8) & 0xff)) -+ -+#define Swap32(l) (((l) >> 24) | \ -+ (((l) & 0x00ff0000) >> 8) | \ -+ (((l) & 0x0000ff00) << 8) | \ -+ ((l) << 24)) -+ -+static const int rfbEndianTest = 1; -+ -+#define Swap16IfLE(s) (*(const char *)&rfbEndianTest ? Swap16(s) : (s)) -+ -+#define Swap32IfLE(l) (*(const char *)&rfbEndianTest ? Swap32(l) : (l)) -+ -+ -+/* -+ * Macro to fill in an rfbCapabilityInfo structure (protocol 3.130). -+ * Normally, using macros is no good, but this macro saves us from -+ * writing constants twice -- it constructs signature names from codes. -+ * Note that "code_sym" argument should be a single symbol, not an expression. -+ */ -+ -+#define SetCapInfo(cap_ptr, code_sym, vendor) \ -+{ \ -+ rfbCapabilityInfo *pcap; \ -+ pcap = (cap_ptr); \ -+ pcap->code = Swap32IfLE(code_sym); \ -+ memcpy(pcap->vendorSignature, (vendor), \ -+ sz_rfbCapabilityInfoVendor); \ -+ memcpy(pcap->nameSignature, sig_##code_sym, \ -+ sz_rfbCapabilityInfoName); \ -+} -+ -+ -+/* init.c */ -+ -+extern char *desktopName; -+extern char rfbThisHost[]; -+extern Atom VNC_LAST_CLIENT_ID; -+ -+extern rfbScreenInfo rfbScreen; -+extern int rfbGCIndex; -+ -+extern int inetdSock; -+ -+extern int rfbBitsPerPixel(int depth); -+extern void rfbLog(char *format, ...); -+extern void rfbLogPerror(char *str); -+ -+ -+/* sockets.c */ -+ -+extern int rfbMaxClientWait; -+ -+extern Bool rfbInitSockets(ScreenPtr pScreen); -+extern void rfbDisconnectUDPSock(ScreenPtr pScreen); -+extern void rfbCloseSock(ScreenPtr pScreen, int sock); -+extern void rfbCheckFds(ScreenPtr pScreen); -+extern void rfbWaitForClient(int sock); -+extern int rfbConnect(ScreenPtr pScreen, char *host, int port); -+ -+extern int ReadExact(int sock, char *buf, int len); -+extern int WriteExact(int sock, char *buf, int len); -+extern int ListenOnTCPPort(ScreenPtr pScreen, int port); -+extern int ListenOnUDPPort(ScreenPtr pScreen, int port); -+extern int ConnectToTcpAddr(char *host, int port); -+ -+ -+/* cmap.c */ -+ -+ -+extern int rfbListInstalledColormaps(ScreenPtr pScreen, Colormap *pmaps); -+extern void rfbInstallColormap(ColormapPtr pmap); -+extern void rfbUninstallColormap(ColormapPtr pmap); -+extern void rfbStoreColors(ColormapPtr pmap, int ndef, xColorItem *pdefs); -+ -+ -+/* draw.c */ -+ -+extern int rfbDeferUpdateTime; -+ -+extern void -+rfbComposite( -+ CARD8 op, -+ PicturePtr pSrc, -+ PicturePtr pMask, -+ PicturePtr pDst, -+ INT16 xSrc, -+ INT16 ySrc, -+ INT16 xMask, -+ INT16 yMask, -+ INT16 xDst, -+ INT16 yDst, -+ CARD16 width, -+ CARD16 height -+); -+ -+extern void rfbGlyphs( -+ CARD8 op, -+ PicturePtr pSrc, -+ PicturePtr pDst, -+ PictFormatPtr maskFormat, -+ INT16 xSrc, -+ INT16 ySrc, -+ int nlistInit, -+ GlyphListPtr listInit, -+ GlyphPtr *glyphsInit -+); -+extern Bool rfbCloseScreen(int,ScreenPtr); -+extern Bool rfbCreateGC(GCPtr); -+extern void rfbPaintWindowBackground(WindowPtr, RegionPtr, int what); -+extern void rfbPaintWindowBorder(WindowPtr, RegionPtr, int what); -+extern void rfbCopyWindow(WindowPtr, DDXPointRec, RegionPtr); -+#ifdef CHROMIUM -+extern Bool rfbRealizeWindow(WindowPtr); -+extern Bool rfbUnrealizeWindow(WindowPtr); -+extern Bool rfbDestroyWindow(WindowPtr); -+extern void rfbResizeWindow(WindowPtr, int x, int y, unsigned int w, unsigned int h, WindowPtr pSib); -+extern Bool rfbPositionWindow(WindowPtr, int x, int y); -+extern void rfbClipNotify(WindowPtr, int x, int y); -+#endif -+extern void rfbClearToBackground(WindowPtr, int x, int y, int w, -+ int h, Bool generateExposures); -+extern RegionPtr rfbRestoreAreas(WindowPtr, RegionPtr); -+ -+ -+/* cutpaste.c */ -+ -+extern void rfbSetXCutText(char *str, int len); -+extern void rfbGotXCutText(char *str, int len); -+ -+ -+/* kbdptr.c */ -+ -+extern Bool compatibleKbd; -+extern unsigned char ptrAcceleration; -+ -+extern void PtrDeviceInit(void); -+extern void PtrDeviceOn(DeviceIntPtr pDev); -+extern void PtrDeviceOff(void); -+extern void PtrDeviceControl(DeviceIntPtr dev, PtrCtrl *ctrl); -+extern void PtrAddEvent(int buttonMask, int x, int y, rfbClientPtr cl); -+ -+extern void KbdDeviceInit(DeviceIntPtr pDevice, KeySymsPtr pKeySyms, CARD8 *pModMap); -+extern void KbdDeviceOn(void); -+extern void KbdDeviceOff(void); -+extern void KbdAddEvent(Bool down, KeySym keySym, rfbClientPtr cl); -+extern void KbdReleaseAllKeys(void); -+ -+ -+/* rfbserver.c */ -+ -+ -+extern rfbClientPtr rfbClientHead; -+extern rfbClientPtr pointerClient; -+ -+extern void rfbNewClientConnection(ScreenPtr pScreen, int sock); -+extern rfbClientPtr rfbReverseConnection(ScreenPtr pScreen, char *host, int port); -+extern void rfbRootPropertyChange(ScreenPtr pScreen); -+extern void rfbClientConnectionGone(int sock); -+extern void rfbProcessClientMessage(ScreenPtr pScreen, int sock); -+extern void rfbClientConnFailed(rfbClientPtr cl, char *reason); -+extern void rfbNewUDPConnection(int sock); -+extern void rfbProcessUDPInput(ScreenPtr pScreen, int sock); -+extern Bool rfbSendFramebufferUpdate(ScreenPtr pScreen, rfbClientPtr cl); -+extern Bool rfbSendRectEncodingRaw(rfbClientPtr cl, int x,int y,int w,int h); -+extern Bool rfbSendUpdateBuf(rfbClientPtr cl); -+extern Bool rfbSendSetColourMapEntries(rfbClientPtr cl, int firstColour, -+ int nColours); -+extern void rfbSendBell(void); -+extern void rfbSendServerCutText(char *str, int len); -+extern void rfbUserAllow(int sock, int accept); -+extern void rfbSetClip (WindowPtr pWin, BOOL enable); -+ -+extern int GenerateVncConnectedEvent(int sock); -+extern int GenerateVncDisconnectedEvent(int sock); -+ -+#ifdef CHROMIUM -+extern void rfbSendChromiumWindowShow(unsigned int winid, unsigned int show); -+extern void rfbSendChromiumMoveResizeWindow(unsigned int winid, int x, int y, unsigned int w, unsigned int h); -+extern void rfbSendChromiumClipList(unsigned int winid, BoxPtr pClipRects, int numClipRects); -+#endif -+ -+/* translate.c */ -+ -+extern Bool rfbEconomicTranslate; -+ -+extern void rfbTranslateNone(ScreenPtr pScreen, char *table, rfbPixelFormat *in, -+ rfbPixelFormat *out, -+ unsigned char *iptr, char *optr, -+ int bytesBetweenInputLines, -+ int width, int height, -+ int x, int y); -+extern Bool rfbSetTranslateFunction(rfbClientPtr cl); -+extern void rfbSetClientColourMaps(int firstColour, int nColours); -+extern Bool rfbSetClientColourMap(rfbClientPtr cl, int firstColour, -+ int nColours); -+ -+ -+/* httpd.c */ -+ -+extern Bool httpInitSockets(ScreenPtr pScreen); -+extern void httpCheckFds(ScreenPtr pScreen); -+ -+ -+/* vncext.c */ -+ -+#ifdef CHROMIUM -+extern void rfbSendChromiumStart(unsigned int ipaddress, unsigned int crServerPort, unsigned int mothershipPort); -+extern void rfbChromiumMonitorWindowID(unsigned int cr_windowid, unsigned long windowid); -+int GenerateVncChromiumConnectedEvent(int sock); -+#endif -+ -+ -+/* auth.c */ -+ -+extern void rfbAuthNewClient(rfbClientPtr cl); -+extern void rfbProcessClientSecurityType(rfbClientPtr cl); -+extern void rfbProcessClientTunnelingType(rfbClientPtr cl); -+extern void rfbProcessClientAuthType(rfbClientPtr cl); -+extern void rfbVncAuthProcessResponse(rfbClientPtr cl); -+ -+/* Functions to prevent too many successive authentication failures */ -+extern Bool rfbAuthConsiderBlocking(rfbClientPtr cl); -+extern void rfbAuthUnblock(rfbClientPtr cl); -+extern Bool rfbAuthIsBlocked(rfbClientPtr cl); -+ -+/* loginauth.c */ -+ -+extern void rfbLoginAuthProcessClientMessage(rfbClientPtr cl); -+ -+/* rre.c */ -+ -+extern Bool rfbSendRectEncodingRRE(rfbClientPtr cl, int x,int y,int w,int h); -+ -+ -+/* corre.c */ -+ -+extern Bool rfbSendRectEncodingCoRRE(rfbClientPtr cl, int x,int y,int w,int h); -+ -+ -+/* hextile.c */ -+ -+extern Bool rfbSendRectEncodingHextile(rfbClientPtr cl, int x, int y, int w, -+ int h); -+ -+ -+/* zlib.c */ -+ -+/* Minimum zlib rectangle size in bytes. Anything smaller will -+ * not compress well due to overhead. -+ */ -+#define VNC_ENCODE_ZLIB_MIN_COMP_SIZE (17) -+ -+/* Set maximum zlib rectangle size in pixels. Always allow at least -+ * two scan lines. -+ */ -+#define ZLIB_MAX_RECT_SIZE (128*256) -+#define ZLIB_MAX_SIZE(min) ((( min * 2 ) > ZLIB_MAX_RECT_SIZE ) ? \ -+ ( min * 2 ) : ZLIB_MAX_RECT_SIZE ) -+ -+extern Bool rfbSendRectEncodingZlib(rfbClientPtr cl, int x, int y, int w, -+ int h); -+ -+ -+/* tight.c */ -+ -+#define TIGHT_DEFAULT_COMPRESSION 6 -+ -+extern Bool rfbTightDisableGradient; -+ -+extern int rfbNumCodedRectsTight(rfbClientPtr cl, int x,int y,int w,int h); -+extern Bool rfbSendRectEncodingTight(rfbClientPtr cl, int x,int y,int w,int h); -+ -+ -+/* cursor.c */ -+ -+extern Bool rfbSendCursorShape(rfbClientPtr cl, ScreenPtr pScreen); -+extern Bool rfbSendCursorPos(rfbClientPtr cl, ScreenPtr pScreen); -+ -+ -+/* stats.c */ -+ -+extern void rfbResetStats(rfbClientPtr cl); -+extern void rfbPrintStats(rfbClientPtr cl); -diff --git a/hw/vnc/rfbkeyb.c b/hw/vnc/rfbkeyb.c -new file mode 100644 -index 0000000..c65854b ---- /dev/null -+++ b/hw/vnc/rfbkeyb.c -@@ -0,0 +1,412 @@ -+/* -+ * Copyright (C) 2002 Alan Hourihane. 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. -+ * -+ * Author: Alan Hourihane -+ */ -+ -+#if XFREE86VNC -+#ifndef XFree86LOADER -+#include -+#include -+#endif -+ -+#include -+#include -+#define NEED_XF86_TYPES -+#if !defined(DGUX) -+#include -+#include -+#endif -+#include -+#include -+#include /* Needed for InitValuator/Proximity stuff */ -+#include -+#include -+ -+#ifdef XFree86LOADER -+#include -+#endif -+#else -+#include -+#include -+#include -+#endif -+ -+ -+extern Bool noXkbExtension; -+extern void rfbSendBell(void); -+extern DeviceIntPtr kbdDevice; -+ -+static const char *DEFAULTS[] = { -+ NULL -+}; -+ -+#include "keyboard.h" -+ -+#undef XKB -+#ifdef XKB -+#include -+#include -+#include -+ -+#if XFREE86VNC -+ /* -+ * would like to use an XkbComponentNamesRec here but can't without -+ * pulling in a bunch of header files. :-( -+ */ -+static char * xkbkeymap; -+static char * xkbkeycodes; -+static char * xkbtypes; -+static char * xkbcompat; -+static char * xkbsymbols; -+static char * xkbgeometry; -+static Bool xkbcomponents_specified; -+static char * xkbrules; -+static char * xkbmodel; -+static char * xkblayout; -+static char * xkbvariant; -+static char * xkboptions; -+#endif -+#endif -+ -+void -+KbdDeviceInit(DeviceIntPtr pDevice, KeySymsPtr pKeySyms, CARD8 *pModMap) -+{ -+ int i; -+ -+ kbdDevice = pDevice; -+ -+ for (i = 0; i < MAP_LENGTH; i++) -+ pModMap[i] = NoSymbol; -+ -+ pModMap[CONTROL_L_KEY_CODE] = ControlMask; -+ pModMap[CONTROL_R_KEY_CODE] = ControlMask; -+ pModMap[SHIFT_L_KEY_CODE] = ShiftMask; -+ pModMap[SHIFT_R_KEY_CODE] = ShiftMask; -+ pModMap[META_L_KEY_CODE] = Mod1Mask; -+ pModMap[META_R_KEY_CODE] = Mod1Mask; -+ pModMap[ALT_L_KEY_CODE] = Mod1Mask; -+ pModMap[ALT_R_KEY_CODE] = Mod1Mask; -+ -+ pKeySyms->minKeyCode = MIN_KEY_CODE; -+ pKeySyms->maxKeyCode = MAX_KEY_CODE; -+ pKeySyms->mapWidth = GLYPHS_PER_KEY; -+ -+ pKeySyms->map = (KeySym *)xalloc(sizeof(KeySym) -+ * MAP_LENGTH * GLYPHS_PER_KEY); -+ -+ if (!pKeySyms->map) { -+ ErrorF("xalloc failed\n"); -+ exit(1); -+ } -+ -+ for (i = 0; i < MAP_LENGTH * GLYPHS_PER_KEY; i++) -+ pKeySyms->map[i] = NoSymbol; -+ -+ for (i = 0; i < N_PREDEFINED_KEYS * GLYPHS_PER_KEY; i++) { -+ pKeySyms->map[i] = map[i]; -+ } -+} -+ -+ -+void -+KbdDeviceOn(void) -+{ -+} -+ -+ -+void -+KbdDeviceOff(void) -+{ -+} -+ -+ -+#if XFREE86VNC -+static int -+xf86rfbKeybControlProc(DeviceIntPtr device, int onoff) -+{ -+ KeySymsRec keySyms; -+ CARD8 modMap[MAP_LENGTH]; -+ DevicePtr pDev = (DevicePtr)device; -+ -+ switch (onoff) -+ { -+ case DEVICE_INIT: -+ KbdDeviceInit(device, &keySyms, modMap); -+#ifdef XKB -+ if (noXkbExtension) { -+#endif -+ InitKeyboardDeviceStruct(pDev, &keySyms, modMap, -+ (BellProcPtr)rfbSendBell, -+ (KbdCtrlProcPtr)NoopDDA); -+#ifdef XKB -+ } else { -+ XkbComponentNamesRec names; -+ if (XkbInitialMap) { -+ if ((xkbkeymap = strchr(XkbInitialMap, '/')) != NULL) -+ xkbkeymap++; -+ else -+ xkbkeymap = XkbInitialMap; -+ } -+ if (xkbkeymap) { -+ names.keymap = xkbkeymap; -+ names.keycodes = NULL; -+ names.types = NULL; -+ names.compat = NULL; -+ names.symbols = NULL; -+ names.geometry = NULL; -+ } else { -+ names.keymap = NULL; -+ names.keycodes = xkbkeycodes; -+ names.types = xkbtypes; -+ names.compat = xkbcompat; -+ names.symbols = xkbsymbols; -+ names.geometry = xkbgeometry; -+ } -+ if ((xkbkeymap || xkbcomponents_specified) -+ && (xkbmodel == NULL || xkblayout == NULL)) { -+ xkbrules = NULL; -+ } -+#if 0 -+ XkbSetRulesDflts(xkbrules, xkbmodel, -+ xkblayout, xkbvariant, -+ xkboptions); -+#endif -+ XkbInitKeyboardDeviceStruct(device, -+ &names, -+ &keySyms, -+ modMap, -+ (BellProcPtr)rfbSendBell, -+ (KbdCtrlProcPtr)NoopDDA); -+ } -+#endif -+ 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 void -+xf86rfbKeybUninit(InputDriverPtr drv, -+ InputInfoPtr pInfo, -+ int flags) -+{ -+ xf86rfbKeybControlProc(pInfo->dev, DEVICE_OFF); -+} -+ -+static InputInfoPtr -+xf86rfbKeybInit(InputDriverPtr drv, -+ IDevPtr dev, -+ int flags) -+{ -+ InputInfoPtr pInfo; -+ char *s; -+ Bool from; -+ -+ if (!(pInfo = xf86AllocateInput(drv, 0))) -+ return NULL; -+ -+ /* Initialise the InputInfoRec. */ -+ pInfo->name = dev->identifier; -+ pInfo->type_name = "rfbKeyb"; -+ pInfo->flags = XI86_KEYBOARD_CAPABLE; -+ pInfo->device_control = xf86rfbKeybControlProc; -+ pInfo->read_input = NULL; -+ pInfo->motion_history_proc = NULL; -+ pInfo->history_size = 0; -+ pInfo->control_proc = NULL; -+ pInfo->close_proc = NULL; -+ pInfo->switch_mode = NULL; -+ pInfo->conversion_proc = NULL; -+ pInfo->reverse_conversion_proc = NULL; -+ pInfo->fd = -1; -+ pInfo->dev = NULL; -+ pInfo->private_flags = 0; -+ pInfo->always_core_feedback = 0; -+ pInfo->conf_idev = dev; -+ -+ /* Collect the options, and process the common options. */ -+ xf86CollectInputOptions(pInfo, DEFAULTS, NULL); -+ xf86ProcessCommonOptions(pInfo, pInfo->options); -+ -+ /* Mark the device configured */ -+ pInfo->flags |= XI86_CONFIGURED; -+ -+#ifdef XKB -+ from = X_DEFAULT; -+ if (noXkbExtension) -+ from = X_CMDLINE; -+ else if (xf86FindOption(dev->commonOptions, "XkbDisable")) { -+ noXkbExtension = -+ xf86SetBoolOption(dev->commonOptions, "XkbDisable", FALSE); -+ from = X_CONFIG; -+ } -+ if (noXkbExtension) -+ xf86Msg(from, "XKB: disabled\n"); -+ -+#define NULL_IF_EMPTY(s) (s[0] ? s : (xfree(s), (char *)NULL)) -+ -+ if (!noXkbExtension && !XkbInitialMap) { -+ if ((s = xf86SetStrOption(dev->commonOptions, "XkbKeymap", NULL))) { -+ xkbkeymap = NULL_IF_EMPTY(s); -+ xf86Msg(X_CONFIG, "XKB: keymap: \"%s\" " -+ "(overrides other XKB settings)\n", xkbkeymap); -+ } else { -+ if ((s = xf86SetStrOption(dev->commonOptions, "XkbCompat", NULL))) { -+ xkbcompat = NULL_IF_EMPTY(s); -+ xkbcomponents_specified = TRUE; -+ xf86Msg(X_CONFIG, "XKB: compat: \"%s\"\n", s); -+ } -+ -+ if ((s = xf86SetStrOption(dev->commonOptions, "XkbTypes", NULL))) { -+ xkbtypes = NULL_IF_EMPTY(s); -+ xkbcomponents_specified = TRUE; -+ xf86Msg(X_CONFIG, "XKB: types: \"%s\"\n", s); -+ } -+ -+ if ((s = xf86SetStrOption(dev->commonOptions, "XkbKeycodes", NULL))) { -+ xkbkeycodes = NULL_IF_EMPTY(s); -+ xkbcomponents_specified = TRUE; -+ xf86Msg(X_CONFIG, "XKB: keycodes: \"%s\"\n", s); -+ } -+ -+ if ((s = xf86SetStrOption(dev->commonOptions, "XkbGeometry", NULL))) { -+ xkbgeometry = NULL_IF_EMPTY(s); -+ xkbcomponents_specified = TRUE; -+ xf86Msg(X_CONFIG, "XKB: geometry: \"%s\"\n", s); -+ } -+ -+ if ((s = xf86SetStrOption(dev->commonOptions, "XkbSymbols", NULL))) { -+ xkbsymbols = NULL_IF_EMPTY(s); -+ xkbcomponents_specified = TRUE; -+ xf86Msg(X_CONFIG, "XKB: symbols: \"%s\"\n", s); -+ } -+ -+ if ((s = xf86SetStrOption(dev->commonOptions, "XkbRules", NULL))) { -+ xkbrules = NULL_IF_EMPTY(s); -+ xkbcomponents_specified = TRUE; -+ xf86Msg(X_CONFIG, "XKB: rules: \"%s\"\n", s); -+ } -+ -+ if ((s = xf86SetStrOption(dev->commonOptions, "XkbModel", NULL))) { -+ xkbmodel = NULL_IF_EMPTY(s); -+ xkbcomponents_specified = TRUE; -+ xf86Msg(X_CONFIG, "XKB: model: \"%s\"\n", s); -+ } -+ -+ if ((s = xf86SetStrOption(dev->commonOptions, "XkbLayout", NULL))) { -+ xkblayout = NULL_IF_EMPTY(s); -+ xkbcomponents_specified = TRUE; -+ xf86Msg(X_CONFIG, "XKB: layout: \"%s\"\n", s); -+ } -+ -+ if ((s = xf86SetStrOption(dev->commonOptions, "XkbVariant", NULL))) { -+ xkbvariant = NULL_IF_EMPTY(s); -+ xkbcomponents_specified = TRUE; -+ xf86Msg(X_CONFIG, "XKB: variant: \"%s\"\n", s); -+ } -+ -+ if ((s = xf86SetStrOption(dev->commonOptions, "XkbOptions", NULL))) { -+ xkboptions = NULL_IF_EMPTY(s); -+ xkbcomponents_specified = TRUE; -+ xf86Msg(X_CONFIG, "XKB: options: \"%s\"\n", s); -+ } -+ } -+ } -+#undef NULL_IF_EMPTY -+#endif -+ -+ /* Return the configured device */ -+ return (pInfo); -+} -+ -+#ifdef XFree86LOADER -+static -+#endif -+InputDriverRec RFBKEYB = { -+ 1, /* driver version */ -+ "rfbkeyb", /* driver name */ -+ NULL, /* identify */ -+ xf86rfbKeybInit, /* pre-init */ -+ xf86rfbKeybUninit, /* un-init */ -+ NULL, /* module */ -+ 0 /* ref count */ -+}; -+ -+/* -+ *************************************************************************** -+ * -+ * Dynamic loading functions -+ * -+ *************************************************************************** -+ */ -+#ifdef XFree86LOADER -+static void -+xf86rfbKeybUnplug(pointer p) -+{ -+} -+ -+static pointer -+xf86rfbKeybPlug(pointer module, -+ pointer options, -+ int *errmaj, -+ int *errmin) -+{ -+ xf86AddInputDriver(&RFBKEYB, module, 0); -+ -+ return module; -+} -+ -+void -+vncInitKeyb(void) -+{ -+ xf86AddInputDriver(&RFBKEYB, NULL, 0); -+} -+ -+static XF86ModuleVersionInfo xf86rfbKeybVersionRec = -+{ -+ "rfbkeyb", -+ "xf4vnc Project, see http://xf4vnc.sf.net", -+ MODINFOSTRING1, -+ MODINFOSTRING2, -+ XF86_VERSION_CURRENT, -+ 1, 0, 0, -+ ABI_CLASS_XINPUT, -+ ABI_XINPUT_VERSION, -+ MOD_CLASS_XINPUT, -+ {0, 0, 0, 0} /* signature, to be patched into the file by */ -+ /* a tool */ -+}; -+ -+XF86ModuleData rfbkeybModuleData = {&xf86rfbKeybVersionRec, -+ xf86rfbKeybPlug, -+ xf86rfbKeybUnplug}; -+ -+#endif /* XFree86LOADER */ -+#endif -diff --git a/hw/vnc/rfbmouse.c b/hw/vnc/rfbmouse.c -new file mode 100644 -index 0000000..de5fd65 ---- /dev/null -+++ b/hw/vnc/rfbmouse.c -@@ -0,0 +1,244 @@ -+/* -+ * Copyright (C) 2002 Alan Hourihane. 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. -+ * -+ * Author: Alan Hourihane -+ */ -+ -+#if XFREE86VNC -+ -+#ifndef XFree86LOADER -+#include -+#include -+#endif -+ -+#include -+#include -+#define NEED_XF86_TYPES -+ -+#if !defined(DGUX) -+#include -+#include -+#endif -+ -+#include -+#include -+#include /* Needed for InitValuator/Proximity stuff */ -+#include -+#include -+ -+#ifdef XFree86LOADER -+#include -+#endif -+ -+static const char *DEFAULTS[] = { -+ NULL -+}; -+#else -+#include -+#include -+#include -+#endif -+ -+ -+unsigned char ptrAcceleration = 50; -+ -+void -+PtrDeviceOn(DeviceIntPtr pDev) -+{ -+#if 0 -+ ptrAcceleration = (unsigned char)pDev->ptrfeed->ctrl.num; -+#endif -+} -+ -+void -+PtrDeviceInit(void) -+{ -+} -+ -+void -+PtrDeviceOff(void) -+{ -+} -+ -+ -+void -+PtrDeviceControl(DeviceIntPtr dev, PtrCtrl *ctrl) -+{ -+#if 0 -+ ptrAcceleration = (char)ctrl->num; -+ -+ if (udpSockConnected) { -+ if (write(udpSock, &ptrAcceleration, 1) <= 0) { -+ ErrorF("PtrDeviceControl: UDP input: write"); -+ rfbDisconnectUDPSock(); -+ } -+ } -+#endif -+} -+ -+#if XFREE86VNC -+static int -+xf86rfbMouseControlProc(DeviceIntPtr device, int onoff) -+{ -+ BYTE map[6]; -+ DevicePtr pDev = (DevicePtr)device; -+ -+ 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(device); -+ break; -+ -+ case DEVICE_OFF: -+ pDev->on = FALSE; -+ PtrDeviceOff(); -+ break; -+ -+ case DEVICE_CLOSE: -+ if (pDev->on) -+ PtrDeviceOff(); -+ break; -+ } -+ return Success; -+} -+ -+static void -+xf86rfbMouseUninit(InputDriverPtr drv, -+ InputInfoPtr pInfo, -+ int flags) -+{ -+ xf86rfbMouseControlProc(pInfo->dev, DEVICE_OFF); -+} -+ -+static InputInfoPtr -+xf86rfbMouseInit(InputDriverPtr drv, -+ IDevPtr dev, -+ int flags) -+{ -+ InputInfoPtr pInfo; -+ -+ if (!(pInfo = xf86AllocateInput(drv, 0))) -+ return NULL; -+ -+ /* Initialise the InputInfoRec. */ -+ pInfo->name = dev->identifier; -+ pInfo->type_name = "rfbMouse"; -+ pInfo->flags = XI86_POINTER_CAPABLE | XI86_SEND_DRAG_EVENTS; -+ pInfo->device_control = xf86rfbMouseControlProc; -+ pInfo->read_input = NULL; -+ pInfo->motion_history_proc = xf86GetMotionEvents; -+ pInfo->history_size = 0; -+ pInfo->control_proc = NULL; -+ pInfo->close_proc = NULL; -+ pInfo->switch_mode = NULL; -+ pInfo->conversion_proc = NULL; -+ pInfo->reverse_conversion_proc = NULL; -+ pInfo->fd = -1; -+ pInfo->dev = NULL; -+ pInfo->private_flags = 0; -+ pInfo->always_core_feedback = 0; -+ pInfo->conf_idev = dev; -+ -+ /* Collect the options, and process the common options. */ -+ xf86CollectInputOptions(pInfo, DEFAULTS, NULL); -+ xf86ProcessCommonOptions(pInfo, pInfo->options); -+ -+ /* Mark the device configured */ -+ pInfo->flags |= XI86_CONFIGURED; -+ -+ /* Return the configured device */ -+ return (pInfo); -+} -+ -+#ifdef XFree86LOADER -+static -+#endif -+InputDriverRec RFBMOUSE = { -+ 1, /* driver version */ -+ "rfbmouse", /* driver name */ -+ NULL, /* identify */ -+ xf86rfbMouseInit, /* pre-init */ -+ xf86rfbMouseUninit, /* un-init */ -+ NULL, /* module */ -+ 0 /* ref count */ -+}; -+ -+/* -+ *************************************************************************** -+ * -+ * Dynamic loading functions -+ * -+ *************************************************************************** -+ */ -+#ifdef XFree86LOADER -+static void -+xf86rfbMouseUnplug(pointer p) -+{ -+} -+ -+static pointer -+xf86rfbMousePlug(pointer module, -+ pointer options, -+ int *errmaj, -+ int *errmin) -+{ -+ xf86AddInputDriver(&RFBMOUSE, module, 0); -+ -+ return module; -+} -+ -+void -+vncInitMouse(void) -+{ -+ xf86AddInputDriver(&RFBMOUSE, NULL, 0); -+} -+ -+static XF86ModuleVersionInfo xf86rfbMouseVersionRec = -+{ -+ "rfbmouse", -+ "xf4vnc Project, see http://xf4vnc.sf.net", -+ MODINFOSTRING1, -+ MODINFOSTRING2, -+ XF86_VERSION_CURRENT, -+ 1, 0, 0, -+ ABI_CLASS_XINPUT, -+ ABI_XINPUT_VERSION, -+ MOD_CLASS_XINPUT, -+ {0, 0, 0, 0} /* signature, to be patched into the file by */ -+ /* a tool */ -+}; -+ -+XF86ModuleData rfbmouseModuleData = {&xf86rfbMouseVersionRec, -+ xf86rfbMousePlug, -+ xf86rfbMouseUnplug}; -+ -+#endif /* XFree86LOADER */ -+#endif -diff --git a/hw/vnc/rfbproto.h b/hw/vnc/rfbproto.h -new file mode 100644 -index 0000000..bbef703 ---- /dev/null -+++ b/hw/vnc/rfbproto.h -@@ -0,0 +1,1347 @@ -+/* -+ * Copyright (C) 2000-2004 Constantin Kaplinsky. All Rights Reserved. -+ * Copyright (C) 2000 Tridia Corporation. All Rights Reserved. -+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. -+ * -+ * This is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This software is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this software; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -+ * USA. -+ */ -+ -+/* -+ * rfbproto.h - header file for the RFB protocol, versions 3.3, 3.7 and 3.7t -+ * (protocol 3.7t is effectively 3.7 with TightVNC extensions enabled) -+ * -+ * Uses types CARD for an n-bit unsigned integer, INT for an n-bit signed -+ * integer (for n = 8, 16 and 32). -+ * -+ * All multiple byte integers are in big endian (network) order (most -+ * significant byte first). Unless noted otherwise there is no special -+ * alignment of protocol structures. -+ * -+ * -+ * Once the initial handshaking is done, all messages start with a type byte, -+ * (usually) followed by message-specific data. The order of definitions in -+ * this file is as follows: -+ * -+ * (1) Structures used in several types of message. -+ * (2) Structures used in the initial handshaking. -+ * (3) Message types. -+ * (4) Encoding types. -+ * (5) For each message type, the form of the data following the type byte. -+ * Sometimes this is defined by a single structure but the more complex -+ * messages have to be explained by comments. -+ */ -+ -+ -+/***************************************************************************** -+ * -+ * Structures used in several messages -+ * -+ *****************************************************************************/ -+ -+/*----------------------------------------------------------------------------- -+ * Structure used to specify a rectangle. This structure is a multiple of 4 -+ * bytes so that it can be interspersed with 32-bit pixel data without -+ * affecting alignment. -+ */ -+ -+typedef struct _rfbRectangle { -+ CARD16 x; -+ CARD16 y; -+ CARD16 w; -+ CARD16 h; -+} rfbRectangle; -+ -+#define sz_rfbRectangle 8 -+ -+ -+/*----------------------------------------------------------------------------- -+ * Structure used to specify pixel format. -+ */ -+ -+typedef struct _rfbPixelFormat { -+ -+ CARD8 bitsPerPixel; /* 8,16,32 only */ -+ -+ CARD8 depth; /* 8 to 32 */ -+ -+ CARD8 bigEndian; /* True if multi-byte pixels are interpreted -+ as big endian, or if single-bit-per-pixel -+ has most significant bit of the byte -+ corresponding to first (leftmost) pixel. Of -+ course this is meaningless for 8 bits/pix */ -+ -+ CARD8 trueColour; /* If false then we need a "colour map" to -+ convert pixels to RGB. If true, xxxMax and -+ xxxShift specify bits used for red, green -+ and blue */ -+ -+ /* the following fields are only meaningful if trueColour is true */ -+ -+ CARD16 redMax; /* maximum red value (= 2^n - 1 where n is the -+ number of bits used for red). Note this -+ value is always in big endian order. */ -+ -+ CARD16 greenMax; /* similar for green */ -+ -+ CARD16 blueMax; /* and blue */ -+ -+ CARD8 redShift; /* number of shifts needed to get the red -+ value in a pixel to the least significant -+ bit. To find the red value from a given -+ pixel, do the following: -+ 1) Swap pixel value according to bigEndian -+ (e.g. if bigEndian is false and host byte -+ order is big endian, then swap). -+ 2) Shift right by redShift. -+ 3) AND with redMax (in host byte order). -+ 4) You now have the red value between 0 and -+ redMax. */ -+ -+ CARD8 greenShift; /* similar for green */ -+ -+ CARD8 blueShift; /* and blue */ -+ -+ CARD8 pad1; -+ CARD16 pad2; -+ -+} rfbPixelFormat; -+ -+#define sz_rfbPixelFormat 16 -+ -+ -+/*----------------------------------------------------------------------------- -+ * Structure used to describe protocol options such as tunneling methods, -+ * authentication schemes and message types (protocol version 3.7t). -+ */ -+ -+typedef struct _rfbCapabilityInfo { -+ -+ CARD32 code; /* numeric identifier */ -+ CARD8 vendorSignature[4]; /* vendor identification */ -+ CARD8 nameSignature[8]; /* abbreviated option name */ -+ -+} rfbCapabilityInfo; -+ -+#define sz_rfbCapabilityInfoVendor 4 -+#define sz_rfbCapabilityInfoName 8 -+#define sz_rfbCapabilityInfo 16 -+ -+/* -+ * Vendors known by TightVNC: standard VNC/RealVNC, TridiaVNC, and TightVNC. -+ */ -+ -+#define rfbStandardVendor "STDV" -+#define rfbTridiaVncVendor "TRDV" -+#define rfbTightVncVendor "TGHT" -+#define rfbTungstenGraphicsVendor "TGIV" -+ -+ -+/***************************************************************************** -+ * -+ * Initial handshaking messages -+ * -+ *****************************************************************************/ -+ -+/*----------------------------------------------------------------------------- -+ * Protocol Version -+ * -+ * The server always sends 12 bytes to start which identifies the latest RFB -+ * protocol version number which it supports. These bytes are interpreted -+ * as a string of 12 ASCII characters in the format "RFB xxx.yyy\n" where -+ * xxx and yyy are the major and minor version numbers (for version 3.7 -+ * this is "RFB 003.007\n"). -+ * -+ * The client then replies with a similar 12-byte message giving the version -+ * number of the protocol which should actually be used (which may be different -+ * to that quoted by the server). -+ * -+ * It is intended that both clients and servers may provide some level of -+ * backwards compatibility by this mechanism. Servers in particular should -+ * attempt to provide backwards compatibility, and even forwards compatibility -+ * to some extent. For example if a client demands version 3.1 of the -+ * protocol, a 3.0 server can probably assume that by ignoring requests for -+ * encoding types it doesn't understand, everything will still work OK. This -+ * will probably not be the case for changes in the major version number. -+ * -+ * The format string below can be used in sprintf or sscanf to generate or -+ * decode the version string respectively. -+ */ -+ -+#define rfbProtocolVersionFormat "RFB %03d.%03d\n" -+#define rfbProtocolMajorVersion 3 -+#define rfbProtocolMinorVersion 7 -+#define rfbProtocolFallbackMinorVersion 3 -+ -+typedef char rfbProtocolVersionMsg[13]; /* allow extra byte for null */ -+ -+#define sz_rfbProtocolVersionMsg 12 -+ -+ -+/* -+ * Negotiation of the security type (protocol version 3.7) -+ * -+ * Once the protocol version has been decided, the server either sends a list -+ * of supported security types, or informs the client about an error (when the -+ * number of security types is 0). Security type rfbSecTypeTight is used to -+ * enable TightVNC-specific protocol extensions. The value rfbSecTypeVncAuth -+ * stands for classic VNC authentication. -+ * -+ * The client selects a particular security type from the list provided by the -+ * server. -+ */ -+ -+#define rfbSecTypeInvalid 0 -+#define rfbSecTypeNone 1 -+#define rfbSecTypeVncAuth 2 -+#define rfbSecTypeTight 16 -+ -+ -+/*----------------------------------------------------------------------------- -+ * Negotiation of Tunneling Capabilities (protocol version 3.7t) -+ * -+ * If the chosen security type is rfbSecTypeTight, the server sends a list of -+ * supported tunneling methods ("tunneling" refers to any additional layer of -+ * data transformation, such as encryption or external compression.) -+ * -+ * nTunnelTypes specifies the number of following rfbCapabilityInfo structures -+ * that list all supported tunneling methods in the order of preference. -+ * -+ * NOTE: If nTunnelTypes is 0, that tells the client that no tunneling can be -+ * used, and the client should not send a response requesting a tunneling -+ * method. -+ */ -+ -+typedef struct _rfbTunnelingCapsMsg { -+ CARD32 nTunnelTypes; -+ /* followed by nTunnelTypes * rfbCapabilityInfo structures */ -+} rfbTunnelingCapsMsg; -+ -+#define sz_rfbTunnelingCapsMsg 4 -+ -+/*----------------------------------------------------------------------------- -+ * Tunneling Method Request (protocol version 3.7t) -+ * -+ * If the list of tunneling capabilities sent by the server was not empty, the -+ * client should reply with a 32-bit code specifying a particular tunneling -+ * method. The following code should be used for no tunneling. -+ */ -+ -+#define rfbNoTunneling 0 -+#define sig_rfbNoTunneling "NOTUNNEL" -+ -+ -+/*----------------------------------------------------------------------------- -+ * Negotiation of Authentication Capabilities (protocol version 3.7t) -+ * -+ * After setting up tunneling, the server sends a list of supported -+ * authentication schemes. -+ * -+ * nAuthTypes specifies the number of following rfbCapabilityInfo structures -+ * that list all supported authentication schemes in the order of preference. -+ * -+ * NOTE: If nAuthTypes is 0, that tells the client that no authentication is -+ * necessary, and the client should not send a response requesting an -+ * authentication scheme. -+ */ -+ -+typedef struct _rfbAuthenticationCapsMsg { -+ CARD32 nAuthTypes; -+ /* followed by nAuthTypes * rfbCapabilityInfo structures */ -+} rfbAuthenticationCapsMsg; -+ -+#define sz_rfbAuthenticationCapsMsg 4 -+ -+/*----------------------------------------------------------------------------- -+ * Authentication Scheme Request (protocol version 3.7t) -+ * -+ * If the list of authentication capabilities sent by the server was not empty, -+ * the client should reply with a 32-bit code specifying a particular -+ * authentication scheme. The following codes are supported. -+ */ -+ -+#define rfbAuthNone 1 -+#define rfbAuthVNC 2 -+#define rfbAuthUnixLogin 129 -+#define rfbAuthExternal 130 -+ -+#define sig_rfbAuthNone "NOAUTH__" -+#define sig_rfbAuthVNC "VNCAUTH_" -+#define sig_rfbAuthUnixLogin "ULGNAUTH" -+#define sig_rfbAuthExternal "XTRNAUTH" -+ -+ -+/*----------------------------------------------------------------------------- -+ * Standard VNC Authentication (all protocol versions) -+ * -+ * Standard authentication result codes are defined below. -+ */ -+ -+#define rfbVncAuthOK 0 -+#define rfbVncAuthFailed 1 -+#define rfbVncAuthTooMany 2 -+ -+ -+/*----------------------------------------------------------------------------- -+ * Client Initialisation Message -+ * -+ * Once the client and server are sure that they're happy to talk to one -+ * another, the client sends an initialisation message. At present this -+ * message only consists of a boolean indicating whether the server should try -+ * to share the desktop by leaving other clients connected, or give exclusive -+ * access to this client by disconnecting all other clients. -+ */ -+ -+typedef struct _rfbClientInitMsg { -+ CARD8 shared; -+} rfbClientInitMsg; -+ -+#define sz_rfbClientInitMsg 1 -+ -+ -+/*----------------------------------------------------------------------------- -+ * Server Initialisation Message -+ * -+ * After the client initialisation message, the server sends one of its own. -+ * This tells the client the width and height of the server's framebuffer, -+ * its pixel format and the name associated with the desktop. -+ */ -+ -+typedef struct _rfbServerInitMsg { -+ CARD16 framebufferWidth; -+ CARD16 framebufferHeight; -+ rfbPixelFormat format; /* the server's preferred pixel format */ -+ CARD32 nameLength; -+ /* followed by char name[nameLength] */ -+} rfbServerInitMsg; -+ -+#define sz_rfbServerInitMsg (8 + sz_rfbPixelFormat) -+ -+ -+/*----------------------------------------------------------------------------- -+ * Server Interaction Capabilities Message (protocol version 3.7t) -+ * -+ * In the protocol version 3.7t, the server informs the client what message -+ * types it supports in addition to ones defined in the protocol version 3.7. -+ * Also, the server sends the list of all supported encodings (note that it's -+ * not necessary to advertise the "raw" encoding sinse it MUST be supported in -+ * RFB 3.x protocols). -+ * -+ * This data immediately follows the server initialisation message. -+ */ -+ -+typedef struct _rfbInteractionCapsMsg { -+ CARD16 nServerMessageTypes; -+ CARD16 nClientMessageTypes; -+ CARD16 nEncodingTypes; -+ CARD16 pad; /* reserved, must be 0 */ -+ /* followed by nServerMessageTypes * rfbCapabilityInfo structures */ -+ /* followed by nClientMessageTypes * rfbCapabilityInfo structures */ -+} rfbInteractionCapsMsg; -+ -+#define sz_rfbInteractionCapsMsg 8 -+ -+ -+/* -+ * Following the server initialisation message it's up to the client to send -+ * whichever protocol messages it wants. Typically it will send a -+ * SetPixelFormat message and a SetEncodings message, followed by a -+ * FramebufferUpdateRequest. From then on the server will send -+ * FramebufferUpdate messages in response to the client's -+ * FramebufferUpdateRequest messages. The client should send -+ * FramebufferUpdateRequest messages with incremental set to true when it has -+ * finished processing one FramebufferUpdate and is ready to process another. -+ * With a fast client, the rate at which FramebufferUpdateRequests are sent -+ * should be regulated to avoid hogging the network. -+ */ -+ -+ -+ -+/***************************************************************************** -+ * -+ * Message types -+ * -+ *****************************************************************************/ -+ -+/* server -> client */ -+ -+#define rfbFramebufferUpdate 0 -+#define rfbSetColourMapEntries 1 -+#define rfbBell 2 -+#define rfbServerCutText 3 -+/* Chromium extensions, use higher values */ -+#define rfbChromiumStart 50 -+#define rfbChromiumMoveResizeWindow 51 -+#define rfbChromiumClipList 52 -+#define rfbChromiumWindowShow 53 -+ -+#define rfbFileListData 130 -+#define rfbFileDownloadData 131 -+#define rfbFileUploadCancel 132 -+#define rfbFileDownloadFailed 133 -+ -+/* signatures for non-standard messages */ -+#define sig_rfbFileListData "FTS_LSDT" -+#define sig_rfbFileDownloadData "FTS_DNDT" -+#define sig_rfbFileUploadCancel "FTS_UPCN" -+#define sig_rfbFileDownloadFailed "FTS_DNFL" -+ -+ -+/* client -> server */ -+ -+#define rfbSetPixelFormat 0 -+#define rfbFixColourMapEntries 1 /* not currently supported */ -+#define rfbSetEncodings 2 -+#define rfbFramebufferUpdateRequest 3 -+#define rfbKeyEvent 4 -+#define rfbPointerEvent 5 -+#define rfbClientCutText 6 -+/* Chromium extensions, use higher values */ -+#define rfbChromiumStop 50 -+#define rfbChromiumExpose 51 -+ -+#define rfbFileListRequest 130 -+#define rfbFileDownloadRequest 131 -+#define rfbFileUploadRequest 132 -+#define rfbFileUploadData 133 -+#define rfbFileDownloadCancel 134 -+#define rfbFileUploadFailed 135 -+#define rfbFileCreateDirRequest 136 -+ -+/* signatures for non-standard messages */ -+#define sig_rfbFileListRequest "FTC_LSRQ" -+#define sig_rfbFileDownloadRequest "FTC_DNRQ" -+#define sig_rfbFileUploadRequest "FTC_UPRQ" -+#define sig_rfbFileUploadData "FTC_UPDT" -+#define sig_rfbFileDownloadCancel "FTC_DNCN" -+#define sig_rfbFileUploadFailed "FTC_UPFL" -+#define sig_rfbFileCreateDirRequest "FTC_FCDR" -+ -+/***************************************************************************** -+ * -+ * Encoding types -+ * -+ *****************************************************************************/ -+ -+#define rfbEncodingRaw 0 -+#define rfbEncodingCopyRect 1 -+#define rfbEncodingRRE 2 -+#define rfbEncodingCoRRE 4 -+#define rfbEncodingHextile 5 -+#define rfbEncodingZlib 6 -+#define rfbEncodingTight 7 -+#define rfbEncodingZlibHex 8 -+ -+/* signatures for basic encoding types */ -+#define sig_rfbEncodingRaw "RAW_____" -+#define sig_rfbEncodingCopyRect "COPYRECT" -+#define sig_rfbEncodingRRE "RRE_____" -+#define sig_rfbEncodingCoRRE "CORRE___" -+#define sig_rfbEncodingHextile "HEXTILE_" -+#define sig_rfbEncodingZlib "ZLIB____" -+#define sig_rfbEncodingTight "TIGHT___" -+#define sig_rfbEncodingZlibHex "ZLIBHEX_" -+#define sig_rfbEncodingChromium "CHROMIUM" -+ -+/* -+ * Special encoding numbers: -+ * 0xFFFFFF00 .. 0xFFFFFF0F -- encoding-specific compression levels; -+ * 0xFFFFFF10 .. 0xFFFFFF1F -- mouse cursor shape data; -+ * 0xFFFFFF20 .. 0xFFFFFF2F -- various protocol extensions; -+ * 0xFFFFFF30 .. 0xFFFFFFDF -- not allocated yet; -+ * 0xFFFFFFE0 .. 0xFFFFFFEF -- quality level for JPEG compressor; -+ * 0xFFFFFFF0 .. 0xFFFFFFFF -- not allocated yet. -+ */ -+ -+#define rfbEncodingCompressLevel0 0xFFFFFF00 -+#define rfbEncodingCompressLevel1 0xFFFFFF01 -+#define rfbEncodingCompressLevel2 0xFFFFFF02 -+#define rfbEncodingCompressLevel3 0xFFFFFF03 -+#define rfbEncodingCompressLevel4 0xFFFFFF04 -+#define rfbEncodingCompressLevel5 0xFFFFFF05 -+#define rfbEncodingCompressLevel6 0xFFFFFF06 -+#define rfbEncodingCompressLevel7 0xFFFFFF07 -+#define rfbEncodingCompressLevel8 0xFFFFFF08 -+#define rfbEncodingCompressLevel9 0xFFFFFF09 -+ -+#define rfbEncodingXCursor 0xFFFFFF10 -+#define rfbEncodingRichCursor 0xFFFFFF11 -+#define rfbEncodingPointerPos 0xFFFFFF18 -+ -+#define rfbEncodingLastRect 0xFFFFFF20 -+#define rfbEncodingNewFBSize 0xFFFFFF21 -+#define rfbEncodingChromium 0xFFFFFF2F -+#define rfbEncodingChromium2 0xFFFFFF30 -+ -+#define rfbEncodingQualityLevel0 0xFFFFFFE0 -+#define rfbEncodingQualityLevel1 0xFFFFFFE1 -+#define rfbEncodingQualityLevel2 0xFFFFFFE2 -+#define rfbEncodingQualityLevel3 0xFFFFFFE3 -+#define rfbEncodingQualityLevel4 0xFFFFFFE4 -+#define rfbEncodingQualityLevel5 0xFFFFFFE5 -+#define rfbEncodingQualityLevel6 0xFFFFFFE6 -+#define rfbEncodingQualityLevel7 0xFFFFFFE7 -+#define rfbEncodingQualityLevel8 0xFFFFFFE8 -+#define rfbEncodingQualityLevel9 0xFFFFFFE9 -+ -+/* signatures for "fake" encoding types */ -+#define sig_rfbEncodingCompressLevel0 "COMPRLVL" -+#define sig_rfbEncodingXCursor "X11CURSR" -+#define sig_rfbEncodingRichCursor "RCHCURSR" -+#define sig_rfbEncodingPointerPos "POINTPOS" -+#define sig_rfbEncodingLastRect "LASTRECT" -+#define sig_rfbEncodingNewFBSize "NEWFBSIZ" -+#define sig_rfbEncodingQualityLevel0 "JPEGQLVL" -+ -+ -+/***************************************************************************** -+ * -+ * Server -> client message definitions -+ * -+ *****************************************************************************/ -+ -+ -+/*----------------------------------------------------------------------------- -+ * FramebufferUpdate - a block of rectangles to be copied to the framebuffer. -+ * -+ * This message consists of a header giving the number of rectangles of pixel -+ * data followed by the rectangles themselves. The header is padded so that -+ * together with the type byte it is an exact multiple of 4 bytes (to help -+ * with alignment of 32-bit pixels): -+ */ -+ -+typedef struct _rfbFramebufferUpdateMsg { -+ CARD8 type; /* always rfbFramebufferUpdate */ -+ CARD8 pad; -+ CARD16 nRects; -+ /* followed by nRects rectangles */ -+} rfbFramebufferUpdateMsg; -+ -+#define sz_rfbFramebufferUpdateMsg 4 -+ -+/* -+ * Each rectangle of pixel data consists of a header describing the position -+ * and size of the rectangle and a type word describing the encoding of the -+ * pixel data, followed finally by the pixel data. Note that if the client has -+ * not sent a SetEncodings message then it will only receive raw pixel data. -+ * Also note again that this structure is a multiple of 4 bytes. -+ */ -+ -+typedef struct _rfbFramebufferUpdateRectHeader { -+ rfbRectangle r; -+ CARD32 encoding; /* one of the encoding types rfbEncoding... */ -+} rfbFramebufferUpdateRectHeader; -+ -+#define sz_rfbFramebufferUpdateRectHeader (sz_rfbRectangle + 4) -+ -+ -+/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+ * Raw Encoding. Pixels are sent in top-to-bottom scanline order, -+ * left-to-right within a scanline with no padding in between. -+ */ -+ -+ -+/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+ * CopyRect Encoding. The pixels are specified simply by the x and y position -+ * of the source rectangle. -+ */ -+ -+typedef struct _rfbCopyRect { -+ CARD16 srcX; -+ CARD16 srcY; -+} rfbCopyRect; -+ -+#define sz_rfbCopyRect 4 -+ -+ -+/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+ * RRE - Rise-and-Run-length Encoding. We have an rfbRREHeader structure -+ * giving the number of subrectangles following. Finally the data follows in -+ * the form [...] where each is -+ * []. -+ */ -+ -+typedef struct _rfbRREHeader { -+ CARD32 nSubrects; -+} rfbRREHeader; -+ -+#define sz_rfbRREHeader 4 -+ -+ -+/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+ * CoRRE - Compact RRE Encoding. We have an rfbRREHeader structure giving -+ * the number of subrectangles following. Finally the data follows in the form -+ * [...] where each is -+ * []. This means that -+ * the whole rectangle must be at most 255x255 pixels. -+ */ -+ -+typedef struct _rfbCoRRERectangle { -+ CARD8 x; -+ CARD8 y; -+ CARD8 w; -+ CARD8 h; -+} rfbCoRRERectangle; -+ -+#define sz_rfbCoRRERectangle 4 -+ -+ -+/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+ * Hextile Encoding. The rectangle is divided up into "tiles" of 16x16 pixels, -+ * starting at the top left going in left-to-right, top-to-bottom order. If -+ * the width of the rectangle is not an exact multiple of 16 then the width of -+ * the last tile in each row will be correspondingly smaller. Similarly if the -+ * height is not an exact multiple of 16 then the height of each tile in the -+ * final row will also be smaller. Each tile begins with a "subencoding" type -+ * byte, which is a mask made up of a number of bits. If the Raw bit is set -+ * then the other bits are irrelevant; w*h pixel values follow (where w and h -+ * are the width and height of the tile). Otherwise the tile is encoded in a -+ * similar way to RRE, except that the position and size of each subrectangle -+ * can be specified in just two bytes. The other bits in the mask are as -+ * follows: -+ * -+ * BackgroundSpecified - if set, a pixel value follows which specifies -+ * the background colour for this tile. The first non-raw tile in a -+ * rectangle must have this bit set. If this bit isn't set then the -+ * background is the same as the last tile. -+ * -+ * ForegroundSpecified - if set, a pixel value follows which specifies -+ * the foreground colour to be used for all subrectangles in this tile. -+ * If this bit is set then the SubrectsColoured bit must be zero. -+ * -+ * AnySubrects - if set, a single byte follows giving the number of -+ * subrectangles following. If not set, there are no subrectangles (i.e. -+ * the whole tile is just solid background colour). -+ * -+ * SubrectsColoured - if set then each subrectangle is preceded by a pixel -+ * value giving the colour of that subrectangle. If not set, all -+ * subrectangles are the same colour, the foreground colour; if the -+ * ForegroundSpecified bit wasn't set then the foreground is the same as -+ * the last tile. -+ * -+ * The position and size of each subrectangle is specified in two bytes. The -+ * Pack macros below can be used to generate the two bytes from x, y, w, h, -+ * and the Extract macros can be used to extract the x, y, w, h values from -+ * the two bytes. -+ */ -+ -+#define rfbHextileRaw (1 << 0) -+#define rfbHextileBackgroundSpecified (1 << 1) -+#define rfbHextileForegroundSpecified (1 << 2) -+#define rfbHextileAnySubrects (1 << 3) -+#define rfbHextileSubrectsColoured (1 << 4) -+ -+#define rfbHextilePackXY(x,y) (((x) << 4) | (y)) -+#define rfbHextilePackWH(w,h) ((((w)-1) << 4) | ((h)-1)) -+#define rfbHextileExtractX(byte) ((byte) >> 4) -+#define rfbHextileExtractY(byte) ((byte) & 0xf) -+#define rfbHextileExtractW(byte) (((byte) >> 4) + 1) -+#define rfbHextileExtractH(byte) (((byte) & 0xf) + 1) -+ -+/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+ * ZLIB - zlib compression Encoding. We have an rfbZlibHeader structure -+ * giving the number of bytes to follow. Finally the data follows in -+ * zlib compressed format. -+ */ -+ -+typedef struct _rfbZlibHeader { -+ CARD32 nBytes; -+} rfbZlibHeader; -+ -+#define sz_rfbZlibHeader 4 -+ -+ -+/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+ * Tight Encoding. -+ * -+ *-- The first byte of each Tight-encoded rectangle is a "compression control -+ * byte". Its format is as follows (bit 0 is the least significant one): -+ * -+ * bit 0: if 1, then compression stream 0 should be reset; -+ * bit 1: if 1, then compression stream 1 should be reset; -+ * bit 2: if 1, then compression stream 2 should be reset; -+ * bit 3: if 1, then compression stream 3 should be reset; -+ * bits 7-4: if 1000 (0x08), then the compression type is "fill", -+ * if 1001 (0x09), then the compression type is "jpeg", -+ * if 0xxx, then the compression type is "basic", -+ * values greater than 1001 are not valid. -+ * -+ * If the compression type is "basic", then bits 6..4 of the -+ * compression control byte (those xxx in 0xxx) specify the following: -+ * -+ * bits 5-4: decimal representation is the index of a particular zlib -+ * stream which should be used for decompressing the data; -+ * bit 6: if 1, then a "filter id" byte is following this byte. -+ * -+ *-- The data that follows after the compression control byte described -+ * above depends on the compression type ("fill", "jpeg" or "basic"). -+ * -+ *-- If the compression type is "fill", then the only pixel value follows, in -+ * client pixel format (see NOTE 1). This value applies to all pixels of the -+ * rectangle. -+ * -+ *-- If the compression type is "jpeg", the following data stream looks like -+ * this: -+ * -+ * 1..3 bytes: data size (N) in compact representation; -+ * N bytes: JPEG image. -+ * -+ * Data size is compactly represented in one, two or three bytes, according -+ * to the following scheme: -+ * -+ * 0xxxxxxx (for values 0..127) -+ * 1xxxxxxx 0yyyyyyy (for values 128..16383) -+ * 1xxxxxxx 1yyyyyyy zzzzzzzz (for values 16384..4194303) -+ * -+ * Here each character denotes one bit, xxxxxxx are the least significant 7 -+ * bits of the value (bits 0-6), yyyyyyy are bits 7-13, and zzzzzzzz are the -+ * most significant 8 bits (bits 14-21). For example, decimal value 10000 -+ * should be represented as two bytes: binary 10010000 01001110, or -+ * hexadecimal 90 4E. -+ * -+ *-- If the compression type is "basic" and bit 6 of the compression control -+ * byte was set to 1, then the next (second) byte specifies "filter id" which -+ * tells the decoder what filter type was used by the encoder to pre-process -+ * pixel data before the compression. The "filter id" byte can be one of the -+ * following: -+ * -+ * 0: no filter ("copy" filter); -+ * 1: "palette" filter; -+ * 2: "gradient" filter. -+ * -+ *-- If bit 6 of the compression control byte is set to 0 (no "filter id" -+ * byte), or if the filter id is 0, then raw pixel values in the client -+ * format (see NOTE 1) will be compressed. See below details on the -+ * compression. -+ * -+ *-- The "gradient" filter pre-processes pixel data with a simple algorithm -+ * which converts each color component to a difference between a "predicted" -+ * intensity and the actual intensity. Such a technique does not affect -+ * uncompressed data size, but helps to compress photo-like images better. -+ * Pseudo-code for converting intensities to differences is the following: -+ * -+ * P[i,j] := V[i-1,j] + V[i,j-1] - V[i-1,j-1]; -+ * if (P[i,j] < 0) then P[i,j] := 0; -+ * if (P[i,j] > MAX) then P[i,j] := MAX; -+ * D[i,j] := V[i,j] - P[i,j]; -+ * -+ * Here V[i,j] is the intensity of a color component for a pixel at -+ * coordinates (i,j). MAX is the maximum value of intensity for a color -+ * component. -+ * -+ *-- The "palette" filter converts true-color pixel data to indexed colors -+ * and a palette which can consist of 2..256 colors. If the number of colors -+ * is 2, then each pixel is encoded in 1 bit, otherwise 8 bits is used to -+ * encode one pixel. 1-bit encoding is performed such way that the most -+ * significant bits correspond to the leftmost pixels, and each raw of pixels -+ * is aligned to the byte boundary. When "palette" filter is used, the -+ * palette is sent before the pixel data. The palette begins with an unsigned -+ * byte which value is the number of colors in the palette minus 1 (i.e. 1 -+ * means 2 colors, 255 means 256 colors in the palette). Then follows the -+ * palette itself which consist of pixel values in client pixel format (see -+ * NOTE 1). -+ * -+ *-- The pixel data is compressed using the zlib library. But if the data -+ * size after applying the filter but before the compression is less then 12, -+ * then the data is sent as is, uncompressed. Four separate zlib streams -+ * (0..3) can be used and the decoder should read the actual stream id from -+ * the compression control byte (see NOTE 2). -+ * -+ * If the compression is not used, then the pixel data is sent as is, -+ * otherwise the data stream looks like this: -+ * -+ * 1..3 bytes: data size (N) in compact representation; -+ * N bytes: zlib-compressed data. -+ * -+ * Data size is compactly represented in one, two or three bytes, just like -+ * in the "jpeg" compression method (see above). -+ * -+ *-- NOTE 1. If the color depth is 24, and all three color components are -+ * 8-bit wide, then one pixel in Tight encoding is always represented by -+ * three bytes, where the first byte is red component, the second byte is -+ * green component, and the third byte is blue component of the pixel color -+ * value. This applies to colors in palettes as well. -+ * -+ *-- NOTE 2. The decoder must reset compression streams' states before -+ * decoding the rectangle, if some of bits 0,1,2,3 in the compression control -+ * byte are set to 1. Note that the decoder must reset zlib streams even if -+ * the compression type is "fill" or "jpeg". -+ * -+ *-- NOTE 3. The "gradient" filter and "jpeg" compression may be used only -+ * when bits-per-pixel value is either 16 or 32, not 8. -+ * -+ *-- NOTE 4. The width of any Tight-encoded rectangle cannot exceed 2048 -+ * pixels. If a rectangle is wider, it must be split into several rectangles -+ * and each one should be encoded separately. -+ * -+ */ -+ -+#define rfbTightExplicitFilter 0x04 -+#define rfbTightFill 0x08 -+#define rfbTightJpeg 0x09 -+#define rfbTightMaxSubencoding 0x09 -+ -+/* Filters to improve compression efficiency */ -+#define rfbTightFilterCopy 0x00 -+#define rfbTightFilterPalette 0x01 -+#define rfbTightFilterGradient 0x02 -+ -+ -+/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+ * ZLIBHEX - zlib compressed Hextile Encoding. Essentially, this is the -+ * hextile encoding with zlib compression on the tiles that can not be -+ * efficiently encoded with one of the other hextile subencodings. The -+ * new zlib subencoding uses two bytes to specify the length of the -+ * compressed tile and then the compressed data follows. As with the -+ * raw sub-encoding, the zlib subencoding invalidates the other -+ * values, if they are also set. -+ */ -+ -+#define rfbHextileZlibRaw (1 << 5) -+#define rfbHextileZlibHex (1 << 6) -+ -+ -+/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+ * XCursor encoding. This is a special encoding used to transmit X-style -+ * cursor shapes from server to clients. Note that for this encoding, -+ * coordinates in rfbFramebufferUpdateRectHeader structure hold hotspot -+ * position (r.x, r.y) and cursor size (r.w, r.h). If (w * h != 0), two RGB -+ * samples are sent after header in the rfbXCursorColors structure. They -+ * denote foreground and background colors of the cursor. If a client -+ * supports only black-and-white cursors, it should ignore these colors and -+ * assume that foreground is black and background is white. Next, two bitmaps -+ * (1 bits per pixel) follow: first one with actual data (value 0 denotes -+ * background color, value 1 denotes foreground color), second one with -+ * transparency data (bits with zero value mean that these pixels are -+ * transparent). Both bitmaps represent cursor data in a byte stream, from -+ * left to right, from top to bottom, and each row is byte-aligned. Most -+ * significant bits correspond to leftmost pixels. The number of bytes in -+ * each row can be calculated as ((w + 7) / 8). If (w * h == 0), cursor -+ * should be hidden (or default local cursor should be set by the client). -+ */ -+ -+typedef struct _rfbXCursorColors { -+ CARD8 foreRed; -+ CARD8 foreGreen; -+ CARD8 foreBlue; -+ CARD8 backRed; -+ CARD8 backGreen; -+ CARD8 backBlue; -+} rfbXCursorColors; -+ -+#define sz_rfbXCursorColors 6 -+ -+ -+/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+ * RichCursor encoding. This is a special encoding used to transmit cursor -+ * shapes from server to clients. It is similar to the XCursor encoding but -+ * uses client pixel format instead of two RGB colors to represent cursor -+ * image. For this encoding, coordinates in rfbFramebufferUpdateRectHeader -+ * structure hold hotspot position (r.x, r.y) and cursor size (r.w, r.h). -+ * After header, two pixmaps follow: first one with cursor image in current -+ * client pixel format (like in raw encoding), second with transparency data -+ * (1 bit per pixel, exactly the same format as used for transparency bitmap -+ * in the XCursor encoding). If (w * h == 0), cursor should be hidden (or -+ * default local cursor should be set by the client). -+ */ -+ -+ -+/*----------------------------------------------------------------------------- -+ * SetColourMapEntries - these messages are only sent if the pixel -+ * format uses a "colour map" (i.e. trueColour false) and the client has not -+ * fixed the entire colour map using FixColourMapEntries. In addition they -+ * will only start being sent after the client has sent its first -+ * FramebufferUpdateRequest. So if the client always tells the server to use -+ * trueColour then it never needs to process this type of message. -+ */ -+ -+typedef struct _rfbSetColourMapEntriesMsg { -+ CARD8 type; /* always rfbSetColourMapEntries */ -+ CARD8 redIndex; /* used to be pad, but used for DirectColor */ -+ CARD16 firstColour; -+ CARD16 nColours; -+ -+ /* Followed by nColours * 3 * CARD16 -+ r1, g1, b1, r2, g2, b2, r3, g3, b3, ..., rn, bn, gn */ -+ -+} rfbSetColourMapEntriesMsg; -+ -+#define sz_rfbSetColourMapEntriesMsg 6 -+ -+ -+ -+/*----------------------------------------------------------------------------- -+ * Bell - ring a bell on the client if it has one. -+ */ -+ -+typedef struct _rfbBellMsg { -+ CARD8 type; /* always rfbBell */ -+} rfbBellMsg; -+ -+#define sz_rfbBellMsg 1 -+ -+ -+ -+/*----------------------------------------------------------------------------- -+ * ServerCutText - the server has new text in its cut buffer. -+ */ -+ -+typedef struct _rfbServerCutTextMsg { -+ CARD8 type; /* always rfbServerCutText */ -+ CARD8 pad1; -+ CARD16 pad2; -+ CARD32 length; -+ /* followed by char text[length] */ -+} rfbServerCutTextMsg; -+ -+#define sz_rfbServerCutTextMsg 8 -+ -+/*----------------------------------------------------------------------------- -+ * ChromiumStart - a port number for the crserver -+ */ -+ -+typedef struct { -+ CARD8 type; /* always rfbChromiumStart */ -+ CARD8 pad1; -+ CARD16 pad2; -+ CARD32 crServerPort; -+ CARD32 mothershipPort; -+} rfbChromiumStartMsg; -+ -+#define sz_rfbChromiumStartMsg 12 -+ -+ -+/*----------------------------------------------------------------------------- -+ * ChromiumMoveResizeWindow - move a chromium window -+ */ -+ -+typedef struct { -+ CARD8 type; /* always rfbChromiumMoveResizeWindow */ -+ CARD8 pad1; -+ CARD16 pad2; -+ CARD32 winid; -+ CARD32 x; -+ CARD32 y; -+ CARD32 w; -+ CARD32 h; -+} rfbChromiumMoveResizeWindowMsg; -+ -+#define sz_rfbChromiumMoveResizeWindowMsg 24 -+ -+/*----------------------------------------------------------------------------- -+ * ChromiumClipList - send clip list -+ */ -+ -+typedef struct { -+ CARD8 type; /* always rfbChromiumClipList */ -+ CARD8 pad1; -+ CARD16 pad2; -+ CARD32 winid; -+ CARD32 length; -+} rfbChromiumClipListMsg; -+ -+#define sz_rfbChromiumClipListMsg 12 -+ -+/*----------------------------------------------------------------------------- -+ * ChromiumWindowShow - map or unmap a window -+ */ -+ -+typedef struct { -+ CARD8 type; /* always rfbChromiumWindowShow */ -+ CARD8 pad1; -+ CARD16 pad2; -+ CARD32 winid; -+ CARD32 show; -+} rfbChromiumWindowShowMsg; -+ -+#define sz_rfbChromiumWindowShowMsg 12 -+ -+/*----------------------------------------------------------------------------- -+ * FileListData -+ */ -+ -+typedef struct _rfbFileListDataMsg { -+ CARD8 type; -+ CARD8 flags; -+ CARD16 numFiles; -+ CARD16 dataSize; -+ CARD16 compressedSize; -+ /* Followed by SizeData[numFiles] */ -+ /* Followed by Filenames[compressedSize] */ -+} rfbFileListDataMsg; -+ -+#define sz_rfbFileListDataMsg 8 -+ -+/*----------------------------------------------------------------------------- -+ * FileDownloadData -+ */ -+ -+typedef struct _rfbFileDownloadDataMsg { -+ CARD8 type; -+ CARD8 compressLevel; -+ CARD16 realSize; -+ CARD16 compressedSize; -+ /* Followed by File[copressedSize] */ -+} rfbFileDownloadDataMsg; -+ -+#define sz_rfbFileDownloadDataMsg 6 -+ -+ -+/*----------------------------------------------------------------------------- -+ * FileUploadCancel -+ */ -+ -+typedef struct _rfbFileUploadCancelMsg { -+ CARD8 type; -+ CARD8 unused; -+ CARD16 reasonLen; -+ /* Followed by reason[reasonLen] */ -+} rfbFileUploadCancelMsg; -+ -+#define sz_rfbFileUploadCancelMsg 4 -+ -+/*----------------------------------------------------------------------------- -+ * FileDownloadFailed -+ */ -+ -+typedef struct _rfbFileDownloadFailedMsg { -+ CARD8 type; -+ CARD8 unused; -+ CARD16 reasonLen; -+ /* Followed by reason[reasonLen] */ -+} rfbFileDownloadFailedMsg; -+ -+#define sz_rfbFileDownloadFailedMsg 4 -+ -+/*----------------------------------------------------------------------------- -+ * Union of all server->client messages. -+ */ -+ -+typedef union _rfbServerToClientMsg { -+ CARD8 type; -+ rfbFramebufferUpdateMsg fu; -+ rfbSetColourMapEntriesMsg scme; -+ rfbBellMsg b; -+ rfbServerCutTextMsg sct; -+ rfbFileListDataMsg fld; -+ rfbFileDownloadDataMsg fdd; -+ rfbFileUploadCancelMsg fuc; -+ rfbFileDownloadFailedMsg fdf; -+ rfbChromiumStartMsg scd; -+ rfbChromiumMoveResizeWindowMsg scm; -+ rfbChromiumClipListMsg sccl; -+ rfbChromiumWindowShowMsg scws; -+} rfbServerToClientMsg; -+ -+ -+ -+/***************************************************************************** -+ * -+ * Message definitions (client -> server) -+ * -+ *****************************************************************************/ -+ -+ -+/*----------------------------------------------------------------------------- -+ * SetPixelFormat - tell the RFB server the format in which the client wants -+ * pixels sent. -+ */ -+ -+typedef struct _rfbSetPixelFormatMsg { -+ CARD8 type; /* always rfbSetPixelFormat */ -+ CARD8 pad1; -+ CARD16 pad2; -+ rfbPixelFormat format; -+} rfbSetPixelFormatMsg; -+ -+#define sz_rfbSetPixelFormatMsg (sz_rfbPixelFormat + 4) -+ -+ -+/*----------------------------------------------------------------------------- -+ * FixColourMapEntries - when the pixel format uses a "colour map", fix -+ * read-only colour map entries. -+ * -+ * ***************** NOT CURRENTLY SUPPORTED ***************** -+ */ -+ -+typedef struct _rfbFixColourMapEntriesMsg { -+ CARD8 type; /* always rfbFixColourMapEntries */ -+ CARD8 pad; -+ CARD16 firstColour; -+ CARD16 nColours; -+ -+ /* Followed by nColours * 3 * CARD16 -+ r1, g1, b1, r2, g2, b2, r3, g3, b3, ..., rn, bn, gn */ -+ -+} rfbFixColourMapEntriesMsg; -+ -+#define sz_rfbFixColourMapEntriesMsg 6 -+ -+ -+/*----------------------------------------------------------------------------- -+ * SetEncodings - tell the RFB server which encoding types we accept. Put them -+ * in order of preference, if we have any. We may always receive raw -+ * encoding, even if we don't specify it here. -+ */ -+ -+typedef struct _rfbSetEncodingsMsg { -+ CARD8 type; /* always rfbSetEncodings */ -+ CARD8 pad; -+ CARD16 nEncodings; -+ /* followed by nEncodings * CARD32 encoding types */ -+} rfbSetEncodingsMsg; -+ -+#define sz_rfbSetEncodingsMsg 4 -+ -+ -+/*----------------------------------------------------------------------------- -+ * FramebufferUpdateRequest - request for a framebuffer update. If incremental -+ * is true then the client just wants the changes since the last update. If -+ * false then it wants the whole of the specified rectangle. -+ */ -+ -+typedef struct _rfbFramebufferUpdateRequestMsg { -+ CARD8 type; /* always rfbFramebufferUpdateRequest */ -+ CARD8 incremental; -+ CARD16 x; -+ CARD16 y; -+ CARD16 w; -+ CARD16 h; -+} rfbFramebufferUpdateRequestMsg; -+ -+#define sz_rfbFramebufferUpdateRequestMsg 10 -+ -+ -+/*----------------------------------------------------------------------------- -+ * KeyEvent - key press or release -+ * -+ * Keys are specified using the "keysym" values defined by the X Window System. -+ * For most ordinary keys, the keysym is the same as the corresponding ASCII -+ * value. Other common keys are: -+ * -+ * BackSpace 0xff08 -+ * Tab 0xff09 -+ * Return or Enter 0xff0d -+ * Escape 0xff1b -+ * Insert 0xff63 -+ * Delete 0xffff -+ * Home 0xff50 -+ * End 0xff57 -+ * Page Up 0xff55 -+ * Page Down 0xff56 -+ * Left 0xff51 -+ * Up 0xff52 -+ * Right 0xff53 -+ * Down 0xff54 -+ * F1 0xffbe -+ * F2 0xffbf -+ * ... ... -+ * F12 0xffc9 -+ * Shift 0xffe1 -+ * Control 0xffe3 -+ * Meta 0xffe7 -+ * Alt 0xffe9 -+ */ -+ -+typedef struct _rfbKeyEventMsg { -+ CARD8 type; /* always rfbKeyEvent */ -+ CARD8 down; /* true if down (press), false if up */ -+ CARD16 pad; -+ CARD32 key; /* key is specified as an X keysym */ -+} rfbKeyEventMsg; -+ -+#define sz_rfbKeyEventMsg 8 -+ -+ -+/*----------------------------------------------------------------------------- -+ * PointerEvent - mouse/pen move and/or button press. -+ */ -+ -+typedef struct _rfbPointerEventMsg { -+ CARD8 type; /* always rfbPointerEvent */ -+ CARD8 buttonMask; /* bits 0-7 are buttons 1-8, 0=up, 1=down */ -+ CARD16 x; -+ CARD16 y; -+} rfbPointerEventMsg; -+ -+#define rfbButton1Mask 1 -+#define rfbButton2Mask 2 -+#define rfbButton3Mask 4 -+#define rfbButton4Mask 8 -+#define rfbButton5Mask 16 -+ -+#define sz_rfbPointerEventMsg 6 -+ -+ -+ -+/*----------------------------------------------------------------------------- -+ * ClientCutText - the client has new text in its cut buffer. -+ */ -+ -+typedef struct _rfbClientCutTextMsg { -+ CARD8 type; /* always rfbClientCutText */ -+ CARD8 pad1; -+ CARD16 pad2; -+ CARD32 length; -+ /* followed by char text[length] */ -+} rfbClientCutTextMsg; -+ -+#define sz_rfbClientCutTextMsg 8 -+ -+/*----------------------------------------------------------------------------- -+ * FileListRequest -+ */ -+ -+typedef struct _rfbFileListRequestMsg { -+ CARD8 type; -+ CARD8 flags; -+ CARD16 dirNameSize; -+ /* Followed by char Dirname[dirNameSize] */ -+} rfbFileListRequestMsg; -+ -+#define sz_rfbFileListRequestMsg 4 -+ -+/*----------------------------------------------------------------------------- -+ * FileDownloadRequest -+ */ -+ -+typedef struct _rfbFileDownloadRequestMsg { -+ CARD8 type; -+ CARD8 compressedLevel; -+ CARD16 fNameSize; -+ CARD32 position; -+ /* Followed by char Filename[fNameSize] */ -+} rfbFileDownloadRequestMsg; -+ -+#define sz_rfbFileDownloadRequestMsg 8 -+ -+/*----------------------------------------------------------------------------- -+ * FileUploadRequest -+ */ -+ -+typedef struct _rfbFileUploadRequestMsg { -+ CARD8 type; -+ CARD8 compressedLevel; -+ CARD16 fNameSize; -+ CARD32 position; -+ /* Followed by char Filename[fNameSize] */ -+} rfbFileUploadRequestMsg; -+ -+#define sz_rfbFileUploadRequestMsg 8 -+ -+ -+/*----------------------------------------------------------------------------- -+ * FileUploadData -+ */ -+ -+typedef struct _rfbFileUploadDataMsg { -+ CARD8 type; -+ CARD8 compressedLevel; -+ CARD16 realSize; -+ CARD16 compressedSize; -+ /* Followed by File[compressedSize] */ -+} rfbFileUploadDataMsg; -+ -+#define sz_rfbFileUploadDataMsg 8 -+ -+/*----------------------------------------------------------------------------- -+ * FileDownloadCancel -+ */ -+ -+typedef struct _rfbFileDownloadCancelMsg { -+ CARD8 type; -+ CARD8 unused; -+ CARD16 reasonLen; -+ /* Followed by reason[reasonLen] */ -+} rfbFileDownloadCancelMsg; -+ -+#define sz_rfbFileDownloadCancelMsg 4 -+ -+/*----------------------------------------------------------------------------- -+ * FileUploadFailed -+ */ -+ -+typedef struct _rfbFileUploadFailedMsg { -+ CARD8 type; -+ CARD8 unused; -+ CARD16 reasonLen; -+ /* Followed by reason[reasonLen] */ -+} rfbFileUploadFailedMsg; -+ -+#define sz_rfbFileUploadFailedMsg 4 -+ -+/*----------------------------------------------------------------------------- -+ * FileCreateDirRequest -+ */ -+ -+typedef struct _rfbFileCreateDirRequestMsg { -+ CARD8 type; -+ CARD8 unused; -+ CARD16 dNameLen; -+ CARD32 dModTime; -+ /* Followed by dName[dNameLen] */ -+} rfbFileCreateDirRequestMsg; -+ -+#define sz_rfbFileCreateDirRequestMsg 8 -+ -+/*----------------------------------------------------------------------------- -+ * ChromiumStop - the client has stopped the GL app. -+ */ -+ -+typedef struct { -+ CARD8 type; /* always rfbChromiumStop */ -+ CARD8 pad1; -+ CARD16 pad2; -+ CARD32 port; -+} rfbChromiumStopMsg; -+ -+#define sz_rfbChromiumStopMsg 8 -+ -+/*----------------------------------------------------------------------------- -+ * ChromiumExpose - redraw the window -+ */ -+ -+typedef struct { -+ CARD8 type; /* always rfbChromiumExpose */ -+ CARD8 pad1; -+ CARD16 pad2; -+ CARD32 winid; -+} rfbChromiumExposeMsg; -+ -+#define sz_rfbChromiumExposeMsg 8 -+ -+/*----------------------------------------------------------------------------- -+ * Union of all client->server messages. -+ */ -+ -+typedef union _rfbClientToServerMsg { -+ CARD8 type; -+ rfbSetPixelFormatMsg spf; -+ rfbFixColourMapEntriesMsg fcme; -+ rfbSetEncodingsMsg se; -+ rfbFramebufferUpdateRequestMsg fur; -+ rfbKeyEventMsg ke; -+ rfbPointerEventMsg pe; -+ rfbClientCutTextMsg cct; -+ rfbFileListRequestMsg flr; -+ rfbFileDownloadRequestMsg fdr; -+ rfbFileUploadRequestMsg fupr; -+ rfbFileUploadDataMsg fud; -+ rfbFileDownloadCancelMsg fdc; -+ rfbFileUploadFailedMsg fuf; -+ rfbFileCreateDirRequestMsg fcdr; -+ rfbChromiumStopMsg csd; -+ rfbChromiumExposeMsg cse; -+} rfbClientToServerMsg; -diff --git a/hw/vnc/rfbserver.c b/hw/vnc/rfbserver.c -new file mode 100644 -index 0000000..6e912e7 ---- /dev/null -+++ b/hw/vnc/rfbserver.c -@@ -0,0 +1,2273 @@ -+/* -+ * rfbserver.c - deal with server-side of the RFB protocol. -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ */ -+ -+/* -+ * Copyright (C) 2000-2004 Constantin Kaplinsky. All Rights Reserved. -+ * Copyright (C) 2000 Tridia Corporation. All Rights Reserved. -+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. -+ * -+ * This is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This software is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this software; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -+ * USA. -+ */ -+ -+/* Use ``#define CORBA'' to enable CORBA control interface */ -+ -+#include "rfb.h" -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "windowstr.h" -+#include "input.h" -+#include "mipointer.h" -+#if XFREE86VNC -+#include -+#endif -+#ifdef CHROMIUM -+#include "mivalidate.h" -+#endif -+#include "sprite.h" -+#include "propertyst.h" -+#include -+ -+#ifdef CORBA -+#include -+#endif -+ -+#ifdef CHROMIUM -+struct CRWindowTable *windowTable = NULL; -+#endif -+ -+extern Atom VNC_CONNECT; -+ -+rfbClientPtr rfbClientHead = NULL; -+rfbClientPtr pointerClient = NULL; /* Mutex for pointer events */ -+ -+static rfbClientPtr rfbNewClient(ScreenPtr pScreen, int sock); -+static void rfbProcessClientProtocolVersion(rfbClientPtr cl); -+static void rfbProcessClientInitMessage(rfbClientPtr cl); -+static void rfbSendInteractionCaps(rfbClientPtr cl); -+static void rfbProcessClientNormalMessage(rfbClientPtr cl); -+static Bool rfbSendCopyRegion(rfbClientPtr cl, RegionPtr reg, int dx, int dy); -+static Bool rfbSendLastRectMarker(rfbClientPtr cl); -+ -+static char *text = NULL; -+ -+void -+rfbRootPropertyChange(ScreenPtr pScreen) -+{ -+ PropertyPtr pProp; -+ WindowPtr pWin = WindowTable[pScreen->myNum]; -+ -+ pProp = wUserProps (pWin); -+ -+ while (pProp) { -+ if ((pProp->propertyName == XA_CUT_BUFFER0) && -+ (pProp->type == XA_STRING) && -+ (pProp->format == 8)) -+ { -+ /* Ensure we don't keep re-sending cut buffer */ -+ -+ if ( (text && pProp->data && strncmp(text, pProp->data, pProp->size)) || !text) -+ rfbGotXCutText(pProp->data, pProp->size); -+ -+ if (text) xfree(text); -+ text = xalloc(1 + pProp->size); -+ if (! text) return; -+ if (pProp->data) memcpy(text, pProp->data, pProp->size); -+ text[pProp->size] = '\0'; -+ -+ return; -+ } -+ if ((pProp->propertyName == VNC_CONNECT) && (pProp->type == XA_STRING) -+ && (pProp->format == 8) && (pProp->size > 0)) -+ { -+ 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(pScreen, host, port); -+ -+#ifdef CORBA -+ if (cl != NULL) -+ newConnection(cl, (KEYBOARD_DEVICE|POINTER_DEVICE), 1, 1, 1); -+#endif -+ -+ ChangeWindowProperty(pWin, -+ pProp->propertyName, pProp->type, -+ pProp->format, PropModeReplace, -+ 0, NULL, -+ FALSE -+ ); -+ -+ free(host); -+ } -+ pProp = pProp->next; -+ } -+} -+ -+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; -+} -+ -+void -+rfbUserAllow(int sock, int accept) -+{ -+ rfbClientPtr cl; -+ -+ for (cl = rfbClientHead; cl; cl = cl->next) { -+ if (cl->sock == sock) { -+ cl->userAccepted = accept; -+ } -+ } -+} -+ -+/* -+ * rfbNewClientConnection is called from sockets.c when a new connection -+ * comes in. -+ */ -+ -+void -+rfbNewClientConnection(ScreenPtr pScreen, int sock) -+{ -+ rfbClientPtr cl; -+ -+ cl = rfbNewClient(pScreen, sock); -+ -+ GenerateVncConnectedEvent(sock); -+ -+#if XFREE86VNC -+ /* Someone is connected - disable VT switching */ -+ xf86EnableVTSwitch(FALSE); -+#endif -+ -+#ifdef CORBA -+ if (cl != NULL) -+ newConnection(cl, (KEYBOARD_DEVICE|POINTER_DEVICE), 1, 1, 1); -+#endif -+} -+ -+ -+/* -+ * rfbReverseConnection is called by the CORBA stuff to make an outward -+ * connection to a "listening" RFB client. -+ */ -+ -+rfbClientPtr -+rfbReverseConnection(ScreenPtr pScreen, char *host, int port) -+{ -+ int sock; -+ rfbClientPtr cl; -+ -+ if ((sock = rfbConnect(pScreen, host, port)) < 0) -+ return (rfbClientPtr)NULL; -+ -+ cl = rfbNewClient(pScreen, sock); -+ -+ if (cl) { -+ cl->reverseConnection = TRUE; -+ } -+ -+ return cl; -+} -+ -+ -+#ifdef CHROMIUM -+/* -+ * rfbSetClip -- -+ * Generate expose event. -+ * This function is overkill and should be cleaned up, but it -+ * works for now. -+ */ -+ -+void -+rfbSetClip (WindowPtr pWin, BOOL enable) -+{ -+ ScreenPtr pScreen = pWin->drawable.pScreen; -+ WindowPtr pChild; -+ Bool WasViewable = (Bool)(pWin->viewable); -+ Bool anyMarked = FALSE; -+ RegionPtr pOldClip = NULL, bsExposed; -+#ifdef DO_SAVE_UNDERS -+ Bool dosave = FALSE; -+#endif -+ WindowPtr pLayerWin; -+ BoxRec box; -+ -+ if (WasViewable) -+ { -+ for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) -+ { -+ (void) (*pScreen->MarkOverlappedWindows)(pChild, -+ pChild, -+ &pLayerWin); -+ } -+ (*pScreen->MarkWindow) (pWin); -+ anyMarked = TRUE; -+ if (pWin->valdata) -+ { -+ if (HasBorder (pWin)) -+ { -+ RegionPtr borderVisible; -+ -+ borderVisible = REGION_CREATE(pScreen, NullBox, 1); -+ REGION_SUBTRACT(pScreen, borderVisible, -+ &pWin->borderClip, &pWin->winSize); -+ pWin->valdata->before.borderVisible = borderVisible; -+ } -+ pWin->valdata->before.resized = TRUE; -+ } -+ } -+ -+ /* -+ * Use REGION_BREAK to avoid optimizations in ValidateTree -+ * that assume the root borderClip can't change well, normally -+ * it doesn't...) -+ */ -+ if (enable) -+ { -+ box.x1 = 0; -+ box.y1 = 0; -+ box.x2 = pScreen->width; -+ box.y2 = pScreen->height; -+ REGION_INIT (pScreen, &pWin->winSize, &box, 1); -+ REGION_INIT (pScreen, &pWin->borderSize, &box, 1); -+ if (WasViewable) -+ REGION_RESET(pScreen, &pWin->borderClip, &box); -+ pWin->drawable.width = pScreen->width; -+ pWin->drawable.height = pScreen->height; -+ REGION_BREAK (pWin->drawable.pScreen, &pWin->clipList); -+ } -+ else -+ { -+ REGION_EMPTY(pScreen, &pWin->borderClip); -+ REGION_BREAK (pWin->drawable.pScreen, &pWin->clipList); -+ } -+ -+ ResizeChildrenWinSize (pWin, 0, 0, 0, 0); -+ -+ if (WasViewable) -+ { -+ if (pWin->backStorage) -+ { -+ pOldClip = REGION_CREATE(pScreen, NullBox, 1); -+ REGION_COPY(pScreen, pOldClip, &pWin->clipList); -+ } -+ -+ if (pWin->firstChild) -+ { -+ anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin->firstChild, -+ pWin->firstChild, -+ (WindowPtr *)NULL); -+ } -+ else -+ { -+ (*pScreen->MarkWindow) (pWin); -+ anyMarked = TRUE; -+ } -+ -+#ifdef DO_SAVE_UNDERS -+ if (DO_SAVE_UNDERS(pWin)) -+ { -+ dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, pLayerWin); -+ } -+#endif /* DO_SAVE_UNDERS */ -+ -+ if (anyMarked) -+ (*pScreen->ValidateTree)(pWin, NullWindow, VTOther); -+ } -+ -+ if (pWin->backStorage && -+ ((pWin->backingStore == Always) || WasViewable)) -+ { -+ if (!WasViewable) -+ pOldClip = &pWin->clipList; /* a convenient empty region */ -+ bsExposed = (*pScreen->TranslateBackingStore) -+ (pWin, 0, 0, pOldClip, -+ pWin->drawable.x, pWin->drawable.y); -+ if (WasViewable) -+ REGION_DESTROY(pScreen, pOldClip); -+ if (bsExposed) -+ { -+ RegionPtr valExposed = NullRegion; -+ -+ if (pWin->valdata) -+ valExposed = &pWin->valdata->after.exposed; -+ (*pScreen->WindowExposures) (pWin, valExposed, bsExposed); -+ if (valExposed) -+ REGION_EMPTY(pScreen, valExposed); -+ REGION_DESTROY(pScreen, bsExposed); -+ } -+ } -+ if (WasViewable) -+ { -+ if (anyMarked) -+ (*pScreen->HandleExposures)(pWin); -+#ifdef DO_SAVE_UNDERS -+ if (dosave) -+ (*pScreen->PostChangeSaveUnder)(pLayerWin, pLayerWin); -+#endif /* DO_SAVE_UNDERS */ -+ if (anyMarked && pScreen->PostValidateTree) -+ (*pScreen->PostValidateTree)(pWin, NullWindow, VTOther); -+ } -+ if (pWin->realized) -+ WindowsRestructured (); -+ FlushAllOutput (); -+} -+#endif /* CHROMIUM */ -+ -+/* -+ * rfbNewClient is called when a new connection has been made by whatever -+ * means. -+ */ -+ -+static rfbClientPtr -+rfbNewClient(ScreenPtr pScreen, int sock) -+{ -+ rfbProtocolVersionMsg pv; -+ rfbClientPtr cl; -+ BoxRec box; -+ struct sockaddr_in addr; -+ SOCKLEN_T addrlen = sizeof(struct sockaddr_in); -+ VNCSCREENPTR(pScreen); -+ int i; -+ -+ if (rfbClientHead == NULL) { -+ /* no other clients - make sure we don't think any keys are pressed */ -+ KbdReleaseAllKeys(); -+ } else { -+ rfbLog(" (other clients"); -+ for (cl = rfbClientHead; cl; cl = cl->next) { -+ rfbLog(" %s",cl->host); -+ } -+ rfbLog(")\n"); -+ } -+ -+ cl = (rfbClientPtr)xalloc(sizeof(rfbClientRec)); -+ -+#ifdef CHROMIUM -+ cl->chromium_port = 0; /* no GL application on this port, yet */ -+#endif -+ cl->userAccepted = 0; /* user hasn't even approached this yet .... */ -+ cl->sock = sock; -+ getpeername(sock, (struct sockaddr *)&addr, &addrlen); -+ cl->host = strdup(inet_ntoa(addr.sin_addr)); -+ cl->login = NULL; -+ -+ /* Dispatch client input to rfbProcessClientProtocolVersion(). */ -+ cl->state = RFB_PROTOCOL_VERSION; -+ -+ cl->viewOnly = FALSE; -+ cl->reverseConnection = FALSE; -+ cl->readyForSetColourMapEntries = FALSE; -+ cl->useCopyRect = FALSE; -+ cl->preferredEncoding = rfbEncodingRaw; -+ cl->correMaxWidth = 48; -+ cl->correMaxHeight = 48; -+ cl->pScreen = pScreen; -+ -+ REGION_NULL(pScreen,&cl->copyRegion); -+ cl->copyDX = 0; -+ cl->copyDY = 0; -+ -+ box.x1 = box.y1 = 0; -+ box.x2 = pVNC->width; -+ box.y2 = pVNC->height; -+ REGION_INIT(pScreen,&cl->modifiedRegion,&box,0); -+ -+ REGION_NULL(pScreen,&cl->requestedRegion); -+ -+ cl->deferredUpdateScheduled = FALSE; -+ cl->deferredUpdateTimer = NULL; -+ -+ cl->format = pVNC->rfbServerFormat; -+ cl->translateFn = rfbTranslateNone; -+ cl->translateLookupTable = NULL; -+ -+ cl->tightCompressLevel = TIGHT_DEFAULT_COMPRESSION; -+ cl->tightQualityLevel = -1; -+ for (i = 0; i < 4; i++) -+ cl->zsActive[i] = FALSE; -+ -+ cl->enableCursorShapeUpdates = FALSE; -+ cl->enableCursorPosUpdates = FALSE; -+ cl->enableLastRectEncoding = FALSE; -+#ifdef CHROMIUM -+ cl->enableChromiumEncoding = FALSE; -+#endif -+ -+ cl->next = rfbClientHead; -+ rfbClientHead = cl; -+ -+ rfbResetStats(cl); -+ -+ cl->compStreamInited = FALSE; -+ cl->compStream.total_in = 0; -+ cl->compStream.total_out = 0; -+ cl->compStream.zalloc = Z_NULL; -+ cl->compStream.zfree = Z_NULL; -+ cl->compStream.opaque = Z_NULL; -+ -+ cl->zlibCompressLevel = 5; -+ -+ sprintf(pv,rfbProtocolVersionFormat,rfbProtocolMajorVersion, -+ rfbProtocolMinorVersion); -+ -+ if (WriteExact(sock, pv, sz_rfbProtocolVersionMsg) < 0) { -+ rfbLogPerror("rfbNewClient: write"); -+ rfbCloseSock(pScreen, sock); -+ return NULL; -+ } -+ -+ return cl; -+} -+ -+ -+/* -+ * rfbClientConnectionGone is called from sockets.c just after a connection -+ * has gone away. -+ */ -+ -+void -+rfbClientConnectionGone(sock) -+ int sock; -+{ -+ rfbClientPtr cl, prev; -+ int i; -+#if XFREE86VNC -+ int allowvt = TRUE; -+#endif -+ -+ for (prev = NULL, cl = rfbClientHead; cl; prev = cl, cl = cl->next) { -+ if (sock == cl->sock) -+ break; -+ } -+ -+ if (!cl) { -+ rfbLog("rfbClientConnectionGone: unknown socket %d\n",sock); -+ return; -+ } -+ -+ if (cl->login != NULL) { -+ rfbLog("Client %s (%s) gone\n", cl->login, cl->host); -+ free(cl->login); -+ } else { -+ rfbLog("Client %s gone\n", cl->host); -+ } -+ free(cl->host); -+ -+ /* Release the compression state structures if any. */ -+ if ( cl->compStreamInited == TRUE ) { -+ deflateEnd( &(cl->compStream) ); -+ } -+ -+ for (i = 0; i < 4; i++) { -+ if (cl->zsActive[i]) -+ deflateEnd(&cl->zsStruct[i]); -+ } -+ -+ if (pointerClient == cl) -+ pointerClient = NULL; -+ -+#ifdef CORBA -+ destroyConnection(cl); -+#endif -+ -+ if (prev) -+ prev->next = cl->next; -+ else -+ rfbClientHead = cl->next; -+ -+ REGION_UNINIT(cl->pScreen,&cl->copyRegion); -+ REGION_UNINIT(cl->pScreen,&cl->modifiedRegion); -+ TimerFree(cl->deferredUpdateTimer); -+ -+ rfbPrintStats(cl); -+ -+ if (cl->translateLookupTable) free(cl->translateLookupTable); -+ -+ xfree(cl); -+ -+ GenerateVncDisconnectedEvent(sock); -+ -+#if XFREE86VNC -+ for (cl = rfbClientHead; cl; cl = cl->next) { -+ /* still someone connected */ -+ allowvt = FALSE; -+ } -+ -+ xf86EnableVTSwitch(allowvt); -+#endif -+} -+ -+ -+/* -+ * rfbProcessClientMessage is called when there is data to read from a client. -+ */ -+ -+void -+rfbProcessClientMessage(ScreenPtr pScreen, int sock) -+{ -+ rfbClientPtr cl; -+ -+ for (cl = rfbClientHead; cl; cl = cl->next) { -+ if (sock == cl->sock) -+ break; -+ } -+ -+ if (!cl) { -+ rfbLog("rfbProcessClientMessage: unknown socket %d\n",sock); -+ rfbCloseSock(pScreen, sock); -+ return; -+ } -+ -+#ifdef CORBA -+ if (isClosePending(cl)) { -+ rfbLog("Closing connection to client %s\n", cl->host); -+ rfbCloseSock(pScreen, sock); -+ return; -+ } -+#endif -+ -+ switch (cl->state) { -+ case RFB_PROTOCOL_VERSION: -+ rfbProcessClientProtocolVersion(cl); -+ break; -+ case RFB_SECURITY_TYPE: /* protocol 3.7 */ -+ rfbProcessClientSecurityType(cl); -+ break; -+ case RFB_TUNNELING_TYPE: /* protocol 3.7t */ -+ rfbProcessClientTunnelingType(cl); -+ break; -+ case RFB_AUTH_TYPE: /* protocol 3.7t */ -+ rfbProcessClientAuthType(cl); -+ break; -+ case RFB_AUTHENTICATION: -+ rfbVncAuthProcessResponse(cl); -+ break; -+ case RFB_INITIALISATION: -+ rfbProcessClientInitMessage(cl); -+ break; -+ default: -+ rfbProcessClientNormalMessage(cl); -+ } -+} -+ -+ -+/* -+ * rfbProcessClientProtocolVersion is called when the client sends its -+ * protocol version. -+ */ -+ -+static void -+rfbProcessClientProtocolVersion(cl) -+ rfbClientPtr cl; -+{ -+ rfbProtocolVersionMsg pv; -+ int n, major, minor; -+ -+ if ((n = ReadExact(cl->sock, pv, sz_rfbProtocolVersionMsg)) <= 0) { -+ if (n == 0) -+ rfbLog("rfbProcessClientProtocolVersion: client gone\n"); -+ else -+ rfbLogPerror("rfbProcessClientProtocolVersion: read"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ pv[sz_rfbProtocolVersionMsg] = 0; -+ if (sscanf(pv,rfbProtocolVersionFormat,&major,&minor) != 2) { -+ rfbLog("rfbProcessClientProtocolVersion: not a valid RFB client\n"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ rfbLog("Using protocol version %d.%d\n", major, minor); -+ -+ if (major != rfbProtocolMajorVersion) { -+ rfbLog("RFB protocol version mismatch - server %d.%d, client %d.%d\n", -+ rfbProtocolMajorVersion,rfbProtocolMinorVersion,major,minor); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ /* Always use one of the two standard versions of the RFB protocol. */ -+ cl->protocol_minor_ver = minor; -+ if (minor > rfbProtocolMinorVersion) { -+ cl->protocol_minor_ver = rfbProtocolMinorVersion; -+ } else if (minor < rfbProtocolMinorVersion) { -+ cl->protocol_minor_ver = rfbProtocolFallbackMinorVersion; -+ } -+ if (minor != rfbProtocolMinorVersion && -+ minor != rfbProtocolFallbackMinorVersion) { -+ rfbLog("Non-standard protocol version %d.%d, using %d.%d instead\n", -+ major, minor, rfbProtocolMajorVersion, cl->protocol_minor_ver); -+ } -+ -+ /* TightVNC protocol extensions are not enabled yet. */ -+ cl->protocol_tightvnc = FALSE; -+ -+ rfbAuthNewClient(cl); -+} -+ -+/* -+ * rfbClientConnFailed is called when a client connection has failed -+ * before the authentication stage. -+ */ -+ -+void -+rfbClientConnFailed(cl, reason) -+ rfbClientPtr cl; -+ char *reason; -+{ -+ int headerLen, reasonLen; -+ char buf[8]; -+ -+ headerLen = (cl->protocol_minor_ver >= 7) ? 1 : 4; -+ reasonLen = strlen(reason); -+ ((CARD32 *)buf)[0] = 0; -+ ((CARD32 *)buf)[1] = Swap32IfLE(reasonLen); -+ -+ if ( WriteExact(cl->sock, buf, headerLen) < 0 || -+ WriteExact(cl->sock, buf + 4, 4) < 0 || -+ WriteExact(cl->sock, reason, reasonLen) < 0 ) { -+ rfbLogPerror("rfbClientConnFailed: write"); -+ } -+ -+ rfbCloseSock(cl->pScreen, cl->sock); -+} -+ -+ -+/* -+ * rfbProcessClientInitMessage is called when the client sends its -+ * initialisation message. -+ */ -+ -+static void -+rfbProcessClientInitMessage(cl) -+ rfbClientPtr cl; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ rfbClientInitMsg ci; -+ char buf[256]; -+ rfbServerInitMsg *si = (rfbServerInitMsg *)buf; -+ struct passwd *user; -+ int len, n; -+ rfbClientPtr otherCl, nextCl; -+ -+ if ((n = ReadExact(cl->sock, (char *)&ci,sz_rfbClientInitMsg)) <= 0) { -+ if (n == 0) -+ rfbLog("rfbProcessClientInitMessage: client gone\n"); -+ else -+ rfbLogPerror("rfbProcessClientInitMessage: read"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ si->framebufferWidth = Swap16IfLE(pVNC->width); -+ si->framebufferHeight = Swap16IfLE(pVNC->height); -+ si->format = pVNC->rfbServerFormat; -+ si->format.redMax = Swap16IfLE(si->format.redMax); -+ si->format.greenMax = Swap16IfLE(si->format.greenMax); -+ si->format.blueMax = Swap16IfLE(si->format.blueMax); -+ -+ user = getpwuid(getuid()); -+ -+ if (strlen(desktopName) > 128) /* sanity check on desktop name len */ -+ desktopName[128] = 0; -+ -+ if (user) { -+ sprintf(buf + sz_rfbServerInitMsg, "%s's %s desktop (%s:%s)", -+ user->pw_name, desktopName, rfbThisHost, display); -+ } else { -+ sprintf(buf + sz_rfbServerInitMsg, "%s desktop (%s:%s)", -+ desktopName, rfbThisHost, display); -+ } -+ len = strlen(buf + sz_rfbServerInitMsg); -+ si->nameLength = Swap32IfLE(len); -+ -+ if (WriteExact(cl->sock, buf, sz_rfbServerInitMsg + len) < 0) { -+ rfbLogPerror("rfbProcessClientInitMessage: write"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ if (cl->protocol_tightvnc) -+ rfbSendInteractionCaps(cl); /* protocol 3.7t */ -+ -+ /* Dispatch client input to rfbProcessClientNormalMessage(). */ -+ cl->state = RFB_NORMAL; -+ -+ if (!cl->reverseConnection && -+ (pVNC->rfbNeverShared || (!pVNC->rfbAlwaysShared && !ci.shared))) { -+ -+ if (pVNC->rfbDontDisconnect) { -+ for (otherCl = rfbClientHead; otherCl; otherCl = otherCl->next) { -+ if ((otherCl != cl) && (otherCl->state == RFB_NORMAL)) { -+ rfbLog("-dontdisconnect: Not shared & existing client\n"); -+ rfbLog(" refusing new client %s\n", cl->host); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ } -+ } else { -+ for (otherCl = rfbClientHead; otherCl; otherCl = nextCl) { -+ nextCl = otherCl->next; -+ if ((otherCl != cl) && (otherCl->state == RFB_NORMAL)) { -+ rfbLog("Not shared - closing connection to client %s\n", -+ otherCl->host); -+ rfbCloseSock(otherCl->pScreen, otherCl->sock); -+ } -+ } -+ } -+ } -+} -+ -+ -+/* -+ * rfbSendInteractionCaps is called after sending the server -+ * initialisation message, only if the protocol version is 3.130. -+ * In this function, we send the lists of supported protocol messages -+ * and encodings. -+ */ -+ -+/* Update these constants on changing capability lists below! */ -+#define N_SMSG_CAPS 0 -+#define N_CMSG_CAPS 0 -+#define N_ENC_CAPS 12 -+ -+void -+rfbSendInteractionCaps(cl) -+ rfbClientPtr cl; -+{ -+ rfbInteractionCapsMsg intr_caps; -+ rfbCapabilityInfo enc_list[N_ENC_CAPS]; -+ int i; -+ -+ /* Fill in the header structure sent prior to capability lists. */ -+ intr_caps.nServerMessageTypes = Swap16IfLE(N_SMSG_CAPS); -+ intr_caps.nClientMessageTypes = Swap16IfLE(N_CMSG_CAPS); -+ intr_caps.nEncodingTypes = Swap16IfLE(N_ENC_CAPS); -+ intr_caps.pad = 0; -+ -+ /* Supported server->client message types. */ -+ /* For future file transfer support: -+ i = 0; -+ SetCapInfo(&smsg_list[i++], rfbFileListData, rfbTightVncVendor); -+ SetCapInfo(&smsg_list[i++], rfbFileDownloadData, rfbTightVncVendor); -+ SetCapInfo(&smsg_list[i++], rfbFileUploadCancel, rfbTightVncVendor); -+ SetCapInfo(&smsg_list[i++], rfbFileDownloadFailed, rfbTightVncVendor); -+ if (i != N_SMSG_CAPS) { -+ rfbLog("rfbSendInteractionCaps: assertion failed, i != N_SMSG_CAPS\n"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ */ -+ -+ /* Supported client->server message types. */ -+ /* For future file transfer support: -+ i = 0; -+ SetCapInfo(&cmsg_list[i++], rfbFileListRequest, rfbTightVncVendor); -+ SetCapInfo(&cmsg_list[i++], rfbFileDownloadRequest, rfbTightVncVendor); -+ SetCapInfo(&cmsg_list[i++], rfbFileUploadRequest, rfbTightVncVendor); -+ SetCapInfo(&cmsg_list[i++], rfbFileUploadData, rfbTightVncVendor); -+ SetCapInfo(&cmsg_list[i++], rfbFileDownloadCancel, rfbTightVncVendor); -+ SetCapInfo(&cmsg_list[i++], rfbFileUploadFailed, rfbTightVncVendor); -+ if (i != N_CMSG_CAPS) { -+ rfbLog("rfbSendInteractionCaps: assertion failed, i != N_CMSG_CAPS\n"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ */ -+ -+ /* Encoding types. */ -+ i = 0; -+ SetCapInfo(&enc_list[i++], rfbEncodingCopyRect, rfbStandardVendor); -+ SetCapInfo(&enc_list[i++], rfbEncodingRRE, rfbStandardVendor); -+ SetCapInfo(&enc_list[i++], rfbEncodingCoRRE, rfbStandardVendor); -+ SetCapInfo(&enc_list[i++], rfbEncodingHextile, rfbStandardVendor); -+ SetCapInfo(&enc_list[i++], rfbEncodingZlib, rfbTridiaVncVendor); -+ SetCapInfo(&enc_list[i++], rfbEncodingTight, rfbTightVncVendor); -+ SetCapInfo(&enc_list[i++], rfbEncodingCompressLevel0, rfbTightVncVendor); -+ SetCapInfo(&enc_list[i++], rfbEncodingQualityLevel0, rfbTightVncVendor); -+ SetCapInfo(&enc_list[i++], rfbEncodingXCursor, rfbTightVncVendor); -+ SetCapInfo(&enc_list[i++], rfbEncodingRichCursor, rfbTightVncVendor); -+ SetCapInfo(&enc_list[i++], rfbEncodingPointerPos, rfbTightVncVendor); -+ SetCapInfo(&enc_list[i++], rfbEncodingLastRect, rfbTightVncVendor); -+ if (i != N_ENC_CAPS) { -+ rfbLog("rfbSendInteractionCaps: assertion failed, i != N_ENC_CAPS\n"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ /* Send header and capability lists */ -+ if (WriteExact(cl->sock, (char *)&intr_caps, -+ sz_rfbInteractionCapsMsg) < 0 || -+ WriteExact(cl->sock, (char *)&enc_list[0], -+ sz_rfbCapabilityInfo * N_ENC_CAPS) < 0) { -+ rfbLogPerror("rfbSendInteractionCaps: write"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ /* Dispatch client input to rfbProcessClientNormalMessage(). */ -+ cl->state = RFB_NORMAL; -+} -+ -+ -+/* -+ * rfbProcessClientNormalMessage is called when the client has sent a normal -+ * protocol message. -+ */ -+ -+static void -+rfbProcessClientNormalMessage(cl) -+ rfbClientPtr cl; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ int n; -+ rfbClientToServerMsg msg; -+ char *str; -+ -+ if (pVNC->rfbUserAccept) { -+ /* -+ * We've asked for another level of user authentication -+ * If the user has not validated this connected, don't -+ * process it. -+ */ -+ /* -+ * NOTE: we do it here, so the vncviewer knows it's -+ * connected, but waiting for the first screen update -+ */ -+ if (cl->userAccepted == VNC_USER_UNDEFINED) { -+ usleep(10); -+ return; -+ } -+ if (cl->userAccepted == VNC_USER_DISCONNECT) { -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ } -+ -+ if ((n = ReadExact(cl->sock, (char *)&msg, 1)) <= 0) { -+ if (n != 0) -+ rfbLogPerror("rfbProcessClientNormalMessage: read"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ switch (msg.type) { -+ -+ case rfbSetPixelFormat: -+ -+ if ((n = ReadExact(cl->sock, ((char *)&msg) + 1, -+ sz_rfbSetPixelFormatMsg - 1)) <= 0) { -+ if (n != 0) -+ rfbLogPerror("rfbProcessClientNormalMessage: read"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ cl->format.bitsPerPixel = msg.spf.format.bitsPerPixel; -+ cl->format.depth = msg.spf.format.depth; -+ cl->format.bigEndian = (msg.spf.format.bigEndian ? 1 : 0); -+ cl->format.trueColour = (msg.spf.format.trueColour ? 1 : 0); -+ cl->format.redMax = Swap16IfLE(msg.spf.format.redMax); -+ cl->format.greenMax = Swap16IfLE(msg.spf.format.greenMax); -+ cl->format.blueMax = Swap16IfLE(msg.spf.format.blueMax); -+ cl->format.redShift = msg.spf.format.redShift; -+ cl->format.greenShift = msg.spf.format.greenShift; -+ cl->format.blueShift = msg.spf.format.blueShift; -+ -+ cl->readyForSetColourMapEntries = TRUE; -+ -+ rfbSetTranslateFunction(cl); -+ return; -+ -+ -+ case rfbFixColourMapEntries: -+ if ((n = ReadExact(cl->sock, ((char *)&msg) + 1, -+ sz_rfbFixColourMapEntriesMsg - 1)) <= 0) { -+ if (n != 0) -+ rfbLogPerror("rfbProcessClientNormalMessage: read"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ rfbLog("rfbProcessClientNormalMessage: %s", -+ "FixColourMapEntries unsupported\n"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ -+ -+ case rfbSetEncodings: -+ { -+ int i; -+ CARD32 enc; -+ -+ if ((n = ReadExact(cl->sock, ((char *)&msg) + 1, -+ sz_rfbSetEncodingsMsg - 1)) <= 0) { -+ if (n != 0) -+ rfbLogPerror("rfbProcessClientNormalMessage: read"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ msg.se.nEncodings = Swap16IfLE(msg.se.nEncodings); -+ -+ cl->preferredEncoding = -1; -+ cl->useCopyRect = FALSE; -+ cl->enableCursorShapeUpdates = FALSE; -+ cl->enableCursorPosUpdates = FALSE; -+ cl->enableLastRectEncoding = FALSE; -+#ifdef CHROMIUM -+ cl->enableChromiumEncoding = FALSE; -+#endif -+ cl->tightCompressLevel = TIGHT_DEFAULT_COMPRESSION; -+ cl->tightQualityLevel = -1; -+ -+ for (i = 0; i < msg.se.nEncodings; i++) { -+ if ((n = ReadExact(cl->sock, (char *)&enc, 4)) <= 0) { -+ if (n != 0) -+ rfbLogPerror("rfbProcessClientNormalMessage: read"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ enc = Swap32IfLE(enc); -+ -+ switch (enc) { -+ -+ case rfbEncodingCopyRect: -+ cl->useCopyRect = TRUE; -+ rfbLog("Using copyrect encoding for client %s\n", -+ cl->host); -+ break; -+ case rfbEncodingRaw: -+ if (cl->preferredEncoding == -1) { -+ cl->preferredEncoding = enc; -+ rfbLog("Using raw encoding for client %s\n", -+ cl->host); -+ } -+ break; -+ case rfbEncodingRRE: -+ if (cl->preferredEncoding == -1) { -+ cl->preferredEncoding = enc; -+ rfbLog("Using rre encoding for client %s\n", -+ cl->host); -+ } -+ break; -+ case rfbEncodingCoRRE: -+ if (cl->preferredEncoding == -1) { -+ cl->preferredEncoding = enc; -+ rfbLog("Using CoRRE encoding for client %s\n", -+ cl->host); -+ } -+ break; -+ case rfbEncodingHextile: -+ if (cl->preferredEncoding == -1) { -+ cl->preferredEncoding = enc; -+ rfbLog("Using hextile encoding for client %s\n", -+ cl->host); -+ } -+ break; -+ case rfbEncodingZlib: -+ if (cl->preferredEncoding == -1) { -+ cl->preferredEncoding = enc; -+ rfbLog("Using zlib encoding for client %s\n", -+ cl->host); -+ } -+ break; -+ case rfbEncodingTight: -+ if (cl->preferredEncoding == -1) { -+ cl->preferredEncoding = enc; -+ rfbLog("Using tight encoding for client %s\n", -+ cl->host); -+ } -+ break; -+ case rfbEncodingXCursor: -+ rfbLog("Enabling X-style cursor updates for client %s\n", -+ cl->host); -+ cl->enableCursorShapeUpdates = TRUE; -+ cl->useRichCursorEncoding = FALSE; -+ cl->cursorWasChanged = TRUE; -+ break; -+ case rfbEncodingRichCursor: -+ if (!cl->enableCursorShapeUpdates) { -+ rfbLog("Enabling full-color cursor updates for client " -+ "%s\n", cl->host); -+ cl->enableCursorShapeUpdates = TRUE; -+ cl->useRichCursorEncoding = TRUE; -+ cl->cursorWasChanged = TRUE; -+ } -+ break; -+ case rfbEncodingPointerPos: -+ if (!cl->enableCursorPosUpdates) { -+ rfbLog("Enabling cursor position updates for client %s\n", -+ cl->host); -+ cl->enableCursorPosUpdates = TRUE; -+ cl->cursorWasMoved = TRUE; -+ cl->cursorX = -1; -+ cl->cursorY = -1; -+ } -+ break; -+ case rfbEncodingLastRect: -+ if (!cl->enableLastRectEncoding) { -+ rfbLog("Enabling LastRect protocol extension for client " -+ "%s\n", cl->host); -+ cl->enableLastRectEncoding = TRUE; -+ } -+ break; -+#ifdef CHROMIUM -+ case rfbEncodingChromium: -+ case rfbEncodingChromium2: -+ if (!cl->enableChromiumEncoding) { -+ cl->enableChromiumEncoding = TRUE; -+ /* This tells OpenGL apps/replicate SPUs that new viewer -+ * has attached. -+ */ -+ GenerateVncChromiumConnectedEvent(cl->sock); -+ if (enc == rfbEncodingChromium) { -+ /* Generate exposures for all windows */ -+ WindowPtr pWin = WindowTable[cl->pScreen->myNum]; -+ rfbSetClip(pWin, 1); -+ } -+ else { -+ /* don't generate exposures for Chromium2 because -+ * that confused DMX. -+ */ -+ } -+ } -+ break; -+#endif -+ default: -+ if ( enc >= (CARD32)rfbEncodingCompressLevel0 && -+ enc <= (CARD32)rfbEncodingCompressLevel9 ) { -+ cl->zlibCompressLevel = enc & 0x0F; -+ cl->tightCompressLevel = enc & 0x0F; -+ rfbLog("Using compression level %d for client %s\n", -+ cl->tightCompressLevel, cl->host); -+ } else if ( enc >= (CARD32)rfbEncodingQualityLevel0 && -+ enc <= (CARD32)rfbEncodingQualityLevel9 ) { -+ cl->tightQualityLevel = enc & 0x0F; -+ rfbLog("Using image quality level %d for client %s\n", -+ cl->tightQualityLevel, cl->host); -+ } else { -+ rfbLog("rfbProcessClientNormalMessage: ignoring unknown " -+ "encoding %d\n", (int)enc); -+ } -+ } -+ } -+ -+ if (cl->preferredEncoding == -1) { -+ cl->preferredEncoding = rfbEncodingRaw; -+ rfbLog("No encoding specified - using raw encoding for client %s\n", -+ cl->host); -+ } -+ -+ if (cl->enableCursorPosUpdates && !cl->enableCursorShapeUpdates) { -+ rfbLog("Disabling cursor position updates for client %s\n", -+ cl->host); -+ cl->enableCursorPosUpdates = FALSE; -+ } -+ -+#if XFREE86VNC -+ /* -+ * With XFree86 and the hardware cursor's we need to put up the -+ * cursor again, and if we've detected a cursor shapeless client -+ * we need to disable hardware cursors. -+ */ -+ if (!cl->enableCursorShapeUpdates) -+ pVNC->SWCursor = (Bool *)TRUE; -+ else -+ pVNC->SWCursor = (Bool *)FALSE; -+ -+ { -+ int x, y; -+ miPointerPosition(&x, &y); -+ (*pVNC->spriteFuncs->SetCursor)(cl->pScreen, pVNC->pCurs, x, y); -+ } -+#endif -+ -+ return; -+ } -+ -+ -+ case rfbFramebufferUpdateRequest: -+ { -+ RegionRec tmpRegion; -+ BoxRec box; -+ -+#ifdef CORBA -+ addCapability(cl, DISPLAY_DEVICE); -+#endif -+ -+ if ((n = ReadExact(cl->sock, ((char *)&msg) + 1, -+ sz_rfbFramebufferUpdateRequestMsg-1)) <= 0) { -+ if (n != 0) -+ rfbLogPerror("rfbProcessClientNormalMessage: read"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ box.x1 = Swap16IfLE(msg.fur.x); -+ box.y1 = Swap16IfLE(msg.fur.y); -+ box.x2 = box.x1 + Swap16IfLE(msg.fur.w); -+ box.y2 = box.y1 + Swap16IfLE(msg.fur.h); -+ SAFE_REGION_INIT(cl->pScreen,&tmpRegion,&box,0); -+ -+ REGION_UNION(cl->pScreen, &cl->requestedRegion, &cl->requestedRegion, -+ &tmpRegion); -+ -+ if (!cl->readyForSetColourMapEntries) { -+ /* client hasn't sent a SetPixelFormat so is using server's */ -+ cl->readyForSetColourMapEntries = TRUE; -+ if (!cl->format.trueColour) { -+ if (!rfbSetClientColourMap(cl, 0, 0)) { -+ REGION_UNINIT(cl->pScreen,&tmpRegion); -+ return; -+ } -+ } -+ } -+ -+ if (!msg.fur.incremental) { -+ REGION_UNION(cl->pScreen,&cl->modifiedRegion,&cl->modifiedRegion, -+ &tmpRegion); -+ REGION_SUBTRACT(cl->pScreen,&cl->copyRegion,&cl->copyRegion, -+ &tmpRegion); -+ } -+ -+ if (FB_UPDATE_PENDING(cl)) { -+ rfbSendFramebufferUpdate(cl->pScreen, cl); -+ } -+ -+ REGION_UNINIT(cl->pScreen,&tmpRegion); -+ return; -+ } -+ -+ case rfbKeyEvent: -+ -+ cl->rfbKeyEventsRcvd++; -+ -+ if ((n = ReadExact(cl->sock, ((char *)&msg) + 1, -+ sz_rfbKeyEventMsg - 1)) <= 0) { -+ if (n != 0) -+ rfbLogPerror("rfbProcessClientNormalMessage: read"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+#ifdef CORBA -+ addCapability(cl, KEYBOARD_DEVICE); -+ -+ if (!isKeyboardEnabled(cl)) -+ return; -+#endif -+ if (!pVNC->rfbViewOnly && !cl->viewOnly) { -+ KbdAddEvent(msg.ke.down, (KeySym)Swap32IfLE(msg.ke.key), cl); -+ } -+ return; -+ -+ -+ case rfbPointerEvent: -+ -+ cl->rfbPointerEventsRcvd++; -+ -+ if ((n = ReadExact(cl->sock, ((char *)&msg) + 1, -+ sz_rfbPointerEventMsg - 1)) <= 0) { -+ if (n != 0) -+ rfbLogPerror("rfbProcessClientNormalMessage: read"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+#ifdef CORBA -+ addCapability(cl, POINTER_DEVICE); -+ -+ if (!isPointerEnabled(cl)) -+ return; -+#endif -+ -+ if (pointerClient && (pointerClient != cl)) -+ return; -+ -+ if (msg.pe.buttonMask == 0) -+ pointerClient = NULL; -+ else -+ pointerClient = cl; -+ -+ if (!pVNC->rfbViewOnly && !cl->viewOnly) { -+ cl->cursorX = (int)Swap16IfLE(msg.pe.x); -+ cl->cursorY = (int)Swap16IfLE(msg.pe.y); -+ PtrAddEvent(msg.pe.buttonMask, cl->cursorX, cl->cursorY, cl); -+ } -+ return; -+ -+ -+ case rfbClientCutText: -+ -+ if ((n = ReadExact(cl->sock, ((char *)&msg) + 1, -+ sz_rfbClientCutTextMsg - 1)) <= 0) { -+ if (n != 0) -+ rfbLogPerror("rfbProcessClientNormalMessage: read"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ msg.cct.length = Swap32IfLE(msg.cct.length); -+ -+ str = (char *)xalloc(msg.cct.length); -+ -+ if ((n = ReadExact(cl->sock, str, msg.cct.length)) <= 0) { -+ if (n != 0) -+ rfbLogPerror("rfbProcessClientNormalMessage: read"); -+ xfree(str); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ /* NOTE: We do not accept cut text from a view-only client */ -+ if (!cl->viewOnly) -+ rfbSetXCutText(str, msg.cct.length); -+ -+ xfree(str); -+ return; -+ -+#ifdef CHROMIUM -+ case rfbChromiumStop: -+ if ((n = ReadExact(cl->sock, ((char *)&msg) + 1, -+ sz_rfbChromiumStopMsg - 1)) <= 0) { -+ if (n != 0) -+ rfbLogPerror("rfbProcessClientNormalMessage: read"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ /* would we use msg.csd.port ??? */ -+ -+ cl->chromium_port = 0; -+ -+ /* tear down window information */ -+ { -+ CRWindowTable *wt, *nextWt = NULL; -+ -+ for (wt = windowTable; wt; wt = nextWt) { -+ nextWt = wt->next; -+ xfree(wt); -+ } -+ -+ windowTable = NULL; -+ } -+ -+ return; -+ -+ case rfbChromiumExpose: -+ if ((n = ReadExact(cl->sock, ((char *)&msg) + 1, -+ sz_rfbChromiumExposeMsg - 1)) <= 0) { -+ if (n != 0) -+ rfbLogPerror("rfbProcessClientNormalMessage: read"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ /* find the window and re-expose it */ -+ { -+ CRWindowTable *wt, *nextWt = NULL; -+ -+ for (wt = windowTable; wt; wt = nextWt) { -+ nextWt = wt->next; -+ if (wt->CRwinId == msg.cse.winid) { -+ WindowPtr pWin; -+ pWin = LookupIDByType(wt->XwinId, RT_WINDOW); -+ if (pWin) { -+ miSendExposures(pWin, &pWin->clipList, -+ pWin->drawable.x, -+ pWin->drawable.y); -+ FlushAllOutput(); -+ } -+ } -+ } -+ } -+ -+ return; -+#endif -+ -+ default: -+ -+ rfbLog("rfbProcessClientNormalMessage: unknown message type %d\n", -+ msg.type); -+ rfbLog(" ... closing connection\n"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+} -+ -+ -+ -+/* -+ * rfbSendFramebufferUpdate - send the currently pending framebuffer update to -+ * the RFB client. -+ */ -+ -+Bool -+rfbSendFramebufferUpdate(pScreen, cl) -+ ScreenPtr pScreen; -+ rfbClientPtr cl; -+{ -+ VNCSCREENPTR(pScreen); -+ int i; -+ int nUpdateRegionRects; -+ rfbFramebufferUpdateMsg *fu = (rfbFramebufferUpdateMsg *)pVNC->updateBuf; -+ RegionRec updateRegion, updateCopyRegion; -+ int dx, dy; -+ Bool sendCursorShape = FALSE; -+ Bool sendCursorPos = FALSE; -+ -+ /* -+ * If this client understands cursor shape updates, cursor should be -+ * removed from the framebuffer. Otherwise, make sure it's put up. -+ */ -+ -+#if !XFREE86VNC -+ if (cl->enableCursorShapeUpdates) { -+ if (pVNC->cursorIsDrawn) -+ rfbSpriteRemoveCursor(pScreen); -+ if (!pVNC->cursorIsDrawn && cl->cursorWasChanged) -+ sendCursorShape = TRUE; -+ } else { -+ if (!pVNC->cursorIsDrawn) -+ rfbSpriteRestoreCursor(pScreen); -+ } -+#else -+ if (cl->enableCursorShapeUpdates) -+ if (cl->cursorWasChanged) -+ sendCursorShape = TRUE; -+#endif -+ -+ /* -+ * Do we plan to send cursor position update? -+ */ -+ -+ if (cl->enableCursorPosUpdates && cl->cursorWasMoved) -+ sendCursorPos = TRUE; -+ -+ /* -+ * The modifiedRegion may overlap the destination copyRegion. We remove -+ * any overlapping bits from the copyRegion (since they'd only be -+ * overwritten anyway). -+ */ -+ -+ REGION_SUBTRACT(pScreen, &cl->copyRegion, &cl->copyRegion, -+ &cl->modifiedRegion); -+ -+ /* -+ * The client is interested in the region requestedRegion. The region -+ * which should be updated now is the intersection of requestedRegion -+ * and the union of modifiedRegion and copyRegion. If it's empty then -+ * no update is needed. -+ */ -+ -+ REGION_NULL(pScreen,&updateRegion); -+ REGION_UNION(pScreen, &updateRegion, &cl->copyRegion, -+ &cl->modifiedRegion); -+ REGION_INTERSECT(pScreen, &updateRegion, &cl->requestedRegion, -+ &updateRegion); -+ -+ if ( !REGION_NOTEMPTY(pScreen,&updateRegion) && -+ !sendCursorShape && !sendCursorPos ) { -+ REGION_UNINIT(pScreen,&updateRegion); -+ return TRUE; -+ } -+ -+ /* -+ * We assume that the client doesn't have any pixel data outside the -+ * requestedRegion. In other words, both the source and destination of a -+ * copy must lie within requestedRegion. So the region we can send as a -+ * copy is the intersection of the copyRegion with both the requestedRegion -+ * and the requestedRegion translated by the amount of the copy. We set -+ * updateCopyRegion to this. -+ */ -+ -+ REGION_NULL(pScreen,&updateCopyRegion); -+ REGION_INTERSECT(pScreen, &updateCopyRegion, &cl->copyRegion, -+ &cl->requestedRegion); -+ REGION_TRANSLATE(pScreen, &cl->requestedRegion, cl->copyDX, cl->copyDY); -+ REGION_INTERSECT(pScreen, &updateCopyRegion, &updateCopyRegion, -+ &cl->requestedRegion); -+ dx = cl->copyDX; -+ dy = cl->copyDY; -+ -+ /* -+ * Next we remove updateCopyRegion from updateRegion so that updateRegion -+ * is the part of this update which is sent as ordinary pixel data (i.e not -+ * a copy). -+ */ -+ -+ REGION_SUBTRACT(pScreen, &updateRegion, &updateRegion, &updateCopyRegion); -+ -+ /* -+ * Finally we leave modifiedRegion to be the remainder (if any) of parts of -+ * the screen which are modified but outside the requestedRegion. We also -+ * empty both the requestedRegion and the copyRegion - note that we never -+ * carry over a copyRegion for a future update. -+ */ -+ -+ REGION_UNION(pScreen, &cl->modifiedRegion, &cl->modifiedRegion, -+ &cl->copyRegion); -+ REGION_SUBTRACT(pScreen, &cl->modifiedRegion, &cl->modifiedRegion, -+ &updateRegion); -+ REGION_SUBTRACT(pScreen, &cl->modifiedRegion, &cl->modifiedRegion, -+ &updateCopyRegion); -+ -+ REGION_EMPTY(pScreen, &cl->requestedRegion); -+ REGION_EMPTY(pScreen, &cl->copyRegion); -+ cl->copyDX = 0; -+ cl->copyDY = 0; -+ -+ /* -+ * Now send the update. -+ */ -+ -+ cl->rfbFramebufferUpdateMessagesSent++; -+ -+ if (cl->preferredEncoding == rfbEncodingCoRRE) { -+ nUpdateRegionRects = 0; -+ -+ for (i = 0; i < REGION_NUM_RECTS(&updateRegion); i++) { -+ int x = REGION_RECTS(&updateRegion)[i].x1; -+ int y = REGION_RECTS(&updateRegion)[i].y1; -+ int w = REGION_RECTS(&updateRegion)[i].x2 - x; -+ int h = REGION_RECTS(&updateRegion)[i].y2 - y; -+ nUpdateRegionRects += (((w-1) / cl->correMaxWidth + 1) -+ * ((h-1) / cl->correMaxHeight + 1)); -+ } -+ } else if (cl->preferredEncoding == rfbEncodingZlib) { -+ nUpdateRegionRects = 0; -+ -+ for (i = 0; i < REGION_NUM_RECTS(&updateRegion); i++) { -+ int x = REGION_RECTS(&updateRegion)[i].x1; -+ int y = REGION_RECTS(&updateRegion)[i].y1; -+ int w = REGION_RECTS(&updateRegion)[i].x2 - x; -+ int h = REGION_RECTS(&updateRegion)[i].y2 - y; -+ nUpdateRegionRects += (((h-1) / (ZLIB_MAX_SIZE( w ) / w)) + 1); -+ } -+ } else if (cl->preferredEncoding == rfbEncodingTight) { -+ nUpdateRegionRects = 0; -+ -+ for (i = 0; i < REGION_NUM_RECTS(&updateRegion); i++) { -+ int x = REGION_RECTS(&updateRegion)[i].x1; -+ int y = REGION_RECTS(&updateRegion)[i].y1; -+ int w = REGION_RECTS(&updateRegion)[i].x2 - x; -+ int h = REGION_RECTS(&updateRegion)[i].y2 - y; -+ int n = rfbNumCodedRectsTight(cl, x, y, w, h); -+ if (n == 0) { -+ nUpdateRegionRects = 0xFFFF; -+ break; -+ } -+ nUpdateRegionRects += n; -+ } -+ } else { -+ nUpdateRegionRects = REGION_NUM_RECTS(&updateRegion); -+ } -+ -+ fu->type = rfbFramebufferUpdate; -+ if (nUpdateRegionRects != 0xFFFF) { -+ fu->nRects = Swap16IfLE(REGION_NUM_RECTS(&updateCopyRegion) + -+ nUpdateRegionRects + -+ !!sendCursorShape + !!sendCursorPos); -+ } else { -+ fu->nRects = 0xFFFF; -+ } -+ pVNC->ublen = sz_rfbFramebufferUpdateMsg; -+ -+ if (sendCursorShape) { -+ cl->cursorWasChanged = FALSE; -+ if (!rfbSendCursorShape(cl, pScreen)) -+ return FALSE; -+ } -+ -+ if (sendCursorPos) { -+ cl->cursorWasMoved = FALSE; -+ if (!rfbSendCursorPos(cl, pScreen)) -+ return FALSE; -+ } -+ -+ if (REGION_NOTEMPTY(pScreen,&updateCopyRegion)) { -+ if (!rfbSendCopyRegion(cl,&updateCopyRegion,dx,dy)) { -+ REGION_UNINIT(pScreen,&updateRegion); -+ REGION_UNINIT(pScreen,&updateCopyRegion); -+ return FALSE; -+ } -+ } -+ -+ REGION_UNINIT(pScreen,&updateCopyRegion); -+ -+ for (i = 0; i < REGION_NUM_RECTS(&updateRegion); i++) { -+ int x = REGION_RECTS(&updateRegion)[i].x1; -+ int y = REGION_RECTS(&updateRegion)[i].y1; -+ int w = REGION_RECTS(&updateRegion)[i].x2 - x; -+ int h = REGION_RECTS(&updateRegion)[i].y2 - y; -+ -+ cl->rfbRawBytesEquivalent += (sz_rfbFramebufferUpdateRectHeader -+ + w * (cl->format.bitsPerPixel / 8) * h); -+ -+ switch (cl->preferredEncoding) { -+ case rfbEncodingRaw: -+ if (!rfbSendRectEncodingRaw(cl, x, y, w, h)) { -+ REGION_UNINIT(pScreen,&updateRegion); -+ return FALSE; -+ } -+ break; -+ case rfbEncodingRRE: -+ if (!rfbSendRectEncodingRRE(cl, x, y, w, h)) { -+ REGION_UNINIT(pScreen,&updateRegion); -+ return FALSE; -+ } -+ break; -+ case rfbEncodingCoRRE: -+ if (!rfbSendRectEncodingCoRRE(cl, x, y, w, h)) { -+ REGION_UNINIT(pScreen,&updateRegion); -+ return FALSE; -+ } -+ break; -+ case rfbEncodingHextile: -+ if (!rfbSendRectEncodingHextile(cl, x, y, w, h)) { -+ REGION_UNINIT(pScreen,&updateRegion); -+ return FALSE; -+ } -+ break; -+ case rfbEncodingZlib: -+ if (!rfbSendRectEncodingZlib(cl, x, y, w, h)) { -+ REGION_UNINIT(pScreen,&updateRegion); -+ return FALSE; -+ } -+ break; -+ case rfbEncodingTight: -+ if (!rfbSendRectEncodingTight(cl, x, y, w, h)) { -+ REGION_UNINIT(pScreen,&updateRegion); -+ return FALSE; -+ } -+ break; -+ } -+ } -+ -+ REGION_UNINIT(pScreen,&updateRegion); -+ -+ if (nUpdateRegionRects == 0xFFFF && !rfbSendLastRectMarker(cl)) -+ return FALSE; -+ -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ -+ return TRUE; -+} -+ -+ -+ -+/* -+ * Send the copy region as a string of CopyRect encoded rectangles. -+ * The only slightly tricky thing is that we should send the messages in -+ * the correct order so that an earlier CopyRect will not corrupt the source -+ * of a later one. -+ */ -+ -+static Bool -+rfbSendCopyRegion(cl, reg, dx, dy) -+ rfbClientPtr cl; -+ RegionPtr reg; -+ int dx, dy; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ int nrects, nrectsInBand, x_inc, y_inc, thisRect, firstInNextBand; -+ int x, y, w, h; -+ rfbFramebufferUpdateRectHeader rect; -+ rfbCopyRect cr; -+ -+ nrects = REGION_NUM_RECTS(reg); -+ -+ if (dx <= 0) { -+ x_inc = 1; -+ } else { -+ x_inc = -1; -+ } -+ -+ if (dy <= 0) { -+ thisRect = 0; -+ y_inc = 1; -+ } else { -+ thisRect = nrects - 1; -+ y_inc = -1; -+ } -+ -+ while (nrects > 0) { -+ -+ firstInNextBand = thisRect; -+ nrectsInBand = 0; -+ -+ while ((nrects > 0) && -+ (REGION_RECTS(reg)[firstInNextBand].y1 -+ == REGION_RECTS(reg)[thisRect].y1)) -+ { -+ firstInNextBand += y_inc; -+ nrects--; -+ nrectsInBand++; -+ } -+ -+ if (x_inc != y_inc) { -+ thisRect = firstInNextBand - y_inc; -+ } -+ -+ while (nrectsInBand > 0) { -+ if ((pVNC->ublen + sz_rfbFramebufferUpdateRectHeader -+ + sz_rfbCopyRect) > UPDATE_BUF_SIZE) -+ { -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ } -+ -+ x = REGION_RECTS(reg)[thisRect].x1; -+ y = REGION_RECTS(reg)[thisRect].y1; -+ w = REGION_RECTS(reg)[thisRect].x2 - x; -+ h = REGION_RECTS(reg)[thisRect].y2 - y; -+ -+ rect.r.x = Swap16IfLE(x); -+ rect.r.y = Swap16IfLE(y); -+ rect.r.w = Swap16IfLE(w); -+ rect.r.h = Swap16IfLE(h); -+ rect.encoding = Swap32IfLE(rfbEncodingCopyRect); -+ -+ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&rect, -+ sz_rfbFramebufferUpdateRectHeader); -+ pVNC->ublen += sz_rfbFramebufferUpdateRectHeader; -+ -+ cr.srcX = Swap16IfLE(x - dx); -+ cr.srcY = Swap16IfLE(y - dy); -+ -+ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&cr, sz_rfbCopyRect); -+ pVNC->ublen += sz_rfbCopyRect; -+ -+ cl->rfbRectanglesSent[rfbEncodingCopyRect]++; -+ cl->rfbBytesSent[rfbEncodingCopyRect] -+ += sz_rfbFramebufferUpdateRectHeader + sz_rfbCopyRect; -+ -+ thisRect += x_inc; -+ nrectsInBand--; -+ } -+ -+ thisRect = firstInNextBand; -+ } -+ -+ return TRUE; -+} -+ -+ -+/* -+ * Send a given rectangle in raw encoding (rfbEncodingRaw). -+ */ -+ -+Bool -+rfbSendRectEncodingRaw(cl, x, y, w, h) -+ rfbClientPtr cl; -+ int x, y, w, h; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ rfbFramebufferUpdateRectHeader rect; -+ int nlines; -+ int bytesPerLine = w * (cl->format.bitsPerPixel / 8); -+ unsigned char *fbptr = NULL; -+ int newy = 0; -+ -+ if (pVNC->useGetImage) { -+ newy = y; -+ } else { -+ fbptr = (pVNC->pfbMemory + (pVNC->paddedWidthInBytes * y) -+ + (x * (pVNC->bitsPerPixel / 8))); -+ } -+ -+ /* Flush the buffer to guarantee correct alignment for translateFn(). */ -+ if (pVNC->ublen > 0) { -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ } -+ -+ rect.r.x = Swap16IfLE(x); -+ rect.r.y = Swap16IfLE(y); -+ rect.r.w = Swap16IfLE(w); -+ rect.r.h = Swap16IfLE(h); -+ rect.encoding = Swap32IfLE(rfbEncodingRaw); -+ -+ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&rect,sz_rfbFramebufferUpdateRectHeader); -+ pVNC->ublen += sz_rfbFramebufferUpdateRectHeader; -+ -+ cl->rfbRectanglesSent[rfbEncodingRaw]++; -+ cl->rfbBytesSent[rfbEncodingRaw] -+ += sz_rfbFramebufferUpdateRectHeader + bytesPerLine * h; -+ -+ nlines = (UPDATE_BUF_SIZE - pVNC->ublen) / bytesPerLine; -+ -+ while (TRUE) { -+ if (nlines > h) -+ nlines = h; -+ -+ if (pVNC->useGetImage) { -+ (*cl->pScreen->GetImage)((DrawablePtr)WindowTable[cl->pScreen->myNum], x, newy, w, nlines, ZPixmap, ~0, &pVNC->updateBuf[pVNC->ublen]); -+ newy += nlines; -+ } else { -+ (*cl->translateFn)(cl->pScreen, cl->translateLookupTable, &pVNC->rfbServerFormat, -+ &cl->format, fbptr, &pVNC->updateBuf[pVNC->ublen], -+ pVNC->paddedWidthInBytes, w, nlines, x, y); -+ } -+ -+ pVNC->ublen += nlines * bytesPerLine; -+ h -= nlines; -+ -+ if (h == 0) /* rect fitted in buffer, do next one */ -+ return TRUE; -+ -+ /* buffer full - flush partial rect and do another nlines */ -+ -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ -+ if (!pVNC->useGetImage) -+ fbptr += (pVNC->paddedWidthInBytes * nlines); -+ -+ nlines = (UPDATE_BUF_SIZE - pVNC->ublen) / bytesPerLine; -+ if (nlines == 0) { -+ rfbLog("rfbSendRectEncodingRaw: send buffer too small for %d " -+ "bytes per line\n", bytesPerLine); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return FALSE; -+ } -+ } -+} -+ -+ -+/* -+ * Send an empty rectangle with encoding field set to value of -+ * rfbEncodingLastRect to notify client that this is the last -+ * rectangle in framebuffer update ("LastRect" extension of RFB -+ * protocol). -+ */ -+ -+static Bool -+rfbSendLastRectMarker(cl) -+ rfbClientPtr cl; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ rfbFramebufferUpdateRectHeader rect; -+ -+ if (pVNC->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) { -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ } -+ -+ rect.encoding = Swap32IfLE(rfbEncodingLastRect); -+ rect.r.x = 0; -+ rect.r.y = 0; -+ rect.r.w = 0; -+ rect.r.h = 0; -+ -+ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&rect,sz_rfbFramebufferUpdateRectHeader); -+ pVNC->ublen += sz_rfbFramebufferUpdateRectHeader; -+ -+ cl->rfbLastRectMarkersSent++; -+ cl->rfbLastRectBytesSent += sz_rfbFramebufferUpdateRectHeader; -+ -+ return TRUE; -+} -+ -+ -+/* -+ * Send the contents of pVNC->updateBuf. Returns 1 if successful, -1 if -+ * not (errno should be set). -+ */ -+ -+Bool -+rfbSendUpdateBuf(cl) -+ rfbClientPtr cl; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ -+ /* -+ int i; -+ for (i = 0; i < pVNC->ublen; i++) { -+ rfbLog("%02x ",((unsigned char *)pVNC->updateBuf)[i]); -+ } -+ rfbLog("\n"); -+ */ -+ -+ if (pVNC->ublen > 0 && WriteExact(cl->sock, pVNC->updateBuf, pVNC->ublen) < 0) { -+ rfbLogPerror("rfbSendUpdateBuf: write"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return FALSE; -+ } -+ -+ pVNC->ublen = 0; -+ return TRUE; -+} -+ -+ -+ -+/* -+ * rfbSendSetColourMapEntries sends a SetColourMapEntries message to the -+ * client, using values from the currently installed colormap. -+ */ -+ -+Bool -+rfbSendSetColourMapEntries(cl, firstColour, nColours) -+ rfbClientPtr cl; -+ int firstColour; -+ int nColours; -+{ -+#if !XFREE86VNC -+ VNCSCREENPTR(cl->pScreen); -+#endif -+ char buf[sz_rfbSetColourMapEntriesMsg + 256 * 3 * 2]; -+ rfbSetColourMapEntriesMsg *scme = (rfbSetColourMapEntriesMsg *)buf; -+ CARD16 *rgb = (CARD16 *)(&buf[sz_rfbSetColourMapEntriesMsg]); -+ EntryPtr pent; -+ EntryPtr redEntry, greenEntry, blueEntry; -+ unsigned short redPart, greenPart, bluePart; -+ int i, len; -+ -+ scme->type = rfbSetColourMapEntries; -+ scme->nColours = Swap16IfLE(nColours); -+ -+ len = sz_rfbSetColourMapEntriesMsg; -+ -+ /* PseudoColor */ -+#if XFREE86VNC -+ if (miInstalledMaps[cl->pScreen->myNum]->class == PseudoColor) { -+#else -+ if (pVNC->rfbInstalledColormap->class == PseudoColor) { -+#endif -+ scme->firstColour = Swap16IfLE(firstColour); -+#if XFREE86VNC -+ pent = (EntryPtr)&miInstalledMaps[cl->pScreen->myNum]->red[firstColour]; -+#else -+ pent = (EntryPtr)&pVNC->rfbInstalledColormap->red[firstColour]; -+#endif -+ for (i = 0; i < nColours; i++) { -+ if (pent->fShared) { -+ rgb[i*3] = Swap16IfLE(pent->co.shco.red->color); -+ rgb[i*3+1] = Swap16IfLE(pent->co.shco.green->color); -+ rgb[i*3+2] = Swap16IfLE(pent->co.shco.blue->color); -+ } else { -+ rgb[i*3] = Swap16IfLE(pent->co.local.red); -+ rgb[i*3+1] = Swap16IfLE(pent->co.local.green); -+ rgb[i*3+2] = Swap16IfLE(pent->co.local.blue); -+ } -+ pent++; -+ } -+ } -+ -+ else { -+ -+ /* Break the DirectColor pixel into its r/g/b components */ -+#if XFREE86VNC -+ redPart = (firstColour & miInstalledMaps[cl->pScreen->myNum]->pVisual->redMask) -+ >> miInstalledMaps[cl->pScreen->myNum]->pVisual->offsetRed; -+ greenPart = (firstColour & miInstalledMaps[cl->pScreen->myNum]->pVisual->greenMask) -+ >> miInstalledMaps[cl->pScreen->myNum]->pVisual->offsetGreen; -+ bluePart = (firstColour & miInstalledMaps[cl->pScreen->myNum]->pVisual->blueMask) -+ >> miInstalledMaps[cl->pScreen->myNum]->pVisual->offsetBlue; -+#else -+ redPart = (firstColour & pVNC->rfbInstalledColormap->pVisual->redMask) -+ >> pVNC->rfbInstalledColormap->pVisual->offsetRed; -+ greenPart = (firstColour & pVNC->rfbInstalledColormap->pVisual->greenMask) -+ >> pVNC->rfbInstalledColormap->pVisual->offsetGreen; -+ bluePart = (firstColour & pVNC->rfbInstalledColormap->pVisual->blueMask) -+ >> pVNC->rfbInstalledColormap->pVisual->offsetBlue; -+#endif -+ -+ /* -+ * The firstColour field is only 16 bits. To support 24-bit pixels we -+ * sneak the red component in the 8-bit padding field which we renamed -+ * to redIndex. Green and blue are in firstColour (MSB, LSB respectively). -+ */ -+ scme->redIndex = Swap16IfLE(redPart); -+ scme->firstColour = Swap16IfLE((greenPart << 8) | bluePart); -+ -+#if XFREE86VNC -+ redEntry = (EntryPtr)&miInstalledMaps[cl->pScreen->myNum]->red[redPart]; -+ greenEntry = (EntryPtr)&miInstalledMaps[cl->pScreen->myNum]->green[greenPart]; -+ blueEntry = (EntryPtr)&miInstalledMaps[cl->pScreen->myNum]->blue[bluePart]; -+#else -+ redEntry = (EntryPtr)&pVNC->rfbInstalledColormap->red[redPart]; -+ greenEntry = (EntryPtr)&pVNC->rfbInstalledColormap->green[greenPart]; -+ blueEntry = (EntryPtr)&pVNC->rfbInstalledColormap->blue[bluePart]; -+#endif -+ for (i = 0; i < nColours; i++) { -+ if (redEntry->fShared) -+ rgb[i*3] = Swap16IfLE(redEntry->co.shco.red->color); -+ else -+ rgb[i*3] = Swap16IfLE(redEntry->co.local.red); -+ -+ if (greenEntry->fShared) -+ rgb[i*3+1] = Swap16IfLE(greenEntry->co.shco.green->color); -+ else -+ rgb[i*3+1] = Swap16IfLE(greenEntry->co.local.green); -+ -+ if (blueEntry->fShared) -+ rgb[i*3+2] = Swap16IfLE(blueEntry->co.shco.blue->color); -+ else -+ rgb[i*3+2] = Swap16IfLE(blueEntry->co.local.blue); -+ -+ redEntry++; -+ greenEntry++; -+ blueEntry++; -+ } -+ } -+ -+ len += nColours * 3 * 2; -+ -+ if (WriteExact(cl->sock, buf, len) < 0) { -+ rfbLogPerror("rfbSendSetColourMapEntries: write"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return FALSE; -+ } -+ return TRUE; -+} -+ -+ -+/* -+ * rfbSendBell sends a Bell message to all the clients. -+ */ -+ -+void -+rfbSendBell() -+{ -+ rfbClientPtr cl, nextCl; -+ rfbBellMsg b; -+ -+ for (cl = rfbClientHead; cl; cl = nextCl) { -+ nextCl = cl->next; -+ b.type = rfbBell; -+ if (WriteExact(cl->sock, (char *)&b, sz_rfbBellMsg) < 0) { -+ rfbLogPerror("rfbSendBell: write"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ } -+ } -+} -+ -+#ifdef CHROMIUM -+#ifdef sun -+extern int inet_aton(const char *cp, struct in_addr *inp); -+#endif -+ -+void -+rfbSendChromiumStart(unsigned int ipaddress, unsigned int crServerPort, -+ unsigned int mothershipPort) -+{ -+ rfbClientPtr cl, nextCl; -+ rfbChromiumStartMsg scd; -+ struct in_addr ip; -+ unsigned int vncipaddress; -+ -+ for (cl = rfbClientHead; cl; cl = nextCl) { -+ nextCl = cl->next; -+ if (!cl->enableChromiumEncoding) -+ continue; -+ inet_aton(cl->host, &ip); -+ memcpy(&vncipaddress, &ip, sizeof(unsigned int)); -+ if (ipaddress == vncipaddress /***&& !cl->chromium_port***/) { -+ cl->chromium_port = crServerPort; -+ cl->chromium_msport = mothershipPort; -+ scd.type = rfbChromiumStart; -+ scd.crServerPort = crServerPort; -+ scd.mothershipPort = mothershipPort; -+ if (WriteExact(cl->sock, (char *)&scd, -+ sz_rfbChromiumStartMsg) < 0) { -+ rfbLogPerror("rfbSendChromiumStart: write"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ } -+ /* We only start one client at at time, so break now! */ -+ break; -+ } -+ } -+} -+ -+ -+/** -+ * Begin monitoring the given X windowid. -+ * When we detect size/position/visibiliy changes we'll send a -+ * rfbChromiumMoveResizeWindow, rfbChromiumClipList, or rfbChromiumWindowShow -+ * message to the VNC viewer, passing the corresponding Chromium window id. -+ */ -+void -+rfbChromiumMonitorWindowID(unsigned int cr_windowid, unsigned long xwindowid) -+{ -+ CRWindowTable *newRec, *wt, *nextWt = NULL; -+ -+ if (xwindowid && !cr_windowid) { -+ /* stop monitoring the X window, remove from list */ -+ CRWindowTable *prev = NULL; -+ for (wt = windowTable; wt; wt = nextWt) { -+ nextWt = wt->next; -+ if (wt->XwinId == xwindowid) { -+ /* remove */ -+ if (prev) -+ prev->next = wt->next; -+ else -+ windowTable = wt->next; -+ xfree(wt); -+ } -+ else { -+ prev = wt; -+ } -+ } -+ return; -+ } -+ -+ /* See if we're already managing this window */ -+ for (wt = windowTable; wt; wt = nextWt) { -+ nextWt = wt->next; -+ /* and if so, update it's window ID */ -+ if (wt->CRwinId == cr_windowid) { -+ wt->XwinId = xwindowid; -+ return; -+ } -+ } -+ -+ /* o.k, new window so create new slot information */ -+ newRec = (CRWindowTable *)xalloc(sizeof(CRWindowTable)); -+ if (!newRec) { -+ rfbLog("Out of memory allocating CRWindowTable.\n"); -+ return; -+ } -+ -+ newRec->next = NULL; -+ newRec->CRwinId = cr_windowid; -+ newRec->XwinId = xwindowid; -+ newRec->clipRects = NULL; -+ newRec->numRects = 0; -+ -+ if (!windowTable) { -+ windowTable = newRec; -+ } -+ else { -+ for (wt = windowTable; wt; wt = nextWt) { -+ nextWt = wt->next; -+ if (!wt->next) /* found the next slot */ -+ wt->next = newRec; -+ } -+ } -+} -+ -+ -+void -+rfbSendChromiumMoveResizeWindow(unsigned int winid, int x, int y, unsigned int w, unsigned int h) -+{ -+ rfbClientPtr cl, nextCl; -+ rfbChromiumMoveResizeWindowMsg scm; -+ -+ for (cl = rfbClientHead; cl; cl = nextCl) { -+ nextCl = cl->next; -+ if (!cl->enableChromiumEncoding) -+ continue; -+ if (cl->chromium_port) { -+ scm.type = rfbChromiumMoveResizeWindow; -+ scm.winid = winid; -+ scm.x = x; -+ scm.y = y; -+ scm.w = w; -+ scm.h = h; -+ if (WriteExact(cl->sock, (char *)&scm, -+ sz_rfbChromiumMoveResizeWindowMsg) < 0) { -+ rfbLogPerror("rfbSendChromiumMoveResizeWindow: write\n"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ continue; -+ } -+ } -+ } -+} -+ -+void -+rfbSendChromiumClipList(unsigned int winid, BoxPtr pClipRects, int numClipRects) -+{ -+ rfbClientPtr cl, nextCl; -+ rfbChromiumClipListMsg sccl; -+ int len = sizeof(BoxRec) * numClipRects; -+ -+ for (cl = rfbClientHead; cl; cl = nextCl) { -+ nextCl = cl->next; -+ if (!cl->enableChromiumEncoding) -+ continue; -+ if (cl->chromium_port) { -+ sccl.type = rfbChromiumClipList; -+ sccl.winid = winid; -+ sccl.length = Swap32IfLE(len); -+ if (WriteExact(cl->sock, (char *)&sccl, -+ sz_rfbChromiumClipListMsg) < 0) { -+ rfbLogPerror("rfbSendChromiumClipList: write\n"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ continue; -+ } -+ if (WriteExact(cl->sock, (char *)pClipRects, len) < 0) { -+ rfbLogPerror("rfbSendChromiumClipList: write\n"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ continue; -+ } -+ } -+ } -+} -+ -+void -+rfbSendChromiumWindowShow(unsigned int winid, unsigned int show) -+{ -+ rfbClientPtr cl, nextCl; -+ rfbChromiumWindowShowMsg scws; -+ -+ for (cl = rfbClientHead; cl; cl = nextCl) { -+ nextCl = cl->next; -+ if (!cl->enableChromiumEncoding) -+ continue; -+ if (cl->chromium_port) { -+ scws.type = rfbChromiumWindowShow; -+ scws.winid = winid; -+ scws.show = show; -+ if (WriteExact(cl->sock, (char *)&scws, -+ sz_rfbChromiumWindowShowMsg) < 0) { -+ rfbLogPerror("rfbSendChromiumWindowShow: write\n"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ continue; -+ } -+ } -+ } -+} -+#endif /* CHROMIUM */ -+ -+/* -+ * rfbSendServerCutText sends a ServerCutText message to all the clients. -+ */ -+ -+void -+rfbSendServerCutText(char *str, int len) -+{ -+ rfbClientPtr cl, nextCl = NULL; -+ rfbServerCutTextMsg sct; -+ -+ for (cl = rfbClientHead; cl; cl = nextCl) { -+ if (cl->state != RFB_NORMAL) continue; -+ nextCl = cl->next; -+ sct.type = rfbServerCutText; -+ sct.length = Swap32IfLE(len); -+ if (WriteExact(cl->sock, (char *)&sct, -+ sz_rfbServerCutTextMsg) < 0) { -+ rfbLogPerror("rfbSendServerCutText: write\n"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ continue; -+ } -+ if (WriteExact(cl->sock, str, len) < 0) { -+ rfbLogPerror("rfbSendServerCutText: write\n"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ } -+ } -+} -+ -+ -+ -+ -+/***************************************************************************** -+ * -+ * UDP can be used for keyboard and pointer events when the underlying -+ * network is highly reliable. This is really here to support ORL's -+ * videotile, whose TCP implementation doesn't like sending lots of small -+ * packets (such as 100s of pen readings per second!). -+ */ -+ -+void -+rfbNewUDPConnection(sock) -+ int sock; -+{ -+ if (write(sock, &ptrAcceleration, 1) < 0) { -+ rfbLogPerror("rfbNewUDPConnection: write"); -+ } -+} -+ -+/* -+ * Because UDP is a message based service, we can't read the first byte and -+ * then the rest of the packet separately like we do with TCP. We will always -+ * get a whole packet delivered in one go, so we ask read() for the maximum -+ * number of bytes we can possibly get. -+ */ -+ -+void -+rfbProcessUDPInput(ScreenPtr pScreen, int sock) -+{ -+ VNCSCREENPTR(pScreen); -+ int n; -+ rfbClientToServerMsg msg; -+ -+ if ((n = read(sock, (char *)&msg, sizeof(msg))) <= 0) { -+ if (n < 0) { -+ rfbLogPerror("rfbProcessUDPInput: read"); -+ } -+ rfbDisconnectUDPSock(pScreen); -+ return; -+ } -+ -+ switch (msg.type) { -+ -+ case rfbKeyEvent: -+ if (n != sz_rfbKeyEventMsg) { -+ rfbLog("rfbProcessUDPInput: key event incorrect length\n"); -+ rfbDisconnectUDPSock(pScreen); -+ return; -+ } -+ if (!pVNC->rfbViewOnly) { -+ KbdAddEvent(msg.ke.down, (KeySym)Swap32IfLE(msg.ke.key), 0); -+ } -+ break; -+ -+ case rfbPointerEvent: -+ if (n != sz_rfbPointerEventMsg) { -+ rfbLog("rfbProcessUDPInput: ptr event incorrect length\n"); -+ rfbDisconnectUDPSock(pScreen); -+ return; -+ } -+ if (!pVNC->rfbViewOnly) { -+ PtrAddEvent(msg.pe.buttonMask, -+ Swap16IfLE(msg.pe.x), Swap16IfLE(msg.pe.y), 0); -+ } -+ break; -+ -+ default: -+ rfbLog("rfbProcessUDPInput: unknown message type %d\n", -+ msg.type); -+ rfbDisconnectUDPSock(pScreen); -+ } -+} -diff --git a/hw/vnc/rre.c b/hw/vnc/rre.c -new file mode 100644 -index 0000000..04c0b4e ---- /dev/null -+++ b/hw/vnc/rre.c -@@ -0,0 +1,323 @@ -+/* -+ * rre.c -+ * -+ * Routines to implement Rise-and-Run-length Encoding (RRE). This -+ * code is based on krw's original javatel rfbserver. -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ */ -+ -+/* -+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. -+ * -+ * This is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This software is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this software; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -+ * USA. -+ */ -+ -+#include -+#include "rfb.h" -+ -+/* -+ * rreBeforeBuf contains pixel data in the client's format. -+ * rreAfterBuf contains the RRE encoded version. If the RRE encoded version is -+ * larger than the raw data or if it exceeds rreAfterBufSize then -+ * raw encoding is used instead. -+ */ -+ -+static int rreBeforeBufSize = 0; -+static char *rreBeforeBuf = NULL; -+ -+static int rreAfterBufSize = 0; -+static char *rreAfterBuf = NULL; -+static int rreAfterBufLen; -+ -+static int subrectEncode8(CARD8 *data, int w, int h); -+static int subrectEncode16(CARD16 *data, int w, int h); -+static int subrectEncode32(CARD32 *data, int w, int h); -+static CARD32 getBgColour(char *data, int size, int bpp); -+ -+ -+/* -+ * rfbSendRectEncodingRRE - send a given rectangle using RRE encoding. -+ */ -+ -+Bool -+rfbSendRectEncodingRRE(cl, x, y, w, h) -+ rfbClientPtr cl; -+ int x, y, w, h; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ rfbFramebufferUpdateRectHeader rect; -+ rfbRREHeader hdr; -+ int nSubrects; -+ int i; -+ unsigned char *fbptr = (pVNC->pfbMemory + (pVNC->paddedWidthInBytes * y) -+ + (x * (pVNC->bitsPerPixel / 8))); -+ -+ int maxRawSize = (pVNC->width * pVNC->height -+ * (cl->format.bitsPerPixel / 8)); -+ -+ if (rreBeforeBufSize < maxRawSize) { -+ rreBeforeBufSize = maxRawSize; -+ if (rreBeforeBuf == NULL) -+ rreBeforeBuf = (char *)xalloc(rreBeforeBufSize); -+ else -+ rreBeforeBuf = (char *)xrealloc(rreBeforeBuf, rreBeforeBufSize); -+ } -+ -+ if (rreAfterBufSize < maxRawSize) { -+ rreAfterBufSize = maxRawSize; -+ if (rreAfterBuf == NULL) -+ rreAfterBuf = (char *)xalloc(rreAfterBufSize); -+ else -+ rreAfterBuf = (char *)xrealloc(rreAfterBuf, rreAfterBufSize); -+ } -+ -+ (*cl->translateFn)(cl->pScreen, cl->translateLookupTable, -+ &pVNC->rfbServerFormat, -+ &cl->format, fbptr, rreBeforeBuf, -+ pVNC->paddedWidthInBytes, w, h, x, y); -+ -+ switch (cl->format.bitsPerPixel) { -+ case 8: -+ nSubrects = subrectEncode8((CARD8 *)rreBeforeBuf, w, h); -+ break; -+ case 16: -+ nSubrects = subrectEncode16((CARD16 *)rreBeforeBuf, w, h); -+ break; -+ case 32: -+ nSubrects = subrectEncode32((CARD32 *)rreBeforeBuf, w, h); -+ break; -+ default: -+ rfbLog("getBgColour: bpp %d?\n",cl->format.bitsPerPixel); -+ exit(1); -+ } -+ -+ if (nSubrects < 0) { -+ -+ /* RRE encoding was too large, use raw */ -+ -+ return rfbSendRectEncodingRaw(cl, x, y, w, h); -+ } -+ -+ cl->rfbRectanglesSent[rfbEncodingRRE]++; -+ cl->rfbBytesSent[rfbEncodingRRE] += (sz_rfbFramebufferUpdateRectHeader -+ + sz_rfbRREHeader + rreAfterBufLen); -+ -+ if (pVNC->ublen + sz_rfbFramebufferUpdateRectHeader + sz_rfbRREHeader -+ > UPDATE_BUF_SIZE) -+ { -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ } -+ -+ rect.r.x = Swap16IfLE(x); -+ rect.r.y = Swap16IfLE(y); -+ rect.r.w = Swap16IfLE(w); -+ rect.r.h = Swap16IfLE(h); -+ rect.encoding = Swap32IfLE(rfbEncodingRRE); -+ -+ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&rect, -+ sz_rfbFramebufferUpdateRectHeader); -+ pVNC->ublen += sz_rfbFramebufferUpdateRectHeader; -+ -+ hdr.nSubrects = Swap32IfLE(nSubrects); -+ -+ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&hdr, sz_rfbRREHeader); -+ pVNC->ublen += sz_rfbRREHeader; -+ -+ for (i = 0; i < rreAfterBufLen;) { -+ -+ int bytesToCopy = UPDATE_BUF_SIZE - pVNC->ublen; -+ -+ if (i + bytesToCopy > rreAfterBufLen) { -+ bytesToCopy = rreAfterBufLen - i; -+ } -+ -+ memcpy(&pVNC->updateBuf[pVNC->ublen], &rreAfterBuf[i], bytesToCopy); -+ -+ pVNC->ublen += bytesToCopy; -+ i += bytesToCopy; -+ -+ if (pVNC->ublen == UPDATE_BUF_SIZE) { -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ } -+ } -+ -+ return TRUE; -+} -+ -+ -+ -+/* -+ * subrectEncode() encodes the given multicoloured rectangle as a background -+ * colour overwritten by single-coloured rectangles. It returns the number -+ * of subrectangles in the encoded buffer, or -1 if subrect encoding won't -+ * fit in the buffer. It puts the encoded rectangles in rreAfterBuf. The -+ * single-colour rectangle partition is not optimal, but does find the biggest -+ * horizontal or vertical rectangle top-left anchored to each consecutive -+ * coordinate position. -+ * -+ * The coding scheme is simply [...] where each -+ * is []. -+ */ -+ -+#define DEFINE_SUBRECT_ENCODE(bpp) \ -+static int \ -+subrectEncode##bpp(data,w,h) \ -+ CARD##bpp *data; \ -+ int w; \ -+ int h; \ -+{ \ -+ CARD##bpp cl; \ -+ rfbRectangle subrect; \ -+ int x,y; \ -+ int i,j; \ -+ int hx=0,hy,vx=0,vy; \ -+ int hyflag; \ -+ CARD##bpp *seg; \ -+ CARD##bpp *line; \ -+ int hw,hh,vw,vh; \ -+ int thex,they,thew,theh; \ -+ int numsubs = 0; \ -+ int newLen; \ -+ CARD##bpp bg = (CARD##bpp)getBgColour((char*)data,w*h,bpp); \ -+ \ -+ *((CARD##bpp*)rreAfterBuf) = bg; \ -+ \ -+ rreAfterBufLen = (bpp/8); \ -+ \ -+ for (y=0; y 0) && (i >= hx)) {hy += 1;} else {hyflag = 0;} \ -+ } \ -+ vy = j-1; \ -+ \ -+ /* We now have two possible subrects: (x,y,hx,hy) and (x,y,vx,vy) \ -+ * We'll choose the bigger of the two. \ -+ */ \ -+ hw = hx-x+1; \ -+ hh = hy-y+1; \ -+ vw = vx-x+1; \ -+ vh = vy-y+1; \ -+ \ -+ thex = x; \ -+ they = y; \ -+ \ -+ if ((hw*hh) > (vw*vh)) { \ -+ thew = hw; \ -+ theh = hh; \ -+ } else { \ -+ thew = vw; \ -+ theh = vh; \ -+ } \ -+ \ -+ subrect.x = Swap16IfLE(thex); \ -+ subrect.y = Swap16IfLE(they); \ -+ subrect.w = Swap16IfLE(thew); \ -+ subrect.h = Swap16IfLE(theh); \ -+ \ -+ newLen = rreAfterBufLen + (bpp/8) + sz_rfbRectangle; \ -+ if ((newLen > (w * h * (bpp/8))) || (newLen > rreAfterBufSize)) \ -+ return -1; \ -+ \ -+ numsubs += 1; \ -+ *((CARD##bpp*)(rreAfterBuf + rreAfterBufLen)) = cl; \ -+ rreAfterBufLen += (bpp/8); \ -+ memcpy(&rreAfterBuf[rreAfterBufLen],&subrect,sz_rfbRectangle); \ -+ rreAfterBufLen += sz_rfbRectangle; \ -+ \ -+ /* \ -+ * Now mark the subrect as done. \ -+ */ \ -+ for (j=they; j < (they+theh); j++) { \ -+ for (i=thex; i < (thex+thew); i++) { \ -+ data[j*w+i] = bg; \ -+ } \ -+ } \ -+ } \ -+ } \ -+ } \ -+ \ -+ return numsubs; \ -+} -+ -+DEFINE_SUBRECT_ENCODE(8) -+DEFINE_SUBRECT_ENCODE(16) -+DEFINE_SUBRECT_ENCODE(32) -+ -+ -+/* -+ * getBgColour() gets the most prevalent colour in a byte array. -+ */ -+static CARD32 -+getBgColour(data,size,bpp) -+ char *data; -+ int size; -+ int bpp; -+{ -+ -+#define NUMCLRS 256 -+ -+ static int counts[NUMCLRS]; -+ int i,j,k; -+ -+ int maxcount = 0; -+ CARD8 maxclr = 0; -+ -+ if (bpp != 8) { -+ if (bpp == 16) { -+ return ((CARD16 *)data)[0]; -+ } else if (bpp == 32) { -+ return ((CARD32 *)data)[0]; -+ } else { -+ rfbLog("getBgColour: bpp %d?\n",bpp); -+ exit(1); -+ } -+ } -+ -+ for (i=0; i= NUMCLRS) { -+ rfbLog("getBgColour: unusual colour = %d\n", k); -+ exit(1); -+ } -+ counts[k] += 1; -+ if (counts[k] > maxcount) { -+ maxcount = counts[k]; -+ maxclr = ((CARD8 *)data)[j]; -+ } -+ } -+ -+ return maxclr; -+} -diff --git a/hw/vnc/sockets.c b/hw/vnc/sockets.c -new file mode 100644 -index 0000000..cdfccad ---- /dev/null -+++ b/hw/vnc/sockets.c -@@ -0,0 +1,654 @@ -+/* -+ * sockets.c - deal with TCP & UDP sockets. -+ * -+ * This code should be independent of any changes in the RFB protocol. It just -+ * deals with the X server scheduling stuff, calling rfbNewClientConnection and -+ * rfbProcessClientMessage to actually deal with the protocol. If a socket -+ * needs to be closed for any reason then rfbCloseSock should be called, and -+ * this in turn will call rfbClientConnectionGone. To make an active -+ * connection out, call rfbConnect - note that this does _not_ call -+ * rfbNewClientConnection. -+ * -+ * This file is divided into two types of function. Those beginning with -+ * "rfb" are specific to sockets using the RFB protocol. Those without the -+ * "rfb" prefix are more general socket routines (which are used by the http -+ * code). -+ * -+ * Thanks to Karl Hakimian for pointing out that some platforms return EAGAIN -+ * not EWOULDBLOCK. -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ */ -+ -+/* -+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. -+ * -+ * This is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This software is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this software; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -+ * USA. -+ */ -+ -+#if HAVE_DIX_CONFIG_H -+#include "dix-config.h" -+#endif -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "windowstr.h" -+ -+#ifndef USE_LIBWRAP -+#define USE_LIBWRAP 0 -+#endif -+#if USE_LIBWRAP -+#include -+#include -+int allow_severity = LOG_INFO; -+int deny_severity = LOG_WARNING; -+#endif -+ -+#include "rfb.h" -+ -+int rfbMaxClientWait = 20000; /* time (ms) after which we decide client has -+ gone away - needed to stop us hanging */ -+ -+static struct sockaddr_in udpRemoteAddr; -+ -+/* -+ * rfbInitSockets sets up the TCP and UDP sockets to listen for RFB -+ * connections. It does nothing if called again. -+ */ -+ -+Bool -+rfbInitSockets(ScreenPtr pScreen) -+{ -+ VNCSCREENPTR(pScreen); -+ -+ if (inetdSock != -1) { -+ const int one = 1; -+ -+ if (fcntl(inetdSock, F_SETFL, O_NONBLOCK) < 0) { -+ rfbLogPerror("fcntl"); -+ return FALSE; -+ } -+ -+ if (setsockopt(inetdSock, IPPROTO_TCP, TCP_NODELAY, -+ (char *)&one, sizeof(one)) < 0) { -+ rfbLogPerror("setsockopt"); -+ return FALSE; -+ } -+ -+ AddEnabledDevice(inetdSock); -+ FD_ZERO(&pVNC->allFds); -+ FD_SET(inetdSock, &pVNC->allFds); -+ pVNC->maxFd = inetdSock; -+ return TRUE; -+ } -+ -+ if (pVNC->rfbPort == 0) { -+ pVNC->rfbPort = 5900 + atoi(display) + pScreen->myNum; -+ } -+ -+ if ((pVNC->rfbListenSock = ListenOnTCPPort(pScreen, pVNC->rfbPort)) < 0) { -+ rfbLogPerror("ListenOnTCPPort"); -+ pVNC->rfbPort = 0; -+ return FALSE; -+ } -+ -+ rfbLog("Listening for VNC connections on TCP port %d\n", pVNC->rfbPort); -+ -+ AddEnabledDevice(pVNC->rfbListenSock); -+ -+ FD_ZERO(&pVNC->allFds); -+ FD_SET(pVNC->rfbListenSock, &pVNC->allFds); -+ pVNC->maxFd = pVNC->rfbListenSock; -+ -+ if (pVNC->udpPort != 0) { -+ rfbLog("rfbInitSockets: listening for input on UDP port %d\n",pVNC->udpPort); -+ -+ if ((pVNC->udpSock = ListenOnUDPPort(pScreen, pVNC->udpPort)) < 0) { -+ rfbLogPerror("ListenOnUDPPort"); -+ return FALSE; -+ } -+ AddEnabledDevice(pVNC->udpSock); -+ FD_SET(pVNC->udpSock, &pVNC->allFds); -+ pVNC->maxFd = max(pVNC->udpSock,pVNC->maxFd); -+ } -+ -+ return TRUE; -+} -+ -+ -+/* -+ * rfbCheckFds is called from ProcessInputEvents to check for input on the RFB -+ * socket(s). If there is input to process, the appropriate function in the -+ * RFB server code will be called (rfbNewClientConnection, -+ * rfbProcessClientMessage, etc). -+ */ -+ -+void -+rfbCheckFds(ScreenPtr pScreen) -+{ -+ VNCSCREENPTR(pScreen); -+#if XFREE86VNC -+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; -+#endif -+ int nfds; -+ fd_set fds; -+ struct timeval tv; -+ struct sockaddr_in addr; -+ SOCKLEN_T addrlen = sizeof(addr); -+ char buf[6]; -+ const int one = 1; -+ int sock; -+ static Bool inetdInitDone = FALSE; -+ -+ if (!inetdInitDone && inetdSock != -1) { -+ rfbNewClientConnection(pScreen, inetdSock); -+ inetdInitDone = TRUE; -+ } -+ -+ memcpy((char *)&fds, (char *)&pVNC->allFds, sizeof(fd_set)); -+ tv.tv_sec = 0; -+ tv.tv_usec = 0; -+ nfds = select(pVNC->maxFd + 1, &fds, NULL, NULL, &tv); -+ if (nfds == 0) { -+ return; -+ } -+ if (nfds < 0) { -+ if (errno != EINTR) -+ rfbLogPerror("rfbCheckFds: select"); -+ return; -+ } -+ -+ if (pVNC->rfbListenSock != -1 && FD_ISSET(pVNC->rfbListenSock, &fds)) { -+ -+ if ((sock = accept(pVNC->rfbListenSock, -+ (struct sockaddr *)&addr, &addrlen)) < 0) { -+ rfbLogPerror("rfbCheckFds: accept"); -+ return; -+ } -+ -+ if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) { -+ rfbLogPerror("rfbCheckFds: fcntl"); -+ close(sock); -+ return; -+ } -+ -+ if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, -+ (char *)&one, sizeof(one)) < 0) { -+ rfbLogPerror("rfbCheckFds: setsockopt"); -+ close(sock); -+ return; -+ } -+ -+ rfbLog("\n"); -+ -+#if USE_LIBWRAP -+ if (!hosts_ctl("Xvnc", STRING_UNKNOWN, inet_ntoa(addr.sin_addr), -+ STRING_UNKNOWN)) { -+ rfbLog("Rejected connection from client %s\n", -+ inet_ntoa(addr.sin_addr)); -+ close(sock); -+ return; -+ } -+#endif -+ -+ rfbLog("Got VNC connection from client %s\n", inet_ntoa(addr.sin_addr)); -+ -+ AddEnabledDevice(sock); -+ FD_SET(sock, &pVNC->allFds); -+ pVNC->maxFd = max(sock,pVNC->maxFd); -+ -+ rfbNewClientConnection(pScreen, sock); -+ -+ FD_CLR(pVNC->rfbListenSock, &fds); -+ if (--nfds == 0) -+ return; -+ } -+ -+ if ((pVNC->udpSock != -1) && FD_ISSET(pVNC->udpSock, &fds)) { -+ -+ if (recvfrom(pVNC->udpSock, buf, 1, MSG_PEEK, -+ (struct sockaddr *)&addr, &addrlen) < 0) { -+ -+ rfbLogPerror("rfbCheckFds: UDP: recvfrom"); -+ rfbDisconnectUDPSock(pScreen); -+ -+ } else { -+ -+ if (!pVNC->udpSockConnected || -+ (memcmp(&addr, &udpRemoteAddr, addrlen) != 0)) -+ { -+ /* new remote end */ -+ rfbLog("rfbCheckFds: UDP: got connection\n"); -+ -+ memcpy(&udpRemoteAddr, &addr, addrlen); -+ pVNC->udpSockConnected = TRUE; -+ -+ if (connect(pVNC->udpSock, -+ (struct sockaddr *)&addr, addrlen) < 0) { -+ rfbLogPerror("rfbCheckFds: UDP: connect"); -+ rfbDisconnectUDPSock(pScreen); -+ return; -+ } -+ -+ rfbNewUDPConnection(pVNC->udpSock); -+ } -+ -+ rfbProcessUDPInput(pScreen, pVNC->udpSock); -+ } -+ -+ FD_CLR(pVNC->udpSock, &fds); -+ if (--nfds == 0) -+ return; -+ } -+ -+ for (sock = 0; sock <= pVNC->maxFd; sock++) { -+ if (FD_ISSET(sock, &fds) && FD_ISSET(sock, &pVNC->allFds)) { -+#if XFREE86VNC -+ if (!pScrn->vtSema) -+ rfbCloseSock(pScreen, sock); -+ else -+#endif -+ rfbProcessClientMessage(pScreen, sock); -+ } -+ } -+} -+ -+ -+void -+rfbDisconnectUDPSock(ScreenPtr pScreen) -+{ -+ VNCSCREENPTR(pScreen); -+ pVNC->udpSockConnected = FALSE; -+} -+ -+ -+void -+rfbCloseSock(ScreenPtr pScreen, int sock) -+{ -+ VNCSCREENPTR(pScreen); -+ close(sock); -+ RemoveEnabledDevice(sock); -+ FD_CLR(sock, &pVNC->allFds); -+ rfbClientConnectionGone(sock); -+ if (sock == inetdSock) -+ GiveUp(0); -+} -+ -+#if 0 -+/* -+ * rfbWaitForClient can be called to wait for the RFB client to send us a -+ * message. When one is received it is processed by calling -+ * rfbProcessClientMessage(). -+ */ -+ -+void -+rfbWaitForClient(sock) -+ int sock; -+{ -+ int n; -+ fd_set fds; -+ struct timeval tv; -+ -+ FD_ZERO(&fds); -+ FD_SET(sock, &fds); -+ tv.tv_sec = rfbMaxClientWait / 1000; -+ tv.tv_usec = (rfbMaxClientWait % 1000) * 1000; -+ n = select(sock+1, &fds, NULL, NULL, &tv); -+ if (n < 0) { -+ rfbLogPerror("rfbWaitForClient: select"); -+ exit(1); -+ } -+ if (n == 0) { -+ rfbCloseSock(sock); -+ return; -+ } -+ -+ rfbProcessClientMessage(sock); -+} -+#endif -+ -+/* -+ * rfbConnect is called to make a connection out to a given TCP address. -+ */ -+ -+int -+rfbConnect(ScreenPtr pScreen, char *host, int port) -+{ -+ VNCSCREENPTR(pScreen); -+ int sock; -+ int one = 1; -+ -+ rfbLog("\n"); -+ rfbLog("Making connection to client on host %s port %d\n", -+ host,port); -+ -+ if ((sock = ConnectToTcpAddr(host, port)) < 0) { -+ rfbLogPerror("connection failed"); -+ return -1; -+ } -+ -+ if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) { -+ rfbLogPerror("fcntl failed"); -+ close(sock); -+ return -1; -+ } -+ -+ if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, -+ (char *)&one, sizeof(one)) < 0) { -+ rfbLogPerror("setsockopt failed"); -+ close(sock); -+ return -1; -+ } -+ -+ AddEnabledDevice(sock); -+ FD_SET(sock, &pVNC->allFds); -+ pVNC->maxFd = max(sock,pVNC->maxFd); -+ -+ return sock; -+} -+ -+ -+ -+ -+/* -+ * ReadExact reads an exact number of bytes on a TCP socket. Returns 1 if -+ * those bytes have been read, 0 if the other end has closed, or -1 if an error -+ * occurred (errno is set to ETIMEDOUT if it timed out). -+ */ -+ -+int -+ReadExact(sock, buf, len) -+ int sock; -+ char *buf; -+ int len; -+{ -+ int n; -+ fd_set fds; -+ int tries = 5; -+ struct timeval tv; -+ -+ while (len > 0) { -+ n = read(sock, buf, len); -+ -+ if (n > 0) { -+ -+ buf += n; -+ len -= n; -+ -+ } else if (n == 0) { -+ -+ return 0; -+ -+ } else { -+ if (errno != EWOULDBLOCK && errno != EAGAIN) { -+ return n; -+ } -+ -+ do { -+ FD_ZERO(&fds); -+ FD_SET(sock, &fds); -+ tv.tv_sec = rfbMaxClientWait / 1000; -+ tv.tv_usec = (rfbMaxClientWait % 1000) * 1000; -+ n = select(sock+1, &fds, NULL, NULL, &tv); -+ tries--; -+ -+ /* We really need to retry if we get EINTR, so spin */ -+ /* If after 5 attempts we're still broke, abort.... */ -+ -+ } while ((n < 0 && errno == EINTR) && tries > 0); -+ -+ if (n < 0) { -+ rfbLogPerror("ReadExact: select"); -+ return n; -+ } -+ if (n == 0) { -+ errno = ETIMEDOUT; -+ return -1; -+ } -+ } -+ } -+ return 1; -+} -+ -+ -+ -+/* -+ * WriteExact writes an exact number of bytes on a TCP socket. Returns 1 if -+ * those bytes have been written, or -1 if an error occurred (errno is set to -+ * ETIMEDOUT if it timed out). -+ */ -+ -+int -+WriteExact(sock, buf, len) -+ int sock; -+ char *buf; -+ int len; -+{ -+ int n; -+ fd_set fds; -+ struct timeval tv; -+ int totalTimeWaited = 0; -+ -+ while (len > 0) { -+ n = write(sock, buf, len); -+ -+ if (n > 0) { -+ -+ buf += n; -+ len -= n; -+ -+ } else if (n == 0) { -+ -+ rfbLog("WriteExact: write returned 0?\n"); -+ return -1; -+ -+ } else { -+ if (errno != EWOULDBLOCK && errno != EAGAIN) { -+ return n; -+ } -+ -+#if 0 -+ /* Retry every 5 seconds until we exceed rfbMaxClientWait. We -+ need to do this because select doesn't necessarily return -+ immediately when the other end has gone away */ -+ -+ FD_ZERO(&fds); -+ FD_SET(sock, &fds); -+ tv.tv_sec = 5; -+ tv.tv_usec = 0; -+#else -+ /* We're in the WakeupHandler now, so don't wait */ -+ -+ FD_ZERO(&fds); -+ FD_SET(sock, &fds); -+ tv.tv_sec = 0; -+ tv.tv_usec = 0; -+#endif -+ n = select(sock+1, NULL, &fds, NULL, &tv); -+#if 0 -+ if (n < 0) { -+ rfbLogPerror("WriteExact: select"); -+ return n; -+ } -+ if (n == 0) { -+ totalTimeWaited += 5000; -+ if (totalTimeWaited >= rfbMaxClientWait) { -+ errno = ETIMEDOUT; -+ return -1; -+ } -+ } else { -+ totalTimeWaited = 0; -+ } -+#endif -+ } -+ } -+ return 1; -+} -+ -+ -+int -+ListenOnTCPPort(ScreenPtr pScreen, int port) -+{ -+ VNCSCREENPTR(pScreen); -+ struct sockaddr_in addr; -+ int sock; -+ int one = 1; -+ -+ memset(&addr, 0, sizeof(addr)); -+ addr.sin_family = AF_INET; -+ addr.sin_port = htons(port); -+ addr.sin_addr.s_addr = pVNC->interface.s_addr; -+ -+ if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { -+ return -1; -+ } -+ if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, -+ (char *)&one, sizeof(one)) < 0) { -+ close(sock); -+ return -1; -+ } -+ if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { -+ close(sock); -+ return -1; -+ } -+ if (listen(sock, 5) < 0) { -+ close(sock); -+ return -1; -+ } -+ -+ return sock; -+} -+ -+ -+int -+ConnectToTcpAddr(host, port) -+ char *host; -+ int port; -+{ -+ struct hostent *hp; -+ int sock, n; -+ struct sockaddr_in addr; -+ int tries = 5; -+ -+ memset(&addr, 0, sizeof(addr)); -+ addr.sin_family = AF_INET; -+ addr.sin_port = htons(port); -+ -+ if ((addr.sin_addr.s_addr = inet_addr(host)) == -1) -+ { -+ if (!(hp = gethostbyname(host))) { -+ errno = EINVAL; -+ return -1; -+ } -+ addr.sin_addr.s_addr = *(unsigned long *)hp->h_addr; -+ } -+ -+ if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { -+ return -1; -+ } -+ -+ do { -+ sock = socket(AF_INET, SOCK_STREAM, 0); -+ tries--; -+ -+ /* We really need to retry if we get EINTR, so spin */ -+ /* If after 5 attempts we're still broke, abort.... */ -+ -+ } while ((sock < 0 && errno == EINTR) && tries > 0); -+ -+ if (sock < 0) { -+ return -1; -+ } -+ -+ tries = 5; -+ -+ do { -+ n = connect(sock, (struct sockaddr *)&addr, (sizeof(addr))); -+ tries--; -+ -+ /* We really need to retry if we get EINTR, so spin */ -+ /* If after 5 attempts we're still broke, abort.... */ -+ -+ } while ((n < 0 && errno == EINTR) && tries > 0); -+ -+ if (n < 0) { -+ close(sock); -+ return -1; -+ } -+ -+ return sock; -+} -+ -+ -+int -+ListenOnUDPPort(ScreenPtr pScreen, int port) -+{ -+ VNCSCREENPTR(pScreen); -+ struct sockaddr_in addr; -+ int sock; -+ int one = 1; -+ -+ memset(&addr, 0, sizeof(addr)); -+ addr.sin_family = AF_INET; -+ addr.sin_port = htons(port); -+ addr.sin_addr.s_addr = pVNC->interface.s_addr; -+ -+ if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { -+ return -1; -+ } -+ if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, -+ (char *)&one, sizeof(one)) < 0) { -+ return -1; -+ } -+ if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { -+ return -1; -+ } -+ -+ return sock; -+} -+ -+#if 0 -+/* -+ * rdpInitSockets sets up the TCP for RDP -+ * connections. It does nothing if called again. -+ */ -+ -+Bool -+rdpInitSockets(ScreenPtr pScreen) -+{ -+ VNCSCREENPTR(pScreen); -+ -+ if ((pVNC->rdpListenSock = ListenOnTCPPort(pScreen, pVNC->rdpPort)) < 0) { -+ rfbLogPerror("ListenOnTCPPort"); -+ pVNC->rdpPort = 0; -+ return FALSE; -+ } -+ -+ rfbLog("Listening for RDP connections on TCP port %d\n", pVNC->rdpPort); -+ -+ AddEnabledDevice(pVNC->rdpListenSock); -+ -+ return TRUE; -+} -+#endif -diff --git a/hw/vnc/sprite.c b/hw/vnc/sprite.c -new file mode 100644 -index 0000000..03f21b2 ---- /dev/null -+++ b/hw/vnc/sprite.c -@@ -0,0 +1,2491 @@ -+/* -+ * sprite.c -+ * -+ * software sprite routines - based on misprite -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ */ -+ -+/* -+ * 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. -+ */ -+ -+/* $XConsortium: misprite.c,v 5.47 94/04/17 20:27:53 dpw Exp $ */ -+ -+/* -+ -+Copyright (c) 1989 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 "rfb.h" -+# include -+# include -+# include -+# include -+# include "misc.h" -+# include "pixmapstr.h" -+# include "input.h" -+# include "mi.h" -+# include "cursorstr.h" -+# include "scrnintstr.h" -+# include "colormapst.h" -+# include "windowstr.h" -+# include "gcstruct.h" -+# include "mipointer.h" -+# include "spritest.h" -+# include "dixfontstr.h" -+#ifdef RENDER -+# include "mipict.h" -+#endif -+ -+/* -+ * screen wrappers -+ */ -+ -+static int rfbSpriteScreenIndex; -+static unsigned long rfbSpriteGeneration = 0; -+ -+static Bool rfbSpriteCloseScreen(int i, ScreenPtr pScreen); -+static void rfbSpriteGetImage(DrawablePtr pDrawable, int sx, int sy, -+ int w, int h, unsigned int format, -+ unsigned long planemask, char *pdstLine); -+static void rfbSpriteGetSpans(DrawablePtr pDrawable, int wMax, -+ DDXPointPtr ppt, int *pwidth, int nspans, -+ char *pdstStart); -+static void rfbSpriteSourceValidate(DrawablePtr pDrawable, int x, int y, -+ int width, int height); -+static Bool rfbSpriteCreateGC(GCPtr pGC); -+static void rfbSpriteBlockHandler(int i, pointer blockData, -+ pointer pTimeout, -+ pointer pReadMask); -+static void rfbSpriteInstallColormap(ColormapPtr pMap); -+static void rfbSpriteStoreColors(ColormapPtr pMap, int ndef, -+ xColorItem *pdef); -+ -+static void rfbSpritePaintWindowBackground(WindowPtr pWin, -+ RegionPtr pRegion, int what); -+static void rfbSpritePaintWindowBorder(WindowPtr pWin, -+ RegionPtr pRegion, int what); -+static void rfbSpriteCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, -+ RegionPtr pRegion); -+static void rfbSpriteClearToBackground(WindowPtr pWin, int x, int y, -+ int w, int h, -+ Bool generateExposures); -+ -+#ifdef RENDER -+static void rfbSpriteComposite(CARD8 op, -+ PicturePtr pSrc, -+ PicturePtr pMask, -+ PicturePtr pDst, -+ INT16 xSrc, -+ INT16 ySrc, -+ INT16 xMask, -+ INT16 yMask, -+ INT16 xDst, -+ INT16 yDst, -+ CARD16 width, -+ CARD16 height); -+ -+static void rfbSpriteGlyphs(CARD8 op, -+ PicturePtr pSrc, -+ PicturePtr pDst, -+ PictFormatPtr maskFormat, -+ INT16 xSrc, -+ INT16 ySrc, -+ int nlist, -+ GlyphListPtr list, -+ GlyphPtr *glyphs); -+#endif -+ -+static void rfbSpriteSaveDoomedAreas(WindowPtr pWin, -+ RegionPtr pObscured, int dx, -+ int dy); -+static RegionPtr rfbSpriteRestoreAreas(WindowPtr pWin, RegionPtr pRgnExposed); -+static void rfbSpriteComputeSaved(ScreenPtr pScreen); -+ -+#define SCREEN_PROLOGUE(pScreen, field)\ -+ ((pScreen)->field = \ -+ ((rfbSpriteScreenPtr) (pScreen)->devPrivates[rfbSpriteScreenIndex].ptr)->field) -+ -+#define SCREEN_EPILOGUE(pScreen, field, wrapper)\ -+ ((pScreen)->field = wrapper) -+ -+/* -+ * GC func wrappers -+ */ -+ -+static int rfbSpriteGCIndex; -+ -+static void rfbSpriteValidateGC(GCPtr pGC, unsigned long stateChanges, -+ DrawablePtr pDrawable); -+static void rfbSpriteCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst); -+static void rfbSpriteDestroyGC(GCPtr pGC); -+static void rfbSpriteChangeGC(GCPtr pGC, unsigned long mask); -+static void rfbSpriteChangeClip(GCPtr pGC, int type, pointer pvalue, int nrects); -+static void rfbSpriteDestroyClip(GCPtr pGC); -+static void rfbSpriteCopyClip(GCPtr pgcDst, GCPtr pgcSrc); -+ -+static GCFuncs rfbSpriteGCFuncs = { -+ rfbSpriteValidateGC, -+ rfbSpriteChangeGC, -+ rfbSpriteCopyGC, -+ rfbSpriteDestroyGC, -+ rfbSpriteChangeClip, -+ rfbSpriteDestroyClip, -+ rfbSpriteCopyClip, -+}; -+ -+#define GC_FUNC_PROLOGUE(pGC) \ -+ rfbSpriteGCPtr pGCPriv = \ -+ (rfbSpriteGCPtr) (pGC)->devPrivates[rfbSpriteGCIndex].ptr;\ -+ (pGC)->funcs = pGCPriv->wrapFuncs; \ -+ if (pGCPriv->wrapOps) \ -+ (pGC)->ops = pGCPriv->wrapOps; -+ -+#define GC_FUNC_EPILOGUE(pGC) \ -+ pGCPriv->wrapFuncs = (pGC)->funcs; \ -+ (pGC)->funcs = &rfbSpriteGCFuncs; \ -+ if (pGCPriv->wrapOps) \ -+ { \ -+ pGCPriv->wrapOps = (pGC)->ops; \ -+ (pGC)->ops = &rfbSpriteGCOps; \ -+ } -+ -+/* -+ * GC op wrappers -+ */ -+ -+static void rfbSpriteFillSpans(DrawablePtr pDrawable, GCPtr pGC, -+ int nInit, DDXPointPtr pptInit, -+ int *pwidthInit, int fSorted); -+static void rfbSpriteSetSpans(DrawablePtr pDrawable, GCPtr pGC, -+ char *psrc, DDXPointPtr ppt, int *pwidth, -+ int nspans, int fSorted); -+static void rfbSpritePutImage(DrawablePtr pDrawable, GCPtr pGC, -+ int depth, int x, int y, int w, int h, -+ int leftPad, int format, char *pBits); -+static RegionPtr rfbSpriteCopyArea(DrawablePtr pSrc, DrawablePtr pDst, -+ GCPtr pGC, int srcx, int srcy, int w, -+ int h, int dstx, int dsty); -+static RegionPtr rfbSpriteCopyPlane(DrawablePtr pSrc, DrawablePtr pDst, -+ GCPtr pGC, int srcx, int srcy, int w, -+ int h, int dstx, int dsty, -+ unsigned long plane); -+static void rfbSpritePolyPoint(DrawablePtr pDrawable, GCPtr pGC, -+ int mode, int npt, xPoint *pptInit); -+static void rfbSpritePolylines(DrawablePtr pDrawable, GCPtr pGC, -+ int mode, int npt, DDXPointPtr pptInit); -+static void rfbSpritePolySegment(DrawablePtr pDrawable, GCPtr pGC, -+ int nseg, xSegment *pSegs); -+static void rfbSpritePolyRectangle(DrawablePtr pDrawable, GCPtr pGC, -+ int nrects, xRectangle *pRects); -+static void rfbSpritePolyArc(DrawablePtr pDrawable, GCPtr pGC, -+ int narcs, xArc *parcs); -+static void rfbSpriteFillPolygon(DrawablePtr pDrawable, GCPtr pGC, -+ int shape, int mode, int count, -+ DDXPointPtr pPts); -+static void rfbSpritePolyFillRect(DrawablePtr pDrawable, GCPtr pGC, -+ int nrectFill, xRectangle *prectInit); -+static void rfbSpritePolyFillArc(DrawablePtr pDrawable, GCPtr pGC, -+ int narcs, xArc *parcs); -+static int rfbSpritePolyText8(DrawablePtr pDrawable, GCPtr pGC, -+ int x, int y, int count, char *chars); -+static int rfbSpritePolyText16(DrawablePtr pDrawable, GCPtr pGC, -+ int x, int y, int count, -+ unsigned short *chars); -+static void rfbSpriteImageText8(DrawablePtr pDrawable, GCPtr pGC, -+ int x, int y, int count, char *chars); -+static void rfbSpriteImageText16(DrawablePtr pDrawable, GCPtr pGC, -+ int x, int y, int count, -+ unsigned short *chars); -+static void rfbSpriteImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, -+ int x, int y, unsigned int nglyph, -+ CharInfoPtr *ppci, -+ pointer pglyphBase); -+static void rfbSpritePolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, -+ int x, int y, unsigned int nglyph, -+ CharInfoPtr *ppci, -+ pointer pglyphBase); -+static void rfbSpritePushPixels(GCPtr pGC, PixmapPtr pBitMap, -+ DrawablePtr pDst, int w, int h, -+ int x, int y); -+#ifdef NEED_LINEHELPER -+static void rfbSpriteLineHelper(); -+#endif -+ -+static GCOps rfbSpriteGCOps = { -+ rfbSpriteFillSpans, rfbSpriteSetSpans, rfbSpritePutImage, -+ rfbSpriteCopyArea, rfbSpriteCopyPlane, rfbSpritePolyPoint, -+ rfbSpritePolylines, rfbSpritePolySegment, rfbSpritePolyRectangle, -+ rfbSpritePolyArc, rfbSpriteFillPolygon, rfbSpritePolyFillRect, -+ rfbSpritePolyFillArc, rfbSpritePolyText8, rfbSpritePolyText16, -+ rfbSpriteImageText8, rfbSpriteImageText16, rfbSpriteImageGlyphBlt, -+ rfbSpritePolyGlyphBlt, rfbSpritePushPixels -+#ifdef NEED_LINEHELPER -+ , rfbSpriteLineHelper -+#endif -+}; -+ -+/* -+ * testing only -- remove cursor for every draw. Eventually, -+ * each draw operation will perform a bounding box check against -+ * the saved cursor area -+ */ -+ -+#define GC_SETUP_CHEAP(pDrawable) \ -+ rfbSpriteScreenPtr pScreenPriv = (rfbSpriteScreenPtr) \ -+ (pDrawable)->pScreen->devPrivates[rfbSpriteScreenIndex].ptr; \ -+ -+#define GC_SETUP(pDrawable, pGC) \ -+ GC_SETUP_CHEAP(pDrawable) \ -+ rfbSpriteGCPtr pGCPrivate = (rfbSpriteGCPtr) \ -+ (pGC)->devPrivates[rfbSpriteGCIndex].ptr; \ -+ GCFuncs *oldFuncs = pGC->funcs; -+ -+#define GC_SETUP_AND_CHECK(pDrawable, pGC) \ -+ GC_SETUP(pDrawable, pGC); \ -+ if (GC_CHECK((WindowPtr)pDrawable)) \ -+ rfbSpriteRemoveCursor (pDrawable->pScreen); -+ -+#define GC_CHECK(pWin) \ -+ (pVNC->cursorIsDrawn && \ -+ (pScreenPriv->pCacheWin == pWin ? \ -+ pScreenPriv->isInCacheWin : ( \ -+ (pScreenPriv->pCacheWin = (pWin)) , \ -+ (pScreenPriv->isInCacheWin = \ -+ (pWin)->drawable.x < pScreenPriv->saved.x2 && \ -+ pScreenPriv->saved.x1 < (pWin)->drawable.x + \ -+ (int) (pWin)->drawable.width && \ -+ (pWin)->drawable.y < pScreenPriv->saved.y2 && \ -+ pScreenPriv->saved.y1 < (pWin)->drawable.y + \ -+ (int) (pWin)->drawable.height &&\ -+ RECT_IN_REGION((pWin)->drawable.pScreen, &(pWin)->borderClip, \ -+ &pScreenPriv->saved) != rgnOUT)))) -+ -+#define GC_OP_PROLOGUE(pGC) { \ -+ (pGC)->funcs = pGCPrivate->wrapFuncs; \ -+ (pGC)->ops = pGCPrivate->wrapOps; \ -+ } -+ -+#define GC_OP_EPILOGUE(pGC) { \ -+ pGCPrivate->wrapOps = (pGC)->ops; \ -+ (pGC)->funcs = oldFuncs; \ -+ (pGC)->ops = &rfbSpriteGCOps; \ -+ } -+ -+/* -+ * pointer-sprite method table -+ */ -+ -+static Bool rfbSpriteRealizeCursor (), rfbSpriteUnrealizeCursor (); -+static void rfbSpriteSetCursor (), rfbSpriteMoveCursor (); -+ -+miPointerSpriteFuncRec rfbSpritePointerFuncs = { -+ rfbSpriteRealizeCursor, -+ rfbSpriteUnrealizeCursor, -+ rfbSpriteSetCursor, -+ rfbSpriteMoveCursor, -+}; -+ -+/* -+ * other misc functions -+ */ -+ -+static Bool rfbDisplayCursor (ScreenPtr pScreen, CursorPtr pCursor); -+ -+ -+/* -+ * rfbSpriteInitialize -- called from device-dependent screen -+ * initialization proc after all of the function pointers have -+ * been stored in the screen structure. -+ */ -+ -+Bool -+rfbSpriteInitialize (pScreen, cursorFuncs, screenFuncs) -+ ScreenPtr pScreen; -+ rfbSpriteCursorFuncPtr cursorFuncs; -+ miPointerScreenFuncPtr screenFuncs; -+{ -+ rfbSpriteScreenPtr pPriv; -+ VisualPtr pVisual; -+#ifdef RENDER -+ PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); -+#endif -+ -+ if (rfbSpriteGeneration != serverGeneration) -+ { -+ rfbSpriteScreenIndex = AllocateScreenPrivateIndex (); -+ if (rfbSpriteScreenIndex < 0) -+ return FALSE; -+ rfbSpriteGeneration = serverGeneration; -+ rfbSpriteGCIndex = AllocateGCPrivateIndex (); -+ } -+ if (!AllocateGCPrivate(pScreen, rfbSpriteGCIndex, sizeof(rfbSpriteGCRec))) -+ return FALSE; -+ pPriv = (rfbSpriteScreenPtr) xalloc (sizeof (rfbSpriteScreenRec)); -+ if (!pPriv) -+ return FALSE; -+ if (!miPointerInitialize (pScreen, &rfbSpritePointerFuncs, screenFuncs,TRUE)) -+ { -+ xfree ((pointer) pPriv); -+ return FALSE; -+ } -+ for (pVisual = pScreen->visuals; -+ pVisual->vid != pScreen->rootVisual; -+ pVisual++) -+ ; -+ pPriv->pVisual = pVisual; -+ pPriv->CloseScreen = pScreen->CloseScreen; -+ pPriv->GetImage = pScreen->GetImage; -+ pPriv->GetSpans = pScreen->GetSpans; -+ pPriv->SourceValidate = pScreen->SourceValidate; -+ pPriv->CreateGC = pScreen->CreateGC; -+#if 0 -+ pPriv->BlockHandler = pScreen->BlockHandler; -+#endif -+ pPriv->InstallColormap = pScreen->InstallColormap; -+ pPriv->StoreColors = pScreen->StoreColors; -+ pPriv->DisplayCursor = pScreen->DisplayCursor; -+ -+ pPriv->PaintWindowBackground = pScreen->PaintWindowBackground; -+ pPriv->PaintWindowBorder = pScreen->PaintWindowBorder; -+ pPriv->CopyWindow = pScreen->CopyWindow; -+ pPriv->ClearToBackground = pScreen->ClearToBackground; -+ -+ pPriv->SaveDoomedAreas = pScreen->SaveDoomedAreas; -+ pPriv->RestoreAreas = pScreen->RestoreAreas; -+#ifdef RENDER -+ if (ps) -+ { -+ pPriv->Composite = ps->Composite; -+ pPriv->Glyphs = ps->Glyphs; -+ } -+#endif -+ -+ pPriv->pCursor = NULL; -+ pPriv->x = 0; -+ pPriv->y = 0; -+ pPriv->shouldBeUp = FALSE; -+ pPriv->pCacheWin = NullWindow; -+ pPriv->isInCacheWin = FALSE; -+ pPriv->checkPixels = TRUE; -+ pPriv->pInstalledMap = NULL; -+ pPriv->pColormap = NULL; -+ pPriv->funcs = cursorFuncs; -+ pPriv->colors[SOURCE_COLOR].red = 0; -+ pPriv->colors[SOURCE_COLOR].green = 0; -+ pPriv->colors[SOURCE_COLOR].blue = 0; -+ pPriv->colors[MASK_COLOR].red = 0; -+ pPriv->colors[MASK_COLOR].green = 0; -+ pPriv->colors[MASK_COLOR].blue = 0; -+ pScreen->devPrivates[rfbSpriteScreenIndex].ptr = (pointer) pPriv; -+ pScreen->CloseScreen = rfbSpriteCloseScreen; -+ pScreen->GetImage = rfbSpriteGetImage; -+ pScreen->GetSpans = rfbSpriteGetSpans; -+ pScreen->SourceValidate = rfbSpriteSourceValidate; -+ pScreen->CreateGC = rfbSpriteCreateGC; -+#if 0 -+ pScreen->BlockHandler = rfbSpriteBlockHandler; -+#endif -+ pScreen->InstallColormap = rfbSpriteInstallColormap; -+ pScreen->StoreColors = rfbSpriteStoreColors; -+ -+ pScreen->PaintWindowBackground = rfbSpritePaintWindowBackground; -+ pScreen->PaintWindowBorder = rfbSpritePaintWindowBorder; -+ pScreen->CopyWindow = rfbSpriteCopyWindow; -+ pScreen->ClearToBackground = rfbSpriteClearToBackground; -+ -+ pScreen->SaveDoomedAreas = rfbSpriteSaveDoomedAreas; -+ pScreen->RestoreAreas = rfbSpriteRestoreAreas; -+ -+ pScreen->DisplayCursor = rfbDisplayCursor; -+#ifdef RENDER -+ if (ps) -+ { -+ ps->Composite = rfbSpriteComposite; -+ ps->Glyphs = rfbSpriteGlyphs; -+ } -+#endif -+ -+ return TRUE; -+} -+ -+/* -+ * Screen wrappers -+ */ -+ -+/* -+ * CloseScreen wrapper -- unwrap everything, free the private data -+ * and call the wrapped function -+ */ -+ -+static Bool -+rfbSpriteCloseScreen (i, pScreen) -+ ScreenPtr pScreen; -+{ -+ rfbSpriteScreenPtr pScreenPriv; -+#ifdef RENDER -+ PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); -+#endif -+ -+ pScreenPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr; -+ -+ pScreen->CloseScreen = pScreenPriv->CloseScreen; -+ pScreen->GetImage = pScreenPriv->GetImage; -+ pScreen->GetSpans = pScreenPriv->GetSpans; -+ pScreen->SourceValidate = pScreenPriv->SourceValidate; -+ pScreen->CreateGC = pScreenPriv->CreateGC; -+#if 0 -+ pScreen->BlockHandler = pScreenPriv->BlockHandler; -+#endif -+ pScreen->InstallColormap = pScreenPriv->InstallColormap; -+ pScreen->StoreColors = pScreenPriv->StoreColors; -+ -+ pScreen->PaintWindowBackground = pScreenPriv->PaintWindowBackground; -+ pScreen->PaintWindowBorder = pScreenPriv->PaintWindowBorder; -+ pScreen->CopyWindow = pScreenPriv->CopyWindow; -+ pScreen->ClearToBackground = pScreenPriv->ClearToBackground; -+ -+ pScreen->SaveDoomedAreas = pScreenPriv->SaveDoomedAreas; -+ pScreen->RestoreAreas = pScreenPriv->RestoreAreas; -+#ifdef RENDER -+ if (ps) -+ { -+ ps->Composite = pScreenPriv->Composite; -+ ps->Glyphs = pScreenPriv->Glyphs; -+ } -+#endif -+ -+ xfree ((pointer) pScreenPriv); -+ -+ return (*pScreen->CloseScreen) (i, pScreen); -+} -+ -+static void -+rfbSpriteGetImage (pDrawable, sx, sy, w, h, format, planemask, pdstLine) -+ DrawablePtr pDrawable; -+ int sx, sy, w, h; -+ unsigned int format; -+ unsigned long planemask; -+ char *pdstLine; -+{ -+ ScreenPtr pScreen = pDrawable->pScreen; -+ rfbSpriteScreenPtr pScreenPriv; -+ VNCSCREENPTR(pScreen); -+ -+ SCREEN_PROLOGUE (pScreen, GetImage); -+ -+ pScreenPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr; -+ -+ if (pDrawable->type == DRAWABLE_WINDOW && -+ pVNC->cursorIsDrawn && -+ ORG_OVERLAP(&pScreenPriv->saved,pDrawable->x,pDrawable->y, sx, sy, w, h)) -+ { -+ rfbSpriteRemoveCursor (pScreen); -+ } -+ -+ (*pScreen->GetImage) (pDrawable, sx, sy, w, h, -+ format, planemask, pdstLine); -+ -+ SCREEN_EPILOGUE (pScreen, GetImage, rfbSpriteGetImage); -+} -+ -+static void -+rfbSpriteGetSpans (pDrawable, wMax, ppt, pwidth, nspans, pdstStart) -+ DrawablePtr pDrawable; -+ int wMax; -+ DDXPointPtr ppt; -+ int *pwidth; -+ int nspans; -+ char *pdstStart; -+{ -+ ScreenPtr pScreen = pDrawable->pScreen; -+ rfbSpriteScreenPtr pScreenPriv; -+ VNCSCREENPTR(pScreen); -+ -+ SCREEN_PROLOGUE (pScreen, GetSpans); -+ -+ pScreenPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr; -+ -+ if (pDrawable->type == DRAWABLE_WINDOW && pVNC->cursorIsDrawn) -+ { -+ register DDXPointPtr pts; -+ register int *widths; -+ register int nPts; -+ register int xorg, -+ yorg; -+ -+ xorg = pDrawable->x; -+ yorg = pDrawable->y; -+ -+ for (pts = ppt, widths = pwidth, nPts = nspans; -+ nPts--; -+ pts++, widths++) -+ { -+ if (SPN_OVERLAP(&pScreenPriv->saved,pts->y+yorg, -+ pts->x+xorg,*widths)) -+ { -+ rfbSpriteRemoveCursor (pScreen); -+ break; -+ } -+ } -+ } -+ -+ (*pScreen->GetSpans) (pDrawable, wMax, ppt, pwidth, nspans, pdstStart); -+ -+ SCREEN_EPILOGUE (pScreen, GetSpans, rfbSpriteGetSpans); -+} -+ -+static void -+rfbSpriteSourceValidate (pDrawable, x, y, width, height) -+ DrawablePtr pDrawable; -+ int x, y, width, height; -+{ -+ ScreenPtr pScreen = pDrawable->pScreen; -+ rfbSpriteScreenPtr pScreenPriv; -+ VNCSCREENPTR(pScreen); -+ -+ SCREEN_PROLOGUE (pScreen, SourceValidate); -+ -+ pScreenPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr; -+ -+ if (pDrawable->type == DRAWABLE_WINDOW && pVNC->cursorIsDrawn && -+ ORG_OVERLAP(&pScreenPriv->saved, pDrawable->x, pDrawable->y, -+ x, y, width, height)) -+ { -+ rfbSpriteRemoveCursor (pScreen); -+ } -+ -+ if (pScreen->SourceValidate) -+ (*pScreen->SourceValidate) (pDrawable, x, y, width, height); -+ -+ SCREEN_EPILOGUE (pScreen, SourceValidate, rfbSpriteSourceValidate); -+} -+ -+static Bool -+rfbSpriteCreateGC (pGC) -+ GCPtr pGC; -+{ -+ ScreenPtr pScreen = pGC->pScreen; -+ Bool ret; -+ rfbSpriteGCPtr pPriv; -+ -+ SCREEN_PROLOGUE (pScreen, CreateGC); -+ -+ pPriv = (rfbSpriteGCPtr)pGC->devPrivates[rfbSpriteGCIndex].ptr; -+ -+ ret = (*pScreen->CreateGC) (pGC); -+ -+ pPriv->wrapOps = NULL; -+ pPriv->wrapFuncs = pGC->funcs; -+ pGC->funcs = &rfbSpriteGCFuncs; -+ -+ SCREEN_EPILOGUE (pScreen, CreateGC, rfbSpriteCreateGC); -+ -+ return ret; -+} -+ -+static void -+rfbSpriteBlockHandler (i, blockData, pTimeout, pReadmask) -+ int i; -+ pointer blockData; -+ pointer pTimeout; -+ pointer pReadmask; -+{ -+ ScreenPtr pScreen = screenInfo.screens[i]; -+ rfbSpriteScreenPtr pPriv; -+ VNCSCREENPTR(pScreen); -+ -+ pPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr; -+ -+ SCREEN_PROLOGUE(pScreen, BlockHandler); -+ -+ (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask); -+ -+ SCREEN_EPILOGUE(pScreen, BlockHandler, rfbSpriteBlockHandler); -+ -+ if (!pVNC->cursorIsDrawn && pPriv->shouldBeUp) -+ rfbSpriteRestoreCursor (pScreen); -+} -+ -+static void -+rfbSpriteInstallColormap (pMap) -+ ColormapPtr pMap; -+{ -+ ScreenPtr pScreen = pMap->pScreen; -+ rfbSpriteScreenPtr pPriv; -+ VNCSCREENPTR(pScreen); -+ -+ pPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr; -+ -+ SCREEN_PROLOGUE(pScreen, InstallColormap); -+ -+ (*pScreen->InstallColormap) (pMap); -+ -+ SCREEN_EPILOGUE(pScreen, InstallColormap, rfbSpriteInstallColormap); -+ -+ pPriv->pInstalledMap = pMap; -+ if (pPriv->pColormap != pMap) -+ { -+ pPriv->checkPixels = TRUE; -+ if (pVNC->cursorIsDrawn) -+ rfbSpriteRemoveCursor (pScreen); -+ } -+} -+ -+static void -+rfbSpriteStoreColors (pMap, ndef, pdef) -+ ColormapPtr pMap; -+ int ndef; -+ xColorItem *pdef; -+{ -+ ScreenPtr pScreen = pMap->pScreen; -+ rfbSpriteScreenPtr pPriv; -+ int i; -+ int updated; -+ VisualPtr pVisual; -+ VNCSCREENPTR(pScreen); -+ -+ pPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr; -+ -+ SCREEN_PROLOGUE(pScreen, StoreColors); -+ -+ (*pScreen->StoreColors) (pMap, ndef, pdef); -+ -+ SCREEN_EPILOGUE(pScreen, StoreColors, rfbSpriteStoreColors); -+ -+ if (pPriv->pColormap == pMap) -+ { -+ updated = 0; -+ pVisual = pMap->pVisual; -+ if (pVisual->class == DirectColor) -+ { -+ /* Direct color - match on any of the subfields */ -+ -+#define MaskMatch(a,b,mask) ((a) & ((pVisual->mask) == (b)) & (pVisual->mask)) -+ -+#define UpdateDAC(plane,dac,mask) {\ -+ if (MaskMatch (pPriv->colors[plane].pixel,pdef[i].pixel,mask)) {\ -+ pPriv->colors[plane].dac = pdef[i].dac; \ -+ updated = 1; \ -+ } \ -+} -+ -+#define CheckDirect(plane) \ -+ UpdateDAC(plane,red,redMask) \ -+ UpdateDAC(plane,green,greenMask) \ -+ UpdateDAC(plane,blue,blueMask) -+ -+ for (i = 0; i < ndef; i++) -+ { -+ CheckDirect (SOURCE_COLOR) -+ CheckDirect (MASK_COLOR) -+ } -+ } -+ else -+ { -+ /* PseudoColor/GrayScale - match on exact pixel */ -+ for (i = 0; i < ndef; i++) -+ { -+ if (pdef[i].pixel == pPriv->colors[SOURCE_COLOR].pixel) -+ { -+ pPriv->colors[SOURCE_COLOR] = pdef[i]; -+ if (++updated == 2) -+ break; -+ } -+ if (pdef[i].pixel == pPriv->colors[MASK_COLOR].pixel) -+ { -+ pPriv->colors[MASK_COLOR] = pdef[i]; -+ if (++updated == 2) -+ break; -+ } -+ } -+ } -+ if (updated) -+ { -+ pPriv->checkPixels = TRUE; -+ if (pVNC->cursorIsDrawn) -+ rfbSpriteRemoveCursor (pScreen); -+ } -+ } -+} -+ -+static void -+rfbSpriteFindColors (pScreen) -+ ScreenPtr pScreen; -+{ -+ rfbSpriteScreenPtr pScreenPriv = (rfbSpriteScreenPtr) -+ pScreen->devPrivates[rfbSpriteScreenIndex].ptr; -+ CursorPtr pCursor; -+ xColorItem *sourceColor, *maskColor; -+ -+ pCursor = pScreenPriv->pCursor; -+ sourceColor = &pScreenPriv->colors[SOURCE_COLOR]; -+ maskColor = &pScreenPriv->colors[MASK_COLOR]; -+ if (pScreenPriv->pColormap != pScreenPriv->pInstalledMap || -+ !(pCursor->foreRed == sourceColor->red && -+ pCursor->foreGreen == sourceColor->green && -+ pCursor->foreBlue == sourceColor->blue && -+ pCursor->backRed == maskColor->red && -+ pCursor->backGreen == maskColor->green && -+ pCursor->backBlue == maskColor->blue)) -+ { -+ pScreenPriv->pColormap = pScreenPriv->pInstalledMap; -+ sourceColor->red = pCursor->foreRed; -+ sourceColor->green = pCursor->foreGreen; -+ sourceColor->blue = pCursor->foreBlue; -+ FakeAllocColor (pScreenPriv->pColormap, sourceColor); -+ maskColor->red = pCursor->backRed; -+ maskColor->green = pCursor->backGreen; -+ maskColor->blue = pCursor->backBlue; -+ FakeAllocColor (pScreenPriv->pColormap, maskColor); -+ /* "free" the pixels right away, don't let this confuse you */ -+ FakeFreeColor(pScreenPriv->pColormap, sourceColor->pixel); -+ FakeFreeColor(pScreenPriv->pColormap, maskColor->pixel); -+ } -+ pScreenPriv->checkPixels = FALSE; -+} -+ -+/* -+ * BackingStore wrappers -+ */ -+ -+static void -+rfbSpriteSaveDoomedAreas (pWin, pObscured, dx, dy) -+ WindowPtr pWin; -+ RegionPtr pObscured; -+ int dx, dy; -+{ -+ ScreenPtr pScreen = pWin->drawable.pScreen; -+ rfbSpriteScreenPtr pScreenPriv; -+ BoxRec cursorBox; -+ VNCSCREENPTR(pScreen); -+ -+ SCREEN_PROLOGUE (pScreen, SaveDoomedAreas); -+ -+ pScreenPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr; -+ if (pVNC->cursorIsDrawn) -+ { -+ cursorBox = pScreenPriv->saved; -+ -+ if (dx || dy) -+ { -+ cursorBox.x1 += dx; -+ cursorBox.y1 += dy; -+ cursorBox.x2 += dx; -+ cursorBox.y2 += dy; -+ } -+ if (RECT_IN_REGION( pScreen, pObscured, &cursorBox) != rgnOUT) -+ rfbSpriteRemoveCursor (pScreen); -+ } -+ -+ (*pScreen->SaveDoomedAreas) (pWin, pObscured, dx, dy); -+ -+ SCREEN_EPILOGUE (pScreen, SaveDoomedAreas, rfbSpriteSaveDoomedAreas); -+} -+ -+static RegionPtr -+rfbSpriteRestoreAreas (pWin, prgnExposed) -+ WindowPtr pWin; -+ RegionPtr prgnExposed; -+{ -+ ScreenPtr pScreen = pWin->drawable.pScreen; -+ rfbSpriteScreenPtr pScreenPriv; -+ RegionPtr result; -+ VNCSCREENPTR(pScreen); -+ -+ SCREEN_PROLOGUE (pScreen, RestoreAreas); -+ -+ pScreenPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr; -+ if (pVNC->cursorIsDrawn) -+ { -+ if (RECT_IN_REGION( pScreen, prgnExposed, &pScreenPriv->saved) != rgnOUT) -+ rfbSpriteRemoveCursor (pScreen); -+ } -+ -+ result = (*pScreen->RestoreAreas) (pWin, prgnExposed); -+ -+ SCREEN_EPILOGUE (pScreen, RestoreAreas, rfbSpriteRestoreAreas); -+ -+ return result; -+} -+ -+/* -+ * Window wrappers -+ */ -+ -+static void -+rfbSpritePaintWindowBackground (pWin, pRegion, what) -+ WindowPtr pWin; -+ RegionPtr pRegion; -+ int what; -+{ -+ ScreenPtr pScreen = pWin->drawable.pScreen; -+ rfbSpriteScreenPtr pScreenPriv; -+ VNCSCREENPTR(pScreen); -+ -+ SCREEN_PROLOGUE (pScreen, PaintWindowBackground); -+ -+ pScreenPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr; -+ if (pVNC->cursorIsDrawn) -+ { -+ /* -+ * If the cursor is on the same screen as the window, check the -+ * region to paint for the cursor and remove it as necessary -+ */ -+ if (RECT_IN_REGION( pScreen, pRegion, &pScreenPriv->saved) != rgnOUT) -+ rfbSpriteRemoveCursor (pScreen); -+ } -+ -+ (*pScreen->PaintWindowBackground) (pWin, pRegion, what); -+ -+ SCREEN_EPILOGUE (pScreen, PaintWindowBackground, rfbSpritePaintWindowBackground); -+} -+ -+static void -+rfbSpritePaintWindowBorder (pWin, pRegion, what) -+ WindowPtr pWin; -+ RegionPtr pRegion; -+ int what; -+{ -+ ScreenPtr pScreen = pWin->drawable.pScreen; -+ rfbSpriteScreenPtr pScreenPriv; -+ VNCSCREENPTR(pScreen); -+ -+ SCREEN_PROLOGUE (pScreen, PaintWindowBorder); -+ -+ pScreenPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr; -+ if (pVNC->cursorIsDrawn) -+ { -+ /* -+ * If the cursor is on the same screen as the window, check the -+ * region to paint for the cursor and remove it as necessary -+ */ -+ if (RECT_IN_REGION( pScreen, pRegion, &pScreenPriv->saved) != rgnOUT) -+ rfbSpriteRemoveCursor (pScreen); -+ } -+ -+ (*pScreen->PaintWindowBorder) (pWin, pRegion, what); -+ -+ SCREEN_EPILOGUE (pScreen, PaintWindowBorder, rfbSpritePaintWindowBorder); -+} -+ -+static void -+rfbSpriteCopyWindow (pWin, ptOldOrg, pRegion) -+ WindowPtr pWin; -+ DDXPointRec ptOldOrg; -+ RegionPtr pRegion; -+{ -+ ScreenPtr pScreen = pWin->drawable.pScreen; -+ rfbSpriteScreenPtr pScreenPriv; -+ BoxRec cursorBox; -+ int dx, dy; -+ VNCSCREENPTR(pScreen); -+ -+ SCREEN_PROLOGUE (pScreen, CopyWindow); -+ -+ pScreenPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr; -+ if (pVNC->cursorIsDrawn) -+ { -+ /* -+ * check both the source and the destination areas. The given -+ * region is source relative, so offset the cursor box by -+ * the delta position -+ */ -+ cursorBox = pScreenPriv->saved; -+ dx = pWin->drawable.x - ptOldOrg.x; -+ dy = pWin->drawable.y - ptOldOrg.y; -+ cursorBox.x1 -= dx; -+ cursorBox.x2 -= dx; -+ cursorBox.y1 -= dy; -+ cursorBox.y2 -= dy; -+ if (RECT_IN_REGION( pScreen, pRegion, &pScreenPriv->saved) != rgnOUT || -+ RECT_IN_REGION( pScreen, pRegion, &cursorBox) != rgnOUT) -+ rfbSpriteRemoveCursor (pScreen); -+ } -+ -+ (*pScreen->CopyWindow) (pWin, ptOldOrg, pRegion); -+ -+ SCREEN_EPILOGUE (pScreen, CopyWindow, rfbSpriteCopyWindow); -+} -+ -+static void -+rfbSpriteClearToBackground (pWin, x, y, w, h, generateExposures) -+ WindowPtr pWin; -+ short x,y; -+ unsigned short w,h; -+ Bool generateExposures; -+{ -+ ScreenPtr pScreen = pWin->drawable.pScreen; -+ rfbSpriteScreenPtr pScreenPriv; -+ int realw, realh; -+ VNCSCREENPTR(pScreen); -+ -+ SCREEN_PROLOGUE (pScreen, ClearToBackground); -+ -+ pScreenPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr; -+ if (GC_CHECK(pWin)) -+ { -+ if (!(realw = w)) -+ realw = (int) pWin->drawable.width - x; -+ if (!(realh = h)) -+ realh = (int) pWin->drawable.height - y; -+ if (ORG_OVERLAP(&pScreenPriv->saved, pWin->drawable.x, pWin->drawable.y, -+ x, y, realw, realh)) -+ { -+ rfbSpriteRemoveCursor (pScreen); -+ } -+ } -+ -+ (*pScreen->ClearToBackground) (pWin, x, y, w, h, generateExposures); -+ -+ SCREEN_EPILOGUE (pScreen, ClearToBackground, rfbSpriteClearToBackground); -+} -+ -+/* -+ * GC Func wrappers -+ */ -+ -+static void -+rfbSpriteValidateGC (pGC, changes, pDrawable) -+ GCPtr pGC; -+ unsigned long changes; -+ DrawablePtr pDrawable; -+{ -+ GC_FUNC_PROLOGUE (pGC); -+ -+ (*pGC->funcs->ValidateGC) (pGC, changes, pDrawable); -+ -+ pGCPriv->wrapOps = NULL; -+ if (pDrawable->type == DRAWABLE_WINDOW && ((WindowPtr) pDrawable)->viewable) -+ { -+ WindowPtr pWin; -+ RegionPtr pRegion; -+ -+ pWin = (WindowPtr) pDrawable; -+ pRegion = &pWin->clipList; -+ if (pGC->subWindowMode == IncludeInferiors) -+ pRegion = &pWin->borderClip; -+ if (REGION_NOTEMPTY(pDrawable->pScreen, pRegion)) -+ pGCPriv->wrapOps = pGC->ops; -+ } -+ -+ GC_FUNC_EPILOGUE (pGC); -+} -+ -+static void -+rfbSpriteChangeGC (pGC, mask) -+ GCPtr pGC; -+ unsigned long mask; -+{ -+ GC_FUNC_PROLOGUE (pGC); -+ -+ (*pGC->funcs->ChangeGC) (pGC, mask); -+ -+ GC_FUNC_EPILOGUE (pGC); -+} -+ -+static void -+rfbSpriteCopyGC (pGCSrc, mask, pGCDst) -+ GCPtr pGCSrc, pGCDst; -+ unsigned long mask; -+{ -+ GC_FUNC_PROLOGUE (pGCDst); -+ -+ (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst); -+ -+ GC_FUNC_EPILOGUE (pGCDst); -+} -+ -+static void -+rfbSpriteDestroyGC (pGC) -+ GCPtr pGC; -+{ -+ GC_FUNC_PROLOGUE (pGC); -+ -+ (*pGC->funcs->DestroyGC) (pGC); -+ -+ GC_FUNC_EPILOGUE (pGC); -+} -+ -+static void -+rfbSpriteChangeClip (pGC, type, pvalue, nrects) -+ GCPtr pGC; -+ int type; -+ pointer pvalue; -+ int nrects; -+{ -+ GC_FUNC_PROLOGUE (pGC); -+ -+ (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects); -+ -+ GC_FUNC_EPILOGUE (pGC); -+} -+ -+static void -+rfbSpriteCopyClip(pgcDst, pgcSrc) -+ GCPtr pgcDst, pgcSrc; -+{ -+ GC_FUNC_PROLOGUE (pgcDst); -+ -+ (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc); -+ -+ GC_FUNC_EPILOGUE (pgcDst); -+} -+ -+static void -+rfbSpriteDestroyClip(pGC) -+ GCPtr pGC; -+{ -+ GC_FUNC_PROLOGUE (pGC); -+ -+ (* pGC->funcs->DestroyClip)(pGC); -+ -+ GC_FUNC_EPILOGUE (pGC); -+} -+ -+/* -+ * GC Op wrappers -+ */ -+ -+static void -+rfbSpriteFillSpans(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted) -+ DrawablePtr pDrawable; -+ GCPtr pGC; -+ int nInit; /* number of spans to fill */ -+ DDXPointPtr pptInit; /* pointer to list of start points */ -+ int *pwidthInit; /* pointer to list of n widths */ -+ int fSorted; -+{ -+ ScreenPtr pScreen = pDrawable->pScreen; -+ VNCSCREENPTR(pScreen); -+ -+ GC_SETUP(pDrawable, pGC); -+ -+ if (GC_CHECK((WindowPtr) pDrawable)) -+ { -+ register DDXPointPtr pts; -+ register int *widths; -+ register int nPts; -+ -+ for (pts = pptInit, widths = pwidthInit, nPts = nInit; -+ nPts--; -+ pts++, widths++) -+ { -+ if (SPN_OVERLAP(&pScreenPriv->saved,pts->y,pts->x,*widths)) -+ { -+ rfbSpriteRemoveCursor (pDrawable->pScreen); -+ break; -+ } -+ } -+ } -+ -+ GC_OP_PROLOGUE (pGC); -+ -+ (*pGC->ops->FillSpans) (pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted); -+ -+ GC_OP_EPILOGUE (pGC); -+} -+ -+static void -+rfbSpriteSetSpans(pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted) -+ DrawablePtr pDrawable; -+ GCPtr pGC; -+ char *psrc; -+ register DDXPointPtr ppt; -+ int *pwidth; -+ int nspans; -+ int fSorted; -+{ -+ ScreenPtr pScreen = pDrawable->pScreen; -+ VNCSCREENPTR(pScreen); -+ -+ GC_SETUP(pDrawable, pGC); -+ -+ if (GC_CHECK((WindowPtr) pDrawable)) -+ { -+ register DDXPointPtr pts; -+ register int *widths; -+ register int nPts; -+ -+ for (pts = ppt, widths = pwidth, nPts = nspans; -+ nPts--; -+ pts++, widths++) -+ { -+ if (SPN_OVERLAP(&pScreenPriv->saved,pts->y,pts->x,*widths)) -+ { -+ rfbSpriteRemoveCursor(pDrawable->pScreen); -+ break; -+ } -+ } -+ } -+ -+ GC_OP_PROLOGUE (pGC); -+ -+ (*pGC->ops->SetSpans) (pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted); -+ -+ GC_OP_EPILOGUE (pGC); -+} -+ -+static void -+rfbSpritePutImage(pDrawable, pGC, depth, x, y, w, h, leftPad, format, pBits) -+ DrawablePtr pDrawable; -+ GCPtr pGC; -+ int depth; -+ int x; -+ int y; -+ int w; -+ int h; -+ int format; -+ char *pBits; -+{ -+ ScreenPtr pScreen = pDrawable->pScreen; -+ VNCSCREENPTR(pScreen); -+ -+ GC_SETUP(pDrawable, pGC); -+ -+ if (GC_CHECK((WindowPtr) pDrawable)) -+ { -+ if (ORG_OVERLAP(&pScreenPriv->saved,pDrawable->x,pDrawable->y, -+ x,y,w,h)) -+ { -+ rfbSpriteRemoveCursor (pDrawable->pScreen); -+ } -+ } -+ -+ GC_OP_PROLOGUE (pGC); -+ -+ (*pGC->ops->PutImage) (pDrawable, pGC, depth, x, y, w, h, leftPad, format, pBits); -+ -+ GC_OP_EPILOGUE (pGC); -+} -+ -+static RegionPtr -+rfbSpriteCopyArea (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty) -+ DrawablePtr pSrc; -+ DrawablePtr pDst; -+ GCPtr pGC; -+ int srcx; -+ int srcy; -+ int w; -+ int h; -+ int dstx; -+ int dsty; -+{ -+ RegionPtr rgn; -+ ScreenPtr pScreen = pGC->pScreen; -+ VNCSCREENPTR(pScreen); -+ -+ GC_SETUP(pDst, pGC); -+ -+ /* check destination/source overlap. */ -+ if (GC_CHECK((WindowPtr) pDst) && -+ (ORG_OVERLAP(&pScreenPriv->saved,pDst->x,pDst->y,dstx,dsty,w,h) || -+ ((pDst == pSrc) && -+ ORG_OVERLAP(&pScreenPriv->saved,pSrc->x,pSrc->y,srcx,srcy,w,h)))) -+ { -+ rfbSpriteRemoveCursor (pDst->pScreen); -+ } -+ -+ GC_OP_PROLOGUE (pGC); -+ -+ rgn = (*pGC->ops->CopyArea) (pSrc, pDst, pGC, srcx, srcy, w, h, -+ dstx, dsty); -+ -+ GC_OP_EPILOGUE (pGC); -+ -+ return rgn; -+} -+ -+static RegionPtr -+rfbSpriteCopyPlane (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty, plane) -+ DrawablePtr pSrc; -+ DrawablePtr pDst; -+ register GCPtr pGC; -+ int srcx, -+ srcy; -+ int w, -+ h; -+ int dstx, -+ dsty; -+ unsigned long plane; -+{ -+ RegionPtr rgn; -+ ScreenPtr pScreen = pGC->pScreen; -+ VNCSCREENPTR(pScreen); -+ -+ GC_SETUP(pDst, pGC); -+ -+ /* -+ * check destination/source for overlap. -+ */ -+ if (GC_CHECK((WindowPtr) pDst) && -+ (ORG_OVERLAP(&pScreenPriv->saved,pDst->x,pDst->y,dstx,dsty,w,h) || -+ ((pDst == pSrc) && -+ ORG_OVERLAP(&pScreenPriv->saved,pSrc->x,pSrc->y,srcx,srcy,w,h)))) -+ { -+ rfbSpriteRemoveCursor (pDst->pScreen); -+ } -+ -+ GC_OP_PROLOGUE (pGC); -+ -+ rgn = (*pGC->ops->CopyPlane) (pSrc, pDst, pGC, srcx, srcy, w, h, -+ dstx, dsty, plane); -+ -+ GC_OP_EPILOGUE (pGC); -+ -+ return rgn; -+} -+ -+static void -+rfbSpritePolyPoint (pDrawable, pGC, mode, npt, pptInit) -+ DrawablePtr pDrawable; -+ GCPtr pGC; -+ int mode; /* Origin or Previous */ -+ int npt; -+ xPoint *pptInit; -+{ -+ xPoint t; -+ int n; -+ BoxRec cursor; -+ register xPoint *pts; -+ ScreenPtr pScreen = pDrawable->pScreen; -+ VNCSCREENPTR(pScreen); -+ -+ GC_SETUP (pDrawable, pGC); -+ -+ if (npt && GC_CHECK((WindowPtr) pDrawable)) -+ { -+ cursor.x1 = pScreenPriv->saved.x1 - pDrawable->x; -+ cursor.y1 = pScreenPriv->saved.y1 - pDrawable->y; -+ cursor.x2 = pScreenPriv->saved.x2 - pDrawable->x; -+ cursor.y2 = pScreenPriv->saved.y2 - pDrawable->y; -+ -+ if (mode == CoordModePrevious) -+ { -+ t.x = 0; -+ t.y = 0; -+ for (pts = pptInit, n = npt; n--; pts++) -+ { -+ t.x += pts->x; -+ t.y += pts->y; -+ if (cursor.x1 <= t.x && t.x <= cursor.x2 && -+ cursor.y1 <= t.y && t.y <= cursor.y2) -+ { -+ rfbSpriteRemoveCursor (pDrawable->pScreen); -+ break; -+ } -+ } -+ } -+ else -+ { -+ for (pts = pptInit, n = npt; n--; pts++) -+ { -+ if (cursor.x1 <= pts->x && pts->x <= cursor.x2 && -+ cursor.y1 <= pts->y && pts->y <= cursor.y2) -+ { -+ rfbSpriteRemoveCursor (pDrawable->pScreen); -+ break; -+ } -+ } -+ } -+ } -+ -+ GC_OP_PROLOGUE (pGC); -+ -+ (*pGC->ops->PolyPoint) (pDrawable, pGC, mode, npt, pptInit); -+ -+ GC_OP_EPILOGUE (pGC); -+} -+ -+static void -+rfbSpritePolylines (pDrawable, pGC, mode, npt, pptInit) -+ DrawablePtr pDrawable; -+ GCPtr pGC; -+ int mode; -+ int npt; -+ DDXPointPtr pptInit; -+{ -+ BoxPtr cursor; -+ register DDXPointPtr pts; -+ int n; -+ int x, y, x1, y1, x2, y2; -+ int lw; -+ int extra; -+ ScreenPtr pScreen = pDrawable->pScreen; -+ VNCSCREENPTR(pScreen); -+ -+ GC_SETUP (pDrawable, pGC); -+ -+ if (npt && GC_CHECK((WindowPtr) pDrawable)) -+ { -+ cursor = &pScreenPriv->saved; -+ lw = pGC->lineWidth; -+ x = pptInit->x + pDrawable->x; -+ y = pptInit->y + pDrawable->y; -+ -+ if (npt == 1) -+ { -+ extra = lw >> 1; -+ if (LINE_OVERLAP(cursor, x, y, x, y, extra)) -+ rfbSpriteRemoveCursor (pDrawable->pScreen); -+ } -+ else -+ { -+ extra = lw >> 1; -+ /* -+ * mitered joins can project quite a way from -+ * the line end; the 11 degree miter limit limits -+ * this extension to 10.43 * lw / 2, rounded up -+ * and converted to int yields 6 * lw -+ */ -+ if (pGC->joinStyle == JoinMiter) -+ extra = 6 * lw; -+ else if (pGC->capStyle == CapProjecting) -+ extra = lw; -+ for (pts = pptInit + 1, n = npt - 1; n--; pts++) -+ { -+ x1 = x; -+ y1 = y; -+ if (mode == CoordModeOrigin) -+ { -+ x2 = pDrawable->x + pts->x; -+ y2 = pDrawable->y + pts->y; -+ } -+ else -+ { -+ x2 = x + pts->x; -+ y2 = y + pts->y; -+ } -+ x = x2; -+ y = y2; -+ LINE_SORT(x1, y1, x2, y2); -+ if (LINE_OVERLAP(cursor, x1, y1, x2, y2, extra)) -+ { -+ rfbSpriteRemoveCursor (pDrawable->pScreen); -+ break; -+ } -+ } -+ } -+ } -+ GC_OP_PROLOGUE (pGC); -+ -+ (*pGC->ops->Polylines) (pDrawable, pGC, mode, npt, pptInit); -+ -+ GC_OP_EPILOGUE (pGC); -+} -+ -+static void -+rfbSpritePolySegment(pDrawable, pGC, nseg, pSegs) -+ DrawablePtr pDrawable; -+ GCPtr pGC; -+ int nseg; -+ xSegment *pSegs; -+{ -+ int n; -+ register xSegment *segs; -+ BoxPtr cursor; -+ int x1, y1, x2, y2; -+ int extra; -+ ScreenPtr pScreen = pDrawable->pScreen; -+ VNCSCREENPTR(pScreen); -+ -+ GC_SETUP(pDrawable, pGC); -+ -+ if (nseg && GC_CHECK((WindowPtr) pDrawable)) -+ { -+ cursor = &pScreenPriv->saved; -+ extra = pGC->lineWidth >> 1; -+ if (pGC->capStyle == CapProjecting) -+ extra = pGC->lineWidth; -+ for (segs = pSegs, n = nseg; n--; segs++) -+ { -+ x1 = segs->x1 + pDrawable->x; -+ y1 = segs->y1 + pDrawable->y; -+ x2 = segs->x2 + pDrawable->x; -+ y2 = segs->y2 + pDrawable->y; -+ LINE_SORT(x1, y1, x2, y2); -+ if (LINE_OVERLAP(cursor, x1, y1, x2, y2, extra)) -+ { -+ rfbSpriteRemoveCursor (pDrawable->pScreen); -+ break; -+ } -+ } -+ } -+ -+ GC_OP_PROLOGUE (pGC); -+ -+ (*pGC->ops->PolySegment) (pDrawable, pGC, nseg, pSegs); -+ -+ GC_OP_EPILOGUE (pGC); -+} -+ -+static void -+rfbSpritePolyRectangle(pDrawable, pGC, nrects, pRects) -+ DrawablePtr pDrawable; -+ GCPtr pGC; -+ int nrects; -+ xRectangle *pRects; -+{ -+ register xRectangle *rects; -+ BoxPtr cursor; -+ int lw; -+ int n; -+ int x1, y1, x2, y2; -+ ScreenPtr pScreen = pDrawable->pScreen; -+ VNCSCREENPTR(pScreen); -+ -+ GC_SETUP (pDrawable, pGC); -+ -+ if (GC_CHECK((WindowPtr) pDrawable)) -+ { -+ lw = pGC->lineWidth >> 1; -+ cursor = &pScreenPriv->saved; -+ for (rects = pRects, n = nrects; n--; rects++) -+ { -+ x1 = rects->x + pDrawable->x; -+ y1 = rects->y + pDrawable->y; -+ x2 = x1 + (int)rects->width; -+ y2 = y1 + (int)rects->height; -+ if (LINE_OVERLAP(cursor, x1, y1, x2, y1, lw) || -+ LINE_OVERLAP(cursor, x2, y1, x2, y2, lw) || -+ LINE_OVERLAP(cursor, x1, y2, x2, y2, lw) || -+ LINE_OVERLAP(cursor, x1, y1, x1, y2, lw)) -+ { -+ rfbSpriteRemoveCursor (pDrawable->pScreen); -+ break; -+ } -+ } -+ } -+ -+ GC_OP_PROLOGUE (pGC); -+ -+ (*pGC->ops->PolyRectangle) (pDrawable, pGC, nrects, pRects); -+ -+ GC_OP_EPILOGUE (pGC); -+} -+ -+static void -+rfbSpritePolyArc(pDrawable, pGC, narcs, parcs) -+ DrawablePtr pDrawable; -+ register GCPtr pGC; -+ int narcs; -+ xArc *parcs; -+{ -+ BoxPtr cursor; -+ int lw; -+ int n; -+ register xArc *arcs; -+ ScreenPtr pScreen = pDrawable->pScreen; -+ VNCSCREENPTR(pScreen); -+ -+ GC_SETUP (pDrawable, pGC); -+ -+ if (GC_CHECK((WindowPtr) pDrawable)) -+ { -+ lw = pGC->lineWidth >> 1; -+ cursor = &pScreenPriv->saved; -+ for (arcs = parcs, n = narcs; n--; arcs++) -+ { -+ if (ORG_OVERLAP (cursor, pDrawable->x, pDrawable->y, -+ arcs->x - lw, arcs->y - lw, -+ (int) arcs->width + pGC->lineWidth, -+ (int) arcs->height + pGC->lineWidth)) -+ { -+ rfbSpriteRemoveCursor (pDrawable->pScreen); -+ break; -+ } -+ } -+ } -+ -+ GC_OP_PROLOGUE (pGC); -+ -+ (*pGC->ops->PolyArc) (pDrawable, pGC, narcs, parcs); -+ -+ GC_OP_EPILOGUE (pGC); -+} -+ -+static void -+rfbSpriteFillPolygon(pDrawable, pGC, shape, mode, count, pPts) -+ register DrawablePtr pDrawable; -+ register GCPtr pGC; -+ int shape, mode; -+ int count; -+ DDXPointPtr pPts; -+{ -+ int x, y, minx, miny, maxx, maxy; -+ register DDXPointPtr pts; -+ int n; -+ ScreenPtr pScreen = pDrawable->pScreen; -+ VNCSCREENPTR(pScreen); -+ -+ GC_SETUP (pDrawable, pGC); -+ -+ if (count && GC_CHECK((WindowPtr) pDrawable)) -+ { -+ x = pDrawable->x; -+ y = pDrawable->y; -+ pts = pPts; -+ minx = maxx = pts->x; -+ miny = maxy = pts->y; -+ pts++; -+ n = count - 1; -+ -+ if (mode == CoordModeOrigin) -+ { -+ for (; n--; pts++) -+ { -+ if (pts->x < minx) -+ minx = pts->x; -+ else if (pts->x > maxx) -+ maxx = pts->x; -+ if (pts->y < miny) -+ miny = pts->y; -+ else if (pts->y > maxy) -+ maxy = pts->y; -+ } -+ minx += x; -+ miny += y; -+ maxx += x; -+ maxy += y; -+ } -+ else -+ { -+ x += minx; -+ y += miny; -+ minx = maxx = x; -+ miny = maxy = y; -+ for (; n--; pts++) -+ { -+ x += pts->x; -+ y += pts->y; -+ if (x < minx) -+ minx = x; -+ else if (x > maxx) -+ maxx = x; -+ if (y < miny) -+ miny = y; -+ else if (y > maxy) -+ maxy = y; -+ } -+ } -+ if (BOX_OVERLAP(&pScreenPriv->saved,minx,miny,maxx,maxy)) -+ rfbSpriteRemoveCursor (pDrawable->pScreen); -+ } -+ -+ GC_OP_PROLOGUE (pGC); -+ -+ (*pGC->ops->FillPolygon) (pDrawable, pGC, shape, mode, count, pPts); -+ -+ GC_OP_EPILOGUE (pGC); -+} -+ -+static void -+rfbSpritePolyFillRect(pDrawable, pGC, nrectFill, prectInit) -+ DrawablePtr pDrawable; -+ GCPtr pGC; -+ int nrectFill; /* number of rectangles to fill */ -+ xRectangle *prectInit; /* Pointer to first rectangle to fill */ -+{ -+ ScreenPtr pScreen = pDrawable->pScreen; -+ VNCSCREENPTR(pScreen); -+ -+ GC_SETUP(pDrawable, pGC); -+ -+ if (GC_CHECK((WindowPtr) pDrawable)) -+ { -+ register int nRect; -+ register xRectangle *pRect; -+ register int xorg, yorg; -+ -+ xorg = pDrawable->x; -+ yorg = pDrawable->y; -+ -+ for (nRect = nrectFill, pRect = prectInit; nRect--; pRect++) { -+ if (ORGRECT_OVERLAP(&pScreenPriv->saved,xorg,yorg,pRect)){ -+ rfbSpriteRemoveCursor(pDrawable->pScreen); -+ break; -+ } -+ } -+ } -+ -+ GC_OP_PROLOGUE (pGC); -+ -+ (*pGC->ops->PolyFillRect) (pDrawable, pGC, nrectFill, prectInit); -+ -+ GC_OP_EPILOGUE (pGC); -+} -+ -+static void -+rfbSpritePolyFillArc(pDrawable, pGC, narcs, parcs) -+ DrawablePtr pDrawable; -+ GCPtr pGC; -+ int narcs; -+ xArc *parcs; -+{ -+ ScreenPtr pScreen = pDrawable->pScreen; -+ VNCSCREENPTR(pScreen); -+ -+ GC_SETUP(pDrawable, pGC); -+ -+ if (GC_CHECK((WindowPtr) pDrawable)) -+ { -+ register int n; -+ BoxPtr cursor; -+ register xArc *arcs; -+ -+ cursor = &pScreenPriv->saved; -+ -+ for (arcs = parcs, n = narcs; n--; arcs++) -+ { -+ if (ORG_OVERLAP(cursor, pDrawable->x, pDrawable->y, -+ arcs->x, arcs->y, -+ (int) arcs->width, (int) arcs->height)) -+ { -+ rfbSpriteRemoveCursor (pDrawable->pScreen); -+ break; -+ } -+ } -+ } -+ -+ GC_OP_PROLOGUE (pGC); -+ -+ (*pGC->ops->PolyFillArc) (pDrawable, pGC, narcs, parcs); -+ -+ GC_OP_EPILOGUE (pGC); -+} -+ -+/* -+ * general Poly/Image text function. Extract glyph information, -+ * compute bounding box and remove cursor if it is overlapped. -+ */ -+ -+static Bool -+rfbSpriteTextOverlap (pDraw, font, x, y, n, charinfo, imageblt, w, cursorBox) -+ DrawablePtr pDraw; -+ FontPtr font; -+ int x, y; -+ unsigned int n; -+ CharInfoPtr *charinfo; -+ Bool imageblt; -+ unsigned int w; -+ BoxPtr cursorBox; -+{ -+ ExtentInfoRec extents; -+ -+ x += pDraw->x; -+ y += pDraw->y; -+ -+ if (FONTMINBOUNDS(font,characterWidth) >= 0) -+ { -+ /* compute an approximate (but covering) bounding box */ -+ if (!imageblt || (charinfo[0]->metrics.leftSideBearing < 0)) -+ extents.overallLeft = charinfo[0]->metrics.leftSideBearing; -+ else -+ extents.overallLeft = 0; -+ if (w) -+ extents.overallRight = w - charinfo[n-1]->metrics.characterWidth; -+ else -+ extents.overallRight = FONTMAXBOUNDS(font,characterWidth) -+ * (n - 1); -+ if (imageblt && (charinfo[n-1]->metrics.characterWidth > -+ charinfo[n-1]->metrics.rightSideBearing)) -+ extents.overallRight += charinfo[n-1]->metrics.characterWidth; -+ else -+ extents.overallRight += charinfo[n-1]->metrics.rightSideBearing; -+ if (imageblt && FONTASCENT(font) > FONTMAXBOUNDS(font,ascent)) -+ extents.overallAscent = FONTASCENT(font); -+ else -+ extents.overallAscent = FONTMAXBOUNDS(font, ascent); -+ if (imageblt && FONTDESCENT(font) > FONTMAXBOUNDS(font,descent)) -+ extents.overallDescent = FONTDESCENT(font); -+ else -+ extents.overallDescent = FONTMAXBOUNDS(font,descent); -+ if (!BOX_OVERLAP(cursorBox, -+ x + extents.overallLeft, -+ y - extents.overallAscent, -+ x + extents.overallRight, -+ y + extents.overallDescent)) -+ return FALSE; -+ else if (imageblt && w) -+ return TRUE; -+ /* if it does overlap, fall through and compute exactly, because -+ * taking down the cursor is expensive enough to make this worth it -+ */ -+ } -+ QueryGlyphExtents(font, charinfo, n, &extents); -+ if (imageblt) -+ { -+ if (extents.overallWidth > extents.overallRight) -+ extents.overallRight = extents.overallWidth; -+ if (extents.overallWidth < extents.overallLeft) -+ extents.overallLeft = extents.overallWidth; -+ if (extents.overallLeft > 0) -+ extents.overallLeft = 0; -+ if (extents.fontAscent > extents.overallAscent) -+ extents.overallAscent = extents.fontAscent; -+ if (extents.fontDescent > extents.overallDescent) -+ extents.overallDescent = extents.fontDescent; -+ } -+ return (BOX_OVERLAP(cursorBox, -+ x + extents.overallLeft, -+ y - extents.overallAscent, -+ x + extents.overallRight, -+ y + extents.overallDescent)); -+} -+ -+/* -+ * values for textType: -+ */ -+#define TT_POLY8 0 -+#define TT_IMAGE8 1 -+#define TT_POLY16 2 -+#define TT_IMAGE16 3 -+ -+static int -+rfbSpriteText (pDraw, pGC, x, y, count, chars, fontEncoding, textType, cursorBox) -+ DrawablePtr pDraw; -+ GCPtr pGC; -+ int x, -+ y; -+ unsigned long count; -+ char *chars; -+ FontEncoding fontEncoding; -+ Bool textType; -+ BoxPtr cursorBox; -+{ -+ CharInfoPtr *charinfo; -+ register CharInfoPtr *info; -+ unsigned long i; -+ unsigned int n; -+ int w; -+ void (*drawFunc)() = NULL; -+ -+ Bool imageblt; -+ -+ imageblt = (textType == TT_IMAGE8) || (textType == TT_IMAGE16); -+ -+ charinfo = (CharInfoPtr *) ALLOCATE_LOCAL(count * sizeof(CharInfoPtr)); -+ if (!charinfo) -+ return x; -+ -+ GetGlyphs(pGC->font, count, (unsigned char *)chars, -+ fontEncoding, &i, charinfo); -+ n = (unsigned int)i; -+ w = 0; -+ if (!imageblt) -+ for (info = charinfo; i--; info++) -+ w += (*info)->metrics.characterWidth; -+ -+ if (n != 0) { -+ if (rfbSpriteTextOverlap(pDraw, pGC->font, x, y, n, charinfo, imageblt, w, cursorBox)) -+ rfbSpriteRemoveCursor(pDraw->pScreen); -+ -+#ifdef AVOID_GLYPHBLT -+ /* -+ * On displays like Apollos, which do not optimize the GlyphBlt functions because they -+ * convert fonts to their internal form in RealizeFont and optimize text directly, we -+ * want to invoke the text functions here, not the GlyphBlt functions. -+ */ -+ switch (textType) -+ { -+ case TT_POLY8: -+ drawFunc = (void (*)())pGC->ops->PolyText8; -+ break; -+ case TT_IMAGE8: -+ drawFunc = pGC->ops->ImageText8; -+ break; -+ case TT_POLY16: -+ drawFunc = (void (*)())pGC->ops->PolyText16; -+ break; -+ case TT_IMAGE16: -+ drawFunc = pGC->ops->ImageText16; -+ break; -+ } -+ (*drawFunc) (pDraw, pGC, x, y, (int) count, chars); -+#else /* don't AVOID_GLYPHBLT */ -+ /* -+ * On the other hand, if the device does use GlyphBlt ultimately to do text, we -+ * don't want to slow it down by invoking the text functions and having them call -+ * GetGlyphs all over again, so we go directly to the GlyphBlt functions here. -+ */ -+ drawFunc = imageblt ? pGC->ops->ImageGlyphBlt : pGC->ops->PolyGlyphBlt; -+ (*drawFunc) (pDraw, pGC, x, y, n, charinfo, FONTGLYPHS(pGC->font)); -+#endif /* AVOID_GLYPHBLT */ -+ } -+ DEALLOCATE_LOCAL(charinfo); -+ return x + w; -+} -+ -+static int -+rfbSpritePolyText8(pDrawable, pGC, x, y, count, chars) -+ DrawablePtr pDrawable; -+ GCPtr pGC; -+ int x, y; -+ int count; -+ char *chars; -+{ -+ int ret; -+ ScreenPtr pScreen = pDrawable->pScreen; -+ VNCSCREENPTR(pScreen); -+ -+ GC_SETUP (pDrawable, pGC); -+ -+ GC_OP_PROLOGUE (pGC); -+ -+ if (GC_CHECK((WindowPtr) pDrawable)) -+ ret = rfbSpriteText (pDrawable, pGC, x, y, (unsigned long)count, chars, -+ Linear8Bit, TT_POLY8, &pScreenPriv->saved); -+ else -+ ret = (*pGC->ops->PolyText8) (pDrawable, pGC, x, y, count, chars); -+ -+ GC_OP_EPILOGUE (pGC); -+ return ret; -+} -+ -+static int -+rfbSpritePolyText16(pDrawable, pGC, x, y, count, chars) -+ DrawablePtr pDrawable; -+ GCPtr pGC; -+ int x, y; -+ int count; -+ unsigned short *chars; -+{ -+ int ret; -+ ScreenPtr pScreen = pDrawable->pScreen; -+ VNCSCREENPTR(pScreen); -+ -+ GC_SETUP(pDrawable, pGC); -+ -+ GC_OP_PROLOGUE (pGC); -+ -+ if (GC_CHECK((WindowPtr) pDrawable)) -+ ret = rfbSpriteText (pDrawable, pGC, x, y, (unsigned long)count, -+ (char *)chars, -+ FONTLASTROW(pGC->font) == 0 ? -+ Linear16Bit : TwoD16Bit, TT_POLY16, &pScreenPriv->saved); -+ else -+ ret = (*pGC->ops->PolyText16) (pDrawable, pGC, x, y, count, chars); -+ -+ GC_OP_EPILOGUE (pGC); -+ return ret; -+} -+ -+static void -+rfbSpriteImageText8(pDrawable, pGC, x, y, count, chars) -+ DrawablePtr pDrawable; -+ GCPtr pGC; -+ int x, y; -+ int count; -+ char *chars; -+{ -+ ScreenPtr pScreen = pDrawable->pScreen; -+ VNCSCREENPTR(pScreen); -+ -+ GC_SETUP(pDrawable, pGC); -+ -+ GC_OP_PROLOGUE (pGC); -+ -+ if (GC_CHECK((WindowPtr) pDrawable)) -+ (void) rfbSpriteText (pDrawable, pGC, x, y, (unsigned long)count, -+ chars, Linear8Bit, TT_IMAGE8, &pScreenPriv->saved); -+ else -+ (*pGC->ops->ImageText8) (pDrawable, pGC, x, y, count, chars); -+ -+ GC_OP_EPILOGUE (pGC); -+} -+ -+static void -+rfbSpriteImageText16(pDrawable, pGC, x, y, count, chars) -+ DrawablePtr pDrawable; -+ GCPtr pGC; -+ int x, y; -+ int count; -+ unsigned short *chars; -+{ -+ ScreenPtr pScreen = pDrawable->pScreen; -+ VNCSCREENPTR(pScreen); -+ -+ GC_SETUP(pDrawable, pGC); -+ -+ GC_OP_PROLOGUE (pGC); -+ -+ if (GC_CHECK((WindowPtr) pDrawable)) -+ (void) rfbSpriteText (pDrawable, pGC, x, y, (unsigned long)count, -+ (char *)chars, -+ FONTLASTROW(pGC->font) == 0 ? -+ Linear16Bit : TwoD16Bit, TT_IMAGE16, &pScreenPriv->saved); -+ else -+ (*pGC->ops->ImageText16) (pDrawable, pGC, x, y, count, chars); -+ -+ GC_OP_EPILOGUE (pGC); -+} -+ -+static void -+rfbSpriteImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase) -+ DrawablePtr pDrawable; -+ GCPtr pGC; -+ int x, y; -+ unsigned int nglyph; -+ CharInfoPtr *ppci; /* array of character info */ -+ pointer pglyphBase; /* start of array of glyphs */ -+{ -+ ScreenPtr pScreen = pDrawable->pScreen; -+ VNCSCREENPTR(pScreen); -+ -+ GC_SETUP(pDrawable, pGC); -+ -+ GC_OP_PROLOGUE (pGC); -+ -+ if (GC_CHECK((WindowPtr) pDrawable) && -+ rfbSpriteTextOverlap (pDrawable, pGC->font, x, y, nglyph, ppci, TRUE, 0, &pScreenPriv->saved)) -+ { -+ rfbSpriteRemoveCursor(pDrawable->pScreen); -+ } -+ (*pGC->ops->ImageGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); -+ -+ GC_OP_EPILOGUE (pGC); -+} -+ -+static void -+rfbSpritePolyGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase) -+ DrawablePtr pDrawable; -+ GCPtr pGC; -+ int x, y; -+ unsigned int nglyph; -+ CharInfoPtr *ppci; /* array of character info */ -+ pointer pglyphBase; /* start of array of glyphs */ -+{ -+ ScreenPtr pScreen = pDrawable->pScreen; -+ VNCSCREENPTR(pScreen); -+ -+ GC_SETUP (pDrawable, pGC); -+ -+ GC_OP_PROLOGUE (pGC); -+ -+ if (GC_CHECK((WindowPtr) pDrawable) && -+ rfbSpriteTextOverlap (pDrawable, pGC->font, x, y, nglyph, ppci, FALSE, 0, &pScreenPriv->saved)) -+ { -+ rfbSpriteRemoveCursor(pDrawable->pScreen); -+ } -+ (*pGC->ops->PolyGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); -+ -+ GC_OP_EPILOGUE (pGC); -+} -+ -+static void -+rfbSpritePushPixels(pGC, pBitMap, pDrawable, w, h, x, y) -+ GCPtr pGC; -+ PixmapPtr pBitMap; -+ DrawablePtr pDrawable; -+ int w, h, x, y; -+{ -+ VNCSCREENPTR(pScreen); -+ GC_SETUP(pDrawable, pGC); -+ -+ if (GC_CHECK((WindowPtr) pDrawable) && -+ ORG_OVERLAP(&pScreenPriv->saved,pDrawable->x,pDrawable->y,x,y,w,h)) -+ { -+ rfbSpriteRemoveCursor (pDrawable->pScreen); -+ } -+ -+ GC_OP_PROLOGUE (pGC); -+ -+ (*pGC->ops->PushPixels) (pGC, pBitMap, pDrawable, w, h, x, y); -+ -+ GC_OP_EPILOGUE (pGC); -+} -+ -+#ifdef NEED_LINEHELPER -+/* -+ * I don't expect this routine will ever be called, as the GC -+ * will have been unwrapped for the line drawing -+ */ -+ -+static void -+rfbSpriteLineHelper() -+{ -+ FatalError("rfbSpriteLineHelper called\n"); -+} -+#endif -+ -+#ifdef RENDER -+ -+# define mod(a,b) ((b) == 1 ? 0 : (a) >= 0 ? (a) % (b) : (b) - (-a) % (b)) -+ -+static void -+rfbSpritePictureOverlap (PicturePtr pPict, -+ INT16 x, -+ INT16 y, -+ CARD16 w, -+ CARD16 h) -+{ -+ VNCSCREENPTR(pScreen); -+ -+ if (pPict->pDrawable->type == DRAWABLE_WINDOW) -+ { -+ WindowPtr pWin = (WindowPtr) (pPict->pDrawable); -+ rfbSpriteScreenPtr pScreenPriv = (rfbSpriteScreenPtr) -+ pPict->pDrawable->pScreen->devPrivates[rfbSpriteScreenIndex].ptr; -+ if (GC_CHECK(pWin)) -+ { -+ if (pPict->repeat) -+ { -+ x = mod(x,pWin->drawable.width); -+ y = mod(y,pWin->drawable.height); -+ } -+ if (ORG_OVERLAP (&pScreenPriv->saved, pWin->drawable.x, pWin->drawable.y, -+ x, y, w, h)) -+ rfbSpriteRemoveCursor (pWin->drawable.pScreen); -+ } -+ } -+} -+ -+#define PICTURE_PROLOGUE(ps, pScreenPriv, field) \ -+ ps->field = pScreenPriv->field -+ -+#define PICTURE_EPILOGUE(ps, field, wrap) \ -+ ps->field = wrap -+ -+static void -+rfbSpriteComposite(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; -+ PictureScreenPtr ps = GetPictureScreen(pScreen); -+ rfbSpriteScreenPtr pScreenPriv; -+ -+ pScreenPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr; -+ PICTURE_PROLOGUE(ps, pScreenPriv, Composite); -+ rfbSpritePictureOverlap (pSrc, xSrc, ySrc, width, height); -+ if (pMask) -+ rfbSpritePictureOverlap (pMask, xMask, yMask, width, height); -+ rfbSpritePictureOverlap (pDst, xDst, yDst, width, height); -+ -+ (*ps->Composite) (op, -+ pSrc, -+ pMask, -+ pDst, -+ xSrc, -+ ySrc, -+ xMask, -+ yMask, -+ xDst, -+ yDst, -+ width, -+ height); -+ -+ PICTURE_EPILOGUE(ps, Composite, rfbSpriteComposite); -+} -+ -+static void -+rfbSpriteGlyphs(CARD8 op, -+ PicturePtr pSrc, -+ PicturePtr pDst, -+ PictFormatPtr maskFormat, -+ INT16 xSrc, -+ INT16 ySrc, -+ int nlist, -+ GlyphListPtr list, -+ GlyphPtr *glyphs) -+{ -+ ScreenPtr pScreen = pDst->pDrawable->pScreen; -+ VNCSCREENPTR(pScreen); -+ PictureScreenPtr ps = GetPictureScreen(pScreen); -+ rfbSpriteScreenPtr pScreenPriv; -+ -+ pScreenPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr; -+ PICTURE_PROLOGUE(ps, pScreenPriv, Glyphs); -+ if (pSrc->pDrawable->type == DRAWABLE_WINDOW) -+ { -+ WindowPtr pSrcWin = (WindowPtr) (pSrc->pDrawable); -+ -+ if (GC_CHECK(pSrcWin)) -+ rfbSpriteRemoveCursor (pScreen); -+ } -+ if (pDst->pDrawable->type == DRAWABLE_WINDOW) -+ { -+ WindowPtr pDstWin = (WindowPtr) (pDst->pDrawable); -+ -+ if (GC_CHECK(pDstWin)) -+ { -+ BoxRec extents; -+ -+ miGlyphExtents (nlist, list, glyphs, &extents); -+ if (BOX_OVERLAP(&pScreenPriv->saved, -+ extents.x1 + pDstWin->drawable.x, -+ extents.y1 + pDstWin->drawable.y, -+ extents.x2 + pDstWin->drawable.x, -+ extents.y2 + pDstWin->drawable.y)) -+ { -+ rfbSpriteRemoveCursor (pScreen); -+ } -+ } -+ } -+ -+ (*ps->Glyphs) (op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs); -+ -+ PICTURE_EPILOGUE (ps, Glyphs, rfbSpriteGlyphs); -+} -+#endif -+ -+/* -+ * miPointer interface routines -+ */ -+ -+#define SPRITE_PAD 8 -+ -+static Bool -+rfbSpriteRealizeCursor (pScreen, pCursor) -+ ScreenPtr pScreen; -+ CursorPtr pCursor; -+{ -+ rfbSpriteScreenPtr pScreenPriv; -+ -+ pScreenPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr; -+ if (pCursor == pScreenPriv->pCursor) -+ pScreenPriv->checkPixels = TRUE; -+ return (*pScreenPriv->funcs->RealizeCursor) (pScreen, pCursor); -+} -+ -+static Bool -+rfbSpriteUnrealizeCursor (pScreen, pCursor) -+ ScreenPtr pScreen; -+ CursorPtr pCursor; -+{ -+ rfbSpriteScreenPtr pScreenPriv; -+ -+ pScreenPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr; -+ return (*pScreenPriv->funcs->UnrealizeCursor) (pScreen, pCursor); -+} -+ -+static void -+rfbSpriteSetCursor (pScreen, pCursor, x, y) -+ ScreenPtr pScreen; -+ CursorPtr pCursor; -+{ -+ rfbSpriteScreenPtr pScreenPriv; -+ rfbClientPtr cl, nextCl; -+ VNCSCREENPTR(pScreen); -+ -+ pScreenPriv -+ = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr; -+ if (!pCursor) -+ { -+ pScreenPriv->shouldBeUp = FALSE; -+ if (pVNC->cursorIsDrawn) -+ rfbSpriteRemoveCursor (pScreen); -+ pScreenPriv->pCursor = 0; -+ return; -+ } -+ pScreenPriv->shouldBeUp = TRUE; -+ if (pScreenPriv->x == x && -+ pScreenPriv->y == y && -+ pScreenPriv->pCursor == pCursor && -+ !pScreenPriv->checkPixels) -+ { -+ return; -+ } -+ pScreenPriv->x = x; -+ pScreenPriv->y = y; -+ pScreenPriv->pCacheWin = NullWindow; -+ if (pScreenPriv->checkPixels || pScreenPriv->pCursor != pCursor) -+ { -+ pScreenPriv->pCursor = pCursor; -+ rfbSpriteFindColors (pScreen); -+ } -+ if (pVNC->cursorIsDrawn) { -+ int sx, sy; -+ /* -+ * check to see if the old saved region -+ * encloses the new sprite, in which case we use -+ * the flicker-free MoveCursor primitive. -+ */ -+ sx = pScreenPriv->x - (int)pCursor->bits->xhot; -+ sy = pScreenPriv->y - (int)pCursor->bits->yhot; -+ if (sx + (int) pCursor->bits->width >= pScreenPriv->saved.x1 && -+ sx < pScreenPriv->saved.x2 && -+ sy + (int) pCursor->bits->height >= pScreenPriv->saved.y1 && -+ sy < pScreenPriv->saved.y2 && -+ (int) pCursor->bits->width + (2 * SPRITE_PAD) == -+ pScreenPriv->saved.x2 - pScreenPriv->saved.x1 && -+ (int) pCursor->bits->height + (2 * SPRITE_PAD) == -+ pScreenPriv->saved.y2 - pScreenPriv->saved.y1 -+ ) -+ { -+ pVNC->cursorIsDrawn = FALSE; -+ if (!(sx >= pScreenPriv->saved.x1 && -+ sx + (int)pCursor->bits->width < pScreenPriv->saved.x2 && -+ sy >= pScreenPriv->saved.y1 && -+ sy + (int)pCursor->bits->height < pScreenPriv->saved.y2)) -+ { -+ int oldx1, oldy1, dx, dy; -+ -+ oldx1 = pScreenPriv->saved.x1; -+ oldy1 = pScreenPriv->saved.y1; -+ dx = oldx1 - (sx - SPRITE_PAD); -+ dy = oldy1 - (sy - SPRITE_PAD); -+ pScreenPriv->saved.x1 -= dx; -+ pScreenPriv->saved.y1 -= dy; -+ pScreenPriv->saved.x2 -= dx; -+ pScreenPriv->saved.y2 -= dy; -+ (void) (*pScreenPriv->funcs->ChangeSave) (pScreen, -+ pScreenPriv->saved.x1, -+ pScreenPriv->saved.y1, -+ pScreenPriv->saved.x2 - pScreenPriv->saved.x1, -+ pScreenPriv->saved.y2 - pScreenPriv->saved.y1, -+ dx, dy); -+ } -+ (void) (*pScreenPriv->funcs->MoveCursor) (pScreen, pCursor, -+ pScreenPriv->saved.x1, -+ pScreenPriv->saved.y1, -+ pScreenPriv->saved.x2 - pScreenPriv->saved.x1, -+ pScreenPriv->saved.y2 - pScreenPriv->saved.y1, -+ sx - pScreenPriv->saved.x1, -+ sy - pScreenPriv->saved.y1, -+ pScreenPriv->colors[SOURCE_COLOR].pixel, -+ pScreenPriv->colors[MASK_COLOR].pixel); -+ pVNC->cursorIsDrawn = TRUE; -+ } -+ else -+ { -+ rfbSpriteRemoveCursor (pScreen); -+ } -+ } -+#if 0 -+ if (!pVNC->cursorIsDrawn && pScreenPriv->pCursor) -+ rfbSpriteRestoreCursor (pScreen); -+#endif -+ if (pVNC->cursorIsDrawn) -+ rfbSpriteRemoveCursor (pScreen); -+ -+ for (cl = rfbClientHead; cl; cl = nextCl) { -+ nextCl = cl->next; -+ if (cl->enableCursorPosUpdates) { -+ if (x == cl->cursorX && y == cl->cursorY) { -+ cl->cursorWasMoved = FALSE; -+ continue; -+ } -+ cl->cursorWasMoved = TRUE; -+ } -+ if (REGION_NOTEMPTY(pScreen,&cl->requestedRegion)) { -+ /* cursorIsDrawn is guaranteed to be FALSE here, so we definitely -+ want to send a screen update to the client, even if that's only -+ putting up the cursor */ -+ rfbSendFramebufferUpdate(pScreen, cl); -+ } -+ } -+} -+ -+static void -+rfbSpriteMoveCursor (pScreen, x, y) -+ ScreenPtr pScreen; -+ int x, y; -+{ -+ rfbSpriteScreenPtr pScreenPriv; -+ -+ pScreenPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr; -+ rfbSpriteSetCursor (pScreen, pScreenPriv->pCursor, x, y); -+} -+ -+/* -+ * undraw/draw cursor -+ */ -+ -+void -+rfbSpriteRemoveCursor (pScreen) -+ ScreenPtr pScreen; -+{ -+ rfbSpriteScreenPtr pScreenPriv; -+ VNCSCREENPTR(pScreen); -+ -+ if (!pVNC->cursorIsDrawn) -+ return; -+ -+ pScreenPriv -+ = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr; -+ -+ pVNC->dontSendFramebufferUpdate = TRUE; -+ pVNC->cursorIsDrawn = FALSE; -+ pScreenPriv->pCacheWin = NullWindow; -+ if (!(*pScreenPriv->funcs->RestoreUnderCursor) (pScreen, -+ pScreenPriv->saved.x1, -+ pScreenPriv->saved.y1, -+ pScreenPriv->saved.x2 - pScreenPriv->saved.x1, -+ pScreenPriv->saved.y2 - pScreenPriv->saved.y1)) -+ { -+ pVNC->cursorIsDrawn = TRUE; -+ } -+ pVNC->dontSendFramebufferUpdate = FALSE; -+} -+ -+ -+void -+rfbSpriteRestoreCursor (pScreen) -+ ScreenPtr pScreen; -+{ -+ rfbSpriteScreenPtr pScreenPriv; -+ int x, y; -+ CursorPtr pCursor; -+ VNCSCREENPTR(pScreen); -+ -+ pScreenPriv -+ = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr; -+ pCursor = pScreenPriv->pCursor; -+ -+ if (pVNC->cursorIsDrawn || !pCursor) -+ return; -+ -+ pVNC->dontSendFramebufferUpdate = TRUE; -+ -+ rfbSpriteComputeSaved (pScreen); -+ -+ x = pScreenPriv->x - (int)pCursor->bits->xhot; -+ y = pScreenPriv->y - (int)pCursor->bits->yhot; -+ if ((*pScreenPriv->funcs->SaveUnderCursor) (pScreen, -+ pScreenPriv->saved.x1, -+ pScreenPriv->saved.y1, -+ pScreenPriv->saved.x2 - pScreenPriv->saved.x1, -+ pScreenPriv->saved.y2 - pScreenPriv->saved.y1)) -+ { -+ if (pScreenPriv->checkPixels) -+ rfbSpriteFindColors (pScreen); -+ if ((*pScreenPriv->funcs->PutUpCursor) (pScreen, pCursor, x, y, -+ pScreenPriv->colors[SOURCE_COLOR].pixel, -+ pScreenPriv->colors[MASK_COLOR].pixel)) -+ pVNC->cursorIsDrawn = TRUE; -+ } -+ -+ pVNC->dontSendFramebufferUpdate = FALSE; -+} -+ -+/* -+ * compute the desired area of the screen to save -+ */ -+ -+static void -+rfbSpriteComputeSaved (pScreen) -+ ScreenPtr pScreen; -+{ -+ rfbSpriteScreenPtr pScreenPriv; -+ int x, y, w, h; -+ int wpad, hpad; -+ CursorPtr pCursor; -+ -+ pScreenPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr; -+ pCursor = pScreenPriv->pCursor; -+ x = pScreenPriv->x - (int)pCursor->bits->xhot; -+ y = pScreenPriv->y - (int)pCursor->bits->yhot; -+ w = pCursor->bits->width; -+ h = pCursor->bits->height; -+ wpad = SPRITE_PAD; -+ hpad = SPRITE_PAD; -+ pScreenPriv->saved.x1 = x - wpad; -+ pScreenPriv->saved.y1 = y - hpad; -+ pScreenPriv->saved.x2 = pScreenPriv->saved.x1 + w + wpad * 2; -+ pScreenPriv->saved.y2 = pScreenPriv->saved.y1 + h + hpad * 2; -+} -+ -+ -+/* -+ * this function is called when the cursor shape is being changed -+ */ -+ -+static Bool -+rfbDisplayCursor(pScreen, pCursor) -+ ScreenPtr pScreen; -+ CursorPtr pCursor; -+{ -+ rfbClientPtr cl; -+ rfbSpriteScreenPtr pPriv; -+ -+ for (cl = rfbClientHead; cl ; cl = cl->next) { -+ if (cl->enableCursorShapeUpdates) -+ cl->cursorWasChanged = TRUE; -+ } -+ -+ pPriv = (rfbSpriteScreenPtr)pScreen->devPrivates[rfbSpriteScreenIndex].ptr; -+ return (*pPriv->DisplayCursor)(pScreen, pCursor); -+} -+ -+ -+/* -+ * obtain current cursor pointer -+ */ -+ -+CursorPtr -+rfbSpriteGetCursorPtr (pScreen) -+ ScreenPtr pScreen; -+{ -+ rfbSpriteScreenPtr pScreenPriv; -+ -+ pScreenPriv = (rfbSpriteScreenPtr) -+ pScreen->devPrivates[rfbSpriteScreenIndex].ptr; -+ -+ return pScreenPriv->pCursor; -+} -+ -+/* -+ * obtain current cursor position -+ */ -+ -+void -+rfbSpriteGetCursorPos (pScreen, px, py) -+ ScreenPtr pScreen; -+ int *px, *py; -+{ -+ rfbSpriteScreenPtr pScreenPriv; -+ -+ pScreenPriv = (rfbSpriteScreenPtr) -+ pScreen->devPrivates[rfbSpriteScreenIndex].ptr; -+ -+ *px = pScreenPriv->x; -+ *py = pScreenPriv->y; -+} -+ -diff --git a/hw/vnc/sprite.h b/hw/vnc/sprite.h -new file mode 100644 -index 0000000..ed34726 ---- /dev/null -+++ b/hw/vnc/sprite.h -@@ -0,0 +1,141 @@ -+/* -+ * sprite.h -+ * -+ * software-sprite/sprite drawing - based on misprite -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ */ -+ -+/* -+ * 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) 1989 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. -+*/ -+ -+typedef struct { -+ Bool (*RealizeCursor)( -+ ScreenPtr /*pScreen*/, -+ CursorPtr /*pCursor*/ -+); -+ Bool (*UnrealizeCursor)( -+ ScreenPtr /*pScreen*/, -+ CursorPtr /*pCursor*/ -+); -+ Bool (*PutUpCursor)( -+ ScreenPtr /*pScreen*/, -+ CursorPtr /*pCursor*/, -+ int /*x*/, -+ int /*y*/, -+ unsigned long /*source*/, -+ unsigned long /*mask*/ -+); -+ Bool (*SaveUnderCursor)( -+ ScreenPtr /*pScreen*/, -+ int /*x*/, -+ int /*y*/, -+ int /*w*/, -+ int /*h*/ -+); -+ Bool (*RestoreUnderCursor)( -+ ScreenPtr /*pScreen*/, -+ int /*x*/, -+ int /*y*/, -+ int /*w*/, -+ int /*h*/ -+); -+ Bool (*MoveCursor)( -+ ScreenPtr /*pScreen*/, -+ CursorPtr /*pCursor*/, -+ int /*x*/, -+ int /*y*/, -+ int /*w*/, -+ int /*h*/, -+ int /*dx*/, -+ int /*dy*/, -+ unsigned long /*source*/, -+ unsigned long /*mask*/ -+); -+ Bool (*ChangeSave)( -+ ScreenPtr /*pScreen*/, -+ int /*x*/, -+ int /*y*/, -+ int /*w*/, -+ int /*h*/, -+ int /*dx*/, -+ int /*dy*/ -+); -+ -+} rfbSpriteCursorFuncRec, *rfbSpriteCursorFuncPtr; -+ -+extern Bool rfbSpriteInitialize( -+#if NeedFunctionPrototypes -+ ScreenPtr /*pScreen*/, -+ rfbSpriteCursorFuncPtr /*cursorFuncs*/, -+ miPointerScreenFuncPtr /*screenFuncs*/ -+#endif -+); -+ -+extern void rfbSpriteRestoreCursor( -+#if NeedFunctionPrototypes -+ ScreenPtr /*pScreen*/ -+#endif -+); -+ -+extern void rfbSpriteRemoveCursor( -+#if NeedFunctionPrototypes -+ ScreenPtr /*pScreen*/ -+#endif -+); -+ -+extern CursorPtr rfbSpriteGetCursorPtr( -+#if NeedFunctionPrototypes -+ ScreenPtr /*pScreen*/ -+#endif -+); -+ -+extern void rfbSpriteGetCursorPos( -+#if NeedFunctionPrototypes -+ ScreenPtr /*pScreen*/, -+ int * /*px*/, -+ int * /*py*/ -+#endif -+); -diff --git a/hw/vnc/spritest.h b/hw/vnc/spritest.h -new file mode 100644 -index 0000000..8593ee0 ---- /dev/null -+++ b/hw/vnc/spritest.h -@@ -0,0 +1,138 @@ -+/* -+ * spritest.h -+ * -+ * sprite structures - based on misprite -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ */ -+ -+/* -+ * 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) 1989 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 "sprite.h" -+ -+#ifdef RENDER -+# include "picturestr.h" -+#endif -+ -+/* -+ * per screen information -+ */ -+ -+typedef struct { -+ CloseScreenProcPtr CloseScreen; -+ GetImageProcPtr GetImage; -+ GetSpansProcPtr GetSpans; -+ SourceValidateProcPtr SourceValidate; -+ CreateGCProcPtr CreateGC; -+ ScreenBlockHandlerProcPtr BlockHandler; -+ InstallColormapProcPtr InstallColormap; -+ StoreColorsProcPtr StoreColors; -+ PaintWindowBackgroundProcPtr PaintWindowBackground; -+ PaintWindowBorderProcPtr PaintWindowBorder; -+ CopyWindowProcPtr CopyWindow; -+ ClearToBackgroundProcPtr ClearToBackground; -+ SaveDoomedAreasProcPtr SaveDoomedAreas; -+ RestoreAreasProcPtr RestoreAreas; -+ DisplayCursorProcPtr DisplayCursor; -+#ifdef RENDER -+ CompositeProcPtr Composite; -+ GlyphsProcPtr Glyphs; -+#endif -+ -+ CursorPtr pCursor; -+ int x; -+ int y; -+ Bool shouldBeUp; -+ BoxRec saved; -+ WindowPtr pCacheWin; -+ Bool isInCacheWin; -+ Bool checkPixels; -+ xColorItem colors[2]; -+ ColormapPtr pInstalledMap; -+ ColormapPtr pColormap; -+ VisualPtr pVisual; -+ rfbSpriteCursorFuncPtr funcs; -+} rfbSpriteScreenRec, *rfbSpriteScreenPtr; -+ -+#define SOURCE_COLOR 0 -+#define MASK_COLOR 1 -+ -+typedef struct { -+ GCFuncs *wrapFuncs; -+ GCOps *wrapOps; -+} rfbSpriteGCRec, *rfbSpriteGCPtr; -+ -+/* -+ * Overlap BoxPtr and Box elements -+ */ -+#define BOX_OVERLAP(pCbox,X1,Y1,X2,Y2) \ -+ (((pCbox)->x1 <= (X2)) && ((X1) <= (pCbox)->x2) && \ -+ ((pCbox)->y1 <= (Y2)) && ((Y1) <= (pCbox)->y2)) -+ -+/* -+ * Overlap BoxPtr, origins, and rectangle -+ */ -+#define ORG_OVERLAP(pCbox,xorg,yorg,x,y,w,h) \ -+ BOX_OVERLAP((pCbox),(x)+(xorg),(y)+(yorg),(x)+(xorg)+(w),(y)+(yorg)+(h)) -+ -+/* -+ * Overlap BoxPtr, origins and RectPtr -+ */ -+#define ORGRECT_OVERLAP(pCbox,xorg,yorg,pRect) \ -+ ORG_OVERLAP((pCbox),(xorg),(yorg),(pRect)->x,(pRect)->y, \ -+ (int)((pRect)->width), (int)((pRect)->height)) -+/* -+ * Overlap BoxPtr and horizontal span -+ */ -+#define SPN_OVERLAP(pCbox,y,x,w) BOX_OVERLAP((pCbox),(x),(y),(x)+(w),(y)) -+ -+#define LINE_SORT(x1,y1,x2,y2) \ -+{ int _t; \ -+ if (x1 > x2) { _t = x1; x1 = x2; x2 = _t; } \ -+ if (y1 > y2) { _t = y1; y1 = y2; y2 = _t; } } -+ -+#define LINE_OVERLAP(pCbox,x1,y1,x2,y2,lw2) \ -+ BOX_OVERLAP((pCbox), (x1)-(lw2), (y1)-(lw2), (x2)+(lw2), (y2)+(lw2)) -diff --git a/hw/vnc/stats.c b/hw/vnc/stats.c -new file mode 100644 -index 0000000..53017ee ---- /dev/null -+++ b/hw/vnc/stats.c -@@ -0,0 +1,113 @@ -+/* -+ * stats.c -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ */ -+ -+/* -+ * Copyright (C) 2002 Constantin Kaplinsky. All Rights Reserved. -+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. -+ * -+ * This is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This software is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this software; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -+ * USA. -+ */ -+ -+#include -+#include -+#include "rfb.h" -+ -+static char* encNames[] = { -+ "raw", "copyRect", "RRE", "[encoding 3]", "CoRRE", "hextile", -+ "zlib", "tight", "[encoding 8]", "[encoding 9]" -+}; -+ -+ -+void -+rfbResetStats(rfbClientPtr cl) -+{ -+ int i; -+ for (i = 0; i < MAX_ENCODINGS; i++) { -+ cl->rfbBytesSent[i] = 0; -+ cl->rfbRectanglesSent[i] = 0; -+ } -+ cl->rfbLastRectMarkersSent = 0; -+ cl->rfbLastRectBytesSent = 0; -+ cl->rfbCursorShapeBytesSent = 0; -+ cl->rfbCursorShapeUpdatesSent = 0; -+ cl->rfbCursorPosBytesSent = 0; -+ cl->rfbCursorPosUpdatesSent = 0; -+ cl->rfbFramebufferUpdateMessagesSent = 0; -+ cl->rfbRawBytesEquivalent = 0; -+ cl->rfbKeyEventsRcvd = 0; -+ cl->rfbPointerEventsRcvd = 0; -+} -+ -+void -+rfbPrintStats(rfbClientPtr cl) -+{ -+ int i; -+ int totalRectanglesSent = 0; -+ int totalBytesSent = 0; -+ -+ rfbLog("Statistics:\n"); -+ -+ if ((cl->rfbKeyEventsRcvd != 0) || (cl->rfbPointerEventsRcvd != 0)) -+ rfbLog(" key events received %d, pointer events %d\n", -+ cl->rfbKeyEventsRcvd, cl->rfbPointerEventsRcvd); -+ -+ for (i = 0; i < MAX_ENCODINGS; i++) { -+ totalRectanglesSent += cl->rfbRectanglesSent[i]; -+ totalBytesSent += cl->rfbBytesSent[i]; -+ } -+ totalRectanglesSent += (cl->rfbCursorShapeUpdatesSent + -+ cl->rfbCursorPosUpdatesSent + -+ cl->rfbLastRectMarkersSent); -+ totalBytesSent += (cl->rfbCursorShapeBytesSent + -+ cl->rfbCursorPosBytesSent + -+ cl->rfbLastRectBytesSent); -+ -+ rfbLog(" framebuffer updates %d, rectangles %d, bytes %d\n", -+ cl->rfbFramebufferUpdateMessagesSent, totalRectanglesSent, -+ totalBytesSent); -+ -+ if (cl->rfbLastRectMarkersSent != 0) -+ rfbLog(" LastRect markers %d, bytes %d\n", -+ cl->rfbLastRectMarkersSent, cl->rfbLastRectBytesSent); -+ -+ if (cl->rfbCursorShapeUpdatesSent != 0) -+ rfbLog(" cursor shape updates %d, bytes %d\n", -+ cl->rfbCursorShapeUpdatesSent, cl->rfbCursorShapeBytesSent); -+ -+ if (cl->rfbCursorPosUpdatesSent != 0) -+ rfbLog(" cursor position updates %d, bytes %d\n", -+ cl->rfbCursorPosUpdatesSent, cl->rfbCursorPosBytesSent); -+ -+ for (i = 0; i < MAX_ENCODINGS; i++) { -+ if (cl->rfbRectanglesSent[i] != 0) -+ rfbLog(" %s rectangles %d, bytes %d\n", -+ encNames[i], cl->rfbRectanglesSent[i], cl->rfbBytesSent[i]); -+ } -+ -+ if ((totalBytesSent - cl->rfbBytesSent[rfbEncodingCopyRect]) != 0) { -+ rfbLog(" raw bytes equivalent %d, compression ratio %f\n", -+ cl->rfbRawBytesEquivalent, -+ (double)cl->rfbRawBytesEquivalent -+ / (double)(totalBytesSent - -+ cl->rfbBytesSent[rfbEncodingCopyRect] - -+ cl->rfbCursorShapeBytesSent - -+ cl->rfbCursorPosBytesSent - -+ cl->rfbLastRectBytesSent)); -+ } -+} -diff --git a/hw/vnc/tableinitcmtemplate.c b/hw/vnc/tableinitcmtemplate.c -new file mode 100644 -index 0000000..8a757e5 ---- /dev/null -+++ b/hw/vnc/tableinitcmtemplate.c -@@ -0,0 +1,89 @@ -+/* -+ * tableinitcmtemplate.c - template for initialising lookup tables for -+ * translation from a colour map to true colour. -+ * -+ * This file shouldn't be compiled. It is included multiple times by -+ * translate.c, each time with a different definition of the macro OUT. -+ * For each value of OUT, this file defines a function which allocates an -+ * appropriately sized lookup table and initialises it. -+ * -+ * I know this code isn't nice to read because of all the macros, but -+ * efficiency is important here. -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ */ -+ -+/* -+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. -+ * -+ * This is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This software is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this software; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -+ * USA. -+ */ -+ -+#if !defined(OUT) -+#error "This file shouldn't be compiled." -+#error "It is included as part of translate.c" -+#endif -+ -+#define OUT_T CONCAT2E(CARD,OUT) -+#define SwapOUT(x) CONCAT2E(Swap,OUT(x)) -+#define rfbInitColourMapSingleTableOUT \ -+ CONCAT2E(rfbInitColourMapSingleTable,OUT) -+ -+static void -+rfbInitColourMapSingleTableOUT (ScreenPtr pScreen, char **table, rfbPixelFormat *in, -+ rfbPixelFormat *out) -+{ -+ VNCSCREENPTR(pScreen); -+ int i, r, g, b; -+ OUT_T *t; -+ EntryPtr pent; -+ int nEntries = 1 << in->bitsPerPixel; -+ -+ if (*table) free(*table); -+ *table = (char *)malloc(nEntries * sizeof(OUT_T)); -+ t = (OUT_T *)*table; -+ -+#if XFREE86VNC -+ pent = (EntryPtr)&miInstalledMaps[pScreen->myNum]->red[0]; -+#else -+ pent = (EntryPtr)&pVNC->rfbInstalledColormap->red[0]; -+#endif -+ -+ for (i = 0; i < nEntries; i++) { -+ 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; -+ } -+ t[i] = ((((r * out->redMax + 32767) / 65535) << out->redShift) | -+ (((g * out->greenMax + 32767) / 65535) << out->greenShift) | -+ (((b * out->blueMax + 32767) / 65535) << out->blueShift)); -+#if (OUT != 8) -+ if (out->bigEndian != in->bigEndian) { -+ t[i] = SwapOUT(t[i]); -+ } -+#endif -+ pent++; -+ } -+} -+ -+#undef OUT_T -+#undef SwapOUT -+#undef rfbInitColourMapSingleTableOUT -diff --git a/hw/vnc/tableinittctemplate.c b/hw/vnc/tableinittctemplate.c -new file mode 100644 -index 0000000..da8ae01 ---- /dev/null -+++ b/hw/vnc/tableinittctemplate.c -@@ -0,0 +1,142 @@ -+/* -+ * tableinittctemplate.c - template for initialising lookup tables for -+ * truecolour to truecolour translation. -+ * -+ * This file shouldn't be compiled. It is included multiple times by -+ * translate.c, each time with a different definition of the macro OUT. -+ * For each value of OUT, this file defines two functions for initialising -+ * lookup tables. One is for truecolour translation using a single lookup -+ * table, the other is for truecolour translation using three separate -+ * lookup tables for the red, green and blue values. -+ * -+ * I know this code isn't nice to read because of all the macros, but -+ * efficiency is important here. -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ */ -+ -+/* -+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. -+ * -+ * This is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This software is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this software; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -+ * USA. -+ */ -+ -+#if !defined(OUT) -+#error "This file shouldn't be compiled." -+#error "It is included as part of translate.c" -+#endif -+ -+#define OUT_T CONCAT2E(CARD,OUT) -+#define SwapOUT(x) CONCAT2E(Swap,OUT(x)) -+#define rfbInitTrueColourSingleTableOUT \ -+ CONCAT2E(rfbInitTrueColourSingleTable,OUT) -+#define rfbInitTrueColourRGBTablesOUT CONCAT2E(rfbInitTrueColourRGBTables,OUT) -+#define rfbInitOneRGBTableOUT CONCAT2E(rfbInitOneRGBTable,OUT) -+ -+static void -+rfbInitOneRGBTableOUT (OUT_T *table, int inMax, int outMax, int outShift, -+ int swap); -+ -+ -+/* -+ * rfbInitTrueColourSingleTable sets up a single lookup table for truecolour -+ * translation. -+ */ -+ -+static void -+rfbInitTrueColourSingleTableOUT (ScreenPtr pScreen, char **table, rfbPixelFormat *in, -+ rfbPixelFormat *out) -+{ -+ int i; -+ int inRed, inGreen, inBlue, outRed, outGreen, outBlue; -+ OUT_T *t; -+ int nEntries = 1 << in->bitsPerPixel; -+ -+ if (*table) free(*table); -+ *table = (char *)malloc(nEntries * sizeof(OUT_T)); -+ t = (OUT_T *)*table; -+ -+ for (i = 0; i < nEntries; i++) { -+ inRed = (i >> in->redShift) & in->redMax; -+ inGreen = (i >> in->greenShift) & in->greenMax; -+ inBlue = (i >> in->blueShift) & in->blueMax; -+ -+ outRed = (inRed * out->redMax + in->redMax / 2) / in->redMax; -+ outGreen = (inGreen * out->greenMax + in->greenMax / 2) / in->greenMax; -+ outBlue = (inBlue * out->blueMax + in->blueMax / 2) / in->blueMax; -+ -+ t[i] = ((outRed << out->redShift) | -+ (outGreen << out->greenShift) | -+ (outBlue << out->blueShift)); -+#if (OUT != 8) -+ if (out->bigEndian != in->bigEndian) { -+ t[i] = SwapOUT(t[i]); -+ } -+#endif -+ } -+} -+ -+ -+/* -+ * rfbInitTrueColourRGBTables sets up three separate lookup tables for the -+ * red, green and blue values. -+ */ -+ -+static void -+rfbInitTrueColourRGBTablesOUT (ScreenPtr pScreen, char **table, rfbPixelFormat *in, -+ rfbPixelFormat *out) -+{ -+ OUT_T *redTable; -+ OUT_T *greenTable; -+ OUT_T *blueTable; -+ -+ if (*table) free(*table); -+ *table = (char *)malloc((in->redMax + in->greenMax + in->blueMax + 3) -+ * sizeof(OUT_T)); -+ redTable = (OUT_T *)*table; -+ greenTable = redTable + in->redMax + 1; -+ blueTable = greenTable + in->greenMax + 1; -+ -+ rfbInitOneRGBTableOUT (redTable, in->redMax, out->redMax, -+ out->redShift, (out->bigEndian != in->bigEndian)); -+ rfbInitOneRGBTableOUT (greenTable, in->greenMax, out->greenMax, -+ out->greenShift, (out->bigEndian != in->bigEndian)); -+ rfbInitOneRGBTableOUT (blueTable, in->blueMax, out->blueMax, -+ out->blueShift, (out->bigEndian != in->bigEndian)); -+} -+ -+static void -+rfbInitOneRGBTableOUT (OUT_T *table, int inMax, int outMax, int outShift, -+ int swap) -+{ -+ int i; -+ int nEntries = inMax + 1; -+ -+ for (i = 0; i < nEntries; i++) { -+ table[i] = ((i * outMax + inMax / 2) / inMax) << outShift; -+#if (OUT != 8) -+ if (swap) { -+ table[i] = SwapOUT(table[i]); -+ } -+#endif -+ } -+} -+ -+#undef OUT_T -+#undef SwapOUT -+#undef rfbInitTrueColourSingleTableOUT -+#undef rfbInitTrueColourRGBTablesOUT -+#undef rfbInitOneRGBTableOUT -diff --git a/hw/vnc/tabletranstemplate.c b/hw/vnc/tabletranstemplate.c -new file mode 100644 -index 0000000..87cfcba ---- /dev/null -+++ b/hw/vnc/tabletranstemplate.c -@@ -0,0 +1,119 @@ -+/* -+ * tabletranstemplate.c - template for translation using lookup tables. -+ * -+ * This file shouldn't be compiled. It is included multiple times by -+ * translate.c, each time with different definitions of the macros IN and OUT. -+ * -+ * For each pair of values IN and OUT, this file defines two functions for -+ * translating a given rectangle of pixel data. One uses a single lookup -+ * table, and the other uses three separate lookup tables for the red, green -+ * and blue values. -+ * -+ * I know this code isn't nice to read because of all the macros, but -+ * efficiency is important here. -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ */ -+ -+/* -+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. -+ * -+ * This is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This software is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this software; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -+ * USA. -+ */ -+ -+#if !defined(IN) || !defined(OUT) -+#error "This file shouldn't be compiled." -+#error "It is included as part of translate.c" -+#endif -+ -+#define IN_T CONCAT2E(CARD,IN) -+#define OUT_T CONCAT2E(CARD,OUT) -+#define rfbTranslateWithSingleTableINtoOUT \ -+ CONCAT4E(rfbTranslateWithSingleTable,IN,to,OUT) -+#define rfbTranslateWithRGBTablesINtoOUT \ -+ CONCAT4E(rfbTranslateWithRGBTables,IN,to,OUT) -+ -+/* -+ * rfbTranslateWithSingleTableINtoOUT translates a rectangle of pixel data -+ * using a single lookup table. -+ */ -+ -+static void -+rfbTranslateWithSingleTableINtoOUT (ScreenPtr pScreen, char *table, rfbPixelFormat *in, -+ rfbPixelFormat *out, -+ unsigned char *iptr, char *optr, -+ int bytesBetweenInputLines, -+ int width, int height, -+ int x, int y) -+{ -+ IN_T *ip = (IN_T *)iptr; -+ OUT_T *op = (OUT_T *)optr; -+ int ipextra = bytesBetweenInputLines / sizeof(IN_T) - width; -+ OUT_T *opLineEnd; -+ OUT_T *t = (OUT_T *)table; -+ -+ while (height > 0) { -+ opLineEnd = op + width; -+ -+ while (op < opLineEnd) { -+ *(op++) = t[*(ip++)]; -+ } -+ -+ ip += ipextra; -+ height--; -+ } -+} -+ -+ -+/* -+ * rfbTranslateWithRGBTablesINtoOUT translates a rectangle of pixel data -+ * using three separate lookup tables for the red, green and blue values. -+ */ -+ -+static void -+rfbTranslateWithRGBTablesINtoOUT (ScreenPtr pScreen, char *table, rfbPixelFormat *in, -+ rfbPixelFormat *out, -+ unsigned char *iptr, char *optr, -+ int bytesBetweenInputLines, -+ int width, int height, -+ int x, int y) -+{ -+ IN_T *ip = (IN_T *)iptr; -+ OUT_T *op = (OUT_T *)optr; -+ int ipextra = bytesBetweenInputLines / sizeof(IN_T) - width; -+ OUT_T *opLineEnd; -+ OUT_T *redTable = (OUT_T *)table; -+ OUT_T *greenTable = redTable + in->redMax + 1; -+ OUT_T *blueTable = greenTable + in->greenMax + 1; -+ -+ while (height > 0) { -+ opLineEnd = op + width; -+ -+ while (op < opLineEnd) { -+ *(op++) = (redTable[(*ip >> in->redShift) & in->redMax] | -+ greenTable[(*ip >> in->greenShift) & in->greenMax] | -+ blueTable[(*ip >> in->blueShift) & in->blueMax]); -+ ip++; -+ } -+ ip += ipextra; -+ height--; -+ } -+} -+ -+#undef IN_T -+#undef OUT_T -+#undef rfbTranslateWithSingleTableINtoOUT -+#undef rfbTranslateWithRGBTablesINtoOUT -diff --git a/hw/vnc/tight.c b/hw/vnc/tight.c -new file mode 100644 -index 0000000..d14b2ce ---- /dev/null -+++ b/hw/vnc/tight.c -@@ -0,0 +1,1824 @@ -+/* -+ * tight.c -+ * -+ * Routines to implement Tight Encoding -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ */ -+ -+/* -+ * Copyright (C) 2000, 2001 Const Kaplinsky. All Rights Reserved. -+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. -+ * -+ * This is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This software is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this software; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -+ * USA. -+ */ -+ -+#include -+#include "rfb.h" -+#include -+ -+ -+/* Note: The following constant should not be changed. */ -+#define TIGHT_MIN_TO_COMPRESS 12 -+ -+/* The parameters below may be adjusted. */ -+#define MIN_SPLIT_RECT_SIZE 4096 -+#define MIN_SOLID_SUBRECT_SIZE 2048 -+#define MAX_SPLIT_TILE_SIZE 16 -+ -+/* May be set to TRUE with "-lazytight" Xvnc option. */ -+Bool rfbTightDisableGradient = FALSE; -+ -+/* This variable is set on every rfbSendRectEncodingTight() call. */ -+static Bool usePixelFormat24; -+ -+ -+/* Compression level stuff. The following array contains various -+ encoder parameters for each of 10 compression levels (0..9). -+ Last three parameters correspond to JPEG quality levels (0..9). */ -+ -+typedef struct TIGHT_CONF_s { -+ int maxRectSize, maxRectWidth; -+ int monoMinRectSize, gradientMinRectSize; -+ int idxZlibLevel, monoZlibLevel, rawZlibLevel, gradientZlibLevel; -+ int gradientThreshold, gradientThreshold24; -+ int idxMaxColorsDivisor; -+ int jpegQuality, jpegThreshold, jpegThreshold24; -+} TIGHT_CONF; -+ -+static TIGHT_CONF tightConf[10] = { -+ { 512, 32, 6, 65536, 0, 0, 0, 0, 0, 0, 4, 5, 10000, 23000 }, -+ { 2048, 128, 6, 65536, 1, 1, 1, 0, 0, 0, 8, 10, 8000, 18000 }, -+ { 6144, 256, 8, 65536, 3, 3, 2, 0, 0, 0, 24, 15, 6500, 15000 }, -+ { 10240, 1024, 12, 65536, 5, 5, 3, 0, 0, 0, 32, 25, 5000, 12000 }, -+ { 16384, 2048, 12, 65536, 6, 6, 4, 0, 0, 0, 32, 37, 4000, 10000 }, -+ { 32768, 2048, 12, 4096, 7, 7, 5, 4, 150, 380, 32, 50, 3000, 8000 }, -+ { 65536, 2048, 16, 4096, 7, 7, 6, 4, 170, 420, 48, 60, 2000, 5000 }, -+ { 65536, 2048, 16, 4096, 8, 8, 7, 5, 180, 450, 64, 70, 1000, 2500 }, -+ { 65536, 2048, 32, 8192, 9, 9, 8, 6, 190, 475, 64, 75, 500, 1200 }, -+ { 65536, 2048, 32, 8192, 9, 9, 9, 6, 200, 500, 96, 80, 200, 500 } -+}; -+ -+/* Stuff dealing with palettes. */ -+ -+typedef struct COLOR_LIST_s { -+ struct COLOR_LIST_s *next; -+ int idx; -+ CARD32 rgb; -+} COLOR_LIST; -+ -+typedef struct PALETTE_ENTRY_s { -+ COLOR_LIST *listNode; -+ int numPixels; -+} PALETTE_ENTRY; -+ -+typedef struct PALETTE_s { -+ PALETTE_ENTRY entry[256]; -+ COLOR_LIST *hash[256]; -+ COLOR_LIST list[256]; -+} PALETTE; -+ -+static int paletteNumColors, paletteMaxColors; -+static CARD32 monoBackground, monoForeground; -+static PALETTE palette; -+ -+/* Pointers to dynamically-allocated buffers. */ -+ -+static int tightBeforeBufSize = 0; -+static char *tightBeforeBuf = NULL; -+ -+static int tightAfterBufSize = 0; -+static char *tightAfterBuf = NULL; -+ -+static int *prevRowBuf = NULL; -+ -+ -+/* Prototypes for static functions. */ -+ -+static void FindBestSolidArea (ScreenPtr pScreen, int x, int y, int w, int h, -+ CARD32 colorValue, int *w_ptr, int *h_ptr); -+static void ExtendSolidArea (ScreenPtr pScreen, int x, int y, int w, int h, -+ CARD32 colorValue, -+ int *x_ptr, int *y_ptr, int *w_ptr, int *h_ptr); -+static Bool CheckSolidTile (ScreenPtr pScreen, int x, int y, int w, int h, -+ CARD32 *colorPtr, Bool needSameColor); -+static Bool CheckSolidTile8 (ScreenPtr pScreen, int x, int y, int w, int h, -+ CARD32 *colorPtr, Bool needSameColor); -+static Bool CheckSolidTile16 (ScreenPtr pScreen, int x, int y, int w, int h, -+ CARD32 *colorPtr, Bool needSameColor); -+static Bool CheckSolidTile32 (ScreenPtr pScreen, int x, int y, int w, int h, -+ CARD32 *colorPtr, Bool needSameColor); -+ -+static Bool SendRectSimple (rfbClientPtr cl, int x, int y, int w, int h); -+static Bool SendSubrect (rfbClientPtr cl, int x, int y, int w, int h); -+static Bool SendTightHeader (rfbClientPtr cl, int x, int y, int w, int h); -+ -+static Bool SendSolidRect (rfbClientPtr cl); -+static Bool SendMonoRect (rfbClientPtr cl, int w, int h); -+static Bool SendIndexedRect (rfbClientPtr cl, int w, int h); -+static Bool SendFullColorRect (rfbClientPtr cl, int w, int h); -+static Bool SendGradientRect (rfbClientPtr cl, int w, int h); -+ -+static Bool CompressData(rfbClientPtr cl, int streamId, int dataLen, -+ int zlibLevel, int zlibStrategy); -+static Bool SendCompressedData(rfbClientPtr cl, int compressedLen); -+ -+static void FillPalette8(int count); -+static void FillPalette16(int count); -+static void FillPalette32(int count); -+ -+static void PaletteReset(void); -+static int PaletteInsert(CARD32 rgb, int numPixels, int bpp); -+ -+static void Pack24(ScreenPtr pScreen, char *buf, rfbPixelFormat *fmt, int count); -+ -+static void EncodeIndexedRect16(CARD8 *buf, int count); -+static void EncodeIndexedRect32(CARD8 *buf, int count); -+ -+static void EncodeMonoRect8(CARD8 *buf, int w, int h); -+static void EncodeMonoRect16(CARD8 *buf, int w, int h); -+static void EncodeMonoRect32(CARD8 *buf, int w, int h); -+ -+static void FilterGradient24(ScreenPtr pScreen, char *buf, rfbPixelFormat *fmt, int w, int h); -+static void FilterGradient16(ScreenPtr pScreen, CARD16 *buf, rfbPixelFormat *fmt, int w, int h); -+static void FilterGradient32(ScreenPtr pScreen, CARD32 *buf, rfbPixelFormat *fmt, int w, int h); -+ -+static int DetectSmoothImage(rfbClientPtr cl, rfbPixelFormat *fmt, int w, int h); -+static unsigned long DetectSmoothImage24(rfbClientPtr cl, rfbPixelFormat *fmt, int w, int h); -+static unsigned long DetectSmoothImage16(rfbClientPtr cl, rfbPixelFormat *fmt, int w, int h); -+static unsigned long DetectSmoothImage32(rfbClientPtr cl, rfbPixelFormat *fmt, int w, int h); -+ -+static Bool SendJpegRect(rfbClientPtr cl, int x, int y, int w, int h, -+ int quality); -+static void PrepareRowForJpeg(ScreenPtr pScreen, CARD8 *dst, int x, int y, int count); -+static void PrepareRowForJpeg24(ScreenPtr pScreen, CARD8 *dst, int x, int y, int count); -+static void PrepareRowForJpeg16(ScreenPtr pScreen, CARD8 *dst, int x, int y, int count); -+static void PrepareRowForJpeg32(ScreenPtr pScreen, CARD8 *dst, int x, int y, int count); -+ -+static void JpegInitDestination(j_compress_ptr cinfo); -+static boolean JpegEmptyOutputBuffer(j_compress_ptr cinfo); -+static void JpegTermDestination(j_compress_ptr cinfo); -+static void JpegSetDstManager(j_compress_ptr cinfo); -+ -+ -+/* -+ * Tight encoding implementation. -+ */ -+ -+int -+rfbNumCodedRectsTight(cl, x, y, w, h) -+ rfbClientPtr cl; -+ int x, y, w, h; -+{ -+ int maxRectSize, maxRectWidth; -+ int subrectMaxWidth, subrectMaxHeight; -+ -+ /* No matter how many rectangles we will send if LastRect markers -+ are used to terminate rectangle stream. */ -+ if (cl->enableLastRectEncoding && w * h >= MIN_SPLIT_RECT_SIZE) -+ return 0; -+ -+ maxRectSize = tightConf[cl->tightCompressLevel].maxRectSize; -+ maxRectWidth = tightConf[cl->tightCompressLevel].maxRectWidth; -+ -+ if (w > maxRectWidth || w * h > maxRectSize) { -+ subrectMaxWidth = (w > maxRectWidth) ? maxRectWidth : w; -+ subrectMaxHeight = maxRectSize / subrectMaxWidth; -+ return (((w - 1) / maxRectWidth + 1) * -+ ((h - 1) / subrectMaxHeight + 1)); -+ } else { -+ return 1; -+ } -+} -+ -+Bool -+rfbSendRectEncodingTight(cl, x, y, w, h) -+ rfbClientPtr cl; -+ int x, y, w, h; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ int nMaxRows; -+ CARD32 colorValue; -+ int dx, dy, dw, dh; -+ int x_best, y_best, w_best, h_best; -+ unsigned char *fbptr; -+ -+ if ( cl->format.depth == 24 && cl->format.redMax == 0xFF && -+ cl->format.greenMax == 0xFF && cl->format.blueMax == 0xFF ) { -+ usePixelFormat24 = TRUE; -+ } else { -+ usePixelFormat24 = FALSE; -+ } -+ -+ if (!cl->enableLastRectEncoding || w * h < MIN_SPLIT_RECT_SIZE) -+ return SendRectSimple(cl, x, y, w, h); -+ -+ /* Make sure we can write at least one pixel into tightBeforeBuf. */ -+ -+ if (tightBeforeBufSize < 4) { -+ tightBeforeBufSize = 4; -+ if (tightBeforeBuf == NULL) -+ tightBeforeBuf = (char *)xalloc(tightBeforeBufSize); -+ else -+ tightBeforeBuf = (char *)xrealloc(tightBeforeBuf, -+ tightBeforeBufSize); -+ } -+ -+ /* Calculate maximum number of rows in one non-solid rectangle. */ -+ -+ { -+ int maxRectSize, maxRectWidth, nMaxWidth; -+ -+ maxRectSize = tightConf[cl->tightCompressLevel].maxRectSize; -+ maxRectWidth = tightConf[cl->tightCompressLevel].maxRectWidth; -+ nMaxWidth = (w > maxRectWidth) ? maxRectWidth : w; -+ nMaxRows = maxRectSize / nMaxWidth; -+ } -+ -+ /* Try to find large solid-color areas and send them separately. */ -+ -+ for (dy = y; dy < y + h; dy += MAX_SPLIT_TILE_SIZE) { -+ -+ /* If a rectangle becomes too large, send its upper part now. */ -+ -+ if (dy - y >= nMaxRows) { -+ if (!SendRectSimple(cl, x, y, w, nMaxRows)) -+ return 0; -+ y += nMaxRows; -+ h -= nMaxRows; -+ } -+ -+ dh = (dy + MAX_SPLIT_TILE_SIZE <= y + h) ? -+ MAX_SPLIT_TILE_SIZE : (y + h - dy); -+ -+ for (dx = x; dx < x + w; dx += MAX_SPLIT_TILE_SIZE) { -+ -+ dw = (dx + MAX_SPLIT_TILE_SIZE <= x + w) ? -+ MAX_SPLIT_TILE_SIZE : (x + w - dx); -+ -+ if (CheckSolidTile(cl->pScreen, dx, dy, dw, dh, &colorValue, FALSE)) { -+ -+ /* Get dimensions of solid-color area. */ -+ -+ FindBestSolidArea(cl->pScreen, dx, dy, w - (dx - x), h - (dy - y), -+ colorValue, &w_best, &h_best); -+ -+ /* Make sure a solid rectangle is large enough -+ (or the whole rectangle is of the same color). */ -+ -+ if ( w_best * h_best != w * h && -+ w_best * h_best < MIN_SOLID_SUBRECT_SIZE ) -+ continue; -+ -+ /* Try to extend solid rectangle to maximum size. */ -+ -+ x_best = dx; y_best = dy; -+ ExtendSolidArea(cl->pScreen, x, y, w, h, colorValue, -+ &x_best, &y_best, &w_best, &h_best); -+ -+ /* Send rectangles at top and left to solid-color area. */ -+ -+ if ( y_best != y && -+ !SendRectSimple(cl, x, y, w, y_best-y) ) -+ return FALSE; -+ if ( x_best != x && -+ !rfbSendRectEncodingTight(cl, x, y_best, -+ x_best-x, h_best) ) -+ return FALSE; -+ -+ /* Send solid-color rectangle. */ -+ -+ if (!SendTightHeader(cl, x_best, y_best, w_best, h_best)) -+ return FALSE; -+ -+ fbptr = (pVNC->pfbMemory + -+ (pVNC->paddedWidthInBytes * y_best) + -+ (x_best * (pVNC->bitsPerPixel / 8))); -+ -+ (*cl->translateFn)(cl->pScreen, cl->translateLookupTable, -+ &pVNC->rfbServerFormat, -+ &cl->format, fbptr, tightBeforeBuf, -+ pVNC->paddedWidthInBytes, 1, 1, -+ x_best, y_best); -+ -+ if (!SendSolidRect(cl)) -+ return FALSE; -+ -+ /* Send remaining rectangles (at right and bottom). */ -+ -+ if ( x_best + w_best != x + w && -+ !rfbSendRectEncodingTight(cl, x_best+w_best, y_best, -+ w-(x_best-x)-w_best, h_best) ) -+ return FALSE; -+ if ( y_best + h_best != y + h && -+ !rfbSendRectEncodingTight(cl, x, y_best+h_best, -+ w, h-(y_best-y)-h_best) ) -+ return FALSE; -+ -+ /* Return after all recursive calls are done. */ -+ -+ return TRUE; -+ } -+ -+ } -+ -+ } -+ -+ /* No suitable solid-color rectangles found. */ -+ -+ return SendRectSimple(cl, x, y, w, h); -+} -+ -+static void -+FindBestSolidArea(pScreen, x, y, w, h, colorValue, w_ptr, h_ptr) -+ ScreenPtr pScreen; -+ int x, y, w, h; -+ CARD32 colorValue; -+ int *w_ptr, *h_ptr; -+{ -+ int dx, dy, dw, dh; -+ int w_prev; -+ int w_best = 0, h_best = 0; -+ -+ w_prev = w; -+ -+ for (dy = y; dy < y + h; dy += MAX_SPLIT_TILE_SIZE) { -+ -+ dh = (dy + MAX_SPLIT_TILE_SIZE <= y + h) ? -+ MAX_SPLIT_TILE_SIZE : (y + h - dy); -+ dw = (w_prev > MAX_SPLIT_TILE_SIZE) ? -+ MAX_SPLIT_TILE_SIZE : w_prev; -+ -+ if (!CheckSolidTile(pScreen, x, dy, dw, dh, &colorValue, TRUE)) -+ break; -+ -+ for (dx = x + dw; dx < x + w_prev;) { -+ dw = (dx + MAX_SPLIT_TILE_SIZE <= x + w_prev) ? -+ MAX_SPLIT_TILE_SIZE : (x + w_prev - dx); -+ if (!CheckSolidTile(pScreen, dx, dy, dw, dh, &colorValue, TRUE)) -+ break; -+ dx += dw; -+ } -+ -+ w_prev = dx - x; -+ if (w_prev * (dy + dh - y) > w_best * h_best) { -+ w_best = w_prev; -+ h_best = dy + dh - y; -+ } -+ } -+ -+ *w_ptr = w_best; -+ *h_ptr = h_best; -+} -+ -+static void -+ExtendSolidArea(pScreen, x, y, w, h, colorValue, x_ptr, y_ptr, w_ptr, h_ptr) -+ ScreenPtr pScreen; -+ int x, y, w, h; -+ CARD32 colorValue; -+ int *x_ptr, *y_ptr, *w_ptr, *h_ptr; -+{ -+ int cx, cy; -+ -+ /* Try to extend the area upwards. */ -+ for ( cy = *y_ptr - 1; -+ cy >= y && CheckSolidTile(pScreen, *x_ptr, cy, *w_ptr, 1, &colorValue, TRUE); -+ cy-- ); -+ *h_ptr += *y_ptr - (cy + 1); -+ *y_ptr = cy + 1; -+ -+ /* ... downwards. */ -+ for ( cy = *y_ptr + *h_ptr; -+ cy < y + h && -+ CheckSolidTile(pScreen, *x_ptr, cy, *w_ptr, 1, &colorValue, TRUE); -+ cy++ ); -+ *h_ptr += cy - (*y_ptr + *h_ptr); -+ -+ /* ... to the left. */ -+ for ( cx = *x_ptr - 1; -+ cx >= x && CheckSolidTile(pScreen, cx, *y_ptr, 1, *h_ptr, &colorValue, TRUE); -+ cx-- ); -+ *w_ptr += *x_ptr - (cx + 1); -+ *x_ptr = cx + 1; -+ -+ /* ... to the right. */ -+ for ( cx = *x_ptr + *w_ptr; -+ cx < x + w && -+ CheckSolidTile(pScreen, cx, *y_ptr, 1, *h_ptr, &colorValue, TRUE); -+ cx++ ); -+ *w_ptr += cx - (*x_ptr + *w_ptr); -+} -+ -+/* -+ * Check if a rectangle is all of the same color. If needSameColor is -+ * set to non-zero, then also check that its color equals to the -+ * *colorPtr value. The result is 1 if the test is successfull, and in -+ * that case new color will be stored in *colorPtr. -+ */ -+ -+static Bool -+CheckSolidTile(pScreen, x, y, w, h, colorPtr, needSameColor) -+ ScreenPtr pScreen; -+ int x, y, w, h; -+ CARD32 *colorPtr; -+ Bool needSameColor; -+{ -+ VNCSCREENPTR(pScreen); -+ switch(pVNC->rfbServerFormat.bitsPerPixel) { -+ case 32: -+ return CheckSolidTile32(pScreen, x, y, w, h, colorPtr, needSameColor); -+ case 16: -+ return CheckSolidTile16(pScreen, x, y, w, h, colorPtr, needSameColor); -+ default: -+ return CheckSolidTile8(pScreen, x, y, w, h, colorPtr, needSameColor); -+ } -+} -+ -+#define DEFINE_CHECK_SOLID_FUNCTION(bpp) \ -+ \ -+static Bool \ -+CheckSolidTile##bpp(pScreen, x, y, w, h, colorPtr, needSameColor) \ -+ ScreenPtr pScreen; \ -+ int x, y; \ -+ CARD32 *colorPtr; \ -+ Bool needSameColor; \ -+{ \ -+ VNCSCREENPTR(pScreen); \ -+ CARD##bpp *fbptr; \ -+ CARD##bpp colorValue; \ -+ int dx, dy; \ -+ \ -+ fbptr = (CARD##bpp *) \ -+ &pVNC->pfbMemory[y * pVNC->paddedWidthInBytes + x * (bpp/8)]; \ -+ \ -+ colorValue = *fbptr; \ -+ if (needSameColor && (CARD32)colorValue != *colorPtr) \ -+ return FALSE; \ -+ \ -+ for (dy = 0; dy < h; dy++) { \ -+ for (dx = 0; dx < w; dx++) { \ -+ if (colorValue != fbptr[dx]) \ -+ return FALSE; \ -+ } \ -+ fbptr = (CARD##bpp *)((CARD8 *)fbptr + pVNC->paddedWidthInBytes); \ -+ } \ -+ \ -+ *colorPtr = (CARD32)colorValue; \ -+ return TRUE; \ -+} -+ -+DEFINE_CHECK_SOLID_FUNCTION(8) -+DEFINE_CHECK_SOLID_FUNCTION(16) -+DEFINE_CHECK_SOLID_FUNCTION(32) -+ -+static Bool -+SendRectSimple(cl, x, y, w, h) -+ rfbClientPtr cl; -+ int x, y, w, h; -+{ -+ int maxBeforeSize, maxAfterSize; -+ int maxRectSize, maxRectWidth; -+ int subrectMaxWidth, subrectMaxHeight; -+ int dx, dy; -+ int rw, rh; -+ -+ maxRectSize = tightConf[cl->tightCompressLevel].maxRectSize; -+ maxRectWidth = tightConf[cl->tightCompressLevel].maxRectWidth; -+ -+ maxBeforeSize = maxRectSize * (cl->format.bitsPerPixel / 8); -+ maxAfterSize = maxBeforeSize + (maxBeforeSize + 99) / 100 + 12; -+ -+ if (tightBeforeBufSize < maxBeforeSize) { -+ tightBeforeBufSize = maxBeforeSize; -+ if (tightBeforeBuf == NULL) -+ tightBeforeBuf = (char *)xalloc(tightBeforeBufSize); -+ else -+ tightBeforeBuf = (char *)xrealloc(tightBeforeBuf, -+ tightBeforeBufSize); -+ } -+ -+ if (tightAfterBufSize < maxAfterSize) { -+ tightAfterBufSize = maxAfterSize; -+ if (tightAfterBuf == NULL) -+ tightAfterBuf = (char *)xalloc(tightAfterBufSize); -+ else -+ tightAfterBuf = (char *)xrealloc(tightAfterBuf, -+ tightAfterBufSize); -+ } -+ -+ if (w > maxRectWidth || w * h > maxRectSize) { -+ subrectMaxWidth = (w > maxRectWidth) ? maxRectWidth : w; -+ subrectMaxHeight = maxRectSize / subrectMaxWidth; -+ -+ for (dy = 0; dy < h; dy += subrectMaxHeight) { -+ for (dx = 0; dx < w; dx += maxRectWidth) { -+ rw = (dx + maxRectWidth < w) ? maxRectWidth : w - dx; -+ rh = (dy + subrectMaxHeight < h) ? subrectMaxHeight : h - dy; -+ if (!SendSubrect(cl, x+dx, y+dy, rw, rh)) -+ return FALSE; -+ } -+ } -+ } else { -+ if (!SendSubrect(cl, x, y, w, h)) -+ return FALSE; -+ } -+ -+ return TRUE; -+} -+ -+static Bool -+SendSubrect(cl, x, y, w, h) -+ rfbClientPtr cl; -+ int x, y, w, h; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ unsigned char *fbptr; -+ Bool success = FALSE; -+ -+ /* Send pending data if there is more than 128 bytes. */ -+ if (pVNC->ublen > 128) { -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ } -+ -+ if (!SendTightHeader(cl, x, y, w, h)) -+ return FALSE; -+ -+ fbptr = (pVNC->pfbMemory + (pVNC->paddedWidthInBytes * y) -+ + (x * (pVNC->bitsPerPixel / 8))); -+ -+ (*cl->translateFn)(cl->pScreen, cl->translateLookupTable, &pVNC->rfbServerFormat, -+ &cl->format, fbptr, tightBeforeBuf, -+ pVNC->paddedWidthInBytes, w, h, x, y); -+ -+ paletteMaxColors = w * h / tightConf[cl->tightCompressLevel].idxMaxColorsDivisor; -+ if ( paletteMaxColors < 2 && -+ w * h >= tightConf[cl->tightCompressLevel].monoMinRectSize ) { -+ paletteMaxColors = 2; -+ } -+ switch (cl->format.bitsPerPixel) { -+ case 8: -+ FillPalette8(w * h); -+ break; -+ case 16: -+ FillPalette16(w * h); -+ break; -+ default: -+ FillPalette32(w * h); -+ } -+ -+ switch (paletteNumColors) { -+ case 0: -+ /* Truecolor image */ -+ if (DetectSmoothImage(cl, &cl->format, w, h)) { -+ if (cl->tightQualityLevel != -1) { -+ success = SendJpegRect(cl, x, y, w, h, -+ tightConf[cl->tightQualityLevel].jpegQuality); -+ } else { -+ success = SendGradientRect(cl, w, h); -+ } -+ } else { -+ success = SendFullColorRect(cl, w, h); -+ } -+ break; -+ case 1: -+ /* Solid rectangle */ -+ success = SendSolidRect(cl); -+ break; -+ case 2: -+ /* Two-color rectangle */ -+ success = SendMonoRect(cl, w, h); -+ break; -+ default: -+ /* Up to 256 different colors */ -+ if ( paletteNumColors > 96 && -+ cl->tightQualityLevel != -1 && cl->tightQualityLevel <= 3 && -+ DetectSmoothImage(cl, &cl->format, w, h) ) { -+ success = SendJpegRect(cl, x, y, w, h, -+ tightConf[cl->tightQualityLevel].jpegQuality); -+ } else { -+ success = SendIndexedRect(cl, w, h); -+ } -+ } -+ return success; -+} -+ -+static Bool -+SendTightHeader(cl, x, y, w, h) -+ rfbClientPtr cl; -+ int x, y, w, h; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ rfbFramebufferUpdateRectHeader rect; -+ -+ if (pVNC->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) { -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ } -+ -+ rect.r.x = Swap16IfLE(x); -+ rect.r.y = Swap16IfLE(y); -+ rect.r.w = Swap16IfLE(w); -+ rect.r.h = Swap16IfLE(h); -+ rect.encoding = Swap32IfLE(rfbEncodingTight); -+ -+ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&rect, -+ sz_rfbFramebufferUpdateRectHeader); -+ pVNC->ublen += sz_rfbFramebufferUpdateRectHeader; -+ -+ cl->rfbRectanglesSent[rfbEncodingTight]++; -+ cl->rfbBytesSent[rfbEncodingTight] += sz_rfbFramebufferUpdateRectHeader; -+ -+ return TRUE; -+} -+ -+/* -+ * Subencoding implementations. -+ */ -+ -+static Bool -+SendSolidRect(cl) -+ rfbClientPtr cl; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ int len; -+ -+ if (usePixelFormat24) { -+ Pack24(cl->pScreen, tightBeforeBuf, &cl->format, 1); -+ len = 3; -+ } else -+ len = cl->format.bitsPerPixel / 8; -+ -+ if (pVNC->ublen + 1 + len > UPDATE_BUF_SIZE) { -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ } -+ -+ pVNC->updateBuf[pVNC->ublen++] = (char)(rfbTightFill << 4); -+ memcpy (&pVNC->updateBuf[pVNC->ublen], tightBeforeBuf, len); -+ pVNC->ublen += len; -+ -+ cl->rfbBytesSent[rfbEncodingTight] += len + 1; -+ -+ return TRUE; -+} -+ -+static Bool -+SendMonoRect(cl, w, h) -+ rfbClientPtr cl; -+ int w, h; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ int streamId = 1; -+ int paletteLen, dataLen; -+ -+ if ( (pVNC->ublen + TIGHT_MIN_TO_COMPRESS + 6 + -+ 2 * cl->format.bitsPerPixel / 8) > UPDATE_BUF_SIZE ) { -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ } -+ -+ /* Prepare tight encoding header. */ -+ dataLen = (w + 7) / 8; -+ dataLen *= h; -+ -+ pVNC->updateBuf[pVNC->ublen++] = (streamId | rfbTightExplicitFilter) << 4; -+ pVNC->updateBuf[pVNC->ublen++] = rfbTightFilterPalette; -+ pVNC->updateBuf[pVNC->ublen++] = 1; -+ -+ /* Prepare palette, convert image. */ -+ switch (cl->format.bitsPerPixel) { -+ -+ case 32: -+ EncodeMonoRect32((CARD8 *)tightBeforeBuf, w, h); -+ -+ ((CARD32 *)tightAfterBuf)[0] = monoBackground; -+ ((CARD32 *)tightAfterBuf)[1] = monoForeground; -+ if (usePixelFormat24) { -+ Pack24(cl->pScreen, tightAfterBuf, &cl->format, 2); -+ paletteLen = 6; -+ } else -+ paletteLen = 8; -+ -+ memcpy(&pVNC->updateBuf[pVNC->ublen], tightAfterBuf, paletteLen); -+ pVNC->ublen += paletteLen; -+ cl->rfbBytesSent[rfbEncodingTight] += 3 + paletteLen; -+ break; -+ -+ case 16: -+ EncodeMonoRect16((CARD8 *)tightBeforeBuf, w, h); -+ -+ ((CARD16 *)tightAfterBuf)[0] = (CARD16)monoBackground; -+ ((CARD16 *)tightAfterBuf)[1] = (CARD16)monoForeground; -+ -+ memcpy(&pVNC->updateBuf[pVNC->ublen], tightAfterBuf, 4); -+ pVNC->ublen += 4; -+ cl->rfbBytesSent[rfbEncodingTight] += 7; -+ break; -+ -+ default: -+ EncodeMonoRect8((CARD8 *)tightBeforeBuf, w, h); -+ -+ pVNC->updateBuf[pVNC->ublen++] = (char)monoBackground; -+ pVNC->updateBuf[pVNC->ublen++] = (char)monoForeground; -+ cl->rfbBytesSent[rfbEncodingTight] += 5; -+ } -+ -+ return CompressData(cl, streamId, dataLen, -+ tightConf[cl->tightCompressLevel].monoZlibLevel, -+ Z_DEFAULT_STRATEGY); -+} -+ -+static Bool -+SendIndexedRect(cl, w, h) -+ rfbClientPtr cl; -+ int w, h; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ int streamId = 2; -+ int i, entryLen; -+ -+ if ( (pVNC->ublen + TIGHT_MIN_TO_COMPRESS + 6 + -+ paletteNumColors * cl->format.bitsPerPixel / 8) > UPDATE_BUF_SIZE ) { -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ } -+ -+ /* Prepare tight encoding header. */ -+ pVNC->updateBuf[pVNC->ublen++] = (streamId | rfbTightExplicitFilter) << 4; -+ pVNC->updateBuf[pVNC->ublen++] = rfbTightFilterPalette; -+ pVNC->updateBuf[pVNC->ublen++] = (char)(paletteNumColors - 1); -+ -+ /* Prepare palette, convert image. */ -+ switch (cl->format.bitsPerPixel) { -+ -+ case 32: -+ EncodeIndexedRect32((CARD8 *)tightBeforeBuf, w * h); -+ -+ for (i = 0; i < paletteNumColors; i++) { -+ ((CARD32 *)tightAfterBuf)[i] = -+ palette.entry[i].listNode->rgb; -+ } -+ if (usePixelFormat24) { -+ Pack24(cl->pScreen, tightAfterBuf, &cl->format, paletteNumColors); -+ entryLen = 3; -+ } else -+ entryLen = 4; -+ -+ memcpy(&pVNC->updateBuf[pVNC->ublen], tightAfterBuf, paletteNumColors * entryLen); -+ pVNC->ublen += paletteNumColors * entryLen; -+ cl->rfbBytesSent[rfbEncodingTight] += 3 + paletteNumColors * entryLen; -+ break; -+ -+ case 16: -+ EncodeIndexedRect16((CARD8 *)tightBeforeBuf, w * h); -+ -+ for (i = 0; i < paletteNumColors; i++) { -+ ((CARD16 *)tightAfterBuf)[i] = -+ (CARD16)palette.entry[i].listNode->rgb; -+ } -+ -+ memcpy(&pVNC->updateBuf[pVNC->ublen], tightAfterBuf, paletteNumColors * 2); -+ pVNC->ublen += paletteNumColors * 2; -+ cl->rfbBytesSent[rfbEncodingTight] += 3 + paletteNumColors * 2; -+ break; -+ -+ default: -+ return FALSE; /* Should never happen. */ -+ } -+ -+ return CompressData(cl, streamId, w * h, -+ tightConf[cl->tightCompressLevel].idxZlibLevel, -+ Z_DEFAULT_STRATEGY); -+} -+ -+static Bool -+SendFullColorRect(cl, w, h) -+ rfbClientPtr cl; -+ int w, h; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ int streamId = 0; -+ int len; -+ -+ if (pVNC->ublen + TIGHT_MIN_TO_COMPRESS + 1 > UPDATE_BUF_SIZE) { -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ } -+ -+ pVNC->updateBuf[pVNC->ublen++] = 0x00; /* stream id = 0, no flushing, no filter */ -+ cl->rfbBytesSent[rfbEncodingTight]++; -+ -+ if (usePixelFormat24) { -+ Pack24(cl->pScreen, tightBeforeBuf, &cl->format, w * h); -+ len = 3; -+ } else -+ len = cl->format.bitsPerPixel / 8; -+ -+ return CompressData(cl, streamId, w * h * len, -+ tightConf[cl->tightCompressLevel].rawZlibLevel, -+ Z_DEFAULT_STRATEGY); -+} -+ -+static Bool -+SendGradientRect(cl, w, h) -+ rfbClientPtr cl; -+ int w, h; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ int streamId = 3; -+ int len; -+ -+ if (cl->format.bitsPerPixel == 8) -+ return SendFullColorRect(cl, w, h); -+ -+ if (pVNC->ublen + TIGHT_MIN_TO_COMPRESS + 2 > UPDATE_BUF_SIZE) { -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ } -+ -+ if (prevRowBuf == NULL) -+ prevRowBuf = (int *)xalloc(2048 * 3 * sizeof(int)); -+ -+ pVNC->updateBuf[pVNC->ublen++] = (streamId | rfbTightExplicitFilter) << 4; -+ pVNC->updateBuf[pVNC->ublen++] = rfbTightFilterGradient; -+ cl->rfbBytesSent[rfbEncodingTight] += 2; -+ -+ if (usePixelFormat24) { -+ FilterGradient24(cl->pScreen, tightBeforeBuf, &cl->format, w, h); -+ len = 3; -+ } else if (cl->format.bitsPerPixel == 32) { -+ FilterGradient32(cl->pScreen, (CARD32 *)tightBeforeBuf, &cl->format, w, h); -+ len = 4; -+ } else { -+ FilterGradient16(cl->pScreen, (CARD16 *)tightBeforeBuf, &cl->format, w, h); -+ len = 2; -+ } -+ -+ return CompressData(cl, streamId, w * h * len, -+ tightConf[cl->tightCompressLevel].gradientZlibLevel, -+ Z_FILTERED); -+} -+ -+static Bool -+CompressData(cl, streamId, dataLen, zlibLevel, zlibStrategy) -+ rfbClientPtr cl; -+ int streamId, dataLen, zlibLevel, zlibStrategy; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ z_streamp pz; -+ int err; -+ -+ if (dataLen < TIGHT_MIN_TO_COMPRESS) { -+ memcpy(&pVNC->updateBuf[pVNC->ublen], tightBeforeBuf, dataLen); -+ pVNC->ublen += dataLen; -+ cl->rfbBytesSent[rfbEncodingTight] += dataLen; -+ return TRUE; -+ } -+ -+ pz = &cl->zsStruct[streamId]; -+ -+ /* Initialize compression stream if needed. */ -+ if (!cl->zsActive[streamId]) { -+ pz->zalloc = Z_NULL; -+ pz->zfree = Z_NULL; -+ pz->opaque = Z_NULL; -+ -+ err = deflateInit2 (pz, zlibLevel, Z_DEFLATED, MAX_WBITS, -+ MAX_MEM_LEVEL, zlibStrategy); -+ if (err != Z_OK) -+ return FALSE; -+ -+ cl->zsActive[streamId] = TRUE; -+ cl->zsLevel[streamId] = zlibLevel; -+ } -+ -+ /* Prepare buffer pointers. */ -+ pz->next_in = (Bytef *)tightBeforeBuf; -+ pz->avail_in = dataLen; -+ pz->next_out = (Bytef *)tightAfterBuf; -+ pz->avail_out = tightAfterBufSize; -+ -+ /* Change compression parameters if needed. */ -+ if (zlibLevel != cl->zsLevel[streamId]) { -+ if (deflateParams (pz, zlibLevel, zlibStrategy) != Z_OK) { -+ return FALSE; -+ } -+ cl->zsLevel[streamId] = zlibLevel; -+ } -+ -+ /* Actual compression. */ -+ if ( deflate (pz, Z_SYNC_FLUSH) != Z_OK || -+ pz->avail_in != 0 || pz->avail_out == 0 ) { -+ return FALSE; -+ } -+ -+ return SendCompressedData(cl, tightAfterBufSize - pz->avail_out); -+} -+ -+static Bool SendCompressedData(cl, compressedLen) -+ rfbClientPtr cl; -+ int compressedLen; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ int i, portionLen; -+ -+ pVNC->updateBuf[pVNC->ublen++] = compressedLen & 0x7F; -+ cl->rfbBytesSent[rfbEncodingTight]++; -+ if (compressedLen > 0x7F) { -+ pVNC->updateBuf[pVNC->ublen-1] |= 0x80; -+ pVNC->updateBuf[pVNC->ublen++] = compressedLen >> 7 & 0x7F; -+ cl->rfbBytesSent[rfbEncodingTight]++; -+ if (compressedLen > 0x3FFF) { -+ pVNC->updateBuf[pVNC->ublen-1] |= 0x80; -+ pVNC->updateBuf[pVNC->ublen++] = compressedLen >> 14 & 0xFF; -+ cl->rfbBytesSent[rfbEncodingTight]++; -+ } -+ } -+ -+ portionLen = UPDATE_BUF_SIZE; -+ for (i = 0; i < compressedLen; i += portionLen) { -+ if (i + portionLen > compressedLen) { -+ portionLen = compressedLen - i; -+ } -+ if (pVNC->ublen + portionLen > UPDATE_BUF_SIZE) { -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ } -+ memcpy(&pVNC->updateBuf[pVNC->ublen], &tightAfterBuf[i], portionLen); -+ pVNC->ublen += portionLen; -+ } -+ cl->rfbBytesSent[rfbEncodingTight] += compressedLen; -+ return TRUE; -+} -+ -+/* -+ * Code to determine how many different colors used in rectangle. -+ */ -+ -+static void -+FillPalette8(count) -+ int count; -+{ -+ CARD8 *data = (CARD8 *)tightBeforeBuf; -+ CARD8 c0, c1; -+ int i, n0, n1; -+ -+ paletteNumColors = 0; -+ -+ c0 = data[0]; -+ for (i = 1; i < count && data[i] == c0; i++); -+ if (i == count) { -+ paletteNumColors = 1; -+ return; /* Solid rectangle */ -+ } -+ -+ if (paletteMaxColors < 2) -+ return; -+ -+ n0 = i; -+ c1 = data[i]; -+ n1 = 0; -+ for (i++; i < count; i++) { -+ if (data[i] == c0) { -+ n0++; -+ } else if (data[i] == c1) { -+ n1++; -+ } else -+ break; -+ } -+ if (i == count) { -+ if (n0 > n1) { -+ monoBackground = (CARD32)c0; -+ monoForeground = (CARD32)c1; -+ } else { -+ monoBackground = (CARD32)c1; -+ monoForeground = (CARD32)c0; -+ } -+ paletteNumColors = 2; /* Two colors */ -+ } -+} -+ -+#define DEFINE_FILL_PALETTE_FUNCTION(bpp) \ -+ \ -+static void \ -+FillPalette##bpp(count) \ -+ int count; \ -+{ \ -+ CARD##bpp *data = (CARD##bpp *)tightBeforeBuf; \ -+ CARD##bpp c0, c1, ci = 0; \ -+ int i, n0, n1, ni; \ -+ \ -+ c0 = data[0]; \ -+ for (i = 1; i < count && data[i] == c0; i++); \ -+ if (i >= count) { \ -+ paletteNumColors = 1; /* Solid rectangle */ \ -+ return; \ -+ } \ -+ \ -+ if (paletteMaxColors < 2) { \ -+ paletteNumColors = 0; /* Full-color encoding preferred */ \ -+ return; \ -+ } \ -+ \ -+ n0 = i; \ -+ c1 = data[i]; \ -+ n1 = 0; \ -+ for (i++; i < count; i++) { \ -+ ci = data[i]; \ -+ if (ci == c0) { \ -+ n0++; \ -+ } else if (ci == c1) { \ -+ n1++; \ -+ } else \ -+ break; \ -+ } \ -+ if (i >= count) { \ -+ if (n0 > n1) { \ -+ monoBackground = (CARD32)c0; \ -+ monoForeground = (CARD32)c1; \ -+ } else { \ -+ monoBackground = (CARD32)c1; \ -+ monoForeground = (CARD32)c0; \ -+ } \ -+ paletteNumColors = 2; /* Two colors */ \ -+ return; \ -+ } \ -+ \ -+ PaletteReset(); \ -+ PaletteInsert (c0, (CARD32)n0, bpp); \ -+ PaletteInsert (c1, (CARD32)n1, bpp); \ -+ \ -+ ni = 1; \ -+ for (i++; i < count; i++) { \ -+ if (data[i] == ci) { \ -+ ni++; \ -+ } else { \ -+ if (!PaletteInsert (ci, (CARD32)ni, bpp)) \ -+ return; \ -+ ci = data[i]; \ -+ ni = 1; \ -+ } \ -+ } \ -+ PaletteInsert (ci, (CARD32)ni, bpp); \ -+} -+ -+DEFINE_FILL_PALETTE_FUNCTION(16) -+DEFINE_FILL_PALETTE_FUNCTION(32) -+ -+ -+/* -+ * Functions to operate with palette structures. -+ */ -+ -+#define HASH_FUNC16(rgb) ((int)((((rgb) >> 8) + (rgb)) & 0xFF)) -+#define HASH_FUNC32(rgb) ((int)((((rgb) >> 16) + ((rgb) >> 8)) & 0xFF)) -+ -+static void -+PaletteReset(void) -+{ -+ paletteNumColors = 0; -+ memset(palette.hash, 0, 256 * sizeof(COLOR_LIST *)); -+} -+ -+static int -+PaletteInsert(CARD32 rgb, int numPixels, int bpp) -+{ -+ COLOR_LIST *pnode; -+ COLOR_LIST *prev_pnode = NULL; -+ int hash_key, idx, new_idx, count; -+ -+ hash_key = (bpp == 16) ? HASH_FUNC16(rgb) : HASH_FUNC32(rgb); -+ -+ pnode = palette.hash[hash_key]; -+ -+ while (pnode != NULL) { -+ if (pnode->rgb == rgb) { -+ /* Such palette entry already exists. */ -+ new_idx = idx = pnode->idx; -+ count = palette.entry[idx].numPixels + numPixels; -+ if (new_idx && palette.entry[new_idx-1].numPixels < count) { -+ do { -+ palette.entry[new_idx] = palette.entry[new_idx-1]; -+ palette.entry[new_idx].listNode->idx = new_idx; -+ new_idx--; -+ } -+ while (new_idx && palette.entry[new_idx-1].numPixels < count); -+ palette.entry[new_idx].listNode = pnode; -+ pnode->idx = new_idx; -+ } -+ palette.entry[new_idx].numPixels = count; -+ return paletteNumColors; -+ } -+ prev_pnode = pnode; -+ pnode = pnode->next; -+ } -+ -+ /* Check if palette is full. */ -+ if (paletteNumColors == 256 || paletteNumColors == paletteMaxColors) { -+ paletteNumColors = 0; -+ return 0; -+ } -+ -+ /* Move palette entries with lesser pixel counts. */ -+ for ( idx = paletteNumColors; -+ idx > 0 && palette.entry[idx-1].numPixels < numPixels; -+ idx-- ) { -+ palette.entry[idx] = palette.entry[idx-1]; -+ palette.entry[idx].listNode->idx = idx; -+ } -+ -+ /* Add new palette entry into the freed slot. */ -+ pnode = &palette.list[paletteNumColors]; -+ if (prev_pnode != NULL) { -+ prev_pnode->next = pnode; -+ } else { -+ palette.hash[hash_key] = pnode; -+ } -+ pnode->next = NULL; -+ pnode->idx = idx; -+ pnode->rgb = rgb; -+ palette.entry[idx].listNode = pnode; -+ palette.entry[idx].numPixels = numPixels; -+ -+ return (++paletteNumColors); -+} -+ -+ -+/* -+ * Converting 32-bit color samples into 24-bit colors. -+ * Should be called only when redMax, greenMax and blueMax are 255. -+ * Color components assumed to be byte-aligned. -+ */ -+ -+static void Pack24(pScreen, buf, fmt, count) -+ ScreenPtr pScreen; -+ char *buf; -+ rfbPixelFormat *fmt; -+ int count; -+{ -+ VNCSCREENPTR(pScreen); -+ CARD32 *buf32; -+ CARD32 pix; -+ int r_shift, g_shift, b_shift; -+ -+ buf32 = (CARD32 *)buf; -+ -+ if (!pVNC->rfbServerFormat.bigEndian == !fmt->bigEndian) { -+ r_shift = fmt->redShift; -+ g_shift = fmt->greenShift; -+ b_shift = fmt->blueShift; -+ } else { -+ r_shift = 24 - fmt->redShift; -+ g_shift = 24 - fmt->greenShift; -+ b_shift = 24 - fmt->blueShift; -+ } -+ -+ while (count--) { -+ pix = *buf32++; -+ *buf++ = (char)(pix >> r_shift); -+ *buf++ = (char)(pix >> g_shift); -+ *buf++ = (char)(pix >> b_shift); -+ } -+} -+ -+ -+/* -+ * Converting truecolor samples into palette indices. -+ */ -+ -+#define DEFINE_IDX_ENCODE_FUNCTION(bpp) \ -+ \ -+static void \ -+EncodeIndexedRect##bpp(buf, count) \ -+ CARD8 *buf; \ -+ int count; \ -+{ \ -+ COLOR_LIST *pnode; \ -+ CARD##bpp *src; \ -+ CARD##bpp rgb; \ -+ int rep = 0; \ -+ \ -+ src = (CARD##bpp *) buf; \ -+ \ -+ while (count--) { \ -+ rgb = *src++; \ -+ while (count && *src == rgb) { \ -+ rep++, src++, count--; \ -+ } \ -+ pnode = palette.hash[HASH_FUNC##bpp(rgb)]; \ -+ while (pnode != NULL) { \ -+ if ((CARD##bpp)pnode->rgb == rgb) { \ -+ *buf++ = (CARD8)pnode->idx; \ -+ while (rep) { \ -+ *buf++ = (CARD8)pnode->idx; \ -+ rep--; \ -+ } \ -+ break; \ -+ } \ -+ pnode = pnode->next; \ -+ } \ -+ } \ -+} -+ -+DEFINE_IDX_ENCODE_FUNCTION(16) -+DEFINE_IDX_ENCODE_FUNCTION(32) -+ -+#define DEFINE_MONO_ENCODE_FUNCTION(bpp) \ -+ \ -+static void \ -+EncodeMonoRect##bpp(buf, w, h) \ -+ CARD8 *buf; \ -+ int w, h; \ -+{ \ -+ CARD##bpp *ptr; \ -+ CARD##bpp bg; \ -+ unsigned int value, mask; \ -+ int aligned_width; \ -+ int x, y, bg_bits; \ -+ \ -+ ptr = (CARD##bpp *) buf; \ -+ bg = (CARD##bpp) monoBackground; \ -+ aligned_width = w - w % 8; \ -+ \ -+ for (y = 0; y < h; y++) { \ -+ for (x = 0; x < aligned_width; x += 8) { \ -+ for (bg_bits = 0; bg_bits < 8; bg_bits++) { \ -+ if (*ptr++ != bg) \ -+ break; \ -+ } \ -+ if (bg_bits == 8) { \ -+ *buf++ = 0; \ -+ continue; \ -+ } \ -+ mask = 0x80 >> bg_bits; \ -+ value = mask; \ -+ for (bg_bits++; bg_bits < 8; bg_bits++) { \ -+ mask >>= 1; \ -+ if (*ptr++ != bg) { \ -+ value |= mask; \ -+ } \ -+ } \ -+ *buf++ = (CARD8)value; \ -+ } \ -+ \ -+ mask = 0x80; \ -+ value = 0; \ -+ if (x >= w) \ -+ continue; \ -+ \ -+ for (; x < w; x++) { \ -+ if (*ptr++ != bg) { \ -+ value |= mask; \ -+ } \ -+ mask >>= 1; \ -+ } \ -+ *buf++ = (CARD8)value; \ -+ } \ -+} -+ -+DEFINE_MONO_ENCODE_FUNCTION(8) -+DEFINE_MONO_ENCODE_FUNCTION(16) -+DEFINE_MONO_ENCODE_FUNCTION(32) -+ -+ -+/* -+ * ``Gradient'' filter for 24-bit color samples. -+ * Should be called only when redMax, greenMax and blueMax are 255. -+ * Color components assumed to be byte-aligned. -+ */ -+ -+static void -+FilterGradient24(pScreen, buf, fmt, w, h) -+ ScreenPtr pScreen; -+ char *buf; -+ rfbPixelFormat *fmt; -+ int w, h; -+{ -+ VNCSCREENPTR(pScreen); -+ CARD32 *buf32; -+ CARD32 pix32; -+ int *prevRowPtr; -+ int shiftBits[3]; -+ int pixHere[3], pixUpper[3], pixLeft[3], pixUpperLeft[3]; -+ int prediction; -+ int x, y, c; -+ -+ buf32 = (CARD32 *)buf; -+ memset (prevRowBuf, 0, w * 3 * sizeof(int)); -+ -+ if (!pVNC->rfbServerFormat.bigEndian == !fmt->bigEndian) { -+ shiftBits[0] = fmt->redShift; -+ shiftBits[1] = fmt->greenShift; -+ shiftBits[2] = fmt->blueShift; -+ } else { -+ shiftBits[0] = 24 - fmt->redShift; -+ shiftBits[1] = 24 - fmt->greenShift; -+ shiftBits[2] = 24 - fmt->blueShift; -+ } -+ -+ for (y = 0; y < h; y++) { -+ for (c = 0; c < 3; c++) { -+ pixUpper[c] = 0; -+ pixHere[c] = 0; -+ } -+ prevRowPtr = prevRowBuf; -+ for (x = 0; x < w; x++) { -+ pix32 = *buf32++; -+ for (c = 0; c < 3; c++) { -+ pixUpperLeft[c] = pixUpper[c]; -+ pixLeft[c] = pixHere[c]; -+ pixUpper[c] = *prevRowPtr; -+ pixHere[c] = (int)(pix32 >> shiftBits[c] & 0xFF); -+ *prevRowPtr++ = pixHere[c]; -+ -+ prediction = pixLeft[c] + pixUpper[c] - pixUpperLeft[c]; -+ if (prediction < 0) { -+ prediction = 0; -+ } else if (prediction > 0xFF) { -+ prediction = 0xFF; -+ } -+ *buf++ = (char)(pixHere[c] - prediction); -+ } -+ } -+ } -+} -+ -+ -+/* -+ * ``Gradient'' filter for other color depths. -+ */ -+ -+#define DEFINE_GRADIENT_FILTER_FUNCTION(bpp) \ -+ \ -+static void \ -+FilterGradient##bpp(pScreen, buf, fmt, w, h) \ -+ ScreenPtr pScreen; \ -+ CARD##bpp *buf; \ -+ rfbPixelFormat *fmt; \ -+ int w, h; \ -+{ \ -+ VNCSCREENPTR(pScreen); \ -+ CARD##bpp pix, diff; \ -+ Bool endianMismatch; \ -+ int *prevRowPtr; \ -+ int maxColor[3], shiftBits[3]; \ -+ int pixHere[3], pixUpper[3], pixLeft[3], pixUpperLeft[3]; \ -+ int prediction; \ -+ int x, y, c; \ -+ \ -+ memset (prevRowBuf, 0, w * 3 * sizeof(int)); \ -+ \ -+ endianMismatch = (!pVNC->rfbServerFormat.bigEndian != !fmt->bigEndian); \ -+ \ -+ maxColor[0] = fmt->redMax; \ -+ maxColor[1] = fmt->greenMax; \ -+ maxColor[2] = fmt->blueMax; \ -+ shiftBits[0] = fmt->redShift; \ -+ shiftBits[1] = fmt->greenShift; \ -+ shiftBits[2] = fmt->blueShift; \ -+ \ -+ for (y = 0; y < h; y++) { \ -+ for (c = 0; c < 3; c++) { \ -+ pixUpper[c] = 0; \ -+ pixHere[c] = 0; \ -+ } \ -+ prevRowPtr = prevRowBuf; \ -+ for (x = 0; x < w; x++) { \ -+ pix = *buf; \ -+ if (endianMismatch) { \ -+ pix = Swap##bpp(pix); \ -+ } \ -+ diff = 0; \ -+ for (c = 0; c < 3; c++) { \ -+ pixUpperLeft[c] = pixUpper[c]; \ -+ pixLeft[c] = pixHere[c]; \ -+ pixUpper[c] = *prevRowPtr; \ -+ pixHere[c] = (int)(pix >> shiftBits[c] & maxColor[c]); \ -+ *prevRowPtr++ = pixHere[c]; \ -+ \ -+ prediction = pixLeft[c] + pixUpper[c] - pixUpperLeft[c]; \ -+ if (prediction < 0) { \ -+ prediction = 0; \ -+ } else if (prediction > maxColor[c]) { \ -+ prediction = maxColor[c]; \ -+ } \ -+ diff |= ((pixHere[c] - prediction) & maxColor[c]) \ -+ << shiftBits[c]; \ -+ } \ -+ if (endianMismatch) { \ -+ diff = Swap##bpp(diff); \ -+ } \ -+ *buf++ = diff; \ -+ } \ -+ } \ -+} -+ -+DEFINE_GRADIENT_FILTER_FUNCTION(16) -+DEFINE_GRADIENT_FILTER_FUNCTION(32) -+ -+ -+/* -+ * Code to guess if given rectangle is suitable for smooth image -+ * compression (by applying "gradient" filter or JPEG coder). -+ */ -+ -+#define JPEG_MIN_RECT_SIZE 4096 -+ -+#define DETECT_SUBROW_WIDTH 7 -+#define DETECT_MIN_WIDTH 8 -+#define DETECT_MIN_HEIGHT 8 -+ -+static int -+DetectSmoothImage (cl, fmt, w, h) -+ rfbClientPtr cl; -+ rfbPixelFormat *fmt; -+ int w, h; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ unsigned long avgError; -+ -+ if ( pVNC->rfbServerFormat.bitsPerPixel == 8 || fmt->bitsPerPixel == 8 || -+ w < DETECT_MIN_WIDTH || h < DETECT_MIN_HEIGHT ) { -+ return 0; -+ } -+ -+ if (cl->tightQualityLevel != -1) { -+ if (w * h < JPEG_MIN_RECT_SIZE) { -+ return 0; -+ } -+ } else { -+ if ( rfbTightDisableGradient || -+ w * h < tightConf[cl->tightCompressLevel].gradientMinRectSize ) { -+ return 0; -+ } -+ } -+ -+ if (fmt->bitsPerPixel == 32) { -+ if (usePixelFormat24) { -+ avgError = DetectSmoothImage24(cl, fmt, w, h); -+ if (cl->tightQualityLevel != -1) { -+ return (avgError < tightConf[cl->tightQualityLevel].jpegThreshold24); -+ } -+ return (avgError < tightConf[cl->tightCompressLevel].gradientThreshold24); -+ } else { -+ avgError = DetectSmoothImage32(cl, fmt, w, h); -+ } -+ } else { -+ avgError = DetectSmoothImage16(cl, fmt, w, h); -+ } -+ if (cl->tightQualityLevel != -1) { -+ return (avgError < tightConf[cl->tightQualityLevel].jpegThreshold); -+ } -+ return (avgError < tightConf[cl->tightCompressLevel].gradientThreshold); -+} -+ -+static unsigned long -+DetectSmoothImage24 (cl, fmt, w, h) -+ rfbClientPtr cl; -+ rfbPixelFormat *fmt; -+ int w, h; -+{ -+ int off; -+ int x, y, d, dx, c; -+ int diffStat[256]; -+ int pixelCount = 0; -+ int pix, left[3]; -+ unsigned long avgError; -+ -+ /* If client is big-endian, color samples begin from the second -+ byte (offset 1) of a 32-bit pixel value. */ -+ off = (fmt->bigEndian != 0); -+ -+ memset(diffStat, 0, 256*sizeof(int)); -+ -+ y = 0, x = 0; -+ while (y < h && x < w) { -+ for (d = 0; d < h - y && d < w - x - DETECT_SUBROW_WIDTH; d++) { -+ for (c = 0; c < 3; c++) { -+ left[c] = (int)tightBeforeBuf[((y+d)*w+x+d)*4+off+c] & 0xFF; -+ } -+ for (dx = 1; dx <= DETECT_SUBROW_WIDTH; dx++) { -+ for (c = 0; c < 3; c++) { -+ pix = (int)tightBeforeBuf[((y+d)*w+x+d+dx)*4+off+c] & 0xFF; -+ diffStat[abs(pix - left[c])]++; -+ left[c] = pix; -+ } -+ pixelCount++; -+ } -+ } -+ if (w > h) { -+ x += h; -+ y = 0; -+ } else { -+ x = 0; -+ y += w; -+ } -+ } -+ -+ if (diffStat[0] * 33 / pixelCount >= 95) -+ return 0; -+ -+ avgError = 0; -+ for (c = 1; c < 8; c++) { -+ avgError += (unsigned long)diffStat[c] * (unsigned long)(c * c); -+ if (diffStat[c] == 0 || diffStat[c] > diffStat[c-1] * 2) -+ return 0; -+ } -+ for (; c < 256; c++) { -+ avgError += (unsigned long)diffStat[c] * (unsigned long)(c * c); -+ } -+ avgError /= (pixelCount * 3 - diffStat[0]); -+ -+ return avgError; -+} -+ -+#define DEFINE_DETECT_FUNCTION(bpp) \ -+ \ -+static unsigned long \ -+DetectSmoothImage##bpp (cl, fmt, w, h) \ -+ rfbClientPtr cl; \ -+ rfbPixelFormat *fmt; \ -+ int w, h; \ -+{ \ -+ VNCSCREENPTR(cl->pScreen); \ -+ Bool endianMismatch; \ -+ CARD##bpp pix; \ -+ int maxColor[3], shiftBits[3]; \ -+ int x, y, d, dx, c; \ -+ int diffStat[256]; \ -+ int pixelCount = 0; \ -+ int sample, sum, left[3]; \ -+ unsigned long avgError; \ -+ \ -+ endianMismatch = (!pVNC->rfbServerFormat.bigEndian != !fmt->bigEndian); \ -+ \ -+ maxColor[0] = fmt->redMax; \ -+ maxColor[1] = fmt->greenMax; \ -+ maxColor[2] = fmt->blueMax; \ -+ shiftBits[0] = fmt->redShift; \ -+ shiftBits[1] = fmt->greenShift; \ -+ shiftBits[2] = fmt->blueShift; \ -+ \ -+ memset(diffStat, 0, 256*sizeof(int)); \ -+ \ -+ y = 0, x = 0; \ -+ while (y < h && x < w) { \ -+ for (d = 0; d < h - y && d < w - x - DETECT_SUBROW_WIDTH; d++) { \ -+ pix = ((CARD##bpp *)tightBeforeBuf)[(y+d)*w+x+d]; \ -+ if (endianMismatch) { \ -+ pix = Swap##bpp(pix); \ -+ } \ -+ for (c = 0; c < 3; c++) { \ -+ left[c] = (int)(pix >> shiftBits[c] & maxColor[c]); \ -+ } \ -+ for (dx = 1; dx <= DETECT_SUBROW_WIDTH; dx++) { \ -+ pix = ((CARD##bpp *)tightBeforeBuf)[(y+d)*w+x+d+dx]; \ -+ if (endianMismatch) { \ -+ pix = Swap##bpp(pix); \ -+ } \ -+ sum = 0; \ -+ for (c = 0; c < 3; c++) { \ -+ sample = (int)(pix >> shiftBits[c] & maxColor[c]); \ -+ sum += abs(sample - left[c]); \ -+ left[c] = sample; \ -+ } \ -+ if (sum > 255) \ -+ sum = 255; \ -+ diffStat[sum]++; \ -+ pixelCount++; \ -+ } \ -+ } \ -+ if (w > h) { \ -+ x += h; \ -+ y = 0; \ -+ } else { \ -+ x = 0; \ -+ y += w; \ -+ } \ -+ } \ -+ \ -+ if ((diffStat[0] + diffStat[1]) * 100 / pixelCount >= 90) \ -+ return 0; \ -+ \ -+ avgError = 0; \ -+ for (c = 1; c < 8; c++) { \ -+ avgError += (unsigned long)diffStat[c] * (unsigned long)(c * c); \ -+ if (diffStat[c] == 0 || diffStat[c] > diffStat[c-1] * 2) \ -+ return 0; \ -+ } \ -+ for (; c < 256; c++) { \ -+ avgError += (unsigned long)diffStat[c] * (unsigned long)(c * c); \ -+ } \ -+ avgError /= (pixelCount - diffStat[0]); \ -+ \ -+ return avgError; \ -+} -+ -+DEFINE_DETECT_FUNCTION(16) -+DEFINE_DETECT_FUNCTION(32) -+ -+ -+/* -+ * JPEG compression stuff. -+ */ -+ -+static struct jpeg_destination_mgr jpegDstManager; -+static Bool jpegError; -+static int jpegDstDataLen; -+ -+static Bool -+SendJpegRect(cl, x, y, w, h, quality) -+ rfbClientPtr cl; -+ int x, y, w, h; -+ int quality; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ struct jpeg_compress_struct cinfo; -+ struct jpeg_error_mgr jerr; -+ CARD8 *srcBuf; -+ JSAMPROW rowPointer[1]; -+ int dy; -+ -+ if (pVNC->rfbServerFormat.bitsPerPixel == 8) -+ return SendFullColorRect(cl, w, h); -+ -+ srcBuf = (CARD8 *)xalloc(w * 3); -+ if (srcBuf == NULL) { -+ return SendFullColorRect(cl, w, h); -+ } -+ rowPointer[0] = srcBuf; -+ -+ cinfo.err = jpeg_std_error(&jerr); -+ jpeg_create_compress(&cinfo); -+ -+ cinfo.image_width = w; -+ cinfo.image_height = h; -+ cinfo.input_components = 3; -+ cinfo.in_color_space = JCS_RGB; -+ -+ jpeg_set_defaults(&cinfo); -+ jpeg_set_quality(&cinfo, quality, TRUE); -+ -+ JpegSetDstManager (&cinfo); -+ -+ jpeg_start_compress(&cinfo, TRUE); -+ -+ for (dy = 0; dy < h; dy++) { -+ PrepareRowForJpeg(cl->pScreen, srcBuf, x, y + dy, w); -+ jpeg_write_scanlines(&cinfo, rowPointer, 1); -+ if (jpegError) -+ break; -+ } -+ -+ if (!jpegError) -+ jpeg_finish_compress(&cinfo); -+ -+ jpeg_destroy_compress(&cinfo); -+ xfree((char *)srcBuf); -+ -+ if (jpegError) -+ return SendFullColorRect(cl, w, h); -+ -+ if (pVNC->ublen + TIGHT_MIN_TO_COMPRESS + 1 > UPDATE_BUF_SIZE) { -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ } -+ -+ pVNC->updateBuf[pVNC->ublen++] = (char)(rfbTightJpeg << 4); -+ cl->rfbBytesSent[rfbEncodingTight]++; -+ -+ return SendCompressedData(cl, jpegDstDataLen); -+} -+ -+static void -+PrepareRowForJpeg(pScreen, dst, x, y, count) -+ ScreenPtr pScreen; -+ CARD8 *dst; -+ int x, y, count; -+{ -+ VNCSCREENPTR(pScreen); -+ if (pVNC->rfbServerFormat.bitsPerPixel == 32) { -+ if ( pVNC->rfbServerFormat.redMax == 0xFF && -+ pVNC->rfbServerFormat.greenMax == 0xFF && -+ pVNC->rfbServerFormat.blueMax == 0xFF ) { -+ PrepareRowForJpeg24(pScreen, dst, x, y, count); -+ } else { -+ PrepareRowForJpeg32(pScreen, dst, x, y, count); -+ } -+ } else { -+ /* 16 bpp assumed. */ -+ PrepareRowForJpeg16(pScreen, dst, x, y, count); -+ } -+} -+ -+static void -+PrepareRowForJpeg24(pScreen, dst, x, y, count) -+ ScreenPtr pScreen; -+ CARD8 *dst; -+ int x, y, count; -+{ -+ VNCSCREENPTR(pScreen); -+ CARD32 *fbptr; -+ CARD32 pix; -+ -+ fbptr = (CARD32 *) -+ &pVNC->pfbMemory[y * pVNC->paddedWidthInBytes + x * 4]; -+ -+ while (count--) { -+ pix = *fbptr++; -+ *dst++ = (CARD8)(pix >> pVNC->rfbServerFormat.redShift); -+ *dst++ = (CARD8)(pix >> pVNC->rfbServerFormat.greenShift); -+ *dst++ = (CARD8)(pix >> pVNC->rfbServerFormat.blueShift); -+ } -+} -+ -+#define DEFINE_JPEG_GET_ROW_FUNCTION(bpp) \ -+ \ -+static void \ -+PrepareRowForJpeg##bpp(pScreen, dst, x, y, count) \ -+ ScreenPtr pScreen; \ -+ CARD8 *dst; \ -+ int x, y, count; \ -+{ \ -+ VNCSCREENPTR(pScreen); \ -+ CARD##bpp *fbptr; \ -+ CARD##bpp pix; \ -+ int inRed, inGreen, inBlue; \ -+ \ -+ fbptr = (CARD##bpp *) \ -+ &pVNC->pfbMemory[y * pVNC->paddedWidthInBytes + \ -+ x * (bpp / 8)]; \ -+ \ -+ while (count--) { \ -+ pix = *fbptr++; \ -+ \ -+ inRed = (int) \ -+ (pix >> pVNC->rfbServerFormat.redShift & pVNC->rfbServerFormat.redMax); \ -+ inGreen = (int) \ -+ (pix >> pVNC->rfbServerFormat.greenShift & pVNC->rfbServerFormat.greenMax); \ -+ inBlue = (int) \ -+ (pix >> pVNC->rfbServerFormat.blueShift & pVNC->rfbServerFormat.blueMax); \ -+ \ -+ *dst++ = (CARD8)((inRed * 255 + pVNC->rfbServerFormat.redMax / 2) / \ -+ pVNC->rfbServerFormat.redMax); \ -+ *dst++ = (CARD8)((inGreen * 255 + pVNC->rfbServerFormat.greenMax / 2) / \ -+ pVNC->rfbServerFormat.greenMax); \ -+ *dst++ = (CARD8)((inBlue * 255 + pVNC->rfbServerFormat.blueMax / 2) / \ -+ pVNC->rfbServerFormat.blueMax); \ -+ } \ -+} -+ -+DEFINE_JPEG_GET_ROW_FUNCTION(16) -+DEFINE_JPEG_GET_ROW_FUNCTION(32) -+ -+/* -+ * Destination manager implementation for JPEG library. -+ */ -+ -+static void -+JpegInitDestination(j_compress_ptr cinfo) -+{ -+ jpegError = FALSE; -+ jpegDstManager.next_output_byte = (JOCTET *)tightAfterBuf; -+ jpegDstManager.free_in_buffer = (size_t)tightAfterBufSize; -+} -+ -+static boolean -+JpegEmptyOutputBuffer(j_compress_ptr cinfo) -+{ -+ jpegError = TRUE; -+ jpegDstManager.next_output_byte = (JOCTET *)tightAfterBuf; -+ jpegDstManager.free_in_buffer = (size_t)tightAfterBufSize; -+ -+ return TRUE; -+} -+ -+static void -+JpegTermDestination(j_compress_ptr cinfo) -+{ -+ jpegDstDataLen = tightAfterBufSize - jpegDstManager.free_in_buffer; -+} -+ -+static void -+JpegSetDstManager(j_compress_ptr cinfo) -+{ -+ jpegDstManager.init_destination = JpegInitDestination; -+ jpegDstManager.empty_output_buffer = JpegEmptyOutputBuffer; -+ jpegDstManager.term_destination = JpegTermDestination; -+ cinfo->dest = &jpegDstManager; -+} -+ -diff --git a/hw/vnc/translate.c b/hw/vnc/translate.c -new file mode 100644 -index 0000000..eb9bcb0 ---- /dev/null -+++ b/hw/vnc/translate.c -@@ -0,0 +1,496 @@ -+/* -+ * translate.c - translate between different pixel formats -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ */ -+ -+/* -+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. -+ * -+ * This is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This software is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this software; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -+ * USA. -+ */ -+ -+#include -+#include "rfb.h" -+#if XFREE86VNC -+#include -+#endif -+ -+static void PrintPixelFormat(rfbPixelFormat *pf); -+static Bool rfbSetClientColourMapBGR233(); -+ -+Bool rfbEconomicTranslate = FALSE; -+ -+/* -+ * Some standard pixel formats. -+ */ -+ -+static const rfbPixelFormat BGR233Format = { -+ 8, 8, 0, 1, 7, 7, 3, 0, 3, 6 -+}; -+ -+ -+/* -+ * Macro to compare pixel formats. -+ */ -+ -+#define PF_EQ(x,y) \ -+ ((x.bitsPerPixel == y.bitsPerPixel) && \ -+ (x.depth == y.depth) && \ -+ ((x.bigEndian == y.bigEndian) || (x.bitsPerPixel == 8)) && \ -+ (x.trueColour == y.trueColour) && \ -+ (!x.trueColour || ((x.redMax == y.redMax) && \ -+ (x.greenMax == y.greenMax) && \ -+ (x.blueMax == y.blueMax) && \ -+ (x.redShift == y.redShift) && \ -+ (x.greenShift == y.greenShift) && \ -+ (x.blueShift == y.blueShift)))) -+ -+#define CONCAT2(a,b) a##b -+#define CONCAT2E(a,b) CONCAT2(a,b) -+#define CONCAT4(a,b,c,d) a##b##c##d -+#define CONCAT4E(a,b,c,d) CONCAT4(a,b,c,d) -+ -+#define OUT 8 -+#include "tableinittctemplate.c" -+#include "tableinitcmtemplate.c" -+#define IN 8 -+#include "tabletranstemplate.c" -+#undef IN -+#define IN 16 -+#include "tabletranstemplate.c" -+#undef IN -+#define IN 32 -+#include "tabletranstemplate.c" -+#undef IN -+#undef OUT -+ -+#define OUT 16 -+#include "tableinittctemplate.c" -+#include "tableinitcmtemplate.c" -+#define IN 8 -+#include "tabletranstemplate.c" -+#undef IN -+#define IN 16 -+#include "tabletranstemplate.c" -+#undef IN -+#define IN 32 -+#include "tabletranstemplate.c" -+#undef IN -+#undef OUT -+ -+#define OUT 32 -+#include "tableinittctemplate.c" -+#include "tableinitcmtemplate.c" -+#define IN 8 -+#include "tabletranstemplate.c" -+#undef IN -+#define IN 16 -+#include "tabletranstemplate.c" -+#undef IN -+#define IN 32 -+#include "tabletranstemplate.c" -+#undef IN -+#undef OUT -+ -+typedef void (*rfbInitTableFnType)(ScreenPtr pScreen, char **table, rfbPixelFormat *in, -+ rfbPixelFormat *out); -+ -+rfbInitTableFnType rfbInitTrueColourSingleTableFns[3] = { -+ rfbInitTrueColourSingleTable8, -+ rfbInitTrueColourSingleTable16, -+ rfbInitTrueColourSingleTable32 -+}; -+ -+rfbInitTableFnType rfbInitColourMapSingleTableFns[3] = { -+ rfbInitColourMapSingleTable8, -+ rfbInitColourMapSingleTable16, -+ rfbInitColourMapSingleTable32 -+}; -+ -+rfbInitTableFnType rfbInitTrueColourRGBTablesFns[3] = { -+ rfbInitTrueColourRGBTables8, -+ rfbInitTrueColourRGBTables16, -+ rfbInitTrueColourRGBTables32 -+}; -+ -+rfbTranslateFnType rfbTranslateWithSingleTableFns[3][3] = { -+ { rfbTranslateWithSingleTable8to8, -+ rfbTranslateWithSingleTable8to16, -+ rfbTranslateWithSingleTable8to32 }, -+ { rfbTranslateWithSingleTable16to8, -+ rfbTranslateWithSingleTable16to16, -+ rfbTranslateWithSingleTable16to32 }, -+ { rfbTranslateWithSingleTable32to8, -+ rfbTranslateWithSingleTable32to16, -+ rfbTranslateWithSingleTable32to32 } -+}; -+ -+rfbTranslateFnType rfbTranslateWithRGBTablesFns[3][3] = { -+ { rfbTranslateWithRGBTables8to8, -+ rfbTranslateWithRGBTables8to16, -+ rfbTranslateWithRGBTables8to32 }, -+ { rfbTranslateWithRGBTables16to8, -+ rfbTranslateWithRGBTables16to16, -+ rfbTranslateWithRGBTables16to32 }, -+ { rfbTranslateWithRGBTables32to8, -+ rfbTranslateWithRGBTables32to16, -+ rfbTranslateWithRGBTables32to32 } -+}; -+ -+ -+ -+/* -+ * rfbTranslateNone is used when no translation is required. -+ */ -+ -+void -+rfbTranslateNone(ScreenPtr pScreen, char *table, rfbPixelFormat *in, rfbPixelFormat *out, -+ unsigned char *iptr, char *optr, int bytesBetweenInputLines, -+ int width, int height, int x, int y) -+{ -+ VNCSCREENPTR(pScreen); -+ int bytesPerOutputLine = width * (out->bitsPerPixel / 8); -+ -+ if (pVNC->useGetImage) { -+ DrawablePtr pDraw = (DrawablePtr)WindowTable[pScreen->myNum]; -+ -+ /* catch all for other TranslateNone cases - hextile, corre, rre, etc.*/ -+ (*pScreen->GetImage)(pDraw, x, y, width, height, ZPixmap, ~0, optr); -+ } else { -+ while (height > 0) { -+ memcpy(optr, iptr, bytesPerOutputLine); -+ iptr += bytesBetweenInputLines; -+ optr += bytesPerOutputLine; -+ height--; -+ } -+ } -+} -+ -+ -+/* -+ * rfbSetTranslateFunction sets the translation function. -+ */ -+ -+Bool -+rfbSetTranslateFunction(cl) -+ rfbClientPtr cl; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ rfbLog("Pixel format for client %s:\n",cl->host); -+ PrintPixelFormat(&cl->format); -+ -+ /* -+ * Check that bits per pixel values are valid -+ */ -+ -+ if ((pVNC->rfbServerFormat.bitsPerPixel != 8) && -+ (pVNC->rfbServerFormat.bitsPerPixel != 16) && -+ (pVNC->rfbServerFormat.bitsPerPixel != 32)) -+ { -+ rfbLog("%s: server bits per pixel not 8, 16 or 32\n", -+ "rfbSetTranslateFunction"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return FALSE; -+ } -+ -+ if ((cl->format.bitsPerPixel != 8) && -+ (cl->format.bitsPerPixel != 16) && -+ (cl->format.bitsPerPixel != 32)) -+ { -+ rfbLog("%s: client bits per pixel not 8, 16 or 32\n", -+ "rfbSetTranslateFunction"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return FALSE; -+ } -+ -+ if (!pVNC->rfbServerFormat.trueColour && -+ (pVNC->rfbServerFormat.bitsPerPixel != 8) && -+#if XFREE86VNC -+ (miInstalledMaps[cl->pScreen->myNum]->class == PseudoColor)) { -+#else -+ (pVNC->rfbInstalledColormap->class == PseudoColor)) { -+#endif -+ rfbLog("rfbSetTranslateFunction: server has colour map " -+ "but %d-bit - can only cope with 8-bit colour maps\n", -+ pVNC->rfbServerFormat.bitsPerPixel); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return FALSE; -+ } -+ -+ if (!cl->format.trueColour && -+ (cl->format.bitsPerPixel != 8) && -+#if XFREE86VNC -+ (miInstalledMaps[cl->pScreen->myNum]->class == PseudoColor)) { -+#else -+ (pVNC->rfbInstalledColormap->class == PseudoColor) ) { -+#endif -+ rfbLog("rfbSetTranslateFunction: client has colour map " -+ "but %d-bit - can only cope with 8-bit colour maps\n", -+ cl->format.bitsPerPixel); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return FALSE; -+ } -+ -+ /* -+ * bpp is valid, now work out how to translate -+ */ -+ -+ if (!cl->format.trueColour) { -+ -+ /* ? -> colour map */ -+ -+ if (!pVNC->rfbServerFormat.trueColour) { -+ -+ /* colour map -> colour map */ -+ -+#if XFREE86VNC -+ if (miInstalledMaps[cl->pScreen->myNum]->class == DirectColor) { -+#else -+ if (pVNC->rfbInstalledColormap->class == DirectColor) { -+#endif -+ rfbLog("rfbSetTranslateFunction: client is %d-bit DirectColor," -+ " client has colour map\n",cl->format.bitsPerPixel); -+ -+ cl->translateFn = rfbTranslateWithRGBTablesFns -+ [pVNC->rfbServerFormat.bitsPerPixel / 16] -+ [cl->format.bitsPerPixel / 16]; -+ -+ (*rfbInitTrueColourRGBTablesFns [cl->format.bitsPerPixel / 16]) -+ (cl->pScreen, &cl->translateLookupTable, -+ &pVNC->rfbServerFormat, &cl->format); -+ -+ return rfbSetClientColourMap(cl, 0, 0); -+ -+ /* PseudoColor colormap */ -+ -+ } else { -+ rfbLog("rfbSetTranslateFunction: both 8-bit colour map: " -+ "no translation needed\n"); -+ cl->translateFn = rfbTranslateNone; -+ return rfbSetClientColourMap(cl, 0, 0); -+ } -+ } -+ -+ /* -+ * truecolour -> colour map -+ * -+ * Set client's colour map to BGR233, then effectively it's -+ * truecolour as well -+ */ -+ -+ if (!rfbSetClientColourMapBGR233(cl)) -+ return FALSE; -+ -+ cl->format = BGR233Format; -+ } -+ -+ /* ? -> truecolour */ -+ -+ if (!pVNC->rfbServerFormat.trueColour) { -+ -+ /* colour map -> truecolour */ -+ -+ rfbLog("rfbSetTranslateFunction: client is %d-bit trueColour," -+ " server has colour map\n",cl->format.bitsPerPixel); -+ -+ cl->translateFn = rfbTranslateWithSingleTableFns -+ [pVNC->rfbServerFormat.bitsPerPixel / 16] -+ [cl->format.bitsPerPixel / 16]; -+ -+ return rfbSetClientColourMap(cl, 0, 0); -+ } -+ -+ /* truecolour -> truecolour */ -+ -+ if (PF_EQ(cl->format,pVNC->rfbServerFormat)) { -+ -+ /* client & server the same */ -+ -+ rfbLog(" no translation needed\n"); -+ cl->translateFn = rfbTranslateNone; -+ return TRUE; -+ } -+ -+ if ((pVNC->rfbServerFormat.bitsPerPixel < 16) || -+ (!rfbEconomicTranslate && (pVNC->rfbServerFormat.bitsPerPixel == 16))) { -+ -+ /* we can use a single lookup table for <= 16 bpp */ -+ -+ cl->translateFn = rfbTranslateWithSingleTableFns -+ [pVNC->rfbServerFormat.bitsPerPixel / 16] -+ [cl->format.bitsPerPixel / 16]; -+ -+ (*rfbInitTrueColourSingleTableFns -+ [cl->format.bitsPerPixel / 16]) (cl->pScreen, -+ &cl->translateLookupTable, -+ &pVNC->rfbServerFormat, &cl->format); -+ -+ } else { -+ -+ /* otherwise we use three separate tables for red, green and blue */ -+ -+ cl->translateFn = rfbTranslateWithRGBTablesFns -+ [pVNC->rfbServerFormat.bitsPerPixel / 16] -+ [cl->format.bitsPerPixel / 16]; -+ -+ (*rfbInitTrueColourRGBTablesFns -+ [cl->format.bitsPerPixel / 16]) (cl->pScreen, -+ &cl->translateLookupTable, -+ &pVNC->rfbServerFormat, &cl->format); -+ } -+ -+ return TRUE; -+} -+ -+ -+ -+/* -+ * rfbSetClientColourMapBGR233 sets the client's colour map so that it's -+ * just like an 8-bit BGR233 true colour client. -+ */ -+ -+static Bool -+rfbSetClientColourMapBGR233(cl) -+ rfbClientPtr cl; -+{ -+ char buf[sz_rfbSetColourMapEntriesMsg + 256 * 3 * 2]; -+ rfbSetColourMapEntriesMsg *scme = (rfbSetColourMapEntriesMsg *)buf; -+ CARD16 *rgb = (CARD16 *)(&buf[sz_rfbSetColourMapEntriesMsg]); -+ int i, len; -+ int r, g, b; -+ -+ if (cl->format.bitsPerPixel != 8) { -+ rfbLog("%s: client not 8 bits per pixel\n", -+ "rfbSetClientColourMapBGR233"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return FALSE; -+ } -+ -+ scme->type = rfbSetColourMapEntries; -+ -+ scme->firstColour = Swap16IfLE(0); -+ scme->nColours = Swap16IfLE(256); -+ -+ len = sz_rfbSetColourMapEntriesMsg; -+ -+ i = 0; -+ -+ for (b = 0; b < 4; b++) { -+ for (g = 0; g < 8; g++) { -+ for (r = 0; r < 8; r++) { -+ rgb[i++] = Swap16IfLE(r * 65535 / 7); -+ rgb[i++] = Swap16IfLE(g * 65535 / 7); -+ rgb[i++] = Swap16IfLE(b * 65535 / 3); -+ } -+ } -+ } -+ -+ len += 256 * 3 * 2; -+ -+ if (WriteExact(cl->sock, buf, len) < 0) { -+ rfbLogPerror("rfbSetClientColourMapBGR233: write"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return FALSE; -+ } -+ return TRUE; -+} -+ -+ -+/* -+ * rfbSetClientColourMap is called to set the client's colour map. If the -+ * client is a true colour client, we simply update our own translation table -+ * and mark the whole screen as having been modified. -+ */ -+ -+Bool -+rfbSetClientColourMap(cl, firstColour, nColours) -+ rfbClientPtr cl; -+ int firstColour; -+ int nColours; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ BoxRec box; -+ -+ if (nColours == 0) { -+#if XFREE86VNC -+ nColours = miInstalledMaps[cl->pScreen->myNum]->pVisual->ColormapEntries; -+#else -+ nColours = pVNC->rfbInstalledColormap->pVisual->ColormapEntries; -+#endif -+ } -+ -+ if (pVNC->rfbServerFormat.trueColour || !cl->readyForSetColourMapEntries) { -+ return TRUE; -+ } -+ -+ if (cl->format.trueColour) { -+ (*rfbInitColourMapSingleTableFns -+ [cl->format.bitsPerPixel / 16]) (cl->pScreen, -+ &cl->translateLookupTable, -+ &pVNC->rfbServerFormat, &cl->format); -+ -+ REGION_UNINIT(cl->pScreen,&cl->modifiedRegion); -+ box.x1 = box.y1 = 0; -+ box.x2 = pVNC->width; -+ box.y2 = pVNC->height; -+ REGION_INIT(cl->pScreen,&cl->modifiedRegion,&box,0); -+ -+ return TRUE; -+ } -+ -+ return rfbSendSetColourMapEntries(cl, firstColour, nColours); -+} -+ -+ -+/* -+ * rfbSetClientColourMaps sets the colour map for each RFB client. -+ */ -+ -+void -+rfbSetClientColourMaps(firstColour, nColours) -+ int firstColour; -+ int nColours; -+{ -+ rfbClientPtr cl, nextCl; -+ -+ for (cl = rfbClientHead; cl; cl = nextCl) { -+ nextCl = cl->next; -+ rfbSetClientColourMap(cl, firstColour, nColours); -+ } -+} -+ -+ -+static void -+PrintPixelFormat(pf) -+ rfbPixelFormat *pf; -+{ -+ if (pf->bitsPerPixel == 1) { -+ rfbLog(" 1 bpp, %s sig bit in each byte is leftmost on the screen.\n", -+ (pf->bigEndian ? "most" : "least")); -+ } else { -+ rfbLog(" %d bpp, depth %d%s\n",pf->bitsPerPixel,pf->depth, -+ ((pf->bitsPerPixel == 8) ? "" -+ : (pf->bigEndian ? ", big endian" : ", little endian"))); -+ if (pf->trueColour) { -+ rfbLog(" true colour: max r %d g %d b %d, shift r %d g %d b %d\n", -+ pf->redMax, pf->greenMax, pf->blueMax, -+ pf->redShift, pf->greenShift, pf->blueShift); -+ } else { -+ rfbLog(" uses a colour map (not true colour).\n"); -+ } -+ } -+} -diff --git a/hw/vnc/vncauth.h b/hw/vnc/vncauth.h -new file mode 100644 -index 0000000..adc280b ---- /dev/null -+++ b/hw/vnc/vncauth.h -@@ -0,0 +1,33 @@ -+/* -+ * 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. -+ */ -+ -+/* -+ * vncauth.h - describes the functions provided by the vncauth library. -+ */ -+ -+#define MAXPWLEN 8 -+#define CHALLENGESIZE 16 -+ -+extern int vncEncryptAndStorePasswd(char *passwd, char *fname); -+extern char *vncDecryptPasswdFromFile(char *fname); -+extern void vncRandomBytes(unsigned char *bytes); -+extern void vncEncryptBytes(unsigned char *bytes, char *passwd); -+extern int vncEncryptAndStorePasswd2(char *passwd, char *passwdViewOnly, char *fname); -+extern int vncDecryptPasswdFromFile2(char *fname, char *passwdFullControl, char *passwdViewOnly); -+ -diff --git a/hw/vnc/vncext.c b/hw/vnc/vncext.c -new file mode 100644 -index 0000000..a823253 ---- /dev/null -+++ b/hw/vnc/vncext.c -@@ -0,0 +1,794 @@ -+/* -+ * Copyright (C) 2002 Alan Hourihane. 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. -+ * -+ * Author: Alan Hourihane -+ */ -+ -+#include "rfb.h" -+ -+#include "extnsionst.h" -+#define _VNC_SERVER -+#include -+#ifdef XFree86LOADER -+#include "xf86Module.h" -+#endif -+ -+#include -+#include -+#include -+#include -+ -+int VncSelectNotify(ClientPtr client, BOOL onoff); -+void VncExtensionInit(void); -+ -+static int VncErrorBase; /* first vnc error number */ -+static int VncEventBase; /* first vnc event number */ -+ -+#define USE_ORIG_RES_CODE 0 -+ -+#if USE_ORIG_RES_CODE -+unsigned long VncResourceGeneration = 0; -+ -+static RESTYPE VncNotifyList; -+ -+static XID faked; -+ -+typedef struct _VncNotifyListRec { -+ struct _VncNotifyListRec *next; -+ ClientPtr client; -+} VncNotifyListRec, *VncNotifyListPtr; -+#endif -+ -+ -+/** -+ * Each X client that uses libVnc to talk to this extension will get -+ * recorded by one of these records. -+ */ -+typedef struct _VncClientRec { -+ ClientPtr client; -+ struct _VncClientRec *next; -+ XID fakeID; -+ RESTYPE res; -+} VncClientRec, *VncClientRecPtr; -+ -+static VncClientRecPtr ClientsList = NULL; -+ -+ -+/** -+ * Remove client record from list -+ */ -+static void -+VncRemoveClientRecord(ClientPtr client) -+{ -+ /* XXX need 'deleteresource' flag? */ -+ VncClientRecPtr p = ClientsList, prev = NULL; -+ rfbLog("%s client %p\n", __func__, (void *) client); -+ while (p) { -+ if (p->client == client) { -+ /* remove this one */ -+ if (prev) -+ prev->next = p->next; -+ else -+ ClientsList = p->next; -+ xfree(p); -+ return; -+ } -+ prev = p; -+ p = p->next; -+ } -+} -+ -+ -+/** -+ * This callback will be called by X's resource manager to delete the -+ * given resource. We create one resource for each client. When X -+ * deletes the resource, we know the client is going away. -+ */ -+static int -+VncDestroyClientResourceCallback(pointer pn, XID id) -+{ -+ VncClientRecPtr rec = (VncClientRecPtr) pn; -+ VncRemoveClientRecord(rec->client); -+ return Success; -+} -+ -+ -+/** -+ * Add a client record to the list of clients (unless already in list). -+ * We'll create a new, unique resource for this client. This is used -+ * to detect when an X client goes away. -+ */ -+static void -+VncSaveClientRecord(ClientPtr client) -+{ -+ VncClientRecPtr rec = ClientsList; -+ -+ rfbLog("%s saving client %p\n", __func__, (void *) client); -+ -+ /* look if already in list */ -+ while (rec) { -+ if (rec->client == client) { -+ return; /* already in list */ -+ } -+ rec = rec->next; -+ } -+ -+ /* allocate new client record */ -+ rec = (VncClientRecPtr) xalloc(sizeof(VncClientRec)); -+ if (rec) { -+ rec->client = client; -+ rec->fakeID = FakeClientID(client->index); -+ rec->res = CreateNewResourceType(VncDestroyClientResourceCallback); -+ if (!AddResource(rec->fakeID, rec->res, rec)) { -+ xfree(rec); -+ } -+ -+ /* insert at head of list */ -+ rec->next = ClientsList; -+ ClientsList = rec; -+ } -+} -+ -+ -+ -+static int -+ProcVncQueryVersion(ClientPtr client) -+{ -+ xVncQueryVersionReply rep; -+ -+ REQUEST_SIZE_MATCH(xVncQueryVersionReq); -+ rep.type = X_Reply; -+ rep.sequenceNumber = client->sequence; -+ rep.length = 0; -+ rep.majorVersion = VNC_MAJOR_VERSION; -+ rep.minorVersion = VNC_MINOR_VERSION; -+ if(client->swapped) -+ { -+ register char n; -+ swaps(&rep.sequenceNumber, n); -+ swaps(&rep.majorVersion, n); -+ swaps(&rep.minorVersion, n); -+ } -+ (void)WriteToClient(client, SIZEOF(xVncQueryVersionReply), -+ (char *)&rep); -+ return (client->noClientException); -+} /* ProcVncQueryVersion */ -+ -+static int -+ProcVncConnection(ClientPtr client) -+{ -+ REQUEST(xVncConnectionReq); -+ xVncConnectionReply rep; -+ -+ rfbUserAllow( stuff->sock, stuff->accept ); -+ -+ REQUEST_SIZE_MATCH(xVncConnectionReq); -+ rep.type = X_Reply; -+ rep.sequenceNumber = client->sequence; -+ rep.length = 0; -+ rep.sock = 0; -+ rep.accept = 0; -+ if(client->swapped) -+ { -+ register char n; -+ swaps(&rep.sequenceNumber, n); -+ swaps(&rep.sock, n); -+ swaps(&rep.accept, n); -+ } -+ (void)WriteToClient(client, SIZEOF(xVncConnectionReply), -+ (char *)&rep); -+ return (client->noClientException); -+} /* ProcVncConnection */ -+ -+static int -+ProcVncSelectNotify(ClientPtr client) -+{ -+ REQUEST(xVncSelectNotifyReq); -+ xVncSelectNotifyReply rep; -+ -+ VncSelectNotify(client, stuff->onoff); -+ -+ REQUEST_SIZE_MATCH(xVncSelectNotifyReq); -+ rep.type = X_Reply; -+ rep.sequenceNumber = client->sequence; -+ rep.length = 0; -+ if(client->swapped) -+ { -+ register char n; -+ swaps(&rep.sequenceNumber, n); -+ } -+ (void)WriteToClient(client, SIZEOF(xVncSelectNotifyReply), -+ (char *)&rep); -+ return (client->noClientException); -+ -+} -+ -+static int -+ProcVncListConnections(ClientPtr client) -+{ -+ xVncListConnectionsReply rep; -+ rfbClientPtr cl; -+ int count = 0; -+ struct in_addr ipaddress; -+ xVncConnectionListInfo Info; -+ -+ /* count connections */ -+ for (cl = rfbClientHead; cl; cl = cl->next) -+#ifdef CHROMIUM -+ /* -+ * Fix this, as it should be generic, but we're only using it -+ * for Chromium at the moment, so we only list the connections -+ * that have a valid chromium encoding. We should be able to list -+ * any type requested. FIXME! XXXX -+ * See furthur down this function too!!! -+ */ -+ if (cl->enableChromiumEncoding) -+#endif -+ count++; -+ -+ REQUEST_SIZE_MATCH(xVncListConnectionsReq); -+ rep.type = X_Reply; -+ rep.sequenceNumber = client->sequence; -+ rep.count = count; -+ rep.length = count * sizeof(xVncConnectionListInfo) >> 2; -+ if(client->swapped) -+ { -+ register char n; -+ swaps(&rep.sequenceNumber, n); -+ swaps(&rep.count, n); -+ } -+ (void)WriteToClient(client, SIZEOF(xVncListConnectionsReply), -+ (char *)&rep); -+ -+ for (cl = rfbClientHead; cl; cl = cl->next) { -+#ifdef CHROMIUM -+ /* -+ * Fix this, as it should be generic, but we're only using it -+ * for Chromium at the moment, so we only list the connections -+ * that have a valid chromium encoding. We should be able to list -+ * any type requested. FIXME! XXXX -+ */ -+ if (!cl->enableChromiumEncoding) -+ continue; -+#endif -+ inet_aton(cl->host, &ipaddress); -+ memcpy(&Info, &ipaddress, sizeof(struct in_addr)); -+ WriteToClient(client, SIZEOF(xVncConnectionListInfo), (char*)&Info); -+ } -+ -+ return (client->noClientException); -+} /* ProcVncListConnections */ -+ -+#ifdef CHROMIUM -+static int -+ProcVncChromiumStart(ClientPtr client) -+{ -+ REQUEST(xVncChromiumStartReq); -+ xVncChromiumStartReply rep; -+ -+ rfbSendChromiumStart(stuff->ipaddress, stuff->crServerPort, stuff->mothershipPort); -+ -+ REQUEST_SIZE_MATCH(xVncChromiumStartReq); -+ rep.type = X_Reply; -+ rep.sequenceNumber = client->sequence; -+ rep.length = 0; -+ if(client->swapped) -+ { -+ register char n; -+ swaps(&rep.sequenceNumber, n); -+ } -+ (void)WriteToClient(client, SIZEOF(xVncChromiumStartReply), -+ (char *)&rep); -+ return (client->noClientException); -+} /* ProcVncChromiumStart */ -+ -+static int -+ProcVncChromiumMonitor(ClientPtr client) -+{ -+ REQUEST(xVncChromiumMonitorReq); -+ xVncChromiumMonitorReply rep; -+ -+ rfbChromiumMonitorWindowID(stuff->cr_windowid, stuff->windowid); -+ -+ REQUEST_SIZE_MATCH(xVncChromiumMonitorReq); -+ rep.type = X_Reply; -+ rep.sequenceNumber = client->sequence; -+ rep.length = 0; -+ if(client->swapped) -+ { -+ register char n; -+ swaps(&rep.sequenceNumber, n); -+ } -+ (void)WriteToClient(client, SIZEOF(xVncChromiumMonitorReply), -+ (char *)&rep); -+ return (client->noClientException); -+} /* ProcVncChromiumMonitor */ -+#endif /* CHROMIUM */ -+ -+static int -+ProcVncDispatch(ClientPtr client) -+{ -+ REQUEST(xReq); -+ -+ switch (stuff->data) -+ { -+ case X_VncQueryVersion: -+ return ProcVncQueryVersion(client); -+ case X_VncSelectNotify: -+ return ProcVncSelectNotify(client); -+ case X_VncConnection: -+ return ProcVncConnection(client); -+ case X_VncListConnections: -+ return ProcVncListConnections(client); -+#ifdef CHROMIUM -+ case X_VncChromiumStart: -+ return ProcVncChromiumStart(client); -+ case X_VncChromiumMonitor: -+ return ProcVncChromiumMonitor(client); -+#endif -+ default: -+ return BadRequest; -+ } -+} /* ProcVncDispatch */ -+ -+static int -+SProcVncQueryVersion(ClientPtr client) -+{ -+ REQUEST(xVncQueryVersionReq); -+ register char n; -+ -+ swaps(&stuff->length, n); -+ REQUEST_SIZE_MATCH(xVncQueryVersionReq); -+ swaps(&stuff->majorVersion, n); -+ swaps(&stuff->minorVersion,n); -+ return ProcVncQueryVersion(client); -+} /* SProcVncQueryVersion */ -+ -+static int -+SProcVncSelectNotify(ClientPtr client) -+{ -+ REQUEST(xVncSelectNotifyReq); -+ register char n; -+ -+ swaps(&stuff->length, n); -+ REQUEST_SIZE_MATCH(xVncSelectNotifyReq); -+ return ProcVncSelectNotify(client); -+} /* SProcVncSelectNotify */ -+ -+static int -+SProcVncListConnections(ClientPtr client) -+{ -+ REQUEST(xVncListConnectionsReq); -+ register char n; -+ -+ swaps(&stuff->length, n); -+ REQUEST_SIZE_MATCH(xVncListConnectionsReq); -+ return ProcVncListConnections(client); -+} /* SProcVncListConnections */ -+ -+#ifdef CHROMIUM -+static int -+SProcVncChromiumStart(ClientPtr client) -+{ -+ REQUEST(xVncChromiumStartReq); -+ register char n; -+ -+ swaps(&stuff->ipaddress, n); -+ swaps(&stuff->crServerPort, n); -+ swaps(&stuff->mothershipPort, n); -+ swaps(&stuff->length, n); -+ REQUEST_SIZE_MATCH(xVncChromiumStartReq); -+ return ProcVncChromiumStart(client); -+} /* SProcVncChromiumStart */ -+ -+static int -+SProcVncChromiumMonitor(ClientPtr client) -+{ -+ REQUEST(xVncChromiumMonitorReq); -+ register char n; -+ -+ swaps(&stuff->length, n); -+ swaps(&stuff->windowid, n); -+ swaps(&stuff->cr_windowid, n); -+ REQUEST_SIZE_MATCH(xVncChromiumMonitorReq); -+ return ProcVncChromiumMonitor(client); -+} /* SProcVncChromiumMonitor */ -+#endif /* CHROMIUM */ -+ -+static int -+SProcVncConnection(ClientPtr client) -+{ -+ REQUEST(xVncConnectionReq); -+ register char n; -+ -+ -+ swaps(&stuff->length, n); -+ REQUEST_SIZE_MATCH(xVncConnectionReq); -+ swaps(&stuff->sock, n); -+ swaps(&stuff->accept,n); -+ return ProcVncConnection(client); -+} /* SProcVncConnection */ -+ -+static int -+SProcVncDispatch(ClientPtr client) -+{ -+ REQUEST(xReq); -+ -+ switch (stuff->data) -+ { -+ case X_VncQueryVersion: -+ return SProcVncQueryVersion(client); -+ case X_VncSelectNotify: -+ return SProcVncSelectNotify(client); -+ case X_VncConnection: -+ return SProcVncConnection(client); -+ case X_VncListConnections: -+ return SProcVncListConnections(client); -+#ifdef CHROMIUM -+ case X_VncChromiumStart: -+ return SProcVncChromiumStart(client); -+ case X_VncChromiumMonitor: -+ return SProcVncChromiumMonitor(client); -+#endif -+ default: -+ return BadRequest; -+ } -+} /* SProcVncDispatch */ -+ -+static void -+SwapVncConnectedEvent(xVncConnectedEvent *from, xVncConnectedEvent *to) -+{ -+ to->type = from->type; -+ to->detail = from->detail; -+ cpswaps(from->sequenceNumber, to->sequenceNumber); -+ cpswapl(from->connected, to->connected); -+} -+ -+#ifdef CHROMIUM -+static void -+SwapVncChromiumConnectedEvent(xVncConnectedEvent *from, xVncConnectedEvent *to) -+{ -+ to->type = from->type; -+ to->detail = from->detail; -+ cpswaps(from->sequenceNumber, to->sequenceNumber); -+ cpswapl(from->connected, to->connected); -+} -+#endif -+ -+static void -+SwapVncDisconnectedEvent(xVncConnectedEvent *from, xVncConnectedEvent *to) -+{ -+ to->type = from->type; -+ to->detail = from->detail; -+ cpswaps(from->sequenceNumber, to->sequenceNumber); -+ cpswapl(from->connected, to->connected); -+} -+ -+int -+GenerateVncConnectedEvent(int sock) -+{ -+#if USE_ORIG_RES_CODE -+ VncNotifyListPtr pn; -+ -+ pn = (VncNotifyListPtr)LookupIDByType(faked, VncNotifyList); -+#else -+ VncClientRecPtr pn = ClientsList; -+#endif -+ -+ while (pn) -+ { -+ if (pn->client) -+ { -+ xVncConnectedEvent conn; -+ SOCKLEN_T peer_len; -+ struct sockaddr_in peer; -+ -+ conn.type = VncEventBase + XVncConnected; -+ conn.sequenceNumber = pn->client->sequence; -+ conn.connected = sock; -+ -+ peer_len = sizeof(peer); -+ if (getpeername(sock, (struct sockaddr *) &peer, &peer_len) == -1) -+ conn.ipaddress = 0; -+ else -+ conn.ipaddress = (CARD32)peer.sin_addr.s_addr; -+ -+ (void) TryClientEvents(pn->client, (xEventPtr)&conn, 1, NoEventMask, -+ NoEventMask, NullGrab); -+ } -+ pn = pn->next; -+ } -+ -+ return 1; -+} -+ -+ -+ -+#ifdef CHROMIUM -+int -+GenerateVncChromiumConnectedEvent(int sock) -+{ -+#if USE_ORIG_RES_CODE -+ VncNotifyListPtr pn; -+ pn = (VncNotifyListPtr)LookupIDByType(faked, VncNotifyList); -+#else -+ VncClientRecPtr pn = ClientsList; -+#endif -+ rfbLog("Enter GenerateVncChromiumConnectedEvent\n"); -+ while (pn) -+ { -+ if (pn->client) -+ { -+ xVncConnectedEvent conn; -+ SOCKLEN_T peer_len; -+ struct sockaddr_in peer; -+ -+ rfbLog("Sending XVncChromiumConnected to client %p\n", -+ (void *) pn->client); -+ -+ conn.type = VncEventBase + XVncChromiumConnected; -+ conn.sequenceNumber = pn->client->sequence; -+ conn.connected = sock; -+ -+ peer_len = sizeof(peer); -+ if (getpeername(sock, (struct sockaddr *)&peer, &peer_len) == -1) -+ conn.ipaddress = 0; -+ else -+ conn.ipaddress = (CARD32)peer.sin_addr.s_addr; -+ -+ (void) TryClientEvents(pn->client, (xEventPtr)&conn, 1, NoEventMask, -+ NoEventMask, NullGrab); -+ } -+ pn = pn->next; -+ } -+ return 1; -+} -+#endif /* CHROMIUM */ -+ -+ -+int -+GenerateVncDisconnectedEvent(int sock) -+{ -+#if USE_ORIG_RES_CODE -+ VncNotifyListPtr pn; -+ -+ pn = (VncNotifyListPtr)LookupIDByType(faked, VncNotifyList); -+#else -+ VncClientRecPtr pn = ClientsList; -+#endif -+ while (pn) -+ { -+ if (pn->client) -+ { -+ xVncDisconnectedEvent conn; -+ conn.type = VncEventBase + XVncDisconnected; -+ conn.sequenceNumber = pn->client->sequence; -+ conn.connected = sock; -+ (void) TryClientEvents(pn->client, (xEventPtr)&conn, 1, NoEventMask, -+ NoEventMask, NullGrab); -+ } -+ pn = pn->next; -+ } -+ -+ return 1; -+} -+ -+static void -+VncResetProc(ExtensionEntry *extEntry) -+{ -+} /* VncResetProc */ -+ -+ -+ -+/** -+ * When the app calls libVnc's XVncSelectNotify() we wind up here. -+ * Either add or remove 'client' from the VncNotifyList depending on 'onoff'. -+ */ -+int -+VncSelectNotify(ClientPtr client, BOOL onoff) -+{ -+#if USE_ORIG_RES_CODE -+ VncNotifyListPtr head, newRec, tmp, freeRec = NULL; -+ -+ rfbLog("%s client %p onoff=%d\n", __func__, (void *) client, (int) onoff); -+ if (!faked) -+ faked = FakeClientID(client->index); -+#else -+ /* ignore onoff param */ -+ VncSaveClientRecord(client); -+#endif -+ -+#if USE_ORIG_RES_CODE -+ /* Get the first VncNotifyListPtr */ -+ head = (VncNotifyListPtr) LookupIDByType(faked, VncNotifyList); -+ -+ /* search list for this client */ -+ tmp = head; -+ while (tmp) { -+ if (tmp->client == client) { -+ /* found client! */ -+ if (!onoff) -+ tmp->client = NULL; -+ return Success; -+ } -+ if (!tmp->client) -+ freeRec = tmp; /* save ptr to free record */ -+ tmp = tmp->next; -+ } -+ -+ /* if we get here, we didn't find client in the list */ -+ -+ if (!onoff) { -+ /* if turning off non-existing client, just return */ -+ return Success; -+ } -+ -+ /* OK, add new client to list now */ -+ -+ if (freeRec) { -+ /* re-using a free spot */ -+ freeRec->client = client; -+ return Success; -+ } -+ -+ /* need to allocate new node */ -+ if (!(newRec = (VncNotifyListPtr)xalloc(sizeof(VncNotifyListRec)))) -+ return BadAlloc; -+ /* insert at head, just as AddResource() does!!! */ -+ newRec->next = head; -+ newRec->client = client; -+ if (!AddResource(faked, VncNotifyList, newRec)) { -+ xfree(newRec); -+ return BadAlloc; -+ } -+#endif -+ return Success; -+} -+ -+ -+#if USE_ORIG_RES_CODE -+static int -+VncDestroyNotifyList(pointer pn, XID id) -+{ -+ VncNotifyListPtr cpn = (VncNotifyListPtr) pn; -+ rfbLog("%s client %p\n", __func__, (void *) cpn->client); -+ cpn->client = NULL; -+ return Success; -+} -+#endif -+ -+static Bool -+CreateResourceTypes(void) -+{ -+#if USE_ORIG_RES_CODE -+ if (VncResourceGeneration == serverGeneration) -+ return TRUE; -+ -+ VncResourceGeneration = serverGeneration; -+ -+ if (!(VncNotifyList = CreateNewResourceType(VncDestroyNotifyList))) { -+ ErrorF("CreateResourceTypes: failed to allocate vnc notify list resource.\n"); -+ return FALSE; -+ } -+#endif -+ return TRUE; -+} -+ -+ -+ -+#if XFREE86VNC -+static unsigned long vncCreateScreenResourcesIndex; -+static unsigned long vncExtGeneration = 0; -+extern Bool VNCInit(ScreenPtr pScreen, unsigned char *FBStart); -+ -+/* copied from miscrinit.c */ -+typedef struct -+{ -+ pointer pbits; /* pointer to framebuffer */ -+ int width; /* delta to add to a framebuffer addr to move one row down */ -+} miScreenInitParmsRec, *miScreenInitParmsPtr; -+ -+ -+static Bool -+vncCreateScreenResources(ScreenPtr pScreen) -+{ -+ int ret = TRUE; -+ CreateScreenResourcesProcPtr CreateScreenResources = -+ (CreateScreenResourcesProcPtr) -+ pScreen->devPrivates[vncCreateScreenResourcesIndex].ptr; -+ miScreenInitParmsPtr pScrInitParms; -+ -+ pScrInitParms = (miScreenInitParmsPtr)pScreen->devPrivate; -+ -+ if ( pScreen->CreateScreenResources != vncCreateScreenResources ) { -+ /* Can't find hook we are hung on */ -+ xf86DrvMsg(pScreen->myNum, X_WARNING /* X_ERROR */, -+ "vncCreateScreenResources %p called when not in " -+ "pScreen->CreateScreenResources %p n", -+ (void *) vncCreateScreenResources, -+ (void *) pScreen->CreateScreenResources ); -+ } -+ -+ /* Now do our stuff */ -+ VNCInit(pScreen, pScrInitParms->pbits); -+ -+ /* Unhook this function ... */ -+ pScreen->CreateScreenResources = CreateScreenResources; -+ pScreen->devPrivates[vncCreateScreenResourcesIndex].ptr = NULL; -+ -+ /* ... and call the previous CreateScreenResources fuction, if any */ -+ if (pScreen->CreateScreenResources) { -+ ret = (*pScreen->CreateScreenResources)(pScreen); -+ } -+ -+#ifdef DEBUG -+ ErrorF("vncCreateScreenResources() returns %d\n", ret); -+#endif -+ return ret; -+} -+#endif -+ -+ -+ -+void -+VncExtensionInit(void) -+{ -+ ExtensionEntry *extEntry; -+ -+#if XFREE86VNC -+ if (vncExtGeneration != serverGeneration) { -+ unsigned int i; -+ -+ vncExtGeneration = serverGeneration; -+ -+ if ( ((vncCreateScreenResourcesIndex = AllocateScreenPrivateIndex()) < 0) || -+ ((vncScreenPrivateIndex = AllocateScreenPrivateIndex()) < 0) || -+ ((rfbGCIndex = AllocateGCPrivateIndex()) < 0) ) -+ return; -+ -+ for (i = 0 ; i < screenInfo.numScreens; i++) -+ { -+ screenInfo.screens[i]->devPrivates[vncCreateScreenResourcesIndex].ptr -+ = (void*)(xf86Screens[i]->pScreen->CreateScreenResources); -+ xf86Screens[i]->pScreen->CreateScreenResources = vncCreateScreenResources; -+ } -+ -+ gethostname(rfbThisHost, 255); -+ } -+#endif -+ -+ if (!CreateResourceTypes()) -+ return; -+ -+ extEntry = AddExtension(VNC_EXTENSION_NAME, -+ XVncNumberEvents, XVncNumberErrors, -+ ProcVncDispatch, SProcVncDispatch, -+ VncResetProc, StandardMinorOpcode); -+ -+ VncErrorBase = extEntry->errorBase; -+ VncEventBase = extEntry->eventBase; -+ -+ EventSwapVector[VncEventBase + XVncConnected] = -+ (EventSwapPtr)SwapVncConnectedEvent; -+ EventSwapVector[VncEventBase + XVncDisconnected] = -+ (EventSwapPtr)SwapVncDisconnectedEvent; -+#ifdef CHROMIUM -+ EventSwapVector[VncEventBase + XVncChromiumConnected] = -+ (EventSwapPtr)SwapVncChromiumConnectedEvent; -+#endif -+} /* VncExtensionInit */ -diff --git a/hw/vnc/xistubs.c b/hw/vnc/xistubs.c -new file mode 100644 -index 0000000..be874f5 ---- /dev/null -+++ b/hw/vnc/xistubs.c -@@ -0,0 +1,319 @@ -+/* $Xorg: stubs.c,v 1.4 2001/02/09 02:04:35 xorgcvs Exp $ */ -+ -+/************************************************************ -+ -+Copyright 1989, 1998 The Open Group -+ -+Permission to use, copy, modify, distribute, and sell this software and its -+documentation for any purpose is hereby granted without fee, provided that -+the above copyright notice appear in all copies and that both that -+copyright notice and this permission notice appear in supporting -+documentation. -+ -+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 -+OPEN GROUP 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 Open Group 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 Open Group. -+ -+Copyright 1989 by Hewlett-Packard Company, Palo Alto, California. -+ -+ All Rights Reserved -+ -+Permission to use, copy, modify, and distribute this software and its -+documentation for any purpose and without fee is hereby granted, -+provided that the above copyright notice appear in all copies and that -+both that copyright notice and this permission notice appear in -+supporting documentation, and that the name of Hewlett-Packard not be -+used in advertising or publicity pertaining to distribution of the -+software without specific, written prior permission. -+ -+HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL -+HEWLETT-PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS -+SOFTWARE. -+ -+********************************************************/ -+/* $XFree86: xc/programs/Xserver/Xi/stubs.c,v 3.3 2001/01/17 22:13:26 dawes Exp $ */ -+ -+/* -+ * stubs.c -- stub routines for the X server side of the XINPUT -+ * extension. This file is mainly to be used only as documentation. -+ * There is not much code here, and you can't get a working XINPUT -+ * server just using this. -+ * The Xvfb server uses this file so it will compile with the same -+ * object files as the real X server for a platform that has XINPUT. -+ * Xnest could do the same thing. -+ */ -+ -+#define NEED_EVENTS -+#include -+#include -+#include -+#include -+#include "inputstr.h" -+#include "XIstubs.h" -+ -+/*********************************************************************** -+ * -+ * Caller: ProcXChangeKeyboardDevice -+ * -+ * This procedure does the implementation-dependent portion of the work -+ * needed to change the keyboard device. -+ * -+ * The X keyboard device has a FocusRec. If the device that has been -+ * made into the new X keyboard did not have a FocusRec, -+ * ProcXChangeKeyboardDevice will allocate one for it. -+ * -+ * If you do not want clients to be able to focus the old X keyboard -+ * device, call DeleteFocusClassDeviceStruct to free the FocusRec. -+ * -+ * If you support input devices with keys that you do not want to be -+ * used as the X keyboard, you need to check for them here and return -+ * a BadDevice error. -+ * -+ * The default implementation is to do nothing (assume you do want -+ * clients to be able to focus the old X keyboard). The commented-out -+ * sample code shows what you might do if you don't want the default. -+ * -+ */ -+ -+int -+ChangeKeyboardDevice (old_dev, new_dev) -+ DeviceIntPtr old_dev; -+ DeviceIntPtr new_dev; -+ { -+ /*********************************************************************** -+ DeleteFocusClassDeviceStruct(old_dev); * defined in xchgptr.c * -+ **********************************************************************/ -+ return BadMatch; -+ } -+ -+ -+/*********************************************************************** -+ * -+ * Caller: ProcXChangePointerDevice -+ * -+ * This procedure does the implementation-dependent portion of the work -+ * needed to change the pointer device. -+ * -+ * The X pointer device does not have a FocusRec. If the device that -+ * has been made into the new X pointer had a FocusRec, -+ * ProcXChangePointerDevice will free it. -+ * -+ * If you want clients to be able to focus the old pointer device that -+ * has now become accessible through the input extension, you need to -+ * add a FocusRec to it here. -+ * -+ * The XChangePointerDevice protocol request also allows the client -+ * to choose which axes of the new pointer device are used to move -+ * the X cursor in the X- and Y- directions. If the axes are different -+ * than the default ones, you need to keep track of that here. -+ * -+ * If you support input devices with valuators that you do not want to be -+ * used as the X pointer, you need to check for them here and return a -+ * BadDevice error. -+ * -+ * The default implementation is to do nothing (assume you don't want -+ * clients to be able to focus the old X pointer). The commented-out -+ * sample code shows what you might do if you don't want the default. -+ * -+ */ -+ -+int -+#if NeedFunctionPrototypes -+ChangePointerDevice ( -+ DeviceIntPtr old_dev, -+ DeviceIntPtr new_dev, -+ unsigned char x, -+ unsigned char y) -+#else -+ChangePointerDevice (old_dev, new_dev, x, y) -+ DeviceIntPtr old_dev, new_dev; -+ unsigned char x, y; -+#endif -+ { -+ /*********************************************************************** -+ InitFocusClassDeviceStruct(old_dev); * allow focusing old ptr* -+ -+ x_axis = x; * keep track of new x-axis* -+ y_axis = y; * keep track of new y-axis* -+ if (x_axis != 0 || y_axis != 1) -+ axes_changed = TRUE; * remember axes have changed* -+ else -+ axes_changed = FALSE; -+ *************************************************************************/ -+ return BadMatch; -+ } -+ -+/*********************************************************************** -+ * -+ * Caller: ProcXCloseDevice -+ * -+ * Take care of implementation-dependent details of closing a device. -+ * Some implementations may actually close the device, others may just -+ * remove this clients interest in that device. -+ * -+ * The default implementation is to do nothing (assume all input devices -+ * are initialized during X server initialization and kept open). -+ * -+ */ -+ -+void -+CloseInputDevice (d, client) -+ DeviceIntPtr d; -+ ClientPtr client; -+ { -+ } -+ -+/*********************************************************************** -+ * -+ * Caller: ProcXListInputDevices -+ * -+ * This is the implementation-dependent routine to initialize an input -+ * device to the point that information about it can be listed. -+ * Some implementations open all input devices when the server is first -+ * initialized, and never close them. Other implementations open only -+ * the X pointer and keyboard devices during server initialization, -+ * and only open other input devices when some client makes an -+ * XOpenDevice request. If some other process has the device open, the -+ * server may not be able to get information about the device to list it. -+ * -+ * This procedure should be used by implementations that do not initialize -+ * all input devices at server startup. It should do device-dependent -+ * initialization for any devices not previously initialized, and call -+ * AddInputDevice for each of those devices so that a DeviceIntRec will be -+ * created for them. -+ * -+ * The default implementation is to do nothing (assume all input devices -+ * are initialized during X server initialization and kept open). -+ * The commented-out sample code shows what you might do if you don't want -+ * the default. -+ * -+ */ -+ -+void -+AddOtherInputDevices () -+ { -+ /********************************************************************** -+ for each uninitialized device, do something like: -+ -+ DeviceIntPtr dev; -+ DeviceProc deviceProc; -+ pointer private; -+ -+ dev = (DeviceIntPtr) AddInputDevice(deviceProc, TRUE); -+ dev->public.devicePrivate = private; -+ RegisterOtherDevice(dev); -+ dev->inited = ((*dev->deviceProc)(dev, DEVICE_INIT) == Success); -+ ************************************************************************/ -+ -+ } -+ -+/*********************************************************************** -+ * -+ * Caller: ProcXOpenDevice -+ * -+ * This is the implementation-dependent routine to open an input device. -+ * Some implementations open all input devices when the server is first -+ * initialized, and never close them. Other implementations open only -+ * the X pointer and keyboard devices during server initialization, -+ * and only open other input devices when some client makes an -+ * XOpenDevice request. This entry point is for the latter type of -+ * implementation. -+ * -+ * If the physical device is not already open, do it here. In this case, -+ * you need to keep track of the fact that one or more clients has the -+ * device open, and physically close it when the last client that has -+ * it open does an XCloseDevice. -+ * -+ * The default implementation is to do nothing (assume all input devices -+ * are opened during X server initialization and kept open). -+ * -+ */ -+ -+void -+OpenInputDevice (dev, client, status) -+ DeviceIntPtr dev; -+ ClientPtr client; -+ int *status; -+ { -+ } -+ -+/**************************************************************************** -+ * -+ * Caller: ProcXSetDeviceMode -+ * -+ * Change the mode of an extension device. -+ * This function is used to change the mode of a device from reporting -+ * relative motion to reporting absolute positional information, and -+ * vice versa. -+ * The default implementation below is that no such devices are supported. -+ * -+ */ -+ -+int -+SetDeviceMode (client, dev, mode) -+ register ClientPtr client; -+ DeviceIntPtr dev; -+ int mode; -+ { -+ return BadMatch; -+ } -+ -+/**************************************************************************** -+ * -+ * Caller: ProcXSetDeviceValuators -+ * -+ * Set the value of valuators on an extension input device. -+ * This function is used to set the initial value of valuators on -+ * those input devices that are capable of reporting either relative -+ * motion or an absolute position, and allow an initial position to be set. -+ * The default implementation below is that no such devices are supported. -+ * -+ */ -+ -+int -+SetDeviceValuators (client, dev, valuators, first_valuator, num_valuators) -+ register ClientPtr client; -+ DeviceIntPtr dev; -+ int *valuators; -+ int first_valuator; -+ int num_valuators; -+ { -+ return BadMatch; -+ } -+ -+/**************************************************************************** -+ * -+ * Caller: ProcXChangeDeviceControl -+ * -+ * Change the specified device controls on an extension input device. -+ * -+ */ -+ -+int -+ChangeDeviceControl (client, dev, control) -+ register ClientPtr client; -+ DeviceIntPtr dev; -+ xDeviceCtl *control; -+ { -+ switch (control->control) -+ { -+ case DEVICE_RESOLUTION: -+ return (BadMatch); -+ default: -+ return (BadMatch); -+ } -+ } -diff --git a/hw/vnc/zlib.c b/hw/vnc/zlib.c -new file mode 100644 -index 0000000..2533a6b ---- /dev/null -+++ b/hw/vnc/zlib.c -@@ -0,0 +1,309 @@ -+/* -+ * zlib.c -+ * -+ * Routines to implement zlib based encoding (deflate). -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ */ -+ -+/* -+ * Copyright (C) 2000 Tridia Corporation. All Rights Reserved. -+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. -+ * -+ * This is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This software is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this software; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -+ * USA. -+ * -+ * For the latest source code, please check: -+ * -+ * http://www.developVNC.org/ -+ * -+ * or send email to feedback@developvnc.org. -+ */ -+ -+#include -+#include "rfb.h" -+ -+/* -+ * zlibBeforeBuf contains pixel data in the client's format. -+ * zlibAfterBuf contains the zlib (deflated) encoding version. -+ * If the zlib compressed/encoded version is -+ * larger than the raw data or if it exceeds zlibAfterBufSize then -+ * raw encoding is used instead. -+ */ -+ -+static int zlibBeforeBufSize = 0; -+static char *zlibBeforeBuf = NULL; -+ -+static int zlibAfterBufSize = 0; -+static char *zlibAfterBuf = NULL; -+static int zlibAfterBufLen; -+ -+/* -+ * rfbSendOneRectEncodingZlib - send a given rectangle using one Zlib -+ * rectangle encoding. -+ */ -+ -+Bool -+rfbSendOneRectEncodingZlib(cl, x, y, w, h) -+ rfbClientPtr cl; -+ int x, y, w, h; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ rfbFramebufferUpdateRectHeader rect; -+ rfbZlibHeader hdr; -+ int deflateResult; -+ int previousOut; -+ int i; -+ unsigned char *fbptr = (pVNC->pfbMemory + (pVNC->paddedWidthInBytes * y) -+ + (x * (pVNC->bitsPerPixel / 8))); -+ -+ int maxRawSize; -+ int maxCompSize; -+ -+ maxRawSize = (pVNC->width * pVNC->height -+ * (cl->format.bitsPerPixel / 8)); -+ -+ if (zlibBeforeBufSize < maxRawSize) { -+ zlibBeforeBufSize = maxRawSize; -+ if (zlibBeforeBuf == NULL) -+ zlibBeforeBuf = (char *)xalloc(zlibBeforeBufSize); -+ else -+ zlibBeforeBuf = (char *)xrealloc(zlibBeforeBuf, zlibBeforeBufSize); -+ } -+ -+ /* zlib compression is not useful for very small data sets. -+ * So, we just send these raw without any compression. -+ */ -+ if (( w * h * (pVNC->bitsPerPixel / 8)) < -+ VNC_ENCODE_ZLIB_MIN_COMP_SIZE ) { -+ -+ int result; -+ -+ /* The translation function (used also by the in raw encoding) -+ * requires 4/2/1 byte alignment in the output buffer (which is -+ * pVNC->updateBuf for the raw encoding) based on the bitsPerPixel of -+ * the viewer/client. This prevents SIGBUS errors on some -+ * architectures like SPARC, PARISC... -+ */ -+ if (( cl->format.bitsPerPixel > 8 ) && -+ ( pVNC->ublen % ( cl->format.bitsPerPixel / 8 )) != 0 ) { -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ } -+ -+ result = rfbSendRectEncodingRaw(cl, x, y, w, h); -+ -+ return result; -+ -+ } -+ -+ /* -+ * zlib requires output buffer to be slightly larger than the input -+ * buffer, in the worst case. -+ */ -+ maxCompSize = maxRawSize + (( maxRawSize + 99 ) / 100 ) + 12; -+ -+ if (zlibAfterBufSize < maxCompSize) { -+ zlibAfterBufSize = maxCompSize; -+ if (zlibAfterBuf == NULL) -+ zlibAfterBuf = (char *)xalloc(zlibAfterBufSize); -+ else -+ zlibAfterBuf = (char *)xrealloc(zlibAfterBuf, zlibAfterBufSize); -+ } -+ -+ /* -+ * Convert pixel data to client format. -+ */ -+ (*cl->translateFn)(cl->pScreen, cl->translateLookupTable, -+ &pVNC->rfbServerFormat, -+ &cl->format, fbptr, zlibBeforeBuf, -+ pVNC->paddedWidthInBytes, w, h, x, y); -+ -+ cl->compStream.next_in = ( Bytef * )zlibBeforeBuf; -+ cl->compStream.avail_in = w * h * (cl->format.bitsPerPixel / 8); -+ cl->compStream.next_out = ( Bytef * )zlibAfterBuf; -+ cl->compStream.avail_out = maxCompSize; -+ cl->compStream.data_type = Z_BINARY; -+ -+ /* Initialize the deflation state. */ -+ if ( cl->compStreamInited == FALSE ) { -+ -+ cl->compStream.total_in = 0; -+ cl->compStream.total_out = 0; -+ cl->compStream.zalloc = Z_NULL; -+ cl->compStream.zfree = Z_NULL; -+ cl->compStream.opaque = Z_NULL; -+ -+ deflateInit2( &(cl->compStream), -+ cl->zlibCompressLevel, -+ Z_DEFLATED, -+ MAX_WBITS, -+ MAX_MEM_LEVEL, -+ Z_DEFAULT_STRATEGY ); -+ /* deflateInit( &(cl->compStream), Z_BEST_COMPRESSION ); */ -+ /* deflateInit( &(cl->compStream), Z_BEST_SPEED ); */ -+ cl->compStreamInited = TRUE; -+ -+ } -+ -+ previousOut = cl->compStream.total_out; -+ -+ /* Perform the compression here. */ -+ deflateResult = deflate( &(cl->compStream), Z_SYNC_FLUSH ); -+ -+ /* Find the total size of the resulting compressed data. */ -+ zlibAfterBufLen = cl->compStream.total_out - previousOut; -+ -+ if ( deflateResult != Z_OK ) { -+ rfbLog("zlib deflation error: %s\n", cl->compStream.msg); -+ return FALSE; -+ } -+ -+ /* Note that it is not possible to switch zlib parameters based on -+ * the results of the compression pass. The reason is -+ * that we rely on the compressor and decompressor states being -+ * in sync. Compressing and then discarding the results would -+ * cause lose of synchronization. -+ */ -+ -+ /* Update statics */ -+ cl->rfbRectanglesSent[rfbEncodingZlib]++; -+ cl->rfbBytesSent[rfbEncodingZlib] += (sz_rfbFramebufferUpdateRectHeader -+ + sz_rfbZlibHeader + zlibAfterBufLen); -+ -+ if (pVNC->ublen + sz_rfbFramebufferUpdateRectHeader + sz_rfbZlibHeader -+ > UPDATE_BUF_SIZE) -+ { -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ } -+ -+ rect.r.x = Swap16IfLE(x); -+ rect.r.y = Swap16IfLE(y); -+ rect.r.w = Swap16IfLE(w); -+ rect.r.h = Swap16IfLE(h); -+ rect.encoding = Swap32IfLE(rfbEncodingZlib); -+ -+ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&rect, -+ sz_rfbFramebufferUpdateRectHeader); -+ pVNC->ublen += sz_rfbFramebufferUpdateRectHeader; -+ -+ hdr.nBytes = Swap32IfLE(zlibAfterBufLen); -+ -+ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&hdr, sz_rfbZlibHeader); -+ pVNC->ublen += sz_rfbZlibHeader; -+ -+ for (i = 0; i < zlibAfterBufLen;) { -+ -+ int bytesToCopy = UPDATE_BUF_SIZE - pVNC->ublen; -+ -+ if (i + bytesToCopy > zlibAfterBufLen) { -+ bytesToCopy = zlibAfterBufLen - i; -+ } -+ -+ memcpy(&pVNC->updateBuf[pVNC->ublen], &zlibAfterBuf[i], bytesToCopy); -+ -+ pVNC->ublen += bytesToCopy; -+ i += bytesToCopy; -+ -+ if (pVNC->ublen == UPDATE_BUF_SIZE) { -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ } -+ } -+ -+ return TRUE; -+ -+} -+ -+ -+/* -+ * rfbSendRectEncodingZlib - send a given rectangle using one or more -+ * Zlib encoding rectangles. -+ */ -+ -+Bool -+rfbSendRectEncodingZlib(cl, x, y, w, h) -+ rfbClientPtr cl; -+ int x, y, w, h; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ int maxLines; -+ int linesRemaining; -+ rfbRectangle partialRect; -+ -+ partialRect.x = x; -+ partialRect.y = y; -+ partialRect.w = w; -+ partialRect.h = h; -+ -+ /* Determine maximum pixel/scan lines allowed per rectangle. */ -+ maxLines = ( ZLIB_MAX_SIZE(w) / w ); -+ -+ /* Initialize number of scan lines left to do. */ -+ linesRemaining = h; -+ -+ /* Loop until all work is done. */ -+ while ( linesRemaining > 0 ) { -+ -+ int linesToComp; -+ -+ if ( maxLines < linesRemaining ) -+ linesToComp = maxLines; -+ else -+ linesToComp = linesRemaining; -+ -+ partialRect.h = linesToComp; -+ -+ /* Encode (compress) and send the next rectangle. */ -+ if ( ! rfbSendOneRectEncodingZlib( cl, -+ partialRect.x, -+ partialRect.y, -+ partialRect.w, -+ partialRect.h )) { -+ -+ return FALSE; -+ } -+ -+ /* Technically, flushing the buffer here is not extrememly -+ * efficient. However, this improves the overall throughput -+ * of the system over very slow networks. By flushing -+ * the buffer with every maximum size zlib rectangle, we -+ * improve the pipelining usage of the server CPU, network, -+ * and viewer CPU components. Insuring that these components -+ * are working in parallel actually improves the performance -+ * seen by the user. -+ * Since, zlib is most useful for slow networks, this flush -+ * is appropriate for the desired behavior of the zlib encoding. -+ */ -+ if (( pVNC->ublen > 0 ) && -+ ( linesToComp == maxLines )) { -+ if (!rfbSendUpdateBuf(cl)) { -+ -+ return FALSE; -+ } -+ } -+ -+ /* Update remaining and incremental rectangle location. */ -+ linesRemaining -= linesToComp; -+ partialRect.y += linesToComp; -+ -+ } -+ -+ return TRUE; -+ -+} -+ -+ -diff --git a/hw/xfree86/Makefile.am b/hw/xfree86/Makefile.am -index 8665926..5ada381 100644 ---- a/hw/xfree86/Makefile.am -+++ b/hw/xfree86/Makefile.am -@@ -8,16 +8,20 @@ if DRI - XF86UTILS_SUBDIR = utils - endif - -+if XORG_VNC -+VNC_SUBDIR = vnc -+endif -+ - DOC_SUBDIR = doc - - SUBDIRS = common ddc dummylib i2c x86emu int10 fbdevhw os-support parser rac \ - ramdac shadowfb vbe vgahw xaa xf1bpp xf4bpp xf8_16bpp \ - xf8_32bpp loader scanpci dixmods exa \ -- $(DRI_SUBDIR) $(XF86UTILS_SUBDIR) $(DOC_SUBDIR) -+ $(DRI_SUBDIR) $(XF86UTILS_SUBDIR) $(VNC_SUBDIR) $(DOC_SUBDIR) - - DIST_SUBDIRS = common ddc dummylib i2c x86emu int10 fbdevhw os-support \ - parser rac ramdac shadowfb vbe vgahw xaa xf1bpp xf4bpp \ -- xf8_16bpp xf8_32bpp loader scanpci dixmods dri exa \ -+ xf8_16bpp xf8_32bpp loader scanpci dixmods dri vnc exa \ - utils doc - - bin_PROGRAMS = Xorg -diff --git a/hw/xfree86/dixmods/Makefile.am b/hw/xfree86/dixmods/Makefile.am -index 7b6afc4..dbc136e 100644 ---- a/hw/xfree86/dixmods/Makefile.am -+++ b/hw/xfree86/dixmods/Makefile.am -@@ -14,6 +14,10 @@ if XTRAP - DBEMOD = libdbe.la - endif - -+if XCLIPLIST -+XCLIPLISTMOD = libxcliplist.la -+endif -+ - module_LTLIBRARIES = libafb.la \ - libcfb.la \ - libcfb32.la \ -@@ -37,6 +41,7 @@ INCLUDES = @XORG_INCS@ \ - -I$(top_srcdir)/cfb \ - -I$(top_srcdir)/mfb \ - -I$(top_srcdir)/dbe \ -+ -I$(top_srcdir)/xcliplist \ - -I$(top_srcdir)/hw/xfree86/loader \ - -I$(top_srcdir)/miext/shadow \ - -I$(top_srcdir)/GL/glx -@@ -61,6 +66,10 @@ libdbe_la_LDFLAGS = -avoid-version - libdbe_la_LIBADD = $(top_builddir)/dbe/libdbe.la - libdbe_la_SOURCES = dbemodule.c - -+libxcliplist_la_LDFLAGS = -avoid-version -+libxcliplist_la_LIBADD = $(top_builddir)/xcliplist/libxcliplist.la -+libxcliplist_la_SOURCES = $(top_srcdir)/xcliplist/cliplistmod.c -+ - libfb_la_LDFLAGS = -avoid-version - libfb_la_LIBADD = $(top_builddir)/fb/libfb.la - libfb_la_SOURCES = $(top_builddir)/fb/fbcmap.c fbmodule.c -diff --git a/hw/xfree86/vnc/Makefile.am b/hw/xfree86/vnc/Makefile.am -new file mode 100644 -index 0000000..432e9b0 ---- /dev/null -+++ b/hw/xfree86/vnc/Makefile.am -@@ -0,0 +1,45 @@ -+libvnc_la_LTLIBRARIES = libvnc.la -+libvnc_la_CFLAGS = -I$(top_srcdir)/hw/xfree86/common \ -+ -I$(top_srcdir)/hw/xfree86/os-support \ -+ -I$(top_srcdir)/hw/xfree86/os-support/bus \ -+ -I$(top_srcdir)/hw/xfree86/ramdac \ -+ -I$(top_srcdir)/GL/glx \ -+ -I$(top_srcdir)/GL/include \ -+ -I$(top_builddir)/GL/include \ -+ -I@MESA_SOURCE@/include \ -+ -DHAVE_XORG_CONFIG_H \ -+ -DXFree86LOADER \ -+ -DXFREE86VNC=1 \ -+ -DCHROMIUM=1 \ -+ @LIBDRM_CFLAGS@ \ -+ @GL_CFLAGS@ -+ -+# @MODULE_DEFINES@ -+# @LOADER_DEFINES@ -+ -+libvnc_la_LDFLAGS = -module -avoid-version -+libvnc_ladir = $(moduledir)/extensions -+libvnc_la_SOURCES = \ -+ auth.c \ -+ cmap.c \ -+ corre.c \ -+ cursor.c \ -+ cutpaste.c \ -+ draw.c \ -+ hextile.c \ -+ httpd.c \ -+ kbdptr.c \ -+ loginauth.c \ -+ rfbkeyb.c \ -+ rfbmouse.c \ -+ rfbserver.c \ -+ rre.c \ -+ sockets.c \ -+ stats.c \ -+ tight.c \ -+ translate.c \ -+ vncext.c \ -+ vncInit.c \ -+ zlib.c -+ -+#sdk_HEADERS = vncint.h -diff --git a/hw/xfree86/vnc/README b/hw/xfree86/vnc/README -new file mode 100644 -index 0000000..64aa888 ---- /dev/null -+++ b/hw/xfree86/vnc/README -@@ -0,0 +1 @@ -+This directory contains the sources for building the vnc.so server extension module. -diff --git a/hw/xfree86/vnc/auth.c b/hw/xfree86/vnc/auth.c -new file mode 100644 -index 0000000..706db55 ---- /dev/null -+++ b/hw/xfree86/vnc/auth.c -@@ -0,0 +1,563 @@ -+/* -+ * auth.c - deal with authentication. -+ * -+ * This file implements authentication when setting up an RFB connection. -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ */ -+ -+/* -+ * Copyright (C) 2003-2004 Constantin Kaplinsky. All Rights Reserved. -+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. -+ * -+ * This is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This software is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this software; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -+ * USA. -+ */ -+ -+#include -+#include "rfb.h" -+#include "windowstr.h" -+ -+static void rfbSendSecurityType(rfbClientPtr cl, int securityType); -+static void rfbSendSecurityTypeList(rfbClientPtr cl, int primaryType); -+static void rfbSendTunnelingCaps(rfbClientPtr cl); -+static void rfbSendAuthCaps(rfbClientPtr cl); -+static void rfbVncAuthSendChallenge(rfbClientPtr cl); -+ -+/* -+ * rfbAuthNewClient is called right after negotiating the protocol -+ * version. Depending on the protocol version, we send either a code -+ * for authentication scheme to be used (protocol 3.3), or a list of -+ * possible "security types" (protocol 3.7). -+ */ -+ -+void -+rfbAuthNewClient(cl) -+ rfbClientPtr cl; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ int securityType = rfbSecTypeInvalid; -+ -+ if ((!pVNC->rfbAuthPasswdFile && !pVNC->loginAuthEnabled) || cl->reverseConnection) { -+ securityType = rfbSecTypeNone; -+ } else { -+ if (rfbAuthIsBlocked(cl)) { -+ rfbLog("Too many authentication failures - client rejected\n"); -+ rfbClientConnFailed(cl, "Too many authentication failures"); -+ return; -+ } -+ if (pVNC->rfbAuthPasswdFile) -+ securityType = rfbSecTypeVncAuth; -+ } -+ -+ if (cl->protocol_minor_ver < 7) { -+ /* Make sure we use only RFB 3.3 compatible security types. */ -+ if (securityType == rfbSecTypeInvalid) { -+ rfbLog("VNC authentication disabled - RFB 3.3 client rejected\n"); -+ rfbClientConnFailed(cl, "Your viewer cannot handle required " -+ "authentication methods"); -+ return; -+ } -+ rfbSendSecurityType(cl, securityType); -+ } else { -+ /* Here it's ok when securityType is set to rfbSecTypeInvalid. */ -+ rfbSendSecurityTypeList(cl, securityType); -+ } -+} -+ -+ -+/* -+ * Tell the client what security type will be used (protocol 3.3). -+ */ -+ -+static void -+rfbSendSecurityType(cl, securityType) -+ rfbClientPtr cl; -+ int securityType; -+{ -+ CARD32 value32; -+ -+ /* Send the value. */ -+ value32 = Swap32IfLE(securityType); -+ if (WriteExact(cl->sock, (char *)&value32, 4) < 0) { -+ rfbLogPerror("rfbSendSecurityType: write"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ /* Decide what to do next. */ -+ switch (securityType) { -+ case rfbSecTypeNone: -+ /* Dispatch client input to rfbProcessClientInitMessage. */ -+ cl->state = RFB_INITIALISATION; -+ break; -+ case rfbSecTypeVncAuth: -+ /* Begin the standard VNC authentication procedure. */ -+ rfbVncAuthSendChallenge(cl); -+ break; -+ default: -+ /* Impossible case (hopefully). */ -+ rfbLogPerror("rfbSendSecurityType: assertion failed"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ } -+} -+ -+ -+/* -+ * Advertise our supported security types (protocol 3.7). The list -+ * will include one standard security type (if primaryType is not set -+ * to rfbSecTypeInvalid), and then one more value telling the client -+ * that we support TightVNC protocol extensions. Thus, currently, -+ * there will be either 1 or 2 items in the list. -+ */ -+ -+static void -+rfbSendSecurityTypeList(cl, primaryType) -+ rfbClientPtr cl; -+ int primaryType; -+{ -+ int count = 1; -+ -+ /* Fill in the list of security types in the client structure. */ -+ if (primaryType != rfbSecTypeInvalid) { -+ cl->securityTypes[count++] = (CARD8)primaryType; -+ } -+ cl->securityTypes[count] = (CARD8)rfbSecTypeTight; -+ cl->securityTypes[0] = (CARD8)count++; -+ -+ /* Send the list. */ -+ if (WriteExact(cl->sock, (char *)cl->securityTypes, count) < 0) { -+ rfbLogPerror("rfbSendSecurityTypeList: write"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ /* Dispatch client input to rfbProcessClientSecurityType. */ -+ cl->state = RFB_SECURITY_TYPE; -+} -+ -+ -+/* -+ * Read the security type chosen by the client (protocol 3.7). -+ */ -+ -+void -+rfbProcessClientSecurityType(cl) -+ rfbClientPtr cl; -+{ -+ int n, count, i; -+ CARD8 chosenType; -+ -+ /* Read the security type. */ -+ n = ReadExact(cl->sock, (char *)&chosenType, 1); -+ if (n <= 0) { -+ if (n == 0) -+ rfbLog("rfbProcessClientSecurityType: client gone\n"); -+ else -+ rfbLogPerror("rfbProcessClientSecurityType: read"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ /* Make sure it was present in the list sent by the server. */ -+ count = (int)cl->securityTypes[0]; -+ for (i = 1; i <= count; i++) { -+ if (chosenType == cl->securityTypes[i]) -+ break; -+ } -+ if (i > count) { -+ rfbLog("rfbProcessClientSecurityType: " -+ "wrong security type requested\n"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ /* Now go to the proper authentication procedure. */ -+ switch (chosenType) { -+ case rfbSecTypeNone: -+ /* Dispatch client input to rfbProcessClientInitMessage. */ -+ cl->state = RFB_INITIALISATION; -+ break; -+ case rfbSecTypeVncAuth: -+ /* Begin the standard VNC authentication procedure. */ -+ rfbVncAuthSendChallenge(cl); -+ break; -+ case rfbSecTypeTight: -+ /* We are lucky: the viewer supports TightVNC extensions. */ -+ rfbLog("Enabling TightVNC protocol extensions\n"); -+ /* Switch to the protocol 3.7t. */ -+ cl->protocol_tightvnc = TRUE; -+ /* Advertise our tunneling capabilities. */ -+ rfbSendTunnelingCaps(cl); -+ break; -+ default: -+ /* Impossible case (hopefully). */ -+ rfbLog("rfbProcessClientSecurityType: " -+ "unknown authentication scheme\n"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ } -+} -+ -+ -+/* -+ * Send the list of our tunneling capabilities (protocol 3.7t). -+ */ -+ -+static void -+rfbSendTunnelingCaps(cl) -+ rfbClientPtr cl; -+{ -+ rfbTunnelingCapsMsg caps; -+ CARD32 nTypes = 0; /* we don't support tunneling yet */ -+ -+ caps.nTunnelTypes = Swap32IfLE(nTypes); -+ if (WriteExact(cl->sock, (char *)&caps, sz_rfbTunnelingCapsMsg) < 0) { -+ rfbLogPerror("rfbSendTunnelingCaps: write"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ if (nTypes) { -+ /* Dispatch client input to rfbProcessClientTunnelingType(). */ -+ cl->state = RFB_TUNNELING_TYPE; -+ } else { -+ rfbSendAuthCaps(cl); -+ } -+} -+ -+ -+/* -+ * Read tunneling type requested by the client (protocol 3.7t). -+ * NOTE: Currently, we don't support tunneling, and this function -+ * can never be called. -+ */ -+ -+void -+rfbProcessClientTunnelingType(cl) -+ rfbClientPtr cl; -+{ -+ /* If we were called, then something's really wrong. */ -+ rfbLog("rfbProcessClientTunnelingType: not implemented\n"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+} -+ -+ -+/* -+ * Send the list of our authentication capabilities to the client -+ * (protocol 3.7t). -+ */ -+ -+static void -+rfbSendAuthCaps(cl) -+ rfbClientPtr cl; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ Bool authRequired; -+ rfbAuthenticationCapsMsg caps; -+ rfbCapabilityInfo caplist[MAX_AUTH_CAPS]; -+ int count = 0; -+ -+ authRequired = ((pVNC->rfbAuthPasswdFile != NULL || pVNC->loginAuthEnabled) && -+ !cl->reverseConnection); -+ -+ if (authRequired) { -+ if (pVNC->loginAuthEnabled) { -+ SetCapInfo(&caplist[count], rfbAuthUnixLogin, rfbTightVncVendor); -+ cl->authCaps[count++] = rfbAuthUnixLogin; -+ } -+ if (pVNC->rfbAuthPasswdFile != NULL) { -+ SetCapInfo(&caplist[count], rfbAuthVNC, rfbStandardVendor); -+ cl->authCaps[count++] = rfbAuthVNC; -+ } -+ if (count == 0) { -+ /* Should never happen. */ -+ rfbLog("rfbSendAuthCaps: assertion failed\n"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ } -+ -+ cl->nAuthCaps = count; -+ caps.nAuthTypes = Swap32IfLE((CARD32)count); -+ if (WriteExact(cl->sock, (char *)&caps, sz_rfbAuthenticationCapsMsg) < 0) { -+ rfbLogPerror("rfbSendAuthCaps: write"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ if (count) { -+ if (WriteExact(cl->sock, (char *)&caplist[0], -+ count * sz_rfbCapabilityInfo) < 0) { -+ rfbLogPerror("rfbSendAuthCaps: write"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ /* Dispatch client input to rfbProcessClientAuthType. */ -+ cl->state = RFB_AUTH_TYPE; -+ } else { -+ /* Dispatch client input to rfbProcessClientInitMessage. */ -+ cl->state = RFB_INITIALISATION; -+ } -+} -+ -+ -+/* -+ * Read client's preferred authentication type (protocol 3.7t). -+ */ -+ -+void -+rfbProcessClientAuthType(cl) -+ rfbClientPtr cl; -+{ -+ CARD32 auth_type; -+ int n, i; -+ -+ /* Read authentication type selected by the client. */ -+ n = ReadExact(cl->sock, (char *)&auth_type, sizeof(auth_type)); -+ if (n <= 0) { -+ if (n == 0) -+ rfbLog("rfbProcessClientAuthType: client gone\n"); -+ else -+ rfbLogPerror("rfbProcessClientAuthType: read"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ auth_type = Swap32IfLE(auth_type); -+ -+ /* Make sure it was present in the list sent by the server. */ -+ for (i = 0; i < cl->nAuthCaps; i++) { -+ if (auth_type == cl->authCaps[i]) -+ break; -+ } -+ if (i >= cl->nAuthCaps) { -+ rfbLog("rfbProcessClientAuthType: " -+ "wrong authentication type requested\n"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ switch (auth_type) { -+ case rfbAuthNone: -+ /* Dispatch client input to rfbProcessClientInitMessage. */ -+ cl->state = RFB_INITIALISATION; -+ break; -+ case rfbAuthVNC: -+ rfbVncAuthSendChallenge(cl); -+ break; -+ case rfbAuthUnixLogin: -+ /* FIXME: Do (cl->state = RFB_LOGIN_AUTH) instead? */ -+ rfbLoginAuthProcessClientMessage(cl); -+ break; -+ default: -+ rfbLog("rfbProcessClientAuthType: unknown authentication scheme\n"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ } -+} -+ -+ -+/* -+ * Send the authentication challenge. -+ */ -+ -+static void -+rfbVncAuthSendChallenge(cl) -+ rfbClientPtr cl; -+{ -+ vncRandomBytes(cl->authChallenge); -+ if (WriteExact(cl->sock, (char *)cl->authChallenge, CHALLENGESIZE) < 0) { -+ rfbLogPerror("rfbVncAuthSendChallenge: write"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ /* Dispatch client input to rfbVncAuthProcessResponse. */ -+ cl->state = RFB_AUTHENTICATION; -+} -+ -+/* -+ * rfbVncAuthProcessResponse is called when the client sends its -+ * authentication response. -+ */ -+ -+void -+rfbVncAuthProcessResponse(cl) -+ rfbClientPtr cl; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ char passwdFullControl[9]; -+ char passwdViewOnly[9]; -+ int numPasswords; -+ Bool ok; -+ int n; -+ CARD8 encryptedChallenge1[CHALLENGESIZE]; -+ CARD8 encryptedChallenge2[CHALLENGESIZE]; -+ CARD8 response[CHALLENGESIZE]; -+ CARD32 authResult; -+ -+ n = ReadExact(cl->sock, (char *)response, CHALLENGESIZE); -+ if (n <= 0) { -+ if (n != 0) -+ rfbLogPerror("rfbVncAuthProcessResponse: read"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ numPasswords = vncDecryptPasswdFromFile2(pVNC->rfbAuthPasswdFile, -+ passwdFullControl, -+ passwdViewOnly); -+ if (numPasswords == 0) { -+ rfbLog("rfbVncAuthProcessResponse: could not get password from %s\n", -+ pVNC->rfbAuthPasswdFile); -+ -+ authResult = Swap32IfLE(rfbVncAuthFailed); -+ -+ if (WriteExact(cl->sock, (char *)&authResult, 4) < 0) { -+ rfbLogPerror("rfbVncAuthProcessResponse: write"); -+ } -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ memcpy(encryptedChallenge1, cl->authChallenge, CHALLENGESIZE); -+ vncEncryptBytes(encryptedChallenge1, passwdFullControl); -+ memcpy(encryptedChallenge2, cl->authChallenge, CHALLENGESIZE); -+ vncEncryptBytes(encryptedChallenge2, -+ (numPasswords == 2) ? passwdViewOnly : passwdFullControl); -+ -+ /* Lose the passwords from memory */ -+ memset(passwdFullControl, 0, 9); -+ memset(passwdViewOnly, 0, 9); -+ -+ ok = FALSE; -+ if (memcmp(encryptedChallenge1, response, CHALLENGESIZE) == 0) { -+ rfbLog("Full-control authentication passed by %s\n", cl->host); -+ ok = TRUE; -+ cl->viewOnly = FALSE; -+ } else if (memcmp(encryptedChallenge2, response, CHALLENGESIZE) == 0) { -+ rfbLog("View-only authentication passed by %s\n", cl->host); -+ ok = TRUE; -+ cl->viewOnly = TRUE; -+ } -+ -+ if (!ok) { -+ rfbLog("rfbVncAuthProcessResponse: authentication failed from %s\n", -+ cl->host); -+ -+ if (rfbAuthConsiderBlocking(cl)) { -+ authResult = Swap32IfLE(rfbVncAuthTooMany); -+ } else { -+ authResult = Swap32IfLE(rfbVncAuthFailed); -+ } -+ -+ if (WriteExact(cl->sock, (char *)&authResult, 4) < 0) { -+ rfbLogPerror("rfbVncAuthProcessResponse: write"); -+ } -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ rfbAuthUnblock(cl); -+ -+ authResult = Swap32IfLE(rfbVncAuthOK); -+ -+ if (WriteExact(cl->sock, (char *)&authResult, 4) < 0) { -+ rfbLogPerror("rfbVncAuthProcessResponse: write"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ /* Dispatch client input to rfbProcessClientInitMessage(). */ -+ cl->state = RFB_INITIALISATION; -+} -+ -+ -+/* -+ * Functions to prevent too many successive authentication failures. -+ * FIXME: This should be performed separately per each client IP. -+ */ -+ -+/* Maximum authentication failures before blocking connections */ -+#define MAX_AUTH_TRIES 5 -+ -+/* Delay in ms, doubles for each failure over MAX_AUTH_TRIES */ -+#define AUTH_TOO_MANY_BASE_DELAY 10 * 1000 -+ -+/* -+ * This function should not be called directly, it is called by -+ * setting a timer in rfbAuthConsiderBlocking(). -+ */ -+ -+static CARD32 -+rfbAuthReenable(OsTimerPtr timer, CARD32 now, pointer arg) -+{ -+ rfbClientPtr cl = (rfbClientPtr) arg; -+ VNCSCREENPTR(cl->pScreen); -+ pVNC->rfbAuthTooManyTries = FALSE; -+ return 0; -+} -+ -+/* -+ * This function should be called after each authentication failure. -+ * The return value will be true if there was too many failures. -+ */ -+ -+Bool -+rfbAuthConsiderBlocking(rfbClientPtr cl) -+{ -+ VNCSCREENPTR(cl->pScreen); -+ int i; -+ -+ pVNC->rfbAuthTries++; -+ -+ if (pVNC->rfbAuthTries >= MAX_AUTH_TRIES) { -+ CARD32 delay = AUTH_TOO_MANY_BASE_DELAY; -+ for (i = MAX_AUTH_TRIES; i < pVNC->rfbAuthTries; i++) -+ delay *= 2; -+ pVNC->timer = TimerSet(pVNC->timer, 0, delay, rfbAuthReenable, NULL); -+ pVNC->rfbAuthTooManyTries = TRUE; -+ return TRUE; -+ } -+ -+ return FALSE; -+} -+ -+/* -+ * This function should be called after successful authentication. -+ * It resets the counter of authentication failures. Note that it's -+ * not necessary to clear the rfbAuthTooManyTries flag as it will be -+ * reset by the timer function. -+ */ -+ -+void -+rfbAuthUnblock(rfbClientPtr cl) -+{ -+ VNCSCREENPTR(cl->pScreen); -+ pVNC->rfbAuthTries = 0; -+} -+ -+/* -+ * This function should be called before authentication process. -+ * The return value will be true if there was too many authentication -+ * failures, and the server should not allow another try. -+ */ -+ -+Bool -+rfbAuthIsBlocked(rfbClientPtr cl) -+{ -+ VNCSCREENPTR(cl->pScreen); -+ return pVNC->rfbAuthTooManyTries; -+} -+ -diff --git a/hw/xfree86/vnc/cmap.c b/hw/xfree86/vnc/cmap.c -new file mode 100644 -index 0000000..88aad12 ---- /dev/null -+++ b/hw/xfree86/vnc/cmap.c -@@ -0,0 +1,163 @@ -+/* -+ * cmap.c -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ */ -+ -+/* -+ * 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 "rfb.h" -+ -+int -+rfbListInstalledColormaps(pScreen, pmaps) -+ ScreenPtr pScreen; -+ Colormap *pmaps; -+{ -+ VNCSCREENPTR(pScreen); -+ /* By the time we are processing requests, we can guarantee that there -+ * is always a colormap installed */ -+ if (pVNC->rfbInstalledColormap) -+ *pmaps = pVNC->rfbInstalledColormap->mid; -+ -+#if XFREE86VNC -+ pScreen->ListInstalledColormaps = pVNC->ListInstalledColormaps; -+ (*pScreen->ListInstalledColormaps)(pScreen, pmaps); -+ pScreen->ListInstalledColormaps = rfbListInstalledColormaps; -+#endif -+ -+ return (1); -+} -+ -+ -+void -+rfbInstallColormap(pmap) -+ ColormapPtr pmap; -+{ -+ VNCSCREENPTR(pmap->pScreen); -+ -+ if (pmap != pVNC->rfbInstalledColormap) { -+ -+ if(pVNC->rfbInstalledColormap != (ColormapPtr)None) -+ WalkTree(pmap->pScreen, TellLostMap, -+ (char *)&pVNC->rfbInstalledColormap->mid); -+ /* Install pmap */ -+ pVNC->rfbInstalledColormap = pmap; -+ WalkTree(pmap->pScreen, TellGainedMap, (char *)&pmap->mid); -+ -+ rfbSetClientColourMaps(0, 0); -+ } -+#if XFREE86VNC -+ pmap->pScreen->InstallColormap = pVNC->InstallColormap; -+ (*pmap->pScreen->InstallColormap)(pmap); -+ pmap->pScreen->InstallColormap = rfbInstallColormap; -+#endif -+} -+ -+void -+rfbUninstallColormap(pmap) -+ ColormapPtr pmap; -+{ -+ VNCSCREENPTR(pmap->pScreen); -+ -+ if(pmap == pVNC->rfbInstalledColormap) -+ { -+ if (pmap->mid != pmap->pScreen->defColormap) -+ { -+ pVNC->rfbInstalledColormap = -+ (ColormapPtr) LookupIDByType(pmap->pScreen->defColormap, -+ RT_COLORMAP); -+ (*pmap->pScreen->InstallColormap)(pVNC->rfbInstalledColormap); -+ } -+ } -+#if XFREE86VNC -+ pmap->pScreen->UninstallColormap = pVNC->UninstallColormap; -+ (*pmap->pScreen->UninstallColormap)(pmap); -+ pmap->pScreen->UninstallColormap = rfbUninstallColormap; -+#endif -+} -+ -+ -+/* -+ * rfbStoreColors. We have a set of pixels but they may be in any order. -+ * If some of them happen to be in continuous ascending order then we can -+ * group them together into a single call to rfbSetClientColourMaps. -+ */ -+ -+void -+rfbStoreColors(pmap, ndef, pdefs) -+ ColormapPtr pmap; -+ int ndef; -+ xColorItem *pdefs; -+{ -+ VNCSCREENPTR(pmap->pScreen); -+ int i; -+ int first = -1; -+ int n = 0; -+ -+ if (pmap == pVNC->rfbInstalledColormap) { -+ for (i = 0; i < ndef; i++) { -+ if ((first != -1) && (first + n == pdefs[i].pixel)) { -+ n++; -+ } else { -+ if (first != -1) { -+ rfbSetClientColourMaps(first, n); -+ } -+ first = pdefs[i].pixel; -+ n = 1; -+ } -+ } -+ rfbSetClientColourMaps(first, n); -+ } -+#if XFREE86VNC -+ pmap->pScreen->StoreColors = pVNC->StoreColors; -+ (*pmap->pScreen->StoreColors)(pmap, ndef, pdefs); -+ pmap->pScreen->StoreColors = rfbStoreColors; -+#endif -+} -diff --git a/hw/xfree86/vnc/corre.c b/hw/xfree86/vnc/corre.c -new file mode 100644 -index 0000000..ec1c917 ---- /dev/null -+++ b/hw/xfree86/vnc/corre.c -@@ -0,0 +1,355 @@ -+/* -+ * corre.c -+ * -+ * Routines to implement Compact Rise-and-Run-length Encoding (CoRRE). This -+ * code is based on krw's original javatel rfbserver. -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ */ -+ -+/* -+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. -+ * -+ * This is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This software is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this software; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -+ * USA. -+ */ -+ -+#include -+#include -+#include -+#include "rfb.h" -+ -+/* -+ * rreBeforeBuf contains pixel data in the client's format. -+ * rreAfterBuf contains the RRE encoded version. If the RRE encoded version is -+ * larger than the raw data or if it exceeds rreAfterBufSize then -+ * raw encoding is used instead. -+ */ -+ -+static int rreBeforeBufSize = 0; -+static char *rreBeforeBuf = NULL; -+ -+static int rreAfterBufSize = 0; -+static char *rreAfterBuf = NULL; -+static int rreAfterBufLen; -+ -+static int subrectEncode8(CARD8 *data, int w, int h); -+static int subrectEncode16(CARD16 *data, int w, int h); -+static int subrectEncode32(CARD32 *data, int w, int h); -+static CARD32 getBgColour(char *data, int size, int bpp); -+static Bool rfbSendSmallRectEncodingCoRRE(rfbClientPtr cl, int x, int y, -+ int w, int h); -+ -+ -+/* -+ * rfbSendRectEncodingCoRRE - send an arbitrary size rectangle using CoRRE -+ * encoding. -+ */ -+ -+Bool -+rfbSendRectEncodingCoRRE(cl, x, y, w, h) -+ rfbClientPtr cl; -+ int x, y, w, h; -+{ -+ if (h > cl->correMaxHeight) { -+ return (rfbSendRectEncodingCoRRE(cl, x, y, w, cl->correMaxHeight) && -+ rfbSendRectEncodingCoRRE(cl, x, y + cl->correMaxHeight, -+ w, h - cl->correMaxHeight)); -+ } -+ -+ if (w > cl->correMaxWidth) { -+ return (rfbSendRectEncodingCoRRE(cl, x, y, cl->correMaxWidth, h) && -+ rfbSendRectEncodingCoRRE(cl, x + cl->correMaxWidth, y, -+ w - cl->correMaxWidth, h)); -+ } -+ -+ return rfbSendSmallRectEncodingCoRRE(cl, x, y, w, h); -+} -+ -+ -+ -+/* -+ * rfbSendSmallRectEncodingCoRRE - send a small (guaranteed < 256x256) -+ * rectangle using CoRRE encoding. -+ */ -+ -+static Bool -+rfbSendSmallRectEncodingCoRRE(cl, x, y, w, h) -+ rfbClientPtr cl; -+ int x, y, w, h; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ rfbFramebufferUpdateRectHeader rect; -+ rfbRREHeader hdr; -+ int nSubrects; -+ int i; -+ unsigned char *fbptr = (pVNC->pfbMemory + (pVNC->paddedWidthInBytes * y) -+ + (x * (pVNC->bitsPerPixel / 8))); -+ -+ int maxRawSize = (pVNC->width * pVNC->height -+ * (cl->format.bitsPerPixel / 8)); -+ -+ if (rreBeforeBufSize < maxRawSize) { -+ rreBeforeBufSize = maxRawSize; -+ if (rreBeforeBuf == NULL) -+ rreBeforeBuf = (char *)xalloc(rreBeforeBufSize); -+ else -+ rreBeforeBuf = (char *)xrealloc(rreBeforeBuf, rreBeforeBufSize); -+ } -+ -+ if (rreAfterBufSize < maxRawSize) { -+ rreAfterBufSize = maxRawSize; -+ if (rreAfterBuf == NULL) -+ rreAfterBuf = (char *)xalloc(rreAfterBufSize); -+ else -+ rreAfterBuf = (char *)xrealloc(rreAfterBuf, rreAfterBufSize); -+ } -+ -+ (*cl->translateFn)(cl->pScreen, cl->translateLookupTable, -+ &pVNC->rfbServerFormat, -+ &cl->format, fbptr, rreBeforeBuf, -+ pVNC->paddedWidthInBytes, w, h, x, y); -+ -+ switch (cl->format.bitsPerPixel) { -+ case 8: -+ nSubrects = subrectEncode8((CARD8 *)rreBeforeBuf, w, h); -+ break; -+ case 16: -+ nSubrects = subrectEncode16((CARD16 *)rreBeforeBuf, w, h); -+ break; -+ case 32: -+ nSubrects = subrectEncode32((CARD32 *)rreBeforeBuf, w, h); -+ break; -+ default: -+ rfbLog("getBgColour: bpp %d?\n",cl->format.bitsPerPixel); -+ exit(1); -+ } -+ -+ if (nSubrects < 0) { -+ -+ /* RRE encoding was too large, use raw */ -+ -+ return rfbSendRectEncodingRaw(cl, x, y, w, h); -+ } -+ -+ cl->rfbRectanglesSent[rfbEncodingCoRRE]++; -+ cl->rfbBytesSent[rfbEncodingCoRRE] += (sz_rfbFramebufferUpdateRectHeader -+ + sz_rfbRREHeader + rreAfterBufLen); -+ -+ if (pVNC->ublen + sz_rfbFramebufferUpdateRectHeader + sz_rfbRREHeader -+ > UPDATE_BUF_SIZE) -+ { -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ } -+ -+ rect.r.x = Swap16IfLE(x); -+ rect.r.y = Swap16IfLE(y); -+ rect.r.w = Swap16IfLE(w); -+ rect.r.h = Swap16IfLE(h); -+ rect.encoding = Swap32IfLE(rfbEncodingCoRRE); -+ -+ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&rect, -+ sz_rfbFramebufferUpdateRectHeader); -+ pVNC->ublen += sz_rfbFramebufferUpdateRectHeader; -+ -+ hdr.nSubrects = Swap32IfLE(nSubrects); -+ -+ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&hdr, sz_rfbRREHeader); -+ pVNC->ublen += sz_rfbRREHeader; -+ -+ for (i = 0; i < rreAfterBufLen;) { -+ -+ int bytesToCopy = UPDATE_BUF_SIZE - pVNC->ublen; -+ -+ if (i + bytesToCopy > rreAfterBufLen) { -+ bytesToCopy = rreAfterBufLen - i; -+ } -+ -+ memcpy(&pVNC->updateBuf[pVNC->ublen], &rreAfterBuf[i], bytesToCopy); -+ -+ pVNC->ublen += bytesToCopy; -+ i += bytesToCopy; -+ -+ if (pVNC->ublen == UPDATE_BUF_SIZE) { -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ } -+ } -+ -+ return TRUE; -+} -+ -+ -+ -+/* -+ * subrectEncode() encodes the given multicoloured rectangle as a background -+ * colour overwritten by single-coloured rectangles. It returns the number -+ * of subrectangles in the encoded buffer, or -1 if subrect encoding won't -+ * fit in the buffer. It puts the encoded rectangles in rreAfterBuf. The -+ * single-colour rectangle partition is not optimal, but does find the biggest -+ * horizontal or vertical rectangle top-left anchored to each consecutive -+ * coordinate position. -+ * -+ * The coding scheme is simply [...] where each -+ * is []. -+ */ -+ -+#define DEFINE_SUBRECT_ENCODE(bpp) \ -+static int \ -+subrectEncode##bpp(data,w,h) \ -+ CARD##bpp *data; \ -+ int w; \ -+ int h; \ -+{ \ -+ CARD##bpp cl; \ -+ rfbCoRRERectangle subrect; \ -+ int x,y; \ -+ int i,j; \ -+ int hx=0,hy,vx=0,vy; \ -+ int hyflag; \ -+ CARD##bpp *seg; \ -+ CARD##bpp *line; \ -+ int hw,hh,vw,vh; \ -+ int thex,they,thew,theh; \ -+ int numsubs = 0; \ -+ int newLen; \ -+ CARD##bpp bg = (CARD##bpp)getBgColour((char*)data,w*h,bpp); \ -+ \ -+ *((CARD##bpp*)rreAfterBuf) = bg; \ -+ \ -+ rreAfterBufLen = (bpp/8); \ -+ \ -+ for (y=0; y 0) && (i >= hx)) {hy += 1;} else {hyflag = 0;} \ -+ } \ -+ vy = j-1; \ -+ \ -+ /* We now have two possible subrects: (x,y,hx,hy) and (x,y,vx,vy) \ -+ * We'll choose the bigger of the two. \ -+ */ \ -+ hw = hx-x+1; \ -+ hh = hy-y+1; \ -+ vw = vx-x+1; \ -+ vh = vy-y+1; \ -+ \ -+ thex = x; \ -+ they = y; \ -+ \ -+ if ((hw*hh) > (vw*vh)) { \ -+ thew = hw; \ -+ theh = hh; \ -+ } else { \ -+ thew = vw; \ -+ theh = vh; \ -+ } \ -+ \ -+ subrect.x = thex; \ -+ subrect.y = they; \ -+ subrect.w = thew; \ -+ subrect.h = theh; \ -+ \ -+ newLen = rreAfterBufLen + (bpp/8) + sz_rfbCoRRERectangle; \ -+ if ((newLen > (w * h * (bpp/8))) || (newLen > rreAfterBufSize)) \ -+ return -1; \ -+ \ -+ numsubs += 1; \ -+ *((CARD##bpp*)(rreAfterBuf + rreAfterBufLen)) = cl; \ -+ rreAfterBufLen += (bpp/8); \ -+ memcpy(&rreAfterBuf[rreAfterBufLen],&subrect,sz_rfbCoRRERectangle); \ -+ rreAfterBufLen += sz_rfbCoRRERectangle; \ -+ \ -+ /* \ -+ * Now mark the subrect as done. \ -+ */ \ -+ for (j=they; j < (they+theh); j++) { \ -+ for (i=thex; i < (thex+thew); i++) { \ -+ data[j*w+i] = bg; \ -+ } \ -+ } \ -+ } \ -+ } \ -+ } \ -+ \ -+ return numsubs; \ -+} -+ -+DEFINE_SUBRECT_ENCODE(8) -+DEFINE_SUBRECT_ENCODE(16) -+DEFINE_SUBRECT_ENCODE(32) -+ -+ -+/* -+ * getBgColour() gets the most prevalent colour in a byte array. -+ */ -+static CARD32 -+getBgColour(data,size,bpp) -+ char *data; -+ int size; -+ int bpp; -+{ -+ -+#define NUMCLRS 256 -+ -+ static int counts[NUMCLRS]; -+ int i,j,k; -+ -+ int maxcount = 0; -+ CARD8 maxclr = 0; -+ -+ if (bpp != 8) { -+ if (bpp == 16) { -+ return ((CARD16 *)data)[0]; -+ } else if (bpp == 32) { -+ return ((CARD32 *)data)[0]; -+ } else { -+ rfbLog("getBgColour: bpp %d?\n",bpp); -+ exit(1); -+ } -+ } -+ -+ for (i=0; i= NUMCLRS) { -+ rfbLog("getBgColour: unusual colour = %d\n", k); -+ exit(1); -+ } -+ counts[k] += 1; -+ if (counts[k] > maxcount) { -+ maxcount = counts[k]; -+ maxclr = ((CARD8 *)data)[j]; -+ } -+ } -+ -+ return maxclr; -+} -diff --git a/hw/xfree86/vnc/cursor.c b/hw/xfree86/vnc/cursor.c -new file mode 100644 -index 0000000..a79111d ---- /dev/null -+++ b/hw/xfree86/vnc/cursor.c -@@ -0,0 +1,405 @@ -+/* -+ * cursor.c - support for cursor shape updates. -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ */ -+ -+/* -+ * Copyright (C) 2000, 2001 Const Kaplinsky. All Rights Reserved. -+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. -+ * -+ * This is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This software is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this software; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -+ * USA. -+ */ -+ -+#include -+#include -+#include "rfb.h" -+#include "mipointer.h" -+#include "sprite.h" -+#include "cursorstr.h" -+#include "servermd.h" -+ -+ -+/* Copied from Xvnc/lib/font/util/utilbitmap.c */ -+static unsigned char _reverse_byte[0x100] = { -+ 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 -+}; -+ -+ -+static int EncodeRichCursorData8 (char *buf, rfbPixelFormat *fmt, -+ CursorPtr pCursor); -+static int EncodeRichCursorData16 (ScreenPtr pScreen, -+ char *buf, rfbPixelFormat *fmt, -+ CursorPtr pCursor); -+static int EncodeRichCursorData32 (ScreenPtr pScreen, -+ char *buf, rfbPixelFormat *fmt, -+ CursorPtr pCursor); -+ -+ -+/* -+ * Send cursor shape either in X-style format or in client pixel format. -+ */ -+ -+Bool -+rfbSendCursorShape(cl, pScreen) -+ rfbClientPtr cl; -+ ScreenPtr pScreen; -+{ -+ VNCSCREENPTR(pScreen); -+ CursorPtr pCursor; -+ rfbFramebufferUpdateRectHeader rect; -+ rfbXCursorColors colors; -+ int saved_ublen; -+ int bitmapRowBytes, paddedRowBytes, maskBytes, dataBytes; -+ int i, j; -+ CARD8 *bitmapData; -+ CARD8 bitmapByte; -+ -+ if (cl->useRichCursorEncoding) { -+ rect.encoding = Swap32IfLE(rfbEncodingRichCursor); -+ } else { -+ rect.encoding = Swap32IfLE(rfbEncodingXCursor); -+ } -+ -+#if XFREE86VNC -+ pCursor = pVNC->pCurs; -+#else -+ pCursor = rfbSpriteGetCursorPtr(pScreen); -+#endif -+ -+ /* If there is no cursor, send update with empty cursor data. */ -+ -+ if ( pCursor != NULL && -+ pCursor->bits->width == 1 && -+ pCursor->bits->height == 1 && -+ pCursor->bits->mask[0] == 0 ) { -+ pCursor = NULL; -+ } -+ -+ if (pCursor == NULL) { -+ if (pVNC->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE ) { -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ } -+ rect.r.x = rect.r.y = 0; -+ rect.r.w = rect.r.h = 0; -+ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&rect, -+ sz_rfbFramebufferUpdateRectHeader); -+ pVNC->ublen += sz_rfbFramebufferUpdateRectHeader; -+ -+ cl->rfbCursorShapeBytesSent += sz_rfbFramebufferUpdateRectHeader; -+ cl->rfbCursorShapeUpdatesSent++; -+ -+ return TRUE; -+ } -+ -+ /* Calculate data sizes. */ -+ -+ bitmapRowBytes = (pCursor->bits->width + 7) / 8; -+ paddedRowBytes = PixmapBytePad(pCursor->bits->width, 1); -+ maskBytes = bitmapRowBytes * pCursor->bits->height; -+ dataBytes = (cl->useRichCursorEncoding) ? -+ (pCursor->bits->width * pCursor->bits->height * -+ (cl->format.bitsPerPixel / 8)) : maskBytes; -+ -+ /* Send buffer contents if needed. */ -+ -+ if ( pVNC->ublen + sz_rfbFramebufferUpdateRectHeader + -+ sz_rfbXCursorColors + maskBytes + dataBytes > UPDATE_BUF_SIZE ) { -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ } -+ -+ if ( pVNC->ublen + sz_rfbFramebufferUpdateRectHeader + -+ sz_rfbXCursorColors + maskBytes + dataBytes > UPDATE_BUF_SIZE ) { -+ return FALSE; /* FIXME. */ -+ } -+ -+ saved_ublen = pVNC->ublen; -+ -+ /* Prepare rectangle header. */ -+ -+ rect.r.x = Swap16IfLE(pCursor->bits->xhot); -+ rect.r.y = Swap16IfLE(pCursor->bits->yhot); -+ rect.r.w = Swap16IfLE(pCursor->bits->width); -+ rect.r.h = Swap16IfLE(pCursor->bits->height); -+ -+ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&rect,sz_rfbFramebufferUpdateRectHeader); -+ pVNC->ublen += sz_rfbFramebufferUpdateRectHeader; -+ -+ /* Prepare actual cursor data (depends on encoding used). */ -+ -+ if (!cl->useRichCursorEncoding) { -+ /* XCursor encoding. */ -+ colors.foreRed = (char)(pCursor->foreRed >> 8); -+ colors.foreGreen = (char)(pCursor->foreGreen >> 8); -+ colors.foreBlue = (char)(pCursor->foreBlue >> 8); -+ colors.backRed = (char)(pCursor->backRed >> 8); -+ colors.backGreen = (char)(pCursor->backGreen >> 8); -+ colors.backBlue = (char)(pCursor->backBlue >> 8); -+ -+ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&colors, sz_rfbXCursorColors); -+ pVNC->ublen += sz_rfbXCursorColors; -+ -+ bitmapData = (CARD8 *)pCursor->bits->source; -+ -+ for (i = 0; i < pCursor->bits->height; i++) { -+ for (j = 0; j < bitmapRowBytes; j++) { -+ bitmapByte = bitmapData[i * paddedRowBytes + j]; -+ if (screenInfo.bitmapBitOrder == LSBFirst) { -+ bitmapByte = _reverse_byte[bitmapByte]; -+ } -+ pVNC->updateBuf[pVNC->ublen++] = (char)bitmapByte; -+ } -+ } -+ } else { -+ /* RichCursor encoding. */ -+ switch (cl->format.bitsPerPixel) { -+ case 8: -+ pVNC->ublen += EncodeRichCursorData8(&pVNC->updateBuf[pVNC->ublen], -+ &cl->format, pCursor); -+ break; -+ case 16: -+ pVNC->ublen += EncodeRichCursorData16(pScreen, &pVNC->updateBuf[pVNC->ublen], -+ &cl->format, pCursor); -+ break; -+ case 32: -+ pVNC->ublen += EncodeRichCursorData32(pScreen, &pVNC->updateBuf[pVNC->ublen], -+ &cl->format, pCursor); -+ break; -+ default: -+ return FALSE; -+ } -+ } -+ -+ /* Prepare transparency mask. */ -+ -+ bitmapData = (CARD8 *)pCursor->bits->mask; -+ -+ for (i = 0; i < pCursor->bits->height; i++) { -+ for (j = 0; j < bitmapRowBytes; j++) { -+ bitmapByte = bitmapData[i * paddedRowBytes + j]; -+ if (screenInfo.bitmapBitOrder == LSBFirst) { -+ bitmapByte = _reverse_byte[bitmapByte]; -+ } -+ pVNC->updateBuf[pVNC->ublen++] = (char)bitmapByte; -+ } -+ } -+ -+ /* Update statistics. */ -+ -+ cl->rfbCursorShapeBytesSent += (pVNC->ublen - saved_ublen); -+ cl->rfbCursorShapeUpdatesSent++; -+ -+ return TRUE; -+} -+ -+/* -+ * Send cursor position (PointerPos pseudo-encoding). -+ */ -+Bool -+rfbSendCursorPos(cl, pScreen) -+ rfbClientPtr cl; -+ ScreenPtr pScreen; -+{ -+ VNCSCREENPTR(pScreen); -+ rfbFramebufferUpdateRectHeader rect; -+#if XFREE86VNC -+ ScreenPtr pCursorScreen = miPointerCurrentScreen(); -+#endif -+ int x, y; -+ -+ if (pVNC->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) { -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ } -+ -+#if XFREE86VNC -+ if (pScreen == pCursorScreen) -+ miPointerPosition(&x, &y); -+#else -+ rfbSpriteGetCursorPos(pScreen, &x, &y); -+#endif -+ -+ rect.encoding = Swap32IfLE(rfbEncodingPointerPos); -+ rect.r.x = Swap16IfLE((CARD16)x); -+ rect.r.y = Swap16IfLE((CARD16)y); -+ rect.r.w = 0; -+ rect.r.h = 0; -+ -+ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&rect, -+ sz_rfbFramebufferUpdateRectHeader); -+ pVNC->ublen += sz_rfbFramebufferUpdateRectHeader; -+ -+ cl->rfbCursorPosBytesSent += sz_rfbFramebufferUpdateRectHeader; -+ cl->rfbCursorPosUpdatesSent++; -+ -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ -+ cl->cursorX = x; -+ cl->cursorY = y; -+ -+ return TRUE; -+} -+ -+/* -+ * Code to convert cursor source bitmap to the desired pixel format. -+ */ -+ -+#define RGB48_TO_PIXEL(fmt,r,g,b) \ -+ (((CARD32)(r) * ((fmt)->redMax + 1) >> 16) << (fmt)->redShift | \ -+ ((CARD32)(g) * ((fmt)->greenMax + 1) >> 16) << (fmt)->greenShift | \ -+ ((CARD32)(b) * ((fmt)->blueMax + 1) >> 16) << (fmt)->blueShift) -+ -+static int -+EncodeRichCursorData8(buf, fmt, pCursor) -+ char *buf; -+ rfbPixelFormat *fmt; -+ CursorPtr pCursor; -+{ -+ int widthPixels, widthBytes; -+ int x, y, b; -+ CARD8 *src; -+ char pix[2]; -+ CARD8 bitmapByte; -+ -+ pix[0] = (char)RGB48_TO_PIXEL(fmt, pCursor->backRed, pCursor->backGreen, -+ pCursor->backBlue); -+ pix[1] = (char)RGB48_TO_PIXEL(fmt, pCursor->foreRed, pCursor->foreGreen, -+ pCursor->foreBlue); -+ -+ src = (CARD8 *)pCursor->bits->source; -+ widthPixels = pCursor->bits->width; -+ widthBytes = PixmapBytePad(widthPixels, 1); -+ -+ for (y = 0; y < pCursor->bits->height; y++) { -+ for (x = 0; x < widthPixels / 8; x++) { -+ bitmapByte = src[y * widthBytes + x]; -+ if (screenInfo.bitmapBitOrder == LSBFirst) { -+ bitmapByte = _reverse_byte[bitmapByte]; -+ } -+ for (b = 7; b >= 0; b--) { -+ *buf++ = pix[bitmapByte >> b & 1]; -+ } -+ } -+ if (widthPixels % 8) { -+ bitmapByte = src[y * widthBytes + x]; -+ if (screenInfo.bitmapBitOrder == LSBFirst) { -+ bitmapByte = _reverse_byte[bitmapByte]; -+ } -+ for (b = 7; b > 7 - widthPixels % 8; b--) { -+ *buf++ = pix[bitmapByte >> b & 1]; -+ } -+ } -+ } -+ -+ return (widthPixels * pCursor->bits->height); -+} -+ -+#define DEFINE_RICH_ENCODE(bpp) \ -+ \ -+static int \ -+EncodeRichCursorData##bpp(pScreen, buf, fmt, pCursor) \ -+ ScreenPtr pScreen; \ -+ char *buf; \ -+ rfbPixelFormat *fmt; \ -+ CursorPtr pCursor; \ -+{ \ -+ VNCSCREENPTR(pScreen); \ -+ int widthPixels, widthBytes; \ -+ int x, y, b; \ -+ CARD8 *src; \ -+ CARD##bpp pix[2]; \ -+ CARD8 bitmapByte; \ -+ \ -+ pix[0] = (CARD##bpp)RGB48_TO_PIXEL(fmt, pCursor->backRed, \ -+ pCursor->backGreen, \ -+ pCursor->backBlue); \ -+ pix[1] = (CARD##bpp)RGB48_TO_PIXEL(fmt, pCursor->foreRed, \ -+ pCursor->foreGreen, \ -+ pCursor->foreBlue); \ -+ if (!pVNC->rfbServerFormat.bigEndian != !fmt->bigEndian) { \ -+ pix[0] = Swap##bpp(pix[0]); \ -+ pix[1] = Swap##bpp(pix[1]); \ -+ } \ -+ \ -+ src = (CARD8 *)pCursor->bits->source; \ -+ widthPixels = pCursor->bits->width; \ -+ widthBytes = PixmapBytePad(widthPixels, 1); \ -+ \ -+ for (y = 0; y < pCursor->bits->height; y++) { \ -+ for (x = 0; x < widthPixels / 8; x++) { \ -+ bitmapByte = src[y * widthBytes + x]; \ -+ if (screenInfo.bitmapBitOrder == LSBFirst) { \ -+ bitmapByte = _reverse_byte[bitmapByte]; \ -+ } \ -+ for (b = 7; b >= 0; b--) { \ -+ memcpy (buf, (char *)&pix[bitmapByte >> b & 1], \ -+ sizeof(CARD##bpp)); \ -+ buf += sizeof(CARD##bpp); \ -+ } \ -+ } \ -+ if (widthPixels % 8) { \ -+ bitmapByte = src[y * widthBytes + x]; \ -+ if (screenInfo.bitmapBitOrder == LSBFirst) { \ -+ bitmapByte = _reverse_byte[bitmapByte]; \ -+ } \ -+ for (b = 7; b > 7 - widthPixels % 8; b--) { \ -+ memcpy (buf, (char *)&pix[bitmapByte >> b & 1], \ -+ sizeof(CARD##bpp)); \ -+ buf += sizeof(CARD##bpp); \ -+ } \ -+ } \ -+ } \ -+ \ -+ return (widthPixels * pCursor->bits->height * (bpp / 8)); \ -+} -+ -+DEFINE_RICH_ENCODE(16) -+DEFINE_RICH_ENCODE(32) -+ -diff --git a/hw/xfree86/vnc/cutpaste.c b/hw/xfree86/vnc/cutpaste.c -new file mode 100644 -index 0000000..13aebbb ---- /dev/null -+++ b/hw/xfree86/vnc/cutpaste.c -@@ -0,0 +1,87 @@ -+/* -+ * cutpaste.c - routines to deal with cut & paste buffers / selection. -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ */ -+ -+/* -+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. -+ * -+ * This is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This software is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this software; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -+ * USA. -+ */ -+ -+#include -+#define NEED_EVENTS -+#include -+#include -+#include -+#include "rfb.h" -+#include "selection.h" -+#include "input.h" -+ -+extern Selection *CurrentSelections; -+extern int NumCurrentSelections; -+ -+ -+static Bool inSetXCutText = FALSE; -+ -+/* -+ * rfbSetXCutText sets the cut buffer to be the given string. We also clear -+ * the primary selection. Ideally we'd like to set it to the same thing, but I -+ * can't work out how to do that without some kind of helper X client. -+ */ -+ -+void -+rfbSetXCutText(char *str, int len) -+{ -+ int i = 0; -+ -+ inSetXCutText = TRUE; -+ ChangeWindowProperty(WindowTable[0], XA_CUT_BUFFER0, XA_STRING, -+ 8, PropModeReplace, len, -+ (pointer)str, TRUE); -+ -+ while ((i < NumCurrentSelections) && -+ CurrentSelections[i].selection != XA_PRIMARY) -+ i++; -+ -+ if (i < NumCurrentSelections) { -+ xEvent event; -+ -+ if (CurrentSelections[i].client) { -+ event.u.u.type = SelectionClear; -+ event.u.selectionClear.time = GetTimeInMillis(); -+ event.u.selectionClear.window = CurrentSelections[i].window; -+ event.u.selectionClear.atom = CurrentSelections[i].selection; -+ (void) TryClientEvents (CurrentSelections[i].client, &event, 1, -+ NoEventMask, NoEventMask /* CantBeFiltered */, -+ NullGrab); -+ } -+ -+ CurrentSelections[i].window = None; -+ CurrentSelections[i].pWin = NULL; -+ CurrentSelections[i].client = NullClient; -+ } -+ -+ inSetXCutText = FALSE; -+} -+ -+ -+void rfbGotXCutText(char *str, int len) -+{ -+ if (!inSetXCutText) -+ rfbSendServerCutText(str, len); -+} -diff --git a/hw/xfree86/vnc/draw.c b/hw/xfree86/vnc/draw.c -new file mode 100644 -index 0000000..889db6f ---- /dev/null -+++ b/hw/xfree86/vnc/draw.c -@@ -0,0 +1,2108 @@ -+/* -+ * draw.c - drawing routines for the RFB X server. This is a set of -+ * wrappers around the standard MI/MFB/CFB drawing routines which work out -+ * to a fair approximation the region of the screen being modified by the -+ * drawing. If the RFB client is ready then the modified region of the screen -+ * is sent to the client, otherwise the modified region will simply grow with -+ * each drawing request until the client is ready. -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ */ -+ -+/* -+ * 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) 1989 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 "rfb.h" -+ -+int rfbDeferUpdateTime = 40; /* ms */ -+ -+ -+/****************************************************************************/ -+/* -+ * Macro definitions -+ */ -+/****************************************************************************/ -+ -+#define TRC(x) /* (rfbLog x) */ -+ -+/* ADD_TO_MODIFIED_REGION adds the given region to the modified region for each -+ client */ -+ -+#define ADD_TO_MODIFIED_REGION(pScreen,reg) \ -+ { \ -+ rfbClientPtr cl; \ -+ for (cl = rfbClientHead; cl; cl = cl->next) { \ -+ REGION_UNION((pScreen),&cl->modifiedRegion,&cl->modifiedRegion,reg);\ -+ } \ -+ } -+ -+/* SCHEDULE_FB_UPDATE is used at the end of each drawing routine to schedule an -+ update to be sent to each client if there is one pending and the client is -+ ready for it. */ -+ -+#define SCHEDULE_FB_UPDATE(pScreen,pVNC) \ -+ if (!pVNC->dontSendFramebufferUpdate) { \ -+ rfbClientPtr cl, nextCl; \ -+ for (cl = rfbClientHead; cl; cl = nextCl) { \ -+ nextCl = cl->next; \ -+ if (!cl->deferredUpdateScheduled && FB_UPDATE_PENDING(cl) && \ -+ REGION_NOTEMPTY(pScreen,&cl->requestedRegion)) \ -+ { \ -+ rfbScheduleDeferredUpdate(pScreen, cl); \ -+ } \ -+ } \ -+ } -+ -+/* function prototypes */ -+ -+static void rfbScheduleDeferredUpdate(ScreenPtr pScreen, rfbClientPtr cl); -+static void rfbCopyRegion(ScreenPtr pScreen, rfbClientPtr cl, -+ RegionPtr src, RegionPtr dst, int dx, int dy); -+#ifdef DEBUG -+static void PrintRegion(ScreenPtr pScreen, RegionPtr reg); -+#endif -+ -+/* GC funcs */ -+ -+static void rfbValidateGC(GCPtr, unsigned long /*changes*/, DrawablePtr); -+static void rfbChangeGC(GCPtr, unsigned long /*mask*/); -+static void rfbCopyGC(GCPtr /*src*/, unsigned long /*mask*/, GCPtr /*dst*/); -+static void rfbDestroyGC(GCPtr); -+static void rfbChangeClip(GCPtr, int /*type*/, pointer /*pValue*/, -+ int /*nrects*/); -+static void rfbDestroyClip(GCPtr); -+static void rfbCopyClip(GCPtr /*dst*/, GCPtr /*src*/); -+ -+/* GC ops */ -+ -+static void rfbFillSpans(DrawablePtr pDrawable, GCPtr pGC, int nInit, DDXPointPtr pptInit, int *pwidthInit, int fSorted); -+static void rfbSetSpans(DrawablePtr pDrawable, -+ GCPtr pGC, -+ char *psrc, -+ register DDXPointPtr ppt, -+ int *pwidth, -+ int nspans, -+ int fSorted); -+static void rfbPutImage(); -+static RegionPtr rfbCopyArea(); -+static RegionPtr rfbCopyPlane(); -+static void rfbPolyPoint(); -+static void rfbPolylines (DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, DDXPointPtr ppts); -+static void rfbPolySegment(); -+static void rfbPolyRectangle(); -+static void rfbPolyArc(); -+static void rfbFillPolygon(); -+static void rfbPolyFillRect(); -+static void rfbPolyFillArc(); -+static int rfbPolyText8(); -+static int rfbPolyText16(); -+static void rfbImageText8(); -+static void rfbImageText16(); -+static void rfbImageGlyphBlt(); -+static void rfbPolyGlyphBlt(); -+static void rfbPushPixels(); -+ -+ -+static GCFuncs rfbGCFuncs = { -+ rfbValidateGC, -+ rfbChangeGC, -+ rfbCopyGC, -+ rfbDestroyGC, -+ rfbChangeClip, -+ rfbDestroyClip, -+ rfbCopyClip, -+}; -+ -+ -+static GCOps rfbGCOps = { -+ rfbFillSpans, rfbSetSpans, rfbPutImage, -+ rfbCopyArea, rfbCopyPlane, rfbPolyPoint, -+ rfbPolylines, rfbPolySegment, rfbPolyRectangle, -+ rfbPolyArc, rfbFillPolygon, rfbPolyFillRect, -+ rfbPolyFillArc, rfbPolyText8, rfbPolyText16, -+ rfbImageText8, rfbImageText16, rfbImageGlyphBlt, -+ rfbPolyGlyphBlt, rfbPushPixels -+}; -+ -+ -+ -+/****************************************************************************/ -+/* -+ * Screen functions wrapper stuff -+ */ -+/****************************************************************************/ -+ -+#define SCREEN_PROLOGUE(scrn, field) \ -+ ScreenPtr pScreen = scrn; \ -+ VNCSCREENPTR(pScreen); \ -+ pScreen->field = pVNC->field; -+ -+#define SCREEN_EPILOGUE(field, wrapper) \ -+ pScreen->field = wrapper; -+ -+ -+/* -+ * CloseScreen wrapper -- unwrap everything, free the private data -+ * and call the wrapped CloseScreen function. -+ */ -+ -+Bool -+rfbCloseScreen (int i, ScreenPtr pScreen) -+{ -+ VNCSCREENPTR(pScreen); -+#if XFREE86VNC -+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; -+#endif -+ int sock; -+ -+ for (sock = 0; sock <= pVNC->maxFd; sock++) { -+ if (FD_ISSET(sock, &pVNC->allFds)) -+ if (sock != pVNC->rfbListenSock && sock != pVNC->httpListenSock) { -+ rfbCloseSock(pScreen, sock); -+ } -+ } -+ -+ if (pVNC->rfbListenSock > 0) -+ if (close(pVNC->rfbListenSock)) -+ ErrorF("Close of port %d failed\n",pVNC->rfbPort); -+ -+ if (pVNC->httpListenSock > 0) -+ if (close(pVNC->httpListenSock)) -+ ErrorF("Close of port %d failed\n",pVNC->httpPort); -+ -+ pScreen->CloseScreen = pVNC->CloseScreen; -+ pScreen->CreateGC = pVNC->CreateGC; -+ pScreen->PaintWindowBackground = pVNC->PaintWindowBackground; -+ pScreen->PaintWindowBorder = pVNC->PaintWindowBorder; -+ pScreen->CopyWindow = pVNC->CopyWindow; -+ pScreen->ClearToBackground = pVNC->ClearToBackground; -+ pScreen->RestoreAreas = pVNC->RestoreAreas; -+ pScreen->WakeupHandler = pVNC->WakeupHandler; -+ -+#if XFREE86VNC -+ pScreen->InstallColormap = pVNC->InstallColormap; -+ pScreen->UninstallColormap = pVNC->UninstallColormap; -+ pScreen->ListInstalledColormaps = pVNC->ListInstalledColormaps; -+ pScreen->StoreColors = pVNC->StoreColors; -+ pScrn->EnableDisableFBAccess = pVNC->EnableDisableFBAccess; -+ -+ xfree(pVNC); -+#endif -+ -+ TRC((stderr,"Unwrapped screen functions\n")); -+ -+ return (*pScreen->CloseScreen) (i, pScreen); -+} -+ -+#if XFREE86VNC -+void -+rfbEnableDisableFBAccess (int index, Bool enable) -+{ -+ ScrnInfoPtr pScrn = xf86Screens[index]; -+ VNCSCREENPTR(pScrn->pScreen); -+ -+ /* -+ * Blank the screen for security while inputs are disabled. -+ * When VT switching is fixed, we might be able to allow -+ * control even when switched away. -+ */ -+ if (!enable) { -+ WindowPtr pWin = WindowTable[index]; -+ ScreenPtr pScreen = pWin->drawable.pScreen; -+ GCPtr pGC; -+ xRectangle rect; -+ -+ rect.x = 0; -+ rect.y = 0; -+ rect.width = pScrn->virtualX; -+ rect.height = pScrn->virtualY; -+ -+ if (!(pGC = GetScratchGC(pScreen->rootDepth, pScreen))) { -+ ErrorF("Couldn't blank screen"); -+ } else { -+ CARD32 attributes[2]; -+ attributes[0] = pScreen->whitePixel; -+ attributes[1] = pScreen->blackPixel; -+ (void)ChangeGC(pGC, GCForeground | GCBackground, attributes); -+ -+ ValidateGC((DrawablePtr)pWin, pGC); -+ -+ (*pGC->ops->PolyFillRect)((DrawablePtr)pWin, pGC, 1, &rect); -+ -+ FreeScratchGC(pGC); -+ -+ /* Flush pending packets */ -+ rfbCheckFds(pScreen); -+ httpCheckFds(pScreen); -+ } -+ } -+ -+ pScrn->EnableDisableFBAccess = pVNC->EnableDisableFBAccess; -+ (*pScrn->EnableDisableFBAccess)(index, enable); -+ pScrn->EnableDisableFBAccess = rfbEnableDisableFBAccess; -+} -+#endif -+ -+/* -+ * CreateGC - wrap the GC funcs (the GC ops will be wrapped when the GC -+ * func "ValidateGC" is called). -+ */ -+ -+Bool -+rfbCreateGC (GCPtr pGC) -+{ -+ Bool ret; -+ rfbGCPtr pGCPriv; -+ -+ SCREEN_PROLOGUE(pGC->pScreen,CreateGC); -+ -+ pGCPriv = (rfbGCPtr)pGC->devPrivates[rfbGCIndex].ptr; -+ -+ ret = (*pScreen->CreateGC) (pGC); -+ -+ TRC((stderr,"rfbCreateGC called\n")); -+ -+ pGCPriv->wrapOps = NULL; -+ pGCPriv->wrapFuncs = pGC->funcs; -+ pGC->funcs = &rfbGCFuncs; -+ -+ SCREEN_EPILOGUE(CreateGC,rfbCreateGC); -+ -+ return ret; -+} -+ -+/* -+ * PaintWindowBackground - the region being modified is just the given region. -+ */ -+ -+void -+rfbPaintWindowBackground (WindowPtr pWin, RegionPtr pRegion, int what) -+{ -+ SCREEN_PROLOGUE(pWin->drawable.pScreen,PaintWindowBackground); -+ -+ TRC((stderr,"rfbPaintWindowBackground called\n")); -+ -+ ADD_TO_MODIFIED_REGION(pScreen,pRegion); -+ -+ (*pScreen->PaintWindowBackground) (pWin, pRegion, what); -+ -+ SCHEDULE_FB_UPDATE(pScreen, pVNC); -+ -+ SCREEN_EPILOGUE(PaintWindowBackground,rfbPaintWindowBackground); -+} -+ -+/* -+ * PaintWindowBorder - the region being modified is just the given region. -+ */ -+ -+void -+rfbPaintWindowBorder (WindowPtr pWin, RegionPtr pRegion, int what) -+{ -+ SCREEN_PROLOGUE(pWin->drawable.pScreen,PaintWindowBorder); -+ -+ TRC((stderr,"rfbPaintWindowBorder called\n")); -+ -+ ADD_TO_MODIFIED_REGION(pScreen,pRegion); -+ -+ (*pScreen->PaintWindowBorder) (pWin, pRegion, what); -+ -+ SCHEDULE_FB_UPDATE(pScreen, pVNC); -+ -+ SCREEN_EPILOGUE(PaintWindowBorder,rfbPaintWindowBorder); -+} -+ -+#ifdef CHROMIUM -+Bool -+rfbRealizeWindow(WindowPtr pWin) -+{ -+ CRWindowTable *wt = NULL, *nextWt = NULL; -+ Bool ret; -+ SCREEN_PROLOGUE(pWin->drawable.pScreen,RealizeWindow); -+ -+ for (wt = windowTable; wt; wt = nextWt) { -+ nextWt = wt->next; -+ if (wt->XwinId == pWin->drawable.id) { -+ rfbSendChromiumWindowShow(wt->CRwinId, 1); -+ } -+ } -+ -+ ret = (*pScreen->RealizeWindow)(pWin); -+ -+ SCREEN_EPILOGUE(RealizeWindow,rfbRealizeWindow); -+ -+ return ret; -+} -+ -+Bool -+rfbUnrealizeWindow(WindowPtr pWin) -+{ -+ CRWindowTable *wt = NULL, *nextWt = NULL; -+ Bool ret; -+ SCREEN_PROLOGUE(pWin->drawable.pScreen,UnrealizeWindow); -+ -+ for (wt = windowTable; wt; wt = nextWt) { -+ nextWt = wt->next; -+ if (wt->XwinId == pWin->drawable.id) { -+ rfbSendChromiumWindowShow(wt->CRwinId, 0); -+ } -+ } -+ -+ ret = (*pScreen->UnrealizeWindow)(pWin); -+ -+ SCREEN_EPILOGUE(UnrealizeWindow,rfbUnrealizeWindow); -+ -+ return ret; -+} -+ -+Bool -+rfbDestroyWindow(WindowPtr pWin) -+{ -+ CRWindowTable *wt = NULL, *nextWt = NULL; -+ Bool ret; -+ SCREEN_PROLOGUE(pWin->drawable.pScreen,DestroyWindow); -+ -+ for (wt = windowTable; wt; wt = nextWt) { -+ nextWt = wt->next; -+ if (wt->XwinId == pWin->drawable.id) { -+ rfbSendChromiumWindowShow(wt->CRwinId, 0); -+ } -+ } -+ -+ ret = (*pScreen->DestroyWindow)(pWin); -+ -+ SCREEN_EPILOGUE(DestroyWindow,rfbDestroyWindow); -+ -+ return ret; -+} -+ -+void -+rfbResizeWindow(WindowPtr pWin, int x, int y, unsigned int w, unsigned int h, WindowPtr pSib) -+{ -+ CRWindowTable *wt = NULL, *nextWt = NULL; -+ SCREEN_PROLOGUE(pWin->drawable.pScreen,ResizeWindow); -+ -+ for (wt = windowTable; wt; wt = nextWt) { -+ nextWt = wt->next; -+ if (wt->XwinId == pWin->drawable.id) { -+ rfbSendChromiumMoveResizeWindow(wt->CRwinId, pWin->drawable.x, pWin->drawable.y, w, h); -+ } -+ } -+ -+ (*pScreen->ResizeWindow)(pWin, x, y, w, h, pSib); -+ -+ SCREEN_EPILOGUE(ResizeWindow,rfbResizeWindow); -+} -+ -+Bool -+rfbPositionWindow(WindowPtr pWin, int x, int y) -+{ -+ Bool ret; -+ CRWindowTable *wt, *nextWt; -+ SCREEN_PROLOGUE(pWin->drawable.pScreen,PositionWindow); -+ -+ for (wt = windowTable; wt; wt = nextWt) { -+ nextWt = wt->next; -+ if (wt->XwinId == pWin->drawable.id) { -+ rfbSendChromiumMoveResizeWindow(wt->CRwinId, x, y, pWin->drawable.width, pWin->drawable.height); -+ } -+ } -+ -+ ret = (*pScreen->PositionWindow)(pWin, x, y); -+ -+ SCREEN_EPILOGUE(PositionWindow,rfbPositionWindow); -+ -+ return ret; -+} -+ -+void -+rfbClipNotify(WindowPtr pWin, int x, int y) -+{ -+ CRWindowTable *wt, *nextWt; -+ SCREEN_PROLOGUE(pWin->drawable.pScreen,ClipNotify); -+ -+ for (wt = windowTable; wt; wt = nextWt) { -+ nextWt = wt->next; -+ if (wt->XwinId == pWin->drawable.id) { -+ int numClipRects = REGION_NUM_RECTS(&pWin->clipList); -+ BoxPtr pClipRects = REGION_RECTS(&pWin->clipList); -+ -+ /* Possible optimization - has the cliplist really? changed */ -+ -+ rfbSendChromiumClipList(wt->CRwinId, pClipRects, numClipRects); -+ } -+ } -+ -+ if (*pScreen->ClipNotify) -+ (*pScreen->ClipNotify)(pWin, x, y); -+ -+ SCREEN_EPILOGUE(ClipNotify,rfbClipNotify); -+} -+#endif /* CHROMIUM */ -+ -+/* -+ * CopyWindow - the region being modified is the translation of the old -+ * region, clipped to the border clip region of the window. Note that any -+ * parts of the window which have become newly-visible will not be affected by -+ * this call - a separate PaintWindowBackground/Border will be called to do -+ * that. If the client will accept CopyRect messages then use rfbCopyRegion to -+ * optimise the pending screen changes into a single "copy region" plus the -+ * ordinary modified region. -+ */ -+ -+void -+rfbCopyWindow (WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr pOldRegion) -+{ -+ rfbClientPtr cl; -+ RegionRec srcRegion, dstRegion; -+ SCREEN_PROLOGUE(pWin->drawable.pScreen,CopyWindow); -+ -+ TRC((stderr,"rfbCopyWindow called\n")); -+ -+ REGION_NULL(pScreen,&dstRegion); -+ REGION_COPY(pScreen,&dstRegion,pOldRegion); -+ REGION_TRANSLATE(pWin->drawable.pScreen, &dstRegion, -+ pWin->drawable.x - ptOldOrg.x, -+ pWin->drawable.y - ptOldOrg.y); -+ REGION_INTERSECT(pWin->drawable.pScreen, &dstRegion, &dstRegion, -+ &pWin->borderClip); -+ -+ for (cl = rfbClientHead; cl; cl = cl->next) { -+ if (cl->useCopyRect) { -+ REGION_NULL(pScreen,&srcRegion); -+ REGION_COPY(pScreen,&srcRegion,pOldRegion); -+ -+ rfbCopyRegion(pScreen, cl, &srcRegion, &dstRegion, -+ pWin->drawable.x - ptOldOrg.x, -+ pWin->drawable.y - ptOldOrg.y); -+ -+ REGION_UNINIT(pScreen, &srcRegion); -+ -+ } else { -+ -+ REGION_UNION(pScreen, &cl->modifiedRegion, &cl->modifiedRegion, -+ &dstRegion); -+ } -+ } -+ -+ REGION_UNINIT(pScreen, &dstRegion); -+ -+ (*pScreen->CopyWindow) (pWin, ptOldOrg, pOldRegion); -+ -+ SCHEDULE_FB_UPDATE(pScreen, pVNC); -+ -+ SCREEN_EPILOGUE(CopyWindow,rfbCopyWindow); -+} -+ -+/* -+ * ClearToBackground - when generateExposures is false, the region being -+ * modified is the given rectangle (clipped to the "window clip region"). -+ */ -+ -+void -+rfbClearToBackground (WindowPtr pWin, int x, int y, int w, int h, -+ Bool generateExposures) -+{ -+ RegionRec tmpRegion; -+ BoxRec box; -+ SCREEN_PROLOGUE(pWin->drawable.pScreen,ClearToBackground); -+ -+ TRC((stderr,"rfbClearToBackground called\n")); -+ -+ if (!generateExposures) { -+ 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); -+ -+ SAFE_REGION_INIT(pScreen, &tmpRegion, &box, 0); -+ -+ REGION_INTERSECT(pScreen, &tmpRegion, &tmpRegion, &pWin->clipList); -+ -+ ADD_TO_MODIFIED_REGION(pScreen, &tmpRegion); -+ -+ REGION_UNINIT(pScreen, &tmpRegion); -+ } -+ -+ (*pScreen->ClearToBackground) (pWin, x, y, w, h, generateExposures); -+ -+ if (!generateExposures) { -+ SCHEDULE_FB_UPDATE(pScreen, pVNC); -+ } -+ -+ SCREEN_EPILOGUE(ClearToBackground,rfbClearToBackground); -+} -+ -+/* -+ * RestoreAreas - just be safe here - the region being modified is the whole -+ * exposed region. -+ */ -+ -+RegionPtr -+rfbRestoreAreas (WindowPtr pWin, RegionPtr prgnExposed) -+{ -+ RegionPtr result; -+ SCREEN_PROLOGUE(pWin->drawable.pScreen,RestoreAreas); -+ -+ TRC((stderr,"rfbRestoreAreas called\n")); -+ -+ ADD_TO_MODIFIED_REGION(pScreen, prgnExposed); -+ -+ result = (*pScreen->RestoreAreas) (pWin, prgnExposed); -+ -+ SCHEDULE_FB_UPDATE(pScreen, pVNC); -+ -+ SCREEN_EPILOGUE(RestoreAreas,rfbRestoreAreas); -+ -+ return result; -+} -+ -+ -+ -+/****************************************************************************/ -+/* -+ * GC funcs wrapper stuff -+ * -+ * We only really want to wrap the GC ops, but to do this we need to wrap -+ * ValidateGC and so all the other GC funcs must be wrapped as well. -+ */ -+/****************************************************************************/ -+ -+#define GC_FUNC_PROLOGUE(pGC) \ -+ rfbGCPtr pGCPriv = (rfbGCPtr) (pGC)->devPrivates[rfbGCIndex].ptr; \ -+ (pGC)->funcs = pGCPriv->wrapFuncs; \ -+ if (pGCPriv->wrapOps) \ -+ (pGC)->ops = pGCPriv->wrapOps; -+ -+#define GC_FUNC_EPILOGUE(pGC) \ -+ pGCPriv->wrapFuncs = (pGC)->funcs; \ -+ (pGC)->funcs = &rfbGCFuncs; \ -+ if (pGCPriv->wrapOps) { \ -+ pGCPriv->wrapOps = (pGC)->ops; \ -+ (pGC)->ops = &rfbGCOps; \ -+ } -+ -+ -+/* -+ * ValidateGC - call the wrapped ValidateGC, then wrap the resulting GC ops if -+ * the drawing will be to a viewable window. -+ */ -+ -+static void -+rfbValidateGC (GCPtr pGC, unsigned long changes, DrawablePtr pDrawable) -+{ -+ VNCSCREENPTR(pGC->pScreen); -+ GC_FUNC_PROLOGUE(pGC); -+ -+ TRC((stderr,"rfbValidateGC called\n")); -+ -+ (*pGC->funcs->ValidateGC) (pGC, changes, pDrawable); -+ -+ pGCPriv->wrapOps = NULL; -+ 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)) { -+ pGCPriv->wrapOps = pGC->ops; -+ TRC((stderr,"rfbValidateGC: wrapped GC ops\n")); -+ } -+ } -+ -+ GC_FUNC_EPILOGUE(pGC); -+} -+ -+/* -+ * All other GC funcs simply unwrap the GC funcs and ops, call the wrapped -+ * function and then rewrap the funcs and ops. -+ */ -+ -+static void -+rfbChangeGC (pGC, mask) -+ GCPtr pGC; -+ unsigned long mask; -+{ -+ GC_FUNC_PROLOGUE(pGC); -+ (*pGC->funcs->ChangeGC) (pGC, mask); -+ GC_FUNC_EPILOGUE(pGC); -+} -+ -+static void -+rfbCopyGC (pGCSrc, mask, pGCDst) -+ GCPtr pGCSrc, pGCDst; -+ unsigned long mask; -+{ -+ GC_FUNC_PROLOGUE(pGCDst); -+ (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst); -+ GC_FUNC_EPILOGUE(pGCDst); -+} -+ -+static void -+rfbDestroyGC (pGC) -+ GCPtr pGC; -+{ -+ GC_FUNC_PROLOGUE(pGC); -+ (*pGC->funcs->DestroyGC) (pGC); -+ GC_FUNC_EPILOGUE(pGC); -+} -+ -+static void -+rfbChangeClip (pGC, type, pvalue, nrects) -+ GCPtr pGC; -+ int type; -+ pointer pvalue; -+ int nrects; -+{ -+ GC_FUNC_PROLOGUE(pGC); -+ (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects); -+ GC_FUNC_EPILOGUE(pGC); -+} -+ -+static void -+rfbDestroyClip(pGC) -+ GCPtr pGC; -+{ -+ GC_FUNC_PROLOGUE(pGC); -+ (* pGC->funcs->DestroyClip)(pGC); -+ GC_FUNC_EPILOGUE(pGC); -+} -+ -+static void -+rfbCopyClip(pgcDst, pgcSrc) -+ GCPtr pgcDst, pgcSrc; -+{ -+ GC_FUNC_PROLOGUE(pgcDst); -+ (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc); -+ GC_FUNC_EPILOGUE(pgcDst); -+} -+ -+ -+/****************************************************************************/ -+/* -+ * GC ops wrapper stuff -+ * -+ * Note that these routines will only have been wrapped for drawing to -+ * viewable windows so we don't need to check each time that the drawable -+ * is a viewable window. -+ */ -+/****************************************************************************/ -+ -+#define GC_OP_PROLOGUE(pDrawable,pGC) \ -+ ScreenPtr pScreen = pGC->pScreen; \ -+ VNCSCREENPTR(pScreen); \ -+ rfbGCPtr pGCPrivate = (rfbGCPtr) (pGC)->devPrivates[rfbGCIndex].ptr; \ -+ GCFuncs *oldFuncs = pGC->funcs; \ -+ (void) pScreen; /* silence compiler */ \ -+ (pGC)->funcs = pGCPrivate->wrapFuncs; \ -+ (pGC)->ops = pGCPrivate->wrapOps; -+ -+#define GC_OP_EPILOGUE(pGC) \ -+ pGCPrivate->wrapOps = (pGC)->ops; \ -+ (pGC)->funcs = oldFuncs; \ -+ (pGC)->ops = &rfbGCOps; -+ -+ -+/* -+ * FillSpans - being very safe - the region being modified is the border clip -+ * region of the window. -+ */ -+ -+static void -+rfbFillSpans(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted) -+ DrawablePtr pDrawable; -+ GCPtr pGC; -+ int nInit; /* number of spans to fill */ -+ DDXPointPtr pptInit; /* pointer to list of start points */ -+ int *pwidthInit; /* pointer to list of n widths */ -+ int fSorted; -+{ -+ GC_OP_PROLOGUE(pDrawable,pGC); -+ -+ TRC((stderr,"rfbFillSpans called\n")); -+ -+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, -+ &((WindowPtr)pDrawable)->borderClip); -+ -+ (*pGC->ops->FillSpans) (pDrawable, pGC, nInit, pptInit,pwidthInit,fSorted); -+ -+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); -+ -+ GC_OP_EPILOGUE(pGC); -+} -+ -+/* -+ * SetSpans - being very safe - the region being modified is the border clip -+ * region of the window. -+ */ -+ -+static void -+rfbSetSpans(DrawablePtr pDrawable, -+ GCPtr pGC, -+ char *psrc, -+ register DDXPointPtr ppt, -+ int *pwidth, -+ int nspans, -+ int fSorted) -+{ -+ GC_OP_PROLOGUE(pDrawable,pGC); -+ -+ TRC((stderr,"rfbSetSpans called\n")); -+ -+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, -+ &((WindowPtr)pDrawable)->borderClip); -+ -+ (*pGC->ops->SetSpans) (pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted); -+ -+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); -+ -+ GC_OP_EPILOGUE(pGC); -+} -+ -+/* -+ * PutImage - the region being modified is the rectangle of the -+ * PutImage (clipped to the window clip region). -+ */ -+ -+static void -+rfbPutImage(pDrawable, pGC, depth, x, y, w, h, leftPad, format, pBits) -+ DrawablePtr pDrawable; -+ GCPtr pGC; -+ int depth; -+ int x; -+ int y; -+ int w; -+ int h; -+ int leftPad; -+ int format; -+ char *pBits; -+{ -+ RegionRec tmpRegion; -+ BoxRec box; -+ GC_OP_PROLOGUE(pDrawable, pGC); -+ -+ TRC((stderr,"rfbPutImage called\n")); -+ -+ box.x1 = x + pDrawable->x; -+ box.y1 = y + pDrawable->y; -+ box.x2 = box.x1 + w; -+ box.y2 = box.y1 + h; -+ -+ SAFE_REGION_INIT(pDrawable->pScreen, &tmpRegion, &box, 0); -+ -+ REGION_INTERSECT(pDrawable->pScreen, &tmpRegion, &tmpRegion, -+ pGC->pCompositeClip); -+ -+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, &tmpRegion); -+ -+ REGION_UNINIT(pDrawable->pScreen, &tmpRegion); -+ -+ (*pGC->ops->PutImage) (pDrawable, pGC, depth, x, y, w, h, -+ leftPad, format, pBits); -+ -+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); -+ -+ GC_OP_EPILOGUE(pGC); -+} -+ -+/* -+ * CopyArea - the region being modified is the destination rectangle (clipped -+ * to the window clip region). -+ * If the client will accept CopyRect messages then use rfbCopyRegion -+ * to optimise the pending screen changes into a single "copy region" plus -+ * the ordinary modified region. -+ */ -+ -+static RegionPtr -+rfbCopyArea (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty) -+ DrawablePtr pSrc; -+ DrawablePtr pDst; -+ GCPtr pGC; -+ int srcx; -+ int srcy; -+ int w; -+ int h; -+ int dstx; -+ int dsty; -+{ -+ rfbClientPtr cl; -+ RegionPtr rgn; -+ RegionRec srcRegion, dstRegion; -+ BoxRec box; -+ GC_OP_PROLOGUE(pDst, pGC); -+ -+ TRC((stderr,"rfbCopyArea called\n")); -+ -+ box.x1 = dstx + pDst->x; -+ box.y1 = dsty + pDst->y; -+ box.x2 = box.x1 + w; -+ box.y2 = box.y1 + h; -+ -+ SAFE_REGION_INIT(pDst->pScreen, &dstRegion, &box, 0); -+ REGION_INTERSECT(pDst->pScreen, &dstRegion, &dstRegion, -+ pGC->pCompositeClip); -+ -+ if ((pSrc->type == DRAWABLE_WINDOW) && (pSrc->pScreen == pDst->pScreen)) { -+ box.x1 = srcx + pSrc->x; -+ box.y1 = srcy + pSrc->y; -+ box.x2 = box.x1 + w; -+ box.y2 = box.y1 + h; -+ -+ for (cl = rfbClientHead; cl; cl = cl->next) { -+ if (cl->useCopyRect) { -+ SAFE_REGION_INIT(pSrc->pScreen, &srcRegion, &box, 0); -+ REGION_INTERSECT(pSrc->pScreen, &srcRegion, &srcRegion, -+ &((WindowPtr)pSrc)->clipList); -+ -+ rfbCopyRegion(pSrc->pScreen, cl, &srcRegion, &dstRegion, -+ dstx + pDst->x - srcx - pSrc->x, -+ dsty + pDst->y - srcy - pSrc->y); -+ -+ REGION_UNINIT(pSrc->pScreen, &srcRegion); -+ -+ } else { -+ -+ REGION_UNION(pScreen, &cl->modifiedRegion, &cl->modifiedRegion, -+ &dstRegion); -+ } -+ } -+ -+ } else { -+ -+ ADD_TO_MODIFIED_REGION(pDst->pScreen, &dstRegion); -+ } -+ -+ REGION_UNINIT(pDst->pScreen, &dstRegion); -+ -+ rgn = (*pGC->ops->CopyArea) (pSrc, pDst, pGC, srcx, srcy, w, h, -+ dstx, dsty); -+ -+ SCHEDULE_FB_UPDATE(pDst->pScreen, pVNC); -+ -+ GC_OP_EPILOGUE(pGC); -+ -+ return rgn; -+} -+ -+ -+/* -+ * CopyPlane - the region being modified is the destination rectangle (clipped -+ * to the window clip region). -+ */ -+ -+static RegionPtr -+rfbCopyPlane (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty, plane) -+ DrawablePtr pSrc; -+ DrawablePtr pDst; -+ register GCPtr pGC; -+ int srcx, -+ srcy; -+ int w, -+ h; -+ int dstx, -+ dsty; -+ unsigned long plane; -+{ -+ RegionPtr rgn; -+ RegionRec tmpRegion; -+ BoxRec box; -+ GC_OP_PROLOGUE(pDst, pGC); -+ -+ TRC((stderr,"rfbCopyPlane called\n")); -+ -+ box.x1 = dstx + pDst->x; -+ box.y1 = dsty + pDst->y; -+ box.x2 = box.x1 + w; -+ box.y2 = box.y1 + h; -+ -+ SAFE_REGION_INIT(pDst->pScreen, &tmpRegion, &box, 0); -+ -+ REGION_INTERSECT(pDst->pScreen, &tmpRegion, &tmpRegion, -+ pGC->pCompositeClip); -+ -+ ADD_TO_MODIFIED_REGION(pDst->pScreen, &tmpRegion); -+ -+ REGION_UNINIT(pDst->pScreen, &tmpRegion); -+ -+ rgn = (*pGC->ops->CopyPlane) (pSrc, pDst, pGC, srcx, srcy, w, h, -+ dstx, dsty, plane); -+ -+ SCHEDULE_FB_UPDATE(pDst->pScreen, pVNC); -+ -+ GC_OP_EPILOGUE(pGC); -+ -+ return rgn; -+} -+ -+/* -+ * PolyPoint - find the smallest rectangle which encloses the points drawn -+ * (and clip). -+ */ -+ -+static void -+rfbPolyPoint (pDrawable, pGC, mode, npt, pts) -+ DrawablePtr pDrawable; -+ GCPtr pGC; -+ int mode; /* Origin or Previous */ -+ int npt; -+ xPoint *pts; -+{ -+ int i; -+ RegionRec tmpRegion; -+ BoxRec box; -+ GC_OP_PROLOGUE(pDrawable, pGC); -+ -+ TRC((stderr,"rfbPolyPoint called\n")); -+ -+ if (npt) { -+ int minX = pts[0].x, maxX = pts[0].x; -+ int minY = pts[0].y, maxY = pts[0].y; -+ -+ if (mode == CoordModePrevious) -+ { -+ int x = pts[0].x, y = pts[0].y; -+ -+ for (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 (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; -+ } -+ } -+ -+ box.x1 = minX + pDrawable->x; -+ box.y1 = minY + pDrawable->y; -+ box.x2 = maxX + 1 + pDrawable->x; -+ box.y2 = maxY + 1 + pDrawable->y; -+ -+ SAFE_REGION_INIT(pDrawable->pScreen, &tmpRegion, &box, 0); -+ -+ REGION_INTERSECT(pDrawable->pScreen, &tmpRegion, &tmpRegion, -+ pGC->pCompositeClip); -+ -+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, &tmpRegion); -+ -+ REGION_UNINIT(pDrawable->pScreen, &tmpRegion); -+ } -+ -+ (*pGC->ops->PolyPoint) (pDrawable, pGC, mode, npt, pts); -+ -+ if (npt) { -+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); -+ } -+ -+ GC_OP_EPILOGUE(pGC); -+} -+ -+/* -+ * PolyLines - take the union of bounding boxes around each line (and clip). -+ */ -+ -+static void -+rfbPolylines (DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, DDXPointPtr ppts) -+{ -+ RegionPtr tmpRegion; -+ xRectangle *rects; -+ int i, extra, nlines, lw; -+ int x1, x2, y1, y2; -+ GC_OP_PROLOGUE(pDrawable, pGC); -+ -+ TRC((stderr,"rfbPolylines called\n")); -+ -+ if (npt) { -+ lw = pGC->lineWidth; -+ if (lw == 0) -+ lw = 1; -+ -+ if (npt == 1) -+ { -+ nlines = 1; -+ rects = (xRectangle *)xalloc(sizeof(xRectangle)); -+ if (!rects) { -+ FatalError("rfbPolylines: xalloc failed\n"); -+ } -+ -+ rects[0].x = ppts[0].x - lw + pDrawable->x; /* being safe here */ -+ rects[0].y = ppts[0].y - lw + pDrawable->y; -+ rects[0].width = 2*lw; -+ rects[0].height = 2*lw; -+ } -+ else -+ { -+ nlines = npt - 1; -+ rects = (xRectangle *)xalloc(nlines*sizeof(xRectangle)); -+ if (!rects) { -+ FatalError("rfbPolylines: xalloc failed\n"); -+ } -+ -+ /* -+ * 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 -+ */ -+ -+ if (pGC->joinStyle == JoinMiter) { -+ extra = 6 * lw; -+ } else { -+ extra = lw / 2; -+ } -+ -+ x1 = ppts[0].x + pDrawable->x; -+ y1 = ppts[0].y + pDrawable->y; -+ -+ for (i = 0; i < nlines; i++) { -+ if (mode == CoordModeOrigin) { -+ x2 = pDrawable->x + ppts[i+1].x; -+ y2 = pDrawable->y + ppts[i+1].y; -+ } else { -+ x2 = x1 + ppts[i+1].x; -+ y2 = y1 + ppts[i+1].y; -+ } -+ -+ if (x1 > x2) { -+ rects[i].x = x2 - extra; -+ rects[i].width = x1 - x2 + 1 + 2 * extra; -+ } else { -+ rects[i].x = x1 - extra; -+ rects[i].width = x2 - x1 + 1 + 2 * extra; -+ } -+ -+ if (y1 > y2) { -+ rects[i].y = y2 - extra; -+ rects[i].height = y1 - y2 + 1 + 2 * extra; -+ } else { -+ rects[i].y = y1 - extra; -+ rects[i].height = y2 - y1 + 1 + 2 * extra; -+ } -+ -+ x1 = x2; -+ y1 = y2; -+ } -+ } -+ tmpRegion = RECTS_TO_REGION(pDrawable->pScreen, nlines, rects,CT_NONE); -+ REGION_INTERSECT(pDrawable->pScreen, tmpRegion, tmpRegion, -+ pGC->pCompositeClip); -+ -+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, tmpRegion); -+ -+ REGION_DESTROY(pDrawable->pScreen, tmpRegion); -+ xfree((char *)rects); -+ } -+ -+ (*pGC->ops->Polylines) (pDrawable, pGC, mode, npt, ppts); -+ -+ if (npt) { -+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); -+ } -+ -+ GC_OP_EPILOGUE(pGC); -+} -+ -+/* -+ * PolySegment - take the union of bounding boxes around each segment (and -+ * clip). -+ */ -+ -+static void -+rfbPolySegment(pDrawable, pGC, nseg, segs) -+ DrawablePtr pDrawable; -+ GCPtr pGC; -+ int nseg; -+ xSegment *segs; -+{ -+ RegionPtr tmpRegion; -+ xRectangle *rects; -+ int i, extra, lw; -+ -+ GC_OP_PROLOGUE(pDrawable, pGC); -+ -+ TRC((stderr,"rfbPolySegment called\n")); -+ -+ if (nseg) { -+ rects = (xRectangle *)xalloc(nseg*sizeof(xRectangle)); -+ if (!rects) { -+ FatalError("rfbPolySegment: xalloc failed\n"); -+ } -+ -+ lw = pGC->lineWidth; -+ if (lw == 0) -+ lw = 1; -+ -+ extra = lw / 2; -+ -+ for (i = 0; i < nseg; i++) -+ { -+ if (segs[i].x1 > segs[i].x2) { -+ rects[i].x = segs[i].x2 - extra + pDrawable->x; -+ rects[i].width = segs[i].x1 - segs[i].x2 + 1 + 2 * extra; -+ } else { -+ rects[i].x = segs[i].x1 - extra + pDrawable->x; -+ rects[i].width = segs[i].x2 - segs[i].x1 + 1 + 2 * extra; -+ } -+ -+ if (segs[i].y1 > segs[i].y2) { -+ rects[i].y = segs[i].y2 - extra + pDrawable->y; -+ rects[i].height = segs[i].y1 - segs[i].y2 + 1 + 2 * extra; -+ } else { -+ rects[i].y = segs[i].y1 - extra + pDrawable->y; -+ rects[i].height = segs[i].y2 - segs[i].y1 + 1 + 2 * extra; -+ } -+ } -+ -+ tmpRegion = RECTS_TO_REGION(pDrawable->pScreen, nseg, rects, CT_NONE); -+ REGION_INTERSECT(pDrawable->pScreen, tmpRegion, tmpRegion, -+ pGC->pCompositeClip); -+ -+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, tmpRegion); -+ -+ REGION_DESTROY(pDrawable->pScreen, tmpRegion); -+ xfree((char *)rects); -+ } -+ -+ (*pGC->ops->PolySegment) (pDrawable, pGC, nseg, segs); -+ -+ if (nseg) { -+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); -+ } -+ -+ GC_OP_EPILOGUE(pGC); -+} -+ -+/* -+ * PolyRectangle (rectangle outlines) - take the union of bounding boxes -+ * around each line (and clip). -+ */ -+ -+static void -+rfbPolyRectangle(pDrawable, pGC, nrects, rects) -+ DrawablePtr pDrawable; -+ GCPtr pGC; -+ int nrects; -+ xRectangle *rects; -+{ -+ int i, extra, lw; -+ RegionPtr tmpRegion; -+ xRectangle *regRects; -+ GC_OP_PROLOGUE(pDrawable, pGC); -+ -+ TRC((stderr,"rfbPolyRectangle called\n")); -+ -+ if (nrects) { -+ regRects = (xRectangle *)xalloc(nrects*4*sizeof(xRectangle)); -+ if (!regRects) { -+ FatalError("rfbPolyRectangle: xalloc failed\n"); -+ } -+ -+ lw = pGC->lineWidth; -+ if (lw == 0) -+ lw = 1; -+ -+ extra = lw / 2; -+ -+ for (i = 0; i < nrects; i++) -+ { -+ 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; -+ } -+ -+ tmpRegion = RECTS_TO_REGION(pDrawable->pScreen, nrects*4, -+ regRects, CT_NONE); -+ REGION_INTERSECT(pDrawable->pScreen, tmpRegion, tmpRegion, -+ pGC->pCompositeClip); -+ -+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, tmpRegion); -+ -+ REGION_DESTROY(pDrawable->pScreen, tmpRegion); -+ xfree((char *)regRects); -+ } -+ -+ (*pGC->ops->PolyRectangle) (pDrawable, pGC, nrects, rects); -+ -+ if (nrects) { -+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); -+ } -+ -+ GC_OP_EPILOGUE(pGC); -+} -+ -+/* -+ * PolyArc - take the union of bounding boxes around each arc (and clip). -+ * Bounding boxes assume each is a full circle / ellipse. -+ */ -+ -+static void -+rfbPolyArc(pDrawable, pGC, narcs, arcs) -+ DrawablePtr pDrawable; -+ register GCPtr pGC; -+ int narcs; -+ xArc *arcs; -+{ -+ int i, extra, lw; -+ RegionPtr tmpRegion; -+ xRectangle *rects; -+ GC_OP_PROLOGUE(pDrawable, pGC); -+ -+ TRC((stderr,"rfbPolyArc called\n")); -+ -+ if (narcs) { -+ rects = (xRectangle *)xalloc(narcs*sizeof(xRectangle)); -+ if (!rects) { -+ FatalError("rfbPolyArc: xalloc failed\n"); -+ } -+ -+ lw = pGC->lineWidth; -+ if (lw == 0) -+ lw = 1; -+ -+ extra = lw / 2; -+ -+ for (i = 0; i < narcs; i++) -+ { -+ rects[i].x = arcs[i].x - extra + pDrawable->x; -+ rects[i].y = arcs[i].y - extra + pDrawable->y; -+ rects[i].width = arcs[i].width + lw; -+ rects[i].height = arcs[i].height + lw; -+ } -+ -+ tmpRegion = RECTS_TO_REGION(pDrawable->pScreen, narcs, rects, CT_NONE); -+ REGION_INTERSECT(pDrawable->pScreen, tmpRegion, tmpRegion, -+ pGC->pCompositeClip); -+ -+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, tmpRegion); -+ -+ REGION_DESTROY(pDrawable->pScreen, tmpRegion); -+ xfree((char *)rects); -+ } -+ -+ (*pGC->ops->PolyArc) (pDrawable, pGC, narcs, arcs); -+ -+ if (narcs) { -+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); -+ } -+ -+ GC_OP_EPILOGUE(pGC); -+} -+ -+/* -+ * FillPolygon - take bounding box around polygon (and clip). -+ */ -+ -+static void -+rfbFillPolygon(pDrawable, pGC, shape, mode, count, pts) -+ register DrawablePtr pDrawable; -+ register GCPtr pGC; -+ int shape, mode; -+ int count; -+ DDXPointPtr pts; -+{ -+ int i; -+ RegionRec tmpRegion; -+ BoxRec box; -+ GC_OP_PROLOGUE(pDrawable, pGC); -+ -+ TRC((stderr,"rfbFillPolygon called\n")); -+ -+ if (count) { -+ int minX = pts[0].x, maxX = pts[0].x; -+ int minY = pts[0].y, maxY = pts[0].y; -+ -+ if (mode == CoordModePrevious) -+ { -+ int x = pts[0].x, y = pts[0].y; -+ -+ for (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 (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; -+ } -+ } -+ -+ box.x1 = minX + pDrawable->x; -+ box.y1 = minY + pDrawable->y; -+ box.x2 = maxX + 1 + pDrawable->x; -+ box.y2 = maxY + 1 + pDrawable->y; -+ -+ SAFE_REGION_INIT(pDrawable->pScreen, &tmpRegion, &box, 0); -+ -+ REGION_INTERSECT(pDrawable->pScreen, &tmpRegion, &tmpRegion, -+ pGC->pCompositeClip); -+ -+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, &tmpRegion); -+ -+ REGION_UNINIT(pDrawable->pScreen, &tmpRegion); -+ } -+ -+ (*pGC->ops->FillPolygon) (pDrawable, pGC, shape, mode, count, pts); -+ -+ if (count) { -+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); -+ } -+ -+ GC_OP_EPILOGUE(pGC); -+} -+ -+/* -+ * PolyFillRect - take the union of the given rectangles (and clip). -+ */ -+ -+static void -+rfbPolyFillRect(pDrawable, pGC, nrects, rects) -+ DrawablePtr pDrawable; -+ GCPtr pGC; -+ int nrects; -+ xRectangle *rects; -+{ -+ RegionPtr tmpRegion; -+ xRectangle *regRects; -+ int i; -+ GC_OP_PROLOGUE(pDrawable, pGC); -+ -+ TRC((stderr,"rfbPolyFillRect called\n")); -+ -+ if (nrects) { -+ regRects = (xRectangle *)xalloc(nrects*sizeof(xRectangle)); -+ if (!regRects) { -+ FatalError("rfbPolyFillRect: xalloc failed\n"); -+ } -+ -+ for (i = 0; i < nrects; i++) { -+ 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; -+ } -+ -+ tmpRegion = RECTS_TO_REGION(pDrawable->pScreen, nrects, regRects, -+ CT_NONE); -+ REGION_INTERSECT(pDrawable->pScreen, tmpRegion, tmpRegion, -+ pGC->pCompositeClip); -+ -+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, tmpRegion); -+ -+ REGION_DESTROY(pDrawable->pScreen, tmpRegion); -+ xfree((char *)regRects); -+ } -+ -+ (*pGC->ops->PolyFillRect) (pDrawable, pGC, nrects, rects); -+ -+ if (nrects) { -+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); -+ } -+ -+ GC_OP_EPILOGUE(pGC); -+} -+ -+/* -+ * PolyFillArc - take the union of bounding boxes around each arc (and clip). -+ * Bounding boxes assume each is a full circle / ellipse. -+ */ -+ -+static void -+rfbPolyFillArc(pDrawable, pGC, narcs, arcs) -+ DrawablePtr pDrawable; -+ GCPtr pGC; -+ int narcs; -+ xArc *arcs; -+{ -+ int i, extra, lw; -+ RegionPtr tmpRegion; -+ xRectangle *rects; -+ GC_OP_PROLOGUE(pDrawable, pGC); -+ -+ TRC((stderr,"rfbPolyFillArc called\n")); -+ -+ if (narcs) { -+ rects = (xRectangle *)xalloc(narcs*sizeof(xRectangle)); -+ if (!rects) { -+ FatalError("rfbPolyFillArc: xalloc failed\n"); -+ } -+ -+ lw = pGC->lineWidth; -+ if (lw == 0) -+ lw = 1; -+ -+ extra = lw / 2; -+ -+ for (i = 0; i < narcs; i++) -+ { -+ rects[i].x = arcs[i].x - extra + pDrawable->x; -+ rects[i].y = arcs[i].y - extra + pDrawable->y; -+ rects[i].width = arcs[i].width + lw; -+ rects[i].height = arcs[i].height + lw; -+ } -+ -+ tmpRegion = RECTS_TO_REGION(pDrawable->pScreen, narcs, rects, CT_NONE); -+ REGION_INTERSECT(pDrawable->pScreen, tmpRegion, tmpRegion, -+ pGC->pCompositeClip); -+ -+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, tmpRegion); -+ -+ REGION_DESTROY(pDrawable->pScreen, tmpRegion); -+ xfree((char *)rects); -+ } -+ -+ (*pGC->ops->PolyFillArc) (pDrawable, pGC, narcs, arcs); -+ -+ if (narcs) { -+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); -+ } -+ -+ GC_OP_EPILOGUE(pGC); -+} -+ -+/* -+ * Get a rough bounding box around n characters of the given font. -+ */ -+ -+static void GetTextBoundingBox(pDrawable, font, x, y, n, pbox) -+ DrawablePtr pDrawable; -+ FontPtr font; -+ int x, y, n; -+ BoxPtr pbox; -+{ -+ int maxAscent, maxDescent, maxCharWidth; -+ -+ if (FONTASCENT(font) > FONTMAXBOUNDS(font,ascent)) -+ maxAscent = FONTASCENT(font); -+ else -+ maxAscent = FONTMAXBOUNDS(font,ascent); -+ -+ if (FONTDESCENT(font) > FONTMAXBOUNDS(font,descent)) -+ maxDescent = FONTDESCENT(font); -+ else -+ maxDescent = FONTMAXBOUNDS(font,descent); -+ -+ if (FONTMAXBOUNDS(font,rightSideBearing) > FONTMAXBOUNDS(font,characterWidth)) -+ maxCharWidth = FONTMAXBOUNDS(font,rightSideBearing); -+ else -+ maxCharWidth = FONTMAXBOUNDS(font,characterWidth); -+ -+ pbox->x1 = pDrawable->x + x; -+ pbox->y1 = pDrawable->y + y - maxAscent; -+ pbox->x2 = pbox->x1 + maxCharWidth * n; -+ pbox->y2 = pbox->y1 + maxAscent + maxDescent; -+ -+ if (FONTMINBOUNDS(font,leftSideBearing) < 0) { -+ pbox->x1 += FONTMINBOUNDS(font,leftSideBearing); -+ } -+} -+ -+ -+/* -+ * PolyText8 - use rough bounding box. -+ */ -+ -+static int -+rfbPolyText8(pDrawable, pGC, x, y, count, chars) -+ DrawablePtr pDrawable; -+ GCPtr pGC; -+ int x, y; -+ int count; -+ char *chars; -+{ -+ int ret; -+ RegionRec tmpRegion; -+ BoxRec box; -+ GC_OP_PROLOGUE(pDrawable, pGC); -+ -+ TRC((stderr,"rfbPolyText8 called '%.*s'\n",count,chars)); -+ -+ if (count) { -+ GetTextBoundingBox(pDrawable, pGC->font, x, y, count, &box); -+ -+ SAFE_REGION_INIT(pDrawable->pScreen, &tmpRegion, &box, 0); -+ -+ REGION_INTERSECT(pDrawable->pScreen, &tmpRegion, &tmpRegion, -+ pGC->pCompositeClip); -+ -+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, &tmpRegion); -+ -+ REGION_UNINIT(pDrawable->pScreen, &tmpRegion); -+ } -+ -+ ret = (*pGC->ops->PolyText8) (pDrawable, pGC, x, y, count, chars); -+ -+ if (count) { -+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); -+ } -+ -+ GC_OP_EPILOGUE(pGC); -+ return ret; -+} -+ -+/* -+ * PolyText16 - use rough bounding box. -+ */ -+ -+static int -+rfbPolyText16(pDrawable, pGC, x, y, count, chars) -+ DrawablePtr pDrawable; -+ GCPtr pGC; -+ int x, y; -+ int count; -+ unsigned short *chars; -+{ -+ int ret; -+ RegionRec tmpRegion; -+ BoxRec box; -+ GC_OP_PROLOGUE(pDrawable, pGC); -+ -+ TRC((stderr,"rfbPolyText16 called\n")); -+ -+ if (count) { -+ GetTextBoundingBox(pDrawable, pGC->font, x, y, count, &box); -+ -+ SAFE_REGION_INIT(pDrawable->pScreen, &tmpRegion, &box, 0); -+ -+ REGION_INTERSECT(pDrawable->pScreen, &tmpRegion, &tmpRegion, -+ pGC->pCompositeClip); -+ -+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, &tmpRegion); -+ -+ REGION_UNINIT(pDrawable->pScreen, &tmpRegion); -+ } -+ -+ ret = (*pGC->ops->PolyText16) (pDrawable, pGC, x, y, count, chars); -+ -+ if (count) { -+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); -+ } -+ -+ GC_OP_EPILOGUE(pGC); -+ return ret; -+} -+ -+/* -+ * ImageText8 - use rough bounding box. -+ */ -+ -+static void -+rfbImageText8(pDrawable, pGC, x, y, count, chars) -+ DrawablePtr pDrawable; -+ GCPtr pGC; -+ int x, y; -+ int count; -+ char *chars; -+{ -+ RegionRec tmpRegion; -+ BoxRec box; -+ GC_OP_PROLOGUE(pDrawable, pGC); -+ -+ TRC((stderr,"rfbImageText8 called '%.*s'\n",count,chars)); -+ -+ if (count) { -+ GetTextBoundingBox(pDrawable, pGC->font, x, y, count, &box); -+ -+ SAFE_REGION_INIT(pDrawable->pScreen, &tmpRegion, &box, 0); -+ -+ REGION_INTERSECT(pDrawable->pScreen, &tmpRegion, &tmpRegion, -+ pGC->pCompositeClip); -+ -+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, &tmpRegion); -+ -+ REGION_UNINIT(pDrawable->pScreen, &tmpRegion); -+ } -+ -+ (*pGC->ops->ImageText8) (pDrawable, pGC, x, y, count, chars); -+ -+ if (count) { -+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); -+ } -+ -+ GC_OP_EPILOGUE(pGC); -+} -+ -+/* -+ * ImageText16 - use rough bounding box. -+ */ -+ -+static void -+rfbImageText16(pDrawable, pGC, x, y, count, chars) -+ DrawablePtr pDrawable; -+ GCPtr pGC; -+ int x, y; -+ int count; -+ unsigned short *chars; -+{ -+ RegionRec tmpRegion; -+ BoxRec box; -+ GC_OP_PROLOGUE(pDrawable, pGC); -+ -+ TRC((stderr,"rfbImageText16 called\n")); -+ -+ if (count) { -+ GetTextBoundingBox(pDrawable, pGC->font, x, y, count, &box); -+ -+ SAFE_REGION_INIT(pDrawable->pScreen, &tmpRegion, &box, 0); -+ -+ REGION_INTERSECT(pDrawable->pScreen, &tmpRegion, &tmpRegion, -+ pGC->pCompositeClip); -+ -+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, &tmpRegion); -+ -+ REGION_UNINIT(pDrawable->pScreen, &tmpRegion); -+ } -+ -+ (*pGC->ops->ImageText16) (pDrawable, pGC, x, y, count, chars); -+ -+ if (count) { -+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); -+ } -+ -+ GC_OP_EPILOGUE(pGC); -+} -+ -+/* -+ * ImageGlyphBlt - use rough bounding box. -+ */ -+ -+static void -+rfbImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase) -+ DrawablePtr pDrawable; -+ GCPtr pGC; -+ int x, y; -+ unsigned int nglyph; -+ CharInfoPtr *ppci; /* array of character info */ -+ pointer pglyphBase; /* start of array of glyphs */ -+{ -+ RegionRec tmpRegion; -+ BoxRec box; -+ GC_OP_PROLOGUE(pDrawable, pGC); -+ -+ TRC((stderr,"rfbImageGlyphBlt called\n")); -+ -+ if (nglyph) { -+ GetTextBoundingBox(pDrawable, pGC->font, x, y, nglyph, &box); -+ -+ SAFE_REGION_INIT(pDrawable->pScreen, &tmpRegion, &box, 0); -+ -+ REGION_INTERSECT(pDrawable->pScreen, &tmpRegion, &tmpRegion, -+ pGC->pCompositeClip); -+ -+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, &tmpRegion); -+ -+ REGION_UNINIT(pDrawable->pScreen, &tmpRegion); -+ } -+ -+ (*pGC->ops->ImageGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci,pglyphBase); -+ -+ if (nglyph) { -+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); -+ } -+ -+ GC_OP_EPILOGUE(pGC); -+} -+ -+/* -+ * PolyGlyphBlt - use rough bounding box. -+ */ -+ -+static void -+rfbPolyGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase) -+ DrawablePtr pDrawable; -+ GCPtr pGC; -+ int x, y; -+ unsigned int nglyph; -+ CharInfoPtr *ppci; /* array of character info */ -+ pointer pglyphBase; /* start of array of glyphs */ -+{ -+ RegionRec tmpRegion; -+ BoxRec box; -+ GC_OP_PROLOGUE(pDrawable, pGC); -+ -+ TRC((stderr,"rfbPolyGlyphBlt called\n")); -+ -+ if (nglyph) { -+ GetTextBoundingBox(pDrawable, pGC->font, x, y, nglyph, &box); -+ -+ SAFE_REGION_INIT(pDrawable->pScreen, &tmpRegion, &box, 0); -+ -+ REGION_INTERSECT(pDrawable->pScreen, &tmpRegion, &tmpRegion, -+ pGC->pCompositeClip); -+ -+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, &tmpRegion); -+ -+ REGION_UNINIT(pDrawable->pScreen, &tmpRegion); -+ } -+ -+ (*pGC->ops->PolyGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); -+ -+ if (nglyph) { -+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); -+ } -+ -+ GC_OP_EPILOGUE(pGC); -+} -+ -+/* -+ * PushPixels - be fairly safe - region modified is intersection of the given -+ * rectangle with the window clip region. -+ */ -+ -+static void -+rfbPushPixels(pGC, pBitMap, pDrawable, w, h, x, y) -+ GCPtr pGC; -+ PixmapPtr pBitMap; -+ DrawablePtr pDrawable; -+ int w, h, x, y; -+{ -+ RegionRec tmpRegion; -+ BoxRec box; -+ GC_OP_PROLOGUE(pDrawable, pGC); -+ -+ TRC((stderr,"rfbPushPixels called\n")); -+ -+ box.x1 = x + pDrawable->x; -+ box.y1 = y + pDrawable->y; -+ box.x2 = box.x1 + w; -+ box.y2 = box.y1 + h; -+ -+ SAFE_REGION_INIT(pDrawable->pScreen, &tmpRegion, &box, 0); -+ -+ REGION_INTERSECT(pDrawable->pScreen, &tmpRegion, &tmpRegion, -+ pGC->pCompositeClip); -+ -+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, &tmpRegion); -+ -+ REGION_UNINIT(pDrawable->pScreen, &tmpRegion); -+ -+ (*pGC->ops->PushPixels) (pGC, pBitMap, pDrawable, w, h, x, y); -+ -+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); -+ -+ GC_OP_EPILOGUE(pGC); -+} -+ -+#ifdef RENDER -+void -+rfbComposite( -+ 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; -+ VNCSCREENPTR(pScreen); -+ RegionRec tmpRegion; -+ BoxRec box; -+ PictureScreenPtr ps = GetPictureScreen(pScreen); -+ -+ box.x1 = pDst->pDrawable->x + xDst; -+ box.y1 = pDst->pDrawable->y + yDst; -+ box.x2 = box.x1 + width; -+ box.y2 = box.y1 + height; -+ -+ REGION_INIT(pScreen, &tmpRegion, &box, 0); -+ -+ ADD_TO_MODIFIED_REGION(pScreen, &tmpRegion); -+ -+ ps->Composite = pVNC->Composite; -+ (*ps->Composite)(op, pSrc, pMask, pDst, xSrc, ySrc, -+ xMask, yMask, xDst, yDst, width, height); -+ ps->Composite = rfbComposite; -+ -+ SCHEDULE_FB_UPDATE(pScreen, pVNC); -+ -+ REGION_UNINIT(pScreen, &tmpRegion); -+} -+#endif /* RENDER */ -+ -+/****************************************************************************/ -+/* -+ * Other functions -+ */ -+/****************************************************************************/ -+ -+/* -+ * rfbCopyRegion. Args are src and dst regions plus a translation (dx,dy). -+ * Takes these args together with the existing modified region and possibly an -+ * existing copy region and translation. Produces a combined modified region -+ * plus copy region and translation. Note that the copy region is the -+ * destination of the copy. -+ * -+ * First we trim parts of src which are invalid (ie in the modified region). -+ * Then we see if there is any overlap between the src and the existing copy -+ * region. If not then the two copies cannot be combined, so we choose -+ * whichever is bigger to form the basis of a new copy, while the other copy is -+ * just done the hard way by being added to the modified region. So if the -+ * existing copy is bigger then we simply add the destination of the new copy -+ * to the modified region and we're done. If the new copy is bigger, we add -+ * the old copy region to the modified region and behave as though there is no -+ * existing copy region. -+ * -+ * At this stage we now know that either the two copies can be combined, or -+ * that there is no existing copy. We temporarily add both the existing copy -+ * region and dst to the modified region (this is the entire area of the screen -+ * affected in any way). Finally we calculate the new copy region, and remove -+ * it from the modified region. -+ * -+ * Note: -+ * 1. The src region is modified by this routine. -+ * 2. When the copy region is empty, copyDX and copyDY MUST be set to zero. -+ */ -+ -+static void -+rfbCopyRegion(pScreen, cl, src, dst, dx, dy) -+ ScreenPtr pScreen; -+ rfbClientPtr cl; -+ RegionPtr src; -+ RegionPtr dst; -+ int dx, dy; -+{ -+ RegionRec tmp; -+ -+ /* src = src - modifiedRegion */ -+ -+ REGION_SUBTRACT(pScreen, src, src, &cl->modifiedRegion); -+ -+ if (REGION_NOTEMPTY(pScreen, &cl->copyRegion)) { -+ -+ REGION_NULL(pScreen, &tmp); -+ REGION_INTERSECT(pScreen, &tmp, src, &cl->copyRegion); -+ -+ if (REGION_NOTEMPTY(pScreen, &tmp)) { -+ -+ /* if src and copyRegion overlap: -+ src = src intersect copyRegion */ -+ -+ REGION_COPY(pScreen, src, &tmp); -+ -+ } else { -+ -+ /* if no overlap, find bigger region */ -+ -+ int newArea = (((REGION_EXTENTS(pScreen,src))->x2 -+ - (REGION_EXTENTS(pScreen,src))->x1) -+ * ((REGION_EXTENTS(pScreen,src))->y2 -+ - (REGION_EXTENTS(pScreen,src))->y1)); -+ -+ int oldArea = (((REGION_EXTENTS(pScreen,&cl->copyRegion))->x2 -+ - (REGION_EXTENTS(pScreen,&cl->copyRegion))->x1) -+ * ((REGION_EXTENTS(pScreen,&cl->copyRegion))->y2 -+ - (REGION_EXTENTS(pScreen,&cl->copyRegion))->y1)); -+ -+ if (oldArea > newArea) { -+ -+ /* existing copy is bigger: -+ modifiedRegion = modifiedRegion union dst -+ copyRegion = copyRegion - dst -+ return */ -+ -+ REGION_UNION(pScreen, &cl->modifiedRegion, &cl->modifiedRegion, -+ dst); -+ REGION_SUBTRACT(pScreen, &cl->copyRegion, &cl->copyRegion, -+ dst); -+ if (!REGION_NOTEMPTY(pScreen, &cl->copyRegion)) { -+ cl->copyDX = 0; -+ cl->copyDY = 0; -+ } -+ return; -+ } -+ -+ /* new copy is bigger: -+ modifiedRegion = modifiedRegion union copyRegion -+ copyRegion = empty */ -+ -+ REGION_UNION(pScreen, &cl->modifiedRegion, &cl->modifiedRegion, -+ &cl->copyRegion); -+ REGION_EMPTY(pScreen, &cl->copyRegion); -+ cl->copyDX = cl->copyDY = 0; -+ } -+ } -+ -+ -+ /* modifiedRegion = modifiedRegion union dst union copyRegion */ -+ -+ REGION_UNION(pScreen, &cl->modifiedRegion, &cl->modifiedRegion, dst); -+ REGION_UNION(pScreen, &cl->modifiedRegion, &cl->modifiedRegion, -+ &cl->copyRegion); -+ -+ /* copyRegion = T(src) intersect dst */ -+ -+ REGION_TRANSLATE(pScreen, src, dx, dy); -+ REGION_INTERSECT(pScreen, &cl->copyRegion, src, dst); -+ -+ /* modifiedRegion = modifiedRegion - copyRegion */ -+ -+ REGION_SUBTRACT(pScreen, &cl->modifiedRegion, &cl->modifiedRegion, -+ &cl->copyRegion); -+ -+ /* combine new translation T with existing translation */ -+ -+ if (REGION_NOTEMPTY(pScreen, &cl->copyRegion)) { -+ cl->copyDX += dx; -+ cl->copyDY += dy; -+ } else { -+ cl->copyDX = 0; -+ cl->copyDY = 0; -+ } -+} -+ -+ -+/* -+ * rfbDeferredUpdateCallback() is called when a client's deferredUpdateTimer -+ * goes off. -+ */ -+ -+static CARD32 -+rfbDeferredUpdateCallback(OsTimerPtr timer, CARD32 now, pointer arg) -+{ -+ rfbClientPtr cl = (rfbClientPtr)arg; -+ -+ rfbSendFramebufferUpdate(cl->pScreen, cl); -+ -+ cl->deferredUpdateScheduled = FALSE; -+ return 0; -+} -+ -+ -+/* -+ * rfbScheduleDeferredUpdate() is called from the SCHEDULE_FB_UPDATE macro -+ * to schedule an update. -+ */ -+ -+static void -+rfbScheduleDeferredUpdate(ScreenPtr pScreen, rfbClientPtr cl) -+{ -+ if (rfbDeferUpdateTime != 0) { -+ cl->deferredUpdateTimer = TimerSet(cl->deferredUpdateTimer, 0, -+ rfbDeferUpdateTime, -+ rfbDeferredUpdateCallback, cl); -+ cl->deferredUpdateScheduled = TRUE; -+ } else { -+ rfbSendFramebufferUpdate(pScreen, cl); -+ } -+} -+ -+ -+/* -+ * PrintRegion is useful for debugging. -+ */ -+ -+#ifdef DEBUG -+static void -+PrintRegion(ScreenPtr pScreen, RegionPtr reg) -+{ -+ int nrects = REGION_NUM_RECTS(reg); -+ int i; -+ -+ ErrorF("Region num rects %d extents %d,%d %d,%d\n",nrects, -+ (REGION_EXTENTS(pScreen,reg))->x1, -+ (REGION_EXTENTS(pScreen,reg))->y1, -+ (REGION_EXTENTS(pScreen,reg))->x2, -+ (REGION_EXTENTS(pScreen,reg))->y2); -+ -+ for (i = 0; i < nrects; i++) { -+ ErrorF(" rect %d,%d %dx%d\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); -+ } -+} -+#endif -+ -+ -+/** -+ * Allow scheduling updates from other functions in other files. -+ */ -+void -+rfbScheduleUpdate(ScreenPtr pScreen) -+{ -+ VNCSCREENPTR(pScreen); -+ SCHEDULE_FB_UPDATE(pScreen, pVNC); -+} -diff --git a/hw/xfree86/vnc/hextile.c b/hw/xfree86/vnc/hextile.c -new file mode 100644 -index 0000000..6017489 ---- /dev/null -+++ b/hw/xfree86/vnc/hextile.c -@@ -0,0 +1,352 @@ -+/* -+ * hextile.c -+ * -+ * Routines to implement Hextile Encoding -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ */ -+ -+/* -+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. -+ * -+ * This is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This software is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this software; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -+ * USA. -+ */ -+ -+#include -+#include -+#include "rfb.h" -+ -+static Bool sendHextiles8(rfbClientPtr cl, int x, int y, int w, int h); -+static Bool sendHextiles16(rfbClientPtr cl, int x, int y, int w, int h); -+static Bool sendHextiles32(rfbClientPtr cl, int x, int y, int w, int h); -+ -+ -+/* -+ * rfbSendRectEncodingHextile - send a rectangle using hextile encoding. -+ */ -+ -+Bool -+rfbSendRectEncodingHextile(cl, x, y, w, h) -+ rfbClientPtr cl; -+ int x, y, w, h; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ rfbFramebufferUpdateRectHeader rect; -+ -+ if (pVNC->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) { -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ } -+ -+ rect.r.x = Swap16IfLE(x); -+ rect.r.y = Swap16IfLE(y); -+ rect.r.w = Swap16IfLE(w); -+ rect.r.h = Swap16IfLE(h); -+ rect.encoding = Swap32IfLE(rfbEncodingHextile); -+ -+ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&rect, -+ sz_rfbFramebufferUpdateRectHeader); -+ pVNC->ublen += sz_rfbFramebufferUpdateRectHeader; -+ -+ cl->rfbRectanglesSent[rfbEncodingHextile]++; -+ cl->rfbBytesSent[rfbEncodingHextile] += sz_rfbFramebufferUpdateRectHeader; -+ -+ switch (cl->format.bitsPerPixel) { -+ case 8: -+ return sendHextiles8(cl, x, y, w, h); -+ case 16: -+ return sendHextiles16(cl, x, y, w, h); -+ case 32: -+ return sendHextiles32(cl, x, y, w, h); -+ } -+ -+ rfbLog("rfbSendRectEncodingHextile: bpp %d?\n", cl->format.bitsPerPixel); -+ return FALSE; -+} -+ -+ -+#define PUT_PIXEL8(pix) (pVNC->updateBuf[pVNC->ublen++] = (pix)) -+ -+#define PUT_PIXEL16(pix) (pVNC->updateBuf[pVNC->ublen++] = ((char*)&(pix))[0], \ -+ pVNC->updateBuf[pVNC->ublen++] = ((char*)&(pix))[1]) -+ -+#define PUT_PIXEL32(pix) (pVNC->updateBuf[pVNC->ublen++] = ((char*)&(pix))[0], \ -+ pVNC->updateBuf[pVNC->ublen++] = ((char*)&(pix))[1], \ -+ pVNC->updateBuf[pVNC->ublen++] = ((char*)&(pix))[2], \ -+ pVNC->updateBuf[pVNC->ublen++] = ((char*)&(pix))[3]) -+ -+ -+#define DEFINE_SEND_HEXTILES(bpp) \ -+ \ -+ \ -+static Bool subrectEncode##bpp(ScreenPtr pScreen, CARD##bpp *data, int w, \ -+ int h, CARD##bpp bg, \ -+ CARD##bpp fg, Bool mono); \ -+static void testColours##bpp(CARD##bpp *data, int size, Bool *mono, \ -+ Bool *solid, CARD##bpp *bg, CARD##bpp *fg); \ -+ \ -+ \ -+/* \ -+ * rfbSendHextiles \ -+ */ \ -+ \ -+static Bool \ -+sendHextiles##bpp(cl, rx, ry, rw, rh) \ -+ rfbClientPtr cl; \ -+ int rx, ry, rw, rh; \ -+{ \ -+ VNCSCREENPTR(cl->pScreen); \ -+ int x, y, w, h; \ -+ int startUblen; \ -+ unsigned char *fbptr; \ -+ CARD##bpp bg = 0, fg = 0, newBg, newFg; \ -+ Bool mono, solid; \ -+ Bool validBg = FALSE; \ -+ Bool validFg = FALSE; \ -+ CARD##bpp clientPixelData[16*16*(bpp/8)]; \ -+ \ -+ for (y = ry; y < ry+rh; y += 16) { \ -+ for (x = rx; x < rx+rw; x += 16) { \ -+ w = h = 16; \ -+ if (rx+rw - x < 16) \ -+ w = rx+rw - x; \ -+ if (ry+rh - y < 16) \ -+ h = ry+rh - y; \ -+ \ -+ if ((pVNC->ublen + 1 + (2 + 16 * 16) * (bpp/8)) > UPDATE_BUF_SIZE) { \ -+ if (!rfbSendUpdateBuf(cl)) \ -+ return FALSE; \ -+ } \ -+ \ -+ fbptr = (pVNC->pfbMemory + (pVNC->paddedWidthInBytes * y) \ -+ + (x * (pVNC->bitsPerPixel / 8))); \ -+ \ -+ (*cl->translateFn)(cl->pScreen, cl->translateLookupTable, \ -+ &pVNC->rfbServerFormat, \ -+ &cl->format, fbptr, (char *)clientPixelData, \ -+ pVNC->paddedWidthInBytes, w, h, x, y); \ -+ \ -+ startUblen = pVNC->ublen; \ -+ pVNC->updateBuf[startUblen] = 0; \ -+ pVNC->ublen++; \ -+ \ -+ testColours##bpp(clientPixelData, w * h, \ -+ &mono, &solid, &newBg, &newFg); \ -+ \ -+ if (!validBg || (newBg != bg)) { \ -+ validBg = TRUE; \ -+ bg = newBg; \ -+ pVNC->updateBuf[startUblen] |= rfbHextileBackgroundSpecified; \ -+ PUT_PIXEL##bpp(bg); \ -+ } \ -+ \ -+ if (solid) { \ -+ cl->rfbBytesSent[rfbEncodingHextile] += pVNC->ublen - startUblen; \ -+ continue; \ -+ } \ -+ \ -+ pVNC->updateBuf[startUblen] |= rfbHextileAnySubrects; \ -+ \ -+ if (mono) { \ -+ if (!validFg || (newFg != fg)) { \ -+ validFg = TRUE; \ -+ fg = newFg; \ -+ pVNC->updateBuf[startUblen] |= rfbHextileForegroundSpecified; \ -+ PUT_PIXEL##bpp(fg); \ -+ } \ -+ } else { \ -+ validFg = FALSE; \ -+ pVNC->updateBuf[startUblen] |= rfbHextileSubrectsColoured; \ -+ } \ -+ \ -+ if (!subrectEncode##bpp(cl->pScreen, clientPixelData, w, h, bg, fg, mono)) { \ -+ /* encoding was too large, use raw */ \ -+ validBg = FALSE; \ -+ validFg = FALSE; \ -+ pVNC->ublen = startUblen; \ -+ pVNC->updateBuf[pVNC->ublen++] = rfbHextileRaw; \ -+ (*cl->translateFn)(cl->pScreen, cl->translateLookupTable, \ -+ &pVNC->rfbServerFormat, &cl->format, fbptr,\ -+ (char *)clientPixelData, \ -+ pVNC->paddedWidthInBytes, w, h, x, y); \ -+ \ -+ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)clientPixelData,\ -+ w * h * (bpp/8)); \ -+ \ -+ pVNC->ublen += w * h * (bpp/8); \ -+ } \ -+ \ -+ cl->rfbBytesSent[rfbEncodingHextile] += pVNC->ublen - startUblen; \ -+ } \ -+ } \ -+ \ -+ return TRUE; \ -+} \ -+ \ -+ \ -+static Bool \ -+subrectEncode##bpp(ScreenPtr pScreen, CARD##bpp *data, int w, int h, \ -+ CARD##bpp bg, CARD##bpp fg, Bool mono) \ -+{ \ -+ VNCSCREENPTR(pScreen); \ -+ CARD##bpp clientdata; \ -+ int x,y; \ -+ int i,j; \ -+ int hx=0,hy,vx=0,vy; \ -+ int hyflag; \ -+ CARD##bpp *seg; \ -+ CARD##bpp *line; \ -+ int hw,hh,vw,vh; \ -+ int thex,they,thew,theh; \ -+ int numsubs = 0; \ -+ int newLen; \ -+ int nSubrectsUblen; \ -+ \ -+ nSubrectsUblen = pVNC->ublen; \ -+ pVNC->ublen++; \ -+ \ -+ for (y=0; y 0) && (i >= hx)) { \ -+ hy += 1; \ -+ } else { \ -+ hyflag = 0; \ -+ } \ -+ } \ -+ vy = j-1; \ -+ \ -+ /* We now have two possible subrects: (x,y,hx,hy) and \ -+ * (x,y,vx,vy). We'll choose the bigger of the two. \ -+ */ \ -+ hw = hx-x+1; \ -+ hh = hy-y+1; \ -+ vw = vx-x+1; \ -+ vh = vy-y+1; \ -+ \ -+ thex = x; \ -+ they = y; \ -+ \ -+ if ((hw*hh) > (vw*vh)) { \ -+ thew = hw; \ -+ theh = hh; \ -+ } else { \ -+ thew = vw; \ -+ theh = vh; \ -+ } \ -+ \ -+ if (mono) { \ -+ newLen = pVNC->ublen - nSubrectsUblen + 2; \ -+ } else { \ -+ newLen = pVNC->ublen - nSubrectsUblen + bpp/8 + 2; \ -+ } \ -+ \ -+ if (newLen > (w * h * (bpp/8))) \ -+ return FALSE; \ -+ \ -+ numsubs += 1; \ -+ \ -+ if (!mono) PUT_PIXEL##bpp(clientdata); \ -+ \ -+ pVNC->updateBuf[pVNC->ublen++] = rfbHextilePackXY(thex,they); \ -+ pVNC->updateBuf[pVNC->ublen++] = rfbHextilePackWH(thew,theh); \ -+ \ -+ /* \ -+ * Now mark the subrect as done. \ -+ */ \ -+ for (j=they; j < (they+theh); j++) { \ -+ for (i=thex; i < (thex+thew); i++) { \ -+ data[j*w+i] = bg; \ -+ } \ -+ } \ -+ } \ -+ } \ -+ } \ -+ \ -+ pVNC->updateBuf[nSubrectsUblen] = numsubs; \ -+ \ -+ return TRUE; \ -+} \ -+ \ -+ \ -+/* \ -+ * testColours() tests if there are one (solid), two (mono) or more \ -+ * colours in a tile and gets a reasonable guess at the best background \ -+ * pixel, and the foreground pixel for mono. \ -+ */ \ -+ \ -+static void \ -+testColours##bpp(data,size,mono,solid,bg,fg) \ -+ CARD##bpp *data; \ -+ int size; \ -+ Bool *mono; \ -+ Bool *solid; \ -+ CARD##bpp *bg; \ -+ CARD##bpp *fg; \ -+{ \ -+ CARD##bpp colour1 = 0, colour2 = 0; \ -+ int n1 = 0, n2 = 0; \ -+ *mono = TRUE; \ -+ *solid = TRUE; \ -+ \ -+ for (; size > 0; size--, data++) { \ -+ \ -+ if (n1 == 0) \ -+ colour1 = *data; \ -+ \ -+ if (*data == colour1) { \ -+ n1++; \ -+ continue; \ -+ } \ -+ \ -+ if (n2 == 0) { \ -+ *solid = FALSE; \ -+ colour2 = *data; \ -+ } \ -+ \ -+ if (*data == colour2) { \ -+ n2++; \ -+ continue; \ -+ } \ -+ \ -+ *mono = FALSE; \ -+ break; \ -+ } \ -+ \ -+ if (n1 > n2) { \ -+ *bg = colour1; \ -+ *fg = colour2; \ -+ } else { \ -+ *bg = colour2; \ -+ *fg = colour1; \ -+ } \ -+} -+ -+DEFINE_SEND_HEXTILES(8) -+DEFINE_SEND_HEXTILES(16) -+DEFINE_SEND_HEXTILES(32) -diff --git a/hw/xfree86/vnc/httpd.c b/hw/xfree86/vnc/httpd.c -new file mode 100644 -index 0000000..863543a ---- /dev/null -+++ b/hw/xfree86/vnc/httpd.c -@@ -0,0 +1,520 @@ -+/* -+ * httpd.c - a simple HTTP server -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ */ -+ -+/* -+ * Copyright (C) 2002 Constantin Kaplinsky. All Rights Reserved. -+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. -+ * -+ * This is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This software is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this software; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -+ * USA. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#ifndef USE_LIBWRAP -+#define USE_LIBWRAP 0 -+#endif -+#if USE_LIBWRAP -+#include -+#endif -+ -+#include "rfb.h" -+ -+#define NOT_FOUND_STR "HTTP/1.0 404 Not found\r\n\r\n" \ -+ "File Not Found\n" \ -+ "

File Not Found

\n" -+ -+#define OK_STR "HTTP/1.0 200 OK\r\n\r\n" -+ -+static void httpProcessInput(ScreenPtr pScreen); -+static Bool compareAndSkip(char **ptr, const char *str); -+static Bool parseParams(const char *request, char *result, int max_bytes); -+static Bool validateString(char *str); -+ -+/* -+ * httpInitSockets sets up the TCP socket to listen for HTTP connections. -+ */ -+ -+Bool -+httpInitSockets(ScreenPtr pScreen) -+{ -+ VNCSCREENPTR(pScreen); -+ -+ if (!pVNC->httpDir) -+ return FALSE; -+ -+ pVNC->buf_filled = 0; -+ -+ if (pVNC->httpPort == 0) { -+ pVNC->httpPort = 5800 + atoi(display) + pScreen->myNum; -+ } -+ -+ if ((pVNC->httpListenSock = ListenOnTCPPort(pScreen, pVNC->httpPort)) < 0) { -+ rfbLog("ListenOnTCPPort %d failed\n",pVNC->httpPort); -+ pVNC->httpPort = 0; -+ return FALSE; -+ } -+ -+ rfbLog("Listening for HTTP connections on TCP port %d\n", pVNC->httpPort); -+ rfbLog(" URL http://%s:%d\n",rfbThisHost,pVNC->httpPort); -+ -+ AddEnabledDevice(pVNC->httpListenSock); -+ -+ return TRUE; -+} -+ -+ -+/* -+ * httpCheckFds is called from ProcessInputEvents to check for input on the -+ * HTTP socket(s). If there is input to process, httpProcessInput is called. -+ */ -+ -+void -+httpCheckFds(ScreenPtr pScreen) -+{ -+ VNCSCREENPTR(pScreen); -+ int nfds; -+ fd_set fds; -+ struct timeval tv; -+ struct sockaddr_in addr; -+ SOCKLEN_T addrlen = sizeof(addr); -+ -+ if (!pVNC->httpDir) -+ return; -+ -+ FD_ZERO(&fds); -+ FD_SET(pVNC->httpListenSock, &fds); -+ if (pVNC->httpSock >= 0) { -+ FD_SET(pVNC->httpSock, &fds); -+ } -+ tv.tv_sec = 0; -+ tv.tv_usec = 0; -+ nfds = select(max(pVNC->httpSock,pVNC->httpListenSock) + 1, &fds, NULL, NULL, &tv); -+ if (nfds == 0) { -+ return; -+ } -+ if (nfds < 0) { -+ if (errno != EINTR) -+ rfbLogPerror("httpCheckFds: select"); -+ return; -+ } -+ -+ if ((pVNC->httpSock >= 0) && FD_ISSET(pVNC->httpSock, &fds)) { -+ httpProcessInput(pScreen); -+ } -+ -+ if (FD_ISSET(pVNC->httpListenSock, &fds)) { -+ int flags; -+ -+ if (pVNC->httpSock >= 0) close(pVNC->httpSock); -+ -+ if ((pVNC->httpSock = accept(pVNC->httpListenSock, -+ (struct sockaddr *)&addr, &addrlen)) < 0) { -+ rfbLogPerror("httpCheckFds: accept"); -+ return; -+ } -+ -+#if USE_LIBWRAP -+ if (!hosts_ctl("Xvnc", STRING_UNKNOWN, inet_ntoa(addr.sin_addr), -+ STRING_UNKNOWN)) { -+ rfbLog("Rejected HTTP connection from client %s\n", -+ inet_ntoa(addr.sin_addr)); -+ close(pVNC->httpSock); -+ pVNC->httpSock = -1; -+ return; -+ } -+#endif -+ -+ flags = fcntl (pVNC->httpSock, F_GETFL); -+ -+ if (flags == -1 || -+ fcntl (pVNC->httpSock, F_SETFL, flags | O_NONBLOCK) == -1) { -+ rfbLogPerror("httpCheckFds: fcntl"); -+ close (pVNC->httpSock); -+ pVNC->httpSock = -1; -+ return; -+ } -+ -+ AddEnabledDevice(pVNC->httpSock); -+ } -+} -+ -+ -+static void -+httpCloseSock(ScreenPtr pScreen) -+{ -+ VNCSCREENPTR(pScreen); -+ close(pVNC->httpSock); -+ RemoveEnabledDevice(pVNC->httpSock); -+ pVNC->httpSock = -1; -+ pVNC->buf_filled = 0; -+} -+ -+ -+/* -+ * httpProcessInput is called when input is received on the HTTP socket. -+ */ -+ -+static void -+httpProcessInput(ScreenPtr pScreen) -+{ -+ VNCSCREENPTR(pScreen); -+ struct sockaddr_in addr; -+ SOCKLEN_T addrlen = sizeof(addr); -+ char fullFname[512]; -+ char params[1024]; -+ char *ptr; -+ char *fname; -+ int maxFnameLen; -+ int fd; -+ Bool performSubstitutions = FALSE; -+ char str[256]; -+ struct passwd *user = getpwuid(getuid()); -+ -+ if (strlen(pVNC->httpDir) > 255) { -+ rfbLog("-httpd directory too long\n"); -+ httpCloseSock(pScreen); -+ return; -+ } -+ strcpy(fullFname, pVNC->httpDir); -+ fname = &fullFname[strlen(fullFname)]; -+ maxFnameLen = 511 - strlen(fullFname); -+ -+ /* Read data from the HTTP client until we get a complete request. */ -+ while (1) { -+ ssize_t got = read (pVNC->httpSock, pVNC->buf + pVNC->buf_filled, -+ sizeof (pVNC->buf) - pVNC->buf_filled - 1); -+ -+ if (got <= 0) { -+ if (got == 0) { -+ rfbLog("httpd: premature connection close\n"); -+ } else { -+ if (errno == EAGAIN) { -+ return; -+ } -+ rfbLogPerror("httpProcessInput: read"); -+ } -+ httpCloseSock(pScreen); -+ return; -+ } -+ -+ pVNC->buf_filled += got; -+ pVNC->buf[pVNC->buf_filled] = '\0'; -+ -+ /* Is it complete yet (is there a blank line)? */ -+ if (strstr (pVNC->buf, "\r\r") || strstr (pVNC->buf, "\n\n") || -+ strstr (pVNC->buf, "\r\n\r\n") || strstr (pVNC->buf, "\n\r\n\r")) -+ break; -+ } -+ -+ /* Process the request. */ -+ if (strncmp(pVNC->buf, "GET ", 4)) { -+ rfbLog("httpd: no GET line\n"); -+ httpCloseSock(pScreen); -+ return; -+ } else { -+ /* Only use the first line. */ -+ pVNC->buf[strcspn(pVNC->buf, "\n\r")] = '\0'; -+ } -+ -+ if (strlen(pVNC->buf) > maxFnameLen) { -+ rfbLog("httpd: GET line too long\n"); -+ httpCloseSock(pScreen); -+ return; -+ } -+ -+ if (sscanf(pVNC->buf, "GET %s HTTP/1.0", fname) != 1) { -+ rfbLog("httpd: couldn't parse GET line\n"); -+ httpCloseSock(pScreen); -+ return; -+ } -+ -+ if (fname[0] != '/') { -+ rfbLog("httpd: filename didn't begin with '/'\n"); -+ WriteExact(pVNC->httpSock, NOT_FOUND_STR, strlen(NOT_FOUND_STR)); -+ httpCloseSock(pScreen); -+ return; -+ } -+ -+ if (strchr(fname+1, '/') != NULL) { -+ rfbLog("httpd: asking for file in other directory\n"); -+ WriteExact(pVNC->httpSock, NOT_FOUND_STR, strlen(NOT_FOUND_STR)); -+ httpCloseSock(pScreen); -+ return; -+ } -+ -+ getpeername(pVNC->httpSock, (struct sockaddr *)&addr, &addrlen); -+ rfbLog("httpd: get '%s' for %s\n", fname+1, -+ inet_ntoa(addr.sin_addr)); -+ -+ /* Extract parameters from the URL string if necessary */ -+ -+ params[0] = '\0'; -+ ptr = strchr(fname, '?'); -+ if (ptr != NULL) { -+ *ptr = '\0'; -+ if (!parseParams(&ptr[1], params, 1024)) { -+ params[0] = '\0'; -+ rfbLog("httpd: bad parameters in the URL\n"); -+ } -+ } -+ -+ /* If we were asked for '/', actually read the file index.vnc */ -+ -+ if (strcmp(fname, "/") == 0) { -+ strcpy(fname, "/index.vnc"); -+ rfbLog("httpd: defaulting to '%s'\n", fname+1); -+ } -+ -+ /* Substitutions are performed on files ending .vnc */ -+ -+ if (strlen(fname) >= 4 && strcmp(&fname[strlen(fname)-4], ".vnc") == 0) { -+ performSubstitutions = TRUE; -+ } -+ -+ /* Open the file */ -+ -+ if ((fd = open(fullFname, O_RDONLY)) < 0) { -+ rfbLogPerror("httpProcessInput: open"); -+ WriteExact(pVNC->httpSock, NOT_FOUND_STR, strlen(NOT_FOUND_STR)); -+ httpCloseSock(pScreen); -+ return; -+ } -+ -+ WriteExact(pVNC->httpSock, OK_STR, strlen(OK_STR)); -+ -+ while (1) { -+ int n = read(fd, pVNC->buf, HTTP_BUF_SIZE-1); -+ if (n < 0) { -+ rfbLogPerror("httpProcessInput: read"); -+ close(fd); -+ httpCloseSock(pScreen); -+ return; -+ } -+ -+ if (n == 0) -+ break; -+ -+ if (performSubstitutions) { -+ -+ /* Substitute $WIDTH, $HEIGHT, etc with the appropriate values. -+ This won't quite work properly if the .vnc file is longer than -+ HTTP_BUF_SIZE, but it's reasonable to assume that .vnc files will -+ always be short. */ -+ -+ char *ptr = pVNC->buf; -+ char *dollar; -+ pVNC->buf[n] = 0; /* make sure it's null-terminated */ -+ -+ while ((dollar = strchr(ptr, '$'))) { -+ WriteExact(pVNC->httpSock, ptr, (dollar - ptr)); -+ -+ ptr = dollar; -+ -+ if (compareAndSkip(&ptr, "$WIDTH")) { -+ -+ sprintf(str, "%d", pVNC->width); -+ WriteExact(pVNC->httpSock, str, strlen(str)); -+ -+ } else if (compareAndSkip(&ptr, "$HEIGHT")) { -+ -+ sprintf(str, "%d", pVNC->height); -+ WriteExact(pVNC->httpSock, str, strlen(str)); -+ -+ } else if (compareAndSkip(&ptr, "$APPLETWIDTH")) { -+ -+ sprintf(str, "%d", pVNC->width); -+ WriteExact(pVNC->httpSock, str, strlen(str)); -+ -+ } else if (compareAndSkip(&ptr, "$APPLETHEIGHT")) { -+ -+ sprintf(str, "%d", pVNC->height + 32); -+ WriteExact(pVNC->httpSock, str, strlen(str)); -+ -+ } else if (compareAndSkip(&ptr, "$PORT")) { -+ -+ sprintf(str, "%d", pVNC->rfbPort); -+ WriteExact(pVNC->httpSock, str, strlen(str)); -+ -+ } else if (compareAndSkip(&ptr, "$DESKTOP")) { -+ -+ WriteExact(pVNC->httpSock, desktopName, strlen(desktopName)); -+ -+ } else if (compareAndSkip(&ptr, "$DISPLAY")) { -+ -+ sprintf(str, "%s:%s", rfbThisHost, display); -+ WriteExact(pVNC->httpSock, str, strlen(str)); -+ -+ } else if (compareAndSkip(&ptr, "$USER")) { -+ -+ if (user) { -+ WriteExact(pVNC->httpSock, user->pw_name, -+ strlen(user->pw_name)); -+ } else { -+ WriteExact(pVNC->httpSock, "?", 1); -+ } -+ -+ } else if (compareAndSkip(&ptr, "$PARAMS")) { -+ -+ if (params[0] != '\0') -+ WriteExact(pVNC->httpSock, params, strlen(params)); -+ -+ } else { -+ if (!compareAndSkip(&ptr, "$$")) -+ ptr++; -+ -+ if (WriteExact(pVNC->httpSock, "$", 1) < 0) { -+ close(fd); -+ httpCloseSock(pScreen); -+ return; -+ } -+ } -+ } -+ if (WriteExact(pVNC->httpSock, ptr, (&pVNC->buf[n] - ptr)) < 0) -+ break; -+ -+ } else { -+ -+ /* For files not ending .vnc, just write out the buffer */ -+ -+ if (WriteExact(pVNC->httpSock, pVNC->buf, n) < 0) -+ break; -+ } -+ } -+ -+ close(fd); -+ httpCloseSock(pScreen); -+} -+ -+ -+static Bool -+compareAndSkip(char **ptr, const char *str) -+{ -+ if (strncmp(*ptr, str, strlen(str)) == 0) { -+ *ptr += strlen(str); -+ return TRUE; -+ } -+ -+ return FALSE; -+} -+ -+/* -+ * Parse the request tail after the '?' character, and format a sequence -+ * of tags for inclusion into an HTML page with embedded applet. -+ */ -+ -+static Bool -+parseParams(const char *request, char *result, int max_bytes) -+{ -+ char param_request[128]; -+ char param_formatted[196]; -+ const char *tail; -+ char *delim_ptr; -+ char *value_str; -+ int cur_bytes, len; -+ -+ result[0] = '\0'; -+ cur_bytes = 0; -+ -+ tail = request; -+ for (;;) { -+ /* Copy individual "name=value" string into a buffer */ -+ delim_ptr = strchr((char *)tail, '&'); -+ if (delim_ptr == NULL) { -+ if (strlen(tail) >= sizeof(param_request)) { -+ return FALSE; -+ } -+ strcpy(param_request, tail); -+ } else { -+ len = delim_ptr - tail; -+ if (len >= sizeof(param_request)) { -+ return FALSE; -+ } -+ memcpy(param_request, tail, len); -+ param_request[len] = '\0'; -+ } -+ -+ /* Split the request into parameter name and value */ -+ value_str = strchr(¶m_request[1], '='); -+ if (value_str == NULL) { -+ return FALSE; -+ } -+ *value_str++ = '\0'; -+ if (strlen(value_str) == 0) { -+ return FALSE; -+ } -+ -+ /* Validate both parameter name and value */ -+ if (!validateString(param_request) || !validateString(value_str)) { -+ return FALSE; -+ } -+ -+ /* Prepare HTML-formatted representation of the name=value pair */ -+ len = sprintf(param_formatted, -+ "\n", -+ param_request, value_str); -+ if (cur_bytes + len + 1 > max_bytes) { -+ return FALSE; -+ } -+ strcat(result, param_formatted); -+ cur_bytes += len; -+ -+ /* Go to the next parameter */ -+ if (delim_ptr == NULL) { -+ break; -+ } -+ tail = delim_ptr + 1; -+ } -+ return TRUE; -+} -+ -+/* -+ * Check if the string consists only of alphanumeric characters, '+' -+ * signs, underscores, and dots. Replace all '+' signs with spaces. -+ */ -+ -+static Bool -+validateString(char *str) -+{ -+ char *ptr; -+ -+ for (ptr = str; *ptr != '\0'; ptr++) { -+ if (!isalnum(*ptr) && *ptr != '_' && *ptr != '.') { -+ if (*ptr == '+') { -+ *ptr = ' '; -+ } else { -+ return FALSE; -+ } -+ } -+ } -+ return TRUE; -+} -+ -diff --git a/hw/xfree86/vnc/kbdptr.c b/hw/xfree86/vnc/kbdptr.c -new file mode 100644 -index 0000000..6fd0d73 ---- /dev/null -+++ b/hw/xfree86/vnc/kbdptr.c -@@ -0,0 +1,426 @@ -+/* -+ * kbdptr.c - deal with keyboard and pointer device over TCP & UDP. -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ * -+ */ -+ -+/* -+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. -+ * -+ * This is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This software is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this software; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -+ * USA. -+ */ -+ -+#include "rfb.h" -+#include "X11/X.h" -+#define NEED_EVENTS -+#include "X11/Xproto.h" -+#include "inputstr.h" -+#define XK_CYRILLIC -+#include -+#include -+#include "mi.h" -+#include "mipointer.h" -+ -+#if XFREE86VNC -+#ifdef XINPUT -+# include "xf86Xinput.h" -+# define Enqueue(ev) xf86eqEnqueue(ev) -+#else -+# define Enqueue(ev) mieqEnqueue(ev) -+#endif -+#else -+#define Enqueue(ev) mieqEnqueue(ev) -+#endif -+ -+#define KEY_IS_PRESSED(keycode) \ -+ (kbdDevice->key->down[(keycode) >> 3] & (1 << ((keycode) & 7))) -+ -+static void XConvertCase(KeySym sym, KeySym *lower, KeySym *upper); -+ -+DeviceIntPtr kbdDevice = NULL; -+ -+#include "keyboard.h" -+ -+/* -+ * Called when the rfbserver receives a rfbKeyEvent event from a client. -+ * Put an X keyboard event into the event queue. -+ */ -+void -+KbdAddEvent(Bool down, KeySym keySym, rfbClientPtr cl) -+{ -+ xEvent ev, fake; -+ KeySymsPtr keySyms; -+ int i; -+ int keyCode = 0; -+ int freeIndex = -1; -+ unsigned long time; -+ Bool fakeShiftPress = FALSE; -+ Bool fakeShiftLRelease = FALSE; -+ Bool fakeShiftRRelease = FALSE; -+ Bool shiftMustBeReleased = FALSE; -+ Bool shiftMustBePressed = FALSE; -+ -+ if (!kbdDevice) return; -+ -+ keySyms = &kbdDevice->key->curKeySyms; -+ -+#ifdef CORBA -+ if (cl) { -+ CARD32 clientId = cl->sock; -+ ChangeWindowProperty(WindowTable[0], VNC_LAST_CLIENT_ID, XA_INTEGER, -+ 32, PropModeReplace, 1, (pointer)&clientId, TRUE); -+ } -+#endif -+ -+ if (down) { -+ ev.u.u.type = KeyPress; -+ } else { -+ ev.u.u.type = KeyRelease; -+ } -+ -+ /* NOTE: This is where it gets hairy for XFree86 servers. -+ * I think the best way to deal with this is invent a new protocol -+ * to send over the wire the remote keyboard type and correctly -+ * handle that as XINPUT extension device (we're part of the way -+ * there for that. -+ * -+ * Alan. -+ */ -+#if !XFREE86VNC -+ /* First check if it's one of our predefined keys. If so then we can make -+ some attempt at allowing an xmodmap inside a VNC desktop behave -+ something like you'd expect - e.g. if keys A & B are swapped over and -+ the VNC client sends an A, then map it to a B when generating the X -+ event. We don't attempt to do this for keycodes which we make up on the -+ fly because it's too hard... */ -+ -+ for (i = 0; i < N_PREDEFINED_KEYS * GLYPHS_PER_KEY; i++) { -+ if (keySym == map[i]) { -+ keyCode = MIN_KEY_CODE + i / GLYPHS_PER_KEY; -+ -+ if (map[(i/GLYPHS_PER_KEY) * GLYPHS_PER_KEY + 1] != NoSymbol) { -+ -+ /* this keycode has more than one symbol associated with it, -+ so shift state is important */ -+ -+ if ((i % GLYPHS_PER_KEY) == 0) -+ shiftMustBeReleased = TRUE; -+ else -+ shiftMustBePressed = TRUE; -+ } -+ break; -+ } -+ } -+#endif -+ -+ if (!keyCode) { -+ -+ /* not one of our predefined keys - see if it's in the current keyboard -+ mapping (i.e. we've already allocated an extra keycode for it) */ -+ -+ if (keySyms->mapWidth < 2) { -+ ErrorF("KbdAddEvent: Sanity check failed - Keyboard mapping has " -+ "less than 2 keysyms per keycode (KeySym 0x%x)\n", -+ (unsigned) keySym); -+ return; -+ } -+ -+ for (i = 0; i < NO_OF_KEYS * keySyms->mapWidth; i++) { -+ if (keySym == keySyms->map[i]) { -+ keyCode = MIN_KEY_CODE + i / keySyms->mapWidth; -+ -+ if (keySyms->map[(i / keySyms->mapWidth) -+ * keySyms->mapWidth + 1] != NoSymbol) { -+ -+ /* this keycode has more than one symbol associated with -+ it, so shift state is important */ -+ -+ if ((i % keySyms->mapWidth) == 0) -+ shiftMustBeReleased = TRUE; -+ else -+ shiftMustBePressed = TRUE; -+ } -+ break; -+ } -+ if ((freeIndex == -1) && (keySyms->map[i] == NoSymbol) -+ && (i % keySyms->mapWidth) == 0) -+ { -+ freeIndex = i; -+ } -+ } -+ } -+ -+ if (!keyCode) { -+ KeySym lower, upper; -+ -+ /* we don't have an existing keycode - make one up on the fly and add -+ it to the keyboard mapping. Thanks to Vlad Harchev for pointing -+ out problems with non-ascii capitalisation. */ -+ -+ if (freeIndex == -1) { -+ ErrorF("KbdAddEvent: ignoring KeySym 0x%x - no free KeyCodes\n", -+ (unsigned) keySym); -+ return; -+ } -+ -+ keyCode = MIN_KEY_CODE + freeIndex / keySyms->mapWidth; -+ -+ XConvertCase(keySym, &lower, &upper); -+ -+ if (lower == upper) { -+ keySyms->map[freeIndex] = keySym; -+ -+ } else { -+ keySyms->map[freeIndex] = lower; -+ keySyms->map[freeIndex+1] = upper; -+ -+ if (keySym == lower) -+ shiftMustBeReleased = TRUE; -+ else -+ shiftMustBePressed = TRUE; -+ } -+ -+ SendMappingNotify(MappingKeyboard, keyCode, 1, serverClient); -+ -+ ErrorF("KbdAddEvent: unknown KeySym 0x%x - allocating KeyCode %d\n", -+ (unsigned) keySym, keyCode); -+ } -+ -+ time = GetTimeInMillis(); -+ -+ if (down) { -+ if (shiftMustBePressed && !(kbdDevice->key->state & ShiftMask)) { -+ fakeShiftPress = TRUE; -+ fake.u.u.type = KeyPress; -+ fake.u.u.detail = SHIFT_L_KEY_CODE; -+ fake.u.keyButtonPointer.time = time; -+ Enqueue(&fake); -+ } -+ if (shiftMustBeReleased && (kbdDevice->key->state & ShiftMask)) { -+ if (KEY_IS_PRESSED(SHIFT_L_KEY_CODE)) { -+ fakeShiftLRelease = TRUE; -+ fake.u.u.type = KeyRelease; -+ fake.u.u.detail = SHIFT_L_KEY_CODE; -+ fake.u.keyButtonPointer.time = time; -+ Enqueue(&fake); -+ } -+ if (KEY_IS_PRESSED(SHIFT_R_KEY_CODE)) { -+ fakeShiftRRelease = TRUE; -+ fake.u.u.type = KeyRelease; -+ fake.u.u.detail = SHIFT_R_KEY_CODE; -+ fake.u.keyButtonPointer.time = time; -+ Enqueue(&fake); -+ } -+ } -+ } -+ -+ ev.u.u.detail = keyCode; -+ ev.u.keyButtonPointer.time = time; -+ Enqueue(&ev); -+ -+ if (fakeShiftPress) { -+ fake.u.u.type = KeyRelease; -+ fake.u.u.detail = SHIFT_L_KEY_CODE; -+ fake.u.keyButtonPointer.time = time; -+ Enqueue(&fake); -+ } -+ if (fakeShiftLRelease) { -+ fake.u.u.type = KeyPress; -+ fake.u.u.detail = SHIFT_L_KEY_CODE; -+ fake.u.keyButtonPointer.time = time; -+ Enqueue(&fake); -+ } -+ if (fakeShiftRRelease) { -+ fake.u.u.type = KeyPress; -+ fake.u.u.detail = SHIFT_R_KEY_CODE; -+ fake.u.keyButtonPointer.time = time; -+ Enqueue(&fake); -+ } -+} -+ -+/* -+ * Called when the rfbserver receives a rfbPointerEvent event from a client. -+ * Put an X mouse event into the event queue. -+ */ -+void -+PtrAddEvent(buttonMask, x, y, cl) -+ int buttonMask; -+ int x; -+ int y; -+ rfbClientPtr cl; -+{ -+ xEvent ev; -+ int i; -+ unsigned long time; -+ static int oldButtonMask = 0; -+ -+#ifdef CORBA -+ if (cl) { -+ CARD32 clientId = cl->sock; -+ ChangeWindowProperty(WindowTable[0], VNC_LAST_CLIENT_ID, XA_INTEGER, -+ 32, PropModeReplace, 1, (pointer)&clientId, TRUE); -+ } -+#endif -+ -+ time = GetTimeInMillis(); -+ -+ miPointerAbsoluteCursor(x, y, time); -+ -+ for (i = 0; i < 5; i++) { -+ if ((buttonMask ^ oldButtonMask) & (1<key->down[i] != 0) { -+ for (j = 0; j < 8; j++) { -+ if (kbdDevice->key->down[i] & (1 << j)) { -+ ev.u.u.type = KeyRelease; -+ ev.u.u.detail = (i << 3) | j; -+ ev.u.keyButtonPointer.time = time; -+ Enqueue(&ev); -+ } -+ } -+ } -+ } -+} -+ -+ -+/* copied from Xlib source */ -+ -+static 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; -+ } -+} -diff --git a/hw/xfree86/vnc/keyboard.h b/hw/xfree86/vnc/keyboard.h -new file mode 100644 -index 0000000..ab5b1b3 ---- /dev/null -+++ b/hw/xfree86/vnc/keyboard.h -@@ -0,0 +1,167 @@ -+/* -+ * Copyright (C) 2002 Alan Hourihane. 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. -+ * -+ * Author: Alan Hourihane -+ */ -+ -+#define MIN_KEY_CODE 8 -+#define MAX_KEY_CODE 255 -+#define NO_OF_KEYS (MAX_KEY_CODE - MIN_KEY_CODE + 1) -+#define GLYPHS_PER_KEY 4 -+ -+#define CONTROL_L_KEY_CODE (MIN_KEY_CODE + 29) -+#define CONTROL_R_KEY_CODE (MIN_KEY_CODE + 101) -+#define SHIFT_L_KEY_CODE (MIN_KEY_CODE + 42) -+#define SHIFT_R_KEY_CODE (MIN_KEY_CODE + 54) -+#define META_L_KEY_CODE (MIN_KEY_CODE + 107) -+#define META_R_KEY_CODE (MIN_KEY_CODE + 108) -+#define ALT_L_KEY_CODE (MIN_KEY_CODE + 56) -+#define ALT_R_KEY_CODE (MIN_KEY_CODE + 105) -+ -+static KeySym map[MAX_KEY_CODE * GLYPHS_PER_KEY] = { -+ /* 0x00 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x01 */ XK_Escape, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x02 */ XK_1, XK_exclam, NoSymbol, NoSymbol, -+ /* 0x03 */ XK_2, XK_at, NoSymbol, NoSymbol, -+ /* 0x04 */ XK_3, XK_numbersign, NoSymbol, NoSymbol, -+ /* 0x05 */ XK_4, XK_dollar, NoSymbol, NoSymbol, -+ /* 0x06 */ XK_5, XK_percent, NoSymbol, NoSymbol, -+ /* 0x07 */ XK_6, XK_asciicircum, NoSymbol, NoSymbol, -+ /* 0x08 */ XK_7, XK_ampersand, NoSymbol, NoSymbol, -+ /* 0x09 */ XK_8, XK_asterisk, NoSymbol, NoSymbol, -+ /* 0x0a */ XK_9, XK_parenleft, NoSymbol, NoSymbol, -+ /* 0x0b */ XK_0, XK_parenright, NoSymbol, NoSymbol, -+ /* 0x0c */ XK_minus, XK_underscore, NoSymbol, NoSymbol, -+ /* 0x0d */ XK_equal, XK_plus, NoSymbol, NoSymbol, -+ /* 0x0e */ XK_BackSpace, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x0f */ XK_Tab, XK_ISO_Left_Tab,NoSymbol, NoSymbol, -+ /* 0x10 */ XK_q, XK_Q, NoSymbol, NoSymbol, -+ /* 0x11 */ XK_w, XK_W, NoSymbol, NoSymbol, -+ /* 0x12 */ XK_e, XK_E, NoSymbol, NoSymbol, -+ /* 0x13 */ XK_r, XK_R, NoSymbol, NoSymbol, -+ /* 0x14 */ XK_t, XK_T, NoSymbol, NoSymbol, -+ /* 0x15 */ XK_y, XK_Y, NoSymbol, NoSymbol, -+ /* 0x16 */ XK_u, XK_U, NoSymbol, NoSymbol, -+ /* 0x17 */ XK_i, XK_I, NoSymbol, NoSymbol, -+ /* 0x18 */ XK_o, XK_O, NoSymbol, NoSymbol, -+ /* 0x19 */ XK_p, XK_P, NoSymbol, NoSymbol, -+ /* 0x1a */ XK_bracketleft, XK_braceleft, NoSymbol, NoSymbol, -+ /* 0x1b */ XK_bracketright,XK_braceright, NoSymbol, NoSymbol, -+ /* 0x1c */ XK_Return, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x1d */ XK_Control_L, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x1e */ XK_a, XK_A, NoSymbol, NoSymbol, -+ /* 0x1f */ XK_s, XK_S, NoSymbol, NoSymbol, -+ /* 0x20 */ XK_d, XK_D, NoSymbol, NoSymbol, -+ /* 0x21 */ XK_f, XK_F, NoSymbol, NoSymbol, -+ /* 0x22 */ XK_g, XK_G, NoSymbol, NoSymbol, -+ /* 0x23 */ XK_h, XK_H, NoSymbol, NoSymbol, -+ /* 0x24 */ XK_j, XK_J, NoSymbol, NoSymbol, -+ /* 0x25 */ XK_k, XK_K, NoSymbol, NoSymbol, -+ /* 0x26 */ XK_l, XK_L, NoSymbol, NoSymbol, -+ /* 0x27 */ XK_semicolon, XK_colon, NoSymbol, NoSymbol, -+ /* 0x28 */ XK_quoteright, XK_quotedbl, NoSymbol, NoSymbol, -+ /* 0x29 */ XK_quoteleft, XK_asciitilde, NoSymbol, NoSymbol, -+ /* 0x2a */ XK_Shift_L, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x2b */ XK_backslash, XK_bar, NoSymbol, NoSymbol, -+ /* 0x2c */ XK_z, XK_Z, NoSymbol, NoSymbol, -+ /* 0x2d */ XK_x, XK_X, NoSymbol, NoSymbol, -+ /* 0x2e */ XK_c, XK_C, NoSymbol, NoSymbol, -+ /* 0x2f */ XK_v, XK_V, NoSymbol, NoSymbol, -+ /* 0x30 */ XK_b, XK_B, NoSymbol, NoSymbol, -+ /* 0x31 */ XK_n, XK_N, NoSymbol, NoSymbol, -+ /* 0x32 */ XK_m, XK_M, NoSymbol, NoSymbol, -+ /* 0x33 */ XK_comma, XK_less, NoSymbol, NoSymbol, -+ /* 0x34 */ XK_period, XK_greater, NoSymbol, NoSymbol, -+ /* 0x35 */ XK_slash, XK_question, NoSymbol, NoSymbol, -+ /* 0x36 */ XK_Shift_R, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x37 */ XK_KP_Multiply, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x38 */ XK_Alt_L, XK_Meta_L, NoSymbol, NoSymbol, -+ /* 0x39 */ XK_space, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x3a */ XK_Caps_Lock, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x3b */ XK_F1, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x3c */ XK_F2, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x3d */ XK_F3, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x3e */ XK_F4, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x3f */ XK_F5, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x40 */ XK_F6, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x41 */ XK_F7, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x42 */ XK_F8, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x43 */ XK_F9, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x44 */ XK_F10, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x45 */ XK_Num_Lock, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x46 */ XK_Scroll_Lock, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x47 */ XK_KP_Home, XK_KP_7, NoSymbol, NoSymbol, -+ /* 0x48 */ XK_KP_Up, XK_KP_8, NoSymbol, NoSymbol, -+ /* 0x49 */ XK_KP_Prior, XK_KP_9, NoSymbol, NoSymbol, -+ /* 0x4a */ XK_KP_Subtract, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x4b */ XK_KP_Left, XK_KP_4, NoSymbol, NoSymbol, -+ /* 0x4c */ XK_KP_Begin, XK_KP_5, NoSymbol, NoSymbol, -+ /* 0x4d */ XK_KP_Right, XK_KP_6, NoSymbol, NoSymbol, -+ /* 0x4e */ XK_KP_Add, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x4f */ XK_KP_End, XK_KP_1, NoSymbol, NoSymbol, -+ /* 0x50 */ XK_KP_Down, XK_KP_2, NoSymbol, NoSymbol, -+ /* 0x51 */ XK_KP_Next, XK_KP_3, NoSymbol, NoSymbol, -+ /* 0x52 */ XK_KP_Insert, XK_KP_0, NoSymbol, NoSymbol, -+ /* 0x53 */ XK_KP_Delete, XK_KP_Decimal, NoSymbol, NoSymbol, -+ /* 0x54 */ XK_Sys_Req, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x55 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x56 */ XK_less, XK_greater, NoSymbol, NoSymbol, -+ /* 0x57 */ XK_F11, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x58 */ XK_F12, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x59 */ XK_Home, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x5a */ XK_Up, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x5b */ XK_Prior, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x5c */ XK_Left, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x5d */ XK_Begin, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x5e */ XK_Right, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x5f */ XK_End, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x60 */ XK_Down, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x61 */ XK_Next, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x62 */ XK_Insert, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x63 */ XK_Delete, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x64 */ XK_KP_Enter, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x65 */ XK_Control_R, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x66 */ XK_Pause, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x67 */ XK_Print, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x68 */ XK_KP_Divide, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x69 */ XK_Alt_R, XK_Meta_R, NoSymbol, NoSymbol, -+ /* 0x6a */ XK_Break, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x6b */ XK_Meta_L, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x6c */ XK_Meta_R, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x6d */ XK_Menu, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x6e */ XK_F13, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x6f */ XK_F14, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x70 */ XK_F15, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x71 */ XK_F16, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x72 */ XK_F17, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x73 */ XK_backslash, XK_underscore, NoSymbol, NoSymbol, -+ /* 0x74 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x75 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x76 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x77 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x78 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x79 */ XK_Henkan, XK_Mode_switch, NoSymbol, NoSymbol, -+ /* 0x7a */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x7b */ XK_Muhenkan, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x7c */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x7d */ XK_backslash, XK_bar, NoSymbol, NoSymbol, -+ /* 0x7e */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, -+ /* 0x7f */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, -+}; -+ -+#define N_PREDEFINED_KEYS (sizeof(map) / (sizeof(KeySym) * GLYPHS_PER_KEY)) -diff --git a/hw/xfree86/vnc/loginauth.c b/hw/xfree86/vnc/loginauth.c -new file mode 100644 -index 0000000..5041429 ---- /dev/null -+++ b/hw/xfree86/vnc/loginauth.c -@@ -0,0 +1,141 @@ -+/* -+ * loginauth.c - deal with login-style Unix authentication. -+ * -+ * This file implements the UnixLogin authentication protocol when setting up -+ * an RFB connection. -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ */ -+ -+/* -+ * Copyright (C) 2003 Constantin Kaplinsky. 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. -+ */ -+ -+#ifdef linux -+#include /* XXX xserver has a shadow.h file too */ -+#endif -+#include -+#include -+#include -+#define _XOPEN_SOURCE -+#define __USE_XOPEN /* XXX shouldn't really need this */ -+#include -+#include -+#include -+#include "rfb.h" -+ -+void rfbLoginAuthProcessClientMessage(rfbClientPtr cl) -+{ -+ int n1 = 0, n2 = 0; -+ CARD32 loginLen, passwdLen, authResult; -+ char *loginBuf, *passwdBuf; -+ struct passwd *ps; -+ char *encPasswd1, *encPasswd2; -+ Bool ok; -+ -+ if ((n1 = ReadExact(cl->sock, (char *)&loginLen, -+ sizeof(loginLen))) <= 0 || -+ (n2 = ReadExact(cl->sock, (char *)&passwdLen, -+ sizeof(passwdLen))) <= 0) { -+ if (n1 != 0 || n2 != 0) -+ rfbLogPerror("rfbLoginAuthProcessClientMessage: read"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ loginLen = Swap32IfLE(loginLen); -+ passwdLen = Swap32IfLE(passwdLen); -+ loginBuf = (char *)xalloc(loginLen + 1); -+ passwdBuf = (char *)xalloc(passwdLen + 1); -+ -+ n1 = n2 = 0; -+ if ((n1 = ReadExact(cl->sock, loginBuf, loginLen)) <= 0 || -+ (n2 = ReadExact(cl->sock, passwdBuf, passwdLen)) <= 0) { -+ if (n1 != 0 || n2 != 0) -+ rfbLogPerror("rfbLoginAuthProcessClientMessage: read"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ loginBuf[loginLen] = '\0'; -+ passwdBuf[passwdLen] = '\0'; -+ -+ encPasswd1 = encPasswd2 = NULL; -+ -+ ps = getpwnam(loginBuf); -+ if (ps == NULL) { -+ rfbLog("rfbLoginAuthProcessClientMessage: " -+ "Cannot get password file entry for \"%s\"\n", loginBuf); -+ } else { -+ encPasswd1 = ps->pw_passwd; -+#ifdef linux -+ if (strlen(ps->pw_passwd) == 1) { -+ struct spwd *sps; -+ -+ sps = getspnam(loginBuf); -+ if (sps == NULL) { -+ rfbLog("rfbLoginAuthProcessClientMessage:" -+ " getspnam() failed for user \"%s\"\n", loginBuf); -+ } else { -+ encPasswd1 = sps->sp_pwdp; -+ } -+ } -+#endif -+ encPasswd2 = crypt(passwdBuf, encPasswd1); -+ memset(passwdBuf, 0, strlen(passwdBuf)); -+ } -+ -+ ok = FALSE; -+ if (encPasswd1 != NULL && encPasswd2 != NULL) { -+ if (strcmp(encPasswd1, encPasswd2) == 0) -+ ok = TRUE; -+ } -+ -+ if (!ok) { -+ rfbLog("rfbAuthProcessClientMessage: authentication failed from %s\n", -+ cl->host); -+ -+ if (rfbAuthConsiderBlocking(cl)) { -+ authResult = Swap32IfLE(rfbVncAuthTooMany); -+ } else { -+ authResult = Swap32IfLE(rfbVncAuthFailed); -+ } -+ -+ if (WriteExact(cl->sock, (char *)&authResult, -+ sizeof(authResult)) < 0) { -+ rfbLogPerror("rfbLoginAuthProcessClientMessage: write"); -+ } -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ rfbAuthUnblock(cl); -+ -+ cl->login = strdup(loginBuf); -+ rfbLog("Login-style authentication passed for user %s at %s\n", -+ cl->login, cl->host); -+ -+ authResult = Swap32IfLE(rfbVncAuthOK); -+ -+ if (WriteExact(cl->sock, (char *)&authResult, sizeof(authResult)) < 0) { -+ rfbLogPerror("rfbLoginAuthProcessClientMessage: write"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ cl->state = RFB_INITIALISATION; -+} -+ -diff --git a/hw/xfree86/vnc/rfb.h b/hw/xfree86/vnc/rfb.h -new file mode 100644 -index 0000000..f22604b ---- /dev/null -+++ b/hw/xfree86/vnc/rfb.h -@@ -0,0 +1,726 @@ -+/* -+ * rfb.h - header file for RFB DDX implementation. -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ */ -+ -+/* -+ * Copyright (C) 2000-2004 Const Kaplinsky. All Rights Reserved. -+ * Copyright (C) 2000 Tridia Corporation. All Rights Reserved. -+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. -+ * -+ * This is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This software is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this software; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -+ * USA. -+ */ -+ -+#ifdef HAVE_XORG_CONFIG_H -+#include -+#endif -+ -+#include -+#include "scrnintstr.h" -+#include "colormapst.h" -+#include "dixstruct.h" -+#include "gcstruct.h" -+#include "regionstr.h" -+#include "windowstr.h" -+#include "dixfontstr.h" -+#include "rfbproto.h" -+#include "vncauth.h" -+#include "picturestr.h" -+ -+#define _VNC_SERVER -+#include -+ -+ -+ -+#if defined(sun) || defined(hpux) -+#define SOCKLEN_T int -+#else -+#define SOCKLEN_T socklen_t -+#endif -+ -+/* It's a good idea to keep these values a bit greater than required. */ -+#define MAX_ENCODINGS 10 -+#define MAX_SECURITY_TYPES 4 -+#define MAX_TUNNELING_CAPS 16 -+#define MAX_AUTH_CAPS 16 -+ -+/* -+ * HTTP_BUF_SIZE for http transfers -+ */ -+#define HTTP_BUF_SIZE 32768 -+ -+/* -+ * UPDATE_BUF_SIZE must be big enough to send at least one whole line of the -+ * framebuffer. So for a max screen width of say 2K with 32-bit pixels this -+ * means 8K minimum. -+ */ -+#define UPDATE_BUF_SIZE 30000 -+ -+#if XFREE86VNC -+#include "xf86.h" -+#include "vncint.h" -+#define VNCSCREENPTR(ptr) \ -+ vncScreenPtr pVNC = VNCPTR(ptr) -+#else -+bad! -+#define VNCSCREENPTR(ptr) \ -+/* Soon \ -+ rfbScreenInfoPtr pVNC = rfbScreen[ptr->myNum] \ -+*/ \ -+ rfbScreenInfoPtr pVNC = &rfbScreen -+#endif -+ -+/* -+ * Per-screen (framebuffer) structure. There is only one of these, since we -+ * don't allow the X server to have multiple screens. -+ */ -+ -+typedef struct -+{ -+ int rfbPort; -+ int rdpPort; -+ int udpPort; -+ int rfbListenSock; -+ int rdpListenSock; -+ int udpSock; -+ int httpPort; -+ int httpListenSock; -+ int httpSock; -+ char * httpDir; -+ char buf[HTTP_BUF_SIZE]; -+ Bool udpSockConnected; -+ char * rfbAuthPasswdFile; -+ size_t buf_filled; -+ int maxFd; -+ fd_set allFds; -+ Bool useGetImage; -+ Bool noCursor; -+ Bool rfbAlwaysShared; -+ Bool rfbNeverShared; -+ Bool rfbDontDisconnect; -+ Bool rfbUserAccept; -+ Bool rfbViewOnly; -+ ColormapPtr savedColormap; -+ ColormapPtr rfbInstalledColormap; -+ rfbPixelFormat rfbServerFormat; -+ Bool rfbAuthTooManyTries; -+ int rfbAuthTries; -+ Bool loginAuthEnabled; -+ struct in_addr interface; -+ OsTimerPtr timer; -+ char updateBuf[UPDATE_BUF_SIZE]; -+ int ublen; -+ int width; -+ int paddedWidthInBytes; -+ int height; -+ int depth; -+ int bitsPerPixel; -+ int sizeInBytes; -+ unsigned char *pfbMemory; -+ Pixel blackPixel; -+ Pixel whitePixel; -+ -+ /* The following two members are used to minimise the amount of unnecessary -+ drawing caused by cursor movement. Whenever any drawing affects the -+ part of the screen where the cursor is, the cursor is removed first and -+ then the drawing is done (this is what the sprite routines test for). -+ Afterwards, however, we do not replace the cursor, even when the cursor -+ is logically being moved across the screen. We only draw the cursor -+ again just as we are about to send the client a framebuffer update. -+ -+ We need to be careful when removing and drawing the cursor because of -+ their relationship with the normal drawing routines. The drawing -+ routines can invoke the cursor routines, but also the cursor routines -+ themselves end up invoking drawing routines. -+ -+ Removing the cursor (rfbSpriteRemoveCursor) is eventually achieved by -+ doing a CopyArea from a pixmap to the screen, where the pixmap contains -+ the saved contents of the screen under the cursor. Before doing this, -+ however, we set cursorIsDrawn to FALSE. Then, when CopyArea is called, -+ it sees that cursorIsDrawn is FALSE and so doesn't feel the need to -+ (recursively!) remove the cursor before doing it. -+ -+ Putting up the cursor (rfbSpriteRestoreCursor) involves a call to -+ PushPixels. While this is happening, cursorIsDrawn must be FALSE so -+ that PushPixels doesn't think it has to remove the cursor first. -+ Obviously cursorIsDrawn is set to TRUE afterwards. -+ -+ Another problem we face is that drawing routines sometimes cause a -+ framebuffer update to be sent to the RFB client. When the RFB client is -+ already waiting for a framebuffer update and some drawing to the -+ framebuffer then happens, the drawing routine sees that the client is -+ ready, so it calls rfbSendFramebufferUpdate. If the cursor is not drawn -+ at this stage, it must be put up, and so rfbSpriteRestoreCursor is -+ called. However, if the original drawing routine was actually called -+ from within rfbSpriteRestoreCursor or rfbSpriteRemoveCursor we don't -+ want this to happen. So both the cursor routines set -+ dontSendFramebufferUpdate to TRUE, and all the drawing routines check -+ this before calling rfbSendFramebufferUpdate. */ -+ -+ Bool cursorIsDrawn; /* TRUE if the cursor is currently drawn */ -+ Bool dontSendFramebufferUpdate; /* TRUE while removing or drawing the -+ cursor */ -+ -+ /* wrapped screen functions */ -+ -+ CloseScreenProcPtr CloseScreen; -+ CreateGCProcPtr CreateGC; -+ PaintWindowBackgroundProcPtr PaintWindowBackground; -+ PaintWindowBorderProcPtr PaintWindowBorder; -+ CopyWindowProcPtr CopyWindow; -+ ClearToBackgroundProcPtr ClearToBackground; -+ RestoreAreasProcPtr RestoreAreas; -+ ScreenWakeupHandlerProcPtr WakeupHandler; -+#ifdef CHROMIUM -+ RealizeWindowProcPtr RealizeWindow; -+ UnrealizeWindowProcPtr UnrealizeWindow; -+ DestroyWindowProcPtr DestroyWindow; -+ ResizeWindowProcPtr ResizeWindow; -+ PositionWindowProcPtr PositionWindow; -+ ClipNotifyProcPtr ClipNotify; -+#endif -+#ifdef RENDER -+ CompositeProcPtr Composite; -+#endif -+ -+} rfbScreenInfo, *rfbScreenInfoPtr; -+ -+ -+/* -+ * rfbTranslateFnType is the type of translation functions. -+ */ -+ -+struct rfbClientRec; -+typedef void (*rfbTranslateFnType)(ScreenPtr pScreen, -+ char *table, rfbPixelFormat *in, -+ rfbPixelFormat *out, -+ unsigned char *iptr, char *optr, -+ int bytesBetweenInputLines, -+ int width, int height, -+ int x, int y); -+ -+ -+/* -+ * Per-client structure. -+ */ -+ -+typedef struct rfbClientRec { -+ int sock; -+ char *host; -+ char *login; -+ -+ int protocol_minor_ver; /* RFB protocol minor version in use. */ -+ Bool protocol_tightvnc; /* TightVNC protocol extensions enabled */ -+ -+ /* Possible client states: */ -+ -+ enum { -+ RFB_PROTOCOL_VERSION, /* establishing protocol version */ -+ RFB_SECURITY_TYPE, /* negotiating security (RFB v.3.7) */ -+ RFB_TUNNELING_TYPE, /* establishing tunneling (RFB v.3.7t) */ -+ RFB_AUTH_TYPE, /* negotiating authentication (RFB v.3.7t) */ -+ RFB_AUTHENTICATION, /* authenticating (VNC authentication) */ -+ RFB_INITIALISATION, /* sending initialisation messages */ -+ RFB_NORMAL /* normal protocol messages */ -+ } state; -+ -+ Bool viewOnly; /* Do not accept input from this client. */ -+ -+ Bool reverseConnection; -+ -+ Bool readyForSetColourMapEntries; -+ -+ Bool useCopyRect; -+ int preferredEncoding; -+ int correMaxWidth, correMaxHeight; -+ -+ /* The list of security types sent to this client (protocol 3.7). -+ Note that the first entry is the number of list items following. */ -+ -+ CARD8 securityTypes[MAX_SECURITY_TYPES + 1]; -+ -+ /* Lists of capability codes sent to clients. We remember these -+ lists to restrict clients from choosing those tunneling and -+ authentication types that were not advertised. */ -+ -+ int nAuthCaps; -+ CARD32 authCaps[MAX_AUTH_CAPS]; -+ -+ /* This is not useful while we don't support tunneling: -+ int nTunnelingCaps; -+ CARD32 tunnelingCaps[MAX_TUNNELING_CAPS]; */ -+ -+ /* The following member is only used during VNC authentication */ -+ -+ CARD8 authChallenge[CHALLENGESIZE]; -+ -+ /* The following members represent the update needed to get the client's -+ framebuffer from its present state to the current state of our -+ framebuffer. -+ -+ If the client does not accept CopyRect encoding then the update is -+ simply represented as the region of the screen which has been modified -+ (modifiedRegion). -+ -+ If the client does accept CopyRect encoding, then the update consists of -+ two parts. First we have a single copy from one region of the screen to -+ another (the destination of the copy is copyRegion), and second we have -+ the region of the screen which has been modified in some other way -+ (modifiedRegion). -+ -+ Although the copy is of a single region, this region may have many -+ rectangles. When sending an update, the copyRegion is always sent -+ before the modifiedRegion. This is because the modifiedRegion may -+ overlap parts of the screen which are in the source of the copy. -+ -+ In fact during normal processing, the modifiedRegion may even overlap -+ the destination copyRegion. Just before an update is sent we remove -+ from the copyRegion anything in the modifiedRegion. */ -+ -+ RegionRec copyRegion; /* the destination region of the copy */ -+ int copyDX, copyDY; /* the translation by which the copy happens */ -+ -+ RegionRec modifiedRegion; /* the region of the screen modified in any -+ other way */ -+ -+ /* As part of the FramebufferUpdateRequest, a client can express interest -+ in a subrectangle of the whole framebuffer. This is stored in the -+ requestedRegion member. In the normal case this is the whole -+ framebuffer if the client is ready, empty if it's not. */ -+ -+ RegionRec requestedRegion; -+ -+ /* The following members represent the state of the "deferred update" timer -+ - when the framebuffer is modified and the client is ready, in most -+ cases it is more efficient to defer sending the update by a few -+ milliseconds so that several changes to the framebuffer can be combined -+ into a single update. */ -+ -+ Bool deferredUpdateScheduled; -+ OsTimerPtr deferredUpdateTimer; -+ -+ /* translateFn points to the translation function which is used to copy -+ and translate a rectangle from the framebuffer to an output buffer. */ -+ -+ rfbTranslateFnType translateFn; -+ -+ char *translateLookupTable; -+ -+ rfbPixelFormat format; -+ -+ /* statistics */ -+ -+ int rfbBytesSent[MAX_ENCODINGS]; -+ int rfbRectanglesSent[MAX_ENCODINGS]; -+ int rfbLastRectMarkersSent; -+ int rfbLastRectBytesSent; -+ int rfbCursorShapeBytesSent; -+ int rfbCursorShapeUpdatesSent; -+ int rfbCursorPosBytesSent; -+ int rfbCursorPosUpdatesSent; -+ int rfbFramebufferUpdateMessagesSent; -+ int rfbRawBytesEquivalent; -+ int rfbKeyEventsRcvd; -+ int rfbPointerEventsRcvd; -+ -+ /* zlib encoding -- necessary compression state info per client */ -+ -+ struct z_stream_s compStream; -+ Bool compStreamInited; -+ -+ CARD32 zlibCompressLevel; -+ -+ /* tight encoding -- preserve zlib streams' state for each client */ -+ -+ z_stream zsStruct[4]; -+ Bool zsActive[4]; -+ int zsLevel[4]; -+ int tightCompressLevel; -+ int tightQualityLevel; -+ -+ Bool enableLastRectEncoding; /* client supports LastRect encoding */ -+ Bool enableCursorShapeUpdates; /* client supports cursor shape updates */ -+ Bool enableCursorPosUpdates; /* client supports PointerPos updates */ -+#ifdef CHROMIUM -+ Bool enableChromiumEncoding; /* client supports Chromium encoding */ -+#endif -+ Bool useRichCursorEncoding; /* rfbEncodingRichCursor is preferred */ -+ Bool cursorWasChanged; /* cursor shape update should be sent */ -+ Bool cursorWasMoved; /* cursor position update should be sent */ -+ -+ int cursorX, cursorY; /* client's cursor position */ -+ -+ struct rfbClientRec *next; -+ -+ ScreenPtr pScreen; -+ int userAccepted; -+ -+#ifdef CHROMIUM -+ unsigned int chromium_port; -+ unsigned int chromium_msport; -+#endif -+} rfbClientRec, *rfbClientPtr; -+ -+#ifdef CHROMIUM -+typedef struct CRWindowTable { -+ unsigned long CRwinId; -+ unsigned long XwinId; -+ BoxPtr clipRects; -+ int numRects; -+ struct CRWindowTable *next; -+} CRWindowTable, *CRWindowTablePtr; -+ -+extern struct CRWindowTable *windowTable; -+#endif -+ -+/* -+ * This macro is used to test whether there is a framebuffer update needing to -+ * be sent to the client. -+ */ -+ -+#define FB_UPDATE_PENDING(cl) \ -+ ((!(cl)->enableCursorShapeUpdates && !pVNC->cursorIsDrawn) || \ -+ ((cl)->enableCursorShapeUpdates && (cl)->cursorWasChanged) || \ -+ ((cl)->enableCursorPosUpdates && (cl)->cursorWasMoved) || \ -+ REGION_NOTEMPTY(((cl)->pScreen),&(cl)->copyRegion) || \ -+ REGION_NOTEMPTY(((cl)->pScreen),&(cl)->modifiedRegion)) -+ -+/* -+ * This macro creates an empty region (ie. a region with no areas) if it is -+ * given a rectangle with a width or height of zero. It appears that -+ * REGION_INTERSECT does not quite do the right thing with zero-width -+ * rectangles, but it should with completely empty regions. -+ */ -+ -+#define SAFE_REGION_INIT(pscreen, preg, rect, size) \ -+{ \ -+ if ( ( (rect) ) && \ -+ ( ( (rect)->x2 == (rect)->x1 ) || \ -+ ( (rect)->y2 == (rect)->y1 ) ) ) { \ -+ REGION_NULL( (pscreen), (preg) ); \ -+ } else { \ -+ REGION_INIT( (pscreen), (preg), (rect), (size) ); \ -+ } \ -+} -+ -+/* -+ * An rfbGCRec is where we store the pointers to the original GC funcs and ops -+ * which we wrap (NULL means not wrapped). -+ */ -+ -+typedef struct { -+ GCFuncs *wrapFuncs; -+ GCOps *wrapOps; -+} rfbGCRec, *rfbGCPtr; -+ -+ -+ -+/* -+ * Macros for endian swapping. -+ */ -+ -+#define Swap16(s) ((((s) & 0xff) << 8) | (((s) >> 8) & 0xff)) -+ -+#define Swap32(l) (((l) >> 24) | \ -+ (((l) & 0x00ff0000) >> 8) | \ -+ (((l) & 0x0000ff00) << 8) | \ -+ ((l) << 24)) -+ -+static const int rfbEndianTest = 1; -+ -+#define Swap16IfLE(s) (*(const char *)&rfbEndianTest ? Swap16(s) : (s)) -+ -+#define Swap32IfLE(l) (*(const char *)&rfbEndianTest ? Swap32(l) : (l)) -+ -+ -+/* -+ * Macro to fill in an rfbCapabilityInfo structure (protocol 3.130). -+ * Normally, using macros is no good, but this macro saves us from -+ * writing constants twice -- it constructs signature names from codes. -+ * Note that "code_sym" argument should be a single symbol, not an expression. -+ */ -+ -+#define SetCapInfo(cap_ptr, code_sym, vendor) \ -+{ \ -+ rfbCapabilityInfo *pcap; \ -+ pcap = (cap_ptr); \ -+ pcap->code = Swap32IfLE(code_sym); \ -+ memcpy(pcap->vendorSignature, (vendor), \ -+ sz_rfbCapabilityInfoVendor); \ -+ memcpy(pcap->nameSignature, sig_##code_sym, \ -+ sz_rfbCapabilityInfoName); \ -+} -+ -+ -+/* init.c */ -+ -+extern char *desktopName; -+extern char rfbThisHost[]; -+extern Atom VNC_LAST_CLIENT_ID; -+ -+extern rfbScreenInfo rfbScreen; -+extern int rfbGCIndex; -+ -+extern int inetdSock; -+ -+extern int rfbBitsPerPixel(int depth); -+extern void rfbLog(char *format, ...); -+extern void rfbLogPerror(char *str); -+ -+ -+/* sockets.c */ -+ -+extern int rfbMaxClientWait; -+ -+extern Bool rfbInitSockets(ScreenPtr pScreen); -+extern void rfbDisconnectUDPSock(ScreenPtr pScreen); -+extern void rfbCloseSock(ScreenPtr pScreen, int sock); -+extern void rfbCheckFds(ScreenPtr pScreen); -+extern void rfbWaitForClient(int sock); -+extern int rfbConnect(ScreenPtr pScreen, char *host, int port); -+ -+extern int ReadExact(int sock, char *buf, int len); -+extern int WriteExact(int sock, char *buf, int len); -+extern int ListenOnTCPPort(ScreenPtr pScreen, int port); -+extern int ListenOnUDPPort(ScreenPtr pScreen, int port); -+extern int ConnectToTcpAddr(char *host, int port); -+ -+ -+/* cmap.c */ -+ -+ -+extern int rfbListInstalledColormaps(ScreenPtr pScreen, Colormap *pmaps); -+extern void rfbInstallColormap(ColormapPtr pmap); -+extern void rfbUninstallColormap(ColormapPtr pmap); -+extern void rfbStoreColors(ColormapPtr pmap, int ndef, xColorItem *pdefs); -+ -+ -+/* draw.c */ -+ -+extern int rfbDeferUpdateTime; -+ -+extern void -+rfbComposite( -+ CARD8 op, -+ PicturePtr pSrc, -+ PicturePtr pMask, -+ PicturePtr pDst, -+ INT16 xSrc, -+ INT16 ySrc, -+ INT16 xMask, -+ INT16 yMask, -+ INT16 xDst, -+ INT16 yDst, -+ CARD16 width, -+ CARD16 height -+); -+ -+extern void rfbGlyphs( -+ CARD8 op, -+ PicturePtr pSrc, -+ PicturePtr pDst, -+ PictFormatPtr maskFormat, -+ INT16 xSrc, -+ INT16 ySrc, -+ int nlistInit, -+ GlyphListPtr listInit, -+ GlyphPtr *glyphsInit -+); -+extern Bool rfbCloseScreen(int,ScreenPtr); -+extern Bool rfbCreateGC(GCPtr); -+extern void rfbPaintWindowBackground(WindowPtr, RegionPtr, int what); -+extern void rfbPaintWindowBorder(WindowPtr, RegionPtr, int what); -+extern void rfbCopyWindow(WindowPtr, DDXPointRec, RegionPtr); -+#ifdef CHROMIUM -+extern Bool rfbRealizeWindow(WindowPtr); -+extern Bool rfbUnrealizeWindow(WindowPtr); -+extern Bool rfbDestroyWindow(WindowPtr); -+extern void rfbResizeWindow(WindowPtr, int x, int y, unsigned int w, unsigned int h, WindowPtr pSib); -+extern Bool rfbPositionWindow(WindowPtr, int x, int y); -+extern void rfbClipNotify(WindowPtr, int x, int y); -+#endif -+extern void rfbClearToBackground(WindowPtr, int x, int y, int w, -+ int h, Bool generateExposures); -+extern RegionPtr rfbRestoreAreas(WindowPtr, RegionPtr); -+extern void rfbScheduleUpdate(ScreenPtr pScreen); -+ -+ -+/* cutpaste.c */ -+ -+extern void rfbSetXCutText(char *str, int len); -+extern void rfbGotXCutText(char *str, int len); -+ -+ -+/* kbdptr.c */ -+ -+extern Bool compatibleKbd; -+extern unsigned char ptrAcceleration; -+ -+extern void PtrDeviceInit(void); -+extern void PtrDeviceOn(DeviceIntPtr pDev); -+extern void PtrDeviceOff(void); -+extern void PtrDeviceControl(DeviceIntPtr dev, PtrCtrl *ctrl); -+extern void PtrAddEvent(int buttonMask, int x, int y, rfbClientPtr cl); -+ -+extern void KbdDeviceInit(DeviceIntPtr pDevice, KeySymsPtr pKeySyms, CARD8 *pModMap); -+extern void KbdDeviceOn(void); -+extern void KbdDeviceOff(void); -+extern void KbdAddEvent(Bool down, KeySym keySym, rfbClientPtr cl); -+extern void KbdReleaseAllKeys(void); -+ -+/* rfbmouse.c */ -+extern void vncInitMouse(void); -+ -+/* rfbkeyb.c */ -+extern void vncInitKeyb(void); -+ -+ -+/* rfbserver.c */ -+ -+ -+extern rfbClientPtr rfbClientHead; -+extern rfbClientPtr pointerClient; -+ -+extern void rfbNewClientConnection(ScreenPtr pScreen, int sock); -+extern rfbClientPtr rfbReverseConnection(ScreenPtr pScreen, char *host, int port); -+extern void rfbRootPropertyChange(ScreenPtr pScreen); -+extern void rfbClientConnectionGone(int sock); -+extern void rfbProcessClientMessage(ScreenPtr pScreen, int sock); -+extern void rfbClientConnFailed(rfbClientPtr cl, char *reason); -+extern void rfbNewUDPConnection(int sock); -+extern void rfbProcessUDPInput(ScreenPtr pScreen, int sock); -+extern Bool rfbSendFramebufferUpdate(ScreenPtr pScreen, rfbClientPtr cl); -+extern Bool rfbSendRectEncodingRaw(rfbClientPtr cl, int x,int y,int w,int h); -+extern Bool rfbSendUpdateBuf(rfbClientPtr cl); -+extern Bool rfbSendSetColourMapEntries(rfbClientPtr cl, int firstColour, -+ int nColours); -+extern void rfbSendBell(void); -+extern void rfbSendServerCutText(char *str, int len); -+extern void rfbUserAllow(int sock, int accept); -+extern void rfbSetClip (WindowPtr pWin, BOOL enable); -+ -+extern int GenerateVncConnectedEvent(int sock); -+extern int GenerateVncDisconnectedEvent(int sock); -+ -+#ifdef CHROMIUM -+extern void rfbSendChromiumWindowShow(unsigned int winid, unsigned int show); -+extern void rfbSendChromiumMoveResizeWindow(unsigned int winid, int x, int y, unsigned int w, unsigned int h); -+extern void rfbSendChromiumClipList(unsigned int winid, BoxPtr pClipRects, int numClipRects); -+#endif -+ -+/* translate.c */ -+ -+extern Bool rfbEconomicTranslate; -+ -+extern void rfbTranslateNone(ScreenPtr pScreen, char *table, rfbPixelFormat *in, -+ rfbPixelFormat *out, -+ unsigned char *iptr, char *optr, -+ int bytesBetweenInputLines, -+ int width, int height, -+ int x, int y); -+extern Bool rfbSetTranslateFunction(rfbClientPtr cl); -+extern void rfbSetClientColourMaps(int firstColour, int nColours); -+extern Bool rfbSetClientColourMap(rfbClientPtr cl, int firstColour, -+ int nColours); -+ -+ -+/* httpd.c */ -+ -+extern Bool httpInitSockets(ScreenPtr pScreen); -+extern void httpCheckFds(ScreenPtr pScreen); -+ -+ -+/* vncext.c */ -+ -+#ifdef CHROMIUM -+extern void rfbSendChromiumStart(unsigned int ipaddress, unsigned int crServerPort, unsigned int mothershipPort); -+extern void rfbChromiumMonitorWindowID(unsigned int cr_windowid, unsigned long windowid); -+int GenerateVncChromiumConnectedEvent(int sock); -+#endif -+ -+ -+/* auth.c */ -+ -+extern void rfbAuthNewClient(rfbClientPtr cl); -+extern void rfbProcessClientSecurityType(rfbClientPtr cl); -+extern void rfbProcessClientTunnelingType(rfbClientPtr cl); -+extern void rfbProcessClientAuthType(rfbClientPtr cl); -+extern void rfbVncAuthProcessResponse(rfbClientPtr cl); -+ -+/* Functions to prevent too many successive authentication failures */ -+extern Bool rfbAuthConsiderBlocking(rfbClientPtr cl); -+extern void rfbAuthUnblock(rfbClientPtr cl); -+extern Bool rfbAuthIsBlocked(rfbClientPtr cl); -+ -+/* loginauth.c */ -+ -+extern void rfbLoginAuthProcessClientMessage(rfbClientPtr cl); -+ -+/* rre.c */ -+ -+extern Bool rfbSendRectEncodingRRE(rfbClientPtr cl, int x,int y,int w,int h); -+ -+ -+/* corre.c */ -+ -+extern Bool rfbSendRectEncodingCoRRE(rfbClientPtr cl, int x,int y,int w,int h); -+ -+ -+/* hextile.c */ -+ -+extern Bool rfbSendRectEncodingHextile(rfbClientPtr cl, int x, int y, int w, -+ int h); -+ -+ -+/* zlib.c */ -+ -+/* Minimum zlib rectangle size in bytes. Anything smaller will -+ * not compress well due to overhead. -+ */ -+#define VNC_ENCODE_ZLIB_MIN_COMP_SIZE (17) -+ -+/* Set maximum zlib rectangle size in pixels. Always allow at least -+ * two scan lines. -+ */ -+#define ZLIB_MAX_RECT_SIZE (128*256) -+#define ZLIB_MAX_SIZE(min) ((( min * 2 ) > ZLIB_MAX_RECT_SIZE ) ? \ -+ ( min * 2 ) : ZLIB_MAX_RECT_SIZE ) -+ -+extern Bool rfbSendRectEncodingZlib(rfbClientPtr cl, int x, int y, int w, -+ int h); -+ -+ -+/* tight.c */ -+ -+#define TIGHT_DEFAULT_COMPRESSION 6 -+ -+extern Bool rfbTightDisableGradient; -+ -+extern int rfbNumCodedRectsTight(rfbClientPtr cl, int x,int y,int w,int h); -+extern Bool rfbSendRectEncodingTight(rfbClientPtr cl, int x,int y,int w,int h); -+ -+ -+/* cursor.c */ -+ -+extern Bool rfbSendCursorShape(rfbClientPtr cl, ScreenPtr pScreen); -+extern Bool rfbSendCursorPos(rfbClientPtr cl, ScreenPtr pScreen); -+ -+ -+/* stats.c */ -+ -+extern void rfbResetStats(rfbClientPtr cl); -+extern void rfbPrintStats(rfbClientPtr cl); -diff --git a/hw/xfree86/vnc/rfbkeyb.c b/hw/xfree86/vnc/rfbkeyb.c -new file mode 100644 -index 0000000..4a26781 ---- /dev/null -+++ b/hw/xfree86/vnc/rfbkeyb.c -@@ -0,0 +1,410 @@ -+/* -+ * Copyright (C) 2002 Alan Hourihane. 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. -+ * -+ * Author: Alan Hourihane -+ */ -+ -+#include -+ -+#define XINPUT -+ -+#if XFREE86VNC -+ -+#include -+#include -+#include -+#include -+#include "xf86Xinput.h" -+#include -+#include -+ -+#else /* XFREE86VNC */ -+ -+#include -+#include -+#include -+ -+#endif /* XFREE86VNC */ -+ -+#include "rfb.h" -+ -+ -+extern Bool noXkbExtension; -+extern void rfbSendBell(void); -+extern DeviceIntPtr kbdDevice; -+ -+static const char *DEFAULTS[] = { -+ NULL -+}; -+ -+#include "keyboard.h" -+ -+#undef XKB -+#ifdef XKB -+#include -+#include -+#include -+ -+#if XFREE86VNC -+ /* -+ * would like to use an XkbComponentNamesRec here but can't without -+ * pulling in a bunch of header files. :-( -+ */ -+static char * xkbkeymap; -+static char * xkbkeycodes; -+static char * xkbtypes; -+static char * xkbcompat; -+static char * xkbsymbols; -+static char * xkbgeometry; -+static Bool xkbcomponents_specified; -+static char * xkbrules; -+static char * xkbmodel; -+static char * xkblayout; -+static char * xkbvariant; -+static char * xkboptions; -+#endif -+#endif -+ -+void -+KbdDeviceInit(DeviceIntPtr pDevice, KeySymsPtr pKeySyms, CARD8 *pModMap) -+{ -+ int i; -+ -+ kbdDevice = pDevice; -+ -+ for (i = 0; i < MAP_LENGTH; i++) -+ pModMap[i] = NoSymbol; -+ -+ pModMap[CONTROL_L_KEY_CODE] = ControlMask; -+ pModMap[CONTROL_R_KEY_CODE] = ControlMask; -+ pModMap[SHIFT_L_KEY_CODE] = ShiftMask; -+ pModMap[SHIFT_R_KEY_CODE] = ShiftMask; -+ pModMap[META_L_KEY_CODE] = Mod1Mask; -+ pModMap[META_R_KEY_CODE] = Mod1Mask; -+ pModMap[ALT_L_KEY_CODE] = Mod1Mask; -+ pModMap[ALT_R_KEY_CODE] = Mod1Mask; -+ -+ pKeySyms->minKeyCode = MIN_KEY_CODE; -+ pKeySyms->maxKeyCode = MAX_KEY_CODE; -+ pKeySyms->mapWidth = GLYPHS_PER_KEY; -+ -+ pKeySyms->map = (KeySym *)xalloc(sizeof(KeySym) -+ * MAP_LENGTH * GLYPHS_PER_KEY); -+ -+ if (!pKeySyms->map) { -+ ErrorF("xalloc failed\n"); -+ exit(1); -+ } -+ -+ for (i = 0; i < MAP_LENGTH * GLYPHS_PER_KEY; i++) -+ pKeySyms->map[i] = NoSymbol; -+ -+ for (i = 0; i < N_PREDEFINED_KEYS * GLYPHS_PER_KEY; i++) { -+ pKeySyms->map[i] = map[i]; -+ } -+} -+ -+ -+void -+KbdDeviceOn(void) -+{ -+} -+ -+ -+void -+KbdDeviceOff(void) -+{ -+} -+ -+ -+#if XFREE86VNC -+static int -+xf86rfbKeybControlProc(DeviceIntPtr device, int onoff) -+{ -+ KeySymsRec keySyms; -+ CARD8 modMap[MAP_LENGTH]; -+ DevicePtr pDev = (DevicePtr)device; -+ -+ switch (onoff) -+ { -+ case DEVICE_INIT: -+ KbdDeviceInit(device, &keySyms, modMap); -+#ifdef XKB -+ if (noXkbExtension) { -+#endif -+ InitKeyboardDeviceStruct(pDev, &keySyms, modMap, -+ (BellProcPtr)rfbSendBell, -+ (KbdCtrlProcPtr)NoopDDA); -+#ifdef XKB -+ } else { -+ XkbComponentNamesRec names; -+ if (XkbInitialMap) { -+ if ((xkbkeymap = strchr(XkbInitialMap, '/')) != NULL) -+ xkbkeymap++; -+ else -+ xkbkeymap = XkbInitialMap; -+ } -+ if (xkbkeymap) { -+ names.keymap = xkbkeymap; -+ names.keycodes = NULL; -+ names.types = NULL; -+ names.compat = NULL; -+ names.symbols = NULL; -+ names.geometry = NULL; -+ } else { -+ names.keymap = NULL; -+ names.keycodes = xkbkeycodes; -+ names.types = xkbtypes; -+ names.compat = xkbcompat; -+ names.symbols = xkbsymbols; -+ names.geometry = xkbgeometry; -+ } -+ if ((xkbkeymap || xkbcomponents_specified) -+ && (xkbmodel == NULL || xkblayout == NULL)) { -+ xkbrules = NULL; -+ } -+#if 0 -+ XkbSetRulesDflts(xkbrules, xkbmodel, -+ xkblayout, xkbvariant, -+ xkboptions); -+#endif -+ XkbInitKeyboardDeviceStruct(device, -+ &names, -+ &keySyms, -+ modMap, -+ (BellProcPtr)rfbSendBell, -+ (KbdCtrlProcPtr)NoopDDA); -+ } -+#endif /* XKB */ -+ 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 void -+xf86rfbKeybUninit(InputDriverPtr drv, -+ InputInfoPtr pInfo, -+ int flags) -+{ -+ xf86rfbKeybControlProc(pInfo->dev, DEVICE_OFF); -+} -+ -+static InputInfoPtr -+xf86rfbKeybInit(InputDriverPtr drv, -+ IDevPtr dev, -+ int flags) -+{ -+ InputInfoPtr pInfo; -+#ifdef XKB -+ char *s; -+ Bool from; -+#endif -+ if (!(pInfo = xf86AllocateInput(drv, 0))) -+ return NULL; -+ -+ /* Initialise the InputInfoRec. */ -+ pInfo->name = dev->identifier; -+ pInfo->type_name = "rfbKeyb"; -+ pInfo->flags = XI86_KEYBOARD_CAPABLE; -+ pInfo->device_control = xf86rfbKeybControlProc; -+ pInfo->read_input = NULL; -+ pInfo->motion_history_proc = NULL; -+ pInfo->history_size = 0; -+ pInfo->control_proc = NULL; -+ pInfo->close_proc = NULL; -+ pInfo->switch_mode = NULL; -+ pInfo->conversion_proc = NULL; -+ pInfo->reverse_conversion_proc = NULL; -+ pInfo->fd = -1; -+ pInfo->dev = NULL; -+ pInfo->private_flags = 0; -+ pInfo->always_core_feedback = 0; -+ pInfo->conf_idev = dev; -+ -+ /* Collect the options, and process the common options. */ -+ xf86CollectInputOptions(pInfo, DEFAULTS, NULL); -+ xf86ProcessCommonOptions(pInfo, pInfo->options); -+ -+ /* Mark the device configured */ -+ pInfo->flags |= XI86_CONFIGURED; -+ -+#ifdef XKB -+ from = X_DEFAULT; -+ if (noXkbExtension) -+ from = X_CMDLINE; -+ else if (xf86FindOption(dev->commonOptions, "XkbDisable")) { -+ noXkbExtension = -+ xf86SetBoolOption(dev->commonOptions, "XkbDisable", FALSE); -+ from = X_CONFIG; -+ } -+ if (noXkbExtension) -+ xf86Msg(from, "XKB: disabled\n"); -+ -+#define NULL_IF_EMPTY(s) (s[0] ? s : (xfree(s), (char *)NULL)) -+ -+ if (!noXkbExtension && !XkbInitialMap) { -+ if ((s = xf86SetStrOption(dev->commonOptions, "XkbKeymap", NULL))) { -+ xkbkeymap = NULL_IF_EMPTY(s); -+ xf86Msg(X_CONFIG, "XKB: keymap: \"%s\" " -+ "(overrides other XKB settings)\n", xkbkeymap); -+ } else { -+ if ((s = xf86SetStrOption(dev->commonOptions, "XkbCompat", NULL))) { -+ xkbcompat = NULL_IF_EMPTY(s); -+ xkbcomponents_specified = TRUE; -+ xf86Msg(X_CONFIG, "XKB: compat: \"%s\"\n", s); -+ } -+ -+ if ((s = xf86SetStrOption(dev->commonOptions, "XkbTypes", NULL))) { -+ xkbtypes = NULL_IF_EMPTY(s); -+ xkbcomponents_specified = TRUE; -+ xf86Msg(X_CONFIG, "XKB: types: \"%s\"\n", s); -+ } -+ -+ if ((s = xf86SetStrOption(dev->commonOptions, "XkbKeycodes", NULL))) { -+ xkbkeycodes = NULL_IF_EMPTY(s); -+ xkbcomponents_specified = TRUE; -+ xf86Msg(X_CONFIG, "XKB: keycodes: \"%s\"\n", s); -+ } -+ -+ if ((s = xf86SetStrOption(dev->commonOptions, "XkbGeometry", NULL))) { -+ xkbgeometry = NULL_IF_EMPTY(s); -+ xkbcomponents_specified = TRUE; -+ xf86Msg(X_CONFIG, "XKB: geometry: \"%s\"\n", s); -+ } -+ -+ if ((s = xf86SetStrOption(dev->commonOptions, "XkbSymbols", NULL))) { -+ xkbsymbols = NULL_IF_EMPTY(s); -+ xkbcomponents_specified = TRUE; -+ xf86Msg(X_CONFIG, "XKB: symbols: \"%s\"\n", s); -+ } -+ -+ if ((s = xf86SetStrOption(dev->commonOptions, "XkbRules", NULL))) { -+ xkbrules = NULL_IF_EMPTY(s); -+ xkbcomponents_specified = TRUE; -+ xf86Msg(X_CONFIG, "XKB: rules: \"%s\"\n", s); -+ } -+ -+ if ((s = xf86SetStrOption(dev->commonOptions, "XkbModel", NULL))) { -+ xkbmodel = NULL_IF_EMPTY(s); -+ xkbcomponents_specified = TRUE; -+ xf86Msg(X_CONFIG, "XKB: model: \"%s\"\n", s); -+ } -+ -+ if ((s = xf86SetStrOption(dev->commonOptions, "XkbLayout", NULL))) { -+ xkblayout = NULL_IF_EMPTY(s); -+ xkbcomponents_specified = TRUE; -+ xf86Msg(X_CONFIG, "XKB: layout: \"%s\"\n", s); -+ } -+ -+ if ((s = xf86SetStrOption(dev->commonOptions, "XkbVariant", NULL))) { -+ xkbvariant = NULL_IF_EMPTY(s); -+ xkbcomponents_specified = TRUE; -+ xf86Msg(X_CONFIG, "XKB: variant: \"%s\"\n", s); -+ } -+ -+ if ((s = xf86SetStrOption(dev->commonOptions, "XkbOptions", NULL))) { -+ xkboptions = NULL_IF_EMPTY(s); -+ xkbcomponents_specified = TRUE; -+ xf86Msg(X_CONFIG, "XKB: options: \"%s\"\n", s); -+ } -+ } -+ } -+#undef NULL_IF_EMPTY -+#endif /* XKB */ -+ -+ /* Return the configured device */ -+ return (pInfo); -+} -+ -+#ifdef XFree86LOADER -+static -+#endif -+InputDriverRec RFBKEYB = { -+ 1, /* driver version */ -+ "rfbkeyb", /* driver name */ -+ NULL, /* identify */ -+ xf86rfbKeybInit, /* pre-init */ -+ xf86rfbKeybUninit, /* un-init */ -+ NULL, /* module */ -+ 0 /* ref count */ -+}; -+ -+/* -+ *************************************************************************** -+ * -+ * Dynamic loading functions -+ * -+ *************************************************************************** -+ */ -+#ifdef XFree86LOADER -+static void -+xf86rfbKeybUnplug(pointer p) -+{ -+} -+ -+static pointer -+xf86rfbKeybPlug(pointer module, -+ pointer options, -+ int *errmaj, -+ int *errmin) -+{ -+ xf86AddInputDriver(&RFBKEYB, module, 0); -+ -+ return module; -+} -+ -+void -+vncInitKeyb(void) -+{ -+ xf86AddInputDriver(&RFBKEYB, NULL, 0); -+} -+ -+static XF86ModuleVersionInfo xf86rfbKeybVersionRec = -+{ -+ "rfbkeyb", -+ "xf4vnc Project, see http://xf4vnc.sf.net", -+ MODINFOSTRING1, -+ MODINFOSTRING2, -+ XF86_VERSION_CURRENT, -+ 1, 0, 0, -+ ABI_CLASS_XINPUT, -+ ABI_XINPUT_VERSION, -+ MOD_CLASS_XINPUT, -+ {0, 0, 0, 0} /* signature, to be patched into the file by */ -+ /* a tool */ -+}; -+ -+XF86ModuleData rfbkeybModuleData = {&xf86rfbKeybVersionRec, -+ xf86rfbKeybPlug, -+ xf86rfbKeybUnplug}; -+ -+#endif /* XFree86LOADER */ -+#endif /* XFREE86VNC */ -+ -diff --git a/hw/xfree86/vnc/rfbmouse.c b/hw/xfree86/vnc/rfbmouse.c -new file mode 100644 -index 0000000..342469b ---- /dev/null -+++ b/hw/xfree86/vnc/rfbmouse.c -@@ -0,0 +1,240 @@ -+/* -+ * Copyright (C) 2002 Alan Hourihane. 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. -+ * -+ * Author: Alan Hourihane -+ */ -+ -+#ifdef HAVE_XORG_CONFIG_H -+#include -+#endif -+ -+#ifndef XINPUT -+#define XINPUT -+#endif -+ -+#if XFREE86VNC -+ -+#include -+#include -+#include -+#include -+#include "xf86Xinput.h" -+ -+#ifdef XFree86LOADER -+#include -+#endif -+ -+static const char *DEFAULTS[] = { -+ NULL -+}; -+#else -+#include -+#include -+#include -+#endif -+ -+#include "rfb.h" -+ -+ -+unsigned char ptrAcceleration = 50; -+ -+void -+PtrDeviceOn(DeviceIntPtr pDev) -+{ -+#if 0 -+ ptrAcceleration = (unsigned char)pDev->ptrfeed->ctrl.num; -+#endif -+} -+ -+void -+PtrDeviceInit(void) -+{ -+} -+ -+void -+PtrDeviceOff(void) -+{ -+} -+ -+ -+void -+PtrDeviceControl(DeviceIntPtr dev, PtrCtrl *ctrl) -+{ -+#if 0 -+ ptrAcceleration = (char)ctrl->num; -+ -+ if (udpSockConnected) { -+ if (write(udpSock, &ptrAcceleration, 1) <= 0) { -+ ErrorF("PtrDeviceControl: UDP input: write"); -+ rfbDisconnectUDPSock(); -+ } -+ } -+#endif -+} -+ -+#if XFREE86VNC -+static int -+xf86rfbMouseControlProc(DeviceIntPtr device, int onoff) -+{ -+ BYTE map[6]; -+ DevicePtr pDev = (DevicePtr)device; -+ -+ 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(device); -+ break; -+ -+ case DEVICE_OFF: -+ pDev->on = FALSE; -+ PtrDeviceOff(); -+ break; -+ -+ case DEVICE_CLOSE: -+ if (pDev->on) -+ PtrDeviceOff(); -+ break; -+ } -+ return Success; -+} -+ -+static void -+xf86rfbMouseUninit(InputDriverPtr drv, -+ InputInfoPtr pInfo, -+ int flags) -+{ -+ xf86rfbMouseControlProc(pInfo->dev, DEVICE_OFF); -+} -+ -+static InputInfoPtr -+xf86rfbMouseInit(InputDriverPtr drv, -+ IDevPtr dev, -+ int flags) -+{ -+ InputInfoPtr pInfo; -+ -+ if (!(pInfo = xf86AllocateInput(drv, 0))) -+ return NULL; -+ -+ /* Initialise the InputInfoRec. */ -+ pInfo->name = dev->identifier; -+ pInfo->type_name = "rfbMouse"; -+ pInfo->flags = XI86_POINTER_CAPABLE | XI86_SEND_DRAG_EVENTS; -+ pInfo->device_control = xf86rfbMouseControlProc; -+ pInfo->read_input = NULL; -+ pInfo->motion_history_proc = xf86GetMotionEvents; -+ pInfo->history_size = 0; -+ pInfo->control_proc = NULL; -+ pInfo->close_proc = NULL; -+ pInfo->switch_mode = NULL; -+ pInfo->conversion_proc = NULL; -+ pInfo->reverse_conversion_proc = NULL; -+ pInfo->fd = -1; -+ pInfo->dev = NULL; -+ pInfo->private_flags = 0; -+ pInfo->always_core_feedback = 0; -+ pInfo->conf_idev = dev; -+ -+ /* Collect the options, and process the common options. */ -+ xf86CollectInputOptions(pInfo, DEFAULTS, NULL); -+ xf86ProcessCommonOptions(pInfo, pInfo->options); -+ -+ /* Mark the device configured */ -+ pInfo->flags |= XI86_CONFIGURED; -+ -+ /* Return the configured device */ -+ return (pInfo); -+} -+ -+#ifdef XFree86LOADER -+static -+#endif -+InputDriverRec RFBMOUSE = { -+ 1, /* driver version */ -+ "rfbmouse", /* driver name */ -+ NULL, /* identify */ -+ xf86rfbMouseInit, /* pre-init */ -+ xf86rfbMouseUninit, /* un-init */ -+ NULL, /* module */ -+ 0 /* ref count */ -+}; -+ -+/* -+ *************************************************************************** -+ * -+ * Dynamic loading functions -+ * -+ *************************************************************************** -+ */ -+#ifdef XFree86LOADER -+static void -+xf86rfbMouseUnplug(pointer p) -+{ -+} -+ -+static pointer -+xf86rfbMousePlug(pointer module, -+ pointer options, -+ int *errmaj, -+ int *errmin) -+{ -+ xf86AddInputDriver(&RFBMOUSE, module, 0); -+ -+ return module; -+} -+ -+void -+vncInitMouse(void) -+{ -+ xf86AddInputDriver(&RFBMOUSE, NULL, 0); -+} -+ -+static XF86ModuleVersionInfo xf86rfbMouseVersionRec = -+{ -+ "rfbmouse", -+ "xf4vnc Project, see http://xf4vnc.sf.net", -+ MODINFOSTRING1, -+ MODINFOSTRING2, -+ XF86_VERSION_CURRENT, -+ 1, 0, 0, -+ ABI_CLASS_XINPUT, -+ ABI_XINPUT_VERSION, -+ MOD_CLASS_XINPUT, -+ {0, 0, 0, 0} /* signature, to be patched into the file by */ -+ /* a tool */ -+}; -+ -+XF86ModuleData rfbmouseModuleData = {&xf86rfbMouseVersionRec, -+ xf86rfbMousePlug, -+ xf86rfbMouseUnplug}; -+ -+#endif /* XFree86LOADER */ -+#endif -diff --git a/hw/xfree86/vnc/rfbproto.h b/hw/xfree86/vnc/rfbproto.h -new file mode 100644 -index 0000000..bbef703 ---- /dev/null -+++ b/hw/xfree86/vnc/rfbproto.h -@@ -0,0 +1,1347 @@ -+/* -+ * Copyright (C) 2000-2004 Constantin Kaplinsky. All Rights Reserved. -+ * Copyright (C) 2000 Tridia Corporation. All Rights Reserved. -+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. -+ * -+ * This is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This software is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this software; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -+ * USA. -+ */ -+ -+/* -+ * rfbproto.h - header file for the RFB protocol, versions 3.3, 3.7 and 3.7t -+ * (protocol 3.7t is effectively 3.7 with TightVNC extensions enabled) -+ * -+ * Uses types CARD for an n-bit unsigned integer, INT for an n-bit signed -+ * integer (for n = 8, 16 and 32). -+ * -+ * All multiple byte integers are in big endian (network) order (most -+ * significant byte first). Unless noted otherwise there is no special -+ * alignment of protocol structures. -+ * -+ * -+ * Once the initial handshaking is done, all messages start with a type byte, -+ * (usually) followed by message-specific data. The order of definitions in -+ * this file is as follows: -+ * -+ * (1) Structures used in several types of message. -+ * (2) Structures used in the initial handshaking. -+ * (3) Message types. -+ * (4) Encoding types. -+ * (5) For each message type, the form of the data following the type byte. -+ * Sometimes this is defined by a single structure but the more complex -+ * messages have to be explained by comments. -+ */ -+ -+ -+/***************************************************************************** -+ * -+ * Structures used in several messages -+ * -+ *****************************************************************************/ -+ -+/*----------------------------------------------------------------------------- -+ * Structure used to specify a rectangle. This structure is a multiple of 4 -+ * bytes so that it can be interspersed with 32-bit pixel data without -+ * affecting alignment. -+ */ -+ -+typedef struct _rfbRectangle { -+ CARD16 x; -+ CARD16 y; -+ CARD16 w; -+ CARD16 h; -+} rfbRectangle; -+ -+#define sz_rfbRectangle 8 -+ -+ -+/*----------------------------------------------------------------------------- -+ * Structure used to specify pixel format. -+ */ -+ -+typedef struct _rfbPixelFormat { -+ -+ CARD8 bitsPerPixel; /* 8,16,32 only */ -+ -+ CARD8 depth; /* 8 to 32 */ -+ -+ CARD8 bigEndian; /* True if multi-byte pixels are interpreted -+ as big endian, or if single-bit-per-pixel -+ has most significant bit of the byte -+ corresponding to first (leftmost) pixel. Of -+ course this is meaningless for 8 bits/pix */ -+ -+ CARD8 trueColour; /* If false then we need a "colour map" to -+ convert pixels to RGB. If true, xxxMax and -+ xxxShift specify bits used for red, green -+ and blue */ -+ -+ /* the following fields are only meaningful if trueColour is true */ -+ -+ CARD16 redMax; /* maximum red value (= 2^n - 1 where n is the -+ number of bits used for red). Note this -+ value is always in big endian order. */ -+ -+ CARD16 greenMax; /* similar for green */ -+ -+ CARD16 blueMax; /* and blue */ -+ -+ CARD8 redShift; /* number of shifts needed to get the red -+ value in a pixel to the least significant -+ bit. To find the red value from a given -+ pixel, do the following: -+ 1) Swap pixel value according to bigEndian -+ (e.g. if bigEndian is false and host byte -+ order is big endian, then swap). -+ 2) Shift right by redShift. -+ 3) AND with redMax (in host byte order). -+ 4) You now have the red value between 0 and -+ redMax. */ -+ -+ CARD8 greenShift; /* similar for green */ -+ -+ CARD8 blueShift; /* and blue */ -+ -+ CARD8 pad1; -+ CARD16 pad2; -+ -+} rfbPixelFormat; -+ -+#define sz_rfbPixelFormat 16 -+ -+ -+/*----------------------------------------------------------------------------- -+ * Structure used to describe protocol options such as tunneling methods, -+ * authentication schemes and message types (protocol version 3.7t). -+ */ -+ -+typedef struct _rfbCapabilityInfo { -+ -+ CARD32 code; /* numeric identifier */ -+ CARD8 vendorSignature[4]; /* vendor identification */ -+ CARD8 nameSignature[8]; /* abbreviated option name */ -+ -+} rfbCapabilityInfo; -+ -+#define sz_rfbCapabilityInfoVendor 4 -+#define sz_rfbCapabilityInfoName 8 -+#define sz_rfbCapabilityInfo 16 -+ -+/* -+ * Vendors known by TightVNC: standard VNC/RealVNC, TridiaVNC, and TightVNC. -+ */ -+ -+#define rfbStandardVendor "STDV" -+#define rfbTridiaVncVendor "TRDV" -+#define rfbTightVncVendor "TGHT" -+#define rfbTungstenGraphicsVendor "TGIV" -+ -+ -+/***************************************************************************** -+ * -+ * Initial handshaking messages -+ * -+ *****************************************************************************/ -+ -+/*----------------------------------------------------------------------------- -+ * Protocol Version -+ * -+ * The server always sends 12 bytes to start which identifies the latest RFB -+ * protocol version number which it supports. These bytes are interpreted -+ * as a string of 12 ASCII characters in the format "RFB xxx.yyy\n" where -+ * xxx and yyy are the major and minor version numbers (for version 3.7 -+ * this is "RFB 003.007\n"). -+ * -+ * The client then replies with a similar 12-byte message giving the version -+ * number of the protocol which should actually be used (which may be different -+ * to that quoted by the server). -+ * -+ * It is intended that both clients and servers may provide some level of -+ * backwards compatibility by this mechanism. Servers in particular should -+ * attempt to provide backwards compatibility, and even forwards compatibility -+ * to some extent. For example if a client demands version 3.1 of the -+ * protocol, a 3.0 server can probably assume that by ignoring requests for -+ * encoding types it doesn't understand, everything will still work OK. This -+ * will probably not be the case for changes in the major version number. -+ * -+ * The format string below can be used in sprintf or sscanf to generate or -+ * decode the version string respectively. -+ */ -+ -+#define rfbProtocolVersionFormat "RFB %03d.%03d\n" -+#define rfbProtocolMajorVersion 3 -+#define rfbProtocolMinorVersion 7 -+#define rfbProtocolFallbackMinorVersion 3 -+ -+typedef char rfbProtocolVersionMsg[13]; /* allow extra byte for null */ -+ -+#define sz_rfbProtocolVersionMsg 12 -+ -+ -+/* -+ * Negotiation of the security type (protocol version 3.7) -+ * -+ * Once the protocol version has been decided, the server either sends a list -+ * of supported security types, or informs the client about an error (when the -+ * number of security types is 0). Security type rfbSecTypeTight is used to -+ * enable TightVNC-specific protocol extensions. The value rfbSecTypeVncAuth -+ * stands for classic VNC authentication. -+ * -+ * The client selects a particular security type from the list provided by the -+ * server. -+ */ -+ -+#define rfbSecTypeInvalid 0 -+#define rfbSecTypeNone 1 -+#define rfbSecTypeVncAuth 2 -+#define rfbSecTypeTight 16 -+ -+ -+/*----------------------------------------------------------------------------- -+ * Negotiation of Tunneling Capabilities (protocol version 3.7t) -+ * -+ * If the chosen security type is rfbSecTypeTight, the server sends a list of -+ * supported tunneling methods ("tunneling" refers to any additional layer of -+ * data transformation, such as encryption or external compression.) -+ * -+ * nTunnelTypes specifies the number of following rfbCapabilityInfo structures -+ * that list all supported tunneling methods in the order of preference. -+ * -+ * NOTE: If nTunnelTypes is 0, that tells the client that no tunneling can be -+ * used, and the client should not send a response requesting a tunneling -+ * method. -+ */ -+ -+typedef struct _rfbTunnelingCapsMsg { -+ CARD32 nTunnelTypes; -+ /* followed by nTunnelTypes * rfbCapabilityInfo structures */ -+} rfbTunnelingCapsMsg; -+ -+#define sz_rfbTunnelingCapsMsg 4 -+ -+/*----------------------------------------------------------------------------- -+ * Tunneling Method Request (protocol version 3.7t) -+ * -+ * If the list of tunneling capabilities sent by the server was not empty, the -+ * client should reply with a 32-bit code specifying a particular tunneling -+ * method. The following code should be used for no tunneling. -+ */ -+ -+#define rfbNoTunneling 0 -+#define sig_rfbNoTunneling "NOTUNNEL" -+ -+ -+/*----------------------------------------------------------------------------- -+ * Negotiation of Authentication Capabilities (protocol version 3.7t) -+ * -+ * After setting up tunneling, the server sends a list of supported -+ * authentication schemes. -+ * -+ * nAuthTypes specifies the number of following rfbCapabilityInfo structures -+ * that list all supported authentication schemes in the order of preference. -+ * -+ * NOTE: If nAuthTypes is 0, that tells the client that no authentication is -+ * necessary, and the client should not send a response requesting an -+ * authentication scheme. -+ */ -+ -+typedef struct _rfbAuthenticationCapsMsg { -+ CARD32 nAuthTypes; -+ /* followed by nAuthTypes * rfbCapabilityInfo structures */ -+} rfbAuthenticationCapsMsg; -+ -+#define sz_rfbAuthenticationCapsMsg 4 -+ -+/*----------------------------------------------------------------------------- -+ * Authentication Scheme Request (protocol version 3.7t) -+ * -+ * If the list of authentication capabilities sent by the server was not empty, -+ * the client should reply with a 32-bit code specifying a particular -+ * authentication scheme. The following codes are supported. -+ */ -+ -+#define rfbAuthNone 1 -+#define rfbAuthVNC 2 -+#define rfbAuthUnixLogin 129 -+#define rfbAuthExternal 130 -+ -+#define sig_rfbAuthNone "NOAUTH__" -+#define sig_rfbAuthVNC "VNCAUTH_" -+#define sig_rfbAuthUnixLogin "ULGNAUTH" -+#define sig_rfbAuthExternal "XTRNAUTH" -+ -+ -+/*----------------------------------------------------------------------------- -+ * Standard VNC Authentication (all protocol versions) -+ * -+ * Standard authentication result codes are defined below. -+ */ -+ -+#define rfbVncAuthOK 0 -+#define rfbVncAuthFailed 1 -+#define rfbVncAuthTooMany 2 -+ -+ -+/*----------------------------------------------------------------------------- -+ * Client Initialisation Message -+ * -+ * Once the client and server are sure that they're happy to talk to one -+ * another, the client sends an initialisation message. At present this -+ * message only consists of a boolean indicating whether the server should try -+ * to share the desktop by leaving other clients connected, or give exclusive -+ * access to this client by disconnecting all other clients. -+ */ -+ -+typedef struct _rfbClientInitMsg { -+ CARD8 shared; -+} rfbClientInitMsg; -+ -+#define sz_rfbClientInitMsg 1 -+ -+ -+/*----------------------------------------------------------------------------- -+ * Server Initialisation Message -+ * -+ * After the client initialisation message, the server sends one of its own. -+ * This tells the client the width and height of the server's framebuffer, -+ * its pixel format and the name associated with the desktop. -+ */ -+ -+typedef struct _rfbServerInitMsg { -+ CARD16 framebufferWidth; -+ CARD16 framebufferHeight; -+ rfbPixelFormat format; /* the server's preferred pixel format */ -+ CARD32 nameLength; -+ /* followed by char name[nameLength] */ -+} rfbServerInitMsg; -+ -+#define sz_rfbServerInitMsg (8 + sz_rfbPixelFormat) -+ -+ -+/*----------------------------------------------------------------------------- -+ * Server Interaction Capabilities Message (protocol version 3.7t) -+ * -+ * In the protocol version 3.7t, the server informs the client what message -+ * types it supports in addition to ones defined in the protocol version 3.7. -+ * Also, the server sends the list of all supported encodings (note that it's -+ * not necessary to advertise the "raw" encoding sinse it MUST be supported in -+ * RFB 3.x protocols). -+ * -+ * This data immediately follows the server initialisation message. -+ */ -+ -+typedef struct _rfbInteractionCapsMsg { -+ CARD16 nServerMessageTypes; -+ CARD16 nClientMessageTypes; -+ CARD16 nEncodingTypes; -+ CARD16 pad; /* reserved, must be 0 */ -+ /* followed by nServerMessageTypes * rfbCapabilityInfo structures */ -+ /* followed by nClientMessageTypes * rfbCapabilityInfo structures */ -+} rfbInteractionCapsMsg; -+ -+#define sz_rfbInteractionCapsMsg 8 -+ -+ -+/* -+ * Following the server initialisation message it's up to the client to send -+ * whichever protocol messages it wants. Typically it will send a -+ * SetPixelFormat message and a SetEncodings message, followed by a -+ * FramebufferUpdateRequest. From then on the server will send -+ * FramebufferUpdate messages in response to the client's -+ * FramebufferUpdateRequest messages. The client should send -+ * FramebufferUpdateRequest messages with incremental set to true when it has -+ * finished processing one FramebufferUpdate and is ready to process another. -+ * With a fast client, the rate at which FramebufferUpdateRequests are sent -+ * should be regulated to avoid hogging the network. -+ */ -+ -+ -+ -+/***************************************************************************** -+ * -+ * Message types -+ * -+ *****************************************************************************/ -+ -+/* server -> client */ -+ -+#define rfbFramebufferUpdate 0 -+#define rfbSetColourMapEntries 1 -+#define rfbBell 2 -+#define rfbServerCutText 3 -+/* Chromium extensions, use higher values */ -+#define rfbChromiumStart 50 -+#define rfbChromiumMoveResizeWindow 51 -+#define rfbChromiumClipList 52 -+#define rfbChromiumWindowShow 53 -+ -+#define rfbFileListData 130 -+#define rfbFileDownloadData 131 -+#define rfbFileUploadCancel 132 -+#define rfbFileDownloadFailed 133 -+ -+/* signatures for non-standard messages */ -+#define sig_rfbFileListData "FTS_LSDT" -+#define sig_rfbFileDownloadData "FTS_DNDT" -+#define sig_rfbFileUploadCancel "FTS_UPCN" -+#define sig_rfbFileDownloadFailed "FTS_DNFL" -+ -+ -+/* client -> server */ -+ -+#define rfbSetPixelFormat 0 -+#define rfbFixColourMapEntries 1 /* not currently supported */ -+#define rfbSetEncodings 2 -+#define rfbFramebufferUpdateRequest 3 -+#define rfbKeyEvent 4 -+#define rfbPointerEvent 5 -+#define rfbClientCutText 6 -+/* Chromium extensions, use higher values */ -+#define rfbChromiumStop 50 -+#define rfbChromiumExpose 51 -+ -+#define rfbFileListRequest 130 -+#define rfbFileDownloadRequest 131 -+#define rfbFileUploadRequest 132 -+#define rfbFileUploadData 133 -+#define rfbFileDownloadCancel 134 -+#define rfbFileUploadFailed 135 -+#define rfbFileCreateDirRequest 136 -+ -+/* signatures for non-standard messages */ -+#define sig_rfbFileListRequest "FTC_LSRQ" -+#define sig_rfbFileDownloadRequest "FTC_DNRQ" -+#define sig_rfbFileUploadRequest "FTC_UPRQ" -+#define sig_rfbFileUploadData "FTC_UPDT" -+#define sig_rfbFileDownloadCancel "FTC_DNCN" -+#define sig_rfbFileUploadFailed "FTC_UPFL" -+#define sig_rfbFileCreateDirRequest "FTC_FCDR" -+ -+/***************************************************************************** -+ * -+ * Encoding types -+ * -+ *****************************************************************************/ -+ -+#define rfbEncodingRaw 0 -+#define rfbEncodingCopyRect 1 -+#define rfbEncodingRRE 2 -+#define rfbEncodingCoRRE 4 -+#define rfbEncodingHextile 5 -+#define rfbEncodingZlib 6 -+#define rfbEncodingTight 7 -+#define rfbEncodingZlibHex 8 -+ -+/* signatures for basic encoding types */ -+#define sig_rfbEncodingRaw "RAW_____" -+#define sig_rfbEncodingCopyRect "COPYRECT" -+#define sig_rfbEncodingRRE "RRE_____" -+#define sig_rfbEncodingCoRRE "CORRE___" -+#define sig_rfbEncodingHextile "HEXTILE_" -+#define sig_rfbEncodingZlib "ZLIB____" -+#define sig_rfbEncodingTight "TIGHT___" -+#define sig_rfbEncodingZlibHex "ZLIBHEX_" -+#define sig_rfbEncodingChromium "CHROMIUM" -+ -+/* -+ * Special encoding numbers: -+ * 0xFFFFFF00 .. 0xFFFFFF0F -- encoding-specific compression levels; -+ * 0xFFFFFF10 .. 0xFFFFFF1F -- mouse cursor shape data; -+ * 0xFFFFFF20 .. 0xFFFFFF2F -- various protocol extensions; -+ * 0xFFFFFF30 .. 0xFFFFFFDF -- not allocated yet; -+ * 0xFFFFFFE0 .. 0xFFFFFFEF -- quality level for JPEG compressor; -+ * 0xFFFFFFF0 .. 0xFFFFFFFF -- not allocated yet. -+ */ -+ -+#define rfbEncodingCompressLevel0 0xFFFFFF00 -+#define rfbEncodingCompressLevel1 0xFFFFFF01 -+#define rfbEncodingCompressLevel2 0xFFFFFF02 -+#define rfbEncodingCompressLevel3 0xFFFFFF03 -+#define rfbEncodingCompressLevel4 0xFFFFFF04 -+#define rfbEncodingCompressLevel5 0xFFFFFF05 -+#define rfbEncodingCompressLevel6 0xFFFFFF06 -+#define rfbEncodingCompressLevel7 0xFFFFFF07 -+#define rfbEncodingCompressLevel8 0xFFFFFF08 -+#define rfbEncodingCompressLevel9 0xFFFFFF09 -+ -+#define rfbEncodingXCursor 0xFFFFFF10 -+#define rfbEncodingRichCursor 0xFFFFFF11 -+#define rfbEncodingPointerPos 0xFFFFFF18 -+ -+#define rfbEncodingLastRect 0xFFFFFF20 -+#define rfbEncodingNewFBSize 0xFFFFFF21 -+#define rfbEncodingChromium 0xFFFFFF2F -+#define rfbEncodingChromium2 0xFFFFFF30 -+ -+#define rfbEncodingQualityLevel0 0xFFFFFFE0 -+#define rfbEncodingQualityLevel1 0xFFFFFFE1 -+#define rfbEncodingQualityLevel2 0xFFFFFFE2 -+#define rfbEncodingQualityLevel3 0xFFFFFFE3 -+#define rfbEncodingQualityLevel4 0xFFFFFFE4 -+#define rfbEncodingQualityLevel5 0xFFFFFFE5 -+#define rfbEncodingQualityLevel6 0xFFFFFFE6 -+#define rfbEncodingQualityLevel7 0xFFFFFFE7 -+#define rfbEncodingQualityLevel8 0xFFFFFFE8 -+#define rfbEncodingQualityLevel9 0xFFFFFFE9 -+ -+/* signatures for "fake" encoding types */ -+#define sig_rfbEncodingCompressLevel0 "COMPRLVL" -+#define sig_rfbEncodingXCursor "X11CURSR" -+#define sig_rfbEncodingRichCursor "RCHCURSR" -+#define sig_rfbEncodingPointerPos "POINTPOS" -+#define sig_rfbEncodingLastRect "LASTRECT" -+#define sig_rfbEncodingNewFBSize "NEWFBSIZ" -+#define sig_rfbEncodingQualityLevel0 "JPEGQLVL" -+ -+ -+/***************************************************************************** -+ * -+ * Server -> client message definitions -+ * -+ *****************************************************************************/ -+ -+ -+/*----------------------------------------------------------------------------- -+ * FramebufferUpdate - a block of rectangles to be copied to the framebuffer. -+ * -+ * This message consists of a header giving the number of rectangles of pixel -+ * data followed by the rectangles themselves. The header is padded so that -+ * together with the type byte it is an exact multiple of 4 bytes (to help -+ * with alignment of 32-bit pixels): -+ */ -+ -+typedef struct _rfbFramebufferUpdateMsg { -+ CARD8 type; /* always rfbFramebufferUpdate */ -+ CARD8 pad; -+ CARD16 nRects; -+ /* followed by nRects rectangles */ -+} rfbFramebufferUpdateMsg; -+ -+#define sz_rfbFramebufferUpdateMsg 4 -+ -+/* -+ * Each rectangle of pixel data consists of a header describing the position -+ * and size of the rectangle and a type word describing the encoding of the -+ * pixel data, followed finally by the pixel data. Note that if the client has -+ * not sent a SetEncodings message then it will only receive raw pixel data. -+ * Also note again that this structure is a multiple of 4 bytes. -+ */ -+ -+typedef struct _rfbFramebufferUpdateRectHeader { -+ rfbRectangle r; -+ CARD32 encoding; /* one of the encoding types rfbEncoding... */ -+} rfbFramebufferUpdateRectHeader; -+ -+#define sz_rfbFramebufferUpdateRectHeader (sz_rfbRectangle + 4) -+ -+ -+/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+ * Raw Encoding. Pixels are sent in top-to-bottom scanline order, -+ * left-to-right within a scanline with no padding in between. -+ */ -+ -+ -+/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+ * CopyRect Encoding. The pixels are specified simply by the x and y position -+ * of the source rectangle. -+ */ -+ -+typedef struct _rfbCopyRect { -+ CARD16 srcX; -+ CARD16 srcY; -+} rfbCopyRect; -+ -+#define sz_rfbCopyRect 4 -+ -+ -+/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+ * RRE - Rise-and-Run-length Encoding. We have an rfbRREHeader structure -+ * giving the number of subrectangles following. Finally the data follows in -+ * the form [...] where each is -+ * []. -+ */ -+ -+typedef struct _rfbRREHeader { -+ CARD32 nSubrects; -+} rfbRREHeader; -+ -+#define sz_rfbRREHeader 4 -+ -+ -+/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+ * CoRRE - Compact RRE Encoding. We have an rfbRREHeader structure giving -+ * the number of subrectangles following. Finally the data follows in the form -+ * [...] where each is -+ * []. This means that -+ * the whole rectangle must be at most 255x255 pixels. -+ */ -+ -+typedef struct _rfbCoRRERectangle { -+ CARD8 x; -+ CARD8 y; -+ CARD8 w; -+ CARD8 h; -+} rfbCoRRERectangle; -+ -+#define sz_rfbCoRRERectangle 4 -+ -+ -+/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+ * Hextile Encoding. The rectangle is divided up into "tiles" of 16x16 pixels, -+ * starting at the top left going in left-to-right, top-to-bottom order. If -+ * the width of the rectangle is not an exact multiple of 16 then the width of -+ * the last tile in each row will be correspondingly smaller. Similarly if the -+ * height is not an exact multiple of 16 then the height of each tile in the -+ * final row will also be smaller. Each tile begins with a "subencoding" type -+ * byte, which is a mask made up of a number of bits. If the Raw bit is set -+ * then the other bits are irrelevant; w*h pixel values follow (where w and h -+ * are the width and height of the tile). Otherwise the tile is encoded in a -+ * similar way to RRE, except that the position and size of each subrectangle -+ * can be specified in just two bytes. The other bits in the mask are as -+ * follows: -+ * -+ * BackgroundSpecified - if set, a pixel value follows which specifies -+ * the background colour for this tile. The first non-raw tile in a -+ * rectangle must have this bit set. If this bit isn't set then the -+ * background is the same as the last tile. -+ * -+ * ForegroundSpecified - if set, a pixel value follows which specifies -+ * the foreground colour to be used for all subrectangles in this tile. -+ * If this bit is set then the SubrectsColoured bit must be zero. -+ * -+ * AnySubrects - if set, a single byte follows giving the number of -+ * subrectangles following. If not set, there are no subrectangles (i.e. -+ * the whole tile is just solid background colour). -+ * -+ * SubrectsColoured - if set then each subrectangle is preceded by a pixel -+ * value giving the colour of that subrectangle. If not set, all -+ * subrectangles are the same colour, the foreground colour; if the -+ * ForegroundSpecified bit wasn't set then the foreground is the same as -+ * the last tile. -+ * -+ * The position and size of each subrectangle is specified in two bytes. The -+ * Pack macros below can be used to generate the two bytes from x, y, w, h, -+ * and the Extract macros can be used to extract the x, y, w, h values from -+ * the two bytes. -+ */ -+ -+#define rfbHextileRaw (1 << 0) -+#define rfbHextileBackgroundSpecified (1 << 1) -+#define rfbHextileForegroundSpecified (1 << 2) -+#define rfbHextileAnySubrects (1 << 3) -+#define rfbHextileSubrectsColoured (1 << 4) -+ -+#define rfbHextilePackXY(x,y) (((x) << 4) | (y)) -+#define rfbHextilePackWH(w,h) ((((w)-1) << 4) | ((h)-1)) -+#define rfbHextileExtractX(byte) ((byte) >> 4) -+#define rfbHextileExtractY(byte) ((byte) & 0xf) -+#define rfbHextileExtractW(byte) (((byte) >> 4) + 1) -+#define rfbHextileExtractH(byte) (((byte) & 0xf) + 1) -+ -+/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+ * ZLIB - zlib compression Encoding. We have an rfbZlibHeader structure -+ * giving the number of bytes to follow. Finally the data follows in -+ * zlib compressed format. -+ */ -+ -+typedef struct _rfbZlibHeader { -+ CARD32 nBytes; -+} rfbZlibHeader; -+ -+#define sz_rfbZlibHeader 4 -+ -+ -+/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+ * Tight Encoding. -+ * -+ *-- The first byte of each Tight-encoded rectangle is a "compression control -+ * byte". Its format is as follows (bit 0 is the least significant one): -+ * -+ * bit 0: if 1, then compression stream 0 should be reset; -+ * bit 1: if 1, then compression stream 1 should be reset; -+ * bit 2: if 1, then compression stream 2 should be reset; -+ * bit 3: if 1, then compression stream 3 should be reset; -+ * bits 7-4: if 1000 (0x08), then the compression type is "fill", -+ * if 1001 (0x09), then the compression type is "jpeg", -+ * if 0xxx, then the compression type is "basic", -+ * values greater than 1001 are not valid. -+ * -+ * If the compression type is "basic", then bits 6..4 of the -+ * compression control byte (those xxx in 0xxx) specify the following: -+ * -+ * bits 5-4: decimal representation is the index of a particular zlib -+ * stream which should be used for decompressing the data; -+ * bit 6: if 1, then a "filter id" byte is following this byte. -+ * -+ *-- The data that follows after the compression control byte described -+ * above depends on the compression type ("fill", "jpeg" or "basic"). -+ * -+ *-- If the compression type is "fill", then the only pixel value follows, in -+ * client pixel format (see NOTE 1). This value applies to all pixels of the -+ * rectangle. -+ * -+ *-- If the compression type is "jpeg", the following data stream looks like -+ * this: -+ * -+ * 1..3 bytes: data size (N) in compact representation; -+ * N bytes: JPEG image. -+ * -+ * Data size is compactly represented in one, two or three bytes, according -+ * to the following scheme: -+ * -+ * 0xxxxxxx (for values 0..127) -+ * 1xxxxxxx 0yyyyyyy (for values 128..16383) -+ * 1xxxxxxx 1yyyyyyy zzzzzzzz (for values 16384..4194303) -+ * -+ * Here each character denotes one bit, xxxxxxx are the least significant 7 -+ * bits of the value (bits 0-6), yyyyyyy are bits 7-13, and zzzzzzzz are the -+ * most significant 8 bits (bits 14-21). For example, decimal value 10000 -+ * should be represented as two bytes: binary 10010000 01001110, or -+ * hexadecimal 90 4E. -+ * -+ *-- If the compression type is "basic" and bit 6 of the compression control -+ * byte was set to 1, then the next (second) byte specifies "filter id" which -+ * tells the decoder what filter type was used by the encoder to pre-process -+ * pixel data before the compression. The "filter id" byte can be one of the -+ * following: -+ * -+ * 0: no filter ("copy" filter); -+ * 1: "palette" filter; -+ * 2: "gradient" filter. -+ * -+ *-- If bit 6 of the compression control byte is set to 0 (no "filter id" -+ * byte), or if the filter id is 0, then raw pixel values in the client -+ * format (see NOTE 1) will be compressed. See below details on the -+ * compression. -+ * -+ *-- The "gradient" filter pre-processes pixel data with a simple algorithm -+ * which converts each color component to a difference between a "predicted" -+ * intensity and the actual intensity. Such a technique does not affect -+ * uncompressed data size, but helps to compress photo-like images better. -+ * Pseudo-code for converting intensities to differences is the following: -+ * -+ * P[i,j] := V[i-1,j] + V[i,j-1] - V[i-1,j-1]; -+ * if (P[i,j] < 0) then P[i,j] := 0; -+ * if (P[i,j] > MAX) then P[i,j] := MAX; -+ * D[i,j] := V[i,j] - P[i,j]; -+ * -+ * Here V[i,j] is the intensity of a color component for a pixel at -+ * coordinates (i,j). MAX is the maximum value of intensity for a color -+ * component. -+ * -+ *-- The "palette" filter converts true-color pixel data to indexed colors -+ * and a palette which can consist of 2..256 colors. If the number of colors -+ * is 2, then each pixel is encoded in 1 bit, otherwise 8 bits is used to -+ * encode one pixel. 1-bit encoding is performed such way that the most -+ * significant bits correspond to the leftmost pixels, and each raw of pixels -+ * is aligned to the byte boundary. When "palette" filter is used, the -+ * palette is sent before the pixel data. The palette begins with an unsigned -+ * byte which value is the number of colors in the palette minus 1 (i.e. 1 -+ * means 2 colors, 255 means 256 colors in the palette). Then follows the -+ * palette itself which consist of pixel values in client pixel format (see -+ * NOTE 1). -+ * -+ *-- The pixel data is compressed using the zlib library. But if the data -+ * size after applying the filter but before the compression is less then 12, -+ * then the data is sent as is, uncompressed. Four separate zlib streams -+ * (0..3) can be used and the decoder should read the actual stream id from -+ * the compression control byte (see NOTE 2). -+ * -+ * If the compression is not used, then the pixel data is sent as is, -+ * otherwise the data stream looks like this: -+ * -+ * 1..3 bytes: data size (N) in compact representation; -+ * N bytes: zlib-compressed data. -+ * -+ * Data size is compactly represented in one, two or three bytes, just like -+ * in the "jpeg" compression method (see above). -+ * -+ *-- NOTE 1. If the color depth is 24, and all three color components are -+ * 8-bit wide, then one pixel in Tight encoding is always represented by -+ * three bytes, where the first byte is red component, the second byte is -+ * green component, and the third byte is blue component of the pixel color -+ * value. This applies to colors in palettes as well. -+ * -+ *-- NOTE 2. The decoder must reset compression streams' states before -+ * decoding the rectangle, if some of bits 0,1,2,3 in the compression control -+ * byte are set to 1. Note that the decoder must reset zlib streams even if -+ * the compression type is "fill" or "jpeg". -+ * -+ *-- NOTE 3. The "gradient" filter and "jpeg" compression may be used only -+ * when bits-per-pixel value is either 16 or 32, not 8. -+ * -+ *-- NOTE 4. The width of any Tight-encoded rectangle cannot exceed 2048 -+ * pixels. If a rectangle is wider, it must be split into several rectangles -+ * and each one should be encoded separately. -+ * -+ */ -+ -+#define rfbTightExplicitFilter 0x04 -+#define rfbTightFill 0x08 -+#define rfbTightJpeg 0x09 -+#define rfbTightMaxSubencoding 0x09 -+ -+/* Filters to improve compression efficiency */ -+#define rfbTightFilterCopy 0x00 -+#define rfbTightFilterPalette 0x01 -+#define rfbTightFilterGradient 0x02 -+ -+ -+/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+ * ZLIBHEX - zlib compressed Hextile Encoding. Essentially, this is the -+ * hextile encoding with zlib compression on the tiles that can not be -+ * efficiently encoded with one of the other hextile subencodings. The -+ * new zlib subencoding uses two bytes to specify the length of the -+ * compressed tile and then the compressed data follows. As with the -+ * raw sub-encoding, the zlib subencoding invalidates the other -+ * values, if they are also set. -+ */ -+ -+#define rfbHextileZlibRaw (1 << 5) -+#define rfbHextileZlibHex (1 << 6) -+ -+ -+/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+ * XCursor encoding. This is a special encoding used to transmit X-style -+ * cursor shapes from server to clients. Note that for this encoding, -+ * coordinates in rfbFramebufferUpdateRectHeader structure hold hotspot -+ * position (r.x, r.y) and cursor size (r.w, r.h). If (w * h != 0), two RGB -+ * samples are sent after header in the rfbXCursorColors structure. They -+ * denote foreground and background colors of the cursor. If a client -+ * supports only black-and-white cursors, it should ignore these colors and -+ * assume that foreground is black and background is white. Next, two bitmaps -+ * (1 bits per pixel) follow: first one with actual data (value 0 denotes -+ * background color, value 1 denotes foreground color), second one with -+ * transparency data (bits with zero value mean that these pixels are -+ * transparent). Both bitmaps represent cursor data in a byte stream, from -+ * left to right, from top to bottom, and each row is byte-aligned. Most -+ * significant bits correspond to leftmost pixels. The number of bytes in -+ * each row can be calculated as ((w + 7) / 8). If (w * h == 0), cursor -+ * should be hidden (or default local cursor should be set by the client). -+ */ -+ -+typedef struct _rfbXCursorColors { -+ CARD8 foreRed; -+ CARD8 foreGreen; -+ CARD8 foreBlue; -+ CARD8 backRed; -+ CARD8 backGreen; -+ CARD8 backBlue; -+} rfbXCursorColors; -+ -+#define sz_rfbXCursorColors 6 -+ -+ -+/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+ * RichCursor encoding. This is a special encoding used to transmit cursor -+ * shapes from server to clients. It is similar to the XCursor encoding but -+ * uses client pixel format instead of two RGB colors to represent cursor -+ * image. For this encoding, coordinates in rfbFramebufferUpdateRectHeader -+ * structure hold hotspot position (r.x, r.y) and cursor size (r.w, r.h). -+ * After header, two pixmaps follow: first one with cursor image in current -+ * client pixel format (like in raw encoding), second with transparency data -+ * (1 bit per pixel, exactly the same format as used for transparency bitmap -+ * in the XCursor encoding). If (w * h == 0), cursor should be hidden (or -+ * default local cursor should be set by the client). -+ */ -+ -+ -+/*----------------------------------------------------------------------------- -+ * SetColourMapEntries - these messages are only sent if the pixel -+ * format uses a "colour map" (i.e. trueColour false) and the client has not -+ * fixed the entire colour map using FixColourMapEntries. In addition they -+ * will only start being sent after the client has sent its first -+ * FramebufferUpdateRequest. So if the client always tells the server to use -+ * trueColour then it never needs to process this type of message. -+ */ -+ -+typedef struct _rfbSetColourMapEntriesMsg { -+ CARD8 type; /* always rfbSetColourMapEntries */ -+ CARD8 redIndex; /* used to be pad, but used for DirectColor */ -+ CARD16 firstColour; -+ CARD16 nColours; -+ -+ /* Followed by nColours * 3 * CARD16 -+ r1, g1, b1, r2, g2, b2, r3, g3, b3, ..., rn, bn, gn */ -+ -+} rfbSetColourMapEntriesMsg; -+ -+#define sz_rfbSetColourMapEntriesMsg 6 -+ -+ -+ -+/*----------------------------------------------------------------------------- -+ * Bell - ring a bell on the client if it has one. -+ */ -+ -+typedef struct _rfbBellMsg { -+ CARD8 type; /* always rfbBell */ -+} rfbBellMsg; -+ -+#define sz_rfbBellMsg 1 -+ -+ -+ -+/*----------------------------------------------------------------------------- -+ * ServerCutText - the server has new text in its cut buffer. -+ */ -+ -+typedef struct _rfbServerCutTextMsg { -+ CARD8 type; /* always rfbServerCutText */ -+ CARD8 pad1; -+ CARD16 pad2; -+ CARD32 length; -+ /* followed by char text[length] */ -+} rfbServerCutTextMsg; -+ -+#define sz_rfbServerCutTextMsg 8 -+ -+/*----------------------------------------------------------------------------- -+ * ChromiumStart - a port number for the crserver -+ */ -+ -+typedef struct { -+ CARD8 type; /* always rfbChromiumStart */ -+ CARD8 pad1; -+ CARD16 pad2; -+ CARD32 crServerPort; -+ CARD32 mothershipPort; -+} rfbChromiumStartMsg; -+ -+#define sz_rfbChromiumStartMsg 12 -+ -+ -+/*----------------------------------------------------------------------------- -+ * ChromiumMoveResizeWindow - move a chromium window -+ */ -+ -+typedef struct { -+ CARD8 type; /* always rfbChromiumMoveResizeWindow */ -+ CARD8 pad1; -+ CARD16 pad2; -+ CARD32 winid; -+ CARD32 x; -+ CARD32 y; -+ CARD32 w; -+ CARD32 h; -+} rfbChromiumMoveResizeWindowMsg; -+ -+#define sz_rfbChromiumMoveResizeWindowMsg 24 -+ -+/*----------------------------------------------------------------------------- -+ * ChromiumClipList - send clip list -+ */ -+ -+typedef struct { -+ CARD8 type; /* always rfbChromiumClipList */ -+ CARD8 pad1; -+ CARD16 pad2; -+ CARD32 winid; -+ CARD32 length; -+} rfbChromiumClipListMsg; -+ -+#define sz_rfbChromiumClipListMsg 12 -+ -+/*----------------------------------------------------------------------------- -+ * ChromiumWindowShow - map or unmap a window -+ */ -+ -+typedef struct { -+ CARD8 type; /* always rfbChromiumWindowShow */ -+ CARD8 pad1; -+ CARD16 pad2; -+ CARD32 winid; -+ CARD32 show; -+} rfbChromiumWindowShowMsg; -+ -+#define sz_rfbChromiumWindowShowMsg 12 -+ -+/*----------------------------------------------------------------------------- -+ * FileListData -+ */ -+ -+typedef struct _rfbFileListDataMsg { -+ CARD8 type; -+ CARD8 flags; -+ CARD16 numFiles; -+ CARD16 dataSize; -+ CARD16 compressedSize; -+ /* Followed by SizeData[numFiles] */ -+ /* Followed by Filenames[compressedSize] */ -+} rfbFileListDataMsg; -+ -+#define sz_rfbFileListDataMsg 8 -+ -+/*----------------------------------------------------------------------------- -+ * FileDownloadData -+ */ -+ -+typedef struct _rfbFileDownloadDataMsg { -+ CARD8 type; -+ CARD8 compressLevel; -+ CARD16 realSize; -+ CARD16 compressedSize; -+ /* Followed by File[copressedSize] */ -+} rfbFileDownloadDataMsg; -+ -+#define sz_rfbFileDownloadDataMsg 6 -+ -+ -+/*----------------------------------------------------------------------------- -+ * FileUploadCancel -+ */ -+ -+typedef struct _rfbFileUploadCancelMsg { -+ CARD8 type; -+ CARD8 unused; -+ CARD16 reasonLen; -+ /* Followed by reason[reasonLen] */ -+} rfbFileUploadCancelMsg; -+ -+#define sz_rfbFileUploadCancelMsg 4 -+ -+/*----------------------------------------------------------------------------- -+ * FileDownloadFailed -+ */ -+ -+typedef struct _rfbFileDownloadFailedMsg { -+ CARD8 type; -+ CARD8 unused; -+ CARD16 reasonLen; -+ /* Followed by reason[reasonLen] */ -+} rfbFileDownloadFailedMsg; -+ -+#define sz_rfbFileDownloadFailedMsg 4 -+ -+/*----------------------------------------------------------------------------- -+ * Union of all server->client messages. -+ */ -+ -+typedef union _rfbServerToClientMsg { -+ CARD8 type; -+ rfbFramebufferUpdateMsg fu; -+ rfbSetColourMapEntriesMsg scme; -+ rfbBellMsg b; -+ rfbServerCutTextMsg sct; -+ rfbFileListDataMsg fld; -+ rfbFileDownloadDataMsg fdd; -+ rfbFileUploadCancelMsg fuc; -+ rfbFileDownloadFailedMsg fdf; -+ rfbChromiumStartMsg scd; -+ rfbChromiumMoveResizeWindowMsg scm; -+ rfbChromiumClipListMsg sccl; -+ rfbChromiumWindowShowMsg scws; -+} rfbServerToClientMsg; -+ -+ -+ -+/***************************************************************************** -+ * -+ * Message definitions (client -> server) -+ * -+ *****************************************************************************/ -+ -+ -+/*----------------------------------------------------------------------------- -+ * SetPixelFormat - tell the RFB server the format in which the client wants -+ * pixels sent. -+ */ -+ -+typedef struct _rfbSetPixelFormatMsg { -+ CARD8 type; /* always rfbSetPixelFormat */ -+ CARD8 pad1; -+ CARD16 pad2; -+ rfbPixelFormat format; -+} rfbSetPixelFormatMsg; -+ -+#define sz_rfbSetPixelFormatMsg (sz_rfbPixelFormat + 4) -+ -+ -+/*----------------------------------------------------------------------------- -+ * FixColourMapEntries - when the pixel format uses a "colour map", fix -+ * read-only colour map entries. -+ * -+ * ***************** NOT CURRENTLY SUPPORTED ***************** -+ */ -+ -+typedef struct _rfbFixColourMapEntriesMsg { -+ CARD8 type; /* always rfbFixColourMapEntries */ -+ CARD8 pad; -+ CARD16 firstColour; -+ CARD16 nColours; -+ -+ /* Followed by nColours * 3 * CARD16 -+ r1, g1, b1, r2, g2, b2, r3, g3, b3, ..., rn, bn, gn */ -+ -+} rfbFixColourMapEntriesMsg; -+ -+#define sz_rfbFixColourMapEntriesMsg 6 -+ -+ -+/*----------------------------------------------------------------------------- -+ * SetEncodings - tell the RFB server which encoding types we accept. Put them -+ * in order of preference, if we have any. We may always receive raw -+ * encoding, even if we don't specify it here. -+ */ -+ -+typedef struct _rfbSetEncodingsMsg { -+ CARD8 type; /* always rfbSetEncodings */ -+ CARD8 pad; -+ CARD16 nEncodings; -+ /* followed by nEncodings * CARD32 encoding types */ -+} rfbSetEncodingsMsg; -+ -+#define sz_rfbSetEncodingsMsg 4 -+ -+ -+/*----------------------------------------------------------------------------- -+ * FramebufferUpdateRequest - request for a framebuffer update. If incremental -+ * is true then the client just wants the changes since the last update. If -+ * false then it wants the whole of the specified rectangle. -+ */ -+ -+typedef struct _rfbFramebufferUpdateRequestMsg { -+ CARD8 type; /* always rfbFramebufferUpdateRequest */ -+ CARD8 incremental; -+ CARD16 x; -+ CARD16 y; -+ CARD16 w; -+ CARD16 h; -+} rfbFramebufferUpdateRequestMsg; -+ -+#define sz_rfbFramebufferUpdateRequestMsg 10 -+ -+ -+/*----------------------------------------------------------------------------- -+ * KeyEvent - key press or release -+ * -+ * Keys are specified using the "keysym" values defined by the X Window System. -+ * For most ordinary keys, the keysym is the same as the corresponding ASCII -+ * value. Other common keys are: -+ * -+ * BackSpace 0xff08 -+ * Tab 0xff09 -+ * Return or Enter 0xff0d -+ * Escape 0xff1b -+ * Insert 0xff63 -+ * Delete 0xffff -+ * Home 0xff50 -+ * End 0xff57 -+ * Page Up 0xff55 -+ * Page Down 0xff56 -+ * Left 0xff51 -+ * Up 0xff52 -+ * Right 0xff53 -+ * Down 0xff54 -+ * F1 0xffbe -+ * F2 0xffbf -+ * ... ... -+ * F12 0xffc9 -+ * Shift 0xffe1 -+ * Control 0xffe3 -+ * Meta 0xffe7 -+ * Alt 0xffe9 -+ */ -+ -+typedef struct _rfbKeyEventMsg { -+ CARD8 type; /* always rfbKeyEvent */ -+ CARD8 down; /* true if down (press), false if up */ -+ CARD16 pad; -+ CARD32 key; /* key is specified as an X keysym */ -+} rfbKeyEventMsg; -+ -+#define sz_rfbKeyEventMsg 8 -+ -+ -+/*----------------------------------------------------------------------------- -+ * PointerEvent - mouse/pen move and/or button press. -+ */ -+ -+typedef struct _rfbPointerEventMsg { -+ CARD8 type; /* always rfbPointerEvent */ -+ CARD8 buttonMask; /* bits 0-7 are buttons 1-8, 0=up, 1=down */ -+ CARD16 x; -+ CARD16 y; -+} rfbPointerEventMsg; -+ -+#define rfbButton1Mask 1 -+#define rfbButton2Mask 2 -+#define rfbButton3Mask 4 -+#define rfbButton4Mask 8 -+#define rfbButton5Mask 16 -+ -+#define sz_rfbPointerEventMsg 6 -+ -+ -+ -+/*----------------------------------------------------------------------------- -+ * ClientCutText - the client has new text in its cut buffer. -+ */ -+ -+typedef struct _rfbClientCutTextMsg { -+ CARD8 type; /* always rfbClientCutText */ -+ CARD8 pad1; -+ CARD16 pad2; -+ CARD32 length; -+ /* followed by char text[length] */ -+} rfbClientCutTextMsg; -+ -+#define sz_rfbClientCutTextMsg 8 -+ -+/*----------------------------------------------------------------------------- -+ * FileListRequest -+ */ -+ -+typedef struct _rfbFileListRequestMsg { -+ CARD8 type; -+ CARD8 flags; -+ CARD16 dirNameSize; -+ /* Followed by char Dirname[dirNameSize] */ -+} rfbFileListRequestMsg; -+ -+#define sz_rfbFileListRequestMsg 4 -+ -+/*----------------------------------------------------------------------------- -+ * FileDownloadRequest -+ */ -+ -+typedef struct _rfbFileDownloadRequestMsg { -+ CARD8 type; -+ CARD8 compressedLevel; -+ CARD16 fNameSize; -+ CARD32 position; -+ /* Followed by char Filename[fNameSize] */ -+} rfbFileDownloadRequestMsg; -+ -+#define sz_rfbFileDownloadRequestMsg 8 -+ -+/*----------------------------------------------------------------------------- -+ * FileUploadRequest -+ */ -+ -+typedef struct _rfbFileUploadRequestMsg { -+ CARD8 type; -+ CARD8 compressedLevel; -+ CARD16 fNameSize; -+ CARD32 position; -+ /* Followed by char Filename[fNameSize] */ -+} rfbFileUploadRequestMsg; -+ -+#define sz_rfbFileUploadRequestMsg 8 -+ -+ -+/*----------------------------------------------------------------------------- -+ * FileUploadData -+ */ -+ -+typedef struct _rfbFileUploadDataMsg { -+ CARD8 type; -+ CARD8 compressedLevel; -+ CARD16 realSize; -+ CARD16 compressedSize; -+ /* Followed by File[compressedSize] */ -+} rfbFileUploadDataMsg; -+ -+#define sz_rfbFileUploadDataMsg 8 -+ -+/*----------------------------------------------------------------------------- -+ * FileDownloadCancel -+ */ -+ -+typedef struct _rfbFileDownloadCancelMsg { -+ CARD8 type; -+ CARD8 unused; -+ CARD16 reasonLen; -+ /* Followed by reason[reasonLen] */ -+} rfbFileDownloadCancelMsg; -+ -+#define sz_rfbFileDownloadCancelMsg 4 -+ -+/*----------------------------------------------------------------------------- -+ * FileUploadFailed -+ */ -+ -+typedef struct _rfbFileUploadFailedMsg { -+ CARD8 type; -+ CARD8 unused; -+ CARD16 reasonLen; -+ /* Followed by reason[reasonLen] */ -+} rfbFileUploadFailedMsg; -+ -+#define sz_rfbFileUploadFailedMsg 4 -+ -+/*----------------------------------------------------------------------------- -+ * FileCreateDirRequest -+ */ -+ -+typedef struct _rfbFileCreateDirRequestMsg { -+ CARD8 type; -+ CARD8 unused; -+ CARD16 dNameLen; -+ CARD32 dModTime; -+ /* Followed by dName[dNameLen] */ -+} rfbFileCreateDirRequestMsg; -+ -+#define sz_rfbFileCreateDirRequestMsg 8 -+ -+/*----------------------------------------------------------------------------- -+ * ChromiumStop - the client has stopped the GL app. -+ */ -+ -+typedef struct { -+ CARD8 type; /* always rfbChromiumStop */ -+ CARD8 pad1; -+ CARD16 pad2; -+ CARD32 port; -+} rfbChromiumStopMsg; -+ -+#define sz_rfbChromiumStopMsg 8 -+ -+/*----------------------------------------------------------------------------- -+ * ChromiumExpose - redraw the window -+ */ -+ -+typedef struct { -+ CARD8 type; /* always rfbChromiumExpose */ -+ CARD8 pad1; -+ CARD16 pad2; -+ CARD32 winid; -+} rfbChromiumExposeMsg; -+ -+#define sz_rfbChromiumExposeMsg 8 -+ -+/*----------------------------------------------------------------------------- -+ * Union of all client->server messages. -+ */ -+ -+typedef union _rfbClientToServerMsg { -+ CARD8 type; -+ rfbSetPixelFormatMsg spf; -+ rfbFixColourMapEntriesMsg fcme; -+ rfbSetEncodingsMsg se; -+ rfbFramebufferUpdateRequestMsg fur; -+ rfbKeyEventMsg ke; -+ rfbPointerEventMsg pe; -+ rfbClientCutTextMsg cct; -+ rfbFileListRequestMsg flr; -+ rfbFileDownloadRequestMsg fdr; -+ rfbFileUploadRequestMsg fupr; -+ rfbFileUploadDataMsg fud; -+ rfbFileDownloadCancelMsg fdc; -+ rfbFileUploadFailedMsg fuf; -+ rfbFileCreateDirRequestMsg fcdr; -+ rfbChromiumStopMsg csd; -+ rfbChromiumExposeMsg cse; -+} rfbClientToServerMsg; -diff --git a/hw/xfree86/vnc/rfbserver.c b/hw/xfree86/vnc/rfbserver.c -new file mode 100644 -index 0000000..ee002ab ---- /dev/null -+++ b/hw/xfree86/vnc/rfbserver.c -@@ -0,0 +1,2278 @@ -+/* -+ * rfbserver.c - deal with server-side of the RFB protocol. -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ */ -+ -+/* -+ * Copyright (C) 2000-2004 Constantin Kaplinsky. All Rights Reserved. -+ * Copyright (C) 2000 Tridia Corporation. All Rights Reserved. -+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. -+ * -+ * This is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This software is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this software; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -+ * USA. -+ */ -+ -+/* Use ``#define CORBA'' to enable CORBA control interface */ -+ -+#ifdef HAVE_XORG_CONFIG_H -+#include -+#endif -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "windowstr.h" -+#include "rfb.h" -+#include "input.h" -+#include "mipointer.h" -+#if XFREE86VNC -+#include -+#endif -+#ifdef CHROMIUM -+#include "mivalidate.h" -+#endif -+#include "sprite.h" -+#include "propertyst.h" -+#include -+#include -+ -+#ifdef CORBA -+#include -+#endif -+ -+#ifdef CHROMIUM -+struct CRWindowTable *windowTable = NULL; -+#endif -+ -+extern Atom VNC_CONNECT; -+ -+rfbClientPtr rfbClientHead = NULL; -+rfbClientPtr pointerClient = NULL; /* Mutex for pointer events */ -+ -+static rfbClientPtr rfbNewClient(ScreenPtr pScreen, int sock); -+static void rfbProcessClientProtocolVersion(rfbClientPtr cl); -+static void rfbProcessClientInitMessage(rfbClientPtr cl); -+static void rfbSendInteractionCaps(rfbClientPtr cl); -+static void rfbProcessClientNormalMessage(rfbClientPtr cl); -+static Bool rfbSendCopyRegion(rfbClientPtr cl, RegionPtr reg, int dx, int dy); -+static Bool rfbSendLastRectMarker(rfbClientPtr cl); -+ -+static char *text = NULL; -+ -+void -+rfbRootPropertyChange(ScreenPtr pScreen) -+{ -+ PropertyPtr pProp; -+ WindowPtr pWin = WindowTable[pScreen->myNum]; -+ -+ pProp = wUserProps (pWin); -+ -+ while (pProp) { -+ if ((pProp->propertyName == XA_CUT_BUFFER0) && -+ (pProp->type == XA_STRING) && -+ (pProp->format == 8)) -+ { -+ /* Ensure we don't keep re-sending cut buffer */ -+ -+ if ( (text && pProp->data && strncmp(text, pProp->data, pProp->size)) || !text) -+ rfbGotXCutText(pProp->data, pProp->size); -+ -+ if (text) xfree(text); -+ text = xalloc(1 + pProp->size); -+ if (! text) return; -+ if (pProp->data) memcpy(text, pProp->data, pProp->size); -+ text[pProp->size] = '\0'; -+ -+ return; -+ } -+ if ((pProp->propertyName == VNC_CONNECT) && (pProp->type == XA_STRING) -+ && (pProp->format == 8) && (pProp->size > 0)) -+ { -+ 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(pScreen, host, port); -+ -+#ifdef CORBA -+ if (cl != NULL) -+ newConnection(cl, (KEYBOARD_DEVICE|POINTER_DEVICE), 1, 1, 1); -+#endif -+ -+ ChangeWindowProperty(pWin, -+ pProp->propertyName, pProp->type, -+ pProp->format, PropModeReplace, -+ 0, NULL, -+ FALSE -+ ); -+ -+ free(host); -+ } -+ pProp = pProp->next; -+ } -+} -+ -+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; -+} -+ -+void -+rfbUserAllow(int sock, int accept) -+{ -+ rfbClientPtr cl; -+ -+ for (cl = rfbClientHead; cl; cl = cl->next) { -+ if (cl->sock == sock) { -+ cl->userAccepted = accept; -+ } -+ } -+} -+ -+/* -+ * rfbNewClientConnection is called from sockets.c when a new connection -+ * comes in. -+ */ -+ -+void -+rfbNewClientConnection(ScreenPtr pScreen, int sock) -+{ -+ rfbClientPtr cl; -+ -+ cl = rfbNewClient(pScreen, sock); -+ -+ GenerateVncConnectedEvent(sock); -+ -+#if XFREE86VNC -+ /* Someone is connected - disable VT switching */ -+ xf86EnableVTSwitch(FALSE); -+#endif -+ -+#ifdef CORBA -+ if (cl != NULL) -+ newConnection(cl, (KEYBOARD_DEVICE|POINTER_DEVICE), 1, 1, 1); -+#endif -+} -+ -+ -+/* -+ * rfbReverseConnection is called by the CORBA stuff to make an outward -+ * connection to a "listening" RFB client. -+ */ -+ -+rfbClientPtr -+rfbReverseConnection(ScreenPtr pScreen, char *host, int port) -+{ -+ int sock; -+ rfbClientPtr cl; -+ -+ if ((sock = rfbConnect(pScreen, host, port)) < 0) -+ return (rfbClientPtr)NULL; -+ -+ cl = rfbNewClient(pScreen, sock); -+ -+ if (cl) { -+ cl->reverseConnection = TRUE; -+ } -+ -+ return cl; -+} -+ -+ -+#ifdef CHROMIUM -+/* -+ * rfbSetClip -- -+ * Generate expose event. -+ * This function is overkill and should be cleaned up, but it -+ * works for now. -+ */ -+ -+void -+rfbSetClip (WindowPtr pWin, BOOL enable) -+{ -+ ScreenPtr pScreen = pWin->drawable.pScreen; -+ WindowPtr pChild; -+ Bool WasViewable = (Bool)(pWin->viewable); -+ Bool anyMarked = FALSE; -+ RegionPtr pOldClip = NULL, bsExposed; -+#ifdef DO_SAVE_UNDERS -+ Bool dosave = FALSE; -+#endif -+ WindowPtr pLayerWin; -+ BoxRec box; -+ -+ if (WasViewable) -+ { -+ for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) -+ { -+ (void) (*pScreen->MarkOverlappedWindows)(pChild, -+ pChild, -+ &pLayerWin); -+ } -+ (*pScreen->MarkWindow) (pWin); -+ anyMarked = TRUE; -+ if (pWin->valdata) -+ { -+ if (HasBorder (pWin)) -+ { -+ RegionPtr borderVisible; -+ -+ borderVisible = REGION_CREATE(pScreen, NullBox, 1); -+ REGION_SUBTRACT(pScreen, borderVisible, -+ &pWin->borderClip, &pWin->winSize); -+ pWin->valdata->before.borderVisible = borderVisible; -+ } -+ pWin->valdata->before.resized = TRUE; -+ } -+ } -+ -+ /* -+ * Use REGION_BREAK to avoid optimizations in ValidateTree -+ * that assume the root borderClip can't change well, normally -+ * it doesn't...) -+ */ -+ if (enable) -+ { -+ box.x1 = 0; -+ box.y1 = 0; -+ box.x2 = pScreen->width; -+ box.y2 = pScreen->height; -+ REGION_INIT (pScreen, &pWin->winSize, &box, 1); -+ REGION_INIT (pScreen, &pWin->borderSize, &box, 1); -+ if (WasViewable) -+ REGION_RESET(pScreen, &pWin->borderClip, &box); -+ pWin->drawable.width = pScreen->width; -+ pWin->drawable.height = pScreen->height; -+ REGION_BREAK (pWin->drawable.pScreen, &pWin->clipList); -+ } -+ else -+ { -+ REGION_EMPTY(pScreen, &pWin->borderClip); -+ REGION_BREAK (pWin->drawable.pScreen, &pWin->clipList); -+ } -+ -+ ResizeChildrenWinSize (pWin, 0, 0, 0, 0); -+ -+ if (WasViewable) -+ { -+ if (pWin->backStorage) -+ { -+ pOldClip = REGION_CREATE(pScreen, NullBox, 1); -+ REGION_COPY(pScreen, pOldClip, &pWin->clipList); -+ } -+ -+ if (pWin->firstChild) -+ { -+ anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin->firstChild, -+ pWin->firstChild, -+ (WindowPtr *)NULL); -+ } -+ else -+ { -+ (*pScreen->MarkWindow) (pWin); -+ anyMarked = TRUE; -+ } -+ -+#ifdef DO_SAVE_UNDERS -+ if (DO_SAVE_UNDERS(pWin)) -+ { -+ dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, pLayerWin); -+ } -+#endif /* DO_SAVE_UNDERS */ -+ -+ if (anyMarked) -+ (*pScreen->ValidateTree)(pWin, NullWindow, VTOther); -+ } -+ -+ if (pWin->backStorage && -+ ((pWin->backingStore == Always) || WasViewable)) -+ { -+ if (!WasViewable) -+ pOldClip = &pWin->clipList; /* a convenient empty region */ -+ bsExposed = (*pScreen->TranslateBackingStore) -+ (pWin, 0, 0, pOldClip, -+ pWin->drawable.x, pWin->drawable.y); -+ if (WasViewable) -+ REGION_DESTROY(pScreen, pOldClip); -+ if (bsExposed) -+ { -+ RegionPtr valExposed = NullRegion; -+ -+ if (pWin->valdata) -+ valExposed = &pWin->valdata->after.exposed; -+ (*pScreen->WindowExposures) (pWin, valExposed, bsExposed); -+ if (valExposed) -+ REGION_EMPTY(pScreen, valExposed); -+ REGION_DESTROY(pScreen, bsExposed); -+ } -+ } -+ if (WasViewable) -+ { -+ if (anyMarked) -+ (*pScreen->HandleExposures)(pWin); -+#ifdef DO_SAVE_UNDERS -+ if (dosave) -+ (*pScreen->PostChangeSaveUnder)(pLayerWin, pLayerWin); -+#endif /* DO_SAVE_UNDERS */ -+ if (anyMarked && pScreen->PostValidateTree) -+ (*pScreen->PostValidateTree)(pWin, NullWindow, VTOther); -+ } -+ if (pWin->realized) -+ WindowsRestructured (); -+ FlushAllOutput (); -+} -+#endif /* CHROMIUM */ -+ -+/* -+ * rfbNewClient is called when a new connection has been made by whatever -+ * means. -+ */ -+ -+static rfbClientPtr -+rfbNewClient(ScreenPtr pScreen, int sock) -+{ -+ rfbProtocolVersionMsg pv; -+ rfbClientPtr cl; -+ BoxRec box; -+ struct sockaddr_in addr; -+ SOCKLEN_T addrlen = sizeof(struct sockaddr_in); -+ VNCSCREENPTR(pScreen); -+ int i; -+ -+ if (rfbClientHead == NULL) { -+ /* no other clients - make sure we don't think any keys are pressed */ -+ KbdReleaseAllKeys(); -+ } else { -+ rfbLog(" (other clients"); -+ for (cl = rfbClientHead; cl; cl = cl->next) { -+ rfbLog(" %s",cl->host); -+ } -+ rfbLog(")\n"); -+ } -+ -+ cl = (rfbClientPtr)xalloc(sizeof(rfbClientRec)); -+ -+#ifdef CHROMIUM -+ cl->chromium_port = 0; /* no GL application on this port, yet */ -+#endif -+ cl->userAccepted = 0; /* user hasn't even approached this yet .... */ -+ cl->sock = sock; -+ getpeername(sock, (struct sockaddr *)&addr, &addrlen); -+ cl->host = strdup(inet_ntoa(addr.sin_addr)); -+ cl->login = NULL; -+ -+ /* Dispatch client input to rfbProcessClientProtocolVersion(). */ -+ cl->state = RFB_PROTOCOL_VERSION; -+ -+ cl->viewOnly = FALSE; -+ cl->reverseConnection = FALSE; -+ cl->readyForSetColourMapEntries = FALSE; -+ cl->useCopyRect = FALSE; -+ cl->preferredEncoding = rfbEncodingRaw; -+ cl->correMaxWidth = 48; -+ cl->correMaxHeight = 48; -+ cl->pScreen = pScreen; -+ -+ REGION_NULL(pScreen,&cl->copyRegion); -+ cl->copyDX = 0; -+ cl->copyDY = 0; -+ -+ box.x1 = box.y1 = 0; -+ box.x2 = pVNC->width; -+ box.y2 = pVNC->height; -+ REGION_INIT(pScreen,&cl->modifiedRegion,&box,0); -+ -+ REGION_NULL(pScreen,&cl->requestedRegion); -+ -+ cl->deferredUpdateScheduled = FALSE; -+ cl->deferredUpdateTimer = NULL; -+ -+ cl->format = pVNC->rfbServerFormat; -+ cl->translateFn = rfbTranslateNone; -+ cl->translateLookupTable = NULL; -+ -+ cl->tightCompressLevel = TIGHT_DEFAULT_COMPRESSION; -+ cl->tightQualityLevel = -1; -+ for (i = 0; i < 4; i++) -+ cl->zsActive[i] = FALSE; -+ -+ cl->enableCursorShapeUpdates = FALSE; -+ cl->enableCursorPosUpdates = FALSE; -+ cl->enableLastRectEncoding = FALSE; -+#ifdef CHROMIUM -+ cl->enableChromiumEncoding = FALSE; -+#endif -+ -+ cl->next = rfbClientHead; -+ rfbClientHead = cl; -+ -+ rfbResetStats(cl); -+ -+ cl->compStreamInited = FALSE; -+ cl->compStream.total_in = 0; -+ cl->compStream.total_out = 0; -+ cl->compStream.zalloc = Z_NULL; -+ cl->compStream.zfree = Z_NULL; -+ cl->compStream.opaque = Z_NULL; -+ -+ cl->zlibCompressLevel = 5; -+ -+ sprintf(pv,rfbProtocolVersionFormat,rfbProtocolMajorVersion, -+ rfbProtocolMinorVersion); -+ -+ if (WriteExact(sock, pv, sz_rfbProtocolVersionMsg) < 0) { -+ rfbLogPerror("rfbNewClient: write"); -+ rfbCloseSock(pScreen, sock); -+ return NULL; -+ } -+ -+ return cl; -+} -+ -+ -+/* -+ * rfbClientConnectionGone is called from sockets.c just after a connection -+ * has gone away. -+ */ -+ -+void -+rfbClientConnectionGone(sock) -+ int sock; -+{ -+ rfbClientPtr cl, prev; -+ int i; -+#if XFREE86VNC -+ int allowvt = TRUE; -+#endif -+ -+ for (prev = NULL, cl = rfbClientHead; cl; prev = cl, cl = cl->next) { -+ if (sock == cl->sock) -+ break; -+ } -+ -+ if (!cl) { -+ rfbLog("rfbClientConnectionGone: unknown socket %d\n",sock); -+ return; -+ } -+ -+ if (cl->login != NULL) { -+ rfbLog("Client %s (%s) gone\n", cl->login, cl->host); -+ free(cl->login); -+ } else { -+ rfbLog("Client %s gone\n", cl->host); -+ } -+ free(cl->host); -+ -+ /* Release the compression state structures if any. */ -+ if ( cl->compStreamInited == TRUE ) { -+ deflateEnd( &(cl->compStream) ); -+ } -+ -+ for (i = 0; i < 4; i++) { -+ if (cl->zsActive[i]) -+ deflateEnd(&cl->zsStruct[i]); -+ } -+ -+ if (pointerClient == cl) -+ pointerClient = NULL; -+ -+#ifdef CORBA -+ destroyConnection(cl); -+#endif -+ -+ if (prev) -+ prev->next = cl->next; -+ else -+ rfbClientHead = cl->next; -+ -+ REGION_UNINIT(cl->pScreen,&cl->copyRegion); -+ REGION_UNINIT(cl->pScreen,&cl->modifiedRegion); -+ TimerFree(cl->deferredUpdateTimer); -+ -+ rfbPrintStats(cl); -+ -+ if (cl->translateLookupTable) free(cl->translateLookupTable); -+ -+ xfree(cl); -+ -+ GenerateVncDisconnectedEvent(sock); -+ -+#if XFREE86VNC -+ for (cl = rfbClientHead; cl; cl = cl->next) { -+ /* still someone connected */ -+ allowvt = FALSE; -+ } -+ -+ xf86EnableVTSwitch(allowvt); -+#endif -+} -+ -+ -+/* -+ * rfbProcessClientMessage is called when there is data to read from a client. -+ */ -+ -+void -+rfbProcessClientMessage(ScreenPtr pScreen, int sock) -+{ -+ rfbClientPtr cl; -+ -+ for (cl = rfbClientHead; cl; cl = cl->next) { -+ if (sock == cl->sock) -+ break; -+ } -+ -+ if (!cl) { -+ rfbLog("rfbProcessClientMessage: unknown socket %d\n",sock); -+ rfbCloseSock(pScreen, sock); -+ return; -+ } -+ -+#ifdef CORBA -+ if (isClosePending(cl)) { -+ rfbLog("Closing connection to client %s\n", cl->host); -+ rfbCloseSock(pScreen, sock); -+ return; -+ } -+#endif -+ -+ switch (cl->state) { -+ case RFB_PROTOCOL_VERSION: -+ rfbProcessClientProtocolVersion(cl); -+ break; -+ case RFB_SECURITY_TYPE: /* protocol 3.7 */ -+ rfbProcessClientSecurityType(cl); -+ break; -+ case RFB_TUNNELING_TYPE: /* protocol 3.7t */ -+ rfbProcessClientTunnelingType(cl); -+ break; -+ case RFB_AUTH_TYPE: /* protocol 3.7t */ -+ rfbProcessClientAuthType(cl); -+ break; -+ case RFB_AUTHENTICATION: -+ rfbVncAuthProcessResponse(cl); -+ break; -+ case RFB_INITIALISATION: -+ rfbProcessClientInitMessage(cl); -+ break; -+ default: -+ rfbProcessClientNormalMessage(cl); -+ } -+} -+ -+ -+/* -+ * rfbProcessClientProtocolVersion is called when the client sends its -+ * protocol version. -+ */ -+ -+static void -+rfbProcessClientProtocolVersion(cl) -+ rfbClientPtr cl; -+{ -+ rfbProtocolVersionMsg pv; -+ int n, major, minor; -+ -+ if ((n = ReadExact(cl->sock, pv, sz_rfbProtocolVersionMsg)) <= 0) { -+ if (n == 0) -+ rfbLog("rfbProcessClientProtocolVersion: client gone\n"); -+ else -+ rfbLogPerror("rfbProcessClientProtocolVersion: read"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ pv[sz_rfbProtocolVersionMsg] = 0; -+ if (sscanf(pv,rfbProtocolVersionFormat,&major,&minor) != 2) { -+ rfbLog("rfbProcessClientProtocolVersion: not a valid RFB client\n"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ rfbLog("Using protocol version %d.%d\n", major, minor); -+ -+ if (major != rfbProtocolMajorVersion) { -+ rfbLog("RFB protocol version mismatch - server %d.%d, client %d.%d\n", -+ rfbProtocolMajorVersion,rfbProtocolMinorVersion,major,minor); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ /* Always use one of the two standard versions of the RFB protocol. */ -+ cl->protocol_minor_ver = minor; -+ if (minor > rfbProtocolMinorVersion) { -+ cl->protocol_minor_ver = rfbProtocolMinorVersion; -+ } else if (minor < rfbProtocolMinorVersion) { -+ cl->protocol_minor_ver = rfbProtocolFallbackMinorVersion; -+ } -+ if (minor != rfbProtocolMinorVersion && -+ minor != rfbProtocolFallbackMinorVersion) { -+ rfbLog("Non-standard protocol version %d.%d, using %d.%d instead\n", -+ major, minor, rfbProtocolMajorVersion, cl->protocol_minor_ver); -+ } -+ -+ /* TightVNC protocol extensions are not enabled yet. */ -+ cl->protocol_tightvnc = FALSE; -+ -+ rfbAuthNewClient(cl); -+} -+ -+/* -+ * rfbClientConnFailed is called when a client connection has failed -+ * before the authentication stage. -+ */ -+ -+void -+rfbClientConnFailed(cl, reason) -+ rfbClientPtr cl; -+ char *reason; -+{ -+ int headerLen, reasonLen; -+ char buf[8]; -+ -+ headerLen = (cl->protocol_minor_ver >= 7) ? 1 : 4; -+ reasonLen = strlen(reason); -+ ((CARD32 *)buf)[0] = 0; -+ ((CARD32 *)buf)[1] = Swap32IfLE(reasonLen); -+ -+ if ( WriteExact(cl->sock, buf, headerLen) < 0 || -+ WriteExact(cl->sock, buf + 4, 4) < 0 || -+ WriteExact(cl->sock, reason, reasonLen) < 0 ) { -+ rfbLogPerror("rfbClientConnFailed: write"); -+ } -+ -+ rfbCloseSock(cl->pScreen, cl->sock); -+} -+ -+ -+/* -+ * rfbProcessClientInitMessage is called when the client sends its -+ * initialisation message. -+ */ -+ -+static void -+rfbProcessClientInitMessage(cl) -+ rfbClientPtr cl; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ rfbClientInitMsg ci; -+ char buf[256]; -+ rfbServerInitMsg *si = (rfbServerInitMsg *)buf; -+ struct passwd *user; -+ int len, n; -+ rfbClientPtr otherCl, nextCl; -+ -+ if ((n = ReadExact(cl->sock, (char *)&ci,sz_rfbClientInitMsg)) <= 0) { -+ if (n == 0) -+ rfbLog("rfbProcessClientInitMessage: client gone\n"); -+ else -+ rfbLogPerror("rfbProcessClientInitMessage: read"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ si->framebufferWidth = Swap16IfLE(pVNC->width); -+ si->framebufferHeight = Swap16IfLE(pVNC->height); -+ si->format = pVNC->rfbServerFormat; -+ si->format.redMax = Swap16IfLE(si->format.redMax); -+ si->format.greenMax = Swap16IfLE(si->format.greenMax); -+ si->format.blueMax = Swap16IfLE(si->format.blueMax); -+ -+ user = getpwuid(getuid()); -+ -+ if (strlen(desktopName) > 128) /* sanity check on desktop name len */ -+ desktopName[128] = 0; -+ -+ if (user) { -+ sprintf(buf + sz_rfbServerInitMsg, "%s's %s desktop (%s:%s)", -+ user->pw_name, desktopName, rfbThisHost, display); -+ } else { -+ sprintf(buf + sz_rfbServerInitMsg, "%s desktop (%s:%s)", -+ desktopName, rfbThisHost, display); -+ } -+ len = strlen(buf + sz_rfbServerInitMsg); -+ si->nameLength = Swap32IfLE(len); -+ -+ if (WriteExact(cl->sock, buf, sz_rfbServerInitMsg + len) < 0) { -+ rfbLogPerror("rfbProcessClientInitMessage: write"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ if (cl->protocol_tightvnc) -+ rfbSendInteractionCaps(cl); /* protocol 3.7t */ -+ -+ /* Dispatch client input to rfbProcessClientNormalMessage(). */ -+ cl->state = RFB_NORMAL; -+ -+ if (!cl->reverseConnection && -+ (pVNC->rfbNeverShared || (!pVNC->rfbAlwaysShared && !ci.shared))) { -+ -+ if (pVNC->rfbDontDisconnect) { -+ for (otherCl = rfbClientHead; otherCl; otherCl = otherCl->next) { -+ if ((otherCl != cl) && (otherCl->state == RFB_NORMAL)) { -+ rfbLog("-dontdisconnect: Not shared & existing client\n"); -+ rfbLog(" refusing new client %s\n", cl->host); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ } -+ } else { -+ for (otherCl = rfbClientHead; otherCl; otherCl = nextCl) { -+ nextCl = otherCl->next; -+ if ((otherCl != cl) && (otherCl->state == RFB_NORMAL)) { -+ rfbLog("Not shared - closing connection to client %s\n", -+ otherCl->host); -+ rfbCloseSock(otherCl->pScreen, otherCl->sock); -+ } -+ } -+ } -+ } -+} -+ -+ -+/* -+ * rfbSendInteractionCaps is called after sending the server -+ * initialisation message, only if the protocol version is 3.130. -+ * In this function, we send the lists of supported protocol messages -+ * and encodings. -+ */ -+ -+/* Update these constants on changing capability lists below! */ -+#define N_SMSG_CAPS 0 -+#define N_CMSG_CAPS 0 -+#define N_ENC_CAPS 12 -+ -+void -+rfbSendInteractionCaps(cl) -+ rfbClientPtr cl; -+{ -+ rfbInteractionCapsMsg intr_caps; -+ rfbCapabilityInfo enc_list[N_ENC_CAPS]; -+ int i; -+ -+ /* Fill in the header structure sent prior to capability lists. */ -+ intr_caps.nServerMessageTypes = Swap16IfLE(N_SMSG_CAPS); -+ intr_caps.nClientMessageTypes = Swap16IfLE(N_CMSG_CAPS); -+ intr_caps.nEncodingTypes = Swap16IfLE(N_ENC_CAPS); -+ intr_caps.pad = 0; -+ -+ /* Supported server->client message types. */ -+ /* For future file transfer support: -+ i = 0; -+ SetCapInfo(&smsg_list[i++], rfbFileListData, rfbTightVncVendor); -+ SetCapInfo(&smsg_list[i++], rfbFileDownloadData, rfbTightVncVendor); -+ SetCapInfo(&smsg_list[i++], rfbFileUploadCancel, rfbTightVncVendor); -+ SetCapInfo(&smsg_list[i++], rfbFileDownloadFailed, rfbTightVncVendor); -+ if (i != N_SMSG_CAPS) { -+ rfbLog("rfbSendInteractionCaps: assertion failed, i != N_SMSG_CAPS\n"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ */ -+ -+ /* Supported client->server message types. */ -+ /* For future file transfer support: -+ i = 0; -+ SetCapInfo(&cmsg_list[i++], rfbFileListRequest, rfbTightVncVendor); -+ SetCapInfo(&cmsg_list[i++], rfbFileDownloadRequest, rfbTightVncVendor); -+ SetCapInfo(&cmsg_list[i++], rfbFileUploadRequest, rfbTightVncVendor); -+ SetCapInfo(&cmsg_list[i++], rfbFileUploadData, rfbTightVncVendor); -+ SetCapInfo(&cmsg_list[i++], rfbFileDownloadCancel, rfbTightVncVendor); -+ SetCapInfo(&cmsg_list[i++], rfbFileUploadFailed, rfbTightVncVendor); -+ if (i != N_CMSG_CAPS) { -+ rfbLog("rfbSendInteractionCaps: assertion failed, i != N_CMSG_CAPS\n"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ */ -+ -+ /* Encoding types. */ -+ i = 0; -+ SetCapInfo(&enc_list[i++], rfbEncodingCopyRect, rfbStandardVendor); -+ SetCapInfo(&enc_list[i++], rfbEncodingRRE, rfbStandardVendor); -+ SetCapInfo(&enc_list[i++], rfbEncodingCoRRE, rfbStandardVendor); -+ SetCapInfo(&enc_list[i++], rfbEncodingHextile, rfbStandardVendor); -+ SetCapInfo(&enc_list[i++], rfbEncodingZlib, rfbTridiaVncVendor); -+ SetCapInfo(&enc_list[i++], rfbEncodingTight, rfbTightVncVendor); -+ SetCapInfo(&enc_list[i++], rfbEncodingCompressLevel0, rfbTightVncVendor); -+ SetCapInfo(&enc_list[i++], rfbEncodingQualityLevel0, rfbTightVncVendor); -+ SetCapInfo(&enc_list[i++], rfbEncodingXCursor, rfbTightVncVendor); -+ SetCapInfo(&enc_list[i++], rfbEncodingRichCursor, rfbTightVncVendor); -+ SetCapInfo(&enc_list[i++], rfbEncodingPointerPos, rfbTightVncVendor); -+ SetCapInfo(&enc_list[i++], rfbEncodingLastRect, rfbTightVncVendor); -+ if (i != N_ENC_CAPS) { -+ rfbLog("rfbSendInteractionCaps: assertion failed, i != N_ENC_CAPS\n"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ /* Send header and capability lists */ -+ if (WriteExact(cl->sock, (char *)&intr_caps, -+ sz_rfbInteractionCapsMsg) < 0 || -+ WriteExact(cl->sock, (char *)&enc_list[0], -+ sz_rfbCapabilityInfo * N_ENC_CAPS) < 0) { -+ rfbLogPerror("rfbSendInteractionCaps: write"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ /* Dispatch client input to rfbProcessClientNormalMessage(). */ -+ cl->state = RFB_NORMAL; -+} -+ -+ -+/* -+ * rfbProcessClientNormalMessage is called when the client has sent a normal -+ * protocol message. -+ */ -+ -+static void -+rfbProcessClientNormalMessage(cl) -+ rfbClientPtr cl; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ int n; -+ rfbClientToServerMsg msg; -+ char *str; -+ -+ if (pVNC->rfbUserAccept) { -+ /* -+ * We've asked for another level of user authentication -+ * If the user has not validated this connected, don't -+ * process it. -+ */ -+ /* -+ * NOTE: we do it here, so the vncviewer knows it's -+ * connected, but waiting for the first screen update -+ */ -+ if (cl->userAccepted == VNC_USER_UNDEFINED) { -+ usleep(10); -+ return; -+ } -+ if (cl->userAccepted == VNC_USER_DISCONNECT) { -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ } -+ -+ if ((n = ReadExact(cl->sock, (char *)&msg, 1)) <= 0) { -+ if (n != 0) -+ rfbLogPerror("rfbProcessClientNormalMessage: read"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ switch (msg.type) { -+ -+ case rfbSetPixelFormat: -+ -+ if ((n = ReadExact(cl->sock, ((char *)&msg) + 1, -+ sz_rfbSetPixelFormatMsg - 1)) <= 0) { -+ if (n != 0) -+ rfbLogPerror("rfbProcessClientNormalMessage: read"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ cl->format.bitsPerPixel = msg.spf.format.bitsPerPixel; -+ cl->format.depth = msg.spf.format.depth; -+ cl->format.bigEndian = (msg.spf.format.bigEndian ? 1 : 0); -+ cl->format.trueColour = (msg.spf.format.trueColour ? 1 : 0); -+ cl->format.redMax = Swap16IfLE(msg.spf.format.redMax); -+ cl->format.greenMax = Swap16IfLE(msg.spf.format.greenMax); -+ cl->format.blueMax = Swap16IfLE(msg.spf.format.blueMax); -+ cl->format.redShift = msg.spf.format.redShift; -+ cl->format.greenShift = msg.spf.format.greenShift; -+ cl->format.blueShift = msg.spf.format.blueShift; -+ -+ cl->readyForSetColourMapEntries = TRUE; -+ -+ rfbSetTranslateFunction(cl); -+ return; -+ -+ -+ case rfbFixColourMapEntries: -+ if ((n = ReadExact(cl->sock, ((char *)&msg) + 1, -+ sz_rfbFixColourMapEntriesMsg - 1)) <= 0) { -+ if (n != 0) -+ rfbLogPerror("rfbProcessClientNormalMessage: read"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ rfbLog("rfbProcessClientNormalMessage: %s", -+ "FixColourMapEntries unsupported\n"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ -+ -+ case rfbSetEncodings: -+ { -+ int i; -+ CARD32 enc; -+ -+ if ((n = ReadExact(cl->sock, ((char *)&msg) + 1, -+ sz_rfbSetEncodingsMsg - 1)) <= 0) { -+ if (n != 0) -+ rfbLogPerror("rfbProcessClientNormalMessage: read"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ msg.se.nEncodings = Swap16IfLE(msg.se.nEncodings); -+ -+ cl->preferredEncoding = -1; -+ cl->useCopyRect = FALSE; -+ cl->enableCursorShapeUpdates = FALSE; -+ cl->enableCursorPosUpdates = FALSE; -+ cl->enableLastRectEncoding = FALSE; -+#ifdef CHROMIUM -+ cl->enableChromiumEncoding = FALSE; -+#endif -+ cl->tightCompressLevel = TIGHT_DEFAULT_COMPRESSION; -+ cl->tightQualityLevel = -1; -+ -+ for (i = 0; i < msg.se.nEncodings; i++) { -+ if ((n = ReadExact(cl->sock, (char *)&enc, 4)) <= 0) { -+ if (n != 0) -+ rfbLogPerror("rfbProcessClientNormalMessage: read"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ enc = Swap32IfLE(enc); -+ -+ switch (enc) { -+ -+ case rfbEncodingCopyRect: -+ cl->useCopyRect = TRUE; -+ rfbLog("Using copyrect encoding for client %s\n", -+ cl->host); -+ break; -+ case rfbEncodingRaw: -+ if (cl->preferredEncoding == -1) { -+ cl->preferredEncoding = enc; -+ rfbLog("Using raw encoding for client %s\n", -+ cl->host); -+ } -+ break; -+ case rfbEncodingRRE: -+ if (cl->preferredEncoding == -1) { -+ cl->preferredEncoding = enc; -+ rfbLog("Using rre encoding for client %s\n", -+ cl->host); -+ } -+ break; -+ case rfbEncodingCoRRE: -+ if (cl->preferredEncoding == -1) { -+ cl->preferredEncoding = enc; -+ rfbLog("Using CoRRE encoding for client %s\n", -+ cl->host); -+ } -+ break; -+ case rfbEncodingHextile: -+ if (cl->preferredEncoding == -1) { -+ cl->preferredEncoding = enc; -+ rfbLog("Using hextile encoding for client %s\n", -+ cl->host); -+ } -+ break; -+ case rfbEncodingZlib: -+ if (cl->preferredEncoding == -1) { -+ cl->preferredEncoding = enc; -+ rfbLog("Using zlib encoding for client %s\n", -+ cl->host); -+ } -+ break; -+ case rfbEncodingTight: -+ if (cl->preferredEncoding == -1) { -+ cl->preferredEncoding = enc; -+ rfbLog("Using tight encoding for client %s\n", -+ cl->host); -+ } -+ break; -+ case rfbEncodingXCursor: -+ rfbLog("Enabling X-style cursor updates for client %s\n", -+ cl->host); -+ cl->enableCursorShapeUpdates = TRUE; -+ cl->useRichCursorEncoding = FALSE; -+ cl->cursorWasChanged = TRUE; -+ break; -+ case rfbEncodingRichCursor: -+ if (!cl->enableCursorShapeUpdates) { -+ rfbLog("Enabling full-color cursor updates for client " -+ "%s\n", cl->host); -+ cl->enableCursorShapeUpdates = TRUE; -+ cl->useRichCursorEncoding = TRUE; -+ cl->cursorWasChanged = TRUE; -+ } -+ break; -+ case rfbEncodingPointerPos: -+ if (!cl->enableCursorPosUpdates) { -+ rfbLog("Enabling cursor position updates for client %s\n", -+ cl->host); -+ cl->enableCursorPosUpdates = TRUE; -+ cl->cursorWasMoved = TRUE; -+ cl->cursorX = -1; -+ cl->cursorY = -1; -+ } -+ break; -+ case rfbEncodingLastRect: -+ if (!cl->enableLastRectEncoding) { -+ rfbLog("Enabling LastRect protocol extension for client " -+ "%s\n", cl->host); -+ cl->enableLastRectEncoding = TRUE; -+ } -+ break; -+#ifdef CHROMIUM -+ case rfbEncodingChromium: -+ case rfbEncodingChromium2: -+ if (!cl->enableChromiumEncoding) { -+ cl->enableChromiumEncoding = TRUE; -+ /* This tells OpenGL apps/replicate SPUs that new viewer -+ * has attached. -+ */ -+ GenerateVncChromiumConnectedEvent(cl->sock); -+ if (enc == rfbEncodingChromium) { -+ /* Generate exposures for all windows */ -+ WindowPtr pWin = WindowTable[cl->pScreen->myNum]; -+ rfbSetClip(pWin, 1); -+ } -+ else { -+ /* don't generate exposures for Chromium2 because -+ * that confused DMX. -+ */ -+ } -+ } -+ break; -+#endif -+ default: -+ if ( enc >= (CARD32)rfbEncodingCompressLevel0 && -+ enc <= (CARD32)rfbEncodingCompressLevel9 ) { -+ cl->zlibCompressLevel = enc & 0x0F; -+ cl->tightCompressLevel = enc & 0x0F; -+ rfbLog("Using compression level %d for client %s\n", -+ cl->tightCompressLevel, cl->host); -+ } else if ( enc >= (CARD32)rfbEncodingQualityLevel0 && -+ enc <= (CARD32)rfbEncodingQualityLevel9 ) { -+ cl->tightQualityLevel = enc & 0x0F; -+ rfbLog("Using image quality level %d for client %s\n", -+ cl->tightQualityLevel, cl->host); -+ } else { -+ rfbLog("rfbProcessClientNormalMessage: ignoring unknown " -+ "encoding %d\n", (int)enc); -+ } -+ } -+ } -+ -+ if (cl->preferredEncoding == -1) { -+ cl->preferredEncoding = rfbEncodingRaw; -+ rfbLog("No encoding specified - using raw encoding for client %s\n", -+ cl->host); -+ } -+ -+ if (cl->enableCursorPosUpdates && !cl->enableCursorShapeUpdates) { -+ rfbLog("Disabling cursor position updates for client %s\n", -+ cl->host); -+ cl->enableCursorPosUpdates = FALSE; -+ } -+ -+#if XFREE86VNC -+ /* -+ * With XFree86 and the hardware cursor's we need to put up the -+ * cursor again, and if we've detected a cursor shapeless client -+ * we need to disable hardware cursors. -+ */ -+ if (!cl->enableCursorShapeUpdates) -+ pVNC->SWCursor = (Bool *)TRUE; -+ else -+ pVNC->SWCursor = (Bool *)FALSE; -+ -+ { -+ int x, y; -+ miPointerPosition(&x, &y); -+ (*pVNC->spriteFuncs->SetCursor)(cl->pScreen, pVNC->pCurs, x, y); -+ } -+#endif -+ -+ return; -+ } -+ -+ -+ case rfbFramebufferUpdateRequest: -+ { -+ RegionRec tmpRegion; -+ BoxRec box; -+ -+#ifdef CORBA -+ addCapability(cl, DISPLAY_DEVICE); -+#endif -+ -+ if ((n = ReadExact(cl->sock, ((char *)&msg) + 1, -+ sz_rfbFramebufferUpdateRequestMsg-1)) <= 0) { -+ if (n != 0) -+ rfbLogPerror("rfbProcessClientNormalMessage: read"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ box.x1 = Swap16IfLE(msg.fur.x); -+ box.y1 = Swap16IfLE(msg.fur.y); -+ box.x2 = box.x1 + Swap16IfLE(msg.fur.w); -+ box.y2 = box.y1 + Swap16IfLE(msg.fur.h); -+ SAFE_REGION_INIT(cl->pScreen,&tmpRegion,&box,0); -+ -+ REGION_UNION(cl->pScreen, &cl->requestedRegion, &cl->requestedRegion, -+ &tmpRegion); -+ -+ if (!cl->readyForSetColourMapEntries) { -+ /* client hasn't sent a SetPixelFormat so is using server's */ -+ cl->readyForSetColourMapEntries = TRUE; -+ if (!cl->format.trueColour) { -+ if (!rfbSetClientColourMap(cl, 0, 0)) { -+ REGION_UNINIT(cl->pScreen,&tmpRegion); -+ return; -+ } -+ } -+ } -+ -+ if (!msg.fur.incremental) { -+ REGION_UNION(cl->pScreen,&cl->modifiedRegion,&cl->modifiedRegion, -+ &tmpRegion); -+ REGION_SUBTRACT(cl->pScreen,&cl->copyRegion,&cl->copyRegion, -+ &tmpRegion); -+ } -+ -+ if (FB_UPDATE_PENDING(cl)) { -+ rfbSendFramebufferUpdate(cl->pScreen, cl); -+ } -+ -+ REGION_UNINIT(cl->pScreen,&tmpRegion); -+ return; -+ } -+ -+ case rfbKeyEvent: -+ -+ cl->rfbKeyEventsRcvd++; -+ -+ if ((n = ReadExact(cl->sock, ((char *)&msg) + 1, -+ sz_rfbKeyEventMsg - 1)) <= 0) { -+ if (n != 0) -+ rfbLogPerror("rfbProcessClientNormalMessage: read"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+#ifdef CORBA -+ addCapability(cl, KEYBOARD_DEVICE); -+ -+ if (!isKeyboardEnabled(cl)) -+ return; -+#endif -+ if (!pVNC->rfbViewOnly && !cl->viewOnly) { -+ KbdAddEvent(msg.ke.down, (KeySym)Swap32IfLE(msg.ke.key), cl); -+ } -+ return; -+ -+ -+ case rfbPointerEvent: -+ -+ cl->rfbPointerEventsRcvd++; -+ -+ if ((n = ReadExact(cl->sock, ((char *)&msg) + 1, -+ sz_rfbPointerEventMsg - 1)) <= 0) { -+ if (n != 0) -+ rfbLogPerror("rfbProcessClientNormalMessage: read"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+#ifdef CORBA -+ addCapability(cl, POINTER_DEVICE); -+ -+ if (!isPointerEnabled(cl)) -+ return; -+#endif -+ -+ if (pointerClient && (pointerClient != cl)) -+ return; -+ -+ if (msg.pe.buttonMask == 0) -+ pointerClient = NULL; -+ else -+ pointerClient = cl; -+ -+ if (!pVNC->rfbViewOnly && !cl->viewOnly) { -+ cl->cursorX = (int)Swap16IfLE(msg.pe.x); -+ cl->cursorY = (int)Swap16IfLE(msg.pe.y); -+ PtrAddEvent(msg.pe.buttonMask, cl->cursorX, cl->cursorY, cl); -+ } -+ return; -+ -+ -+ case rfbClientCutText: -+ -+ if ((n = ReadExact(cl->sock, ((char *)&msg) + 1, -+ sz_rfbClientCutTextMsg - 1)) <= 0) { -+ if (n != 0) -+ rfbLogPerror("rfbProcessClientNormalMessage: read"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ msg.cct.length = Swap32IfLE(msg.cct.length); -+ -+ str = (char *)xalloc(msg.cct.length); -+ -+ if ((n = ReadExact(cl->sock, str, msg.cct.length)) <= 0) { -+ if (n != 0) -+ rfbLogPerror("rfbProcessClientNormalMessage: read"); -+ xfree(str); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ /* NOTE: We do not accept cut text from a view-only client */ -+ if (!cl->viewOnly) -+ rfbSetXCutText(str, msg.cct.length); -+ -+ xfree(str); -+ return; -+ -+#ifdef CHROMIUM -+ case rfbChromiumStop: -+ if ((n = ReadExact(cl->sock, ((char *)&msg) + 1, -+ sz_rfbChromiumStopMsg - 1)) <= 0) { -+ if (n != 0) -+ rfbLogPerror("rfbProcessClientNormalMessage: read"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ /* would we use msg.csd.port ??? */ -+ -+ cl->chromium_port = 0; -+ -+ /* tear down window information */ -+ { -+ CRWindowTable *wt, *nextWt = NULL; -+ -+ for (wt = windowTable; wt; wt = nextWt) { -+ nextWt = wt->next; -+ xfree(wt); -+ } -+ -+ windowTable = NULL; -+ } -+ -+ return; -+ -+ case rfbChromiumExpose: -+ if ((n = ReadExact(cl->sock, ((char *)&msg) + 1, -+ sz_rfbChromiumExposeMsg - 1)) <= 0) { -+ if (n != 0) -+ rfbLogPerror("rfbProcessClientNormalMessage: read"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+ -+ /* find the window and re-expose it */ -+ { -+ CRWindowTable *wt, *nextWt = NULL; -+ -+ for (wt = windowTable; wt; wt = nextWt) { -+ nextWt = wt->next; -+ if (wt->CRwinId == msg.cse.winid) { -+ WindowPtr pWin; -+ pWin = LookupIDByType(wt->XwinId, RT_WINDOW); -+ if (pWin) { -+ miSendExposures(pWin, &pWin->clipList, -+ pWin->drawable.x, -+ pWin->drawable.y); -+ FlushAllOutput(); -+ } -+ } -+ } -+ } -+ -+ return; -+#endif -+ -+ default: -+ -+ rfbLog("rfbProcessClientNormalMessage: unknown message type %d\n", -+ msg.type); -+ rfbLog(" ... closing connection\n"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return; -+ } -+} -+ -+ -+ -+/* -+ * rfbSendFramebufferUpdate - send the currently pending framebuffer update to -+ * the RFB client. -+ */ -+ -+Bool -+rfbSendFramebufferUpdate(pScreen, cl) -+ ScreenPtr pScreen; -+ rfbClientPtr cl; -+{ -+ VNCSCREENPTR(pScreen); -+ int i; -+ int nUpdateRegionRects; -+ rfbFramebufferUpdateMsg *fu = (rfbFramebufferUpdateMsg *)pVNC->updateBuf; -+ RegionRec updateRegion, updateCopyRegion; -+ int dx, dy; -+ Bool sendCursorShape = FALSE; -+ Bool sendCursorPos = FALSE; -+ -+ /* -+ * If this client understands cursor shape updates, cursor should be -+ * removed from the framebuffer. Otherwise, make sure it's put up. -+ */ -+ -+#if !XFREE86VNC -+ if (cl->enableCursorShapeUpdates) { -+ if (pVNC->cursorIsDrawn) -+ rfbSpriteRemoveCursor(pScreen); -+ if (!pVNC->cursorIsDrawn && cl->cursorWasChanged) -+ sendCursorShape = TRUE; -+ } else { -+ if (!pVNC->cursorIsDrawn) -+ rfbSpriteRestoreCursor(pScreen); -+ } -+#else -+ if (cl->enableCursorShapeUpdates) -+ if (cl->cursorWasChanged) -+ sendCursorShape = TRUE; -+#endif -+ -+ /* -+ * Do we plan to send cursor position update? -+ */ -+ -+ if (cl->enableCursorPosUpdates && cl->cursorWasMoved) -+ sendCursorPos = TRUE; -+ -+ /* -+ * The modifiedRegion may overlap the destination copyRegion. We remove -+ * any overlapping bits from the copyRegion (since they'd only be -+ * overwritten anyway). -+ */ -+ -+ REGION_SUBTRACT(pScreen, &cl->copyRegion, &cl->copyRegion, -+ &cl->modifiedRegion); -+ -+ /* -+ * The client is interested in the region requestedRegion. The region -+ * which should be updated now is the intersection of requestedRegion -+ * and the union of modifiedRegion and copyRegion. If it's empty then -+ * no update is needed. -+ */ -+ -+ REGION_NULL(pScreen,&updateRegion); -+ REGION_UNION(pScreen, &updateRegion, &cl->copyRegion, -+ &cl->modifiedRegion); -+ REGION_INTERSECT(pScreen, &updateRegion, &cl->requestedRegion, -+ &updateRegion); -+ -+ if ( !REGION_NOTEMPTY(pScreen,&updateRegion) && -+ !sendCursorShape && !sendCursorPos ) { -+ REGION_UNINIT(pScreen,&updateRegion); -+ return TRUE; -+ } -+ -+ /* -+ * We assume that the client doesn't have any pixel data outside the -+ * requestedRegion. In other words, both the source and destination of a -+ * copy must lie within requestedRegion. So the region we can send as a -+ * copy is the intersection of the copyRegion with both the requestedRegion -+ * and the requestedRegion translated by the amount of the copy. We set -+ * updateCopyRegion to this. -+ */ -+ -+ REGION_NULL(pScreen,&updateCopyRegion); -+ REGION_INTERSECT(pScreen, &updateCopyRegion, &cl->copyRegion, -+ &cl->requestedRegion); -+ REGION_TRANSLATE(pScreen, &cl->requestedRegion, cl->copyDX, cl->copyDY); -+ REGION_INTERSECT(pScreen, &updateCopyRegion, &updateCopyRegion, -+ &cl->requestedRegion); -+ dx = cl->copyDX; -+ dy = cl->copyDY; -+ -+ /* -+ * Next we remove updateCopyRegion from updateRegion so that updateRegion -+ * is the part of this update which is sent as ordinary pixel data (i.e not -+ * a copy). -+ */ -+ -+ REGION_SUBTRACT(pScreen, &updateRegion, &updateRegion, &updateCopyRegion); -+ -+ /* -+ * Finally we leave modifiedRegion to be the remainder (if any) of parts of -+ * the screen which are modified but outside the requestedRegion. We also -+ * empty both the requestedRegion and the copyRegion - note that we never -+ * carry over a copyRegion for a future update. -+ */ -+ -+ REGION_UNION(pScreen, &cl->modifiedRegion, &cl->modifiedRegion, -+ &cl->copyRegion); -+ REGION_SUBTRACT(pScreen, &cl->modifiedRegion, &cl->modifiedRegion, -+ &updateRegion); -+ REGION_SUBTRACT(pScreen, &cl->modifiedRegion, &cl->modifiedRegion, -+ &updateCopyRegion); -+ -+ REGION_EMPTY(pScreen, &cl->requestedRegion); -+ REGION_EMPTY(pScreen, &cl->copyRegion); -+ cl->copyDX = 0; -+ cl->copyDY = 0; -+ -+ /* -+ * Now send the update. -+ */ -+ -+ cl->rfbFramebufferUpdateMessagesSent++; -+ -+ if (cl->preferredEncoding == rfbEncodingCoRRE) { -+ nUpdateRegionRects = 0; -+ -+ for (i = 0; i < REGION_NUM_RECTS(&updateRegion); i++) { -+ int x = REGION_RECTS(&updateRegion)[i].x1; -+ int y = REGION_RECTS(&updateRegion)[i].y1; -+ int w = REGION_RECTS(&updateRegion)[i].x2 - x; -+ int h = REGION_RECTS(&updateRegion)[i].y2 - y; -+ nUpdateRegionRects += (((w-1) / cl->correMaxWidth + 1) -+ * ((h-1) / cl->correMaxHeight + 1)); -+ } -+ } else if (cl->preferredEncoding == rfbEncodingZlib) { -+ nUpdateRegionRects = 0; -+ -+ for (i = 0; i < REGION_NUM_RECTS(&updateRegion); i++) { -+ int x = REGION_RECTS(&updateRegion)[i].x1; -+ int y = REGION_RECTS(&updateRegion)[i].y1; -+ int w = REGION_RECTS(&updateRegion)[i].x2 - x; -+ int h = REGION_RECTS(&updateRegion)[i].y2 - y; -+ nUpdateRegionRects += (((h-1) / (ZLIB_MAX_SIZE( w ) / w)) + 1); -+ } -+ } else if (cl->preferredEncoding == rfbEncodingTight) { -+ nUpdateRegionRects = 0; -+ -+ for (i = 0; i < REGION_NUM_RECTS(&updateRegion); i++) { -+ int x = REGION_RECTS(&updateRegion)[i].x1; -+ int y = REGION_RECTS(&updateRegion)[i].y1; -+ int w = REGION_RECTS(&updateRegion)[i].x2 - x; -+ int h = REGION_RECTS(&updateRegion)[i].y2 - y; -+ int n = rfbNumCodedRectsTight(cl, x, y, w, h); -+ if (n == 0) { -+ nUpdateRegionRects = 0xFFFF; -+ break; -+ } -+ nUpdateRegionRects += n; -+ } -+ } else { -+ nUpdateRegionRects = REGION_NUM_RECTS(&updateRegion); -+ } -+ -+ fu->type = rfbFramebufferUpdate; -+ if (nUpdateRegionRects != 0xFFFF) { -+ fu->nRects = Swap16IfLE(REGION_NUM_RECTS(&updateCopyRegion) + -+ nUpdateRegionRects + -+ !!sendCursorShape + !!sendCursorPos); -+ } else { -+ fu->nRects = 0xFFFF; -+ } -+ pVNC->ublen = sz_rfbFramebufferUpdateMsg; -+ -+ if (sendCursorShape) { -+ cl->cursorWasChanged = FALSE; -+ if (!rfbSendCursorShape(cl, pScreen)) -+ return FALSE; -+ } -+ -+ if (sendCursorPos) { -+ cl->cursorWasMoved = FALSE; -+ if (!rfbSendCursorPos(cl, pScreen)) -+ return FALSE; -+ } -+ -+ if (REGION_NOTEMPTY(pScreen,&updateCopyRegion)) { -+ if (!rfbSendCopyRegion(cl,&updateCopyRegion,dx,dy)) { -+ REGION_UNINIT(pScreen,&updateRegion); -+ REGION_UNINIT(pScreen,&updateCopyRegion); -+ return FALSE; -+ } -+ } -+ -+ REGION_UNINIT(pScreen,&updateCopyRegion); -+ -+ for (i = 0; i < REGION_NUM_RECTS(&updateRegion); i++) { -+ int x = REGION_RECTS(&updateRegion)[i].x1; -+ int y = REGION_RECTS(&updateRegion)[i].y1; -+ int w = REGION_RECTS(&updateRegion)[i].x2 - x; -+ int h = REGION_RECTS(&updateRegion)[i].y2 - y; -+ -+ cl->rfbRawBytesEquivalent += (sz_rfbFramebufferUpdateRectHeader -+ + w * (cl->format.bitsPerPixel / 8) * h); -+ -+ switch (cl->preferredEncoding) { -+ case rfbEncodingRaw: -+ if (!rfbSendRectEncodingRaw(cl, x, y, w, h)) { -+ REGION_UNINIT(pScreen,&updateRegion); -+ return FALSE; -+ } -+ break; -+ case rfbEncodingRRE: -+ if (!rfbSendRectEncodingRRE(cl, x, y, w, h)) { -+ REGION_UNINIT(pScreen,&updateRegion); -+ return FALSE; -+ } -+ break; -+ case rfbEncodingCoRRE: -+ if (!rfbSendRectEncodingCoRRE(cl, x, y, w, h)) { -+ REGION_UNINIT(pScreen,&updateRegion); -+ return FALSE; -+ } -+ break; -+ case rfbEncodingHextile: -+ if (!rfbSendRectEncodingHextile(cl, x, y, w, h)) { -+ REGION_UNINIT(pScreen,&updateRegion); -+ return FALSE; -+ } -+ break; -+ case rfbEncodingZlib: -+ if (!rfbSendRectEncodingZlib(cl, x, y, w, h)) { -+ REGION_UNINIT(pScreen,&updateRegion); -+ return FALSE; -+ } -+ break; -+ case rfbEncodingTight: -+ if (!rfbSendRectEncodingTight(cl, x, y, w, h)) { -+ REGION_UNINIT(pScreen,&updateRegion); -+ return FALSE; -+ } -+ break; -+ } -+ } -+ -+ REGION_UNINIT(pScreen,&updateRegion); -+ -+ if (nUpdateRegionRects == 0xFFFF && !rfbSendLastRectMarker(cl)) -+ return FALSE; -+ -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ -+ return TRUE; -+} -+ -+ -+ -+/* -+ * Send the copy region as a string of CopyRect encoded rectangles. -+ * The only slightly tricky thing is that we should send the messages in -+ * the correct order so that an earlier CopyRect will not corrupt the source -+ * of a later one. -+ */ -+ -+static Bool -+rfbSendCopyRegion(cl, reg, dx, dy) -+ rfbClientPtr cl; -+ RegionPtr reg; -+ int dx, dy; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ int nrects, nrectsInBand, x_inc, y_inc, thisRect, firstInNextBand; -+ int x, y, w, h; -+ rfbFramebufferUpdateRectHeader rect; -+ rfbCopyRect cr; -+ -+ nrects = REGION_NUM_RECTS(reg); -+ -+ if (dx <= 0) { -+ x_inc = 1; -+ } else { -+ x_inc = -1; -+ } -+ -+ if (dy <= 0) { -+ thisRect = 0; -+ y_inc = 1; -+ } else { -+ thisRect = nrects - 1; -+ y_inc = -1; -+ } -+ -+ while (nrects > 0) { -+ -+ firstInNextBand = thisRect; -+ nrectsInBand = 0; -+ -+ while ((nrects > 0) && -+ (REGION_RECTS(reg)[firstInNextBand].y1 -+ == REGION_RECTS(reg)[thisRect].y1)) -+ { -+ firstInNextBand += y_inc; -+ nrects--; -+ nrectsInBand++; -+ } -+ -+ if (x_inc != y_inc) { -+ thisRect = firstInNextBand - y_inc; -+ } -+ -+ while (nrectsInBand > 0) { -+ if ((pVNC->ublen + sz_rfbFramebufferUpdateRectHeader -+ + sz_rfbCopyRect) > UPDATE_BUF_SIZE) -+ { -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ } -+ -+ x = REGION_RECTS(reg)[thisRect].x1; -+ y = REGION_RECTS(reg)[thisRect].y1; -+ w = REGION_RECTS(reg)[thisRect].x2 - x; -+ h = REGION_RECTS(reg)[thisRect].y2 - y; -+ -+ rect.r.x = Swap16IfLE(x); -+ rect.r.y = Swap16IfLE(y); -+ rect.r.w = Swap16IfLE(w); -+ rect.r.h = Swap16IfLE(h); -+ rect.encoding = Swap32IfLE(rfbEncodingCopyRect); -+ -+ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&rect, -+ sz_rfbFramebufferUpdateRectHeader); -+ pVNC->ublen += sz_rfbFramebufferUpdateRectHeader; -+ -+ cr.srcX = Swap16IfLE(x - dx); -+ cr.srcY = Swap16IfLE(y - dy); -+ -+ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&cr, sz_rfbCopyRect); -+ pVNC->ublen += sz_rfbCopyRect; -+ -+ cl->rfbRectanglesSent[rfbEncodingCopyRect]++; -+ cl->rfbBytesSent[rfbEncodingCopyRect] -+ += sz_rfbFramebufferUpdateRectHeader + sz_rfbCopyRect; -+ -+ thisRect += x_inc; -+ nrectsInBand--; -+ } -+ -+ thisRect = firstInNextBand; -+ } -+ -+ return TRUE; -+} -+ -+ -+/* -+ * Send a given rectangle in raw encoding (rfbEncodingRaw). -+ */ -+ -+Bool -+rfbSendRectEncodingRaw(cl, x, y, w, h) -+ rfbClientPtr cl; -+ int x, y, w, h; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ rfbFramebufferUpdateRectHeader rect; -+ int nlines; -+ int bytesPerLine = w * (cl->format.bitsPerPixel / 8); -+ unsigned char *fbptr = NULL; -+ int newy = 0; -+ -+ if (pVNC->useGetImage) { -+ newy = y; -+ } else { -+ fbptr = (pVNC->pfbMemory + (pVNC->paddedWidthInBytes * y) -+ + (x * (pVNC->bitsPerPixel / 8))); -+ } -+ -+ /* Flush the buffer to guarantee correct alignment for translateFn(). */ -+ if (pVNC->ublen > 0) { -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ } -+ -+ rect.r.x = Swap16IfLE(x); -+ rect.r.y = Swap16IfLE(y); -+ rect.r.w = Swap16IfLE(w); -+ rect.r.h = Swap16IfLE(h); -+ rect.encoding = Swap32IfLE(rfbEncodingRaw); -+ -+ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&rect,sz_rfbFramebufferUpdateRectHeader); -+ pVNC->ublen += sz_rfbFramebufferUpdateRectHeader; -+ -+ cl->rfbRectanglesSent[rfbEncodingRaw]++; -+ cl->rfbBytesSent[rfbEncodingRaw] -+ += sz_rfbFramebufferUpdateRectHeader + bytesPerLine * h; -+ -+ nlines = (UPDATE_BUF_SIZE - pVNC->ublen) / bytesPerLine; -+ -+ while (TRUE) { -+ if (nlines > h) -+ nlines = h; -+ -+ if (pVNC->useGetImage) { -+ (*cl->pScreen->GetImage)((DrawablePtr)WindowTable[cl->pScreen->myNum], x, newy, w, nlines, ZPixmap, ~0, &pVNC->updateBuf[pVNC->ublen]); -+ newy += nlines; -+ } else { -+ (*cl->translateFn)(cl->pScreen, cl->translateLookupTable, &pVNC->rfbServerFormat, -+ &cl->format, fbptr, &pVNC->updateBuf[pVNC->ublen], -+ pVNC->paddedWidthInBytes, w, nlines, x, y); -+ } -+ -+ pVNC->ublen += nlines * bytesPerLine; -+ h -= nlines; -+ -+ if (h == 0) /* rect fitted in buffer, do next one */ -+ return TRUE; -+ -+ /* buffer full - flush partial rect and do another nlines */ -+ -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ -+ if (!pVNC->useGetImage) -+ fbptr += (pVNC->paddedWidthInBytes * nlines); -+ -+ nlines = (UPDATE_BUF_SIZE - pVNC->ublen) / bytesPerLine; -+ if (nlines == 0) { -+ rfbLog("rfbSendRectEncodingRaw: send buffer too small for %d " -+ "bytes per line\n", bytesPerLine); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return FALSE; -+ } -+ } -+} -+ -+ -+/* -+ * Send an empty rectangle with encoding field set to value of -+ * rfbEncodingLastRect to notify client that this is the last -+ * rectangle in framebuffer update ("LastRect" extension of RFB -+ * protocol). -+ */ -+ -+static Bool -+rfbSendLastRectMarker(cl) -+ rfbClientPtr cl; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ rfbFramebufferUpdateRectHeader rect; -+ -+ if (pVNC->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) { -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ } -+ -+ rect.encoding = Swap32IfLE(rfbEncodingLastRect); -+ rect.r.x = 0; -+ rect.r.y = 0; -+ rect.r.w = 0; -+ rect.r.h = 0; -+ -+ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&rect,sz_rfbFramebufferUpdateRectHeader); -+ pVNC->ublen += sz_rfbFramebufferUpdateRectHeader; -+ -+ cl->rfbLastRectMarkersSent++; -+ cl->rfbLastRectBytesSent += sz_rfbFramebufferUpdateRectHeader; -+ -+ return TRUE; -+} -+ -+ -+/* -+ * Send the contents of pVNC->updateBuf. Returns 1 if successful, -1 if -+ * not (errno should be set). -+ */ -+ -+Bool -+rfbSendUpdateBuf(cl) -+ rfbClientPtr cl; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ -+ /* -+ int i; -+ for (i = 0; i < pVNC->ublen; i++) { -+ rfbLog("%02x ",((unsigned char *)pVNC->updateBuf)[i]); -+ } -+ rfbLog("\n"); -+ */ -+ -+ if (pVNC->ublen > 0 && WriteExact(cl->sock, pVNC->updateBuf, pVNC->ublen) < 0) { -+ rfbLogPerror("rfbSendUpdateBuf: write"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return FALSE; -+ } -+ -+ pVNC->ublen = 0; -+ return TRUE; -+} -+ -+ -+ -+/* -+ * rfbSendSetColourMapEntries sends a SetColourMapEntries message to the -+ * client, using values from the currently installed colormap. -+ */ -+ -+Bool -+rfbSendSetColourMapEntries(cl, firstColour, nColours) -+ rfbClientPtr cl; -+ int firstColour; -+ int nColours; -+{ -+#if !XFREE86VNC -+ VNCSCREENPTR(cl->pScreen); -+#endif -+ char buf[sz_rfbSetColourMapEntriesMsg + 256 * 3 * 2]; -+ rfbSetColourMapEntriesMsg *scme = (rfbSetColourMapEntriesMsg *)buf; -+ CARD16 *rgb = (CARD16 *)(&buf[sz_rfbSetColourMapEntriesMsg]); -+ EntryPtr pent; -+ EntryPtr redEntry, greenEntry, blueEntry; -+ unsigned short redPart, greenPart, bluePart; -+ int i, len; -+ -+ scme->type = rfbSetColourMapEntries; -+ scme->nColours = Swap16IfLE(nColours); -+ -+ len = sz_rfbSetColourMapEntriesMsg; -+ -+ /* PseudoColor */ -+#if XFREE86VNC -+ if (miInstalledMaps[cl->pScreen->myNum]->class == PseudoColor) { -+#else -+ if (pVNC->rfbInstalledColormap->class == PseudoColor) { -+#endif -+ scme->firstColour = Swap16IfLE(firstColour); -+#if XFREE86VNC -+ pent = (EntryPtr)&miInstalledMaps[cl->pScreen->myNum]->red[firstColour]; -+#else -+ pent = (EntryPtr)&pVNC->rfbInstalledColormap->red[firstColour]; -+#endif -+ for (i = 0; i < nColours; i++) { -+ if (pent->fShared) { -+ rgb[i*3] = Swap16IfLE(pent->co.shco.red->color); -+ rgb[i*3+1] = Swap16IfLE(pent->co.shco.green->color); -+ rgb[i*3+2] = Swap16IfLE(pent->co.shco.blue->color); -+ } else { -+ rgb[i*3] = Swap16IfLE(pent->co.local.red); -+ rgb[i*3+1] = Swap16IfLE(pent->co.local.green); -+ rgb[i*3+2] = Swap16IfLE(pent->co.local.blue); -+ } -+ pent++; -+ } -+ } -+ -+ else { -+ -+ /* Break the DirectColor pixel into its r/g/b components */ -+#if XFREE86VNC -+ redPart = (firstColour & miInstalledMaps[cl->pScreen->myNum]->pVisual->redMask) -+ >> miInstalledMaps[cl->pScreen->myNum]->pVisual->offsetRed; -+ greenPart = (firstColour & miInstalledMaps[cl->pScreen->myNum]->pVisual->greenMask) -+ >> miInstalledMaps[cl->pScreen->myNum]->pVisual->offsetGreen; -+ bluePart = (firstColour & miInstalledMaps[cl->pScreen->myNum]->pVisual->blueMask) -+ >> miInstalledMaps[cl->pScreen->myNum]->pVisual->offsetBlue; -+#else -+ redPart = (firstColour & pVNC->rfbInstalledColormap->pVisual->redMask) -+ >> pVNC->rfbInstalledColormap->pVisual->offsetRed; -+ greenPart = (firstColour & pVNC->rfbInstalledColormap->pVisual->greenMask) -+ >> pVNC->rfbInstalledColormap->pVisual->offsetGreen; -+ bluePart = (firstColour & pVNC->rfbInstalledColormap->pVisual->blueMask) -+ >> pVNC->rfbInstalledColormap->pVisual->offsetBlue; -+#endif -+ -+ /* -+ * The firstColour field is only 16 bits. To support 24-bit pixels we -+ * sneak the red component in the 8-bit padding field which we renamed -+ * to redIndex. Green and blue are in firstColour (MSB, LSB respectively). -+ */ -+ scme->redIndex = Swap16IfLE(redPart); -+ scme->firstColour = Swap16IfLE((greenPart << 8) | bluePart); -+ -+#if XFREE86VNC -+ redEntry = (EntryPtr)&miInstalledMaps[cl->pScreen->myNum]->red[redPart]; -+ greenEntry = (EntryPtr)&miInstalledMaps[cl->pScreen->myNum]->green[greenPart]; -+ blueEntry = (EntryPtr)&miInstalledMaps[cl->pScreen->myNum]->blue[bluePart]; -+#else -+ redEntry = (EntryPtr)&pVNC->rfbInstalledColormap->red[redPart]; -+ greenEntry = (EntryPtr)&pVNC->rfbInstalledColormap->green[greenPart]; -+ blueEntry = (EntryPtr)&pVNC->rfbInstalledColormap->blue[bluePart]; -+#endif -+ for (i = 0; i < nColours; i++) { -+ if (redEntry->fShared) -+ rgb[i*3] = Swap16IfLE(redEntry->co.shco.red->color); -+ else -+ rgb[i*3] = Swap16IfLE(redEntry->co.local.red); -+ -+ if (greenEntry->fShared) -+ rgb[i*3+1] = Swap16IfLE(greenEntry->co.shco.green->color); -+ else -+ rgb[i*3+1] = Swap16IfLE(greenEntry->co.local.green); -+ -+ if (blueEntry->fShared) -+ rgb[i*3+2] = Swap16IfLE(blueEntry->co.shco.blue->color); -+ else -+ rgb[i*3+2] = Swap16IfLE(blueEntry->co.local.blue); -+ -+ redEntry++; -+ greenEntry++; -+ blueEntry++; -+ } -+ } -+ -+ len += nColours * 3 * 2; -+ -+ if (WriteExact(cl->sock, buf, len) < 0) { -+ rfbLogPerror("rfbSendSetColourMapEntries: write"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return FALSE; -+ } -+ return TRUE; -+} -+ -+ -+/* -+ * rfbSendBell sends a Bell message to all the clients. -+ */ -+ -+void -+rfbSendBell() -+{ -+ rfbClientPtr cl, nextCl; -+ rfbBellMsg b; -+ -+ for (cl = rfbClientHead; cl; cl = nextCl) { -+ nextCl = cl->next; -+ b.type = rfbBell; -+ if (WriteExact(cl->sock, (char *)&b, sz_rfbBellMsg) < 0) { -+ rfbLogPerror("rfbSendBell: write"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ } -+ } -+} -+ -+#ifdef CHROMIUM -+#ifdef sun -+extern int inet_aton(const char *cp, struct in_addr *inp); -+#endif -+ -+void -+rfbSendChromiumStart(unsigned int ipaddress, unsigned int crServerPort, -+ unsigned int mothershipPort) -+{ -+ rfbClientPtr cl, nextCl; -+ rfbChromiumStartMsg scd; -+ struct in_addr ip; -+ unsigned int vncipaddress; -+ -+ for (cl = rfbClientHead; cl; cl = nextCl) { -+ nextCl = cl->next; -+ if (!cl->enableChromiumEncoding) -+ continue; -+ inet_aton(cl->host, &ip); -+ memcpy(&vncipaddress, &ip, sizeof(unsigned int)); -+ if (ipaddress == vncipaddress /***&& !cl->chromium_port***/) { -+ cl->chromium_port = crServerPort; -+ cl->chromium_msport = mothershipPort; -+ scd.type = rfbChromiumStart; -+ scd.crServerPort = crServerPort; -+ scd.mothershipPort = mothershipPort; -+ if (WriteExact(cl->sock, (char *)&scd, -+ sz_rfbChromiumStartMsg) < 0) { -+ rfbLogPerror("rfbSendChromiumStart: write"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ } -+ /* We only start one client at at time, so break now! */ -+ break; -+ } -+ } -+} -+ -+ -+/** -+ * Begin monitoring the given X windowid. -+ * When we detect size/position/visibiliy changes we'll send a -+ * rfbChromiumMoveResizeWindow, rfbChromiumClipList, or rfbChromiumWindowShow -+ * message to the VNC viewer, passing the corresponding Chromium window id. -+ */ -+void -+rfbChromiumMonitorWindowID(unsigned int cr_windowid, unsigned long xwindowid) -+{ -+ CRWindowTable *newRec, *wt, *nextWt = NULL; -+ -+ if (xwindowid && !cr_windowid) { -+ /* stop monitoring the X window, remove from list */ -+ CRWindowTable *prev = NULL; -+ for (wt = windowTable; wt; wt = nextWt) { -+ nextWt = wt->next; -+ if (wt->XwinId == xwindowid) { -+ /* remove */ -+ if (prev) -+ prev->next = wt->next; -+ else -+ windowTable = wt->next; -+ xfree(wt); -+ } -+ else { -+ prev = wt; -+ } -+ } -+ return; -+ } -+ -+ /* See if we're already managing this window */ -+ for (wt = windowTable; wt; wt = nextWt) { -+ nextWt = wt->next; -+ /* and if so, update it's window ID */ -+ if (wt->CRwinId == cr_windowid) { -+ wt->XwinId = xwindowid; -+ return; -+ } -+ } -+ -+ /* o.k, new window so create new slot information */ -+ newRec = (CRWindowTable *)xalloc(sizeof(CRWindowTable)); -+ if (!newRec) { -+ rfbLog("Out of memory allocating CRWindowTable.\n"); -+ return; -+ } -+ -+ newRec->next = NULL; -+ newRec->CRwinId = cr_windowid; -+ newRec->XwinId = xwindowid; -+ newRec->clipRects = NULL; -+ newRec->numRects = 0; -+ -+ if (!windowTable) { -+ windowTable = newRec; -+ } -+ else { -+ for (wt = windowTable; wt; wt = nextWt) { -+ nextWt = wt->next; -+ if (!wt->next) /* found the next slot */ -+ wt->next = newRec; -+ } -+ } -+} -+ -+ -+void -+rfbSendChromiumMoveResizeWindow(unsigned int winid, int x, int y, unsigned int w, unsigned int h) -+{ -+ rfbClientPtr cl, nextCl; -+ rfbChromiumMoveResizeWindowMsg scm; -+ -+ for (cl = rfbClientHead; cl; cl = nextCl) { -+ nextCl = cl->next; -+ if (!cl->enableChromiumEncoding) -+ continue; -+ if (cl->chromium_port) { -+ scm.type = rfbChromiumMoveResizeWindow; -+ scm.winid = winid; -+ scm.x = x; -+ scm.y = y; -+ scm.w = w; -+ scm.h = h; -+ if (WriteExact(cl->sock, (char *)&scm, -+ sz_rfbChromiumMoveResizeWindowMsg) < 0) { -+ rfbLogPerror("rfbSendChromiumMoveResizeWindow: write\n"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ continue; -+ } -+ } -+ } -+} -+ -+void -+rfbSendChromiumClipList(unsigned int winid, BoxPtr pClipRects, int numClipRects) -+{ -+ rfbClientPtr cl, nextCl; -+ rfbChromiumClipListMsg sccl; -+ int len = sizeof(BoxRec) * numClipRects; -+ -+ for (cl = rfbClientHead; cl; cl = nextCl) { -+ nextCl = cl->next; -+ if (!cl->enableChromiumEncoding) -+ continue; -+ if (cl->chromium_port) { -+ sccl.type = rfbChromiumClipList; -+ sccl.winid = winid; -+ sccl.length = Swap32IfLE(len); -+ if (WriteExact(cl->sock, (char *)&sccl, -+ sz_rfbChromiumClipListMsg) < 0) { -+ rfbLogPerror("rfbSendChromiumClipList: write\n"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ continue; -+ } -+ if (WriteExact(cl->sock, (char *)pClipRects, len) < 0) { -+ rfbLogPerror("rfbSendChromiumClipList: write\n"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ continue; -+ } -+ } -+ } -+} -+ -+void -+rfbSendChromiumWindowShow(unsigned int winid, unsigned int show) -+{ -+ rfbClientPtr cl, nextCl; -+ rfbChromiumWindowShowMsg scws; -+ -+ for (cl = rfbClientHead; cl; cl = nextCl) { -+ nextCl = cl->next; -+ if (!cl->enableChromiumEncoding) -+ continue; -+ if (cl->chromium_port) { -+ scws.type = rfbChromiumWindowShow; -+ scws.winid = winid; -+ scws.show = show; -+ if (WriteExact(cl->sock, (char *)&scws, -+ sz_rfbChromiumWindowShowMsg) < 0) { -+ rfbLogPerror("rfbSendChromiumWindowShow: write\n"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ continue; -+ } -+ } -+ } -+} -+#endif /* CHROMIUM */ -+ -+/* -+ * rfbSendServerCutText sends a ServerCutText message to all the clients. -+ */ -+ -+void -+rfbSendServerCutText(char *str, int len) -+{ -+ rfbClientPtr cl, nextCl = NULL; -+ rfbServerCutTextMsg sct; -+ -+ for (cl = rfbClientHead; cl; cl = nextCl) { -+ if (cl->state != RFB_NORMAL) continue; -+ nextCl = cl->next; -+ sct.type = rfbServerCutText; -+ sct.length = Swap32IfLE(len); -+ if (WriteExact(cl->sock, (char *)&sct, -+ sz_rfbServerCutTextMsg) < 0) { -+ rfbLogPerror("rfbSendServerCutText: write\n"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ continue; -+ } -+ if (WriteExact(cl->sock, str, len) < 0) { -+ rfbLogPerror("rfbSendServerCutText: write\n"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ } -+ } -+} -+ -+ -+ -+ -+/***************************************************************************** -+ * -+ * UDP can be used for keyboard and pointer events when the underlying -+ * network is highly reliable. This is really here to support ORL's -+ * videotile, whose TCP implementation doesn't like sending lots of small -+ * packets (such as 100s of pen readings per second!). -+ */ -+ -+void -+rfbNewUDPConnection(sock) -+ int sock; -+{ -+ if (write(sock, &ptrAcceleration, 1) < 0) { -+ rfbLogPerror("rfbNewUDPConnection: write"); -+ } -+} -+ -+/* -+ * Because UDP is a message based service, we can't read the first byte and -+ * then the rest of the packet separately like we do with TCP. We will always -+ * get a whole packet delivered in one go, so we ask read() for the maximum -+ * number of bytes we can possibly get. -+ */ -+ -+void -+rfbProcessUDPInput(ScreenPtr pScreen, int sock) -+{ -+ VNCSCREENPTR(pScreen); -+ int n; -+ rfbClientToServerMsg msg; -+ -+ if ((n = read(sock, (char *)&msg, sizeof(msg))) <= 0) { -+ if (n < 0) { -+ rfbLogPerror("rfbProcessUDPInput: read"); -+ } -+ rfbDisconnectUDPSock(pScreen); -+ return; -+ } -+ -+ switch (msg.type) { -+ -+ case rfbKeyEvent: -+ if (n != sz_rfbKeyEventMsg) { -+ rfbLog("rfbProcessUDPInput: key event incorrect length\n"); -+ rfbDisconnectUDPSock(pScreen); -+ return; -+ } -+ if (!pVNC->rfbViewOnly) { -+ KbdAddEvent(msg.ke.down, (KeySym)Swap32IfLE(msg.ke.key), 0); -+ } -+ break; -+ -+ case rfbPointerEvent: -+ if (n != sz_rfbPointerEventMsg) { -+ rfbLog("rfbProcessUDPInput: ptr event incorrect length\n"); -+ rfbDisconnectUDPSock(pScreen); -+ return; -+ } -+ if (!pVNC->rfbViewOnly) { -+ PtrAddEvent(msg.pe.buttonMask, -+ Swap16IfLE(msg.pe.x), Swap16IfLE(msg.pe.y), 0); -+ } -+ break; -+ -+ default: -+ rfbLog("rfbProcessUDPInput: unknown message type %d\n", -+ msg.type); -+ rfbDisconnectUDPSock(pScreen); -+ } -+} -diff --git a/hw/xfree86/vnc/rre.c b/hw/xfree86/vnc/rre.c -new file mode 100644 -index 0000000..9e63ed7 ---- /dev/null -+++ b/hw/xfree86/vnc/rre.c -@@ -0,0 +1,325 @@ -+/* -+ * rre.c -+ * -+ * Routines to implement Rise-and-Run-length Encoding (RRE). This -+ * code is based on krw's original javatel rfbserver. -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ */ -+ -+/* -+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. -+ * -+ * This is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This software is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this software; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -+ * USA. -+ */ -+ -+#include -+#include -+#include -+#include "rfb.h" -+ -+/* -+ * rreBeforeBuf contains pixel data in the client's format. -+ * rreAfterBuf contains the RRE encoded version. If the RRE encoded version is -+ * larger than the raw data or if it exceeds rreAfterBufSize then -+ * raw encoding is used instead. -+ */ -+ -+static int rreBeforeBufSize = 0; -+static char *rreBeforeBuf = NULL; -+ -+static int rreAfterBufSize = 0; -+static char *rreAfterBuf = NULL; -+static int rreAfterBufLen; -+ -+static int subrectEncode8(CARD8 *data, int w, int h); -+static int subrectEncode16(CARD16 *data, int w, int h); -+static int subrectEncode32(CARD32 *data, int w, int h); -+static CARD32 getBgColour(char *data, int size, int bpp); -+ -+ -+/* -+ * rfbSendRectEncodingRRE - send a given rectangle using RRE encoding. -+ */ -+ -+Bool -+rfbSendRectEncodingRRE(cl, x, y, w, h) -+ rfbClientPtr cl; -+ int x, y, w, h; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ rfbFramebufferUpdateRectHeader rect; -+ rfbRREHeader hdr; -+ int nSubrects; -+ int i; -+ unsigned char *fbptr = (pVNC->pfbMemory + (pVNC->paddedWidthInBytes * y) -+ + (x * (pVNC->bitsPerPixel / 8))); -+ -+ int maxRawSize = (pVNC->width * pVNC->height -+ * (cl->format.bitsPerPixel / 8)); -+ -+ if (rreBeforeBufSize < maxRawSize) { -+ rreBeforeBufSize = maxRawSize; -+ if (rreBeforeBuf == NULL) -+ rreBeforeBuf = (char *)xalloc(rreBeforeBufSize); -+ else -+ rreBeforeBuf = (char *)xrealloc(rreBeforeBuf, rreBeforeBufSize); -+ } -+ -+ if (rreAfterBufSize < maxRawSize) { -+ rreAfterBufSize = maxRawSize; -+ if (rreAfterBuf == NULL) -+ rreAfterBuf = (char *)xalloc(rreAfterBufSize); -+ else -+ rreAfterBuf = (char *)xrealloc(rreAfterBuf, rreAfterBufSize); -+ } -+ -+ (*cl->translateFn)(cl->pScreen, cl->translateLookupTable, -+ &pVNC->rfbServerFormat, -+ &cl->format, fbptr, rreBeforeBuf, -+ pVNC->paddedWidthInBytes, w, h, x, y); -+ -+ switch (cl->format.bitsPerPixel) { -+ case 8: -+ nSubrects = subrectEncode8((CARD8 *)rreBeforeBuf, w, h); -+ break; -+ case 16: -+ nSubrects = subrectEncode16((CARD16 *)rreBeforeBuf, w, h); -+ break; -+ case 32: -+ nSubrects = subrectEncode32((CARD32 *)rreBeforeBuf, w, h); -+ break; -+ default: -+ rfbLog("getBgColour: bpp %d?\n",cl->format.bitsPerPixel); -+ exit(1); -+ } -+ -+ if (nSubrects < 0) { -+ -+ /* RRE encoding was too large, use raw */ -+ -+ return rfbSendRectEncodingRaw(cl, x, y, w, h); -+ } -+ -+ cl->rfbRectanglesSent[rfbEncodingRRE]++; -+ cl->rfbBytesSent[rfbEncodingRRE] += (sz_rfbFramebufferUpdateRectHeader -+ + sz_rfbRREHeader + rreAfterBufLen); -+ -+ if (pVNC->ublen + sz_rfbFramebufferUpdateRectHeader + sz_rfbRREHeader -+ > UPDATE_BUF_SIZE) -+ { -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ } -+ -+ rect.r.x = Swap16IfLE(x); -+ rect.r.y = Swap16IfLE(y); -+ rect.r.w = Swap16IfLE(w); -+ rect.r.h = Swap16IfLE(h); -+ rect.encoding = Swap32IfLE(rfbEncodingRRE); -+ -+ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&rect, -+ sz_rfbFramebufferUpdateRectHeader); -+ pVNC->ublen += sz_rfbFramebufferUpdateRectHeader; -+ -+ hdr.nSubrects = Swap32IfLE(nSubrects); -+ -+ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&hdr, sz_rfbRREHeader); -+ pVNC->ublen += sz_rfbRREHeader; -+ -+ for (i = 0; i < rreAfterBufLen;) { -+ -+ int bytesToCopy = UPDATE_BUF_SIZE - pVNC->ublen; -+ -+ if (i + bytesToCopy > rreAfterBufLen) { -+ bytesToCopy = rreAfterBufLen - i; -+ } -+ -+ memcpy(&pVNC->updateBuf[pVNC->ublen], &rreAfterBuf[i], bytesToCopy); -+ -+ pVNC->ublen += bytesToCopy; -+ i += bytesToCopy; -+ -+ if (pVNC->ublen == UPDATE_BUF_SIZE) { -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ } -+ } -+ -+ return TRUE; -+} -+ -+ -+ -+/* -+ * subrectEncode() encodes the given multicoloured rectangle as a background -+ * colour overwritten by single-coloured rectangles. It returns the number -+ * of subrectangles in the encoded buffer, or -1 if subrect encoding won't -+ * fit in the buffer. It puts the encoded rectangles in rreAfterBuf. The -+ * single-colour rectangle partition is not optimal, but does find the biggest -+ * horizontal or vertical rectangle top-left anchored to each consecutive -+ * coordinate position. -+ * -+ * The coding scheme is simply [...] where each -+ * is []. -+ */ -+ -+#define DEFINE_SUBRECT_ENCODE(bpp) \ -+static int \ -+subrectEncode##bpp(data,w,h) \ -+ CARD##bpp *data; \ -+ int w; \ -+ int h; \ -+{ \ -+ CARD##bpp cl; \ -+ rfbRectangle subrect; \ -+ int x,y; \ -+ int i,j; \ -+ int hx=0,hy,vx=0,vy; \ -+ int hyflag; \ -+ CARD##bpp *seg; \ -+ CARD##bpp *line; \ -+ int hw,hh,vw,vh; \ -+ int thex,they,thew,theh; \ -+ int numsubs = 0; \ -+ int newLen; \ -+ CARD##bpp bg = (CARD##bpp)getBgColour((char*)data,w*h,bpp); \ -+ \ -+ *((CARD##bpp*)rreAfterBuf) = bg; \ -+ \ -+ rreAfterBufLen = (bpp/8); \ -+ \ -+ for (y=0; y 0) && (i >= hx)) {hy += 1;} else {hyflag = 0;} \ -+ } \ -+ vy = j-1; \ -+ \ -+ /* We now have two possible subrects: (x,y,hx,hy) and (x,y,vx,vy) \ -+ * We'll choose the bigger of the two. \ -+ */ \ -+ hw = hx-x+1; \ -+ hh = hy-y+1; \ -+ vw = vx-x+1; \ -+ vh = vy-y+1; \ -+ \ -+ thex = x; \ -+ they = y; \ -+ \ -+ if ((hw*hh) > (vw*vh)) { \ -+ thew = hw; \ -+ theh = hh; \ -+ } else { \ -+ thew = vw; \ -+ theh = vh; \ -+ } \ -+ \ -+ subrect.x = Swap16IfLE(thex); \ -+ subrect.y = Swap16IfLE(they); \ -+ subrect.w = Swap16IfLE(thew); \ -+ subrect.h = Swap16IfLE(theh); \ -+ \ -+ newLen = rreAfterBufLen + (bpp/8) + sz_rfbRectangle; \ -+ if ((newLen > (w * h * (bpp/8))) || (newLen > rreAfterBufSize)) \ -+ return -1; \ -+ \ -+ numsubs += 1; \ -+ *((CARD##bpp*)(rreAfterBuf + rreAfterBufLen)) = cl; \ -+ rreAfterBufLen += (bpp/8); \ -+ memcpy(&rreAfterBuf[rreAfterBufLen],&subrect,sz_rfbRectangle); \ -+ rreAfterBufLen += sz_rfbRectangle; \ -+ \ -+ /* \ -+ * Now mark the subrect as done. \ -+ */ \ -+ for (j=they; j < (they+theh); j++) { \ -+ for (i=thex; i < (thex+thew); i++) { \ -+ data[j*w+i] = bg; \ -+ } \ -+ } \ -+ } \ -+ } \ -+ } \ -+ \ -+ return numsubs; \ -+} -+ -+DEFINE_SUBRECT_ENCODE(8) -+DEFINE_SUBRECT_ENCODE(16) -+DEFINE_SUBRECT_ENCODE(32) -+ -+ -+/* -+ * getBgColour() gets the most prevalent colour in a byte array. -+ */ -+static CARD32 -+getBgColour(data,size,bpp) -+ char *data; -+ int size; -+ int bpp; -+{ -+ -+#define NUMCLRS 256 -+ -+ static int counts[NUMCLRS]; -+ int i,j,k; -+ -+ int maxcount = 0; -+ CARD8 maxclr = 0; -+ -+ if (bpp != 8) { -+ if (bpp == 16) { -+ return ((CARD16 *)data)[0]; -+ } else if (bpp == 32) { -+ return ((CARD32 *)data)[0]; -+ } else { -+ rfbLog("getBgColour: bpp %d?\n",bpp); -+ exit(1); -+ } -+ } -+ -+ for (i=0; i= NUMCLRS) { -+ rfbLog("getBgColour: unusual colour = %d\n", k); -+ exit(1); -+ } -+ counts[k] += 1; -+ if (counts[k] > maxcount) { -+ maxcount = counts[k]; -+ maxclr = ((CARD8 *)data)[j]; -+ } -+ } -+ -+ return maxclr; -+} -diff --git a/hw/xfree86/vnc/sockets.c b/hw/xfree86/vnc/sockets.c -new file mode 100644 -index 0000000..e79ae42 ---- /dev/null -+++ b/hw/xfree86/vnc/sockets.c -@@ -0,0 +1,656 @@ -+/* -+ * sockets.c - deal with TCP & UDP sockets. -+ * -+ * This code should be independent of any changes in the RFB protocol. It just -+ * deals with the X server scheduling stuff, calling rfbNewClientConnection and -+ * rfbProcessClientMessage to actually deal with the protocol. If a socket -+ * needs to be closed for any reason then rfbCloseSock should be called, and -+ * this in turn will call rfbClientConnectionGone. To make an active -+ * connection out, call rfbConnect - note that this does _not_ call -+ * rfbNewClientConnection. -+ * -+ * This file is divided into two types of function. Those beginning with -+ * "rfb" are specific to sockets using the RFB protocol. Those without the -+ * "rfb" prefix are more general socket routines (which are used by the http -+ * code). -+ * -+ * Thanks to Karl Hakimian for pointing out that some platforms return EAGAIN -+ * not EWOULDBLOCK. -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ */ -+ -+/* -+ * 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. -+ */ -+ -+#ifdef HAVE_XORG_CONFIG_H -+#include -+#endif -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "windowstr.h" -+ -+#ifndef USE_LIBWRAP -+#define USE_LIBWRAP 0 -+#endif -+#if USE_LIBWRAP -+#include -+#include -+int allow_severity = LOG_INFO; -+int deny_severity = LOG_WARNING; -+#endif -+ -+#include "rfb.h" -+ -+int rfbMaxClientWait = 20000; /* time (ms) after which we decide client has -+ gone away - needed to stop us hanging */ -+ -+static struct sockaddr_in udpRemoteAddr; -+ -+/* -+ * rfbInitSockets sets up the TCP and UDP sockets to listen for RFB -+ * connections. It does nothing if called again. -+ */ -+ -+Bool -+rfbInitSockets(ScreenPtr pScreen) -+{ -+ VNCSCREENPTR(pScreen); -+ -+ if (inetdSock != -1) { -+ const int one = 1; -+ -+ if (fcntl(inetdSock, F_SETFL, O_NONBLOCK) < 0) { -+ rfbLogPerror("fcntl"); -+ return FALSE; -+ } -+ -+ if (setsockopt(inetdSock, IPPROTO_TCP, TCP_NODELAY, -+ (char *)&one, sizeof(one)) < 0) { -+ rfbLogPerror("setsockopt"); -+ return FALSE; -+ } -+ -+ AddEnabledDevice(inetdSock); -+ FD_ZERO(&pVNC->allFds); -+ FD_SET(inetdSock, &pVNC->allFds); -+ pVNC->maxFd = inetdSock; -+ return TRUE; -+ } -+ -+ if (pVNC->rfbPort == 0) { -+ pVNC->rfbPort = 5900 + atoi(display) + pScreen->myNum; -+ } -+ -+ if ((pVNC->rfbListenSock = ListenOnTCPPort(pScreen, pVNC->rfbPort)) < 0) { -+ rfbLogPerror("ListenOnTCPPort"); -+ pVNC->rfbPort = 0; -+ return FALSE; -+ } -+ -+ rfbLog("Listening for VNC connections on TCP port %d\n", pVNC->rfbPort); -+ -+ AddEnabledDevice(pVNC->rfbListenSock); -+ -+ FD_ZERO(&pVNC->allFds); -+ FD_SET(pVNC->rfbListenSock, &pVNC->allFds); -+ pVNC->maxFd = pVNC->rfbListenSock; -+ -+ if (pVNC->udpPort != 0) { -+ rfbLog("rfbInitSockets: listening for input on UDP port %d\n",pVNC->udpPort); -+ -+ if ((pVNC->udpSock = ListenOnUDPPort(pScreen, pVNC->udpPort)) < 0) { -+ rfbLogPerror("ListenOnUDPPort"); -+ return FALSE; -+ } -+ AddEnabledDevice(pVNC->udpSock); -+ FD_SET(pVNC->udpSock, &pVNC->allFds); -+ pVNC->maxFd = max(pVNC->udpSock,pVNC->maxFd); -+ } -+ -+ return TRUE; -+} -+ -+ -+/* -+ * rfbCheckFds is called from ProcessInputEvents to check for input on the RFB -+ * socket(s). If there is input to process, the appropriate function in the -+ * RFB server code will be called (rfbNewClientConnection, -+ * rfbProcessClientMessage, etc). -+ */ -+ -+void -+rfbCheckFds(ScreenPtr pScreen) -+{ -+ VNCSCREENPTR(pScreen); -+#if XFREE86VNC -+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; -+#endif -+ int nfds; -+ fd_set fds; -+ struct timeval tv; -+ struct sockaddr_in addr; -+ SOCKLEN_T addrlen = sizeof(addr); -+ char buf[6]; -+ const int one = 1; -+ int sock; -+ static Bool inetdInitDone = FALSE; -+ -+ if (!inetdInitDone && inetdSock != -1) { -+ rfbNewClientConnection(pScreen, inetdSock); -+ inetdInitDone = TRUE; -+ } -+ -+ memcpy((char *)&fds, (char *)&pVNC->allFds, sizeof(fd_set)); -+ tv.tv_sec = 0; -+ tv.tv_usec = 0; -+ nfds = select(pVNC->maxFd + 1, &fds, NULL, NULL, &tv); -+ if (nfds == 0) { -+ return; -+ } -+ if (nfds < 0) { -+ if (errno != EINTR) -+ rfbLogPerror("rfbCheckFds: select"); -+ return; -+ } -+ -+ if (pVNC->rfbListenSock != -1 && FD_ISSET(pVNC->rfbListenSock, &fds)) { -+ -+ if ((sock = accept(pVNC->rfbListenSock, -+ (struct sockaddr *)&addr, &addrlen)) < 0) { -+ rfbLogPerror("rfbCheckFds: accept"); -+ return; -+ } -+ -+ if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) { -+ rfbLogPerror("rfbCheckFds: fcntl"); -+ close(sock); -+ return; -+ } -+ -+ if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, -+ (char *)&one, sizeof(one)) < 0) { -+ rfbLogPerror("rfbCheckFds: setsockopt"); -+ close(sock); -+ return; -+ } -+ -+ rfbLog("\n"); -+ -+#if USE_LIBWRAP -+ if (!hosts_ctl("Xvnc", STRING_UNKNOWN, inet_ntoa(addr.sin_addr), -+ STRING_UNKNOWN)) { -+ rfbLog("Rejected connection from client %s\n", -+ inet_ntoa(addr.sin_addr)); -+ close(sock); -+ return; -+ } -+#endif -+ -+ rfbLog("Got VNC connection from client %s\n", inet_ntoa(addr.sin_addr)); -+ -+ AddEnabledDevice(sock); -+ FD_SET(sock, &pVNC->allFds); -+ pVNC->maxFd = max(sock,pVNC->maxFd); -+ -+ rfbNewClientConnection(pScreen, sock); -+ -+ FD_CLR(pVNC->rfbListenSock, &fds); -+ if (--nfds == 0) -+ return; -+ } -+ -+ if ((pVNC->udpSock != -1) && FD_ISSET(pVNC->udpSock, &fds)) { -+ -+ if (recvfrom(pVNC->udpSock, buf, 1, MSG_PEEK, -+ (struct sockaddr *)&addr, &addrlen) < 0) { -+ -+ rfbLogPerror("rfbCheckFds: UDP: recvfrom"); -+ rfbDisconnectUDPSock(pScreen); -+ -+ } else { -+ -+ if (!pVNC->udpSockConnected || -+ (memcmp(&addr, &udpRemoteAddr, addrlen) != 0)) -+ { -+ /* new remote end */ -+ rfbLog("rfbCheckFds: UDP: got connection\n"); -+ -+ memcpy(&udpRemoteAddr, &addr, addrlen); -+ pVNC->udpSockConnected = TRUE; -+ -+ if (connect(pVNC->udpSock, -+ (struct sockaddr *)&addr, addrlen) < 0) { -+ rfbLogPerror("rfbCheckFds: UDP: connect"); -+ rfbDisconnectUDPSock(pScreen); -+ return; -+ } -+ -+ rfbNewUDPConnection(pVNC->udpSock); -+ } -+ -+ rfbProcessUDPInput(pScreen, pVNC->udpSock); -+ } -+ -+ FD_CLR(pVNC->udpSock, &fds); -+ if (--nfds == 0) -+ return; -+ } -+ -+ for (sock = 0; sock <= pVNC->maxFd; sock++) { -+ if (FD_ISSET(sock, &fds) && FD_ISSET(sock, &pVNC->allFds)) { -+#if XFREE86VNC -+ if (!pScrn->vtSema) -+ rfbCloseSock(pScreen, sock); -+ else -+#endif -+ rfbProcessClientMessage(pScreen, sock); -+ } -+ } -+} -+ -+ -+void -+rfbDisconnectUDPSock(ScreenPtr pScreen) -+{ -+ VNCSCREENPTR(pScreen); -+ pVNC->udpSockConnected = FALSE; -+} -+ -+ -+void -+rfbCloseSock(ScreenPtr pScreen, int sock) -+{ -+ VNCSCREENPTR(pScreen); -+ close(sock); -+ RemoveEnabledDevice(sock); -+ FD_CLR(sock, &pVNC->allFds); -+ rfbClientConnectionGone(sock); -+ if (sock == inetdSock) -+ GiveUp(0); -+} -+ -+#if 0 -+/* -+ * rfbWaitForClient can be called to wait for the RFB client to send us a -+ * message. When one is received it is processed by calling -+ * rfbProcessClientMessage(). -+ */ -+ -+void -+rfbWaitForClient(sock) -+ int sock; -+{ -+ int n; -+ fd_set fds; -+ struct timeval tv; -+ -+ FD_ZERO(&fds); -+ FD_SET(sock, &fds); -+ tv.tv_sec = rfbMaxClientWait / 1000; -+ tv.tv_usec = (rfbMaxClientWait % 1000) * 1000; -+ n = select(sock+1, &fds, NULL, NULL, &tv); -+ if (n < 0) { -+ rfbLogPerror("rfbWaitForClient: select"); -+ exit(1); -+ } -+ if (n == 0) { -+ rfbCloseSock(sock); -+ return; -+ } -+ -+ rfbProcessClientMessage(sock); -+} -+#endif -+ -+/* -+ * rfbConnect is called to make a connection out to a given TCP address. -+ */ -+ -+int -+rfbConnect(ScreenPtr pScreen, char *host, int port) -+{ -+ VNCSCREENPTR(pScreen); -+ int sock; -+ int one = 1; -+ -+ rfbLog("\n"); -+ rfbLog("Making connection to client on host %s port %d\n", -+ host,port); -+ -+ if ((sock = ConnectToTcpAddr(host, port)) < 0) { -+ rfbLogPerror("connection failed"); -+ return -1; -+ } -+ -+ if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) { -+ rfbLogPerror("fcntl failed"); -+ close(sock); -+ return -1; -+ } -+ -+ if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, -+ (char *)&one, sizeof(one)) < 0) { -+ rfbLogPerror("setsockopt failed"); -+ close(sock); -+ return -1; -+ } -+ -+ AddEnabledDevice(sock); -+ FD_SET(sock, &pVNC->allFds); -+ pVNC->maxFd = max(sock,pVNC->maxFd); -+ -+ return sock; -+} -+ -+ -+ -+ -+/* -+ * ReadExact reads an exact number of bytes on a TCP socket. Returns 1 if -+ * those bytes have been read, 0 if the other end has closed, or -1 if an error -+ * occurred (errno is set to ETIMEDOUT if it timed out). -+ */ -+ -+int -+ReadExact(sock, buf, len) -+ int sock; -+ char *buf; -+ int len; -+{ -+ int n; -+ fd_set fds; -+ int tries = 5; -+ struct timeval tv; -+ -+ while (len > 0) { -+ n = read(sock, buf, len); -+ -+ if (n > 0) { -+ -+ buf += n; -+ len -= n; -+ -+ } else if (n == 0) { -+ -+ return 0; -+ -+ } else { -+ if (errno != EWOULDBLOCK && errno != EAGAIN) { -+ return n; -+ } -+ -+ do { -+ FD_ZERO(&fds); -+ FD_SET(sock, &fds); -+ tv.tv_sec = rfbMaxClientWait / 1000; -+ tv.tv_usec = (rfbMaxClientWait % 1000) * 1000; -+ n = select(sock+1, &fds, NULL, NULL, &tv); -+ tries--; -+ -+ /* We really need to retry if we get EINTR, so spin */ -+ /* If after 5 attempts we're still broke, abort.... */ -+ -+ } while ((n < 0 && errno == EINTR) && tries > 0); -+ -+ if (n < 0) { -+ rfbLogPerror("ReadExact: select"); -+ return n; -+ } -+ if (n == 0) { -+ errno = ETIMEDOUT; -+ return -1; -+ } -+ } -+ } -+ return 1; -+} -+ -+ -+ -+/* -+ * WriteExact writes an exact number of bytes on a TCP socket. Returns 1 if -+ * those bytes have been written, or -1 if an error occurred (errno is set to -+ * ETIMEDOUT if it timed out). -+ */ -+ -+int -+WriteExact(sock, buf, len) -+ int sock; -+ char *buf; -+ int len; -+{ -+ int n; -+ fd_set fds; -+ struct timeval tv; -+ int totalTimeWaited = 0; -+ -+ while (len > 0) { -+ n = write(sock, buf, len); -+ -+ if (n > 0) { -+ -+ buf += n; -+ len -= n; -+ -+ } else if (n == 0) { -+ -+ rfbLog("WriteExact: write returned 0?\n"); -+ return -1; -+ -+ } else { -+ if (errno != EWOULDBLOCK && errno != EAGAIN) { -+ return n; -+ } -+ -+#if 0 -+ /* Retry every 5 seconds until we exceed rfbMaxClientWait. We -+ need to do this because select doesn't necessarily return -+ immediately when the other end has gone away */ -+ -+ FD_ZERO(&fds); -+ FD_SET(sock, &fds); -+ tv.tv_sec = 5; -+ tv.tv_usec = 0; -+#else -+ /* We're in the WakeupHandler now, so don't wait */ -+ -+ FD_ZERO(&fds); -+ FD_SET(sock, &fds); -+ tv.tv_sec = 0; -+ tv.tv_usec = 0; -+#endif -+ n = select(sock+1, NULL, &fds, NULL, &tv); -+#if 0 -+ if (n < 0) { -+ rfbLogPerror("WriteExact: select"); -+ return n; -+ } -+ if (n == 0) { -+ totalTimeWaited += 5000; -+ if (totalTimeWaited >= rfbMaxClientWait) { -+ errno = ETIMEDOUT; -+ return -1; -+ } -+ } else { -+ totalTimeWaited = 0; -+ } -+#endif -+ } -+ } -+ return 1; -+} -+ -+ -+int -+ListenOnTCPPort(ScreenPtr pScreen, int port) -+{ -+ VNCSCREENPTR(pScreen); -+ struct sockaddr_in addr; -+ int sock; -+ int one = 1; -+ -+ memset(&addr, 0, sizeof(addr)); -+ addr.sin_family = AF_INET; -+ addr.sin_port = htons(port); -+ addr.sin_addr.s_addr = pVNC->interface.s_addr; -+ -+ if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { -+ return -1; -+ } -+ if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, -+ (char *)&one, sizeof(one)) < 0) { -+ close(sock); -+ return -1; -+ } -+ if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { -+ close(sock); -+ return -1; -+ } -+ if (listen(sock, 5) < 0) { -+ close(sock); -+ return -1; -+ } -+ -+ return sock; -+} -+ -+ -+int -+ConnectToTcpAddr(host, port) -+ char *host; -+ int port; -+{ -+ struct hostent *hp; -+ int sock, n; -+ struct sockaddr_in addr; -+ int tries = 5; -+ -+ memset(&addr, 0, sizeof(addr)); -+ addr.sin_family = AF_INET; -+ addr.sin_port = htons(port); -+ -+ if ((addr.sin_addr.s_addr = inet_addr(host)) == -1) -+ { -+ if (!(hp = gethostbyname(host))) { -+ errno = EINVAL; -+ return -1; -+ } -+ addr.sin_addr.s_addr = *(unsigned long *)hp->h_addr; -+ } -+ -+ if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { -+ return -1; -+ } -+ -+ do { -+ sock = socket(AF_INET, SOCK_STREAM, 0); -+ tries--; -+ -+ /* We really need to retry if we get EINTR, so spin */ -+ /* If after 5 attempts we're still broke, abort.... */ -+ -+ } while ((sock < 0 && errno == EINTR) && tries > 0); -+ -+ if (sock < 0) { -+ return -1; -+ } -+ -+ tries = 5; -+ -+ do { -+ n = connect(sock, (struct sockaddr *)&addr, (sizeof(addr))); -+ tries--; -+ -+ /* We really need to retry if we get EINTR, so spin */ -+ /* If after 5 attempts we're still broke, abort.... */ -+ -+ } while ((n < 0 && errno == EINTR) && tries > 0); -+ -+ if (n < 0) { -+ close(sock); -+ return -1; -+ } -+ -+ return sock; -+} -+ -+ -+int -+ListenOnUDPPort(ScreenPtr pScreen, int port) -+{ -+ VNCSCREENPTR(pScreen); -+ struct sockaddr_in addr; -+ int sock; -+ int one = 1; -+ -+ memset(&addr, 0, sizeof(addr)); -+ addr.sin_family = AF_INET; -+ addr.sin_port = htons(port); -+ addr.sin_addr.s_addr = pVNC->interface.s_addr; -+ -+ if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { -+ return -1; -+ } -+ if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, -+ (char *)&one, sizeof(one)) < 0) { -+ return -1; -+ } -+ if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { -+ return -1; -+ } -+ -+ return sock; -+} -+ -+#if 0 -+/* -+ * rdpInitSockets sets up the TCP for RDP -+ * connections. It does nothing if called again. -+ */ -+ -+Bool -+rdpInitSockets(ScreenPtr pScreen) -+{ -+ VNCSCREENPTR(pScreen); -+ -+ if ((pVNC->rdpListenSock = ListenOnTCPPort(pScreen, pVNC->rdpPort)) < 0) { -+ rfbLogPerror("ListenOnTCPPort"); -+ pVNC->rdpPort = 0; -+ return FALSE; -+ } -+ -+ rfbLog("Listening for RDP connections on TCP port %d\n", pVNC->rdpPort); -+ -+ AddEnabledDevice(pVNC->rdpListenSock); -+ -+ return TRUE; -+} -+#endif -diff --git a/hw/xfree86/vnc/sprite.h b/hw/xfree86/vnc/sprite.h -new file mode 100644 -index 0000000..ed34726 ---- /dev/null -+++ b/hw/xfree86/vnc/sprite.h -@@ -0,0 +1,141 @@ -+/* -+ * sprite.h -+ * -+ * software-sprite/sprite drawing - based on misprite -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ */ -+ -+/* -+ * 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) 1989 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. -+*/ -+ -+typedef struct { -+ Bool (*RealizeCursor)( -+ ScreenPtr /*pScreen*/, -+ CursorPtr /*pCursor*/ -+); -+ Bool (*UnrealizeCursor)( -+ ScreenPtr /*pScreen*/, -+ CursorPtr /*pCursor*/ -+); -+ Bool (*PutUpCursor)( -+ ScreenPtr /*pScreen*/, -+ CursorPtr /*pCursor*/, -+ int /*x*/, -+ int /*y*/, -+ unsigned long /*source*/, -+ unsigned long /*mask*/ -+); -+ Bool (*SaveUnderCursor)( -+ ScreenPtr /*pScreen*/, -+ int /*x*/, -+ int /*y*/, -+ int /*w*/, -+ int /*h*/ -+); -+ Bool (*RestoreUnderCursor)( -+ ScreenPtr /*pScreen*/, -+ int /*x*/, -+ int /*y*/, -+ int /*w*/, -+ int /*h*/ -+); -+ Bool (*MoveCursor)( -+ ScreenPtr /*pScreen*/, -+ CursorPtr /*pCursor*/, -+ int /*x*/, -+ int /*y*/, -+ int /*w*/, -+ int /*h*/, -+ int /*dx*/, -+ int /*dy*/, -+ unsigned long /*source*/, -+ unsigned long /*mask*/ -+); -+ Bool (*ChangeSave)( -+ ScreenPtr /*pScreen*/, -+ int /*x*/, -+ int /*y*/, -+ int /*w*/, -+ int /*h*/, -+ int /*dx*/, -+ int /*dy*/ -+); -+ -+} rfbSpriteCursorFuncRec, *rfbSpriteCursorFuncPtr; -+ -+extern Bool rfbSpriteInitialize( -+#if NeedFunctionPrototypes -+ ScreenPtr /*pScreen*/, -+ rfbSpriteCursorFuncPtr /*cursorFuncs*/, -+ miPointerScreenFuncPtr /*screenFuncs*/ -+#endif -+); -+ -+extern void rfbSpriteRestoreCursor( -+#if NeedFunctionPrototypes -+ ScreenPtr /*pScreen*/ -+#endif -+); -+ -+extern void rfbSpriteRemoveCursor( -+#if NeedFunctionPrototypes -+ ScreenPtr /*pScreen*/ -+#endif -+); -+ -+extern CursorPtr rfbSpriteGetCursorPtr( -+#if NeedFunctionPrototypes -+ ScreenPtr /*pScreen*/ -+#endif -+); -+ -+extern void rfbSpriteGetCursorPos( -+#if NeedFunctionPrototypes -+ ScreenPtr /*pScreen*/, -+ int * /*px*/, -+ int * /*py*/ -+#endif -+); -diff --git a/hw/xfree86/vnc/stats.c b/hw/xfree86/vnc/stats.c -new file mode 100644 -index 0000000..53017ee ---- /dev/null -+++ b/hw/xfree86/vnc/stats.c -@@ -0,0 +1,113 @@ -+/* -+ * stats.c -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ */ -+ -+/* -+ * Copyright (C) 2002 Constantin Kaplinsky. All Rights Reserved. -+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. -+ * -+ * This is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This software is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this software; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -+ * USA. -+ */ -+ -+#include -+#include -+#include "rfb.h" -+ -+static char* encNames[] = { -+ "raw", "copyRect", "RRE", "[encoding 3]", "CoRRE", "hextile", -+ "zlib", "tight", "[encoding 8]", "[encoding 9]" -+}; -+ -+ -+void -+rfbResetStats(rfbClientPtr cl) -+{ -+ int i; -+ for (i = 0; i < MAX_ENCODINGS; i++) { -+ cl->rfbBytesSent[i] = 0; -+ cl->rfbRectanglesSent[i] = 0; -+ } -+ cl->rfbLastRectMarkersSent = 0; -+ cl->rfbLastRectBytesSent = 0; -+ cl->rfbCursorShapeBytesSent = 0; -+ cl->rfbCursorShapeUpdatesSent = 0; -+ cl->rfbCursorPosBytesSent = 0; -+ cl->rfbCursorPosUpdatesSent = 0; -+ cl->rfbFramebufferUpdateMessagesSent = 0; -+ cl->rfbRawBytesEquivalent = 0; -+ cl->rfbKeyEventsRcvd = 0; -+ cl->rfbPointerEventsRcvd = 0; -+} -+ -+void -+rfbPrintStats(rfbClientPtr cl) -+{ -+ int i; -+ int totalRectanglesSent = 0; -+ int totalBytesSent = 0; -+ -+ rfbLog("Statistics:\n"); -+ -+ if ((cl->rfbKeyEventsRcvd != 0) || (cl->rfbPointerEventsRcvd != 0)) -+ rfbLog(" key events received %d, pointer events %d\n", -+ cl->rfbKeyEventsRcvd, cl->rfbPointerEventsRcvd); -+ -+ for (i = 0; i < MAX_ENCODINGS; i++) { -+ totalRectanglesSent += cl->rfbRectanglesSent[i]; -+ totalBytesSent += cl->rfbBytesSent[i]; -+ } -+ totalRectanglesSent += (cl->rfbCursorShapeUpdatesSent + -+ cl->rfbCursorPosUpdatesSent + -+ cl->rfbLastRectMarkersSent); -+ totalBytesSent += (cl->rfbCursorShapeBytesSent + -+ cl->rfbCursorPosBytesSent + -+ cl->rfbLastRectBytesSent); -+ -+ rfbLog(" framebuffer updates %d, rectangles %d, bytes %d\n", -+ cl->rfbFramebufferUpdateMessagesSent, totalRectanglesSent, -+ totalBytesSent); -+ -+ if (cl->rfbLastRectMarkersSent != 0) -+ rfbLog(" LastRect markers %d, bytes %d\n", -+ cl->rfbLastRectMarkersSent, cl->rfbLastRectBytesSent); -+ -+ if (cl->rfbCursorShapeUpdatesSent != 0) -+ rfbLog(" cursor shape updates %d, bytes %d\n", -+ cl->rfbCursorShapeUpdatesSent, cl->rfbCursorShapeBytesSent); -+ -+ if (cl->rfbCursorPosUpdatesSent != 0) -+ rfbLog(" cursor position updates %d, bytes %d\n", -+ cl->rfbCursorPosUpdatesSent, cl->rfbCursorPosBytesSent); -+ -+ for (i = 0; i < MAX_ENCODINGS; i++) { -+ if (cl->rfbRectanglesSent[i] != 0) -+ rfbLog(" %s rectangles %d, bytes %d\n", -+ encNames[i], cl->rfbRectanglesSent[i], cl->rfbBytesSent[i]); -+ } -+ -+ if ((totalBytesSent - cl->rfbBytesSent[rfbEncodingCopyRect]) != 0) { -+ rfbLog(" raw bytes equivalent %d, compression ratio %f\n", -+ cl->rfbRawBytesEquivalent, -+ (double)cl->rfbRawBytesEquivalent -+ / (double)(totalBytesSent - -+ cl->rfbBytesSent[rfbEncodingCopyRect] - -+ cl->rfbCursorShapeBytesSent - -+ cl->rfbCursorPosBytesSent - -+ cl->rfbLastRectBytesSent)); -+ } -+} -diff --git a/hw/xfree86/vnc/tableinitcmtemplate.c b/hw/xfree86/vnc/tableinitcmtemplate.c -new file mode 100644 -index 0000000..8a757e5 ---- /dev/null -+++ b/hw/xfree86/vnc/tableinitcmtemplate.c -@@ -0,0 +1,89 @@ -+/* -+ * tableinitcmtemplate.c - template for initialising lookup tables for -+ * translation from a colour map to true colour. -+ * -+ * This file shouldn't be compiled. It is included multiple times by -+ * translate.c, each time with a different definition of the macro OUT. -+ * For each value of OUT, this file defines a function which allocates an -+ * appropriately sized lookup table and initialises it. -+ * -+ * I know this code isn't nice to read because of all the macros, but -+ * efficiency is important here. -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ */ -+ -+/* -+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. -+ * -+ * This is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This software is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this software; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -+ * USA. -+ */ -+ -+#if !defined(OUT) -+#error "This file shouldn't be compiled." -+#error "It is included as part of translate.c" -+#endif -+ -+#define OUT_T CONCAT2E(CARD,OUT) -+#define SwapOUT(x) CONCAT2E(Swap,OUT(x)) -+#define rfbInitColourMapSingleTableOUT \ -+ CONCAT2E(rfbInitColourMapSingleTable,OUT) -+ -+static void -+rfbInitColourMapSingleTableOUT (ScreenPtr pScreen, char **table, rfbPixelFormat *in, -+ rfbPixelFormat *out) -+{ -+ VNCSCREENPTR(pScreen); -+ int i, r, g, b; -+ OUT_T *t; -+ EntryPtr pent; -+ int nEntries = 1 << in->bitsPerPixel; -+ -+ if (*table) free(*table); -+ *table = (char *)malloc(nEntries * sizeof(OUT_T)); -+ t = (OUT_T *)*table; -+ -+#if XFREE86VNC -+ pent = (EntryPtr)&miInstalledMaps[pScreen->myNum]->red[0]; -+#else -+ pent = (EntryPtr)&pVNC->rfbInstalledColormap->red[0]; -+#endif -+ -+ for (i = 0; i < nEntries; i++) { -+ 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; -+ } -+ t[i] = ((((r * out->redMax + 32767) / 65535) << out->redShift) | -+ (((g * out->greenMax + 32767) / 65535) << out->greenShift) | -+ (((b * out->blueMax + 32767) / 65535) << out->blueShift)); -+#if (OUT != 8) -+ if (out->bigEndian != in->bigEndian) { -+ t[i] = SwapOUT(t[i]); -+ } -+#endif -+ pent++; -+ } -+} -+ -+#undef OUT_T -+#undef SwapOUT -+#undef rfbInitColourMapSingleTableOUT -diff --git a/hw/xfree86/vnc/tableinittctemplate.c b/hw/xfree86/vnc/tableinittctemplate.c -new file mode 100644 -index 0000000..da8ae01 ---- /dev/null -+++ b/hw/xfree86/vnc/tableinittctemplate.c -@@ -0,0 +1,142 @@ -+/* -+ * tableinittctemplate.c - template for initialising lookup tables for -+ * truecolour to truecolour translation. -+ * -+ * This file shouldn't be compiled. It is included multiple times by -+ * translate.c, each time with a different definition of the macro OUT. -+ * For each value of OUT, this file defines two functions for initialising -+ * lookup tables. One is for truecolour translation using a single lookup -+ * table, the other is for truecolour translation using three separate -+ * lookup tables for the red, green and blue values. -+ * -+ * I know this code isn't nice to read because of all the macros, but -+ * efficiency is important here. -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ */ -+ -+/* -+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. -+ * -+ * This is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This software is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this software; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -+ * USA. -+ */ -+ -+#if !defined(OUT) -+#error "This file shouldn't be compiled." -+#error "It is included as part of translate.c" -+#endif -+ -+#define OUT_T CONCAT2E(CARD,OUT) -+#define SwapOUT(x) CONCAT2E(Swap,OUT(x)) -+#define rfbInitTrueColourSingleTableOUT \ -+ CONCAT2E(rfbInitTrueColourSingleTable,OUT) -+#define rfbInitTrueColourRGBTablesOUT CONCAT2E(rfbInitTrueColourRGBTables,OUT) -+#define rfbInitOneRGBTableOUT CONCAT2E(rfbInitOneRGBTable,OUT) -+ -+static void -+rfbInitOneRGBTableOUT (OUT_T *table, int inMax, int outMax, int outShift, -+ int swap); -+ -+ -+/* -+ * rfbInitTrueColourSingleTable sets up a single lookup table for truecolour -+ * translation. -+ */ -+ -+static void -+rfbInitTrueColourSingleTableOUT (ScreenPtr pScreen, char **table, rfbPixelFormat *in, -+ rfbPixelFormat *out) -+{ -+ int i; -+ int inRed, inGreen, inBlue, outRed, outGreen, outBlue; -+ OUT_T *t; -+ int nEntries = 1 << in->bitsPerPixel; -+ -+ if (*table) free(*table); -+ *table = (char *)malloc(nEntries * sizeof(OUT_T)); -+ t = (OUT_T *)*table; -+ -+ for (i = 0; i < nEntries; i++) { -+ inRed = (i >> in->redShift) & in->redMax; -+ inGreen = (i >> in->greenShift) & in->greenMax; -+ inBlue = (i >> in->blueShift) & in->blueMax; -+ -+ outRed = (inRed * out->redMax + in->redMax / 2) / in->redMax; -+ outGreen = (inGreen * out->greenMax + in->greenMax / 2) / in->greenMax; -+ outBlue = (inBlue * out->blueMax + in->blueMax / 2) / in->blueMax; -+ -+ t[i] = ((outRed << out->redShift) | -+ (outGreen << out->greenShift) | -+ (outBlue << out->blueShift)); -+#if (OUT != 8) -+ if (out->bigEndian != in->bigEndian) { -+ t[i] = SwapOUT(t[i]); -+ } -+#endif -+ } -+} -+ -+ -+/* -+ * rfbInitTrueColourRGBTables sets up three separate lookup tables for the -+ * red, green and blue values. -+ */ -+ -+static void -+rfbInitTrueColourRGBTablesOUT (ScreenPtr pScreen, char **table, rfbPixelFormat *in, -+ rfbPixelFormat *out) -+{ -+ OUT_T *redTable; -+ OUT_T *greenTable; -+ OUT_T *blueTable; -+ -+ if (*table) free(*table); -+ *table = (char *)malloc((in->redMax + in->greenMax + in->blueMax + 3) -+ * sizeof(OUT_T)); -+ redTable = (OUT_T *)*table; -+ greenTable = redTable + in->redMax + 1; -+ blueTable = greenTable + in->greenMax + 1; -+ -+ rfbInitOneRGBTableOUT (redTable, in->redMax, out->redMax, -+ out->redShift, (out->bigEndian != in->bigEndian)); -+ rfbInitOneRGBTableOUT (greenTable, in->greenMax, out->greenMax, -+ out->greenShift, (out->bigEndian != in->bigEndian)); -+ rfbInitOneRGBTableOUT (blueTable, in->blueMax, out->blueMax, -+ out->blueShift, (out->bigEndian != in->bigEndian)); -+} -+ -+static void -+rfbInitOneRGBTableOUT (OUT_T *table, int inMax, int outMax, int outShift, -+ int swap) -+{ -+ int i; -+ int nEntries = inMax + 1; -+ -+ for (i = 0; i < nEntries; i++) { -+ table[i] = ((i * outMax + inMax / 2) / inMax) << outShift; -+#if (OUT != 8) -+ if (swap) { -+ table[i] = SwapOUT(table[i]); -+ } -+#endif -+ } -+} -+ -+#undef OUT_T -+#undef SwapOUT -+#undef rfbInitTrueColourSingleTableOUT -+#undef rfbInitTrueColourRGBTablesOUT -+#undef rfbInitOneRGBTableOUT -diff --git a/hw/xfree86/vnc/tabletranstemplate.c b/hw/xfree86/vnc/tabletranstemplate.c -new file mode 100644 -index 0000000..87cfcba ---- /dev/null -+++ b/hw/xfree86/vnc/tabletranstemplate.c -@@ -0,0 +1,119 @@ -+/* -+ * tabletranstemplate.c - template for translation using lookup tables. -+ * -+ * This file shouldn't be compiled. It is included multiple times by -+ * translate.c, each time with different definitions of the macros IN and OUT. -+ * -+ * For each pair of values IN and OUT, this file defines two functions for -+ * translating a given rectangle of pixel data. One uses a single lookup -+ * table, and the other uses three separate lookup tables for the red, green -+ * and blue values. -+ * -+ * I know this code isn't nice to read because of all the macros, but -+ * efficiency is important here. -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ */ -+ -+/* -+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. -+ * -+ * This is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This software is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this software; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -+ * USA. -+ */ -+ -+#if !defined(IN) || !defined(OUT) -+#error "This file shouldn't be compiled." -+#error "It is included as part of translate.c" -+#endif -+ -+#define IN_T CONCAT2E(CARD,IN) -+#define OUT_T CONCAT2E(CARD,OUT) -+#define rfbTranslateWithSingleTableINtoOUT \ -+ CONCAT4E(rfbTranslateWithSingleTable,IN,to,OUT) -+#define rfbTranslateWithRGBTablesINtoOUT \ -+ CONCAT4E(rfbTranslateWithRGBTables,IN,to,OUT) -+ -+/* -+ * rfbTranslateWithSingleTableINtoOUT translates a rectangle of pixel data -+ * using a single lookup table. -+ */ -+ -+static void -+rfbTranslateWithSingleTableINtoOUT (ScreenPtr pScreen, char *table, rfbPixelFormat *in, -+ rfbPixelFormat *out, -+ unsigned char *iptr, char *optr, -+ int bytesBetweenInputLines, -+ int width, int height, -+ int x, int y) -+{ -+ IN_T *ip = (IN_T *)iptr; -+ OUT_T *op = (OUT_T *)optr; -+ int ipextra = bytesBetweenInputLines / sizeof(IN_T) - width; -+ OUT_T *opLineEnd; -+ OUT_T *t = (OUT_T *)table; -+ -+ while (height > 0) { -+ opLineEnd = op + width; -+ -+ while (op < opLineEnd) { -+ *(op++) = t[*(ip++)]; -+ } -+ -+ ip += ipextra; -+ height--; -+ } -+} -+ -+ -+/* -+ * rfbTranslateWithRGBTablesINtoOUT translates a rectangle of pixel data -+ * using three separate lookup tables for the red, green and blue values. -+ */ -+ -+static void -+rfbTranslateWithRGBTablesINtoOUT (ScreenPtr pScreen, char *table, rfbPixelFormat *in, -+ rfbPixelFormat *out, -+ unsigned char *iptr, char *optr, -+ int bytesBetweenInputLines, -+ int width, int height, -+ int x, int y) -+{ -+ IN_T *ip = (IN_T *)iptr; -+ OUT_T *op = (OUT_T *)optr; -+ int ipextra = bytesBetweenInputLines / sizeof(IN_T) - width; -+ OUT_T *opLineEnd; -+ OUT_T *redTable = (OUT_T *)table; -+ OUT_T *greenTable = redTable + in->redMax + 1; -+ OUT_T *blueTable = greenTable + in->greenMax + 1; -+ -+ while (height > 0) { -+ opLineEnd = op + width; -+ -+ while (op < opLineEnd) { -+ *(op++) = (redTable[(*ip >> in->redShift) & in->redMax] | -+ greenTable[(*ip >> in->greenShift) & in->greenMax] | -+ blueTable[(*ip >> in->blueShift) & in->blueMax]); -+ ip++; -+ } -+ ip += ipextra; -+ height--; -+ } -+} -+ -+#undef IN_T -+#undef OUT_T -+#undef rfbTranslateWithSingleTableINtoOUT -+#undef rfbTranslateWithRGBTablesINtoOUT -diff --git a/hw/xfree86/vnc/tight.c b/hw/xfree86/vnc/tight.c -new file mode 100644 -index 0000000..d4b25ec ---- /dev/null -+++ b/hw/xfree86/vnc/tight.c -@@ -0,0 +1,1831 @@ -+/* -+ * tight.c -+ * -+ * Routines to implement Tight Encoding -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ */ -+ -+/* -+ * Copyright (C) 2000, 2001 Const Kaplinsky. All Rights Reserved. -+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. -+ * -+ * This is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This software is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this software; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -+ * USA. -+ */ -+ -+#ifdef HAVE_XORG_CONFIG_H -+#include -+#endif -+ -+#include -+#include -+#include -+#include -+#include "rfb.h" -+#include -+ -+ -+/* Note: The following constant should not be changed. */ -+#define TIGHT_MIN_TO_COMPRESS 12 -+ -+/* The parameters below may be adjusted. */ -+#define MIN_SPLIT_RECT_SIZE 4096 -+#define MIN_SOLID_SUBRECT_SIZE 2048 -+#define MAX_SPLIT_TILE_SIZE 16 -+ -+/* May be set to TRUE with "-lazytight" Xvnc option. */ -+Bool rfbTightDisableGradient = FALSE; -+ -+/* This variable is set on every rfbSendRectEncodingTight() call. */ -+static Bool usePixelFormat24; -+ -+ -+/* Compression level stuff. The following array contains various -+ encoder parameters for each of 10 compression levels (0..9). -+ Last three parameters correspond to JPEG quality levels (0..9). */ -+ -+typedef struct TIGHT_CONF_s { -+ int maxRectSize, maxRectWidth; -+ int monoMinRectSize, gradientMinRectSize; -+ int idxZlibLevel, monoZlibLevel, rawZlibLevel, gradientZlibLevel; -+ int gradientThreshold, gradientThreshold24; -+ int idxMaxColorsDivisor; -+ int jpegQuality, jpegThreshold, jpegThreshold24; -+} TIGHT_CONF; -+ -+static TIGHT_CONF tightConf[10] = { -+ { 512, 32, 6, 65536, 0, 0, 0, 0, 0, 0, 4, 5, 10000, 23000 }, -+ { 2048, 128, 6, 65536, 1, 1, 1, 0, 0, 0, 8, 10, 8000, 18000 }, -+ { 6144, 256, 8, 65536, 3, 3, 2, 0, 0, 0, 24, 15, 6500, 15000 }, -+ { 10240, 1024, 12, 65536, 5, 5, 3, 0, 0, 0, 32, 25, 5000, 12000 }, -+ { 16384, 2048, 12, 65536, 6, 6, 4, 0, 0, 0, 32, 37, 4000, 10000 }, -+ { 32768, 2048, 12, 4096, 7, 7, 5, 4, 150, 380, 32, 50, 3000, 8000 }, -+ { 65536, 2048, 16, 4096, 7, 7, 6, 4, 170, 420, 48, 60, 2000, 5000 }, -+ { 65536, 2048, 16, 4096, 8, 8, 7, 5, 180, 450, 64, 70, 1000, 2500 }, -+ { 65536, 2048, 32, 8192, 9, 9, 8, 6, 190, 475, 64, 75, 500, 1200 }, -+ { 65536, 2048, 32, 8192, 9, 9, 9, 6, 200, 500, 96, 80, 200, 500 } -+}; -+ -+/* Stuff dealing with palettes. */ -+ -+typedef struct COLOR_LIST_s { -+ struct COLOR_LIST_s *next; -+ int idx; -+ CARD32 rgb; -+} COLOR_LIST; -+ -+typedef struct PALETTE_ENTRY_s { -+ COLOR_LIST *listNode; -+ int numPixels; -+} PALETTE_ENTRY; -+ -+typedef struct PALETTE_s { -+ PALETTE_ENTRY entry[256]; -+ COLOR_LIST *hash[256]; -+ COLOR_LIST list[256]; -+} PALETTE; -+ -+static int paletteNumColors, paletteMaxColors; -+static CARD32 monoBackground, monoForeground; -+static PALETTE palette; -+ -+/* Pointers to dynamically-allocated buffers. */ -+ -+static int tightBeforeBufSize = 0; -+static char *tightBeforeBuf = NULL; -+ -+static int tightAfterBufSize = 0; -+static char *tightAfterBuf = NULL; -+ -+static int *prevRowBuf = NULL; -+ -+ -+/* Prototypes for static functions. */ -+ -+static void FindBestSolidArea (ScreenPtr pScreen, int x, int y, int w, int h, -+ CARD32 colorValue, int *w_ptr, int *h_ptr); -+static void ExtendSolidArea (ScreenPtr pScreen, int x, int y, int w, int h, -+ CARD32 colorValue, -+ int *x_ptr, int *y_ptr, int *w_ptr, int *h_ptr); -+static Bool CheckSolidTile (ScreenPtr pScreen, int x, int y, int w, int h, -+ CARD32 *colorPtr, Bool needSameColor); -+static Bool CheckSolidTile8 (ScreenPtr pScreen, int x, int y, int w, int h, -+ CARD32 *colorPtr, Bool needSameColor); -+static Bool CheckSolidTile16 (ScreenPtr pScreen, int x, int y, int w, int h, -+ CARD32 *colorPtr, Bool needSameColor); -+static Bool CheckSolidTile32 (ScreenPtr pScreen, int x, int y, int w, int h, -+ CARD32 *colorPtr, Bool needSameColor); -+ -+static Bool SendRectSimple (rfbClientPtr cl, int x, int y, int w, int h); -+static Bool SendSubrect (rfbClientPtr cl, int x, int y, int w, int h); -+static Bool SendTightHeader (rfbClientPtr cl, int x, int y, int w, int h); -+ -+static Bool SendSolidRect (rfbClientPtr cl); -+static Bool SendMonoRect (rfbClientPtr cl, int w, int h); -+static Bool SendIndexedRect (rfbClientPtr cl, int w, int h); -+static Bool SendFullColorRect (rfbClientPtr cl, int w, int h); -+static Bool SendGradientRect (rfbClientPtr cl, int w, int h); -+ -+static Bool CompressData(rfbClientPtr cl, int streamId, int dataLen, -+ int zlibLevel, int zlibStrategy); -+static Bool SendCompressedData(rfbClientPtr cl, int compressedLen); -+ -+static void FillPalette8(int count); -+static void FillPalette16(int count); -+static void FillPalette32(int count); -+ -+static void PaletteReset(void); -+static int PaletteInsert(CARD32 rgb, int numPixels, int bpp); -+ -+static void Pack24(ScreenPtr pScreen, char *buf, rfbPixelFormat *fmt, int count); -+ -+static void EncodeIndexedRect16(CARD8 *buf, int count); -+static void EncodeIndexedRect32(CARD8 *buf, int count); -+ -+static void EncodeMonoRect8(CARD8 *buf, int w, int h); -+static void EncodeMonoRect16(CARD8 *buf, int w, int h); -+static void EncodeMonoRect32(CARD8 *buf, int w, int h); -+ -+static void FilterGradient24(ScreenPtr pScreen, char *buf, rfbPixelFormat *fmt, int w, int h); -+static void FilterGradient16(ScreenPtr pScreen, CARD16 *buf, rfbPixelFormat *fmt, int w, int h); -+static void FilterGradient32(ScreenPtr pScreen, CARD32 *buf, rfbPixelFormat *fmt, int w, int h); -+ -+static int DetectSmoothImage(rfbClientPtr cl, rfbPixelFormat *fmt, int w, int h); -+static unsigned long DetectSmoothImage24(rfbClientPtr cl, rfbPixelFormat *fmt, int w, int h); -+static unsigned long DetectSmoothImage16(rfbClientPtr cl, rfbPixelFormat *fmt, int w, int h); -+static unsigned long DetectSmoothImage32(rfbClientPtr cl, rfbPixelFormat *fmt, int w, int h); -+ -+static Bool SendJpegRect(rfbClientPtr cl, int x, int y, int w, int h, -+ int quality); -+static void PrepareRowForJpeg(ScreenPtr pScreen, CARD8 *dst, int x, int y, int count); -+static void PrepareRowForJpeg24(ScreenPtr pScreen, CARD8 *dst, int x, int y, int count); -+static void PrepareRowForJpeg16(ScreenPtr pScreen, CARD8 *dst, int x, int y, int count); -+static void PrepareRowForJpeg32(ScreenPtr pScreen, CARD8 *dst, int x, int y, int count); -+ -+static void JpegInitDestination(j_compress_ptr cinfo); -+static boolean JpegEmptyOutputBuffer(j_compress_ptr cinfo); -+static void JpegTermDestination(j_compress_ptr cinfo); -+static void JpegSetDstManager(j_compress_ptr cinfo); -+ -+ -+/* -+ * Tight encoding implementation. -+ */ -+ -+int -+rfbNumCodedRectsTight(cl, x, y, w, h) -+ rfbClientPtr cl; -+ int x, y, w, h; -+{ -+ int maxRectSize, maxRectWidth; -+ int subrectMaxWidth, subrectMaxHeight; -+ -+ /* No matter how many rectangles we will send if LastRect markers -+ are used to terminate rectangle stream. */ -+ if (cl->enableLastRectEncoding && w * h >= MIN_SPLIT_RECT_SIZE) -+ return 0; -+ -+ maxRectSize = tightConf[cl->tightCompressLevel].maxRectSize; -+ maxRectWidth = tightConf[cl->tightCompressLevel].maxRectWidth; -+ -+ if (w > maxRectWidth || w * h > maxRectSize) { -+ subrectMaxWidth = (w > maxRectWidth) ? maxRectWidth : w; -+ subrectMaxHeight = maxRectSize / subrectMaxWidth; -+ return (((w - 1) / maxRectWidth + 1) * -+ ((h - 1) / subrectMaxHeight + 1)); -+ } else { -+ return 1; -+ } -+} -+ -+Bool -+rfbSendRectEncodingTight(cl, x, y, w, h) -+ rfbClientPtr cl; -+ int x, y, w, h; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ int nMaxRows; -+ CARD32 colorValue; -+ int dx, dy, dw, dh; -+ int x_best, y_best, w_best, h_best; -+ unsigned char *fbptr; -+ -+ if ( cl->format.depth == 24 && cl->format.redMax == 0xFF && -+ cl->format.greenMax == 0xFF && cl->format.blueMax == 0xFF ) { -+ usePixelFormat24 = TRUE; -+ } else { -+ usePixelFormat24 = FALSE; -+ } -+ -+ if (!cl->enableLastRectEncoding || w * h < MIN_SPLIT_RECT_SIZE) -+ return SendRectSimple(cl, x, y, w, h); -+ -+ /* Make sure we can write at least one pixel into tightBeforeBuf. */ -+ -+ if (tightBeforeBufSize < 4) { -+ tightBeforeBufSize = 4; -+ if (tightBeforeBuf == NULL) -+ tightBeforeBuf = (char *)xalloc(tightBeforeBufSize); -+ else -+ tightBeforeBuf = (char *)xrealloc(tightBeforeBuf, -+ tightBeforeBufSize); -+ } -+ -+ /* Calculate maximum number of rows in one non-solid rectangle. */ -+ -+ { -+ int maxRectSize, maxRectWidth, nMaxWidth; -+ -+ maxRectSize = tightConf[cl->tightCompressLevel].maxRectSize; -+ maxRectWidth = tightConf[cl->tightCompressLevel].maxRectWidth; -+ nMaxWidth = (w > maxRectWidth) ? maxRectWidth : w; -+ nMaxRows = maxRectSize / nMaxWidth; -+ } -+ -+ /* Try to find large solid-color areas and send them separately. */ -+ -+ for (dy = y; dy < y + h; dy += MAX_SPLIT_TILE_SIZE) { -+ -+ /* If a rectangle becomes too large, send its upper part now. */ -+ -+ if (dy - y >= nMaxRows) { -+ if (!SendRectSimple(cl, x, y, w, nMaxRows)) -+ return 0; -+ y += nMaxRows; -+ h -= nMaxRows; -+ } -+ -+ dh = (dy + MAX_SPLIT_TILE_SIZE <= y + h) ? -+ MAX_SPLIT_TILE_SIZE : (y + h - dy); -+ -+ for (dx = x; dx < x + w; dx += MAX_SPLIT_TILE_SIZE) { -+ -+ dw = (dx + MAX_SPLIT_TILE_SIZE <= x + w) ? -+ MAX_SPLIT_TILE_SIZE : (x + w - dx); -+ -+ if (CheckSolidTile(cl->pScreen, dx, dy, dw, dh, &colorValue, FALSE)) { -+ -+ /* Get dimensions of solid-color area. */ -+ -+ FindBestSolidArea(cl->pScreen, dx, dy, w - (dx - x), h - (dy - y), -+ colorValue, &w_best, &h_best); -+ -+ /* Make sure a solid rectangle is large enough -+ (or the whole rectangle is of the same color). */ -+ -+ if ( w_best * h_best != w * h && -+ w_best * h_best < MIN_SOLID_SUBRECT_SIZE ) -+ continue; -+ -+ /* Try to extend solid rectangle to maximum size. */ -+ -+ x_best = dx; y_best = dy; -+ ExtendSolidArea(cl->pScreen, x, y, w, h, colorValue, -+ &x_best, &y_best, &w_best, &h_best); -+ -+ /* Send rectangles at top and left to solid-color area. */ -+ -+ if ( y_best != y && -+ !SendRectSimple(cl, x, y, w, y_best-y) ) -+ return FALSE; -+ if ( x_best != x && -+ !rfbSendRectEncodingTight(cl, x, y_best, -+ x_best-x, h_best) ) -+ return FALSE; -+ -+ /* Send solid-color rectangle. */ -+ -+ if (!SendTightHeader(cl, x_best, y_best, w_best, h_best)) -+ return FALSE; -+ -+ fbptr = (pVNC->pfbMemory + -+ (pVNC->paddedWidthInBytes * y_best) + -+ (x_best * (pVNC->bitsPerPixel / 8))); -+ -+ (*cl->translateFn)(cl->pScreen, cl->translateLookupTable, -+ &pVNC->rfbServerFormat, -+ &cl->format, fbptr, tightBeforeBuf, -+ pVNC->paddedWidthInBytes, 1, 1, -+ x_best, y_best); -+ -+ if (!SendSolidRect(cl)) -+ return FALSE; -+ -+ /* Send remaining rectangles (at right and bottom). */ -+ -+ if ( x_best + w_best != x + w && -+ !rfbSendRectEncodingTight(cl, x_best+w_best, y_best, -+ w-(x_best-x)-w_best, h_best) ) -+ return FALSE; -+ if ( y_best + h_best != y + h && -+ !rfbSendRectEncodingTight(cl, x, y_best+h_best, -+ w, h-(y_best-y)-h_best) ) -+ return FALSE; -+ -+ /* Return after all recursive calls are done. */ -+ -+ return TRUE; -+ } -+ -+ } -+ -+ } -+ -+ /* No suitable solid-color rectangles found. */ -+ -+ return SendRectSimple(cl, x, y, w, h); -+} -+ -+static void -+FindBestSolidArea(pScreen, x, y, w, h, colorValue, w_ptr, h_ptr) -+ ScreenPtr pScreen; -+ int x, y, w, h; -+ CARD32 colorValue; -+ int *w_ptr, *h_ptr; -+{ -+ int dx, dy, dw, dh; -+ int w_prev; -+ int w_best = 0, h_best = 0; -+ -+ w_prev = w; -+ -+ for (dy = y; dy < y + h; dy += MAX_SPLIT_TILE_SIZE) { -+ -+ dh = (dy + MAX_SPLIT_TILE_SIZE <= y + h) ? -+ MAX_SPLIT_TILE_SIZE : (y + h - dy); -+ dw = (w_prev > MAX_SPLIT_TILE_SIZE) ? -+ MAX_SPLIT_TILE_SIZE : w_prev; -+ -+ if (!CheckSolidTile(pScreen, x, dy, dw, dh, &colorValue, TRUE)) -+ break; -+ -+ for (dx = x + dw; dx < x + w_prev;) { -+ dw = (dx + MAX_SPLIT_TILE_SIZE <= x + w_prev) ? -+ MAX_SPLIT_TILE_SIZE : (x + w_prev - dx); -+ if (!CheckSolidTile(pScreen, dx, dy, dw, dh, &colorValue, TRUE)) -+ break; -+ dx += dw; -+ } -+ -+ w_prev = dx - x; -+ if (w_prev * (dy + dh - y) > w_best * h_best) { -+ w_best = w_prev; -+ h_best = dy + dh - y; -+ } -+ } -+ -+ *w_ptr = w_best; -+ *h_ptr = h_best; -+} -+ -+static void -+ExtendSolidArea(pScreen, x, y, w, h, colorValue, x_ptr, y_ptr, w_ptr, h_ptr) -+ ScreenPtr pScreen; -+ int x, y, w, h; -+ CARD32 colorValue; -+ int *x_ptr, *y_ptr, *w_ptr, *h_ptr; -+{ -+ int cx, cy; -+ -+ /* Try to extend the area upwards. */ -+ for ( cy = *y_ptr - 1; -+ cy >= y && CheckSolidTile(pScreen, *x_ptr, cy, *w_ptr, 1, &colorValue, TRUE); -+ cy-- ); -+ *h_ptr += *y_ptr - (cy + 1); -+ *y_ptr = cy + 1; -+ -+ /* ... downwards. */ -+ for ( cy = *y_ptr + *h_ptr; -+ cy < y + h && -+ CheckSolidTile(pScreen, *x_ptr, cy, *w_ptr, 1, &colorValue, TRUE); -+ cy++ ); -+ *h_ptr += cy - (*y_ptr + *h_ptr); -+ -+ /* ... to the left. */ -+ for ( cx = *x_ptr - 1; -+ cx >= x && CheckSolidTile(pScreen, cx, *y_ptr, 1, *h_ptr, &colorValue, TRUE); -+ cx-- ); -+ *w_ptr += *x_ptr - (cx + 1); -+ *x_ptr = cx + 1; -+ -+ /* ... to the right. */ -+ for ( cx = *x_ptr + *w_ptr; -+ cx < x + w && -+ CheckSolidTile(pScreen, cx, *y_ptr, 1, *h_ptr, &colorValue, TRUE); -+ cx++ ); -+ *w_ptr += cx - (*x_ptr + *w_ptr); -+} -+ -+/* -+ * Check if a rectangle is all of the same color. If needSameColor is -+ * set to non-zero, then also check that its color equals to the -+ * *colorPtr value. The result is 1 if the test is successfull, and in -+ * that case new color will be stored in *colorPtr. -+ */ -+ -+static Bool -+CheckSolidTile(pScreen, x, y, w, h, colorPtr, needSameColor) -+ ScreenPtr pScreen; -+ int x, y, w, h; -+ CARD32 *colorPtr; -+ Bool needSameColor; -+{ -+ VNCSCREENPTR(pScreen); -+ switch(pVNC->rfbServerFormat.bitsPerPixel) { -+ case 32: -+ return CheckSolidTile32(pScreen, x, y, w, h, colorPtr, needSameColor); -+ case 16: -+ return CheckSolidTile16(pScreen, x, y, w, h, colorPtr, needSameColor); -+ default: -+ return CheckSolidTile8(pScreen, x, y, w, h, colorPtr, needSameColor); -+ } -+} -+ -+#define DEFINE_CHECK_SOLID_FUNCTION(bpp) \ -+ \ -+static Bool \ -+CheckSolidTile##bpp(pScreen, x, y, w, h, colorPtr, needSameColor) \ -+ ScreenPtr pScreen; \ -+ int x, y; \ -+ CARD32 *colorPtr; \ -+ Bool needSameColor; \ -+{ \ -+ VNCSCREENPTR(pScreen); \ -+ CARD##bpp *fbptr; \ -+ CARD##bpp colorValue; \ -+ int dx, dy; \ -+ \ -+ fbptr = (CARD##bpp *) \ -+ &pVNC->pfbMemory[y * pVNC->paddedWidthInBytes + x * (bpp/8)]; \ -+ \ -+ colorValue = *fbptr; \ -+ if (needSameColor && (CARD32)colorValue != *colorPtr) \ -+ return FALSE; \ -+ \ -+ for (dy = 0; dy < h; dy++) { \ -+ for (dx = 0; dx < w; dx++) { \ -+ if (colorValue != fbptr[dx]) \ -+ return FALSE; \ -+ } \ -+ fbptr = (CARD##bpp *)((CARD8 *)fbptr + pVNC->paddedWidthInBytes); \ -+ } \ -+ \ -+ *colorPtr = (CARD32)colorValue; \ -+ return TRUE; \ -+} -+ -+DEFINE_CHECK_SOLID_FUNCTION(8) -+DEFINE_CHECK_SOLID_FUNCTION(16) -+DEFINE_CHECK_SOLID_FUNCTION(32) -+ -+static Bool -+SendRectSimple(cl, x, y, w, h) -+ rfbClientPtr cl; -+ int x, y, w, h; -+{ -+ int maxBeforeSize, maxAfterSize; -+ int maxRectSize, maxRectWidth; -+ int subrectMaxWidth, subrectMaxHeight; -+ int dx, dy; -+ int rw, rh; -+ -+ maxRectSize = tightConf[cl->tightCompressLevel].maxRectSize; -+ maxRectWidth = tightConf[cl->tightCompressLevel].maxRectWidth; -+ -+ maxBeforeSize = maxRectSize * (cl->format.bitsPerPixel / 8); -+ maxAfterSize = maxBeforeSize + (maxBeforeSize + 99) / 100 + 12; -+ -+ if (tightBeforeBufSize < maxBeforeSize) { -+ tightBeforeBufSize = maxBeforeSize; -+ if (tightBeforeBuf == NULL) -+ tightBeforeBuf = (char *)xalloc(tightBeforeBufSize); -+ else -+ tightBeforeBuf = (char *)xrealloc(tightBeforeBuf, -+ tightBeforeBufSize); -+ } -+ -+ if (tightAfterBufSize < maxAfterSize) { -+ tightAfterBufSize = maxAfterSize; -+ if (tightAfterBuf == NULL) -+ tightAfterBuf = (char *)xalloc(tightAfterBufSize); -+ else -+ tightAfterBuf = (char *)xrealloc(tightAfterBuf, -+ tightAfterBufSize); -+ } -+ -+ if (w > maxRectWidth || w * h > maxRectSize) { -+ subrectMaxWidth = (w > maxRectWidth) ? maxRectWidth : w; -+ subrectMaxHeight = maxRectSize / subrectMaxWidth; -+ -+ for (dy = 0; dy < h; dy += subrectMaxHeight) { -+ for (dx = 0; dx < w; dx += maxRectWidth) { -+ rw = (dx + maxRectWidth < w) ? maxRectWidth : w - dx; -+ rh = (dy + subrectMaxHeight < h) ? subrectMaxHeight : h - dy; -+ if (!SendSubrect(cl, x+dx, y+dy, rw, rh)) -+ return FALSE; -+ } -+ } -+ } else { -+ if (!SendSubrect(cl, x, y, w, h)) -+ return FALSE; -+ } -+ -+ return TRUE; -+} -+ -+static Bool -+SendSubrect(cl, x, y, w, h) -+ rfbClientPtr cl; -+ int x, y, w, h; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ unsigned char *fbptr; -+ Bool success = FALSE; -+ -+ /* Send pending data if there is more than 128 bytes. */ -+ if (pVNC->ublen > 128) { -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ } -+ -+ if (!SendTightHeader(cl, x, y, w, h)) -+ return FALSE; -+ -+ fbptr = (pVNC->pfbMemory + (pVNC->paddedWidthInBytes * y) -+ + (x * (pVNC->bitsPerPixel / 8))); -+ -+ (*cl->translateFn)(cl->pScreen, cl->translateLookupTable, &pVNC->rfbServerFormat, -+ &cl->format, fbptr, tightBeforeBuf, -+ pVNC->paddedWidthInBytes, w, h, x, y); -+ -+ paletteMaxColors = w * h / tightConf[cl->tightCompressLevel].idxMaxColorsDivisor; -+ if ( paletteMaxColors < 2 && -+ w * h >= tightConf[cl->tightCompressLevel].monoMinRectSize ) { -+ paletteMaxColors = 2; -+ } -+ switch (cl->format.bitsPerPixel) { -+ case 8: -+ FillPalette8(w * h); -+ break; -+ case 16: -+ FillPalette16(w * h); -+ break; -+ default: -+ FillPalette32(w * h); -+ } -+ -+ switch (paletteNumColors) { -+ case 0: -+ /* Truecolor image */ -+ if (DetectSmoothImage(cl, &cl->format, w, h)) { -+ if (cl->tightQualityLevel != -1) { -+ success = SendJpegRect(cl, x, y, w, h, -+ tightConf[cl->tightQualityLevel].jpegQuality); -+ } else { -+ success = SendGradientRect(cl, w, h); -+ } -+ } else { -+ success = SendFullColorRect(cl, w, h); -+ } -+ break; -+ case 1: -+ /* Solid rectangle */ -+ success = SendSolidRect(cl); -+ break; -+ case 2: -+ /* Two-color rectangle */ -+ success = SendMonoRect(cl, w, h); -+ break; -+ default: -+ /* Up to 256 different colors */ -+ if ( paletteNumColors > 96 && -+ cl->tightQualityLevel != -1 && cl->tightQualityLevel <= 3 && -+ DetectSmoothImage(cl, &cl->format, w, h) ) { -+ success = SendJpegRect(cl, x, y, w, h, -+ tightConf[cl->tightQualityLevel].jpegQuality); -+ } else { -+ success = SendIndexedRect(cl, w, h); -+ } -+ } -+ return success; -+} -+ -+static Bool -+SendTightHeader(cl, x, y, w, h) -+ rfbClientPtr cl; -+ int x, y, w, h; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ rfbFramebufferUpdateRectHeader rect; -+ -+ if (pVNC->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) { -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ } -+ -+ rect.r.x = Swap16IfLE(x); -+ rect.r.y = Swap16IfLE(y); -+ rect.r.w = Swap16IfLE(w); -+ rect.r.h = Swap16IfLE(h); -+ rect.encoding = Swap32IfLE(rfbEncodingTight); -+ -+ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&rect, -+ sz_rfbFramebufferUpdateRectHeader); -+ pVNC->ublen += sz_rfbFramebufferUpdateRectHeader; -+ -+ cl->rfbRectanglesSent[rfbEncodingTight]++; -+ cl->rfbBytesSent[rfbEncodingTight] += sz_rfbFramebufferUpdateRectHeader; -+ -+ return TRUE; -+} -+ -+/* -+ * Subencoding implementations. -+ */ -+ -+static Bool -+SendSolidRect(cl) -+ rfbClientPtr cl; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ int len; -+ -+ if (usePixelFormat24) { -+ Pack24(cl->pScreen, tightBeforeBuf, &cl->format, 1); -+ len = 3; -+ } else -+ len = cl->format.bitsPerPixel / 8; -+ -+ if (pVNC->ublen + 1 + len > UPDATE_BUF_SIZE) { -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ } -+ -+ pVNC->updateBuf[pVNC->ublen++] = (char)(rfbTightFill << 4); -+ memcpy (&pVNC->updateBuf[pVNC->ublen], tightBeforeBuf, len); -+ pVNC->ublen += len; -+ -+ cl->rfbBytesSent[rfbEncodingTight] += len + 1; -+ -+ return TRUE; -+} -+ -+static Bool -+SendMonoRect(cl, w, h) -+ rfbClientPtr cl; -+ int w, h; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ int streamId = 1; -+ int paletteLen, dataLen; -+ -+ if ( (pVNC->ublen + TIGHT_MIN_TO_COMPRESS + 6 + -+ 2 * cl->format.bitsPerPixel / 8) > UPDATE_BUF_SIZE ) { -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ } -+ -+ /* Prepare tight encoding header. */ -+ dataLen = (w + 7) / 8; -+ dataLen *= h; -+ -+ pVNC->updateBuf[pVNC->ublen++] = (streamId | rfbTightExplicitFilter) << 4; -+ pVNC->updateBuf[pVNC->ublen++] = rfbTightFilterPalette; -+ pVNC->updateBuf[pVNC->ublen++] = 1; -+ -+ /* Prepare palette, convert image. */ -+ switch (cl->format.bitsPerPixel) { -+ -+ case 32: -+ EncodeMonoRect32((CARD8 *)tightBeforeBuf, w, h); -+ -+ ((CARD32 *)tightAfterBuf)[0] = monoBackground; -+ ((CARD32 *)tightAfterBuf)[1] = monoForeground; -+ if (usePixelFormat24) { -+ Pack24(cl->pScreen, tightAfterBuf, &cl->format, 2); -+ paletteLen = 6; -+ } else -+ paletteLen = 8; -+ -+ memcpy(&pVNC->updateBuf[pVNC->ublen], tightAfterBuf, paletteLen); -+ pVNC->ublen += paletteLen; -+ cl->rfbBytesSent[rfbEncodingTight] += 3 + paletteLen; -+ break; -+ -+ case 16: -+ EncodeMonoRect16((CARD8 *)tightBeforeBuf, w, h); -+ -+ ((CARD16 *)tightAfterBuf)[0] = (CARD16)monoBackground; -+ ((CARD16 *)tightAfterBuf)[1] = (CARD16)monoForeground; -+ -+ memcpy(&pVNC->updateBuf[pVNC->ublen], tightAfterBuf, 4); -+ pVNC->ublen += 4; -+ cl->rfbBytesSent[rfbEncodingTight] += 7; -+ break; -+ -+ default: -+ EncodeMonoRect8((CARD8 *)tightBeforeBuf, w, h); -+ -+ pVNC->updateBuf[pVNC->ublen++] = (char)monoBackground; -+ pVNC->updateBuf[pVNC->ublen++] = (char)monoForeground; -+ cl->rfbBytesSent[rfbEncodingTight] += 5; -+ } -+ -+ return CompressData(cl, streamId, dataLen, -+ tightConf[cl->tightCompressLevel].monoZlibLevel, -+ Z_DEFAULT_STRATEGY); -+} -+ -+static Bool -+SendIndexedRect(cl, w, h) -+ rfbClientPtr cl; -+ int w, h; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ int streamId = 2; -+ int i, entryLen; -+ -+ if ( (pVNC->ublen + TIGHT_MIN_TO_COMPRESS + 6 + -+ paletteNumColors * cl->format.bitsPerPixel / 8) > UPDATE_BUF_SIZE ) { -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ } -+ -+ /* Prepare tight encoding header. */ -+ pVNC->updateBuf[pVNC->ublen++] = (streamId | rfbTightExplicitFilter) << 4; -+ pVNC->updateBuf[pVNC->ublen++] = rfbTightFilterPalette; -+ pVNC->updateBuf[pVNC->ublen++] = (char)(paletteNumColors - 1); -+ -+ /* Prepare palette, convert image. */ -+ switch (cl->format.bitsPerPixel) { -+ -+ case 32: -+ EncodeIndexedRect32((CARD8 *)tightBeforeBuf, w * h); -+ -+ for (i = 0; i < paletteNumColors; i++) { -+ ((CARD32 *)tightAfterBuf)[i] = -+ palette.entry[i].listNode->rgb; -+ } -+ if (usePixelFormat24) { -+ Pack24(cl->pScreen, tightAfterBuf, &cl->format, paletteNumColors); -+ entryLen = 3; -+ } else -+ entryLen = 4; -+ -+ memcpy(&pVNC->updateBuf[pVNC->ublen], tightAfterBuf, paletteNumColors * entryLen); -+ pVNC->ublen += paletteNumColors * entryLen; -+ cl->rfbBytesSent[rfbEncodingTight] += 3 + paletteNumColors * entryLen; -+ break; -+ -+ case 16: -+ EncodeIndexedRect16((CARD8 *)tightBeforeBuf, w * h); -+ -+ for (i = 0; i < paletteNumColors; i++) { -+ ((CARD16 *)tightAfterBuf)[i] = -+ (CARD16)palette.entry[i].listNode->rgb; -+ } -+ -+ memcpy(&pVNC->updateBuf[pVNC->ublen], tightAfterBuf, paletteNumColors * 2); -+ pVNC->ublen += paletteNumColors * 2; -+ cl->rfbBytesSent[rfbEncodingTight] += 3 + paletteNumColors * 2; -+ break; -+ -+ default: -+ return FALSE; /* Should never happen. */ -+ } -+ -+ return CompressData(cl, streamId, w * h, -+ tightConf[cl->tightCompressLevel].idxZlibLevel, -+ Z_DEFAULT_STRATEGY); -+} -+ -+static Bool -+SendFullColorRect(cl, w, h) -+ rfbClientPtr cl; -+ int w, h; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ int streamId = 0; -+ int len; -+ -+ if (pVNC->ublen + TIGHT_MIN_TO_COMPRESS + 1 > UPDATE_BUF_SIZE) { -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ } -+ -+ pVNC->updateBuf[pVNC->ublen++] = 0x00; /* stream id = 0, no flushing, no filter */ -+ cl->rfbBytesSent[rfbEncodingTight]++; -+ -+ if (usePixelFormat24) { -+ Pack24(cl->pScreen, tightBeforeBuf, &cl->format, w * h); -+ len = 3; -+ } else -+ len = cl->format.bitsPerPixel / 8; -+ -+ return CompressData(cl, streamId, w * h * len, -+ tightConf[cl->tightCompressLevel].rawZlibLevel, -+ Z_DEFAULT_STRATEGY); -+} -+ -+static Bool -+SendGradientRect(cl, w, h) -+ rfbClientPtr cl; -+ int w, h; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ int streamId = 3; -+ int len; -+ -+ if (cl->format.bitsPerPixel == 8) -+ return SendFullColorRect(cl, w, h); -+ -+ if (pVNC->ublen + TIGHT_MIN_TO_COMPRESS + 2 > UPDATE_BUF_SIZE) { -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ } -+ -+ if (prevRowBuf == NULL) -+ prevRowBuf = (int *)xalloc(2048 * 3 * sizeof(int)); -+ -+ pVNC->updateBuf[pVNC->ublen++] = (streamId | rfbTightExplicitFilter) << 4; -+ pVNC->updateBuf[pVNC->ublen++] = rfbTightFilterGradient; -+ cl->rfbBytesSent[rfbEncodingTight] += 2; -+ -+ if (usePixelFormat24) { -+ FilterGradient24(cl->pScreen, tightBeforeBuf, &cl->format, w, h); -+ len = 3; -+ } else if (cl->format.bitsPerPixel == 32) { -+ FilterGradient32(cl->pScreen, (CARD32 *)tightBeforeBuf, &cl->format, w, h); -+ len = 4; -+ } else { -+ FilterGradient16(cl->pScreen, (CARD16 *)tightBeforeBuf, &cl->format, w, h); -+ len = 2; -+ } -+ -+ return CompressData(cl, streamId, w * h * len, -+ tightConf[cl->tightCompressLevel].gradientZlibLevel, -+ Z_FILTERED); -+} -+ -+static Bool -+CompressData(cl, streamId, dataLen, zlibLevel, zlibStrategy) -+ rfbClientPtr cl; -+ int streamId, dataLen, zlibLevel, zlibStrategy; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ z_streamp pz; -+ int err; -+ -+ if (dataLen < TIGHT_MIN_TO_COMPRESS) { -+ memcpy(&pVNC->updateBuf[pVNC->ublen], tightBeforeBuf, dataLen); -+ pVNC->ublen += dataLen; -+ cl->rfbBytesSent[rfbEncodingTight] += dataLen; -+ return TRUE; -+ } -+ -+ pz = &cl->zsStruct[streamId]; -+ -+ /* Initialize compression stream if needed. */ -+ if (!cl->zsActive[streamId]) { -+ pz->zalloc = Z_NULL; -+ pz->zfree = Z_NULL; -+ pz->opaque = Z_NULL; -+ -+ err = deflateInit2 (pz, zlibLevel, Z_DEFLATED, MAX_WBITS, -+ MAX_MEM_LEVEL, zlibStrategy); -+ if (err != Z_OK) -+ return FALSE; -+ -+ cl->zsActive[streamId] = TRUE; -+ cl->zsLevel[streamId] = zlibLevel; -+ } -+ -+ /* Prepare buffer pointers. */ -+ pz->next_in = (Bytef *)tightBeforeBuf; -+ pz->avail_in = dataLen; -+ pz->next_out = (Bytef *)tightAfterBuf; -+ pz->avail_out = tightAfterBufSize; -+ -+ /* Change compression parameters if needed. */ -+ if (zlibLevel != cl->zsLevel[streamId]) { -+ if (deflateParams (pz, zlibLevel, zlibStrategy) != Z_OK) { -+ return FALSE; -+ } -+ cl->zsLevel[streamId] = zlibLevel; -+ } -+ -+ /* Actual compression. */ -+ if ( deflate (pz, Z_SYNC_FLUSH) != Z_OK || -+ pz->avail_in != 0 || pz->avail_out == 0 ) { -+ return FALSE; -+ } -+ -+ return SendCompressedData(cl, tightAfterBufSize - pz->avail_out); -+} -+ -+static Bool SendCompressedData(cl, compressedLen) -+ rfbClientPtr cl; -+ int compressedLen; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ int i, portionLen; -+ -+ pVNC->updateBuf[pVNC->ublen++] = compressedLen & 0x7F; -+ cl->rfbBytesSent[rfbEncodingTight]++; -+ if (compressedLen > 0x7F) { -+ pVNC->updateBuf[pVNC->ublen-1] |= 0x80; -+ pVNC->updateBuf[pVNC->ublen++] = compressedLen >> 7 & 0x7F; -+ cl->rfbBytesSent[rfbEncodingTight]++; -+ if (compressedLen > 0x3FFF) { -+ pVNC->updateBuf[pVNC->ublen-1] |= 0x80; -+ pVNC->updateBuf[pVNC->ublen++] = compressedLen >> 14 & 0xFF; -+ cl->rfbBytesSent[rfbEncodingTight]++; -+ } -+ } -+ -+ portionLen = UPDATE_BUF_SIZE; -+ for (i = 0; i < compressedLen; i += portionLen) { -+ if (i + portionLen > compressedLen) { -+ portionLen = compressedLen - i; -+ } -+ if (pVNC->ublen + portionLen > UPDATE_BUF_SIZE) { -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ } -+ memcpy(&pVNC->updateBuf[pVNC->ublen], &tightAfterBuf[i], portionLen); -+ pVNC->ublen += portionLen; -+ } -+ cl->rfbBytesSent[rfbEncodingTight] += compressedLen; -+ return TRUE; -+} -+ -+/* -+ * Code to determine how many different colors used in rectangle. -+ */ -+ -+static void -+FillPalette8(count) -+ int count; -+{ -+ CARD8 *data = (CARD8 *)tightBeforeBuf; -+ CARD8 c0, c1; -+ int i, n0, n1; -+ -+ paletteNumColors = 0; -+ -+ c0 = data[0]; -+ for (i = 1; i < count && data[i] == c0; i++); -+ if (i == count) { -+ paletteNumColors = 1; -+ return; /* Solid rectangle */ -+ } -+ -+ if (paletteMaxColors < 2) -+ return; -+ -+ n0 = i; -+ c1 = data[i]; -+ n1 = 0; -+ for (i++; i < count; i++) { -+ if (data[i] == c0) { -+ n0++; -+ } else if (data[i] == c1) { -+ n1++; -+ } else -+ break; -+ } -+ if (i == count) { -+ if (n0 > n1) { -+ monoBackground = (CARD32)c0; -+ monoForeground = (CARD32)c1; -+ } else { -+ monoBackground = (CARD32)c1; -+ monoForeground = (CARD32)c0; -+ } -+ paletteNumColors = 2; /* Two colors */ -+ } -+} -+ -+#define DEFINE_FILL_PALETTE_FUNCTION(bpp) \ -+ \ -+static void \ -+FillPalette##bpp(count) \ -+ int count; \ -+{ \ -+ CARD##bpp *data = (CARD##bpp *)tightBeforeBuf; \ -+ CARD##bpp c0, c1, ci = 0; \ -+ int i, n0, n1, ni; \ -+ \ -+ c0 = data[0]; \ -+ for (i = 1; i < count && data[i] == c0; i++); \ -+ if (i >= count) { \ -+ paletteNumColors = 1; /* Solid rectangle */ \ -+ return; \ -+ } \ -+ \ -+ if (paletteMaxColors < 2) { \ -+ paletteNumColors = 0; /* Full-color encoding preferred */ \ -+ return; \ -+ } \ -+ \ -+ n0 = i; \ -+ c1 = data[i]; \ -+ n1 = 0; \ -+ for (i++; i < count; i++) { \ -+ ci = data[i]; \ -+ if (ci == c0) { \ -+ n0++; \ -+ } else if (ci == c1) { \ -+ n1++; \ -+ } else \ -+ break; \ -+ } \ -+ if (i >= count) { \ -+ if (n0 > n1) { \ -+ monoBackground = (CARD32)c0; \ -+ monoForeground = (CARD32)c1; \ -+ } else { \ -+ monoBackground = (CARD32)c1; \ -+ monoForeground = (CARD32)c0; \ -+ } \ -+ paletteNumColors = 2; /* Two colors */ \ -+ return; \ -+ } \ -+ \ -+ PaletteReset(); \ -+ PaletteInsert (c0, (CARD32)n0, bpp); \ -+ PaletteInsert (c1, (CARD32)n1, bpp); \ -+ \ -+ ni = 1; \ -+ for (i++; i < count; i++) { \ -+ if (data[i] == ci) { \ -+ ni++; \ -+ } else { \ -+ if (!PaletteInsert (ci, (CARD32)ni, bpp)) \ -+ return; \ -+ ci = data[i]; \ -+ ni = 1; \ -+ } \ -+ } \ -+ PaletteInsert (ci, (CARD32)ni, bpp); \ -+} -+ -+DEFINE_FILL_PALETTE_FUNCTION(16) -+DEFINE_FILL_PALETTE_FUNCTION(32) -+ -+ -+/* -+ * Functions to operate with palette structures. -+ */ -+ -+#define HASH_FUNC16(rgb) ((int)((((rgb) >> 8) + (rgb)) & 0xFF)) -+#define HASH_FUNC32(rgb) ((int)((((rgb) >> 16) + ((rgb) >> 8)) & 0xFF)) -+ -+static void -+PaletteReset(void) -+{ -+ paletteNumColors = 0; -+ memset(palette.hash, 0, 256 * sizeof(COLOR_LIST *)); -+} -+ -+static int -+PaletteInsert(CARD32 rgb, int numPixels, int bpp) -+{ -+ COLOR_LIST *pnode; -+ COLOR_LIST *prev_pnode = NULL; -+ int hash_key, idx, new_idx, count; -+ -+ hash_key = (bpp == 16) ? HASH_FUNC16(rgb) : HASH_FUNC32(rgb); -+ -+ pnode = palette.hash[hash_key]; -+ -+ while (pnode != NULL) { -+ if (pnode->rgb == rgb) { -+ /* Such palette entry already exists. */ -+ new_idx = idx = pnode->idx; -+ count = palette.entry[idx].numPixels + numPixels; -+ if (new_idx && palette.entry[new_idx-1].numPixels < count) { -+ do { -+ palette.entry[new_idx] = palette.entry[new_idx-1]; -+ palette.entry[new_idx].listNode->idx = new_idx; -+ new_idx--; -+ } -+ while (new_idx && palette.entry[new_idx-1].numPixels < count); -+ palette.entry[new_idx].listNode = pnode; -+ pnode->idx = new_idx; -+ } -+ palette.entry[new_idx].numPixels = count; -+ return paletteNumColors; -+ } -+ prev_pnode = pnode; -+ pnode = pnode->next; -+ } -+ -+ /* Check if palette is full. */ -+ if (paletteNumColors == 256 || paletteNumColors == paletteMaxColors) { -+ paletteNumColors = 0; -+ return 0; -+ } -+ -+ /* Move palette entries with lesser pixel counts. */ -+ for ( idx = paletteNumColors; -+ idx > 0 && palette.entry[idx-1].numPixels < numPixels; -+ idx-- ) { -+ palette.entry[idx] = palette.entry[idx-1]; -+ palette.entry[idx].listNode->idx = idx; -+ } -+ -+ /* Add new palette entry into the freed slot. */ -+ pnode = &palette.list[paletteNumColors]; -+ if (prev_pnode != NULL) { -+ prev_pnode->next = pnode; -+ } else { -+ palette.hash[hash_key] = pnode; -+ } -+ pnode->next = NULL; -+ pnode->idx = idx; -+ pnode->rgb = rgb; -+ palette.entry[idx].listNode = pnode; -+ palette.entry[idx].numPixels = numPixels; -+ -+ return (++paletteNumColors); -+} -+ -+ -+/* -+ * Converting 32-bit color samples into 24-bit colors. -+ * Should be called only when redMax, greenMax and blueMax are 255. -+ * Color components assumed to be byte-aligned. -+ */ -+ -+static void Pack24(pScreen, buf, fmt, count) -+ ScreenPtr pScreen; -+ char *buf; -+ rfbPixelFormat *fmt; -+ int count; -+{ -+ VNCSCREENPTR(pScreen); -+ CARD32 *buf32; -+ CARD32 pix; -+ int r_shift, g_shift, b_shift; -+ -+ buf32 = (CARD32 *)buf; -+ -+ if (!pVNC->rfbServerFormat.bigEndian == !fmt->bigEndian) { -+ r_shift = fmt->redShift; -+ g_shift = fmt->greenShift; -+ b_shift = fmt->blueShift; -+ } else { -+ r_shift = 24 - fmt->redShift; -+ g_shift = 24 - fmt->greenShift; -+ b_shift = 24 - fmt->blueShift; -+ } -+ -+ while (count--) { -+ pix = *buf32++; -+ *buf++ = (char)(pix >> r_shift); -+ *buf++ = (char)(pix >> g_shift); -+ *buf++ = (char)(pix >> b_shift); -+ } -+} -+ -+ -+/* -+ * Converting truecolor samples into palette indices. -+ */ -+ -+#define DEFINE_IDX_ENCODE_FUNCTION(bpp) \ -+ \ -+static void \ -+EncodeIndexedRect##bpp(buf, count) \ -+ CARD8 *buf; \ -+ int count; \ -+{ \ -+ COLOR_LIST *pnode; \ -+ CARD##bpp *src; \ -+ CARD##bpp rgb; \ -+ int rep = 0; \ -+ \ -+ src = (CARD##bpp *) buf; \ -+ \ -+ while (count--) { \ -+ rgb = *src++; \ -+ while (count && *src == rgb) { \ -+ rep++, src++, count--; \ -+ } \ -+ pnode = palette.hash[HASH_FUNC##bpp(rgb)]; \ -+ while (pnode != NULL) { \ -+ if ((CARD##bpp)pnode->rgb == rgb) { \ -+ *buf++ = (CARD8)pnode->idx; \ -+ while (rep) { \ -+ *buf++ = (CARD8)pnode->idx; \ -+ rep--; \ -+ } \ -+ break; \ -+ } \ -+ pnode = pnode->next; \ -+ } \ -+ } \ -+} -+ -+DEFINE_IDX_ENCODE_FUNCTION(16) -+DEFINE_IDX_ENCODE_FUNCTION(32) -+ -+#define DEFINE_MONO_ENCODE_FUNCTION(bpp) \ -+ \ -+static void \ -+EncodeMonoRect##bpp(buf, w, h) \ -+ CARD8 *buf; \ -+ int w, h; \ -+{ \ -+ CARD##bpp *ptr; \ -+ CARD##bpp bg; \ -+ unsigned int value, mask; \ -+ int aligned_width; \ -+ int x, y, bg_bits; \ -+ \ -+ ptr = (CARD##bpp *) buf; \ -+ bg = (CARD##bpp) monoBackground; \ -+ aligned_width = w - w % 8; \ -+ \ -+ for (y = 0; y < h; y++) { \ -+ for (x = 0; x < aligned_width; x += 8) { \ -+ for (bg_bits = 0; bg_bits < 8; bg_bits++) { \ -+ if (*ptr++ != bg) \ -+ break; \ -+ } \ -+ if (bg_bits == 8) { \ -+ *buf++ = 0; \ -+ continue; \ -+ } \ -+ mask = 0x80 >> bg_bits; \ -+ value = mask; \ -+ for (bg_bits++; bg_bits < 8; bg_bits++) { \ -+ mask >>= 1; \ -+ if (*ptr++ != bg) { \ -+ value |= mask; \ -+ } \ -+ } \ -+ *buf++ = (CARD8)value; \ -+ } \ -+ \ -+ mask = 0x80; \ -+ value = 0; \ -+ if (x >= w) \ -+ continue; \ -+ \ -+ for (; x < w; x++) { \ -+ if (*ptr++ != bg) { \ -+ value |= mask; \ -+ } \ -+ mask >>= 1; \ -+ } \ -+ *buf++ = (CARD8)value; \ -+ } \ -+} -+ -+DEFINE_MONO_ENCODE_FUNCTION(8) -+DEFINE_MONO_ENCODE_FUNCTION(16) -+DEFINE_MONO_ENCODE_FUNCTION(32) -+ -+ -+/* -+ * ``Gradient'' filter for 24-bit color samples. -+ * Should be called only when redMax, greenMax and blueMax are 255. -+ * Color components assumed to be byte-aligned. -+ */ -+ -+static void -+FilterGradient24(pScreen, buf, fmt, w, h) -+ ScreenPtr pScreen; -+ char *buf; -+ rfbPixelFormat *fmt; -+ int w, h; -+{ -+ VNCSCREENPTR(pScreen); -+ CARD32 *buf32; -+ CARD32 pix32; -+ int *prevRowPtr; -+ int shiftBits[3]; -+ int pixHere[3], pixUpper[3], pixLeft[3], pixUpperLeft[3]; -+ int prediction; -+ int x, y, c; -+ -+ buf32 = (CARD32 *)buf; -+ memset (prevRowBuf, 0, w * 3 * sizeof(int)); -+ -+ if (!pVNC->rfbServerFormat.bigEndian == !fmt->bigEndian) { -+ shiftBits[0] = fmt->redShift; -+ shiftBits[1] = fmt->greenShift; -+ shiftBits[2] = fmt->blueShift; -+ } else { -+ shiftBits[0] = 24 - fmt->redShift; -+ shiftBits[1] = 24 - fmt->greenShift; -+ shiftBits[2] = 24 - fmt->blueShift; -+ } -+ -+ for (y = 0; y < h; y++) { -+ for (c = 0; c < 3; c++) { -+ pixUpper[c] = 0; -+ pixHere[c] = 0; -+ } -+ prevRowPtr = prevRowBuf; -+ for (x = 0; x < w; x++) { -+ pix32 = *buf32++; -+ for (c = 0; c < 3; c++) { -+ pixUpperLeft[c] = pixUpper[c]; -+ pixLeft[c] = pixHere[c]; -+ pixUpper[c] = *prevRowPtr; -+ pixHere[c] = (int)(pix32 >> shiftBits[c] & 0xFF); -+ *prevRowPtr++ = pixHere[c]; -+ -+ prediction = pixLeft[c] + pixUpper[c] - pixUpperLeft[c]; -+ if (prediction < 0) { -+ prediction = 0; -+ } else if (prediction > 0xFF) { -+ prediction = 0xFF; -+ } -+ *buf++ = (char)(pixHere[c] - prediction); -+ } -+ } -+ } -+} -+ -+ -+/* -+ * ``Gradient'' filter for other color depths. -+ */ -+ -+#define DEFINE_GRADIENT_FILTER_FUNCTION(bpp) \ -+ \ -+static void \ -+FilterGradient##bpp(pScreen, buf, fmt, w, h) \ -+ ScreenPtr pScreen; \ -+ CARD##bpp *buf; \ -+ rfbPixelFormat *fmt; \ -+ int w, h; \ -+{ \ -+ VNCSCREENPTR(pScreen); \ -+ CARD##bpp pix, diff; \ -+ Bool endianMismatch; \ -+ int *prevRowPtr; \ -+ int maxColor[3], shiftBits[3]; \ -+ int pixHere[3], pixUpper[3], pixLeft[3], pixUpperLeft[3]; \ -+ int prediction; \ -+ int x, y, c; \ -+ \ -+ memset (prevRowBuf, 0, w * 3 * sizeof(int)); \ -+ \ -+ endianMismatch = (!pVNC->rfbServerFormat.bigEndian != !fmt->bigEndian); \ -+ \ -+ maxColor[0] = fmt->redMax; \ -+ maxColor[1] = fmt->greenMax; \ -+ maxColor[2] = fmt->blueMax; \ -+ shiftBits[0] = fmt->redShift; \ -+ shiftBits[1] = fmt->greenShift; \ -+ shiftBits[2] = fmt->blueShift; \ -+ \ -+ for (y = 0; y < h; y++) { \ -+ for (c = 0; c < 3; c++) { \ -+ pixUpper[c] = 0; \ -+ pixHere[c] = 0; \ -+ } \ -+ prevRowPtr = prevRowBuf; \ -+ for (x = 0; x < w; x++) { \ -+ pix = *buf; \ -+ if (endianMismatch) { \ -+ pix = Swap##bpp(pix); \ -+ } \ -+ diff = 0; \ -+ for (c = 0; c < 3; c++) { \ -+ pixUpperLeft[c] = pixUpper[c]; \ -+ pixLeft[c] = pixHere[c]; \ -+ pixUpper[c] = *prevRowPtr; \ -+ pixHere[c] = (int)(pix >> shiftBits[c] & maxColor[c]); \ -+ *prevRowPtr++ = pixHere[c]; \ -+ \ -+ prediction = pixLeft[c] + pixUpper[c] - pixUpperLeft[c]; \ -+ if (prediction < 0) { \ -+ prediction = 0; \ -+ } else if (prediction > maxColor[c]) { \ -+ prediction = maxColor[c]; \ -+ } \ -+ diff |= ((pixHere[c] - prediction) & maxColor[c]) \ -+ << shiftBits[c]; \ -+ } \ -+ if (endianMismatch) { \ -+ diff = Swap##bpp(diff); \ -+ } \ -+ *buf++ = diff; \ -+ } \ -+ } \ -+} -+ -+DEFINE_GRADIENT_FILTER_FUNCTION(16) -+DEFINE_GRADIENT_FILTER_FUNCTION(32) -+ -+ -+/* -+ * Code to guess if given rectangle is suitable for smooth image -+ * compression (by applying "gradient" filter or JPEG coder). -+ */ -+ -+#define JPEG_MIN_RECT_SIZE 4096 -+ -+#define DETECT_SUBROW_WIDTH 7 -+#define DETECT_MIN_WIDTH 8 -+#define DETECT_MIN_HEIGHT 8 -+ -+static int -+DetectSmoothImage (cl, fmt, w, h) -+ rfbClientPtr cl; -+ rfbPixelFormat *fmt; -+ int w, h; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ unsigned long avgError; -+ -+ if ( pVNC->rfbServerFormat.bitsPerPixel == 8 || fmt->bitsPerPixel == 8 || -+ w < DETECT_MIN_WIDTH || h < DETECT_MIN_HEIGHT ) { -+ return 0; -+ } -+ -+ if (cl->tightQualityLevel != -1) { -+ if (w * h < JPEG_MIN_RECT_SIZE) { -+ return 0; -+ } -+ } else { -+ if ( rfbTightDisableGradient || -+ w * h < tightConf[cl->tightCompressLevel].gradientMinRectSize ) { -+ return 0; -+ } -+ } -+ -+ if (fmt->bitsPerPixel == 32) { -+ if (usePixelFormat24) { -+ avgError = DetectSmoothImage24(cl, fmt, w, h); -+ if (cl->tightQualityLevel != -1) { -+ return (avgError < tightConf[cl->tightQualityLevel].jpegThreshold24); -+ } -+ return (avgError < tightConf[cl->tightCompressLevel].gradientThreshold24); -+ } else { -+ avgError = DetectSmoothImage32(cl, fmt, w, h); -+ } -+ } else { -+ avgError = DetectSmoothImage16(cl, fmt, w, h); -+ } -+ if (cl->tightQualityLevel != -1) { -+ return (avgError < tightConf[cl->tightQualityLevel].jpegThreshold); -+ } -+ return (avgError < tightConf[cl->tightCompressLevel].gradientThreshold); -+} -+ -+static unsigned long -+DetectSmoothImage24 (cl, fmt, w, h) -+ rfbClientPtr cl; -+ rfbPixelFormat *fmt; -+ int w, h; -+{ -+ int off; -+ int x, y, d, dx, c; -+ int diffStat[256]; -+ int pixelCount = 0; -+ int pix, left[3]; -+ unsigned long avgError; -+ -+ /* If client is big-endian, color samples begin from the second -+ byte (offset 1) of a 32-bit pixel value. */ -+ off = (fmt->bigEndian != 0); -+ -+ memset(diffStat, 0, 256*sizeof(int)); -+ -+ y = 0, x = 0; -+ while (y < h && x < w) { -+ for (d = 0; d < h - y && d < w - x - DETECT_SUBROW_WIDTH; d++) { -+ for (c = 0; c < 3; c++) { -+ left[c] = (int)tightBeforeBuf[((y+d)*w+x+d)*4+off+c] & 0xFF; -+ } -+ for (dx = 1; dx <= DETECT_SUBROW_WIDTH; dx++) { -+ for (c = 0; c < 3; c++) { -+ pix = (int)tightBeforeBuf[((y+d)*w+x+d+dx)*4+off+c] & 0xFF; -+ diffStat[abs(pix - left[c])]++; -+ left[c] = pix; -+ } -+ pixelCount++; -+ } -+ } -+ if (w > h) { -+ x += h; -+ y = 0; -+ } else { -+ x = 0; -+ y += w; -+ } -+ } -+ -+ if (diffStat[0] * 33 / pixelCount >= 95) -+ return 0; -+ -+ avgError = 0; -+ for (c = 1; c < 8; c++) { -+ avgError += (unsigned long)diffStat[c] * (unsigned long)(c * c); -+ if (diffStat[c] == 0 || diffStat[c] > diffStat[c-1] * 2) -+ return 0; -+ } -+ for (; c < 256; c++) { -+ avgError += (unsigned long)diffStat[c] * (unsigned long)(c * c); -+ } -+ avgError /= (pixelCount * 3 - diffStat[0]); -+ -+ return avgError; -+} -+ -+#define DEFINE_DETECT_FUNCTION(bpp) \ -+ \ -+static unsigned long \ -+DetectSmoothImage##bpp (cl, fmt, w, h) \ -+ rfbClientPtr cl; \ -+ rfbPixelFormat *fmt; \ -+ int w, h; \ -+{ \ -+ VNCSCREENPTR(cl->pScreen); \ -+ Bool endianMismatch; \ -+ CARD##bpp pix; \ -+ int maxColor[3], shiftBits[3]; \ -+ int x, y, d, dx, c; \ -+ int diffStat[256]; \ -+ int pixelCount = 0; \ -+ int sample, sum, left[3]; \ -+ unsigned long avgError; \ -+ \ -+ endianMismatch = (!pVNC->rfbServerFormat.bigEndian != !fmt->bigEndian); \ -+ \ -+ maxColor[0] = fmt->redMax; \ -+ maxColor[1] = fmt->greenMax; \ -+ maxColor[2] = fmt->blueMax; \ -+ shiftBits[0] = fmt->redShift; \ -+ shiftBits[1] = fmt->greenShift; \ -+ shiftBits[2] = fmt->blueShift; \ -+ \ -+ memset(diffStat, 0, 256*sizeof(int)); \ -+ \ -+ y = 0, x = 0; \ -+ while (y < h && x < w) { \ -+ for (d = 0; d < h - y && d < w - x - DETECT_SUBROW_WIDTH; d++) { \ -+ pix = ((CARD##bpp *)tightBeforeBuf)[(y+d)*w+x+d]; \ -+ if (endianMismatch) { \ -+ pix = Swap##bpp(pix); \ -+ } \ -+ for (c = 0; c < 3; c++) { \ -+ left[c] = (int)(pix >> shiftBits[c] & maxColor[c]); \ -+ } \ -+ for (dx = 1; dx <= DETECT_SUBROW_WIDTH; dx++) { \ -+ pix = ((CARD##bpp *)tightBeforeBuf)[(y+d)*w+x+d+dx]; \ -+ if (endianMismatch) { \ -+ pix = Swap##bpp(pix); \ -+ } \ -+ sum = 0; \ -+ for (c = 0; c < 3; c++) { \ -+ sample = (int)(pix >> shiftBits[c] & maxColor[c]); \ -+ sum += abs(sample - left[c]); \ -+ left[c] = sample; \ -+ } \ -+ if (sum > 255) \ -+ sum = 255; \ -+ diffStat[sum]++; \ -+ pixelCount++; \ -+ } \ -+ } \ -+ if (w > h) { \ -+ x += h; \ -+ y = 0; \ -+ } else { \ -+ x = 0; \ -+ y += w; \ -+ } \ -+ } \ -+ \ -+ if ((diffStat[0] + diffStat[1]) * 100 / pixelCount >= 90) \ -+ return 0; \ -+ \ -+ avgError = 0; \ -+ for (c = 1; c < 8; c++) { \ -+ avgError += (unsigned long)diffStat[c] * (unsigned long)(c * c); \ -+ if (diffStat[c] == 0 || diffStat[c] > diffStat[c-1] * 2) \ -+ return 0; \ -+ } \ -+ for (; c < 256; c++) { \ -+ avgError += (unsigned long)diffStat[c] * (unsigned long)(c * c); \ -+ } \ -+ avgError /= (pixelCount - diffStat[0]); \ -+ \ -+ return avgError; \ -+} -+ -+DEFINE_DETECT_FUNCTION(16) -+DEFINE_DETECT_FUNCTION(32) -+ -+ -+/* -+ * JPEG compression stuff. -+ */ -+ -+static struct jpeg_destination_mgr jpegDstManager; -+static Bool jpegError; -+static int jpegDstDataLen; -+ -+static Bool -+SendJpegRect(cl, x, y, w, h, quality) -+ rfbClientPtr cl; -+ int x, y, w, h; -+ int quality; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ struct jpeg_compress_struct cinfo; -+ struct jpeg_error_mgr jerr; -+ CARD8 *srcBuf; -+ JSAMPROW rowPointer[1]; -+ int dy; -+ -+ if (pVNC->rfbServerFormat.bitsPerPixel == 8) -+ return SendFullColorRect(cl, w, h); -+ -+ srcBuf = (CARD8 *)xalloc(w * 3); -+ if (srcBuf == NULL) { -+ return SendFullColorRect(cl, w, h); -+ } -+ rowPointer[0] = srcBuf; -+ -+ cinfo.err = jpeg_std_error(&jerr); -+ jpeg_create_compress(&cinfo); -+ -+ cinfo.image_width = w; -+ cinfo.image_height = h; -+ cinfo.input_components = 3; -+ cinfo.in_color_space = JCS_RGB; -+ -+ jpeg_set_defaults(&cinfo); -+ jpeg_set_quality(&cinfo, quality, TRUE); -+ -+ JpegSetDstManager (&cinfo); -+ -+ jpeg_start_compress(&cinfo, TRUE); -+ -+ for (dy = 0; dy < h; dy++) { -+ PrepareRowForJpeg(cl->pScreen, srcBuf, x, y + dy, w); -+ jpeg_write_scanlines(&cinfo, rowPointer, 1); -+ if (jpegError) -+ break; -+ } -+ -+ if (!jpegError) -+ jpeg_finish_compress(&cinfo); -+ -+ jpeg_destroy_compress(&cinfo); -+ xfree((char *)srcBuf); -+ -+ if (jpegError) -+ return SendFullColorRect(cl, w, h); -+ -+ if (pVNC->ublen + TIGHT_MIN_TO_COMPRESS + 1 > UPDATE_BUF_SIZE) { -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ } -+ -+ pVNC->updateBuf[pVNC->ublen++] = (char)(rfbTightJpeg << 4); -+ cl->rfbBytesSent[rfbEncodingTight]++; -+ -+ return SendCompressedData(cl, jpegDstDataLen); -+} -+ -+static void -+PrepareRowForJpeg(pScreen, dst, x, y, count) -+ ScreenPtr pScreen; -+ CARD8 *dst; -+ int x, y, count; -+{ -+ VNCSCREENPTR(pScreen); -+ if (pVNC->rfbServerFormat.bitsPerPixel == 32) { -+ if ( pVNC->rfbServerFormat.redMax == 0xFF && -+ pVNC->rfbServerFormat.greenMax == 0xFF && -+ pVNC->rfbServerFormat.blueMax == 0xFF ) { -+ PrepareRowForJpeg24(pScreen, dst, x, y, count); -+ } else { -+ PrepareRowForJpeg32(pScreen, dst, x, y, count); -+ } -+ } else { -+ /* 16 bpp assumed. */ -+ PrepareRowForJpeg16(pScreen, dst, x, y, count); -+ } -+} -+ -+static void -+PrepareRowForJpeg24(pScreen, dst, x, y, count) -+ ScreenPtr pScreen; -+ CARD8 *dst; -+ int x, y, count; -+{ -+ VNCSCREENPTR(pScreen); -+ CARD32 *fbptr; -+ CARD32 pix; -+ -+ fbptr = (CARD32 *) -+ &pVNC->pfbMemory[y * pVNC->paddedWidthInBytes + x * 4]; -+ -+ while (count--) { -+ pix = *fbptr++; -+ *dst++ = (CARD8)(pix >> pVNC->rfbServerFormat.redShift); -+ *dst++ = (CARD8)(pix >> pVNC->rfbServerFormat.greenShift); -+ *dst++ = (CARD8)(pix >> pVNC->rfbServerFormat.blueShift); -+ } -+} -+ -+#define DEFINE_JPEG_GET_ROW_FUNCTION(bpp) \ -+ \ -+static void \ -+PrepareRowForJpeg##bpp(pScreen, dst, x, y, count) \ -+ ScreenPtr pScreen; \ -+ CARD8 *dst; \ -+ int x, y, count; \ -+{ \ -+ VNCSCREENPTR(pScreen); \ -+ CARD##bpp *fbptr; \ -+ CARD##bpp pix; \ -+ int inRed, inGreen, inBlue; \ -+ \ -+ fbptr = (CARD##bpp *) \ -+ &pVNC->pfbMemory[y * pVNC->paddedWidthInBytes + \ -+ x * (bpp / 8)]; \ -+ \ -+ while (count--) { \ -+ pix = *fbptr++; \ -+ \ -+ inRed = (int) \ -+ (pix >> pVNC->rfbServerFormat.redShift & pVNC->rfbServerFormat.redMax); \ -+ inGreen = (int) \ -+ (pix >> pVNC->rfbServerFormat.greenShift & pVNC->rfbServerFormat.greenMax); \ -+ inBlue = (int) \ -+ (pix >> pVNC->rfbServerFormat.blueShift & pVNC->rfbServerFormat.blueMax); \ -+ \ -+ *dst++ = (CARD8)((inRed * 255 + pVNC->rfbServerFormat.redMax / 2) / \ -+ pVNC->rfbServerFormat.redMax); \ -+ *dst++ = (CARD8)((inGreen * 255 + pVNC->rfbServerFormat.greenMax / 2) / \ -+ pVNC->rfbServerFormat.greenMax); \ -+ *dst++ = (CARD8)((inBlue * 255 + pVNC->rfbServerFormat.blueMax / 2) / \ -+ pVNC->rfbServerFormat.blueMax); \ -+ } \ -+} -+ -+DEFINE_JPEG_GET_ROW_FUNCTION(16) -+DEFINE_JPEG_GET_ROW_FUNCTION(32) -+ -+/* -+ * Destination manager implementation for JPEG library. -+ */ -+ -+static void -+JpegInitDestination(j_compress_ptr cinfo) -+{ -+ jpegError = FALSE; -+ jpegDstManager.next_output_byte = (JOCTET *)tightAfterBuf; -+ jpegDstManager.free_in_buffer = (size_t)tightAfterBufSize; -+} -+ -+static boolean -+JpegEmptyOutputBuffer(j_compress_ptr cinfo) -+{ -+ jpegError = TRUE; -+ jpegDstManager.next_output_byte = (JOCTET *)tightAfterBuf; -+ jpegDstManager.free_in_buffer = (size_t)tightAfterBufSize; -+ -+ return TRUE; -+} -+ -+static void -+JpegTermDestination(j_compress_ptr cinfo) -+{ -+ jpegDstDataLen = tightAfterBufSize - jpegDstManager.free_in_buffer; -+} -+ -+static void -+JpegSetDstManager(j_compress_ptr cinfo) -+{ -+ jpegDstManager.init_destination = JpegInitDestination; -+ jpegDstManager.empty_output_buffer = JpegEmptyOutputBuffer; -+ jpegDstManager.term_destination = JpegTermDestination; -+ cinfo->dest = &jpegDstManager; -+} -+ -diff --git a/hw/xfree86/vnc/translate.c b/hw/xfree86/vnc/translate.c -new file mode 100644 -index 0000000..5fdd602 ---- /dev/null -+++ b/hw/xfree86/vnc/translate.c -@@ -0,0 +1,497 @@ -+/* -+ * translate.c - translate between different pixel formats -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ */ -+ -+/* -+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. -+ * -+ * This is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This software is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this software; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -+ * USA. -+ */ -+ -+#include -+#include -+#include -+#include "rfb.h" -+#if XFREE86VNC -+#include -+#endif -+ -+static void PrintPixelFormat(rfbPixelFormat *pf); -+static Bool rfbSetClientColourMapBGR233(rfbClientPtr cl); -+ -+Bool rfbEconomicTranslate = FALSE; -+ -+/* -+ * Some standard pixel formats. -+ */ -+ -+static const rfbPixelFormat BGR233Format = { -+ 8, 8, 0, 1, 7, 7, 3, 0, 3, 6 -+}; -+ -+ -+/* -+ * Macro to compare pixel formats. -+ */ -+ -+#define PF_EQ(x,y) \ -+ ((x.bitsPerPixel == y.bitsPerPixel) && \ -+ (x.depth == y.depth) && \ -+ ((x.bigEndian == y.bigEndian) || (x.bitsPerPixel == 8)) && \ -+ (x.trueColour == y.trueColour) && \ -+ (!x.trueColour || ((x.redMax == y.redMax) && \ -+ (x.greenMax == y.greenMax) && \ -+ (x.blueMax == y.blueMax) && \ -+ (x.redShift == y.redShift) && \ -+ (x.greenShift == y.greenShift) && \ -+ (x.blueShift == y.blueShift)))) -+ -+#define CONCAT2(a,b) a##b -+#define CONCAT2E(a,b) CONCAT2(a,b) -+#define CONCAT4(a,b,c,d) a##b##c##d -+#define CONCAT4E(a,b,c,d) CONCAT4(a,b,c,d) -+ -+#define OUT 8 -+#include "tableinittctemplate.c" -+#include "tableinitcmtemplate.c" -+#define IN 8 -+#include "tabletranstemplate.c" -+#undef IN -+#define IN 16 -+#include "tabletranstemplate.c" -+#undef IN -+#define IN 32 -+#include "tabletranstemplate.c" -+#undef IN -+#undef OUT -+ -+#define OUT 16 -+#include "tableinittctemplate.c" -+#include "tableinitcmtemplate.c" -+#define IN 8 -+#include "tabletranstemplate.c" -+#undef IN -+#define IN 16 -+#include "tabletranstemplate.c" -+#undef IN -+#define IN 32 -+#include "tabletranstemplate.c" -+#undef IN -+#undef OUT -+ -+#define OUT 32 -+#include "tableinittctemplate.c" -+#include "tableinitcmtemplate.c" -+#define IN 8 -+#include "tabletranstemplate.c" -+#undef IN -+#define IN 16 -+#include "tabletranstemplate.c" -+#undef IN -+#define IN 32 -+#include "tabletranstemplate.c" -+#undef IN -+#undef OUT -+ -+typedef void (*rfbInitTableFnType)(ScreenPtr pScreen, char **table, rfbPixelFormat *in, -+ rfbPixelFormat *out); -+ -+rfbInitTableFnType rfbInitTrueColourSingleTableFns[3] = { -+ rfbInitTrueColourSingleTable8, -+ rfbInitTrueColourSingleTable16, -+ rfbInitTrueColourSingleTable32 -+}; -+ -+rfbInitTableFnType rfbInitColourMapSingleTableFns[3] = { -+ rfbInitColourMapSingleTable8, -+ rfbInitColourMapSingleTable16, -+ rfbInitColourMapSingleTable32 -+}; -+ -+rfbInitTableFnType rfbInitTrueColourRGBTablesFns[3] = { -+ rfbInitTrueColourRGBTables8, -+ rfbInitTrueColourRGBTables16, -+ rfbInitTrueColourRGBTables32 -+}; -+ -+rfbTranslateFnType rfbTranslateWithSingleTableFns[3][3] = { -+ { rfbTranslateWithSingleTable8to8, -+ rfbTranslateWithSingleTable8to16, -+ rfbTranslateWithSingleTable8to32 }, -+ { rfbTranslateWithSingleTable16to8, -+ rfbTranslateWithSingleTable16to16, -+ rfbTranslateWithSingleTable16to32 }, -+ { rfbTranslateWithSingleTable32to8, -+ rfbTranslateWithSingleTable32to16, -+ rfbTranslateWithSingleTable32to32 } -+}; -+ -+rfbTranslateFnType rfbTranslateWithRGBTablesFns[3][3] = { -+ { rfbTranslateWithRGBTables8to8, -+ rfbTranslateWithRGBTables8to16, -+ rfbTranslateWithRGBTables8to32 }, -+ { rfbTranslateWithRGBTables16to8, -+ rfbTranslateWithRGBTables16to16, -+ rfbTranslateWithRGBTables16to32 }, -+ { rfbTranslateWithRGBTables32to8, -+ rfbTranslateWithRGBTables32to16, -+ rfbTranslateWithRGBTables32to32 } -+}; -+ -+ -+ -+/* -+ * rfbTranslateNone is used when no translation is required. -+ */ -+ -+void -+rfbTranslateNone(ScreenPtr pScreen, char *table, rfbPixelFormat *in, rfbPixelFormat *out, -+ unsigned char *iptr, char *optr, int bytesBetweenInputLines, -+ int width, int height, int x, int y) -+{ -+ VNCSCREENPTR(pScreen); -+ int bytesPerOutputLine = width * (out->bitsPerPixel / 8); -+ -+ if (pVNC->useGetImage) { -+ DrawablePtr pDraw = (DrawablePtr)WindowTable[pScreen->myNum]; -+ -+ /* catch all for other TranslateNone cases - hextile, corre, rre, etc.*/ -+ (*pScreen->GetImage)(pDraw, x, y, width, height, ZPixmap, ~0, optr); -+ } else { -+ while (height > 0) { -+ memcpy(optr, iptr, bytesPerOutputLine); -+ iptr += bytesBetweenInputLines; -+ optr += bytesPerOutputLine; -+ height--; -+ } -+ } -+} -+ -+ -+/* -+ * rfbSetTranslateFunction sets the translation function. -+ */ -+ -+Bool -+rfbSetTranslateFunction(cl) -+ rfbClientPtr cl; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ rfbLog("Pixel format for client %s:\n",cl->host); -+ PrintPixelFormat(&cl->format); -+ -+ /* -+ * Check that bits per pixel values are valid -+ */ -+ -+ if ((pVNC->rfbServerFormat.bitsPerPixel != 8) && -+ (pVNC->rfbServerFormat.bitsPerPixel != 16) && -+ (pVNC->rfbServerFormat.bitsPerPixel != 32)) -+ { -+ rfbLog("%s: server bits per pixel not 8, 16 or 32\n", -+ "rfbSetTranslateFunction"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return FALSE; -+ } -+ -+ if ((cl->format.bitsPerPixel != 8) && -+ (cl->format.bitsPerPixel != 16) && -+ (cl->format.bitsPerPixel != 32)) -+ { -+ rfbLog("%s: client bits per pixel not 8, 16 or 32\n", -+ "rfbSetTranslateFunction"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return FALSE; -+ } -+ -+ if (!pVNC->rfbServerFormat.trueColour && -+ (pVNC->rfbServerFormat.bitsPerPixel != 8) && -+#if XFREE86VNC -+ (miInstalledMaps[cl->pScreen->myNum]->class == PseudoColor)) { -+#else -+ (pVNC->rfbInstalledColormap->class == PseudoColor)) { -+#endif -+ rfbLog("rfbSetTranslateFunction: server has colour map " -+ "but %d-bit - can only cope with 8-bit colour maps\n", -+ pVNC->rfbServerFormat.bitsPerPixel); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return FALSE; -+ } -+ -+ if (!cl->format.trueColour && -+ (cl->format.bitsPerPixel != 8) && -+#if XFREE86VNC -+ (miInstalledMaps[cl->pScreen->myNum]->class == PseudoColor)) { -+#else -+ (pVNC->rfbInstalledColormap->class == PseudoColor) ) { -+#endif -+ rfbLog("rfbSetTranslateFunction: client has colour map " -+ "but %d-bit - can only cope with 8-bit colour maps\n", -+ cl->format.bitsPerPixel); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return FALSE; -+ } -+ -+ /* -+ * bpp is valid, now work out how to translate -+ */ -+ -+ if (!cl->format.trueColour) { -+ -+ /* ? -> colour map */ -+ -+ if (!pVNC->rfbServerFormat.trueColour) { -+ -+ /* colour map -> colour map */ -+ -+#if XFREE86VNC -+ if (miInstalledMaps[cl->pScreen->myNum]->class == DirectColor) { -+#else -+ if (pVNC->rfbInstalledColormap->class == DirectColor) { -+#endif -+ rfbLog("rfbSetTranslateFunction: client is %d-bit DirectColor," -+ " client has colour map\n",cl->format.bitsPerPixel); -+ -+ cl->translateFn = rfbTranslateWithRGBTablesFns -+ [pVNC->rfbServerFormat.bitsPerPixel / 16] -+ [cl->format.bitsPerPixel / 16]; -+ -+ (*rfbInitTrueColourRGBTablesFns [cl->format.bitsPerPixel / 16]) -+ (cl->pScreen, &cl->translateLookupTable, -+ &pVNC->rfbServerFormat, &cl->format); -+ -+ return rfbSetClientColourMap(cl, 0, 0); -+ -+ /* PseudoColor colormap */ -+ -+ } else { -+ rfbLog("rfbSetTranslateFunction: both 8-bit colour map: " -+ "no translation needed\n"); -+ cl->translateFn = rfbTranslateNone; -+ return rfbSetClientColourMap(cl, 0, 0); -+ } -+ } -+ -+ /* -+ * truecolour -> colour map -+ * -+ * Set client's colour map to BGR233, then effectively it's -+ * truecolour as well -+ */ -+ -+ if (!rfbSetClientColourMapBGR233(cl)) -+ return FALSE; -+ -+ cl->format = BGR233Format; -+ } -+ -+ /* ? -> truecolour */ -+ -+ if (!pVNC->rfbServerFormat.trueColour) { -+ -+ /* colour map -> truecolour */ -+ -+ rfbLog("rfbSetTranslateFunction: client is %d-bit trueColour," -+ " server has colour map\n",cl->format.bitsPerPixel); -+ -+ cl->translateFn = rfbTranslateWithSingleTableFns -+ [pVNC->rfbServerFormat.bitsPerPixel / 16] -+ [cl->format.bitsPerPixel / 16]; -+ -+ return rfbSetClientColourMap(cl, 0, 0); -+ } -+ -+ /* truecolour -> truecolour */ -+ -+ if (PF_EQ(cl->format,pVNC->rfbServerFormat)) { -+ -+ /* client & server the same */ -+ -+ rfbLog(" no translation needed\n"); -+ cl->translateFn = rfbTranslateNone; -+ return TRUE; -+ } -+ -+ if ((pVNC->rfbServerFormat.bitsPerPixel < 16) || -+ (!rfbEconomicTranslate && (pVNC->rfbServerFormat.bitsPerPixel == 16))) { -+ -+ /* we can use a single lookup table for <= 16 bpp */ -+ -+ cl->translateFn = rfbTranslateWithSingleTableFns -+ [pVNC->rfbServerFormat.bitsPerPixel / 16] -+ [cl->format.bitsPerPixel / 16]; -+ -+ (*rfbInitTrueColourSingleTableFns -+ [cl->format.bitsPerPixel / 16]) (cl->pScreen, -+ &cl->translateLookupTable, -+ &pVNC->rfbServerFormat, &cl->format); -+ -+ } else { -+ -+ /* otherwise we use three separate tables for red, green and blue */ -+ -+ cl->translateFn = rfbTranslateWithRGBTablesFns -+ [pVNC->rfbServerFormat.bitsPerPixel / 16] -+ [cl->format.bitsPerPixel / 16]; -+ -+ (*rfbInitTrueColourRGBTablesFns -+ [cl->format.bitsPerPixel / 16]) (cl->pScreen, -+ &cl->translateLookupTable, -+ &pVNC->rfbServerFormat, &cl->format); -+ } -+ -+ return TRUE; -+} -+ -+ -+ -+/* -+ * rfbSetClientColourMapBGR233 sets the client's colour map so that it's -+ * just like an 8-bit BGR233 true colour client. -+ */ -+ -+static Bool -+rfbSetClientColourMapBGR233(rfbClientPtr cl) -+{ -+ char buf[sz_rfbSetColourMapEntriesMsg + 256 * 3 * 2]; -+ rfbSetColourMapEntriesMsg *scme = (rfbSetColourMapEntriesMsg *)buf; -+ CARD16 *rgb = (CARD16 *)(&buf[sz_rfbSetColourMapEntriesMsg]); -+ int i, len; -+ int r, g, b; -+ -+ if (cl->format.bitsPerPixel != 8) { -+ rfbLog("%s: client not 8 bits per pixel\n", -+ "rfbSetClientColourMapBGR233"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return FALSE; -+ } -+ -+ scme->type = rfbSetColourMapEntries; -+ -+ scme->firstColour = Swap16IfLE(0); -+ scme->nColours = Swap16IfLE(256); -+ -+ len = sz_rfbSetColourMapEntriesMsg; -+ -+ i = 0; -+ -+ for (b = 0; b < 4; b++) { -+ for (g = 0; g < 8; g++) { -+ for (r = 0; r < 8; r++) { -+ rgb[i++] = Swap16IfLE(r * 65535 / 7); -+ rgb[i++] = Swap16IfLE(g * 65535 / 7); -+ rgb[i++] = Swap16IfLE(b * 65535 / 3); -+ } -+ } -+ } -+ -+ len += 256 * 3 * 2; -+ -+ if (WriteExact(cl->sock, buf, len) < 0) { -+ rfbLogPerror("rfbSetClientColourMapBGR233: write"); -+ rfbCloseSock(cl->pScreen, cl->sock); -+ return FALSE; -+ } -+ return TRUE; -+} -+ -+ -+/* -+ * rfbSetClientColourMap is called to set the client's colour map. If the -+ * client is a true colour client, we simply update our own translation table -+ * and mark the whole screen as having been modified. -+ */ -+ -+Bool -+rfbSetClientColourMap(cl, firstColour, nColours) -+ rfbClientPtr cl; -+ int firstColour; -+ int nColours; -+{ -+ VNCSCREENPTR(cl->pScreen); -+ BoxRec box; -+ -+ if (nColours == 0) { -+#if XFREE86VNC -+ nColours = miInstalledMaps[cl->pScreen->myNum]->pVisual->ColormapEntries; -+#else -+ nColours = pVNC->rfbInstalledColormap->pVisual->ColormapEntries; -+#endif -+ } -+ -+ if (pVNC->rfbServerFormat.trueColour || !cl->readyForSetColourMapEntries) { -+ return TRUE; -+ } -+ -+ if (cl->format.trueColour) { -+ (*rfbInitColourMapSingleTableFns -+ [cl->format.bitsPerPixel / 16]) (cl->pScreen, -+ &cl->translateLookupTable, -+ &pVNC->rfbServerFormat, &cl->format); -+ -+ REGION_UNINIT(cl->pScreen,&cl->modifiedRegion); -+ box.x1 = box.y1 = 0; -+ box.x2 = pVNC->width; -+ box.y2 = pVNC->height; -+ REGION_INIT(cl->pScreen,&cl->modifiedRegion,&box,0); -+ -+ return TRUE; -+ } -+ -+ return rfbSendSetColourMapEntries(cl, firstColour, nColours); -+} -+ -+ -+/* -+ * rfbSetClientColourMaps sets the colour map for each RFB client. -+ */ -+ -+void -+rfbSetClientColourMaps(firstColour, nColours) -+ int firstColour; -+ int nColours; -+{ -+ rfbClientPtr cl, nextCl; -+ -+ for (cl = rfbClientHead; cl; cl = nextCl) { -+ nextCl = cl->next; -+ rfbSetClientColourMap(cl, firstColour, nColours); -+ } -+} -+ -+ -+static void -+PrintPixelFormat(pf) -+ rfbPixelFormat *pf; -+{ -+ if (pf->bitsPerPixel == 1) { -+ rfbLog(" 1 bpp, %s sig bit in each byte is leftmost on the screen.\n", -+ (pf->bigEndian ? "most" : "least")); -+ } else { -+ rfbLog(" %d bpp, depth %d%s\n",pf->bitsPerPixel,pf->depth, -+ ((pf->bitsPerPixel == 8) ? "" -+ : (pf->bigEndian ? ", big endian" : ", little endian"))); -+ if (pf->trueColour) { -+ rfbLog(" true colour: max r %d g %d b %d, shift r %d g %d b %d\n", -+ pf->redMax, pf->greenMax, pf->blueMax, -+ pf->redShift, pf->greenShift, pf->blueShift); -+ } else { -+ rfbLog(" uses a colour map (not true colour).\n"); -+ } -+ } -+} -diff --git a/hw/xfree86/vnc/vncInit.c b/hw/xfree86/vnc/vncInit.c -new file mode 100644 -index 0000000..c6b0a31 ---- /dev/null -+++ b/hw/xfree86/vnc/vncInit.c -@@ -0,0 +1,640 @@ -+/* -+ * Copyright (C) 2002 Alan Hourihane. 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. -+ * -+ * Author: Alan Hourihane -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include "../ramdac/xf86CursorPriv.h" -+#include "rfb.h" -+#include "vncint.h" -+ -+#include "xf86.h" -+#include "xf86_OSproc.h" -+#include "xf86Resources.h" -+#include "xf86Version.h" -+ -+int vncScreenPrivateIndex = -1; -+int rfbGCIndex = -1; -+int inetdSock = -1; -+Atom VNC_LAST_CLIENT_ID = 0; -+Atom VNC_CONNECT = 0; -+char *desktopName = "x11"; -+char rfbThisHost[256]; -+ -+extern void VncExtensionInit(void); -+ -+Bool VNCInit(ScreenPtr pScreen, unsigned char *FBStart); -+ -+#ifndef XFree86LOADER -+static unsigned long VNCGeneration = 0; -+#endif -+static const OptionInfoRec *VNCAvailableOptions(void *unused); -+static void rfbWakeupHandler (int i, pointer blockData, unsigned long err, pointer pReadmask); -+ -+static Bool vncCursorRealizeCursor(ScreenPtr, CursorPtr); -+static Bool vncCursorUnrealizeCursor(ScreenPtr, CursorPtr); -+static void vncCursorSetCursor(ScreenPtr, CursorPtr, int, int); -+static void vncCursorMoveCursor(ScreenPtr, int, int); -+static Bool vncDisplayCursor(ScreenPtr, CursorPtr); -+ -+static miPointerSpriteFuncRec vncCursorSpriteFuncs = { -+ vncCursorRealizeCursor, -+ vncCursorUnrealizeCursor, -+ vncCursorSetCursor, -+ vncCursorMoveCursor -+}; -+ -+/* -+ * VNC Config options -+ */ -+ -+typedef enum { -+ OPTION_USEVNC, -+ OPTION_RFBPORT, -+ OPTION_HTTPPORT, -+ OPTION_ALWAYS_SHARED, -+ OPTION_NEVER_SHARED, -+ OPTION_DONT_DISCONNECT, -+ OPTION_HTTPDIR, -+ OPTION_PASSWD_FILE, -+ OPTION_USER_ACCEPT, -+ OPTION_LOCALHOST, -+ OPTION_INTERFACE, -+ OPTION_VIEWONLY, -+ OPTION_LOGIN_AUTH, -+ OPTION_USE_GETIMAGE -+} VNCOpts; -+ -+static const OptionInfoRec VNCOptions[] = { -+ {OPTION_USEVNC, "usevnc", OPTV_BOOLEAN, {0}, FALSE }, -+ {OPTION_RFBPORT, "rfbport", OPTV_INTEGER, {0}, FALSE }, -+ {OPTION_HTTPPORT, "httpport", OPTV_INTEGER, {0}, FALSE }, -+ {OPTION_ALWAYS_SHARED, "alwaysshared", OPTV_BOOLEAN, {0}, FALSE }, -+ {OPTION_NEVER_SHARED, "nevershared", OPTV_BOOLEAN, {0}, FALSE }, -+ {OPTION_DONT_DISCONNECT, "dontdisconnect", OPTV_BOOLEAN, {0}, FALSE }, -+ {OPTION_HTTPDIR, "httpdir", OPTV_STRING, {0}, FALSE }, -+ {OPTION_PASSWD_FILE, "rfbauth", OPTV_STRING, {0}, FALSE }, -+ {OPTION_USER_ACCEPT, "useraccept", OPTV_BOOLEAN, {0}, FALSE }, -+ {OPTION_LOCALHOST, "localhost", OPTV_BOOLEAN, {0}, FALSE }, -+ {OPTION_INTERFACE, "interface", OPTV_STRING, {0}, FALSE }, -+ {OPTION_VIEWONLY, "viewonly", OPTV_BOOLEAN, {0}, FALSE }, -+ {OPTION_LOGIN_AUTH, "loginauth", OPTV_BOOLEAN, {0}, FALSE }, -+ {OPTION_USE_GETIMAGE, "usegetimage", OPTV_BOOLEAN, {0}, FALSE }, -+ { -1, NULL, OPTV_NONE, {0}, FALSE } -+}; -+ -+/*ARGSUSED*/ -+static const OptionInfoRec * -+VNCAvailableOptions(void *unused) -+{ -+ return (VNCOptions); -+} -+ -+/* -+ * rfbLog prints a time-stamped message to the log file (stderr). -+ */ -+ -+void rfbLog(char *format, ...) -+{ -+ va_list ap; -+ char buf[256]; -+ time_t clock; -+ -+ time(&clock); -+ strftime(buf, 255, "%d/%m/%Y %H:%M:%S ", localtime(&clock)); -+ xf86DrvMsgVerb(-1, X_INFO, 1, buf); -+ -+ va_start(ap, format); -+ xf86VDrvMsgVerb(-1, X_NONE, 1, format, ap); -+ va_end(ap); -+} -+ -+void rfbLogPerror(char *str) -+{ -+ rfbLog(""); -+ perror(str); -+} -+ -+/* -+ * Called by vncCreateScreenResources() -+ */ -+Bool -+VNCInit(ScreenPtr pScreen, unsigned char *FBStart) -+{ -+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; -+ VisualPtr visual; -+ vncScreenPtr pScreenPriv; -+ OptionInfoPtr options; -+ char *interface_str = NULL; -+ miPointerScreenPtr PointPriv; -+ xf86CursorScreenPtr xf86CursorPriv; -+#ifdef RENDER -+ PictureScreenPtr ps; -+#endif -+ -+ if (!FBStart) -+ return FALSE; -+ -+#ifndef XFree86LOADER -+ if (VNCGeneration != serverGeneration) { -+ VncExtensionInit(); -+ VNCGeneration = serverGeneration; -+ } -+#endif -+ -+ if (!AllocateGCPrivate(pScreen, rfbGCIndex, sizeof(rfbGCRec))) -+ return FALSE; -+ -+ if (!(pScreenPriv = xalloc(sizeof(vncScreenRec)))) -+ return FALSE; -+ -+ pScreen->devPrivates[vncScreenPrivateIndex].ptr = (pointer)pScreenPriv; -+ -+ options = xnfalloc(sizeof(VNCOptions)); -+ (void)memcpy(options, VNCOptions, sizeof(VNCOptions)); -+ xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options); -+ -+ if (xf86ReturnOptValBool(options, OPTION_USEVNC, FALSE)) { -+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "VNC enabled\n"); -+ } else { -+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VNC disabled\n"); -+ xfree(options); -+ return FALSE; -+ } -+ -+ pScreenPriv->rfbAuthTries = 0; -+ pScreenPriv->rfbAuthTooManyTries = FALSE; -+ pScreenPriv->timer = NULL; -+ pScreenPriv->udpPort = 0; -+ pScreenPriv->rfbListenSock = -1; -+ pScreenPriv->udpSock = -1; -+ pScreenPriv->udpSockConnected = FALSE; -+ pScreenPriv->httpListenSock = -1; -+ pScreenPriv->httpSock = -1; -+ pScreenPriv->maxFd = 0; -+ pScreenPriv->rfbAuthPasswdFile = NULL; -+ pScreenPriv->httpDir = NULL; -+ pScreenPriv->rfbInstalledColormap = NULL; -+ pScreenPriv->interface.s_addr = htonl (INADDR_ANY); -+ -+ pScreenPriv->rfbPort = 0; -+ xf86GetOptValInteger(options, OPTION_RFBPORT, &pScreenPriv->rfbPort); -+ pScreenPriv->httpPort = 0; -+ xf86GetOptValInteger(options, OPTION_HTTPPORT, &pScreenPriv->httpPort); -+ pScreenPriv->rfbAuthPasswdFile = -+ xf86GetOptValString(options, OPTION_PASSWD_FILE); -+ pScreenPriv->httpDir = -+ xf86GetOptValString(options, OPTION_HTTPDIR); -+ pScreenPriv->rfbAlwaysShared = FALSE; -+ xf86GetOptValBool(options, OPTION_ALWAYS_SHARED, -+ &pScreenPriv->rfbAlwaysShared); -+ pScreenPriv->rfbNeverShared = FALSE; -+ xf86GetOptValBool(options, OPTION_NEVER_SHARED, -+ &pScreenPriv->rfbNeverShared); -+ pScreenPriv->rfbUserAccept = FALSE; -+ xf86GetOptValBool(options, OPTION_USER_ACCEPT, -+ &pScreenPriv->rfbUserAccept); -+ pScreenPriv->useGetImage = FALSE; -+ xf86GetOptValBool(options, OPTION_USE_GETIMAGE, -+ &pScreenPriv->useGetImage); -+ pScreenPriv->rfbViewOnly = FALSE; -+ xf86GetOptValBool(options, OPTION_VIEWONLY, -+ &pScreenPriv->rfbViewOnly); -+ pScreenPriv->rfbDontDisconnect = FALSE; -+ xf86GetOptValBool(options, OPTION_DONT_DISCONNECT, -+ &pScreenPriv->rfbDontDisconnect); -+ pScreenPriv->loginAuthEnabled = FALSE; -+ xf86GetOptValBool(options, OPTION_LOGIN_AUTH, -+ &pScreenPriv->loginAuthEnabled); -+ -+ if (xf86ReturnOptValBool(options, OPTION_LOCALHOST, FALSE)) -+ pScreenPriv->interface.s_addr = htonl (INADDR_LOOPBACK); -+ -+ interface_str = xf86GetOptValString(options, OPTION_INTERFACE); -+ -+ if (interface_str && pScreenPriv->interface.s_addr == htonl(INADDR_ANY)) { -+ Bool failed = FALSE; -+ struct in_addr got; -+ unsigned long octet; -+ char *p = interface_str, *end; -+ int q; -+ -+ for (q = 0; q < 4; q++) { -+ octet = strtoul (p, &end, 10); -+ -+ if (p == end || octet > 255) -+ failed = TRUE; -+ -+ if ((q < 3 && *end != '.') || -+ (q == 3 && *end != '\0')) -+ failed = TRUE; -+ -+ got.s_addr = (got.s_addr << 8) | octet; -+ p = end + 1; -+ } -+ -+ if (!failed) -+ pScreenPriv->interface.s_addr = htonl (got.s_addr); -+ else -+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VNC interface option malformed, not using.\n"); -+ } -+ -+ xfree(options); -+ -+ if (!VNC_LAST_CLIENT_ID) -+ VNC_LAST_CLIENT_ID = MakeAtom("VNC_LAST_CLIENT_ID", -+ strlen("VNC_LAST_CLIENT_ID"), TRUE); -+ if (!VNC_CONNECT) -+ VNC_CONNECT = MakeAtom("VNC_CONNECT", strlen("VNC_CONNECT"), TRUE); -+ -+ rfbInitSockets(pScreen); -+ if (inetdSock == -1) -+ httpInitSockets(pScreen); -+ -+#ifdef CORBA -+ initialiseCORBA(argc, argv, desktopName); -+#endif -+ -+ pScreenPriv->width = pScrn->virtualX; -+ pScreenPriv->height = pScrn->virtualY; -+ pScreenPriv->depth = pScrn->depth; -+ pScreenPriv->paddedWidthInBytes = PixmapBytePad(pScrn->displayWidth, pScrn->depth); -+ pScreenPriv->bitsPerPixel = rfbBitsPerPixel(pScrn->depth); -+ pScreenPriv->pfbMemory = FBStart; -+ pScreenPriv->oldpfbMemory = FBStart; -+ -+ pScreenPriv->cursorIsDrawn = TRUE; -+ pScreenPriv->dontSendFramebufferUpdate = FALSE; -+ -+ pScreenPriv->CloseScreen = pScreen->CloseScreen; -+ pScreenPriv->CreateGC = pScreen->CreateGC; -+ pScreenPriv->PaintWindowBackground = pScreen->PaintWindowBackground; -+ pScreenPriv->PaintWindowBorder = pScreen->PaintWindowBorder; -+ pScreenPriv->CopyWindow = pScreen->CopyWindow; -+ pScreenPriv->ClearToBackground = pScreen->ClearToBackground; -+ pScreenPriv->RestoreAreas = pScreen->RestoreAreas; -+ pScreenPriv->WakeupHandler = pScreen->WakeupHandler; -+ pScreenPriv->EnableDisableFBAccess = pScrn->EnableDisableFBAccess; -+ pScreenPriv->InstallColormap = pScreen->InstallColormap; -+ pScreenPriv->UninstallColormap = pScreen->UninstallColormap; -+ pScreenPriv->ListInstalledColormaps = pScreen->ListInstalledColormaps; -+ pScreenPriv->StoreColors = pScreen->StoreColors; -+ pScreenPriv->DisplayCursor = pScreen->DisplayCursor; -+#ifdef CHROMIUM -+ pScreenPriv->RealizeWindow = pScreen->RealizeWindow; -+ pScreenPriv->UnrealizeWindow = pScreen->UnrealizeWindow; -+ pScreenPriv->DestroyWindow = pScreen->DestroyWindow; -+ pScreenPriv->PositionWindow = pScreen->PositionWindow; -+ pScreenPriv->ResizeWindow = pScreen->ResizeWindow; -+ pScreenPriv->ClipNotify = pScreen->ClipNotify; -+#endif -+#ifdef RENDER -+ ps = GetPictureScreenIfSet(pScreen); -+ if (ps) -+ pScreenPriv->Composite = ps->Composite; -+#endif -+ pScreen->CloseScreen = rfbCloseScreen; -+ pScreen->CreateGC = rfbCreateGC; -+ pScreen->PaintWindowBackground = rfbPaintWindowBackground; -+ pScreen->PaintWindowBorder = rfbPaintWindowBorder; -+ pScreen->CopyWindow = rfbCopyWindow; -+ pScreen->ClearToBackground = rfbClearToBackground; -+ pScreen->RestoreAreas = rfbRestoreAreas; -+ pScreen->WakeupHandler = rfbWakeupHandler; -+ pScrn->EnableDisableFBAccess = rfbEnableDisableFBAccess; -+ pScreen->InstallColormap = rfbInstallColormap; -+ pScreen->UninstallColormap = rfbUninstallColormap; -+ pScreen->ListInstalledColormaps = rfbListInstalledColormaps; -+ pScreen->StoreColors = rfbStoreColors; -+ pScreen->DisplayCursor = vncDisplayCursor; /* it's defined in here */ -+ -+#ifdef CHROMIUM -+ pScreen->RealizeWindow = rfbRealizeWindow; -+ pScreen->UnrealizeWindow = rfbUnrealizeWindow; -+ pScreen->DestroyWindow = rfbDestroyWindow; -+ pScreen->PositionWindow = rfbPositionWindow; -+ pScreen->ResizeWindow = rfbResizeWindow; -+ pScreen->ClipNotify = rfbClipNotify; -+#endif -+#ifdef RENDER -+ if (ps) -+ ps->Composite = rfbComposite; -+#endif -+ -+ for (visual = pScreen->visuals; visual->vid != pScreen->rootVisual; visual++) -+ ; -+ -+ if (!visual) { -+ ErrorF("rfbScreenInit: couldn't find root visual\n"); -+ return FALSE; -+ } -+ -+ pScreenPriv->rfbServerFormat.bitsPerPixel = pScrn->bitsPerPixel; -+ pScreenPriv->rfbServerFormat.depth = pScrn->depth; -+ pScreenPriv->rfbServerFormat.bigEndian = !(*(char *)&rfbEndianTest); -+ pScreenPriv->rfbServerFormat.trueColour = (visual->class == TrueColor); -+ if (pScreenPriv->rfbServerFormat.trueColour) { -+ pScreenPriv->rfbServerFormat.redMax = visual->redMask >> visual->offsetRed; -+ pScreenPriv->rfbServerFormat.greenMax = visual->greenMask >> visual->offsetGreen; -+ pScreenPriv->rfbServerFormat.blueMax = visual->blueMask >> visual->offsetBlue; -+ pScreenPriv->rfbServerFormat.redShift = visual->offsetRed; -+ pScreenPriv->rfbServerFormat.greenShift = visual->offsetGreen; -+ pScreenPriv->rfbServerFormat.blueShift = visual->offsetBlue; -+ } else { -+ pScreenPriv->rfbServerFormat.redMax -+ = pScreenPriv->rfbServerFormat.greenMax -+ = pScreenPriv->rfbServerFormat.blueMax = 0; -+ pScreenPriv->rfbServerFormat.redShift -+ = pScreenPriv->rfbServerFormat.greenShift -+ = pScreenPriv->rfbServerFormat.blueShift = 0; -+ } -+ -+ PointPriv = pScreen->devPrivates[miPointerScreenIndex].ptr; -+ -+ pScreenPriv->spriteFuncs = PointPriv->spriteFuncs; -+ PointPriv->spriteFuncs = &vncCursorSpriteFuncs; -+ -+ if (xf86LoaderCheckSymbol("xf86CursorScreenIndex")) { -+ int *si; -+ -+ si = LoaderSymbol("xf86CursorScreenIndex"); -+ -+ if (*si != -1) { -+ xf86CursorPriv = pScreen->devPrivates[*si].ptr; -+ -+ if (xf86CursorPriv) { -+ pScreenPriv->UseHWCursor = xf86CursorPriv->CursorInfoPtr->UseHWCursor; -+ xf86CursorPriv->CursorInfoPtr->UseHWCursor = vncUseHWCursor; -+#ifdef ARGB_CURSOR -+ pScreenPriv->UseHWCursorARGB = xf86CursorPriv->CursorInfoPtr->UseHWCursorARGB; -+ xf86CursorPriv->CursorInfoPtr->UseHWCursorARGB = vncUseHWCursorARGB; -+#endif -+ pScreenPriv->SWCursor = &xf86CursorPriv->SWCursor; -+ } -+ } -+ } -+ -+ return TRUE; -+} -+ -+/****** miPointerSpriteFunctions *******/ -+ -+static Bool -+vncCursorRealizeCursor(ScreenPtr pScreen, CursorPtr pCurs) -+{ -+ vncScreenPtr pScreenPriv = VNCPTR(pScreen); -+ -+ return (*pScreenPriv->spriteFuncs->RealizeCursor)(pScreen, pCurs); -+} -+ -+static Bool -+vncCursorUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCurs) -+{ -+ vncScreenPtr pScreenPriv = VNCPTR(pScreen); -+ -+ return (*pScreenPriv->spriteFuncs->UnrealizeCursor)(pScreen, pCurs); -+} -+ -+static void -+vncCursorSetCursor(ScreenPtr pScreen, CursorPtr pCurs, int x, int y) -+{ -+ vncScreenPtr pScreenPriv = VNCPTR(pScreen); -+ -+ pScreenPriv->pCurs = pCurs; -+ -+ /* Without this call, cursor changes only appear in the viewer when -+ * some other drawing has occured. Added by BrianP. -+ */ -+ rfbScheduleUpdate(pScreen); -+ -+#if 0 -+ if (pCurs == NullCursor) { /* means we're supposed to remove the cursor */ -+ if (pScreenPriv->cursorIsDrawn) -+ pScreenPriv->cursorIsDrawn = FALSE; -+ return; -+ } -+ -+ pScreenPriv->cursorIsDrawn = TRUE; -+#endif -+ -+ (*pScreenPriv->spriteFuncs->SetCursor)(pScreen, pCurs, x, y); -+} -+ -+static void -+vncCursorMoveCursor(ScreenPtr pScreen, int x, int y) -+{ -+ vncScreenPtr pScreenPriv = VNCPTR(pScreen); -+ rfbClientPtr cl; -+ -+ for (cl = rfbClientHead; cl ; cl = cl->next) { -+ if (cl->enableCursorPosUpdates) -+ cl->cursorWasMoved = TRUE; -+ } -+ -+ (*pScreenPriv->spriteFuncs->MoveCursor)(pScreen, x, y); -+} -+ -+Bool -+vncUseHWCursor(pScreen, pCursor) -+ ScreenPtr pScreen; -+ CursorPtr pCursor; -+{ -+ vncScreenPtr pScreenPriv = VNCPTR(pScreen); -+ rfbClientPtr cl; -+ -+ if (!*pScreenPriv->UseHWCursor) { -+ /* If the driver doesn't have a UseHWCursor function we're -+ * basically saying we can have the HWCursor on all the time -+ */ -+ pScreenPriv->SWCursor = (Bool *)FALSE; -+ return TRUE; -+ } -+ -+ pScreenPriv->SWCursor = (Bool *)FALSE; -+ -+ /* If someone's connected, we revert to software cursor */ -+ for (cl = rfbClientHead; cl ; cl = cl->next) { -+ if (!cl->enableCursorShapeUpdates) -+ pScreenPriv->SWCursor = (Bool *)TRUE; -+ } -+ -+ if (pScreenPriv->SWCursor == (Bool *)TRUE) -+ return FALSE; -+ -+ return (*pScreenPriv->UseHWCursor)(pScreen, pCursor); -+} -+ -+#ifdef ARGB_CURSOR -+#include "cursorstr.h" -+ -+Bool -+vncUseHWCursorARGB(pScreen, pCursor) -+ ScreenPtr pScreen; -+ CursorPtr pCursor; -+{ -+ vncScreenPtr pScreenPriv = VNCPTR(pScreen); -+ rfbClientPtr cl; -+ -+ if (!*pScreenPriv->UseHWCursorARGB) { -+ pScreenPriv->SWCursor = (Bool *)TRUE; -+ return FALSE; -+ } -+ -+ pScreenPriv->SWCursor = (Bool *)FALSE; -+ -+ /* If someone's connected, we revert to software cursor */ -+ for (cl = rfbClientHead; cl ; cl = cl->next) { -+ if (!cl->enableCursorShapeUpdates) -+ pScreenPriv->SWCursor = (Bool *)TRUE; -+ } -+ -+ if (pScreenPriv->SWCursor == (Bool *)TRUE) -+ return FALSE; -+ -+ return (*pScreenPriv->UseHWCursorARGB)(pScreen, pCursor); -+} -+#endif -+ -+static Bool -+vncDisplayCursor(pScreen, pCursor) -+ ScreenPtr pScreen; -+ CursorPtr pCursor; -+{ -+ vncScreenPtr pScreenPriv = VNCPTR(pScreen); -+ rfbClientPtr cl; -+ Bool ret; -+ -+ pScreen->DisplayCursor = pScreenPriv->DisplayCursor; -+ -+ for (cl = rfbClientHead; cl ; cl = cl->next) { -+ if (cl->enableCursorShapeUpdates) -+ cl->cursorWasChanged = TRUE; -+ } -+ -+ ret = (*pScreen->DisplayCursor)(pScreen, pCursor); -+ -+ pScreen->DisplayCursor = vncDisplayCursor; -+ -+ return ret; -+} -+ -+static void -+rfbWakeupHandler ( -+ int i, -+ pointer blockData, -+ unsigned long err, -+ pointer pReadmask -+){ -+ ScreenPtr pScreen = screenInfo.screens[i]; -+ vncScreenPtr pScreenPriv = VNCPTR(pScreen); -+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; -+ int sigstate = xf86BlockSIGIO(); -+ -+ rfbRootPropertyChange(pScreen); /* Check clipboard */ -+ -+ if (pScrn->vtSema) { -+ rfbCheckFds(pScreen); -+ httpCheckFds(pScreen); -+#ifdef CORBA -+ corbaCheckFds(); -+#endif -+ } else { -+ rfbCheckFds(pScreen); -+ } -+ -+ xf86UnblockSIGIO(sigstate); -+ -+ pScreen->WakeupHandler = pScreenPriv->WakeupHandler; -+ (*pScreen->WakeupHandler) (i, blockData, err, pReadmask); -+ pScreen->WakeupHandler = rfbWakeupHandler; -+} -+ -+#ifdef XFree86LOADER -+static MODULESETUPPROTO(vncSetup); -+ -+static XF86ModuleVersionInfo vncVersRec = -+{ -+ "vnc", -+ "xf4vnc Project, see http://xf4vnc.sf.net (based on modular X.org)", -+ MODINFOSTRING1, -+ MODINFOSTRING2, -+ XORG_VERSION_CURRENT, -+ 1, 1, 0, -+ ABI_CLASS_EXTENSION, -+#if 0 -+ ABI_EXTENSION_VERSION, -+#else -+ /* Hack to allow module to work with more servers (vs. 0.3 above) */ -+ SET_ABI_VERSION(0, 2), -+#endif -+ MOD_CLASS_EXTENSION, -+ {0,0,0,0} -+}; -+ -+XF86ModuleData vncModuleData = { -+ &vncVersRec, /* vers */ -+ vncSetup, /* ModuleSetupProc */ -+ NULL /* ModuleTearDownProc */ -+}; -+ -+ModuleInfoRec VNC = { -+ 1, /* moduleVersion */ -+ "VNC", /* moduleName */ -+ NULL, /* module pointer */ -+ 0, /* refCount */ -+ VNCAvailableOptions, /* function returning array of OptionsInfoRec */ -+}; -+ -+ExtensionModule vncExtensionModule = { -+ VncExtensionInit, /* initFunc */ -+ "VNC", /* name */ -+ NULL, /* disablePtr */ -+ NULL, /* setupFunc */ -+ NULL /* initDependencies */ -+}; -+ -+ -+/*ARGSUSED*/ -+static pointer -+vncSetup(pointer Module, pointer Options, int *ErrorMajor, int *ErrorMinor) -+{ -+ static Bool Initialised = FALSE; -+ -+ if (!Initialised) { -+ Initialised = TRUE; -+#ifndef REMOVE_LOADER_CHECK_MODULE_INFO -+ if (xf86LoaderCheckSymbol("xf86AddModuleInfo")) -+#endif -+ xf86AddModuleInfo(&VNC, Module); -+ } -+ -+ LoadExtension(&vncExtensionModule, FALSE); -+ /* add mouse/kbd input drivers */ -+ vncInitMouse(); -+ vncInitKeyb(); -+ xf86Msg(X_INFO, "Ignore errors regarding the loading of the rfbmouse & rfbkeyb drivers\n"); -+ -+ return (pointer)TRUE; -+} -+#endif -diff --git a/hw/xfree86/vnc/vncauth.h b/hw/xfree86/vnc/vncauth.h -new file mode 100644 -index 0000000..5ece2e1 ---- /dev/null -+++ b/hw/xfree86/vnc/vncauth.h -@@ -0,0 +1,34 @@ -+/* -+ * 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. -+ */ -+ -+/* -+ * vncauth.h - describes the functions provided by the vncauth library. -+ */ -+ -+#define MAXPWLEN 8 -+#define CHALLENGESIZE 16 -+ -+extern int vncEncryptAndStorePasswd(char *passwd, char *fname); -+extern char *vncDecryptPasswdFromFile(char *fname); -+extern void vncRandomBytes(unsigned char *bytes); -+extern void vncEncryptBytes(unsigned char *bytes, char *passwd); -+ -+extern int vncEncryptAndStorePasswd2(char *passwd, char *passwdViewOnly, char *fname); -+extern int vncDecryptPasswdFromFile2(char *fname, char *passwdFullControl, char *passwdViewOnly); -+ -diff --git a/hw/xfree86/vnc/vncext.c b/hw/xfree86/vnc/vncext.c -new file mode 100644 -index 0000000..f7d7d5a ---- /dev/null -+++ b/hw/xfree86/vnc/vncext.c -@@ -0,0 +1,791 @@ -+/* -+ * Copyright (C) 2002 Alan Hourihane. 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. -+ * -+ * Author: Alan Hourihane -+ */ -+ -+#include "rfb.h" -+#include "extnsionst.h" -+#define _VNC_SERVER -+#include -+#ifdef XFree86LOADER -+#include "xf86Module.h" -+#endif -+ -+#include -+#include -+#include -+#include -+#include -+ -+int VncSelectNotify(ClientPtr client, BOOL onoff); -+void VncExtensionInit(void); -+ -+static int VncErrorBase; /* first vnc error number */ -+static int VncEventBase; /* first vnc event number */ -+ -+#define USE_ORIG_RES_CODE 0 -+ -+#if USE_ORIG_RES_CODE -+unsigned long VncResourceGeneration = 0; -+ -+static RESTYPE VncNotifyList; -+ -+static XID faked; -+ -+typedef struct _VncNotifyListRec { -+ struct _VncNotifyListRec *next; -+ ClientPtr client; -+} VncNotifyListRec, *VncNotifyListPtr; -+#endif -+ -+ -+/** -+ * Each X client that uses libVnc to talk to this extension will get -+ * recorded by one of these records. -+ */ -+typedef struct _VncClientRec { -+ ClientPtr client; -+ struct _VncClientRec *next; -+ XID fakeID; -+ RESTYPE res; -+} VncClientRec, *VncClientRecPtr; -+ -+static VncClientRecPtr ClientsList = NULL; -+ -+ -+/** -+ * Remove client record from list -+ */ -+static void -+VncRemoveClientRecord(ClientPtr client) -+{ -+ /* XXX need 'deleteresource' flag? */ -+ VncClientRecPtr p = ClientsList, prev = NULL; -+ rfbLog("%s client %p\n", __func__, (void *) client); -+ while (p) { -+ if (p->client == client) { -+ /* remove this one */ -+ if (prev) -+ prev->next = p->next; -+ else -+ ClientsList = p->next; -+ xfree(p); -+ return; -+ } -+ prev = p; -+ p = p->next; -+ } -+} -+ -+ -+/** -+ * This callback will be called by X's resource manager to delete the -+ * given resource. We create one resource for each client. When X -+ * deletes the resource, we know the client is going away. -+ */ -+static int -+VncDestroyClientResourceCallback(pointer pn, XID id) -+{ -+ VncClientRecPtr rec = (VncClientRecPtr) pn; -+ VncRemoveClientRecord(rec->client); -+ return Success; -+} -+ -+ -+/** -+ * Add a client record to the list of clients (unless already in list). -+ * We'll create a new, unique resource for this client. This is used -+ * to detect when an X client goes away. -+ */ -+static void -+VncSaveClientRecord(ClientPtr client) -+{ -+ VncClientRecPtr rec = ClientsList; -+ -+ rfbLog("%s saving client %p\n", __func__, (void *) client); -+ -+ /* look if already in list */ -+ while (rec) { -+ if (rec->client == client) { -+ return; /* already in list */ -+ } -+ rec = rec->next; -+ } -+ -+ /* allocate new client record */ -+ rec = (VncClientRecPtr) xalloc(sizeof(VncClientRec)); -+ if (rec) { -+ rec->client = client; -+ rec->fakeID = FakeClientID(client->index); -+ rec->res = CreateNewResourceType(VncDestroyClientResourceCallback); -+ if (!AddResource(rec->fakeID, rec->res, rec)) { -+ xfree(rec); -+ } -+ -+ /* insert at head of list */ -+ rec->next = ClientsList; -+ ClientsList = rec; -+ } -+} -+ -+ -+ -+static int -+ProcVncQueryVersion(ClientPtr client) -+{ -+ xVncQueryVersionReply rep; -+ -+ REQUEST_SIZE_MATCH(xVncQueryVersionReq); -+ rep.type = X_Reply; -+ rep.sequenceNumber = client->sequence; -+ rep.length = 0; -+ rep.majorVersion = VNC_MAJOR_VERSION; -+ rep.minorVersion = VNC_MINOR_VERSION; -+ if(client->swapped) -+ { -+ register char n; -+ swaps(&rep.sequenceNumber, n); -+ swaps(&rep.majorVersion, n); -+ swaps(&rep.minorVersion, n); -+ } -+ (void)WriteToClient(client, SIZEOF(xVncQueryVersionReply), -+ (char *)&rep); -+ return (client->noClientException); -+} /* ProcVncQueryVersion */ -+ -+static int -+ProcVncConnection(ClientPtr client) -+{ -+ REQUEST(xVncConnectionReq); -+ xVncConnectionReply rep; -+ -+ rfbUserAllow( stuff->sock, stuff->accept ); -+ -+ REQUEST_SIZE_MATCH(xVncConnectionReq); -+ rep.type = X_Reply; -+ rep.sequenceNumber = client->sequence; -+ rep.length = 0; -+ rep.sock = 0; -+ rep.accept = 0; -+ if(client->swapped) -+ { -+ register char n; -+ swaps(&rep.sequenceNumber, n); -+ swaps(&rep.sock, n); -+ swaps(&rep.accept, n); -+ } -+ (void)WriteToClient(client, SIZEOF(xVncConnectionReply), -+ (char *)&rep); -+ return (client->noClientException); -+} /* ProcVncConnection */ -+ -+static int -+ProcVncSelectNotify(ClientPtr client) -+{ -+ REQUEST(xVncSelectNotifyReq); -+ xVncSelectNotifyReply rep; -+ -+ VncSelectNotify(client, stuff->onoff); -+ -+ REQUEST_SIZE_MATCH(xVncSelectNotifyReq); -+ rep.type = X_Reply; -+ rep.sequenceNumber = client->sequence; -+ rep.length = 0; -+ if(client->swapped) -+ { -+ register char n; -+ swaps(&rep.sequenceNumber, n); -+ } -+ (void)WriteToClient(client, SIZEOF(xVncSelectNotifyReply), -+ (char *)&rep); -+ return (client->noClientException); -+ -+} -+ -+static int -+ProcVncListConnections(ClientPtr client) -+{ -+ xVncListConnectionsReply rep; -+ rfbClientPtr cl; -+ int count = 0; -+ struct in_addr ipaddress; -+ xVncConnectionListInfo Info; -+ -+ /* count connections */ -+ for (cl = rfbClientHead; cl; cl = cl->next) -+#ifdef CHROMIUM -+ /* -+ * Fix this, as it should be generic, but we're only using it -+ * for Chromium at the moment, so we only list the connections -+ * that have a valid chromium encoding. We should be able to list -+ * any type requested. FIXME! XXXX -+ * See furthur down this function too!!! -+ */ -+ if (cl->enableChromiumEncoding) -+#endif -+ count++; -+ -+ REQUEST_SIZE_MATCH(xVncListConnectionsReq); -+ rep.type = X_Reply; -+ rep.sequenceNumber = client->sequence; -+ rep.count = count; -+ rep.length = count * sizeof(xVncConnectionListInfo) >> 2; -+ if(client->swapped) -+ { -+ register char n; -+ swaps(&rep.sequenceNumber, n); -+ swaps(&rep.count, n); -+ } -+ (void)WriteToClient(client, SIZEOF(xVncListConnectionsReply), -+ (char *)&rep); -+ -+ for (cl = rfbClientHead; cl; cl = cl->next) { -+#ifdef CHROMIUM -+ /* -+ * Fix this, as it should be generic, but we're only using it -+ * for Chromium at the moment, so we only list the connections -+ * that have a valid chromium encoding. We should be able to list -+ * any type requested. FIXME! XXXX -+ */ -+ if (!cl->enableChromiumEncoding) -+ continue; -+#endif -+ inet_aton(cl->host, &ipaddress); -+ memcpy(&Info, &ipaddress, sizeof(struct in_addr)); -+ WriteToClient(client, SIZEOF(xVncConnectionListInfo), (char*)&Info); -+ } -+ -+ return (client->noClientException); -+} /* ProcVncListConnections */ -+ -+#ifdef CHROMIUM -+static int -+ProcVncChromiumStart(ClientPtr client) -+{ -+ REQUEST(xVncChromiumStartReq); -+ xVncChromiumStartReply rep; -+ -+ rfbSendChromiumStart(stuff->ipaddress, stuff->crServerPort, stuff->mothershipPort); -+ -+ REQUEST_SIZE_MATCH(xVncChromiumStartReq); -+ rep.type = X_Reply; -+ rep.sequenceNumber = client->sequence; -+ rep.length = 0; -+ if(client->swapped) -+ { -+ register char n; -+ swaps(&rep.sequenceNumber, n); -+ } -+ (void)WriteToClient(client, SIZEOF(xVncChromiumStartReply), -+ (char *)&rep); -+ return (client->noClientException); -+} /* ProcVncChromiumStart */ -+ -+static int -+ProcVncChromiumMonitor(ClientPtr client) -+{ -+ REQUEST(xVncChromiumMonitorReq); -+ xVncChromiumMonitorReply rep; -+ -+ rfbChromiumMonitorWindowID(stuff->cr_windowid, stuff->windowid); -+ -+ REQUEST_SIZE_MATCH(xVncChromiumMonitorReq); -+ rep.type = X_Reply; -+ rep.sequenceNumber = client->sequence; -+ rep.length = 0; -+ if(client->swapped) -+ { -+ register char n; -+ swaps(&rep.sequenceNumber, n); -+ } -+ (void)WriteToClient(client, SIZEOF(xVncChromiumMonitorReply), -+ (char *)&rep); -+ return (client->noClientException); -+} /* ProcVncChromiumMonitor */ -+#endif /* CHROMIUM */ -+ -+static int -+ProcVncDispatch(ClientPtr client) -+{ -+ REQUEST(xReq); -+ -+ switch (stuff->data) -+ { -+ case X_VncQueryVersion: -+ return ProcVncQueryVersion(client); -+ case X_VncSelectNotify: -+ return ProcVncSelectNotify(client); -+ case X_VncConnection: -+ return ProcVncConnection(client); -+ case X_VncListConnections: -+ return ProcVncListConnections(client); -+#ifdef CHROMIUM -+ case X_VncChromiumStart: -+ return ProcVncChromiumStart(client); -+ case X_VncChromiumMonitor: -+ return ProcVncChromiumMonitor(client); -+#endif -+ default: -+ return BadRequest; -+ } -+} /* ProcVncDispatch */ -+ -+static int -+SProcVncQueryVersion(ClientPtr client) -+{ -+ REQUEST(xVncQueryVersionReq); -+ register char n; -+ -+ swaps(&stuff->length, n); -+ REQUEST_SIZE_MATCH(xVncQueryVersionReq); -+ swaps(&stuff->majorVersion, n); -+ swaps(&stuff->minorVersion,n); -+ return ProcVncQueryVersion(client); -+} /* SProcVncQueryVersion */ -+ -+static int -+SProcVncSelectNotify(ClientPtr client) -+{ -+ REQUEST(xVncSelectNotifyReq); -+ register char n; -+ -+ swaps(&stuff->length, n); -+ REQUEST_SIZE_MATCH(xVncSelectNotifyReq); -+ return ProcVncSelectNotify(client); -+} /* SProcVncSelectNotify */ -+ -+static int -+SProcVncListConnections(ClientPtr client) -+{ -+ REQUEST(xVncListConnectionsReq); -+ register char n; -+ -+ swaps(&stuff->length, n); -+ REQUEST_SIZE_MATCH(xVncListConnectionsReq); -+ return ProcVncListConnections(client); -+} /* SProcVncListConnections */ -+ -+#ifdef CHROMIUM -+static int -+SProcVncChromiumStart(ClientPtr client) -+{ -+ REQUEST(xVncChromiumStartReq); -+ register char n; -+ -+ swaps(&stuff->ipaddress, n); -+ swaps(&stuff->crServerPort, n); -+ swaps(&stuff->mothershipPort, n); -+ swaps(&stuff->length, n); -+ REQUEST_SIZE_MATCH(xVncChromiumStartReq); -+ return ProcVncChromiumStart(client); -+} /* SProcVncChromiumStart */ -+ -+static int -+SProcVncChromiumMonitor(ClientPtr client) -+{ -+ REQUEST(xVncChromiumMonitorReq); -+ register char n; -+ -+ swaps(&stuff->length, n); -+ swaps(&stuff->windowid, n); -+ swaps(&stuff->cr_windowid, n); -+ REQUEST_SIZE_MATCH(xVncChromiumMonitorReq); -+ return ProcVncChromiumMonitor(client); -+} /* SProcVncChromiumMonitor */ -+#endif /* CHROMIUM */ -+ -+static int -+SProcVncConnection(ClientPtr client) -+{ -+ REQUEST(xVncConnectionReq); -+ register char n; -+ -+ -+ swaps(&stuff->length, n); -+ REQUEST_SIZE_MATCH(xVncConnectionReq); -+ swaps(&stuff->sock, n); -+ swaps(&stuff->accept,n); -+ return ProcVncConnection(client); -+} /* SProcVncConnection */ -+ -+static int -+SProcVncDispatch(ClientPtr client) -+{ -+ REQUEST(xReq); -+ -+ switch (stuff->data) -+ { -+ case X_VncQueryVersion: -+ return SProcVncQueryVersion(client); -+ case X_VncSelectNotify: -+ return SProcVncSelectNotify(client); -+ case X_VncConnection: -+ return SProcVncConnection(client); -+ case X_VncListConnections: -+ return SProcVncListConnections(client); -+#ifdef CHROMIUM -+ case X_VncChromiumStart: -+ return SProcVncChromiumStart(client); -+ case X_VncChromiumMonitor: -+ return SProcVncChromiumMonitor(client); -+#endif -+ default: -+ return BadRequest; -+ } -+} /* SProcVncDispatch */ -+ -+static void -+SwapVncConnectedEvent(xVncConnectedEvent *from, xVncConnectedEvent *to) -+{ -+ to->type = from->type; -+ to->detail = from->detail; -+ cpswaps(from->sequenceNumber, to->sequenceNumber); -+ cpswapl(from->connected, to->connected); -+} -+ -+#ifdef CHROMIUM -+static void -+SwapVncChromiumConnectedEvent(xVncConnectedEvent *from, xVncConnectedEvent *to) -+{ -+ to->type = from->type; -+ to->detail = from->detail; -+ cpswaps(from->sequenceNumber, to->sequenceNumber); -+ cpswapl(from->connected, to->connected); -+} -+#endif -+ -+static void -+SwapVncDisconnectedEvent(xVncConnectedEvent *from, xVncConnectedEvent *to) -+{ -+ to->type = from->type; -+ to->detail = from->detail; -+ cpswaps(from->sequenceNumber, to->sequenceNumber); -+ cpswapl(from->connected, to->connected); -+} -+ -+int -+GenerateVncConnectedEvent(int sock) -+{ -+#if USE_ORIG_RES_CODE -+ VncNotifyListPtr pn; -+ -+ pn = (VncNotifyListPtr)LookupIDByType(faked, VncNotifyList); -+#else -+ VncClientRecPtr pn = ClientsList; -+#endif -+ -+ while (pn) -+ { -+ if (pn->client) -+ { -+ xVncConnectedEvent conn; -+ SOCKLEN_T peer_len; -+ struct sockaddr_in peer; -+ -+ conn.type = VncEventBase + XVncConnected; -+ conn.sequenceNumber = pn->client->sequence; -+ conn.connected = sock; -+ -+ peer_len = sizeof(peer); -+ if (getpeername(sock, (struct sockaddr *) &peer, &peer_len) == -1) -+ conn.ipaddress = 0; -+ else -+ conn.ipaddress = (CARD32)peer.sin_addr.s_addr; -+ -+ (void) TryClientEvents(pn->client, (xEventPtr)&conn, 1, NoEventMask, -+ NoEventMask, NullGrab); -+ } -+ pn = pn->next; -+ } -+ -+ return 1; -+} -+ -+ -+ -+#ifdef CHROMIUM -+int -+GenerateVncChromiumConnectedEvent(int sock) -+{ -+#if USE_ORIG_RES_CODE -+ VncNotifyListPtr pn; -+ pn = (VncNotifyListPtr)LookupIDByType(faked, VncNotifyList); -+#else -+ VncClientRecPtr pn = ClientsList; -+#endif -+ rfbLog("Enter GenerateVncChromiumConnectedEvent\n"); -+ while (pn) -+ { -+ if (pn->client) -+ { -+ xVncConnectedEvent conn; -+ SOCKLEN_T peer_len; -+ struct sockaddr_in peer; -+ -+ rfbLog("Sending XVncChromiumConnected to client %p\n", -+ (void *) pn->client); -+ -+ conn.type = VncEventBase + XVncChromiumConnected; -+ conn.sequenceNumber = pn->client->sequence; -+ conn.connected = sock; -+ -+ peer_len = sizeof(peer); -+ if (getpeername(sock, (struct sockaddr *)&peer, &peer_len) == -1) -+ conn.ipaddress = 0; -+ else -+ conn.ipaddress = (CARD32)peer.sin_addr.s_addr; -+ -+ (void) TryClientEvents(pn->client, (xEventPtr)&conn, 1, NoEventMask, -+ NoEventMask, NullGrab); -+ } -+ pn = pn->next; -+ } -+ return 1; -+} -+#endif /* CHROMIUM */ -+ -+ -+int -+GenerateVncDisconnectedEvent(int sock) -+{ -+#if USE_ORIG_RES_CODE -+ VncNotifyListPtr pn; -+ -+ pn = (VncNotifyListPtr)LookupIDByType(faked, VncNotifyList); -+#else -+ VncClientRecPtr pn = ClientsList; -+#endif -+ while (pn) -+ { -+ if (pn->client) -+ { -+ xVncDisconnectedEvent conn; -+ conn.type = VncEventBase + XVncDisconnected; -+ conn.sequenceNumber = pn->client->sequence; -+ conn.connected = sock; -+ (void) TryClientEvents(pn->client, (xEventPtr)&conn, 1, NoEventMask, -+ NoEventMask, NullGrab); -+ } -+ pn = pn->next; -+ } -+ -+ return 1; -+} -+ -+static void -+VncResetProc(ExtensionEntry *extEntry) -+{ -+} /* VncResetProc */ -+ -+ -+ -+/** -+ * When the app calls libVnc's XVncSelectNotify() we wind up here. -+ * Either add or remove 'client' from the VncNotifyList depending on 'onoff'. -+ */ -+int -+VncSelectNotify(ClientPtr client, BOOL onoff) -+{ -+#if USE_ORIG_RES_CODE -+ VncNotifyListPtr head, newRec, tmp, freeRec = NULL; -+ -+ rfbLog("%s client %p onoff=%d\n", __func__, (void *) client, (int) onoff); -+ if (!faked) -+ faked = FakeClientID(client->index); -+#else -+ /* ignore onoff param */ -+ VncSaveClientRecord(client); -+#endif -+ -+#if USE_ORIG_RES_CODE -+ /* Get the first VncNotifyListPtr */ -+ head = (VncNotifyListPtr) LookupIDByType(faked, VncNotifyList); -+ -+ /* search list for this client */ -+ tmp = head; -+ while (tmp) { -+ if (tmp->client == client) { -+ /* found client! */ -+ if (!onoff) -+ tmp->client = NULL; -+ return Success; -+ } -+ if (!tmp->client) -+ freeRec = tmp; /* save ptr to free record */ -+ tmp = tmp->next; -+ } -+ -+ /* if we get here, we didn't find client in the list */ -+ -+ if (!onoff) { -+ /* if turning off non-existing client, just return */ -+ return Success; -+ } -+ -+ /* OK, add new client to list now */ -+ -+ if (freeRec) { -+ /* re-using a free spot */ -+ freeRec->client = client; -+ return Success; -+ } -+ -+ /* need to allocate new node */ -+ if (!(newRec = (VncNotifyListPtr)xalloc(sizeof(VncNotifyListRec)))) -+ return BadAlloc; -+ /* insert at head, just as AddResource() does!!! */ -+ newRec->next = head; -+ newRec->client = client; -+ if (!AddResource(faked, VncNotifyList, newRec)) { -+ xfree(newRec); -+ return BadAlloc; -+ } -+#endif -+ return Success; -+} -+ -+ -+#if USE_ORIG_RES_CODE -+static int -+VncDestroyNotifyList(pointer pn, XID id) -+{ -+ VncNotifyListPtr cpn = (VncNotifyListPtr) pn; -+ rfbLog("%s client %p\n", __func__, (void *) cpn->client); -+ cpn->client = NULL; -+ return Success; -+} -+#endif -+ -+static Bool -+CreateResourceTypes(void) -+{ -+#if USE_ORIG_RES_CODE -+ if (VncResourceGeneration == serverGeneration) -+ return TRUE; -+ -+ VncResourceGeneration = serverGeneration; -+ -+ if (!(VncNotifyList = CreateNewResourceType(VncDestroyNotifyList))) { -+ ErrorF("CreateResourceTypes: failed to allocate vnc notify list resource.\n"); -+ return FALSE; -+ } -+#endif -+ return TRUE; -+} -+ -+ -+ -+#if XFREE86VNC -+static unsigned long vncCreateScreenResourcesIndex; -+static unsigned long vncExtGeneration = 0; -+extern Bool VNCInit(ScreenPtr pScreen, unsigned char *FBStart); -+ -+/* copied from miscrinit.c */ -+typedef struct -+{ -+ pointer pbits; /* pointer to framebuffer */ -+ int width; /* delta to add to a framebuffer addr to move one row down */ -+} miScreenInitParmsRec, *miScreenInitParmsPtr; -+ -+ -+static Bool -+vncCreateScreenResources(ScreenPtr pScreen) -+{ -+ int ret = TRUE; -+ CreateScreenResourcesProcPtr CreateScreenResources = -+ (CreateScreenResourcesProcPtr) -+ pScreen->devPrivates[vncCreateScreenResourcesIndex].ptr; -+ miScreenInitParmsPtr pScrInitParms; -+ -+ pScrInitParms = (miScreenInitParmsPtr)pScreen->devPrivate; -+ -+ if ( pScreen->CreateScreenResources != vncCreateScreenResources ) { -+ /* Can't find hook we are hung on */ -+ xf86DrvMsg(pScreen->myNum, X_WARNING /* X_ERROR */, -+ "vncCreateScreenResources %p called when not in " -+ "pScreen->CreateScreenResources %p n", -+ (void *) vncCreateScreenResources, -+ (void *) pScreen->CreateScreenResources ); -+ } -+ -+ /* Now do our stuff */ -+ VNCInit(pScreen, pScrInitParms->pbits); -+ -+ /* Unhook this function ... */ -+ pScreen->CreateScreenResources = CreateScreenResources; -+ pScreen->devPrivates[vncCreateScreenResourcesIndex].ptr = NULL; -+ -+ /* ... and call the previous CreateScreenResources fuction, if any */ -+ if (pScreen->CreateScreenResources) { -+ ret = (*pScreen->CreateScreenResources)(pScreen); -+ } -+ -+ return ret; -+} -+#endif -+ -+ -+ -+void -+VncExtensionInit(void) -+{ -+ ExtensionEntry *extEntry; -+ -+#if XFREE86VNC -+ if (vncExtGeneration != serverGeneration) { -+ unsigned int i; -+ -+ vncExtGeneration = serverGeneration; -+ -+ if ( ((vncCreateScreenResourcesIndex = AllocateScreenPrivateIndex()) < 0) || -+ ((vncScreenPrivateIndex = AllocateScreenPrivateIndex()) < 0) || -+ ((rfbGCIndex = AllocateGCPrivateIndex()) < 0) ) -+ return; -+ -+ for (i = 0 ; i < screenInfo.numScreens; i++) -+ { -+ screenInfo.screens[i]->devPrivates[vncCreateScreenResourcesIndex].ptr -+ = (void*)(xf86Screens[i]->pScreen->CreateScreenResources); -+ xf86Screens[i]->pScreen->CreateScreenResources = vncCreateScreenResources; -+ } -+ -+ gethostname(rfbThisHost, 255); -+ } -+#endif -+ -+ if (!CreateResourceTypes()) -+ return; -+ -+ extEntry = AddExtension(VNC_EXTENSION_NAME, -+ XVncNumberEvents, XVncNumberErrors, -+ ProcVncDispatch, SProcVncDispatch, -+ VncResetProc, StandardMinorOpcode); -+ -+ VncErrorBase = extEntry->errorBase; -+ VncEventBase = extEntry->eventBase; -+ -+ EventSwapVector[VncEventBase + XVncConnected] = -+ (EventSwapPtr)SwapVncConnectedEvent; -+ EventSwapVector[VncEventBase + XVncDisconnected] = -+ (EventSwapPtr)SwapVncDisconnectedEvent; -+#ifdef CHROMIUM -+ EventSwapVector[VncEventBase + XVncChromiumConnected] = -+ (EventSwapPtr)SwapVncChromiumConnectedEvent; -+#endif -+} /* VncExtensionInit */ -diff --git a/hw/xfree86/vnc/vncint.h b/hw/xfree86/vnc/vncint.h -new file mode 100644 -index 0000000..53c4a81 ---- /dev/null -+++ b/hw/xfree86/vnc/vncint.h -@@ -0,0 +1,155 @@ -+/* -+ * Copyright (C) 2002 Alan Hourihane. 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. -+ * -+ * Author: Alan Hourihane -+ */ -+ -+#ifndef _VNC_H_ -+#define _VNC_H_ -+ -+#include -+/*#include */ -+ -+extern int vncScreenPrivateIndex; -+ -+#define VNCPTR(pScreen)\ -+ (vncScreenPtr)((pScreen)->devPrivates[vncScreenPrivateIndex].ptr) -+ -+typedef struct { -+ int rfbPort; -+ int rdpPort; -+ int udpPort; -+ int rfbListenSock; -+ int rdpListenSock; -+ int udpSock; -+ int httpPort; -+ int httpListenSock; -+ int httpSock; -+ char * httpDir; -+ char buf[HTTP_BUF_SIZE]; -+ Bool udpSockConnected; -+ char * rfbAuthPasswdFile; -+ size_t buf_filled; -+ int maxFd; -+ fd_set allFds; -+ unsigned char * oldpfbMemory; -+ Bool useGetImage; -+ Bool rfbAlwaysShared; -+ Bool rfbNeverShared; -+ Bool rfbDontDisconnect; -+ Bool rfbUserAccept; -+ Bool rfbViewOnly; -+ unsigned char * pfbMemory; -+ int paddedWidthInBytes; -+ ColormapPtr rfbInstalledColormap; -+ ColormapPtr savedColormap; -+ rfbPixelFormat rfbServerFormat; -+ Bool rfbAuthTooManyTries; -+ int rfbAuthTries; -+ Bool loginAuthEnabled; -+ struct in_addr interface; -+ OsTimerPtr timer; -+ char updateBuf[UPDATE_BUF_SIZE]; -+ int ublen; -+ int width; -+ int height; -+ int depth; -+ int bitsPerPixel; -+ -+ /* The following two members are used to minimise the amount of unnecessary -+ drawing caused by cursor movement. Whenever any drawing affects the -+ part of the screen where the cursor is, the cursor is removed first and -+ then the drawing is done (this is what the sprite routines test for). -+ Afterwards, however, we do not replace the cursor, even when the cursor -+ is logically being moved across the screen. We only draw the cursor -+ again just as we are about to send the client a framebuffer update. -+ -+ We need to be careful when removing and drawing the cursor because of -+ their relationship with the normal drawing routines. The drawing -+ routines can invoke the cursor routines, but also the cursor routines -+ themselves end up invoking drawing routines. -+ -+ Removing the cursor (rfbSpriteRemoveCursor) is eventually achieved by -+ doing a CopyArea from a pixmap to the screen, where the pixmap contains -+ the saved contents of the screen under the cursor. Before doing this, -+ however, we set cursorIsDrawn to FALSE. Then, when CopyArea is called, -+ it sees that cursorIsDrawn is FALSE and so doesn't feel the need to -+ (recursively!) remove the cursor before doing it. -+ -+ Putting up the cursor (rfbSpriteRestoreCursor) involves a call to -+ PushPixels. While this is happening, cursorIsDrawn must be FALSE so -+ that PushPixels doesn't think it has to remove the cursor first. -+ Obviously cursorIsDrawn is set to TRUE afterwards. -+ -+ Another problem we face is that drawing routines sometimes cause a -+ framebuffer update to be sent to the RFB client. When the RFB client is -+ already waiting for a framebuffer update and some drawing to the -+ framebuffer then happens, the drawing routine sees that the client is -+ ready, so it calls rfbSendFramebufferUpdate. If the cursor is not drawn -+ at this stage, it must be put up, and so rfbSpriteRestoreCursor is -+ called. However, if the original drawing routine was actually called -+ from within rfbSpriteRestoreCursor or rfbSpriteRemoveCursor we don't -+ want this to happen. So both the cursor routines set -+ dontSendFramebufferUpdate to TRUE, and all the drawing routines check -+ this before calling rfbSendFramebufferUpdate. */ -+ -+ Bool cursorIsDrawn; /* TRUE if the cursor is currently drawn */ -+ Bool dontSendFramebufferUpdate; /* TRUE while removing or drawing the -+ cursor */ -+ -+ /* wrapped screen functions */ -+ -+ CloseScreenProcPtr CloseScreen; -+ CreateGCProcPtr CreateGC; -+ PaintWindowBackgroundProcPtr PaintWindowBackground; -+ PaintWindowBorderProcPtr PaintWindowBorder; -+ CopyWindowProcPtr CopyWindow; -+ ClearToBackgroundProcPtr ClearToBackground; -+ RestoreAreasProcPtr RestoreAreas; -+ ScreenWakeupHandlerProcPtr WakeupHandler; -+ InstallColormapProcPtr InstallColormap; -+ UninstallColormapProcPtr UninstallColormap; -+ ListInstalledColormapsProcPtr ListInstalledColormaps; -+ StoreColorsProcPtr StoreColors; -+ xf86EnableDisableFBAccessProc *EnableDisableFBAccess; -+ miPointerSpriteFuncPtr spriteFuncs; -+ DisplayCursorProcPtr DisplayCursor; -+ CursorPtr pCurs; -+ Bool (*UseHWCursor)(ScreenPtr, CursorPtr); -+ Bool (*UseHWCursorARGB)(ScreenPtr, CursorPtr); -+ Bool *SWCursor; -+#ifdef CHROMIUM -+ RealizeWindowProcPtr RealizeWindow; -+ UnrealizeWindowProcPtr UnrealizeWindow; -+ DestroyWindowProcPtr DestroyWindow; -+ ResizeWindowProcPtr ResizeWindow; -+ PositionWindowProcPtr PositionWindow; -+ ClipNotifyProcPtr ClipNotify; -+#endif -+#ifdef RENDER -+ CompositeProcPtr Composite; -+#endif -+ -+} vncScreenRec, *vncScreenPtr; -+ -+extern Bool vncUseHWCursor(ScreenPtr pScreen, CursorPtr pCurs); -+extern Bool vncUseHWCursorARGB(ScreenPtr pScreen, CursorPtr pCurs); -+extern void rfbEnableDisableFBAccess (int index, Bool enable); -+ -+#endif /* _VNC_H_ */ -+ -diff --git a/hw/xfree86/vnc/zlib.c b/hw/xfree86/vnc/zlib.c -new file mode 100644 -index 0000000..edc4467 ---- /dev/null -+++ b/hw/xfree86/vnc/zlib.c -@@ -0,0 +1,306 @@ -+/* -+ * zlib.c -+ * -+ * Routines to implement zlib based encoding (deflate). -+ * -+ * Modified for XFree86 4.x by Alan Hourihane -+ */ -+ -+/* -+ * Copyright (C) 2000 Tridia Corporation. All Rights Reserved. -+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. -+ * -+ * This is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This software is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this software; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -+ * USA. -+ * -+ * For the latest source code, please check: -+ * -+ * http://www.developVNC.org/ -+ * -+ * or send email to feedback@developvnc.org. -+ */ -+ -+#include -+#include -+#include "rfb.h" -+ -+/* -+ * zlibBeforeBuf contains pixel data in the client's format. -+ * zlibAfterBuf contains the zlib (deflated) encoding version. -+ * If the zlib compressed/encoded version is -+ * larger than the raw data or if it exceeds zlibAfterBufSize then -+ * raw encoding is used instead. -+ */ -+ -+static int zlibBeforeBufSize = 0; -+static char *zlibBeforeBuf = NULL; -+ -+static int zlibAfterBufSize = 0; -+static char *zlibAfterBuf = NULL; -+static int zlibAfterBufLen; -+ -+/* -+ * rfbSendOneRectEncodingZlib - send a given rectangle using one Zlib -+ * rectangle encoding. -+ */ -+ -+static Bool -+rfbSendOneRectEncodingZlib(rfbClientPtr cl, int x, int y, int w, int h) -+{ -+ VNCSCREENPTR(cl->pScreen); -+ rfbFramebufferUpdateRectHeader rect; -+ rfbZlibHeader hdr; -+ int deflateResult; -+ int previousOut; -+ int i; -+ unsigned char *fbptr = (pVNC->pfbMemory + (pVNC->paddedWidthInBytes * y) -+ + (x * (pVNC->bitsPerPixel / 8))); -+ -+ int maxRawSize; -+ int maxCompSize; -+ -+ maxRawSize = (pVNC->width * pVNC->height -+ * (cl->format.bitsPerPixel / 8)); -+ -+ if (zlibBeforeBufSize < maxRawSize) { -+ zlibBeforeBufSize = maxRawSize; -+ if (zlibBeforeBuf == NULL) -+ zlibBeforeBuf = (char *)xalloc(zlibBeforeBufSize); -+ else -+ zlibBeforeBuf = (char *)xrealloc(zlibBeforeBuf, zlibBeforeBufSize); -+ } -+ -+ /* zlib compression is not useful for very small data sets. -+ * So, we just send these raw without any compression. -+ */ -+ if (( w * h * (pVNC->bitsPerPixel / 8)) < -+ VNC_ENCODE_ZLIB_MIN_COMP_SIZE ) { -+ -+ int result; -+ -+ /* The translation function (used also by the in raw encoding) -+ * requires 4/2/1 byte alignment in the output buffer (which is -+ * pVNC->updateBuf for the raw encoding) based on the bitsPerPixel of -+ * the viewer/client. This prevents SIGBUS errors on some -+ * architectures like SPARC, PARISC... -+ */ -+ if (( cl->format.bitsPerPixel > 8 ) && -+ ( pVNC->ublen % ( cl->format.bitsPerPixel / 8 )) != 0 ) { -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ } -+ -+ result = rfbSendRectEncodingRaw(cl, x, y, w, h); -+ -+ return result; -+ -+ } -+ -+ /* -+ * zlib requires output buffer to be slightly larger than the input -+ * buffer, in the worst case. -+ */ -+ maxCompSize = maxRawSize + (( maxRawSize + 99 ) / 100 ) + 12; -+ -+ if (zlibAfterBufSize < maxCompSize) { -+ zlibAfterBufSize = maxCompSize; -+ if (zlibAfterBuf == NULL) -+ zlibAfterBuf = (char *)xalloc(zlibAfterBufSize); -+ else -+ zlibAfterBuf = (char *)xrealloc(zlibAfterBuf, zlibAfterBufSize); -+ } -+ -+ /* -+ * Convert pixel data to client format. -+ */ -+ (*cl->translateFn)(cl->pScreen, cl->translateLookupTable, -+ &pVNC->rfbServerFormat, -+ &cl->format, fbptr, zlibBeforeBuf, -+ pVNC->paddedWidthInBytes, w, h, x, y); -+ -+ cl->compStream.next_in = ( Bytef * )zlibBeforeBuf; -+ cl->compStream.avail_in = w * h * (cl->format.bitsPerPixel / 8); -+ cl->compStream.next_out = ( Bytef * )zlibAfterBuf; -+ cl->compStream.avail_out = maxCompSize; -+ cl->compStream.data_type = Z_BINARY; -+ -+ /* Initialize the deflation state. */ -+ if ( cl->compStreamInited == FALSE ) { -+ -+ cl->compStream.total_in = 0; -+ cl->compStream.total_out = 0; -+ cl->compStream.zalloc = Z_NULL; -+ cl->compStream.zfree = Z_NULL; -+ cl->compStream.opaque = Z_NULL; -+ -+ deflateInit2( &(cl->compStream), -+ cl->zlibCompressLevel, -+ Z_DEFLATED, -+ MAX_WBITS, -+ MAX_MEM_LEVEL, -+ Z_DEFAULT_STRATEGY ); -+ /* deflateInit( &(cl->compStream), Z_BEST_COMPRESSION ); */ -+ /* deflateInit( &(cl->compStream), Z_BEST_SPEED ); */ -+ cl->compStreamInited = TRUE; -+ -+ } -+ -+ previousOut = cl->compStream.total_out; -+ -+ /* Perform the compression here. */ -+ deflateResult = deflate( &(cl->compStream), Z_SYNC_FLUSH ); -+ -+ /* Find the total size of the resulting compressed data. */ -+ zlibAfterBufLen = cl->compStream.total_out - previousOut; -+ -+ if ( deflateResult != Z_OK ) { -+ rfbLog("zlib deflation error: %s\n", cl->compStream.msg); -+ return FALSE; -+ } -+ -+ /* Note that it is not possible to switch zlib parameters based on -+ * the results of the compression pass. The reason is -+ * that we rely on the compressor and decompressor states being -+ * in sync. Compressing and then discarding the results would -+ * cause lose of synchronization. -+ */ -+ -+ /* Update statics */ -+ cl->rfbRectanglesSent[rfbEncodingZlib]++; -+ cl->rfbBytesSent[rfbEncodingZlib] += (sz_rfbFramebufferUpdateRectHeader -+ + sz_rfbZlibHeader + zlibAfterBufLen); -+ -+ if (pVNC->ublen + sz_rfbFramebufferUpdateRectHeader + sz_rfbZlibHeader -+ > UPDATE_BUF_SIZE) -+ { -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ } -+ -+ rect.r.x = Swap16IfLE(x); -+ rect.r.y = Swap16IfLE(y); -+ rect.r.w = Swap16IfLE(w); -+ rect.r.h = Swap16IfLE(h); -+ rect.encoding = Swap32IfLE(rfbEncodingZlib); -+ -+ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&rect, -+ sz_rfbFramebufferUpdateRectHeader); -+ pVNC->ublen += sz_rfbFramebufferUpdateRectHeader; -+ -+ hdr.nBytes = Swap32IfLE(zlibAfterBufLen); -+ -+ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&hdr, sz_rfbZlibHeader); -+ pVNC->ublen += sz_rfbZlibHeader; -+ -+ for (i = 0; i < zlibAfterBufLen;) { -+ -+ int bytesToCopy = UPDATE_BUF_SIZE - pVNC->ublen; -+ -+ if (i + bytesToCopy > zlibAfterBufLen) { -+ bytesToCopy = zlibAfterBufLen - i; -+ } -+ -+ memcpy(&pVNC->updateBuf[pVNC->ublen], &zlibAfterBuf[i], bytesToCopy); -+ -+ pVNC->ublen += bytesToCopy; -+ i += bytesToCopy; -+ -+ if (pVNC->ublen == UPDATE_BUF_SIZE) { -+ if (!rfbSendUpdateBuf(cl)) -+ return FALSE; -+ } -+ } -+ -+ return TRUE; -+ -+} -+ -+ -+/* -+ * rfbSendRectEncodingZlib - send a given rectangle using one or more -+ * Zlib encoding rectangles. -+ */ -+ -+Bool -+rfbSendRectEncodingZlib(rfbClientPtr cl, int x, int y, int w, int h) -+{ -+ VNCSCREENPTR(cl->pScreen); -+ int maxLines; -+ int linesRemaining; -+ rfbRectangle partialRect; -+ -+ partialRect.x = x; -+ partialRect.y = y; -+ partialRect.w = w; -+ partialRect.h = h; -+ -+ /* Determine maximum pixel/scan lines allowed per rectangle. */ -+ maxLines = ( ZLIB_MAX_SIZE(w) / w ); -+ -+ /* Initialize number of scan lines left to do. */ -+ linesRemaining = h; -+ -+ /* Loop until all work is done. */ -+ while ( linesRemaining > 0 ) { -+ -+ int linesToComp; -+ -+ if ( maxLines < linesRemaining ) -+ linesToComp = maxLines; -+ else -+ linesToComp = linesRemaining; -+ -+ partialRect.h = linesToComp; -+ -+ /* Encode (compress) and send the next rectangle. */ -+ if ( ! rfbSendOneRectEncodingZlib( cl, -+ partialRect.x, -+ partialRect.y, -+ partialRect.w, -+ partialRect.h )) { -+ -+ return FALSE; -+ } -+ -+ /* Technically, flushing the buffer here is not extrememly -+ * efficient. However, this improves the overall throughput -+ * of the system over very slow networks. By flushing -+ * the buffer with every maximum size zlib rectangle, we -+ * improve the pipelining usage of the server CPU, network, -+ * and viewer CPU components. Insuring that these components -+ * are working in parallel actually improves the performance -+ * seen by the user. -+ * Since, zlib is most useful for slow networks, this flush -+ * is appropriate for the desired behavior of the zlib encoding. -+ */ -+ if (( pVNC->ublen > 0 ) && -+ ( linesToComp == maxLines )) { -+ if (!rfbSendUpdateBuf(cl)) { -+ -+ return FALSE; -+ } -+ } -+ -+ /* Update remaining and incremental rectangle location. */ -+ linesRemaining -= linesToComp; -+ partialRect.y += linesToComp; -+ -+ } -+ -+ return TRUE; -+ -+} -+ -+ -diff --git a/mi/miinitext.c b/mi/miinitext.c -index 7939a5f..6a71a6f 100644 ---- a/mi/miinitext.c -+++ b/mi/miinitext.c -@@ -79,6 +79,18 @@ #undef XF86DRI - #undef XF86VIDMODE - #endif - -+#ifdef VNCSERVER -+#undef COMPOSITE -+#undef DAMAGE -+#undef DBE -+#undef RANDR -+#undef XF86MISC -+#undef XFreeXDGA -+#undef XF86DRI -+#undef XF86VIDMODE -+#undef XFIXES -+#endif -+ - #include "misc.h" - #include "extension.h" - #include "micmap.h" -diff --git a/xcliplist/Makefile.am b/xcliplist/Makefile.am -new file mode 100644 -index 0000000..3f13acc ---- /dev/null -+++ b/xcliplist/Makefile.am -@@ -0,0 +1,18 @@ -+#noinst_LTLIBRARIES = libxcliplist.la -+libxcliplist_la_LTLIBRARIES = libxcliplist.la -+ -+#AM_CFLAGS = $(DIX_CFLAGS) @SERVER_DEFINES@ @LOADER_DEFINES@ -+AM_CFLAGS = $(DIX_CFLAGS) -+ -+libxcliplist_la_LDFLAGS = -module -avoid-version -+libxcliplist_ladir = $(moduledir)/extensions -+ -+libxcliplist_la_SOURCES = \ -+ cliplist.c \ -+ cliplistmod.c -+ -+## cliplistmod.c -+ -+if XORG -+sdk_HEADERS = -+endif -diff --git a/xcliplist/cliplist.c b/xcliplist/cliplist.c -new file mode 100644 -index 0000000..290eb79 ---- /dev/null -+++ b/xcliplist/cliplist.c -@@ -0,0 +1,128 @@ -+/* -+ * Server-side code for the Xcliplist extension -+ */ -+ -+#if HAVE_DIX_CONFIG_H -+#include "dix-config.h" -+#endif -+ -+#include -+#include -+ -+#include "dixstruct.h" -+#include "extnsionst.h" -+#include "windowstr.h" -+ -+#define _XCLIPLIST_SERVER_ -+#include -+ -+ -+static int XClipListErrorBase; -+static unsigned char XClipListReqCode = 0; -+ -+static void -+XClipListResetProc(ExtensionEntry* extEntry) -+{ -+ (void)extEntry; -+} -+ -+static int -+ProcXClipListQueryVersion(ClientPtr client) -+{ -+ xXClipListQueryVersionReply rep; -+ -+ REQUEST_SIZE_MATCH(xXClipListQueryVersionReq); -+ rep.type = X_Reply; -+ rep.length = 0; -+ rep.sequenceNumber = client->sequence; -+ rep.majorVersion = XCLIPLIST_MAJOR_VERSION; -+ rep.minorVersion = XCLIPLIST_MINOR_VERSION; -+ rep.patchVersion = XCLIPLIST_PATCH_VERSION; -+ -+ WriteToClient(client, sizeof(xXClipListQueryVersionReply), (char *)&rep); -+ return (client->noClientException); -+} -+ -+static int -+ProcXGetClipList(ClientPtr client) -+{ -+ xXGetClipListReply rep; -+ WindowPtr pWin; -+ int i; -+ BoxPtr pClipRects = NULL; -+ short xorig, yorig; -+ REQUEST(xXGetClipListReq); -+ REQUEST_SIZE_MATCH(xXGetClipListReq); -+ -+ rep.type = X_Reply; -+ rep.length = 0; -+ rep.sequenceNumber = client->sequence; -+ -+ if(!(pWin = (WindowPtr)LOOKUP_DRAWABLE(stuff->windowid, client) )) -+ { -+ client->errorValue = stuff->windowid; -+ return (BadWindow); -+ } -+ -+ rep.num_entries = REGION_NUM_RECTS(&pWin->clipList); -+ -+ WriteToClient(client, sizeof(xXGetClipListReply), (char *)&rep); -+ -+ pClipRects = REGION_RECTS(&pWin->clipList); -+ -+ xorig = pWin->drawable.x; -+ yorig = pWin->drawable.y; -+ -+ for (i = 0; i < rep.num_entries; i++) { -+ BoxRec box; -+ /* translate clip rect from screen coords to window coords */ -+ box.x1 = pClipRects[i].x1 - xorig; -+ box.y1 = pClipRects[i].y1 - yorig; -+ box.x2 = pClipRects[i].x2 - xorig; -+ box.y2 = pClipRects[i].y2 - yorig; -+ /*memcpy(&box, &pClipRects[i], sizeof(BoxRec));*/ -+ WriteToClient(client, sizeof(BoxRec), (char *)&box); -+ } -+ -+ return (client->noClientException); -+} -+ -+static int -+ProcXClipListDispatch (ClientPtr client) -+{ -+ REQUEST(xReq); -+ -+ switch (stuff->data) { -+ case X_XClipListQueryVersion: -+ return ProcXClipListQueryVersion(client); -+ case X_XGetClipList: -+ return ProcXGetClipList(client); -+ default: -+ return BadRequest; -+ } -+} -+ -+static int -+SProcXClipListDispatch (ClientPtr client) -+{ -+ REQUEST(xReq); -+ (void)stuff; -+ return XClipListErrorBase + XClipListClientNotLocal; -+} -+ -+void -+XClipListExtensionInit(void) -+{ -+ ExtensionEntry* extEntry; -+ -+ if ((extEntry = AddExtension(XCLIPLISTNAME, -+ XClipListNumberEvents, -+ XClipListNumberErrors, -+ ProcXClipListDispatch, -+ SProcXClipListDispatch, -+ XClipListResetProc, -+ StandardMinorOpcode))) { -+ XClipListReqCode = (unsigned char)extEntry->base; -+ XClipListErrorBase = extEntry->errorBase; -+ } -+} -diff --git a/xcliplist/cliplistmod.c b/xcliplist/cliplistmod.c -new file mode 100644 -index 0000000..3dae42c ---- /dev/null -+++ b/xcliplist/cliplistmod.c -@@ -0,0 +1,46 @@ -+ -+#include "xorg/xf86Module.h" -+ -+extern Bool noTestExtensions; -+ -+static MODULESETUPPROTO(xcliplistSetup); -+ -+extern void XClipListExtensionInit(INITARGS); -+ -+ExtensionModule xcliplistExt = { -+ XClipListExtensionInit, -+ "XClipList", -+ &noTestExtensions, -+ NULL, -+ NULL -+}; -+ -+static XF86ModuleVersionInfo VersRec = { -+ "XClipList", -+ MODULEVENDORSTRING, -+ MODINFOSTRING1, -+ MODINFOSTRING2, -+ XF86_VERSION_CURRENT, /* XXX fix? */ -+ 1, 13, 0, -+ ABI_CLASS_EXTENSION, -+#if 0 -+ ABI_EXTENSION_VERSION, -+#else -+ /* Hack to allow module to work with more servers (vs. 0.3 above) */ -+ SET_ABI_VERSION(0, 2), -+#endif -+ MOD_CLASS_EXTENSION, -+ {0,0,0,0} -+}; -+ -+XF86ModuleData xcliplistModuleData = { &VersRec, xcliplistSetup, NULL }; -+ -+static pointer -+xcliplistSetup(pointer module, pointer opts, int *errmaj, int *errmin) -+{ -+ LoadExtension(&xcliplistExt, FALSE); -+ -+ /* Need a non-NULL return value to indicate success */ -+ return (pointer)1; -+} -+ --- -1.4.2 - diff --git a/0018-vnc-support.txt.diff b/0018-vnc-support.txt.diff deleted file mode 100644 index 34fe940..0000000 --- a/0018-vnc-support.txt.diff +++ /dev/null @@ -1,40 +0,0 @@ -diff -x .deps -u -r xcliplist.orig/cliplistmod.c xcliplist/cliplistmod.c ---- xcliplist.orig/cliplistmod.c 2007-01-14 13:45:20.000000000 +0000 -+++ xcliplist/cliplistmod.c 2007-01-14 13:46:44.000000000 +0000 -@@ -1,5 +1,5 @@ - --#include "xorg/xf86Module.h" -+#include "../hw/xfree86/common/xf86Module.h" - - extern Bool noTestExtensions; - ---- hw/vnc/loginauth.c.orig 2007-01-13 18:00:45.106884000 +0100 -+++ hw/vnc/loginauth.c 2007-01-13 18:08:04.104447000 +0100 -@@ -37,6 +37,8 @@ - #include - #include "rfb.h" - -+char *crypt(const char *key, const char *salt); -+ - void rfbLoginAuthProcessClientMessage(rfbClientPtr cl) - { - int n1 = 0, n2 = 0; ---- ../xorg-server-1.1.99.903.old/hw/xfree86/vnc/Makefile.am 2007-01-16 20:52:51.000000000 +0000 -+++ hw/xfree86/vnc/Makefile.am 2007-01-16 21:35:00.000000000 +0000 -@@ -5,6 +5,7 @@ - -I$(top_srcdir)/hw/xfree86/ramdac \ - -I$(top_srcdir)/GL/glx \ - -I$(top_srcdir)/GL/include \ -+ -I$(top_srcdir)/hw/dmx/vnc \ - -I$(top_builddir)/GL/include \ - -I@MESA_SOURCE@/include \ - -DHAVE_XORG_CONFIG_H \ -@@ -20,6 +21,8 @@ - libvnc_la_LDFLAGS = -module -avoid-version - libvnc_ladir = $(moduledir)/extensions - libvnc_la_SOURCES = \ -+ $(top_srcdir)/hw/dmx/vnc/vncauth.c \ -+ $(top_srcdir)/hw/vnc/d3des.c \ - auth.c \ - cmap.c \ - corre.c \ diff --git a/0018-vnc-support.txt.mbox b/0018-vnc-support.txt.mbox deleted file mode 100644 index b7db9eb..0000000 --- a/0018-vnc-support.txt.mbox +++ /dev/null @@ -1,187 +0,0 @@ -From xorg-bounces@lists.freedesktop.org Thu Jan 11 18:09:18 2007 -Return-Path: -X-Original-To: sndirsch@wotan.suse.de -Received: from Relay2.suse.de (relay2.suse.de [149.44.160.89]) - by wotan.suse.de (Postfix) with ESMTP id 8F76413E45 - for ; Thu, 11 Jan 2007 18:09:18 +0100 (CET) -Received: by Relay2.suse.de (Postfix) - id 8B0DAC03BF; Thu, 11 Jan 2007 18:09:18 +0100 (CET) -Received: from Relay2.suse.de (localhost [127.0.0.1]) - by Relay2.suse.de (Postfix) with ESMTP id 6B1D2AE3B2; - Thu, 11 Jan 2007 18:09:18 +0100 (CET) -Received: from Relay2.suse.de ([127.0.0.1]) - by Relay2.suse.de (Relay2 [127.0.0.1]) (amavisd-new, port 10026) with ESMTP - id 32754-05; Thu, 11 Jan 2007 18:09:12 +0100 (CET) -Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) - (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) - (No client certificate requested) - by Relay2.suse.de (Postfix) with ESMTP id 03A1CC03AF; - Thu, 11 Jan 2007 18:09:12 +0100 (CET) -Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.208.82]) - by mx2.suse.de (Postfix) with ESMTP id BED2E215E1; - Thu, 11 Jan 2007 18:09:11 +0100 (CET) -Received: from gabe.freedesktop.org (localhost [127.0.0.1]) - by gabe.freedesktop.org (Postfix) with ESMTP id 5525D9EB5A; - Thu, 11 Jan 2007 09:09:07 -0800 (PST) -X-Original-To: xorg@freedesktop.org -Delivered-To: xorg@freedesktop.org -Received: from ciao.gmane.org (main.gmane.org [80.91.229.2]) - by gabe.freedesktop.org (Postfix) with ESMTP id 6CC819EAF1 - for ; Thu, 11 Jan 2007 09:09:03 -0800 (PST) -Received: from list by ciao.gmane.org with local (Exim 4.43) - id 1H53Q4-0002Z1-Np - for xorg@freedesktop.org; Thu, 11 Jan 2007 18:08:52 +0100 -Received: from host-84-9-255-116.bulldogdsl.com ([84.9.255.116]) - by main.gmane.org with esmtp (Gmexim 0.1 (Debian)) - id 1AlnuQ-0007hv-00 - for ; Thu, 11 Jan 2007 18:08:52 +0100 -Received: from gmane by host-84-9-255-116.bulldogdsl.com with local (Gmexim - 0.1 (Debian)) id 1AlnuQ-0007hv-00 - for ; Thu, 11 Jan 2007 18:08:52 +0100 -X-Injected-Via-Gmane: http://gmane.org/ -To: xorg@freedesktop.org -From: Colin Guthrie -Date: Thu, 11 Jan 2007 17:08:41 +0000 -Message-ID: -References: <45A66ACD.2060605@Sun.COM> -Mime-Version: 1.0 -Content-Type: text/plain; charset=ISO-8859-1 -Content-Transfer-Encoding: 7bit -X-Complaints-To: usenet@sea.gmane.org -X-Gmane-NNTP-Posting-Host: host-84-9-255-116.bulldogdsl.com -User-Agent: Thunderbird 1.5.0.9 (X11/20070105) -In-Reply-To: <45A66ACD.2060605@Sun.COM> -Subject: Re: VNC on Xorg? -X-BeenThere: xorg@lists.freedesktop.org -X-Mailman-Version: 2.1.5 -Precedence: list -List-Id: Discuss issues related to the xorg tree -List-Unsubscribe: , - -List-Archive: -List-Post: -List-Help: -List-Subscribe: , - -Sender: xorg-bounces@lists.freedesktop.org -Errors-To: xorg-bounces@lists.freedesktop.org -X-Virus-Scanned: by amavisd-new at Relay2.suse.de -X-Spam-Status: No, hits=-1.7 tagged_above=-20.0 required=5.0 tests=BAYES_20, - IS_MAILMAN_LIST -X-Spam-Level: -Status: RO -Content-Length: 561 -Lines: 12 - -Deron Johnson wrote: -> Does anybody know of a version of VNC which is based on Xorg 6.9 or -> greater? For example, Tight VNC is based on an ancient version (XFree86). - -I recently updated the Mandriva VNC patch for Xorg 1.1.99.903, but I've -not tested it at all. It compiles up fine tho'. - -http://svn.mandriva.com/cgi-bin/viewvc.cgi/packages/cooker/x11-server/current/SOURCES/0018-vnc-support.txt?view=log - -HTH - -Col. - -_______________________________________________ -xorg mailing list -xorg@lists.freedesktop.org -http://lists.freedesktop.org/mailman/listinfo/xorg - -From xorg-bounces@lists.freedesktop.org Thu Jan 11 18:15:18 2007 -Return-Path: -X-Original-To: sndirsch@wotan.suse.de -Received: from Relay1.suse.de (relay1.suse.de [149.44.160.87]) - by wotan.suse.de (Postfix) with ESMTP id 08DF413E45 - for ; Thu, 11 Jan 2007 18:15:18 +0100 (CET) -Received: by Relay1.suse.de (Postfix) - id 054EBB189D; Thu, 11 Jan 2007 18:15:18 +0100 (CET) -Received: from Relay1.suse.de (localhost [127.0.0.1]) - by Relay1.suse.de (Postfix) with ESMTP id E8AF9BCC22; - Thu, 11 Jan 2007 18:15:17 +0100 (CET) -Received: from Relay1.suse.de ([127.0.0.1]) - by Relay1.suse.de (Relay1 [127.0.0.1]) (amavisd-new, port 10026) with ESMTP - id 22518-16; Thu, 11 Jan 2007 18:15:12 +0100 (CET) -Received: from mx1.suse.de (ns1.suse.de [195.135.220.2]) - (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) - (No client certificate requested) - by Relay1.suse.de (Postfix) with ESMTP id AACF2BA55A; - Thu, 11 Jan 2007 18:15:12 +0100 (CET) -Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.208.82]) - by mx1.suse.de (Postfix) with ESMTP id 6D30F12208; - Thu, 11 Jan 2007 18:15:12 +0100 (CET) -Received: from gabe.freedesktop.org (localhost [127.0.0.1]) - by gabe.freedesktop.org (Postfix) with ESMTP id E3A279EB68; - Thu, 11 Jan 2007 09:15:08 -0800 (PST) -X-Original-To: xorg@freedesktop.org -Delivered-To: xorg@freedesktop.org -Received: from ciao.gmane.org (main.gmane.org [80.91.229.2]) - by gabe.freedesktop.org (Postfix) with ESMTP id 29AC49EB59 - for ; Thu, 11 Jan 2007 09:15:03 -0800 (PST) -Received: from root by ciao.gmane.org with local (Exim 4.43) - id 1H53W2-0003Hz-6X - for xorg@freedesktop.org; Thu, 11 Jan 2007 18:15:02 +0100 -Received: from host-84-9-255-116.bulldogdsl.com ([84.9.255.116]) - by main.gmane.org with esmtp (Gmexim 0.1 (Debian)) - id 1AlnuQ-0007hv-00 - for ; Thu, 11 Jan 2007 18:15:02 +0100 -Received: from gmane by host-84-9-255-116.bulldogdsl.com with local (Gmexim - 0.1 (Debian)) id 1AlnuQ-0007hv-00 - for ; Thu, 11 Jan 2007 18:15:02 +0100 -X-Injected-Via-Gmane: http://gmane.org/ -To: xorg@freedesktop.org -From: Colin Guthrie -Date: Thu, 11 Jan 2007 17:12:37 +0000 -Message-ID: -References: <45A66ACD.2060605@Sun.COM> -Mime-Version: 1.0 -Content-Type: text/plain; charset=ISO-8859-1 -Content-Transfer-Encoding: 7bit -X-Complaints-To: usenet@sea.gmane.org -X-Gmane-NNTP-Posting-Host: host-84-9-255-116.bulldogdsl.com -User-Agent: Thunderbird 1.5.0.9 (X11/20070105) -In-Reply-To: -Subject: Re: VNC on Xorg? -X-BeenThere: xorg@lists.freedesktop.org -X-Mailman-Version: 2.1.5 -Precedence: list -List-Id: Discuss issues related to the xorg tree -List-Unsubscribe: , - -List-Archive: -List-Post: -List-Help: -List-Subscribe: , - -Sender: xorg-bounces@lists.freedesktop.org -Errors-To: xorg-bounces@lists.freedesktop.org -X-Virus-Scanned: by amavisd-new at Relay1.suse.de -X-Spam-Status: No, hits=-1.7 tagged_above=-20.0 required=5.0 tests=BAYES_20, - IS_MAILMAN_LIST -X-Spam-Level: -Status: RO -Content-Length: 657 -Lines: 13 - -Colin Guthrie wrote: -> Deron Johnson wrote: ->> Does anybody know of a version of VNC which is based on Xorg 6.9 or ->> greater? For example, Tight VNC is based on an ancient version (XFree86). -> -> I recently updated the Mandriva VNC patch for Xorg 1.1.99.903, but I've -> not tested it at all. It compiles up fine tho'. -> -> http://svn.mandriva.com/cgi-bin/viewvc.cgi/packages/cooker/x11-server/current/SOURCES/0018-vnc-support.txt?view=log - -I should also state that the previous revision is for Xorg 1.1.1 - -Col. - -_______________________________________________ -xorg mailing list -xorg@lists.freedesktop.org -http://lists.freedesktop.org/mailman/listinfo/xorg - diff --git a/xorg-server-1.4-vnc-fix.patch b/xorg-server-1.4-vnc-fix.patch new file mode 100644 index 0000000..b5932ee --- /dev/null +++ b/xorg-server-1.4-vnc-fix.patch @@ -0,0 +1,22 @@ +diff -u -r -x .deps xorg-server-1.4.old/hw/xfree86/vnc/vncint.h xorg-server-1.4/hw/xfree86/vnc/vncint.h +--- xorg-server-1.4.old/hw/xfree86/vnc/vncint.h 2007-10-19 01:11:08.000000000 +0000 ++++ xorg-server-1.4/hw/xfree86/vnc/vncint.h 2007-10-19 01:22:20.000000000 +0000 +@@ -22,7 +22,7 @@ + #ifndef _VNC_H_ + #define _VNC_H_ + +-#include ++#include <../ramdac/xf86Cursor.h> + /*#include */ + + extern int vncScreenPrivateIndex; +diff -u -r -x .deps xorg-server-1.4.old/xcliplist/cliplistmod.c xorg-server-1.4/xcliplist/cliplistmod.c +--- xorg-server-1.4.old/xcliplist/cliplistmod.c 2007-10-19 01:11:10.000000000 +0000 ++++ xorg-server-1.4/xcliplist/cliplistmod.c 2007-10-19 01:13:04.000000000 +0000 +@@ -1,5 +1,5 @@ + +-#include "xorg/xf86Module.h" ++#include "../hw/xfree86/common/xf86Module.h" + + extern Bool noTestExtensions; + diff --git a/xorg-server-1.4-vnc.patch b/xorg-server-1.4-vnc.patch new file mode 100644 index 0000000..4fef32b --- /dev/null +++ b/xorg-server-1.4-vnc.patch @@ -0,0 +1,24047 @@ +Diff from xf4vnc 2007-09-06 - xserver 265a633cf1fcbf497d6916d9e22403dffdde2e07 +plus a couple missing commits to clean up the diff. Provides Xvnc and vnc.so +extension. Requires vncproto, xcliplistproto and libXcliplist also from +xf4vnc. Requires autotools rebuild. + +diff -pNur xorg-server-1.4.orig/configure.ac xorg-server-1.4/configure.ac +--- xorg-server-1.4.orig/configure.ac 2007-09-05 22:59:00.000000000 -0700 ++++ xorg-server-1.4/configure.ac 2007-09-06 16:09:51.000000000 -0700 +@@ -518,6 +518,10 @@ AC_ARG_ENABLE(xfree86-utils, AS_HELP + dnl DDXes. + AC_ARG_ENABLE(xorg, AS_HELP_STRING([--enable-xorg], [Build Xorg server (default: auto)]), [XORG=$enableval], [XORG=auto]) + AC_ARG_ENABLE(dmx, AS_HELP_STRING([--enable-dmx], [Build DMX server (default: no)]), [DMX=$enableval], [DMX=no]) ++ ++AC_ARG_ENABLE(xcliplist, AS_HELP_STRING([--enable-xcliplist], [Build XClipList extension (default: auto)]), [XCLIPLIST=$enableval], [XCLIPLIST=auto]) ++AC_ARG_ENABLE(vnc, AS_HELP_STRING([--enable-vnc], [Build Xvnc server (default: yes)]), [VNC=$enableval], [VNC=auto]) ++ + AC_ARG_ENABLE(xvfb, AS_HELP_STRING([--enable-xvfb], [Build Xvfb server (default: yes)]), [XVFB=$enableval], [XVFB=yes]) + AC_ARG_ENABLE(xnest, AS_HELP_STRING([--enable-xnest], [Build Xnest server (default: auto)]), [XNEST=$enableval], [XNEST=auto]) + AC_ARG_ENABLE(xwin, AS_HELP_STRING([--enable-xwin], [Build XWin server (default: auto)]), [XWIN=$enableval], [XWIN=auto]) +@@ -887,6 +891,20 @@ XI_INC='-I$(top_srcdir)/Xi' + + AM_CONDITIONAL(XF86UTILS, test "x$XF86UTILS" = xyes) + ++if test "x$XCLIPLIST" = xauto; then ++ if test "x$XORG" = xno; then ++ XCLIPLIST=no ++ else ++ PKG_CHECK_MODULES([XCLIPLIST], [xcliplistproto xcliplist], [XCLIPLIST=yes], [XCLIPLIST=no]) ++ fi ++fi ++AM_CONDITIONAL(XCLIPLIST, [test "x$XCLIPLIST" = xyes]) ++if test "x$XCLIPLIST" = xyes; then ++ AC_DEFINE(XCLIPLIST, 1, [Support XClipList extension]) ++ REQUIRED_MODULES="$REQUIRED_MODULES xcliplistproto" ++ XCLIPLIST_LIB='$(top_builddir)/xcliplist/libxcliplist.la' ++fi ++ + AC_DEFINE(SHAPE, 1, [Support SHAPE extension]) + + AC_DEFINE(XKB, 1, [Build XKB]) +@@ -1000,6 +1018,8 @@ MI_EXT_LIB='$(top_builddir)/mi/libmiext. + MI_INC='-I$(top_srcdir)/mi' + FB_LIB='$(top_builddir)/fb/libfb.la' + FB_INC='-I$(top_srcdir)/fb' ++MFB_LIB='$(top_builddir)/mfb/libmfb.la' ++MFB_INC='-I$(top_srcdir)/mfb' + MIEXT_SHADOW_INC='-I$(top_srcdir)/miext/shadow' + MIEXT_SHADOW_LIB='$(top_builddir)/miext/shadow/libshadow.la' + XPSTUBS_LIB='$(top_builddir)/dix/libxpstubs.la' +@@ -1162,6 +1182,40 @@ AM_CONDITIONAL([DMX_BUILD_LNX], [test "x + AM_CONDITIONAL([DMX_BUILD_USB], [test "x$DMX_BUILD_USB" = xyes]) + + ++ ++dnl VNC DDX ++ ++AC_MSG_CHECKING([whether to build Xvnc DDX]) ++PKG_CHECK_MODULES([VNCMODULES], [xmuu xext x11 xrender xfont xi vncproto xau $XDMCP_MODULES $PIXMAN], [have_vnc=yes], [have_vnc=no]) ++if test "x$VNC" = xauto; then ++ VNC="$have_vnc" ++fi ++AC_MSG_RESULT([$VNC]) ++AM_CONDITIONAL(VNC, [test "x$VNC" = xyes]) ++ ++if test "x$VNC" = xyes; then ++ if test "x$have_vnc" = xno; then ++ AC_MSG_ERROR([Xvnc build explicitly requested, but required ++ modules not found.]) ++ fi ++ XVNC_CFLAGS="-DVNCSERVER -DHAVE_XVNC_CONFIG_H $PIXMAN_CFLAGS" ++ AC_SUBST([XVNC_CFLAGS]) ++ VNC_INCLUDES="$XEXT_INC $RENDER_INC $XTRAP_INC $RECORD_INC" ++ XVNC_LIBS="$GLX_LIBS $MFB_LIB $FB_LIB $MI_LIB $XEXT_LIB $RENDER_LIB $XTRAP_LIB $RECORD_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $OS_LIB $CWRAP_LIB" ++ AC_SUBST([XVNC_LIBS]) ++ ++ if test "x$GLX" = xyes; then ++ PKG_CHECK_MODULES([GL], [glproto]) ++ fi ++ PKG_CHECK_MODULES([XVNCCONFIG_DEP], [xaw7 xmu xt xpm x11]) ++ AC_SUBST(XVNCCONFIG_DEP_CFLAGS) ++ AC_SUBST(XVNCCONFIG_DEP_LIBS) ++ $srcdir/hw/vnc/symlink-vnc.sh $srcdir/hw/vnc $srcdir/hw/xfree86/vnc ++ $srcdir/hw/vnc/symlink-vnc.sh $srcdir/hw/vnc $srcdir/hw/dmx/vnc ++fi ++ ++ ++ + dnl Xvfb DDX + + AC_MSG_CHECKING([whether to build Xvfb DDX]) +@@ -2011,6 +2065,7 @@ Xext/Makefile + Xi/Makefile + xfixes/Makefile + exa/Makefile ++xcliplist/Makefile + hw/Makefile + hw/xfree86/Makefile + hw/xfree86/common/Makefile +@@ -2048,6 +2103,7 @@ hw/xfree86/scanpci/Makefile + hw/xfree86/shadowfb/Makefile + hw/xfree86/vbe/Makefile + hw/xfree86/vgahw/Makefile ++hw/xfree86/vnc/Makefile + hw/xfree86/x86emu/Makefile + hw/xfree86/xaa/Makefile + hw/xfree86/xf1bpp/Makefile +@@ -2068,8 +2124,10 @@ hw/dmx/doc/Makefile + hw/dmx/examples/Makefile + hw/dmx/input/Makefile + hw/dmx/glxProxy/Makefile ++hw/dmx/vnc/Makefile + hw/dmx/Makefile + hw/vfb/Makefile ++hw/vnc/Makefile + hw/xgl/Makefile + hw/xgl/egl/Makefile + hw/xgl/egl/module/Makefile +diff -pNur xorg-server-1.4.orig/hw/dmx/dmx-config.h xorg-server-1.4/hw/dmx/dmx-config.h +--- xorg-server-1.4.orig/hw/dmx/dmx-config.h 2007-08-23 12:04:52.000000000 -0700 ++++ xorg-server-1.4/hw/dmx/dmx-config.h 2007-09-06 16:09:45.000000000 -0700 +@@ -72,6 +72,9 @@ + /* Enable the DMX extension */ + #define DMXEXT + ++/* Enable VNC ability */ ++#define DMXVNC 1 ++ + /* Disable the extensions that are not currently supported */ + #undef BEZIER + #undef PEXEXT +diff -pNur xorg-server-1.4.orig/hw/dmx/dmxinit.c xorg-server-1.4/hw/dmx/dmxinit.c +--- xorg-server-1.4.orig/hw/dmx/dmxinit.c 2007-08-23 12:04:52.000000000 -0700 ++++ xorg-server-1.4/hw/dmx/dmxinit.c 2007-09-06 16:09:45.000000000 -0700 +@@ -77,6 +77,10 @@ extern void GlxSetVisualConfigs( + ); + #endif /* GLXEXT */ + ++#ifdef DMXVNC ++extern void VNCInitForDMX(void); ++#endif ++ + /* Global variables available to all Xserver/hw/dmx routines. */ + int dmxNumScreens; + DMXScreenInfo *dmxScreens; +@@ -812,6 +816,9 @@ void InitOutput(ScreenInfo *pScreenInfo, + + dmxLog(dmxInfo, "Shadow framebuffer support %s\n", + dmxShadowFB ? "enabled" : "disabled"); ++#ifdef DMXVNC ++ VNCInitForDMX(); ++#endif + } + + /* RATS: Assuming the fp string (which comes from the command-line argv +@@ -1045,3 +1052,14 @@ void ddxUseMsg(void) + ErrorF(" Ctrl-Alt-q Quit (core devices only)\n"); + ErrorF(" Ctrl-Alt-F* Switch to VC (local only)\n"); + } ++ ++#ifdef DDXTIME ++/** Return wall-clock time in milliseconds. */ ++CARD32 GetTimeInMillis(void) ++{ ++ struct timeval tp; ++ ++ gettimeofday(&tp, 0); ++ return tp.tv_sec * 1000 + tp.tv_usec / 1000; ++} ++#endif +diff -pNur xorg-server-1.4.orig/hw/dmx/dmxsync.c xorg-server-1.4/hw/dmx/dmxsync.c +--- xorg-server-1.4.orig/hw/dmx/dmxsync.c 2007-08-23 12:04:52.000000000 -0700 ++++ xorg-server-1.4/hw/dmx/dmxsync.c 2007-09-06 16:09:45.000000000 -0700 +@@ -99,9 +99,16 @@ static void dmxSyncBlockHandler(pointer + TimerForce(dmxSyncTimer); + } + ++#ifdef DMXVNC ++extern void rfbWakeupHandlerDMX(void); ++#endif ++ + static void dmxSyncWakeupHandler(pointer blockData, int result, + pointer pReadMask) + { ++#ifdef DMXVNC ++ rfbWakeupHandlerDMX(); ++#endif + } + + /** Request the XSync() batching optimization with the specified \a +diff -pNur xorg-server-1.4.orig/hw/dmx/input/dmxcommon.c xorg-server-1.4/hw/dmx/input/dmxcommon.c +--- xorg-server-1.4.orig/hw/dmx/input/dmxcommon.c 2007-08-23 12:04:52.000000000 -0700 ++++ xorg-server-1.4/hw/dmx/input/dmxcommon.c 2007-09-06 16:09:45.000000000 -0700 +@@ -655,7 +655,6 @@ void dmxCommonRestoreState(pointer priva + dmxLogInput(dmxInput, "Keyboard busy, waiting\n"); + else + dmxLogInput(dmxInput, "Keyboard error, waiting\n"); +- + /* Don't generate X11 protocol for a bit */ + for (tmp = GetTimeInMillis(); GetTimeInMillis() - tmp < 250;) { + usleep(250); /* This ends up sleeping only until +diff -pNur xorg-server-1.4.orig/hw/dmx/input/dmxinputinit.c xorg-server-1.4/hw/dmx/input/dmxinputinit.c +--- xorg-server-1.4.orig/hw/dmx/input/dmxinputinit.c 2007-08-23 12:04:52.000000000 -0700 ++++ xorg-server-1.4/hw/dmx/input/dmxinputinit.c 2007-09-06 16:09:45.000000000 -0700 +@@ -393,6 +393,10 @@ static int dmxKeyboardOn(DeviceIntPtr pD + DevicePtr pDev = &pDevice->public; + #endif + ++#ifdef DMXVNC ++ vncSetKeyboardDevice(pDevice); ++#endif ++ + #ifdef XKB + if (noXkbExtension) { + #endif +@@ -480,6 +484,10 @@ static int dmxDeviceOnOff(DeviceIntPtr p + break; + } + if (info.keyClass) { ++#ifdef DMXVNC ++ vncSetKeyboardDevice(pDevice); ++#endif ++ + #if 00 /*BP*/ + InitKeyClassDeviceStruct(pDevice, &info.keySyms, info.modMap); + #else +@@ -534,6 +542,9 @@ static int dmxDeviceOnOff(DeviceIntPtr p + info.maxres[i+1]); + #endif + } ++#ifdef DMXVNC ++ vncSetPointerDevice(pDevice); ++#endif + } + if (info.focusClass) InitFocusClassDeviceStruct(pDevice); + #ifdef XINPUT +diff -pNur xorg-server-1.4.orig/hw/dmx/input/dmxinputinit.h xorg-server-1.4/hw/dmx/input/dmxinputinit.h +--- xorg-server-1.4.orig/hw/dmx/input/dmxinputinit.h 2007-08-23 12:04:52.000000000 -0700 ++++ xorg-server-1.4/hw/dmx/input/dmxinputinit.h 2007-09-06 16:09:45.000000000 -0700 +@@ -290,4 +290,9 @@ extern int dmxInputAttachConsol + extern int dmxInputAttachBackend(int physicalScreen, int isCore, + int *id); + ++#ifdef DMXVNC ++extern void vncSetKeyboardDevice(DeviceIntPtr kbd); ++extern void vncSetPointerDevice(DeviceIntPtr ptr); ++#endif ++ + #endif +diff -pNur xorg-server-1.4.orig/hw/dmx/input/Makefile.am xorg-server-1.4/hw/dmx/input/Makefile.am +--- xorg-server-1.4.orig/hw/dmx/input/Makefile.am 2007-08-23 12:04:52.000000000 -0700 ++++ xorg-server-1.4/hw/dmx/input/Makefile.am 2007-09-06 16:09:45.000000000 -0700 +@@ -65,6 +65,7 @@ AM_CFLAGS = $(DIX_CFLAGS) \ + -I$(top_srcdir)/hw/xfree86/common \ + $(GLX_INCS) \ + -DHAVE_DMX_CONFIG_H \ ++ -DDMXVNC=1 \ + $(GLX_DEFS) \ + @DMXMODULES_CFLAGS@ + +diff -pNur xorg-server-1.4.orig/hw/dmx/Makefile.am xorg-server-1.4/hw/dmx/Makefile.am +--- xorg-server-1.4.orig/hw/dmx/Makefile.am 2007-08-31 18:28:27.000000000 -0700 ++++ xorg-server-1.4/hw/dmx/Makefile.am 2007-09-06 16:09:45.000000000 -0700 +@@ -1,6 +1,6 @@ +-DIST_SUBDIRS = input config glxProxy examples doc ++DIST_SUBDIRS = input vnc config glxProxy examples doc + +-SUBDIRS = input config examples ++SUBDIRS = input vnc config examples + bin_PROGRAMS = Xdmx + + if XINERAMA +@@ -86,7 +86,9 @@ Xdmx_LDADD = $(XORG_CORE_LIBS) \ + $(XDMX_LIBS) \ + $(GLX_LIBS) \ + input/libdmxinput.a \ ++ vnc/libdmxvnc.a \ + config/libdmxconfig.a \ ++ -ljpeg -lcrypt \ + @DMXMODULES_LIBS@ + + # Man page +diff -pNur xorg-server-1.4.orig/hw/dmx/vnc/Makefile.am xorg-server-1.4/hw/dmx/vnc/Makefile.am +--- xorg-server-1.4.orig/hw/dmx/vnc/Makefile.am 1969-12-31 16:00:00.000000000 -0800 ++++ xorg-server-1.4/hw/dmx/vnc/Makefile.am 2007-09-06 16:09:45.000000000 -0700 +@@ -0,0 +1,43 @@ ++noinst_LIBRARIES = libdmxvnc.a ++ ++SRCS = \ ++ auth.c \ ++ cmap.c \ ++ corre.c \ ++ cursor.c \ ++ cutpaste.c \ ++ d3des.c \ ++ dispcur.c \ ++ draw.c \ ++ hextile.c \ ++ httpd.c \ ++ kbdptr.c \ ++ loginauth.c \ ++ rdp.c \ ++ rfbkeyb.c \ ++ rfbmouse.c \ ++ rfbserver.c \ ++ rre.c \ ++ sockets.c \ ++ sprite.c \ ++ stats.c \ ++ tight.c \ ++ translate.c \ ++ vncauth.c \ ++ vncext.c \ ++ vncInit.c \ ++ xistubs.c \ ++ zlib.c ++ ++ ++libdmxvnc_a_SOURCES = $(SRCS) ++ ++AM_CFLAGS = \ ++ -I$(top_srcdir)/hw/dmx \ ++ -I$(top_srcdir)/hw/xfree86/common \ ++ -DHAVE_DMX_CONFIG_H \ ++ $(DIX_CFLAGS) \ ++ -DDMXVNC=1 \ ++ @DMXMODULES_CFLAGS@ ++ ++###EXTRA_DIST = dmxdetach.c +diff -pNur xorg-server-1.4.orig/hw/dmx/vnc/vncInit.c xorg-server-1.4/hw/dmx/vnc/vncInit.c +--- xorg-server-1.4.orig/hw/dmx/vnc/vncInit.c 1969-12-31 16:00:00.000000000 -0800 ++++ xorg-server-1.4/hw/dmx/vnc/vncInit.c 2007-09-06 16:09:45.000000000 -0700 +@@ -0,0 +1,453 @@ ++/* ++ * Copyright (C) 2002 Alan Hourihane. 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. ++ * ++ * Author: Alan Hourihane ++ */ ++ ++#include "rfb.h" ++ ++#ifdef HAVE_DMX_CONFIG_H ++#include "dmx-config.h" ++#endif ++ ++#ifdef DMXVNC ++#include "../dmx.h" ++#include "../dmxcb.h" ++#endif ++ ++#include ++#include "fb.h" ++ ++#include "dixstruct.h" ++#include "compiler.h" ++ ++#include "mipointer.h" ++#include "mibstore.h" ++ ++#include "globals.h" ++#define DPMS_SERVER ++#include ++ ++#include ++ ++int vncScreenPrivateIndex = -1; ++int rfbGCIndex = -1; ++int inetdSock = -1; ++Atom VNC_LAST_CLIENT_ID = 0; ++Atom VNC_CONNECT = 0; ++char *desktopName = "x11"; ++char rfbThisHost[256]; ++ ++extern void VncExtensionInit(void); ++ ++extern void vncInitMouse(void); ++extern void vncInitKeyb(void); ++Bool VNCInit(ScreenPtr pScreen, DMXScreenInfo *dmxScreen); ++ ++#ifndef XFree86LOADER ++static unsigned long VNCGeneration = 0; ++#endif ++static void rfbWakeupHandler (int i, pointer blockData, unsigned long err, pointer pReadmask); ++ ++/* ++ * 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 %H:%M:%S ", localtime(&clock)); ++ fprintf(stderr, buf); ++ ++ vfprintf(stderr, format, args); ++ fflush(stderr); ++ ++ va_end(args); ++} ++ ++void rfbLogPerror(char *str) ++{ ++ rfbLog(""); ++ perror(str); ++} ++ ++ ++static ScreenPtr TheVNCScreen = NULL; ++ ++ ++static void ++nopGetImage(DrawablePtr pDrawable, int sx, int sy, ++ int w, int h, unsigned int format, ++ unsigned long planemask, char *pdstLine) ++{ ++ ScreenPtr pScreen = pDrawable->pScreen; ++ ++ (*pScreen->GetImage)(pDrawable,sx,sy,w,h,format,planemask,pdstLine); ++} ++ ++ ++static void ++SetupVNCScreen(void) ++{ ++ vncScreenPtr pScreenPriv; ++ VisualPtr v = NULL; ++ int i; ++ ++ pScreenPriv = xalloc(sizeof(vncScreenRec)); ++ pScreenPriv->width = dmxGlobalWidth; ++ pScreenPriv->height = dmxGlobalHeight; ++ pScreenPriv->rfbAuthTries = 0; ++ pScreenPriv->rfbAuthTooManyTries = FALSE; ++ pScreenPriv->timer = NULL; ++ pScreenPriv->udpPort = 0; ++ pScreenPriv->rfbListenSock = -1; ++ pScreenPriv->udpSock = -1; ++ pScreenPriv->udpSockConnected = FALSE; ++ pScreenPriv->httpListenSock = -1; ++ pScreenPriv->httpSock = -1; ++ pScreenPriv->maxFd = 0; ++ pScreenPriv->rfbAuthPasswdFile = NULL; ++ pScreenPriv->httpDir = NULL; ++ pScreenPriv->rfbInstalledColormap = NULL; ++ pScreenPriv->interface.s_addr = htonl (INADDR_ANY); ++ ++ pScreenPriv->rfbPort = 0; ++ pScreenPriv->httpPort = 0; ++ pScreenPriv->rfbAuthPasswdFile = NULL; ++ pScreenPriv->httpDir = NULL; ++ pScreenPriv->rfbAlwaysShared = FALSE; ++ pScreenPriv->rfbNeverShared = FALSE; ++ pScreenPriv->rfbUserAccept = FALSE; ++ pScreenPriv->rfbViewOnly = FALSE; ++ pScreenPriv->rfbDontDisconnect = FALSE; ++ pScreenPriv->loginAuthEnabled = FALSE; ++ ++ /* Find the root window's visual. ++ * XXX this might be the wrong info to use below. ++ */ ++ for (i = 0; i < screenInfo.screens[0]->numVisuals; i++) { ++ v = screenInfo.screens[0]->visuals + i; ++ if (v->vid == screenInfo.screens[0]->rootVisual) { ++ break; ++ } ++ } ++ ++ /* XXX is this the right depth and bpp? */ ++ /* With DMX, screenInfo.screens[0]->rootDepth is 24 and that doesn't ++ * work in translate.c! We're just using 32. ++ */ ++ pScreenPriv->rfbServerFormat.bitsPerPixel = 32; ++ pScreenPriv->rfbServerFormat.depth = 32; ++ pScreenPriv->rfbServerFormat.bigEndian = 0; ++ pScreenPriv->rfbServerFormat.trueColour = (v->class == TrueColor); ++ if (pScreenPriv->rfbServerFormat.trueColour) { ++ pScreenPriv->rfbServerFormat.redMax = v->redMask >> v->offsetRed; ++ pScreenPriv->rfbServerFormat.greenMax = v->greenMask >> v->offsetGreen; ++ pScreenPriv->rfbServerFormat.blueMax = v->blueMask >> v->offsetBlue; ++ pScreenPriv->rfbServerFormat.redShift = v->offsetRed; ++ pScreenPriv->rfbServerFormat.greenShift = v->offsetGreen; ++ pScreenPriv->rfbServerFormat.blueShift = v->offsetBlue; ++ } else { ++ pScreenPriv->rfbServerFormat.redMax ++ = pScreenPriv->rfbServerFormat.greenMax ++ = pScreenPriv->rfbServerFormat.blueMax = 0; ++ pScreenPriv->rfbServerFormat.redShift ++ = pScreenPriv->rfbServerFormat.greenShift ++ = pScreenPriv->rfbServerFormat.blueShift = 0; ++ } ++ ++ /* Allocate/init TheVNCScreen object */ ++ vncScreenPrivateIndex = 0; ++ ++ TheVNCScreen = (ScreenPtr) Xcalloc(1, sizeof(struct _Screen)); ++ TheVNCScreen->devPrivates = (DevUnion *) Xcalloc(1, sizeof(DevUnion)); ++ TheVNCScreen->devPrivates[vncScreenPrivateIndex].ptr = pScreenPriv; ++ TheVNCScreen->GetImage = nopGetImage; ++ ++ rfbInitSockets(TheVNCScreen); ++ if (inetdSock == -1) ++ httpInitSockets(TheVNCScreen); ++} ++ ++ ++/* ++ * Called by DMX's InitOutput() ++ * Will be called for each X server generation. ++ */ ++void ++VNCInitForDMX(void) ++{ ++ rfbLog("DMXVNC: Initializing VNC for DMX\n"); ++ ErrorF("DMXVNC: Initializing VNC for DMX\n"); ++ ++ if (TheVNCScreen) { ++ rfbLog("DMXVNC: New server generation\n"); ++ } ++ else { ++ rfbLog("DMXVNC: Set up VNC screen\n"); ++ SetupVNCScreen(); ++ } ++ ++ /* Reset the input device pointers. They'll get set later. ++ * This allows successful server regeneration. ++ */ ++ vncSetKeyboardDevice(NULL); ++ vncSetPointerDevice(NULL); ++} ++ ++ ++Bool ++VNCInit(ScreenPtr pScreen, DMXScreenInfo *pScrn) ++{ ++ VisualPtr visual; ++ vncScreenPtr pScreenPriv; ++#if 0 ++ char *interface_str = NULL; ++#endif ++#ifdef RENDER ++ PictureScreenPtr ps; ++#endif ++ ++#ifndef XFree86LOADER ++ if (VNCGeneration != serverGeneration) { ++ VNCGeneration = serverGeneration; ++ if ( ((vncScreenPrivateIndex = AllocateScreenPrivateIndex()) < 0) || ++ ((rfbGCIndex = AllocateGCPrivateIndex()) < 0) ) ++ return FALSE; ++ } ++#endif ++ ++ if (!AllocateGCPrivate(pScreen, rfbGCIndex, sizeof(rfbGCRec))) { ++ ErrorF("VNCInit(): failed to allocate GCIndex\n"); ++ return FALSE; ++ } ++ ++ if (!(pScreenPriv = xalloc(sizeof(vncScreenRec)))) ++ return FALSE; ++ ++ pScreen->devPrivates[vncScreenPrivateIndex].ptr = (pointer)pScreenPriv; ++ ++ pScreenPriv->rfbAuthTries = 0; ++ pScreenPriv->rfbAuthTooManyTries = FALSE; ++ pScreenPriv->timer = NULL; ++ pScreenPriv->udpPort = 0; ++ pScreenPriv->rfbListenSock = -1; ++ pScreenPriv->udpSock = -1; ++ pScreenPriv->udpSockConnected = FALSE; ++ pScreenPriv->httpListenSock = -1; ++ pScreenPriv->httpSock = -1; ++ pScreenPriv->maxFd = 0; ++ pScreenPriv->rfbAuthPasswdFile = NULL; ++ pScreenPriv->httpDir = NULL; ++ pScreenPriv->rfbInstalledColormap = NULL; ++ pScreenPriv->interface.s_addr = htonl (INADDR_ANY); ++ ++ pScreenPriv->rfbPort = 0; ++ pScreenPriv->httpPort = 0; ++ pScreenPriv->rfbAuthPasswdFile = NULL; ++ pScreenPriv->httpDir = NULL; ++ pScreenPriv->rfbAlwaysShared = FALSE; ++ pScreenPriv->rfbNeverShared = FALSE; ++ pScreenPriv->rfbUserAccept = FALSE; ++ pScreenPriv->rfbViewOnly = FALSE; ++ pScreenPriv->rfbDontDisconnect = FALSE; ++ pScreenPriv->loginAuthEnabled = FALSE; ++ ++#if 0 ++ if (xf86ReturnOptValBool(options, OPTION_LOCALHOST, FALSE)) ++ pScreenPriv->interface.s_addr = htonl (INADDR_LOOPBACK); ++ ++ interface_str = xf86GetOptValString(options, OPTION_INTERFACE); ++ ++ if (interface_str && pScreenPriv->interface.s_addr == htonl(INADDR_ANY)) { ++ Bool failed = FALSE; ++ struct in_addr got; ++ unsigned long octet; ++ char *p = interface_str, *end; ++ int q; ++ ++ for (q = 0; q < 4; q++) { ++ octet = strtoul (p, &end, 10); ++ ++ if (p == end || octet > 255) ++ failed = TRUE; ++ ++ if ((q < 3 && *end != '.') || ++ (q == 3 && *end != '\0')) ++ failed = TRUE; ++ ++ got.s_addr = (got.s_addr << 8) | octet; ++ p = end + 1; ++ } ++ ++ if (!failed) ++ pScreenPriv->interface.s_addr = htonl (got.s_addr); ++ else ++ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VNC interface option malformed, not using.\n"); ++ } ++#endif ++ ++ if (!VNC_LAST_CLIENT_ID) ++ VNC_LAST_CLIENT_ID = MakeAtom("VNC_LAST_CLIENT_ID", ++ strlen("VNC_LAST_CLIENT_ID"), TRUE); ++ if (!VNC_CONNECT) ++ VNC_CONNECT = MakeAtom("VNC_CONNECT", strlen("VNC_CONNECT"), TRUE); ++ ++ rfbInitSockets(pScreen); ++ if (inetdSock == -1) ++ httpInitSockets(pScreen); ++ ++#ifdef CORBA ++ initialiseCORBA(argc, argv, desktopName); ++#endif ++ ++ pScreenPriv->width = pScrn->scrnWidth; ++ pScreenPriv->height = pScrn->scrnHeight; ++ pScreenPriv->depth = pScrn->beDepth; ++ pScreenPriv->paddedWidthInBytes = PixmapBytePad(pScrn->scrnWidth, pScrn->beDepth); ++ pScreenPriv->bitsPerPixel = rfbBitsPerPixel(pScrn->beDepth); ++ pScreenPriv->pfbMemory = NULL; ++ pScreenPriv->oldpfbMemory = NULL; ++ ++ pScreenPriv->cursorIsDrawn = TRUE; ++ pScreenPriv->dontSendFramebufferUpdate = FALSE; ++ ++ pScreenPriv->CloseScreen = pScreen->CloseScreen; ++ pScreenPriv->CreateGC = pScreen->CreateGC; ++ pScreenPriv->PaintWindowBackground = pScreen->PaintWindowBackground; ++ pScreenPriv->PaintWindowBorder = pScreen->PaintWindowBorder; ++ pScreenPriv->CopyWindow = pScreen->CopyWindow; ++ pScreenPriv->ClearToBackground = pScreen->ClearToBackground; ++ pScreenPriv->RestoreAreas = pScreen->RestoreAreas; ++ pScreenPriv->WakeupHandler = pScreen->WakeupHandler; ++ pScreenPriv->InstallColormap = pScreen->InstallColormap; ++ pScreenPriv->UninstallColormap = pScreen->UninstallColormap; ++ pScreenPriv->ListInstalledColormaps = pScreen->ListInstalledColormaps; ++ pScreenPriv->StoreColors = pScreen->StoreColors; ++#ifdef CHROMIUM ++ pScreenPriv->RealizeWindow = pScreen->RealizeWindow; ++ pScreenPriv->UnrealizeWindow = pScreen->UnrealizeWindow; ++ pScreenPriv->DestroyWindow = pScreen->DestroyWindow; ++ pScreenPriv->PositionWindow = pScreen->PositionWindow; ++ pScreenPriv->ResizeWindow = pScreen->ResizeWindow; ++ pScreenPriv->ClipNotify = pScreen->ClipNotify; ++#endif ++#ifdef RENDER ++ ps = GetPictureScreenIfSet(pScreen); ++ if (ps) ++ pScreenPriv->Composite = ps->Composite; ++#endif ++ pScreen->CloseScreen = rfbCloseScreen; ++ pScreen->CreateGC = rfbCreateGC; ++ pScreen->PaintWindowBackground = rfbPaintWindowBackground; ++ pScreen->PaintWindowBorder = rfbPaintWindowBorder; ++ pScreen->CopyWindow = rfbCopyWindow; ++ pScreen->ClearToBackground = rfbClearToBackground; ++ pScreen->RestoreAreas = rfbRestoreAreas; ++ pScreen->WakeupHandler = rfbWakeupHandler; ++ pScreen->InstallColormap = rfbInstallColormap; ++ pScreen->UninstallColormap = rfbUninstallColormap; ++ pScreen->ListInstalledColormaps = rfbListInstalledColormaps; ++ pScreen->StoreColors = rfbStoreColors; ++ ++#ifdef CHROMIUM ++ pScreen->RealizeWindow = rfbRealizeWindow; ++ pScreen->UnrealizeWindow = rfbUnrealizeWindow; ++ pScreen->DestroyWindow = rfbDestroyWindow; ++ pScreen->PositionWindow = rfbPositionWindow; ++ pScreen->ResizeWindow = rfbResizeWindow; ++ pScreen->ClipNotify = rfbClipNotify; ++#endif ++#ifdef RENDER ++ if (ps) ++ ps->Composite = rfbComposite; ++#endif ++ ++ for (visual = pScreen->visuals; visual->vid != pScreen->rootVisual; visual++) ++ ; ++ ++ if (!visual) { ++ ErrorF("rfbScreenInit: couldn't find root visual\n"); ++ return FALSE; ++ } ++ ++ pScreenPriv->rfbServerFormat.bitsPerPixel = pScrn->beBPP; ++ pScreenPriv->rfbServerFormat.depth = pScrn->beDepth; ++ pScreenPriv->rfbServerFormat.bigEndian = !(*(char *)&rfbEndianTest); ++ pScreenPriv->rfbServerFormat.trueColour = (visual->class == TrueColor); ++ if (pScreenPriv->rfbServerFormat.trueColour) { ++ pScreenPriv->rfbServerFormat.redMax = visual->redMask >> visual->offsetRed; ++ pScreenPriv->rfbServerFormat.greenMax = visual->greenMask >> visual->offsetGreen; ++ pScreenPriv->rfbServerFormat.blueMax = visual->blueMask >> visual->offsetBlue; ++ pScreenPriv->rfbServerFormat.redShift = visual->offsetRed; ++ pScreenPriv->rfbServerFormat.greenShift = visual->offsetGreen; ++ pScreenPriv->rfbServerFormat.blueShift = visual->offsetBlue; ++ } else { ++ pScreenPriv->rfbServerFormat.redMax ++ = pScreenPriv->rfbServerFormat.greenMax ++ = pScreenPriv->rfbServerFormat.blueMax = 0; ++ pScreenPriv->rfbServerFormat.redShift ++ = pScreenPriv->rfbServerFormat.greenShift ++ = pScreenPriv->rfbServerFormat.blueShift = 0; ++ } ++ ++ return TRUE; ++} ++ ++static void ++rfbWakeupHandler ( ++ int i, ++ pointer blockData, ++ unsigned long err, ++ pointer pReadmask ++){ ++ ScreenPtr pScreen = screenInfo.screens[i]; ++ vncScreenPtr pScreenPriv = VNCPTR(pScreen); ++ /*DMXScreenInfo *pScrn = &dmxScreens[pScreen->myNum];*/ ++ ++ rfbRootPropertyChange(pScreen); /* Check clipboard */ ++ ++ rfbCheckFds(pScreen); ++ httpCheckFds(pScreen); ++#ifdef CORBA ++ corbaCheckFds(); ++#endif ++ ++ pScreen->WakeupHandler = pScreenPriv->WakeupHandler; ++ (*pScreen->WakeupHandler) (i, blockData, err, pReadmask); ++ pScreen->WakeupHandler = rfbWakeupHandler; ++} ++ ++ ++/** ++ * The rfb wake-up handler used when we're compiled into the DMX server. ++ */ ++void ++rfbWakeupHandlerDMX(void) ++{ ++ ScreenPtr pScreen = TheVNCScreen; ++ rfbRootPropertyChange(pScreen); /* Check clipboard */ ++ rfbCheckFds(pScreen); ++ httpCheckFds(pScreen); ++} +diff -pNur xorg-server-1.4.orig/hw/dmx/vnc/vncint.h xorg-server-1.4/hw/dmx/vnc/vncint.h +--- xorg-server-1.4.orig/hw/dmx/vnc/vncint.h 1969-12-31 16:00:00.000000000 -0800 ++++ xorg-server-1.4/hw/dmx/vnc/vncint.h 2007-09-06 16:09:45.000000000 -0700 +@@ -0,0 +1,153 @@ ++/* ++ * Copyright (C) 2002 Alan Hourihane. 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. ++ * ++ * Author: Alan Hourihane ++ */ ++ ++#ifndef _VNCINT_H_ ++#define _VNCINT_H_ ++ ++#include ++ ++extern int vncScreenPrivateIndex; ++ ++#define VNCPTR(pScreen)\ ++ (vncScreenPtr)((pScreen)->devPrivates[vncScreenPrivateIndex].ptr) ++ ++typedef struct { ++ int rfbPort; ++ int rdpPort; ++ int udpPort; ++ int rfbListenSock; ++ int rdpListenSock; ++ int udpSock; ++ int httpPort; ++ int httpListenSock; ++ int httpSock; ++ char * httpDir; ++ char buf[HTTP_BUF_SIZE]; ++ Bool udpSockConnected; ++ char * rfbAuthPasswdFile; ++ size_t buf_filled; ++ int maxFd; ++ fd_set allFds; ++ unsigned char * oldpfbMemory; ++ Bool rfbAlwaysShared; ++ Bool rfbNeverShared; ++ Bool rfbDontDisconnect; ++ Bool rfbUserAccept; ++ Bool rfbViewOnly; ++ unsigned char * pfbMemory; ++ int paddedWidthInBytes; ++ ColormapPtr rfbInstalledColormap; ++ ColormapPtr savedColormap; ++ rfbPixelFormat rfbServerFormat; ++ Bool rfbAuthTooManyTries; ++ int rfbAuthTries; ++ Bool loginAuthEnabled; ++ struct in_addr interface; ++ OsTimerPtr timer; ++ unsigned char updateBuf[UPDATE_BUF_SIZE]; ++ int ublen; ++ int width; ++ int height; ++ int depth; ++ int bitsPerPixel; ++ ++ /* The following two members are used to minimise the amount of unnecessary ++ drawing caused by cursor movement. Whenever any drawing affects the ++ part of the screen where the cursor is, the cursor is removed first and ++ then the drawing is done (this is what the sprite routines test for). ++ Afterwards, however, we do not replace the cursor, even when the cursor ++ is logically being moved across the screen. We only draw the cursor ++ again just as we are about to send the client a framebuffer update. ++ ++ We need to be careful when removing and drawing the cursor because of ++ their relationship with the normal drawing routines. The drawing ++ routines can invoke the cursor routines, but also the cursor routines ++ themselves end up invoking drawing routines. ++ ++ Removing the cursor (rfbSpriteRemoveCursor) is eventually achieved by ++ doing a CopyArea from a pixmap to the screen, where the pixmap contains ++ the saved contents of the screen under the cursor. Before doing this, ++ however, we set cursorIsDrawn to FALSE. Then, when CopyArea is called, ++ it sees that cursorIsDrawn is FALSE and so doesn't feel the need to ++ (recursively!) remove the cursor before doing it. ++ ++ Putting up the cursor (rfbSpriteRestoreCursor) involves a call to ++ PushPixels. While this is happening, cursorIsDrawn must be FALSE so ++ that PushPixels doesn't think it has to remove the cursor first. ++ Obviously cursorIsDrawn is set to TRUE afterwards. ++ ++ Another problem we face is that drawing routines sometimes cause a ++ framebuffer update to be sent to the RFB client. When the RFB client is ++ already waiting for a framebuffer update and some drawing to the ++ framebuffer then happens, the drawing routine sees that the client is ++ ready, so it calls rfbSendFramebufferUpdate. If the cursor is not drawn ++ at this stage, it must be put up, and so rfbSpriteRestoreCursor is ++ called. However, if the original drawing routine was actually called ++ from within rfbSpriteRestoreCursor or rfbSpriteRemoveCursor we don't ++ want this to happen. So both the cursor routines set ++ dontSendFramebufferUpdate to TRUE, and all the drawing routines check ++ this before calling rfbSendFramebufferUpdate. */ ++ ++ Bool cursorIsDrawn; /* TRUE if the cursor is currently drawn */ ++ Bool dontSendFramebufferUpdate; /* TRUE while removing or drawing the ++ cursor */ ++ ++ /* wrapped screen functions */ ++ ++ CloseScreenProcPtr CloseScreen; ++ CreateGCProcPtr CreateGC; ++ PaintWindowBackgroundProcPtr PaintWindowBackground; ++ PaintWindowBorderProcPtr PaintWindowBorder; ++ CopyWindowProcPtr CopyWindow; ++ ClearToBackgroundProcPtr ClearToBackground; ++ RestoreAreasProcPtr RestoreAreas; ++ ScreenWakeupHandlerProcPtr WakeupHandler; ++ InstallColormapProcPtr InstallColormap; ++ UninstallColormapProcPtr UninstallColormap; ++ ListInstalledColormapsProcPtr ListInstalledColormaps; ++ StoreColorsProcPtr StoreColors; ++ DisplayCursorProcPtr DisplayCursor; ++ CursorPtr pCurs; ++ Bool (*UseHWCursor)(ScreenPtr, CursorPtr); ++ Bool (*UseHWCursorARGB)(ScreenPtr, CursorPtr); ++ Bool *SWCursor; ++#ifdef CHROMIUM ++ RealizeWindowProcPtr RealizeWindow; ++ UnrealizeWindowProcPtr UnrealizeWindow; ++ DestroyWindowProcPtr DestroyWindow; ++ ResizeWindowProcPtr ResizeWindow; ++ PositionWindowProcPtr PositionWindow; ++ ClipNotifyProcPtr ClipNotify; ++#endif ++#ifdef RENDER ++ CompositeProcPtr Composite; ++#endif ++ ++} vncScreenRec, *vncScreenPtr; ++ ++extern Bool vncUseHWCursor(ScreenPtr pScreen, CursorPtr pCurs); ++extern Bool vncUseHWCursorARGB(ScreenPtr pScreen, CursorPtr pCurs); ++ ++extern void ++rfbSendChromiumStart(unsigned int ipaddress, unsigned int port); ++ ++#endif /* _VNCINT_H_ */ ++ +diff -pNur xorg-server-1.4.orig/hw/Makefile.am xorg-server-1.4/hw/Makefile.am +--- xorg-server-1.4.orig/hw/Makefile.am 2007-08-23 12:04:52.000000000 -0700 ++++ xorg-server-1.4/hw/Makefile.am 2007-09-06 16:09:45.000000000 -0700 +@@ -38,6 +38,11 @@ if XPRINT + XPRINT_SUBDIRS = xprint + endif + ++if VNC ++VNC_SUBDIRS = vnc ++endif ++ ++# need to add darwin support here + if BUILD_DARWIN + DARWIN_SUBDIRS = darwin + endif +@@ -50,10 +55,11 @@ SUBDIRS = \ + $(XVFB_SUBDIRS) \ + $(XNEST_SUBDIRS) \ + $(DMX_SUBDIRS) \ ++ $(VNC_SUBDIRS) \ + $(KDRIVE_SUBDIRS) \ + $(XPRINT_SUBDIRS) + +-DIST_SUBDIRS = dmx xfree86 vfb xnest xwin darwin kdrive xgl xprint ++DIST_SUBDIRS = dmx xfree86 vfb xnest xwin darwin kdrive xgl xprint vnc + + relink: + for i in $(SUBDIRS) ; do $(MAKE) -C $$i relink ; done +diff -pNur xorg-server-1.4.orig/hw/vnc/auth.c xorg-server-1.4/hw/vnc/auth.c +--- xorg-server-1.4.orig/hw/vnc/auth.c 1969-12-31 16:00:00.000000000 -0800 ++++ xorg-server-1.4/hw/vnc/auth.c 2007-09-06 16:09:45.000000000 -0700 +@@ -0,0 +1,566 @@ ++/* ++ * auth.c - deal with authentication. ++ * ++ * This file implements authentication when setting up an RFB connection. ++ * ++ * Modified for XFree86 4.x by Alan Hourihane ++ */ ++ ++/* ++ * Copyright (C) 2003-2004 Constantin Kaplinsky. All Rights Reserved. ++ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. ++ * ++ * This is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This software is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this software; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, ++ * USA. ++ */ ++#ifdef HAVE_DIX_CONFIG_H ++#include ++#endif ++ ++#include "rfb.h" ++#include "windowstr.h" ++ ++static void rfbSendSecurityType(rfbClientPtr cl, int securityType); ++static void rfbSendSecurityTypeList(rfbClientPtr cl, int primaryType); ++static void rfbSendTunnelingCaps(rfbClientPtr cl); ++static void rfbSendAuthCaps(rfbClientPtr cl); ++static void rfbVncAuthSendChallenge(rfbClientPtr cl); ++ ++/* ++ * rfbAuthNewClient is called right after negotiating the protocol ++ * version. Depending on the protocol version, we send either a code ++ * for authentication scheme to be used (protocol 3.3), or a list of ++ * possible "security types" (protocol 3.7). ++ */ ++ ++void ++rfbAuthNewClient(cl) ++ rfbClientPtr cl; ++{ ++ VNCSCREENPTR(cl->pScreen); ++ int securityType = rfbSecTypeInvalid; ++ ++ if ((!pVNC->rfbAuthPasswdFile && !pVNC->loginAuthEnabled) || cl->reverseConnection) { ++ securityType = rfbSecTypeNone; ++ } else { ++ if (rfbAuthIsBlocked(cl)) { ++ rfbLog("Too many authentication failures - client rejected\n"); ++ rfbClientConnFailed(cl, "Too many authentication failures"); ++ return; ++ } ++ if (pVNC->rfbAuthPasswdFile) ++ securityType = rfbSecTypeVncAuth; ++ } ++ ++ if (cl->protocol_minor_ver < 7) { ++ /* Make sure we use only RFB 3.3 compatible security types. */ ++ if (securityType == rfbSecTypeInvalid) { ++ rfbLog("VNC authentication disabled - RFB 3.3 client rejected\n"); ++ rfbClientConnFailed(cl, "Your viewer cannot handle required " ++ "authentication methods"); ++ return; ++ } ++ rfbSendSecurityType(cl, securityType); ++ } else { ++ /* Here it's ok when securityType is set to rfbSecTypeInvalid. */ ++ rfbSendSecurityTypeList(cl, securityType); ++ } ++} ++ ++ ++/* ++ * Tell the client what security type will be used (protocol 3.3). ++ */ ++ ++static void ++rfbSendSecurityType(cl, securityType) ++ rfbClientPtr cl; ++ int securityType; ++{ ++ CARD32 value32; ++ ++ /* Send the value. */ ++ value32 = Swap32IfLE(securityType); ++ if (WriteExact(cl->sock, (char *)&value32, 4) < 0) { ++ rfbLogPerror("rfbSendSecurityType: write"); ++ rfbCloseSock(cl->pScreen, cl->sock); ++ return; ++ } ++ ++ /* Decide what to do next. */ ++ switch (securityType) { ++ case rfbSecTypeNone: ++ /* Dispatch client input to rfbProcessClientInitMessage. */ ++ cl->state = RFB_INITIALISATION; ++ break; ++ case rfbSecTypeVncAuth: ++ /* Begin the standard VNC authentication procedure. */ ++ rfbVncAuthSendChallenge(cl); ++ break; ++ default: ++ /* Impossible case (hopefully). */ ++ rfbLogPerror("rfbSendSecurityType: assertion failed"); ++ rfbCloseSock(cl->pScreen, cl->sock); ++ } ++} ++ ++ ++/* ++ * Advertise our supported security types (protocol 3.7). The list ++ * will include one standard security type (if primaryType is not set ++ * to rfbSecTypeInvalid), and then one more value telling the client ++ * that we support TightVNC protocol extensions. Thus, currently, ++ * there will be either 1 or 2 items in the list. ++ */ ++ ++static void ++rfbSendSecurityTypeList(cl, primaryType) ++ rfbClientPtr cl; ++ int primaryType; ++{ ++ int count = 1; ++ ++ /* Fill in the list of security types in the client structure. */ ++ if (primaryType != rfbSecTypeInvalid) { ++ cl->securityTypes[count++] = (CARD8)primaryType; ++ } ++ cl->securityTypes[count] = (CARD8)rfbSecTypeTight; ++ cl->securityTypes[0] = (CARD8)count++; ++ ++ /* Send the list. */ ++ if (WriteExact(cl->sock, (char *)cl->securityTypes, count) < 0) { ++ rfbLogPerror("rfbSendSecurityTypeList: write"); ++ rfbCloseSock(cl->pScreen, cl->sock); ++ return; ++ } ++ ++ /* Dispatch client input to rfbProcessClientSecurityType. */ ++ cl->state = RFB_SECURITY_TYPE; ++} ++ ++ ++/* ++ * Read the security type chosen by the client (protocol 3.7). ++ */ ++ ++void ++rfbProcessClientSecurityType(cl) ++ rfbClientPtr cl; ++{ ++ int n, count, i; ++ CARD8 chosenType; ++ ++ /* Read the security type. */ ++ n = ReadExact(cl->sock, (char *)&chosenType, 1); ++ if (n <= 0) { ++ if (n == 0) ++ rfbLog("rfbProcessClientSecurityType: client gone\n"); ++ else ++ rfbLogPerror("rfbProcessClientSecurityType: read"); ++ rfbCloseSock(cl->pScreen, cl->sock); ++ return; ++ } ++ ++ /* Make sure it was present in the list sent by the server. */ ++ count = (int)cl->securityTypes[0]; ++ for (i = 1; i <= count; i++) { ++ if (chosenType == cl->securityTypes[i]) ++ break; ++ } ++ if (i > count) { ++ rfbLog("rfbProcessClientSecurityType: " ++ "wrong security type requested\n"); ++ rfbCloseSock(cl->pScreen, cl->sock); ++ return; ++ } ++ ++ /* Now go to the proper authentication procedure. */ ++ switch (chosenType) { ++ case rfbSecTypeNone: ++ /* Dispatch client input to rfbProcessClientInitMessage. */ ++ cl->state = RFB_INITIALISATION; ++ break; ++ case rfbSecTypeVncAuth: ++ /* Begin the standard VNC authentication procedure. */ ++ rfbVncAuthSendChallenge(cl); ++ break; ++ case rfbSecTypeTight: ++ /* We are lucky: the viewer supports TightVNC extensions. */ ++ rfbLog("Enabling TightVNC protocol extensions\n"); ++ /* Switch to the protocol 3.7t. */ ++ cl->protocol_tightvnc = TRUE; ++ /* Advertise our tunneling capabilities. */ ++ rfbSendTunnelingCaps(cl); ++ break; ++ default: ++ /* Impossible case (hopefully). */ ++ rfbLog("rfbProcessClientSecurityType: " ++ "unknown authentication scheme\n"); ++ rfbCloseSock(cl->pScreen, cl->sock); ++ } ++} ++ ++ ++/* ++ * Send the list of our tunneling capabilities (protocol 3.7t). ++ */ ++ ++static void ++rfbSendTunnelingCaps(cl) ++ rfbClientPtr cl; ++{ ++ rfbTunnelingCapsMsg caps; ++ CARD32 nTypes = 0; /* we don't support tunneling yet */ ++ ++ caps.nTunnelTypes = Swap32IfLE(nTypes); ++ if (WriteExact(cl->sock, (char *)&caps, sz_rfbTunnelingCapsMsg) < 0) { ++ rfbLogPerror("rfbSendTunnelingCaps: write"); ++ rfbCloseSock(cl->pScreen, cl->sock); ++ return; ++ } ++ ++ if (nTypes) { ++ /* Dispatch client input to rfbProcessClientTunnelingType(). */ ++ cl->state = RFB_TUNNELING_TYPE; ++ } else { ++ rfbSendAuthCaps(cl); ++ } ++} ++ ++ ++/* ++ * Read tunneling type requested by the client (protocol 3.7t). ++ * NOTE: Currently, we don't support tunneling, and this function ++ * can never be called. ++ */ ++ ++void ++rfbProcessClientTunnelingType(cl) ++ rfbClientPtr cl; ++{ ++ /* If we were called, then something's really wrong. */ ++ rfbLog("rfbProcessClientTunnelingType: not implemented\n"); ++ rfbCloseSock(cl->pScreen, cl->sock); ++ return; ++} ++ ++ ++/* ++ * Send the list of our authentication capabilities to the client ++ * (protocol 3.7t). ++ */ ++ ++static void ++rfbSendAuthCaps(cl) ++ rfbClientPtr cl; ++{ ++ VNCSCREENPTR(cl->pScreen); ++ Bool authRequired; ++ rfbAuthenticationCapsMsg caps; ++ rfbCapabilityInfo caplist[MAX_AUTH_CAPS]; ++ int count = 0; ++ ++ authRequired = ((pVNC->rfbAuthPasswdFile != NULL || pVNC->loginAuthEnabled) && ++ !cl->reverseConnection); ++ ++ if (authRequired) { ++ if (pVNC->loginAuthEnabled) { ++ SetCapInfo(&caplist[count], rfbAuthUnixLogin, rfbTightVncVendor); ++ cl->authCaps[count++] = rfbAuthUnixLogin; ++ } ++ if (pVNC->rfbAuthPasswdFile != NULL) { ++ SetCapInfo(&caplist[count], rfbAuthVNC, rfbStandardVendor); ++ cl->authCaps[count++] = rfbAuthVNC; ++ } ++ if (count == 0) { ++ /* Should never happen. */ ++ rfbLog("rfbSendAuthCaps: assertion failed\n"); ++ rfbCloseSock(cl->pScreen, cl->sock); ++ return; ++ } ++ } ++ ++ cl->nAuthCaps = count; ++ caps.nAuthTypes = Swap32IfLE((CARD32)count); ++ if (WriteExact(cl->sock, (char *)&caps, sz_rfbAuthenticationCapsMsg) < 0) { ++ rfbLogPerror("rfbSendAuthCaps: write"); ++ rfbCloseSock(cl->pScreen, cl->sock); ++ return; ++ } ++ ++ if (count) { ++ if (WriteExact(cl->sock, (char *)&caplist[0], ++ count * sz_rfbCapabilityInfo) < 0) { ++ rfbLogPerror("rfbSendAuthCaps: write"); ++ rfbCloseSock(cl->pScreen, cl->sock); ++ return; ++ } ++ /* Dispatch client input to rfbProcessClientAuthType. */ ++ cl->state = RFB_AUTH_TYPE; ++ } else { ++ /* Dispatch client input to rfbProcessClientInitMessage. */ ++ cl->state = RFB_INITIALISATION; ++ } ++} ++ ++ ++/* ++ * Read client's preferred authentication type (protocol 3.7t). ++ */ ++ ++void ++rfbProcessClientAuthType(cl) ++ rfbClientPtr cl; ++{ ++ CARD32 auth_type; ++ int n, i; ++ ++ /* Read authentication type selected by the client. */ ++ n = ReadExact(cl->sock, (char *)&auth_type, sizeof(auth_type)); ++ if (n <= 0) { ++ if (n == 0) ++ rfbLog("rfbProcessClientAuthType: client gone\n"); ++ else ++ rfbLogPerror("rfbProcessClientAuthType: read"); ++ rfbCloseSock(cl->pScreen, cl->sock); ++ return; ++ } ++ auth_type = Swap32IfLE(auth_type); ++ ++ /* Make sure it was present in the list sent by the server. */ ++ for (i = 0; i < cl->nAuthCaps; i++) { ++ if (auth_type == cl->authCaps[i]) ++ break; ++ } ++ if (i >= cl->nAuthCaps) { ++ rfbLog("rfbProcessClientAuthType: " ++ "wrong authentication type requested\n"); ++ rfbCloseSock(cl->pScreen, cl->sock); ++ return; ++ } ++ ++ switch (auth_type) { ++ case rfbAuthNone: ++ /* Dispatch client input to rfbProcessClientInitMessage. */ ++ cl->state = RFB_INITIALISATION; ++ break; ++ case rfbAuthVNC: ++ rfbVncAuthSendChallenge(cl); ++ break; ++ case rfbAuthUnixLogin: ++ /* FIXME: Do (cl->state = RFB_LOGIN_AUTH) instead? */ ++ rfbLoginAuthProcessClientMessage(cl); ++ break; ++ default: ++ rfbLog("rfbProcessClientAuthType: unknown authentication scheme\n"); ++ rfbCloseSock(cl->pScreen, cl->sock); ++ } ++} ++ ++ ++/* ++ * Send the authentication challenge. ++ */ ++ ++static void ++rfbVncAuthSendChallenge(cl) ++ rfbClientPtr cl; ++{ ++ vncRandomBytes(cl->authChallenge); ++ if (WriteExact(cl->sock, (char *)cl->authChallenge, CHALLENGESIZE) < 0) { ++ rfbLogPerror("rfbVncAuthSendChallenge: write"); ++ rfbCloseSock(cl->pScreen, cl->sock); ++ return; ++ } ++ ++ /* Dispatch client input to rfbVncAuthProcessResponse. */ ++ cl->state = RFB_AUTHENTICATION; ++} ++ ++/* ++ * rfbVncAuthProcessResponse is called when the client sends its ++ * authentication response. ++ */ ++ ++void ++rfbVncAuthProcessResponse(cl) ++ rfbClientPtr cl; ++{ ++ VNCSCREENPTR(cl->pScreen); ++ char passwdFullControl[9]; ++ char passwdViewOnly[9]; ++ int numPasswords; ++ Bool ok; ++ int n; ++ CARD8 encryptedChallenge1[CHALLENGESIZE]; ++ CARD8 encryptedChallenge2[CHALLENGESIZE]; ++ CARD8 response[CHALLENGESIZE]; ++ CARD32 authResult; ++ ++ n = ReadExact(cl->sock, (char *)response, CHALLENGESIZE); ++ if (n <= 0) { ++ if (n != 0) ++ rfbLogPerror("rfbVncAuthProcessResponse: read"); ++ rfbCloseSock(cl->pScreen, cl->sock); ++ return; ++ } ++ ++ numPasswords = vncDecryptPasswdFromFile2(pVNC->rfbAuthPasswdFile, ++ passwdFullControl, ++ passwdViewOnly); ++ if (numPasswords == 0) { ++ rfbLog("rfbVncAuthProcessResponse: could not get password from %s\n", ++ pVNC->rfbAuthPasswdFile); ++ ++ authResult = Swap32IfLE(rfbVncAuthFailed); ++ ++ if (WriteExact(cl->sock, (char *)&authResult, 4) < 0) { ++ rfbLogPerror("rfbVncAuthProcessResponse: write"); ++ } ++ rfbCloseSock(cl->pScreen, cl->sock); ++ return; ++ } ++ ++ memcpy(encryptedChallenge1, cl->authChallenge, CHALLENGESIZE); ++ vncEncryptBytes(encryptedChallenge1, passwdFullControl); ++ memcpy(encryptedChallenge2, cl->authChallenge, CHALLENGESIZE); ++ vncEncryptBytes(encryptedChallenge2, ++ (numPasswords == 2) ? passwdViewOnly : passwdFullControl); ++ ++ /* Lose the passwords from memory */ ++ memset(passwdFullControl, 0, 9); ++ memset(passwdViewOnly, 0, 9); ++ ++ ok = FALSE; ++ if (memcmp(encryptedChallenge1, response, CHALLENGESIZE) == 0) { ++ rfbLog("Full-control authentication passed by %s\n", cl->host); ++ ok = TRUE; ++ cl->viewOnly = FALSE; ++ } else if (memcmp(encryptedChallenge2, response, CHALLENGESIZE) == 0) { ++ rfbLog("View-only authentication passed by %s\n", cl->host); ++ ok = TRUE; ++ cl->viewOnly = TRUE; ++ } ++ ++ if (!ok) { ++ rfbLog("rfbVncAuthProcessResponse: authentication failed from %s\n", ++ cl->host); ++ ++ if (rfbAuthConsiderBlocking(cl)) { ++ authResult = Swap32IfLE(rfbVncAuthTooMany); ++ } else { ++ authResult = Swap32IfLE(rfbVncAuthFailed); ++ } ++ ++ if (WriteExact(cl->sock, (char *)&authResult, 4) < 0) { ++ rfbLogPerror("rfbVncAuthProcessResponse: write"); ++ } ++ rfbCloseSock(cl->pScreen, cl->sock); ++ return; ++ } ++ ++ rfbAuthUnblock(cl); ++ ++ authResult = Swap32IfLE(rfbVncAuthOK); ++ ++ if (WriteExact(cl->sock, (char *)&authResult, 4) < 0) { ++ rfbLogPerror("rfbVncAuthProcessResponse: write"); ++ rfbCloseSock(cl->pScreen, cl->sock); ++ return; ++ } ++ ++ /* Dispatch client input to rfbProcessClientInitMessage(). */ ++ cl->state = RFB_INITIALISATION; ++} ++ ++ ++/* ++ * Functions to prevent too many successive authentication failures. ++ * FIXME: This should be performed separately per each client IP. ++ */ ++ ++/* Maximum authentication failures before blocking connections */ ++#define MAX_AUTH_TRIES 5 ++ ++/* Delay in ms, doubles for each failure over MAX_AUTH_TRIES */ ++#define AUTH_TOO_MANY_BASE_DELAY 10 * 1000 ++ ++/* ++ * This function should not be called directly, it is called by ++ * setting a timer in rfbAuthConsiderBlocking(). ++ */ ++ ++static CARD32 ++rfbAuthReenable(OsTimerPtr timer, CARD32 now, pointer arg) ++{ ++ rfbClientPtr cl = (rfbClientPtr) arg; ++ VNCSCREENPTR(cl->pScreen); ++ (void)cl; ++ pVNC->rfbAuthTooManyTries = FALSE; ++ return 0; ++} ++ ++/* ++ * This function should be called after each authentication failure. ++ * The return value will be true if there was too many failures. ++ */ ++ ++Bool ++rfbAuthConsiderBlocking(rfbClientPtr cl) ++{ ++ VNCSCREENPTR(cl->pScreen); ++ int i; ++ ++ pVNC->rfbAuthTries++; ++ ++ if (pVNC->rfbAuthTries >= MAX_AUTH_TRIES) { ++ CARD32 delay = AUTH_TOO_MANY_BASE_DELAY; ++ for (i = MAX_AUTH_TRIES; i < pVNC->rfbAuthTries; i++) ++ delay *= 2; ++ pVNC->timer = TimerSet(pVNC->timer, 0, delay, rfbAuthReenable, cl); ++ pVNC->rfbAuthTooManyTries = TRUE; ++ return TRUE; ++ } ++ ++ return FALSE; ++} ++ ++/* ++ * This function should be called after successful authentication. ++ * It resets the counter of authentication failures. Note that it's ++ * not necessary to clear the rfbAuthTooManyTries flag as it will be ++ * reset by the timer function. ++ */ ++ ++void ++rfbAuthUnblock(rfbClientPtr cl) ++{ ++ VNCSCREENPTR(cl->pScreen); ++ pVNC->rfbAuthTries = 0; ++} ++ ++/* ++ * This function should be called before authentication process. ++ * The return value will be true if there was too many authentication ++ * failures, and the server should not allow another try. ++ */ ++ ++Bool ++rfbAuthIsBlocked(rfbClientPtr cl) ++{ ++ VNCSCREENPTR(cl->pScreen); ++ return pVNC->rfbAuthTooManyTries; ++} ++ +diff -pNur xorg-server-1.4.orig/hw/vnc/cmap.c xorg-server-1.4/hw/vnc/cmap.c +--- xorg-server-1.4.orig/hw/vnc/cmap.c 1969-12-31 16:00:00.000000000 -0800 ++++ xorg-server-1.4/hw/vnc/cmap.c 2007-09-06 16:09:45.000000000 -0700 +@@ -0,0 +1,166 @@ ++/* ++ * cmap.c ++ * ++ * Modified for XFree86 4.x by Alan Hourihane ++ */ ++ ++/* ++ * 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. ++ ++*/ ++#ifdef HAVE_DIX_CONFIG_H ++#include ++#endif ++ ++#include "rfb.h" ++ ++int ++rfbListInstalledColormaps(pScreen, pmaps) ++ ScreenPtr pScreen; ++ Colormap *pmaps; ++{ ++ VNCSCREENPTR(pScreen); ++ /* By the time we are processing requests, we can guarantee that there ++ * is always a colormap installed */ ++ if (pVNC->rfbInstalledColormap) ++ *pmaps = pVNC->rfbInstalledColormap->mid; ++ ++#if XFREE86VNC ++ pScreen->ListInstalledColormaps = pVNC->ListInstalledColormaps; ++ (*pScreen->ListInstalledColormaps)(pScreen, pmaps); ++ pScreen->ListInstalledColormaps = rfbListInstalledColormaps; ++#endif ++ ++ return (1); ++} ++ ++ ++void ++rfbInstallColormap(pmap) ++ ColormapPtr pmap; ++{ ++ VNCSCREENPTR(pmap->pScreen); ++ ++ if (pmap != pVNC->rfbInstalledColormap) { ++ ++ if(pVNC->rfbInstalledColormap != (ColormapPtr)None) ++ WalkTree(pmap->pScreen, TellLostMap, ++ (char *)&pVNC->rfbInstalledColormap->mid); ++ /* Install pmap */ ++ pVNC->rfbInstalledColormap = pmap; ++ WalkTree(pmap->pScreen, TellGainedMap, (char *)&pmap->mid); ++ ++ rfbSetClientColourMaps(0, 0); ++ } ++#if XFREE86VNC ++ pmap->pScreen->InstallColormap = pVNC->InstallColormap; ++ (*pmap->pScreen->InstallColormap)(pmap); ++ pmap->pScreen->InstallColormap = rfbInstallColormap; ++#endif ++} ++ ++void ++rfbUninstallColormap(pmap) ++ ColormapPtr pmap; ++{ ++ VNCSCREENPTR(pmap->pScreen); ++ ++ if(pmap == pVNC->rfbInstalledColormap) ++ { ++ if (pmap->mid != pmap->pScreen->defColormap) ++ { ++ pVNC->rfbInstalledColormap = ++ (ColormapPtr) LookupIDByType(pmap->pScreen->defColormap, ++ RT_COLORMAP); ++ (*pmap->pScreen->InstallColormap)(pVNC->rfbInstalledColormap); ++ } ++ } ++#if XFREE86VNC ++ pmap->pScreen->UninstallColormap = pVNC->UninstallColormap; ++ (*pmap->pScreen->UninstallColormap)(pmap); ++ pmap->pScreen->UninstallColormap = rfbUninstallColormap; ++#endif ++} ++ ++ ++/* ++ * rfbStoreColors. We have a set of pixels but they may be in any order. ++ * If some of them happen to be in continuous ascending order then we can ++ * group them together into a single call to rfbSetClientColourMaps. ++ */ ++ ++void ++rfbStoreColors(pmap, ndef, pdefs) ++ ColormapPtr pmap; ++ int ndef; ++ xColorItem *pdefs; ++{ ++ VNCSCREENPTR(pmap->pScreen); ++ int i; ++ int first = -1; ++ int n = 0; ++ ++ if (pmap == pVNC->rfbInstalledColormap) { ++ for (i = 0; i < ndef; i++) { ++ if ((first != -1) && (first + n == pdefs[i].pixel)) { ++ n++; ++ } else { ++ if (first != -1) { ++ rfbSetClientColourMaps(first, n); ++ } ++ first = pdefs[i].pixel; ++ n = 1; ++ } ++ } ++ rfbSetClientColourMaps(first, n); ++ } ++#if XFREE86VNC ++ pmap->pScreen->StoreColors = pVNC->StoreColors; ++ (*pmap->pScreen->StoreColors)(pmap, ndef, pdefs); ++ pmap->pScreen->StoreColors = rfbStoreColors; ++#endif ++} +diff -pNur xorg-server-1.4.orig/hw/vnc/corre.c xorg-server-1.4/hw/vnc/corre.c +--- xorg-server-1.4.orig/hw/vnc/corre.c 1969-12-31 16:00:00.000000000 -0800 ++++ xorg-server-1.4/hw/vnc/corre.c 2007-09-06 16:09:45.000000000 -0700 +@@ -0,0 +1,353 @@ ++/* ++ * corre.c ++ * ++ * Routines to implement Compact Rise-and-Run-length Encoding (CoRRE). This ++ * code is based on krw's original javatel rfbserver. ++ * ++ * Modified for XFree86 4.x by Alan Hourihane ++ */ ++ ++/* ++ * 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. ++ */ ++#ifdef HAVE_DIX_CONFIG_H ++#include ++#endif ++ ++#include ++#include "rfb.h" ++ ++/* ++ * rreBeforeBuf contains pixel data in the client's format. ++ * rreAfterBuf contains the RRE encoded version. If the RRE encoded version is ++ * larger than the raw data or if it exceeds rreAfterBufSize then ++ * raw encoding is used instead. ++ */ ++ ++static int rreBeforeBufSize = 0; ++static unsigned char *rreBeforeBuf = NULL; ++ ++static int rreAfterBufSize = 0; ++static unsigned char *rreAfterBuf = NULL; ++static int rreAfterBufLen; ++ ++static int subrectEncode8(CARD8 *data, int w, int h); ++static int subrectEncode16(CARD16 *data, int w, int h); ++static int subrectEncode32(CARD32 *data, int w, int h); ++static CARD32 getBgColour(char *data, int size, int bpp); ++static Bool rfbSendSmallRectEncodingCoRRE(rfbClientPtr cl, int x, int y, ++ int w, int h); ++ ++ ++/* ++ * rfbSendRectEncodingCoRRE - send an arbitrary size rectangle using CoRRE ++ * encoding. ++ */ ++ ++Bool ++rfbSendRectEncodingCoRRE(cl, x, y, w, h) ++ rfbClientPtr cl; ++ int x, y, w, h; ++{ ++ if (h > cl->correMaxHeight) { ++ return (rfbSendRectEncodingCoRRE(cl, x, y, w, cl->correMaxHeight) && ++ rfbSendRectEncodingCoRRE(cl, x, y + cl->correMaxHeight, ++ w, h - cl->correMaxHeight)); ++ } ++ ++ if (w > cl->correMaxWidth) { ++ return (rfbSendRectEncodingCoRRE(cl, x, y, cl->correMaxWidth, h) && ++ rfbSendRectEncodingCoRRE(cl, x + cl->correMaxWidth, y, ++ w - cl->correMaxWidth, h)); ++ } ++ ++ return rfbSendSmallRectEncodingCoRRE(cl, x, y, w, h); ++} ++ ++ ++ ++/* ++ * rfbSendSmallRectEncodingCoRRE - send a small (guaranteed < 256x256) ++ * rectangle using CoRRE encoding. ++ */ ++ ++static Bool ++rfbSendSmallRectEncodingCoRRE(cl, x, y, w, h) ++ rfbClientPtr cl; ++ int x, y, w, h; ++{ ++ VNCSCREENPTR(cl->pScreen); ++ rfbFramebufferUpdateRectHeader rect; ++ rfbRREHeader hdr; ++ int nSubrects; ++ int i; ++ int maxRawSize = (pVNC->width * pVNC->height ++ * (cl->format.bitsPerPixel / 8)); ++ ++ if (rreBeforeBufSize < maxRawSize) { ++ rreBeforeBufSize = maxRawSize; ++ if (rreBeforeBuf == NULL) ++ rreBeforeBuf = (unsigned char *)xalloc(rreBeforeBufSize); ++ else ++ rreBeforeBuf = (unsigned char *)xrealloc(rreBeforeBuf, rreBeforeBufSize); ++ } ++ ++ if (rreAfterBufSize < maxRawSize) { ++ rreAfterBufSize = maxRawSize; ++ if (rreAfterBuf == NULL) ++ rreAfterBuf = (unsigned char *)xalloc(rreAfterBufSize); ++ else ++ rreAfterBuf = (unsigned char *)xrealloc(rreAfterBuf, rreAfterBufSize); ++ } ++ ++ (*cl->translateFn)(cl->pScreen, cl->translateLookupTable, ++ &pVNC->rfbServerFormat, ++ &cl->format, rreBeforeBuf, ++ pVNC->paddedWidthInBytes, w, h, x, y); ++ ++ switch (cl->format.bitsPerPixel) { ++ case 8: ++ nSubrects = subrectEncode8((CARD8 *)rreBeforeBuf, w, h); ++ break; ++ case 16: ++ nSubrects = subrectEncode16((CARD16 *)rreBeforeBuf, w, h); ++ break; ++ case 32: ++ nSubrects = subrectEncode32((CARD32 *)rreBeforeBuf, w, h); ++ break; ++ default: ++ rfbLog("getBgColour: bpp %d?\n",cl->format.bitsPerPixel); ++ exit(1); ++ } ++ ++ if (nSubrects < 0) { ++ ++ /* RRE encoding was too large, use raw */ ++ ++ return rfbSendRectEncodingRaw(cl, x, y, w, h); ++ } ++ ++ cl->rfbRectanglesSent[rfbEncodingCoRRE]++; ++ cl->rfbBytesSent[rfbEncodingCoRRE] += (sz_rfbFramebufferUpdateRectHeader ++ + sz_rfbRREHeader + rreAfterBufLen); ++ ++ if (pVNC->ublen + sz_rfbFramebufferUpdateRectHeader + sz_rfbRREHeader ++ > UPDATE_BUF_SIZE) ++ { ++ if (!rfbSendUpdateBuf(cl)) ++ return FALSE; ++ } ++ ++ rect.r.x = Swap16IfLE(x); ++ rect.r.y = Swap16IfLE(y); ++ rect.r.w = Swap16IfLE(w); ++ rect.r.h = Swap16IfLE(h); ++ rect.encoding = Swap32IfLE(rfbEncodingCoRRE); ++ ++ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&rect, ++ sz_rfbFramebufferUpdateRectHeader); ++ pVNC->ublen += sz_rfbFramebufferUpdateRectHeader; ++ ++ hdr.nSubrects = Swap32IfLE(nSubrects); ++ ++ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&hdr, sz_rfbRREHeader); ++ pVNC->ublen += sz_rfbRREHeader; ++ ++ for (i = 0; i < rreAfterBufLen;) { ++ ++ int bytesToCopy = UPDATE_BUF_SIZE - pVNC->ublen; ++ ++ if (i + bytesToCopy > rreAfterBufLen) { ++ bytesToCopy = rreAfterBufLen - i; ++ } ++ ++ memcpy(&pVNC->updateBuf[pVNC->ublen], &rreAfterBuf[i], bytesToCopy); ++ ++ pVNC->ublen += bytesToCopy; ++ i += bytesToCopy; ++ ++ if (pVNC->ublen == UPDATE_BUF_SIZE) { ++ if (!rfbSendUpdateBuf(cl)) ++ return FALSE; ++ } ++ } ++ ++ return TRUE; ++} ++ ++ ++ ++/* ++ * subrectEncode() encodes the given multicoloured rectangle as a background ++ * colour overwritten by single-coloured rectangles. It returns the number ++ * of subrectangles in the encoded buffer, or -1 if subrect encoding won't ++ * fit in the buffer. It puts the encoded rectangles in rreAfterBuf. The ++ * single-colour rectangle partition is not optimal, but does find the biggest ++ * horizontal or vertical rectangle top-left anchored to each consecutive ++ * coordinate position. ++ * ++ * The coding scheme is simply [...] where each ++ * is []. ++ */ ++ ++#define DEFINE_SUBRECT_ENCODE(bpp) \ ++static int \ ++subrectEncode##bpp(data,w,h) \ ++ CARD##bpp *data; \ ++ int w; \ ++ int h; \ ++{ \ ++ CARD##bpp cl; \ ++ rfbCoRRERectangle subrect; \ ++ int x,y; \ ++ int i,j; \ ++ int hx=0,hy,vx=0,vy; \ ++ int hyflag; \ ++ CARD##bpp *seg; \ ++ CARD##bpp *line; \ ++ int hw,hh,vw,vh; \ ++ int thex,they,thew,theh; \ ++ int numsubs = 0; \ ++ int newLen; \ ++ CARD##bpp bg = (CARD##bpp)getBgColour((char*)data,w*h,bpp); \ ++ \ ++ *((CARD##bpp*)rreAfterBuf) = bg; \ ++ \ ++ rreAfterBufLen = (bpp/8); \ ++ \ ++ for (y=0; y 0) && (i >= hx)) {hy += 1;} else {hyflag = 0;} \ ++ } \ ++ vy = j-1; \ ++ \ ++ /* We now have two possible subrects: (x,y,hx,hy) and (x,y,vx,vy) \ ++ * We'll choose the bigger of the two. \ ++ */ \ ++ hw = hx-x+1; \ ++ hh = hy-y+1; \ ++ vw = vx-x+1; \ ++ vh = vy-y+1; \ ++ \ ++ thex = x; \ ++ they = y; \ ++ \ ++ if ((hw*hh) > (vw*vh)) { \ ++ thew = hw; \ ++ theh = hh; \ ++ } else { \ ++ thew = vw; \ ++ theh = vh; \ ++ } \ ++ \ ++ subrect.x = thex; \ ++ subrect.y = they; \ ++ subrect.w = thew; \ ++ subrect.h = theh; \ ++ \ ++ newLen = rreAfterBufLen + (bpp/8) + sz_rfbCoRRERectangle; \ ++ if ((newLen > (w * h * (bpp/8))) || (newLen > rreAfterBufSize)) \ ++ return -1; \ ++ \ ++ numsubs += 1; \ ++ *((CARD##bpp*)(rreAfterBuf + rreAfterBufLen)) = cl; \ ++ rreAfterBufLen += (bpp/8); \ ++ memcpy(&rreAfterBuf[rreAfterBufLen],&subrect,sz_rfbCoRRERectangle); \ ++ rreAfterBufLen += sz_rfbCoRRERectangle; \ ++ \ ++ /* \ ++ * Now mark the subrect as done. \ ++ */ \ ++ for (j=they; j < (they+theh); j++) { \ ++ for (i=thex; i < (thex+thew); i++) { \ ++ data[j*w+i] = bg; \ ++ } \ ++ } \ ++ } \ ++ } \ ++ } \ ++ \ ++ return numsubs; \ ++} ++ ++DEFINE_SUBRECT_ENCODE(8) ++DEFINE_SUBRECT_ENCODE(16) ++DEFINE_SUBRECT_ENCODE(32) ++ ++ ++/* ++ * getBgColour() gets the most prevalent colour in a byte array. ++ */ ++static CARD32 ++getBgColour(data,size,bpp) ++ char *data; ++ int size; ++ int bpp; ++{ ++ ++#define NUMCLRS 256 ++ ++ static int counts[NUMCLRS]; ++ int i,j,k; ++ ++ int maxcount = 0; ++ CARD8 maxclr = 0; ++ ++ if (bpp != 8) { ++ if (bpp == 16) { ++ return ((CARD16 *)data)[0]; ++ } else if (bpp == 32) { ++ return ((CARD32 *)data)[0]; ++ } else { ++ rfbLog("getBgColour: bpp %d?\n",bpp); ++ exit(1); ++ } ++ } ++ ++ for (i=0; i= NUMCLRS) { ++ rfbLog("getBgColour: unusual colour = %d\n", k); ++ exit(1); ++ } ++ counts[k] += 1; ++ if (counts[k] > maxcount) { ++ maxcount = counts[k]; ++ maxclr = ((CARD8 *)data)[j]; ++ } ++ } ++ ++ return maxclr; ++} +diff -pNur xorg-server-1.4.orig/hw/vnc/cursor.c xorg-server-1.4/hw/vnc/cursor.c +--- xorg-server-1.4.orig/hw/vnc/cursor.c 1969-12-31 16:00:00.000000000 -0800 ++++ xorg-server-1.4/hw/vnc/cursor.c 2007-09-06 16:09:45.000000000 -0700 +@@ -0,0 +1,407 @@ ++/* ++ * cursor.c - support for cursor shape updates. ++ * ++ * Modified for XFree86 4.x by Alan Hourihane ++ */ ++ ++/* ++ * Copyright (C) 2000, 2001 Const Kaplinsky. All Rights Reserved. ++ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. ++ * ++ * This is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This software is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this software; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, ++ * USA. ++ */ ++#ifdef HAVE_DIX_CONFIG_H ++#include ++#endif ++ ++#include ++#include "rfb.h" ++#include "mipointer.h" ++#include "sprite.h" ++#include "cursorstr.h" ++#include "servermd.h" ++ ++ ++/* Copied from Xvnc/lib/font/util/utilbitmap.c */ ++static unsigned char _reverse_byte[0x100] = { ++ 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 ++}; ++ ++ ++static int EncodeRichCursorData8 (unsigned char *buf, rfbPixelFormat *fmt, ++ CursorPtr pCursor); ++static int EncodeRichCursorData16 (ScreenPtr pScreen, ++ unsigned char *buf, rfbPixelFormat *fmt, ++ CursorPtr pCursor); ++static int EncodeRichCursorData32 (ScreenPtr pScreen, ++ unsigned char *buf, rfbPixelFormat *fmt, ++ CursorPtr pCursor); ++ ++ ++/* ++ * Send cursor shape either in X-style format or in client pixel format. ++ */ ++ ++Bool ++rfbSendCursorShape(cl, pScreen) ++ rfbClientPtr cl; ++ ScreenPtr pScreen; ++{ ++ VNCSCREENPTR(pScreen); ++ CursorPtr pCursor; ++ rfbFramebufferUpdateRectHeader rect; ++ rfbXCursorColors colors; ++ int saved_ublen; ++ int bitmapRowBytes, paddedRowBytes, maskBytes, dataBytes; ++ int i, j; ++ CARD8 *bitmapData; ++ CARD8 bitmapByte; ++ ++ if (cl->useRichCursorEncoding) { ++ rect.encoding = Swap32IfLE(rfbEncodingRichCursor); ++ } else { ++ rect.encoding = Swap32IfLE(rfbEncodingXCursor); ++ } ++ ++#if XFREE86VNC ++ pCursor = pVNC->pCurs; ++#else ++ pCursor = rfbSpriteGetCursorPtr(pScreen); ++#endif ++ ++ /* If there is no cursor, send update with empty cursor data. */ ++ ++ if ( pCursor != NULL && ++ pCursor->bits->width == 1 && ++ pCursor->bits->height == 1 && ++ pCursor->bits->mask[0] == 0 ) { ++ pCursor = NULL; ++ } ++ ++ if (pCursor == NULL) { ++ if (pVNC->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE ) { ++ if (!rfbSendUpdateBuf(cl)) ++ return FALSE; ++ } ++ rect.r.x = rect.r.y = 0; ++ rect.r.w = rect.r.h = 0; ++ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&rect, ++ sz_rfbFramebufferUpdateRectHeader); ++ pVNC->ublen += sz_rfbFramebufferUpdateRectHeader; ++ ++ cl->rfbCursorShapeBytesSent += sz_rfbFramebufferUpdateRectHeader; ++ cl->rfbCursorShapeUpdatesSent++; ++ ++ return TRUE; ++ } ++ ++ /* Calculate data sizes. */ ++ ++ bitmapRowBytes = (pCursor->bits->width + 7) / 8; ++ paddedRowBytes = PixmapBytePad(pCursor->bits->width, 1); ++ maskBytes = bitmapRowBytes * pCursor->bits->height; ++ dataBytes = (cl->useRichCursorEncoding) ? ++ (pCursor->bits->width * pCursor->bits->height * ++ (cl->format.bitsPerPixel / 8)) : maskBytes; ++ ++ /* Send buffer contents if needed. */ ++ ++ if ( pVNC->ublen + sz_rfbFramebufferUpdateRectHeader + ++ sz_rfbXCursorColors + maskBytes + dataBytes > UPDATE_BUF_SIZE ) { ++ if (!rfbSendUpdateBuf(cl)) ++ return FALSE; ++ } ++ ++ if ( pVNC->ublen + sz_rfbFramebufferUpdateRectHeader + ++ sz_rfbXCursorColors + maskBytes + dataBytes > UPDATE_BUF_SIZE ) { ++ return FALSE; /* FIXME. */ ++ } ++ ++ saved_ublen = pVNC->ublen; ++ ++ /* Prepare rectangle header. */ ++ ++ rect.r.x = Swap16IfLE(pCursor->bits->xhot); ++ rect.r.y = Swap16IfLE(pCursor->bits->yhot); ++ rect.r.w = Swap16IfLE(pCursor->bits->width); ++ rect.r.h = Swap16IfLE(pCursor->bits->height); ++ ++ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&rect,sz_rfbFramebufferUpdateRectHeader); ++ pVNC->ublen += sz_rfbFramebufferUpdateRectHeader; ++ ++ /* Prepare actual cursor data (depends on encoding used). */ ++ ++ if (!cl->useRichCursorEncoding) { ++ /* XCursor encoding. */ ++ colors.foreRed = (char)(pCursor->foreRed >> 8); ++ colors.foreGreen = (char)(pCursor->foreGreen >> 8); ++ colors.foreBlue = (char)(pCursor->foreBlue >> 8); ++ colors.backRed = (char)(pCursor->backRed >> 8); ++ colors.backGreen = (char)(pCursor->backGreen >> 8); ++ colors.backBlue = (char)(pCursor->backBlue >> 8); ++ ++ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&colors, sz_rfbXCursorColors); ++ pVNC->ublen += sz_rfbXCursorColors; ++ ++ bitmapData = (CARD8 *)pCursor->bits->source; ++ ++ for (i = 0; i < pCursor->bits->height; i++) { ++ for (j = 0; j < bitmapRowBytes; j++) { ++ bitmapByte = bitmapData[i * paddedRowBytes + j]; ++ if (screenInfo.bitmapBitOrder == LSBFirst) { ++ bitmapByte = _reverse_byte[bitmapByte]; ++ } ++ pVNC->updateBuf[pVNC->ublen++] = (char)bitmapByte; ++ } ++ } ++ } else { ++ /* RichCursor encoding. */ ++ switch (cl->format.bitsPerPixel) { ++ case 8: ++ pVNC->ublen += EncodeRichCursorData8(&pVNC->updateBuf[pVNC->ublen], ++ &cl->format, pCursor); ++ break; ++ case 16: ++ pVNC->ublen += EncodeRichCursorData16(pScreen, &pVNC->updateBuf[pVNC->ublen], ++ &cl->format, pCursor); ++ break; ++ case 32: ++ pVNC->ublen += EncodeRichCursorData32(pScreen, &pVNC->updateBuf[pVNC->ublen], ++ &cl->format, pCursor); ++ break; ++ default: ++ return FALSE; ++ } ++ } ++ ++ /* Prepare transparency mask. */ ++ ++ bitmapData = (CARD8 *)pCursor->bits->mask; ++ ++ for (i = 0; i < pCursor->bits->height; i++) { ++ for (j = 0; j < bitmapRowBytes; j++) { ++ bitmapByte = bitmapData[i * paddedRowBytes + j]; ++ if (screenInfo.bitmapBitOrder == LSBFirst) { ++ bitmapByte = _reverse_byte[bitmapByte]; ++ } ++ pVNC->updateBuf[pVNC->ublen++] = (char)bitmapByte; ++ } ++ } ++ ++ /* Update statistics. */ ++ ++ cl->rfbCursorShapeBytesSent += (pVNC->ublen - saved_ublen); ++ cl->rfbCursorShapeUpdatesSent++; ++ ++ return TRUE; ++} ++ ++/* ++ * Send cursor position (PointerPos pseudo-encoding). ++ */ ++Bool ++rfbSendCursorPos(cl, pScreen) ++ rfbClientPtr cl; ++ ScreenPtr pScreen; ++{ ++ VNCSCREENPTR(pScreen); ++ rfbFramebufferUpdateRectHeader rect; ++#if XFREE86VNC ++ ScreenPtr pCursorScreen = miPointerCurrentScreen(); /*XXX deprecated*/ ++#endif ++ int x, y; ++ ++ if (pVNC->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) { ++ if (!rfbSendUpdateBuf(cl)) ++ return FALSE; ++ } ++ ++#if XFREE86VNC ++ if (pScreen == pCursorScreen) ++ miPointerPosition(&x, &y); ++#else ++ rfbSpriteGetCursorPos(pScreen, &x, &y); ++#endif ++ ++ rect.encoding = Swap32IfLE(rfbEncodingPointerPos); ++ rect.r.x = Swap16IfLE((CARD16)x); ++ rect.r.y = Swap16IfLE((CARD16)y); ++ rect.r.w = 0; ++ rect.r.h = 0; ++ ++ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&rect, ++ sz_rfbFramebufferUpdateRectHeader); ++ pVNC->ublen += sz_rfbFramebufferUpdateRectHeader; ++ ++ cl->rfbCursorPosBytesSent += sz_rfbFramebufferUpdateRectHeader; ++ cl->rfbCursorPosUpdatesSent++; ++ ++ if (!rfbSendUpdateBuf(cl)) ++ return FALSE; ++ ++ cl->cursorX = x; ++ cl->cursorY = y; ++ ++ return TRUE; ++} ++ ++/* ++ * Code to convert cursor source bitmap to the desired pixel format. ++ */ ++ ++#define RGB48_TO_PIXEL(fmt,r,g,b) \ ++ (((CARD32)(r) * ((fmt)->redMax + 1) >> 16) << (fmt)->redShift | \ ++ ((CARD32)(g) * ((fmt)->greenMax + 1) >> 16) << (fmt)->greenShift | \ ++ ((CARD32)(b) * ((fmt)->blueMax + 1) >> 16) << (fmt)->blueShift) ++ ++static int ++EncodeRichCursorData8(buf, fmt, pCursor) ++ unsigned char *buf; ++ rfbPixelFormat *fmt; ++ CursorPtr pCursor; ++{ ++ int widthPixels, widthBytes; ++ int x, y, b; ++ CARD8 *src; ++ char pix[2]; ++ CARD8 bitmapByte; ++ ++ pix[0] = (char)RGB48_TO_PIXEL(fmt, pCursor->backRed, pCursor->backGreen, ++ pCursor->backBlue); ++ pix[1] = (char)RGB48_TO_PIXEL(fmt, pCursor->foreRed, pCursor->foreGreen, ++ pCursor->foreBlue); ++ ++ src = (CARD8 *)pCursor->bits->source; ++ widthPixels = pCursor->bits->width; ++ widthBytes = PixmapBytePad(widthPixels, 1); ++ ++ for (y = 0; y < pCursor->bits->height; y++) { ++ for (x = 0; x < widthPixels / 8; x++) { ++ bitmapByte = src[y * widthBytes + x]; ++ if (screenInfo.bitmapBitOrder == LSBFirst) { ++ bitmapByte = _reverse_byte[bitmapByte]; ++ } ++ for (b = 7; b >= 0; b--) { ++ *buf++ = pix[bitmapByte >> b & 1]; ++ } ++ } ++ if (widthPixels % 8) { ++ bitmapByte = src[y * widthBytes + x]; ++ if (screenInfo.bitmapBitOrder == LSBFirst) { ++ bitmapByte = _reverse_byte[bitmapByte]; ++ } ++ for (b = 7; b > 7 - widthPixels % 8; b--) { ++ *buf++ = pix[bitmapByte >> b & 1]; ++ } ++ } ++ } ++ ++ return (widthPixels * pCursor->bits->height); ++} ++ ++#define DEFINE_RICH_ENCODE(bpp) \ ++ \ ++static int \ ++EncodeRichCursorData##bpp(pScreen, buf, fmt, pCursor) \ ++ ScreenPtr pScreen; \ ++ unsigned char *buf; \ ++ rfbPixelFormat *fmt; \ ++ CursorPtr pCursor; \ ++{ \ ++ VNCSCREENPTR(pScreen); \ ++ int widthPixels, widthBytes; \ ++ int x, y, b; \ ++ CARD8 *src; \ ++ CARD##bpp pix[2]; \ ++ CARD8 bitmapByte; \ ++ \ ++ pix[0] = (CARD##bpp)RGB48_TO_PIXEL(fmt, pCursor->backRed, \ ++ pCursor->backGreen, \ ++ pCursor->backBlue); \ ++ pix[1] = (CARD##bpp)RGB48_TO_PIXEL(fmt, pCursor->foreRed, \ ++ pCursor->foreGreen, \ ++ pCursor->foreBlue); \ ++ if (!pVNC->rfbServerFormat.bigEndian != !fmt->bigEndian) { \ ++ pix[0] = Swap##bpp(pix[0]); \ ++ pix[1] = Swap##bpp(pix[1]); \ ++ } \ ++ \ ++ src = (CARD8 *)pCursor->bits->source; \ ++ widthPixels = pCursor->bits->width; \ ++ widthBytes = PixmapBytePad(widthPixels, 1); \ ++ \ ++ for (y = 0; y < pCursor->bits->height; y++) { \ ++ for (x = 0; x < widthPixels / 8; x++) { \ ++ bitmapByte = src[y * widthBytes + x]; \ ++ if (screenInfo.bitmapBitOrder == LSBFirst) { \ ++ bitmapByte = _reverse_byte[bitmapByte]; \ ++ } \ ++ for (b = 7; b >= 0; b--) { \ ++ memcpy (buf, (char *)&pix[bitmapByte >> b & 1], \ ++ sizeof(CARD##bpp)); \ ++ buf += sizeof(CARD##bpp); \ ++ } \ ++ } \ ++ if (widthPixels % 8) { \ ++ bitmapByte = src[y * widthBytes + x]; \ ++ if (screenInfo.bitmapBitOrder == LSBFirst) { \ ++ bitmapByte = _reverse_byte[bitmapByte]; \ ++ } \ ++ for (b = 7; b > 7 - widthPixels % 8; b--) { \ ++ memcpy (buf, (char *)&pix[bitmapByte >> b & 1], \ ++ sizeof(CARD##bpp)); \ ++ buf += sizeof(CARD##bpp); \ ++ } \ ++ } \ ++ } \ ++ \ ++ return (widthPixels * pCursor->bits->height * (bpp / 8)); \ ++} ++ ++DEFINE_RICH_ENCODE(16) ++DEFINE_RICH_ENCODE(32) ++ +diff -pNur xorg-server-1.4.orig/hw/vnc/cutpaste.c xorg-server-1.4/hw/vnc/cutpaste.c +--- xorg-server-1.4.orig/hw/vnc/cutpaste.c 1969-12-31 16:00:00.000000000 -0800 ++++ xorg-server-1.4/hw/vnc/cutpaste.c 2007-09-06 16:09:45.000000000 -0700 +@@ -0,0 +1,90 @@ ++/* ++ * cutpaste.c - routines to deal with cut & paste buffers / selection. ++ * ++ * Modified for XFree86 4.x by Alan Hourihane ++ */ ++ ++/* ++ * 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. ++ */ ++#ifdef HAVE_DIX_CONFIG_H ++#include ++#endif ++ ++#include ++#define NEED_EVENTS ++#include ++#include ++#include "rfb.h" ++#include "selection.h" ++#include "input.h" ++#include ++ ++extern Selection *CurrentSelections; ++extern int NumCurrentSelections; ++ ++ ++static Bool inSetXCutText = FALSE; ++ ++/* ++ * rfbSetXCutText sets the cut buffer to be the given string. We also clear ++ * the primary selection. Ideally we'd like to set it to the same thing, but I ++ * can't work out how to do that without some kind of helper X client. ++ */ ++ ++void ++rfbSetXCutText(char *str, int len) ++{ ++ int i = 0; ++ ++ inSetXCutText = TRUE; ++ ChangeWindowProperty(WindowTable[0], XA_CUT_BUFFER0, XA_STRING, ++ 8, PropModeReplace, len, ++ (pointer)str, TRUE); ++ ++ while ((i < NumCurrentSelections) && ++ CurrentSelections[i].selection != XA_PRIMARY) ++ i++; ++ ++ if (i < NumCurrentSelections) { ++ xEvent event; ++ ++ if (CurrentSelections[i].client) { ++ event.u.u.type = SelectionClear; ++ event.u.selectionClear.time = GetTimeInMillis(); ++ event.u.selectionClear.window = CurrentSelections[i].window; ++ event.u.selectionClear.atom = CurrentSelections[i].selection; ++ (void) TryClientEvents (CurrentSelections[i].client, &event, 1, ++ NoEventMask, NoEventMask /* CantBeFiltered */, ++ NullGrab); ++ } ++ ++ CurrentSelections[i].window = None; ++ CurrentSelections[i].pWin = NULL; ++ CurrentSelections[i].client = NullClient; ++ } ++ ++ inSetXCutText = FALSE; ++} ++ ++ ++void rfbGotXCutText(char *str, int len) ++{ ++ if (!inSetXCutText) ++ rfbSendServerCutText(str, len); ++} +diff -pNur xorg-server-1.4.orig/hw/vnc/d3des.c xorg-server-1.4/hw/vnc/d3des.c +--- xorg-server-1.4.orig/hw/vnc/d3des.c 1969-12-31 16:00:00.000000000 -0800 ++++ xorg-server-1.4/hw/vnc/d3des.c 2007-09-06 16:09:45.000000000 -0700 +@@ -0,0 +1,437 @@ ++/* ++ * This is D3DES (V5.09) by Richard Outerbridge with the double and ++ * triple-length support removed for use in VNC. Also the bytebit[] array ++ * has been reversed so that the most significant bit in each byte of the ++ * key is ignored, not the least significant. ++ * ++ * These changes are: ++ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. ++ * ++ * This software is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++ */ ++ ++/* D3DES (V5.09) - ++ * ++ * A portable, public domain, version of the Data Encryption Standard. ++ * ++ * Written with Symantec's THINK (Lightspeed) C by Richard Outerbridge. ++ * Thanks to: Dan Hoey for his excellent Initial and Inverse permutation ++ * code; Jim Gillogly & Phil Karn for the DES key schedule code; Dennis ++ * Ferguson, Eric Young and Dana How for comparing notes; and Ray Lau, ++ * for humouring me on. ++ * ++ * Copyright (c) 1988,1989,1990,1991,1992 by Richard Outerbridge. ++ * (GEnie : OUTER; CIS : [71755,204]) Graven Imagery, 1992. ++ */ ++#ifdef HAVE_DIX_CONFIG_H ++#include ++#endif ++ ++#include "d3des.h" ++ ++static void scrunch(unsigned char *, unsigned long *); ++static void unscrun(unsigned long *, unsigned char *); ++static void desfunc(unsigned long *, unsigned long *); ++static void cookey(unsigned long *); ++ ++static unsigned long KnL[32] = { 0L }; ++ ++static unsigned short bytebit[8] = { ++ 01, 02, 04, 010, 020, 040, 0100, 0200 }; ++ ++static unsigned long bigbyte[24] = { ++ 0x800000L, 0x400000L, 0x200000L, 0x100000L, ++ 0x80000L, 0x40000L, 0x20000L, 0x10000L, ++ 0x8000L, 0x4000L, 0x2000L, 0x1000L, ++ 0x800L, 0x400L, 0x200L, 0x100L, ++ 0x80L, 0x40L, 0x20L, 0x10L, ++ 0x8L, 0x4L, 0x2L, 0x1L }; ++ ++/* Use the key schedule specified in the Standard (ANSI X3.92-1981). */ ++ ++static unsigned char pc1[56] = { ++ 56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17, ++ 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35, ++ 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21, ++ 13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3 }; ++ ++static unsigned char totrot[16] = { ++ 1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28 }; ++ ++static unsigned char pc2[48] = { ++ 13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9, ++ 22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1, ++ 40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47, ++ 43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31 }; ++ ++void deskey(key, edf) /* Thanks to James Gillogly & Phil Karn! */ ++unsigned char *key; ++int edf; ++{ ++ register int i, j, l, m, n; ++ unsigned char pc1m[56], pcr[56]; ++ unsigned long kn[32]; ++ ++ for ( j = 0; j < 56; j++ ) { ++ l = pc1[j]; ++ m = l & 07; ++ pc1m[j] = (key[l >> 3] & bytebit[m]) ? 1 : 0; ++ } ++ for( i = 0; i < 16; i++ ) { ++ if( edf == DE1 ) m = (15 - i) << 1; ++ else m = i << 1; ++ n = m + 1; ++ kn[m] = kn[n] = 0L; ++ for( j = 0; j < 28; j++ ) { ++ l = j + totrot[i]; ++ if( l < 28 ) pcr[j] = pc1m[l]; ++ else pcr[j] = pc1m[l - 28]; ++ } ++ for( j = 28; j < 56; j++ ) { ++ l = j + totrot[i]; ++ if( l < 56 ) pcr[j] = pc1m[l]; ++ else pcr[j] = pc1m[l - 28]; ++ } ++ for( j = 0; j < 24; j++ ) { ++ if( pcr[pc2[j]] ) kn[m] |= bigbyte[j]; ++ if( pcr[pc2[j+24]] ) kn[n] |= bigbyte[j]; ++ } ++ } ++ cookey(kn); ++ return; ++ } ++ ++static void cookey(raw1) ++register unsigned long *raw1; ++{ ++ register unsigned long *cook, *raw0; ++ unsigned long dough[32]; ++ register int i; ++ ++ cook = dough; ++ for( i = 0; i < 16; i++, raw1++ ) { ++ raw0 = raw1++; ++ *cook = (*raw0 & 0x00fc0000L) << 6; ++ *cook |= (*raw0 & 0x00000fc0L) << 10; ++ *cook |= (*raw1 & 0x00fc0000L) >> 10; ++ *cook++ |= (*raw1 & 0x00000fc0L) >> 6; ++ *cook = (*raw0 & 0x0003f000L) << 12; ++ *cook |= (*raw0 & 0x0000003fL) << 16; ++ *cook |= (*raw1 & 0x0003f000L) >> 4; ++ *cook++ |= (*raw1 & 0x0000003fL); ++ } ++ usekey(dough); ++ return; ++ } ++ ++void cpkey(into) ++register unsigned long *into; ++{ ++ register unsigned long *from, *endp; ++ ++ from = KnL, endp = &KnL[32]; ++ while( from < endp ) *into++ = *from++; ++ return; ++ } ++ ++void usekey(from) ++register unsigned long *from; ++{ ++ register unsigned long *to, *endp; ++ ++ to = KnL, endp = &KnL[32]; ++ while( to < endp ) *to++ = *from++; ++ return; ++ } ++ ++void des(inblock, outblock) ++unsigned char *inblock, *outblock; ++{ ++ unsigned long work[2]; ++ ++ scrunch(inblock, work); ++ desfunc(work, KnL); ++ unscrun(work, outblock); ++ return; ++ } ++ ++static void scrunch(outof, into) ++register unsigned char *outof; ++register unsigned long *into; ++{ ++ *into = (*outof++ & 0xffL) << 24; ++ *into |= (*outof++ & 0xffL) << 16; ++ *into |= (*outof++ & 0xffL) << 8; ++ *into++ |= (*outof++ & 0xffL); ++ *into = (*outof++ & 0xffL) << 24; ++ *into |= (*outof++ & 0xffL) << 16; ++ *into |= (*outof++ & 0xffL) << 8; ++ *into |= (*outof & 0xffL); ++ return; ++ } ++ ++static void unscrun(outof, into) ++register unsigned long *outof; ++register unsigned char *into; ++{ ++ *into++ = (*outof >> 24) & 0xffL; ++ *into++ = (*outof >> 16) & 0xffL; ++ *into++ = (*outof >> 8) & 0xffL; ++ *into++ = *outof++ & 0xffL; ++ *into++ = (*outof >> 24) & 0xffL; ++ *into++ = (*outof >> 16) & 0xffL; ++ *into++ = (*outof >> 8) & 0xffL; ++ *into = *outof & 0xffL; ++ return; ++ } ++ ++static unsigned long SP1[64] = { ++ 0x01010400L, 0x00000000L, 0x00010000L, 0x01010404L, ++ 0x01010004L, 0x00010404L, 0x00000004L, 0x00010000L, ++ 0x00000400L, 0x01010400L, 0x01010404L, 0x00000400L, ++ 0x01000404L, 0x01010004L, 0x01000000L, 0x00000004L, ++ 0x00000404L, 0x01000400L, 0x01000400L, 0x00010400L, ++ 0x00010400L, 0x01010000L, 0x01010000L, 0x01000404L, ++ 0x00010004L, 0x01000004L, 0x01000004L, 0x00010004L, ++ 0x00000000L, 0x00000404L, 0x00010404L, 0x01000000L, ++ 0x00010000L, 0x01010404L, 0x00000004L, 0x01010000L, ++ 0x01010400L, 0x01000000L, 0x01000000L, 0x00000400L, ++ 0x01010004L, 0x00010000L, 0x00010400L, 0x01000004L, ++ 0x00000400L, 0x00000004L, 0x01000404L, 0x00010404L, ++ 0x01010404L, 0x00010004L, 0x01010000L, 0x01000404L, ++ 0x01000004L, 0x00000404L, 0x00010404L, 0x01010400L, ++ 0x00000404L, 0x01000400L, 0x01000400L, 0x00000000L, ++ 0x00010004L, 0x00010400L, 0x00000000L, 0x01010004L }; ++ ++static unsigned long SP2[64] = { ++ 0x80108020L, 0x80008000L, 0x00008000L, 0x00108020L, ++ 0x00100000L, 0x00000020L, 0x80100020L, 0x80008020L, ++ 0x80000020L, 0x80108020L, 0x80108000L, 0x80000000L, ++ 0x80008000L, 0x00100000L, 0x00000020L, 0x80100020L, ++ 0x00108000L, 0x00100020L, 0x80008020L, 0x00000000L, ++ 0x80000000L, 0x00008000L, 0x00108020L, 0x80100000L, ++ 0x00100020L, 0x80000020L, 0x00000000L, 0x00108000L, ++ 0x00008020L, 0x80108000L, 0x80100000L, 0x00008020L, ++ 0x00000000L, 0x00108020L, 0x80100020L, 0x00100000L, ++ 0x80008020L, 0x80100000L, 0x80108000L, 0x00008000L, ++ 0x80100000L, 0x80008000L, 0x00000020L, 0x80108020L, ++ 0x00108020L, 0x00000020L, 0x00008000L, 0x80000000L, ++ 0x00008020L, 0x80108000L, 0x00100000L, 0x80000020L, ++ 0x00100020L, 0x80008020L, 0x80000020L, 0x00100020L, ++ 0x00108000L, 0x00000000L, 0x80008000L, 0x00008020L, ++ 0x80000000L, 0x80100020L, 0x80108020L, 0x00108000L }; ++ ++static unsigned long SP3[64] = { ++ 0x00000208L, 0x08020200L, 0x00000000L, 0x08020008L, ++ 0x08000200L, 0x00000000L, 0x00020208L, 0x08000200L, ++ 0x00020008L, 0x08000008L, 0x08000008L, 0x00020000L, ++ 0x08020208L, 0x00020008L, 0x08020000L, 0x00000208L, ++ 0x08000000L, 0x00000008L, 0x08020200L, 0x00000200L, ++ 0x00020200L, 0x08020000L, 0x08020008L, 0x00020208L, ++ 0x08000208L, 0x00020200L, 0x00020000L, 0x08000208L, ++ 0x00000008L, 0x08020208L, 0x00000200L, 0x08000000L, ++ 0x08020200L, 0x08000000L, 0x00020008L, 0x00000208L, ++ 0x00020000L, 0x08020200L, 0x08000200L, 0x00000000L, ++ 0x00000200L, 0x00020008L, 0x08020208L, 0x08000200L, ++ 0x08000008L, 0x00000200L, 0x00000000L, 0x08020008L, ++ 0x08000208L, 0x00020000L, 0x08000000L, 0x08020208L, ++ 0x00000008L, 0x00020208L, 0x00020200L, 0x08000008L, ++ 0x08020000L, 0x08000208L, 0x00000208L, 0x08020000L, ++ 0x00020208L, 0x00000008L, 0x08020008L, 0x00020200L }; ++ ++static unsigned long SP4[64] = { ++ 0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L, ++ 0x00802080L, 0x00800081L, 0x00800001L, 0x00002001L, ++ 0x00000000L, 0x00802000L, 0x00802000L, 0x00802081L, ++ 0x00000081L, 0x00000000L, 0x00800080L, 0x00800001L, ++ 0x00000001L, 0x00002000L, 0x00800000L, 0x00802001L, ++ 0x00000080L, 0x00800000L, 0x00002001L, 0x00002080L, ++ 0x00800081L, 0x00000001L, 0x00002080L, 0x00800080L, ++ 0x00002000L, 0x00802080L, 0x00802081L, 0x00000081L, ++ 0x00800080L, 0x00800001L, 0x00802000L, 0x00802081L, ++ 0x00000081L, 0x00000000L, 0x00000000L, 0x00802000L, ++ 0x00002080L, 0x00800080L, 0x00800081L, 0x00000001L, ++ 0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L, ++ 0x00802081L, 0x00000081L, 0x00000001L, 0x00002000L, ++ 0x00800001L, 0x00002001L, 0x00802080L, 0x00800081L, ++ 0x00002001L, 0x00002080L, 0x00800000L, 0x00802001L, ++ 0x00000080L, 0x00800000L, 0x00002000L, 0x00802080L }; ++ ++static unsigned long SP5[64] = { ++ 0x00000100L, 0x02080100L, 0x02080000L, 0x42000100L, ++ 0x00080000L, 0x00000100L, 0x40000000L, 0x02080000L, ++ 0x40080100L, 0x00080000L, 0x02000100L, 0x40080100L, ++ 0x42000100L, 0x42080000L, 0x00080100L, 0x40000000L, ++ 0x02000000L, 0x40080000L, 0x40080000L, 0x00000000L, ++ 0x40000100L, 0x42080100L, 0x42080100L, 0x02000100L, ++ 0x42080000L, 0x40000100L, 0x00000000L, 0x42000000L, ++ 0x02080100L, 0x02000000L, 0x42000000L, 0x00080100L, ++ 0x00080000L, 0x42000100L, 0x00000100L, 0x02000000L, ++ 0x40000000L, 0x02080000L, 0x42000100L, 0x40080100L, ++ 0x02000100L, 0x40000000L, 0x42080000L, 0x02080100L, ++ 0x40080100L, 0x00000100L, 0x02000000L, 0x42080000L, ++ 0x42080100L, 0x00080100L, 0x42000000L, 0x42080100L, ++ 0x02080000L, 0x00000000L, 0x40080000L, 0x42000000L, ++ 0x00080100L, 0x02000100L, 0x40000100L, 0x00080000L, ++ 0x00000000L, 0x40080000L, 0x02080100L, 0x40000100L }; ++ ++static unsigned long SP6[64] = { ++ 0x20000010L, 0x20400000L, 0x00004000L, 0x20404010L, ++ 0x20400000L, 0x00000010L, 0x20404010L, 0x00400000L, ++ 0x20004000L, 0x00404010L, 0x00400000L, 0x20000010L, ++ 0x00400010L, 0x20004000L, 0x20000000L, 0x00004010L, ++ 0x00000000L, 0x00400010L, 0x20004010L, 0x00004000L, ++ 0x00404000L, 0x20004010L, 0x00000010L, 0x20400010L, ++ 0x20400010L, 0x00000000L, 0x00404010L, 0x20404000L, ++ 0x00004010L, 0x00404000L, 0x20404000L, 0x20000000L, ++ 0x20004000L, 0x00000010L, 0x20400010L, 0x00404000L, ++ 0x20404010L, 0x00400000L, 0x00004010L, 0x20000010L, ++ 0x00400000L, 0x20004000L, 0x20000000L, 0x00004010L, ++ 0x20000010L, 0x20404010L, 0x00404000L, 0x20400000L, ++ 0x00404010L, 0x20404000L, 0x00000000L, 0x20400010L, ++ 0x00000010L, 0x00004000L, 0x20400000L, 0x00404010L, ++ 0x00004000L, 0x00400010L, 0x20004010L, 0x00000000L, ++ 0x20404000L, 0x20000000L, 0x00400010L, 0x20004010L }; ++ ++static unsigned long SP7[64] = { ++ 0x00200000L, 0x04200002L, 0x04000802L, 0x00000000L, ++ 0x00000800L, 0x04000802L, 0x00200802L, 0x04200800L, ++ 0x04200802L, 0x00200000L, 0x00000000L, 0x04000002L, ++ 0x00000002L, 0x04000000L, 0x04200002L, 0x00000802L, ++ 0x04000800L, 0x00200802L, 0x00200002L, 0x04000800L, ++ 0x04000002L, 0x04200000L, 0x04200800L, 0x00200002L, ++ 0x04200000L, 0x00000800L, 0x00000802L, 0x04200802L, ++ 0x00200800L, 0x00000002L, 0x04000000L, 0x00200800L, ++ 0x04000000L, 0x00200800L, 0x00200000L, 0x04000802L, ++ 0x04000802L, 0x04200002L, 0x04200002L, 0x00000002L, ++ 0x00200002L, 0x04000000L, 0x04000800L, 0x00200000L, ++ 0x04200800L, 0x00000802L, 0x00200802L, 0x04200800L, ++ 0x00000802L, 0x04000002L, 0x04200802L, 0x04200000L, ++ 0x00200800L, 0x00000000L, 0x00000002L, 0x04200802L, ++ 0x00000000L, 0x00200802L, 0x04200000L, 0x00000800L, ++ 0x04000002L, 0x04000800L, 0x00000800L, 0x00200002L }; ++ ++static unsigned long SP8[64] = { ++ 0x10001040L, 0x00001000L, 0x00040000L, 0x10041040L, ++ 0x10000000L, 0x10001040L, 0x00000040L, 0x10000000L, ++ 0x00040040L, 0x10040000L, 0x10041040L, 0x00041000L, ++ 0x10041000L, 0x00041040L, 0x00001000L, 0x00000040L, ++ 0x10040000L, 0x10000040L, 0x10001000L, 0x00001040L, ++ 0x00041000L, 0x00040040L, 0x10040040L, 0x10041000L, ++ 0x00001040L, 0x00000000L, 0x00000000L, 0x10040040L, ++ 0x10000040L, 0x10001000L, 0x00041040L, 0x00040000L, ++ 0x00041040L, 0x00040000L, 0x10041000L, 0x00001000L, ++ 0x00000040L, 0x10040040L, 0x00001000L, 0x00041040L, ++ 0x10001000L, 0x00000040L, 0x10000040L, 0x10040000L, ++ 0x10040040L, 0x10000000L, 0x00040000L, 0x10001040L, ++ 0x00000000L, 0x10041040L, 0x00040040L, 0x10000040L, ++ 0x10040000L, 0x10001000L, 0x10001040L, 0x00000000L, ++ 0x10041040L, 0x00041000L, 0x00041000L, 0x00001040L, ++ 0x00001040L, 0x00040040L, 0x10000000L, 0x10041000L }; ++ ++static void desfunc(block, keys) ++register unsigned long *block, *keys; ++{ ++ register unsigned long fval, work, right, leftt; ++ register int round; ++ ++ leftt = block[0]; ++ right = block[1]; ++ work = ((leftt >> 4) ^ right) & 0x0f0f0f0fL; ++ right ^= work; ++ leftt ^= (work << 4); ++ work = ((leftt >> 16) ^ right) & 0x0000ffffL; ++ right ^= work; ++ leftt ^= (work << 16); ++ work = ((right >> 2) ^ leftt) & 0x33333333L; ++ leftt ^= work; ++ right ^= (work << 2); ++ work = ((right >> 8) ^ leftt) & 0x00ff00ffL; ++ leftt ^= work; ++ right ^= (work << 8); ++ right = ((right << 1) | ((right >> 31) & 1L)) & 0xffffffffL; ++ work = (leftt ^ right) & 0xaaaaaaaaL; ++ leftt ^= work; ++ right ^= work; ++ leftt = ((leftt << 1) | ((leftt >> 31) & 1L)) & 0xffffffffL; ++ ++ for( round = 0; round < 8; round++ ) { ++ work = (right << 28) | (right >> 4); ++ work ^= *keys++; ++ fval = SP7[ work & 0x3fL]; ++ fval |= SP5[(work >> 8) & 0x3fL]; ++ fval |= SP3[(work >> 16) & 0x3fL]; ++ fval |= SP1[(work >> 24) & 0x3fL]; ++ work = right ^ *keys++; ++ fval |= SP8[ work & 0x3fL]; ++ fval |= SP6[(work >> 8) & 0x3fL]; ++ fval |= SP4[(work >> 16) & 0x3fL]; ++ fval |= SP2[(work >> 24) & 0x3fL]; ++ leftt ^= fval; ++ work = (leftt << 28) | (leftt >> 4); ++ work ^= *keys++; ++ fval = SP7[ work & 0x3fL]; ++ fval |= SP5[(work >> 8) & 0x3fL]; ++ fval |= SP3[(work >> 16) & 0x3fL]; ++ fval |= SP1[(work >> 24) & 0x3fL]; ++ work = leftt ^ *keys++; ++ fval |= SP8[ work & 0x3fL]; ++ fval |= SP6[(work >> 8) & 0x3fL]; ++ fval |= SP4[(work >> 16) & 0x3fL]; ++ fval |= SP2[(work >> 24) & 0x3fL]; ++ right ^= fval; ++ } ++ ++ right = (right << 31) | (right >> 1); ++ work = (leftt ^ right) & 0xaaaaaaaaL; ++ leftt ^= work; ++ right ^= work; ++ leftt = (leftt << 31) | (leftt >> 1); ++ work = ((leftt >> 8) ^ right) & 0x00ff00ffL; ++ right ^= work; ++ leftt ^= (work << 8); ++ work = ((leftt >> 2) ^ right) & 0x33333333L; ++ right ^= work; ++ leftt ^= (work << 2); ++ work = ((right >> 16) ^ leftt) & 0x0000ffffL; ++ leftt ^= work; ++ right ^= (work << 16); ++ work = ((right >> 4) ^ leftt) & 0x0f0f0f0fL; ++ leftt ^= work; ++ right ^= (work << 4); ++ *block++ = right; ++ *block = leftt; ++ return; ++ } ++ ++/* Validation sets: ++ * ++ * Single-length key, single-length plaintext - ++ * Key : 0123 4567 89ab cdef ++ * Plain : 0123 4567 89ab cde7 ++ * Cipher : c957 4425 6a5e d31d ++ * ++ * Double-length key, single-length plaintext - ++ * Key : 0123 4567 89ab cdef fedc ba98 7654 3210 ++ * Plain : 0123 4567 89ab cde7 ++ * Cipher : 7f1d 0a77 826b 8aff ++ * ++ * Double-length key, double-length plaintext - ++ * Key : 0123 4567 89ab cdef fedc ba98 7654 3210 ++ * Plain : 0123 4567 89ab cdef 0123 4567 89ab cdff ++ * Cipher : 27a0 8440 406a df60 278f 47cf 42d6 15d7 ++ * ++ * Triple-length key, single-length plaintext - ++ * Key : 0123 4567 89ab cdef fedc ba98 7654 3210 89ab cdef 0123 4567 ++ * Plain : 0123 4567 89ab cde7 ++ * Cipher : de0b 7c06 ae5e 0ed5 ++ * ++ * Triple-length key, double-length plaintext - ++ * Key : 0123 4567 89ab cdef fedc ba98 7654 3210 89ab cdef 0123 4567 ++ * Plain : 0123 4567 89ab cdef 0123 4567 89ab cdff ++ * Cipher : ad0d 1b30 ac17 cf07 0ed1 1c63 81e4 4de5 ++ * ++ * d3des V5.0a rwo 9208.07 18:44 Graven Imagery ++ **********************************************************************/ +diff -pNur xorg-server-1.4.orig/hw/vnc/d3des.h xorg-server-1.4/hw/vnc/d3des.h +--- xorg-server-1.4.orig/hw/vnc/d3des.h 1969-12-31 16:00:00.000000000 -0800 ++++ xorg-server-1.4/hw/vnc/d3des.h 2007-09-06 16:09:45.000000000 -0700 +@@ -0,0 +1,51 @@ ++/* ++ * This is D3DES (V5.09) by Richard Outerbridge with the double and ++ * triple-length support removed for use in VNC. ++ * ++ * These changes are: ++ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. ++ * ++ * This software is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++ */ ++ ++/* d3des.h - ++ * ++ * Headers and defines for d3des.c ++ * Graven Imagery, 1992. ++ * ++ * Copyright (c) 1988,1989,1990,1991,1992 by Richard Outerbridge ++ * (GEnie : OUTER; CIS : [71755,204]) ++ */ ++ ++#define EN0 0 /* MODE == encrypt */ ++#define DE1 1 /* MODE == decrypt */ ++ ++extern void deskey(unsigned char *, int); ++/* hexkey[8] MODE ++ * Sets the internal key register according to the hexadecimal ++ * key contained in the 8 bytes of hexkey, according to the DES, ++ * for encryption or decryption according to MODE. ++ */ ++ ++extern void usekey(unsigned long *); ++/* cookedkey[32] ++ * Loads the internal key register with the data in cookedkey. ++ */ ++ ++extern void cpkey(unsigned long *); ++/* cookedkey[32] ++ * Copies the contents of the internal key register into the storage ++ * located at &cookedkey[0]. ++ */ ++ ++extern void des(unsigned char *, unsigned char *); ++/* from[8] to[8] ++ * Encrypts/Decrypts (according to the key currently loaded in the ++ * internal key register) one block of eight bytes at address 'from' ++ * into the block at address 'to'. They can be the same. ++ */ ++ ++/* d3des.h V5.09 rwo 9208.04 15:06 Graven Imagery ++ ********************************************************************/ +diff -pNur xorg-server-1.4.orig/hw/vnc/dispcur.c xorg-server-1.4/hw/vnc/dispcur.c +--- xorg-server-1.4.orig/hw/vnc/dispcur.c 1969-12-31 16:00:00.000000000 -0800 ++++ xorg-server-1.4/hw/vnc/dispcur.c 2007-09-06 16:09:45.000000000 -0700 +@@ -0,0 +1,791 @@ ++/* ++ * dispcur.c ++ * ++ * cursor display routines - based on midispcur.c ++ * ++ * Modified for XFree86 4.x by Alan Hourihane ++ */ ++ ++/* ++ * 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) 1989 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. ++*/ ++#ifdef HAVE_DIX_CONFIG_H ++#include ++#endif ++ ++#define NEED_EVENTS ++# include ++# include "rfb.h" ++# include "misc.h" ++# include "input.h" ++# include "cursorstr.h" ++# include "windowstr.h" ++# include "regionstr.h" ++# include "dixstruct.h" ++# include "scrnintstr.h" ++# include "servermd.h" ++# include "sprite.h" ++# include "gcstruct.h" ++ ++#ifdef ARGB_CURSOR ++# include "picturestr.h" ++#endif ++ ++/* per-screen private data */ ++ ++static int rfbDCScreenIndex; ++static unsigned long rfbDCGeneration = 0; ++ ++static Bool rfbDCCloseScreen(int index, ScreenPtr pScreen); ++ ++typedef struct { ++ GCPtr pSourceGC, pMaskGC; ++ GCPtr pSaveGC, pRestoreGC; ++ GCPtr pMoveGC; ++ GCPtr pPixSourceGC, pPixMaskGC; ++ CloseScreenProcPtr CloseScreen; ++ PixmapPtr pSave, pTemp; ++#ifdef ARGB_CURSOR ++ PicturePtr pRootPicture; ++ PicturePtr pTempPicture; ++#endif ++} rfbDCScreenRec, *rfbDCScreenPtr; ++ ++/* per-cursor per-screen private data */ ++typedef struct { ++ PixmapPtr sourceBits; /* source bits */ ++ PixmapPtr maskBits; /* mask bits */ ++#ifdef ARGB_CURSOR ++ PicturePtr pPicture; ++#endif ++} rfbDCCursorRec, *rfbDCCursorPtr; ++ ++/* ++ * sprite/cursor method table ++ */ ++ ++static Bool rfbDCRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor); ++static Bool rfbDCUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCursor); ++static Bool rfbDCPutUpCursor(ScreenPtr pScreen, CursorPtr pCursor, ++ int x, int y, unsigned long source, ++ unsigned long mask); ++static Bool rfbDCSaveUnderCursor(ScreenPtr pScreen, int x, int y, ++ int w, int h); ++static Bool rfbDCRestoreUnderCursor(ScreenPtr pScreen, int x, int y, ++ int w, int h); ++static Bool rfbDCMoveCursor(ScreenPtr pScreen, CursorPtr pCursor, ++ int x, int y, int w, int h, int dx, int dy, ++ unsigned long source, unsigned long mask); ++static Bool rfbDCChangeSave(ScreenPtr pScreen, int x, int y, int w, int h, ++ int dx, int dy); ++ ++static rfbSpriteCursorFuncRec rfbDCFuncs = { ++ rfbDCRealizeCursor, ++ rfbDCUnrealizeCursor, ++ rfbDCPutUpCursor, ++ rfbDCSaveUnderCursor, ++ rfbDCRestoreUnderCursor, ++ rfbDCMoveCursor, ++ rfbDCChangeSave, ++}; ++ ++Bool ++rfbDCInitialize (ScreenPtr pScreen, miPointerScreenFuncPtr screenFuncs) ++{ ++ rfbDCScreenPtr pScreenPriv; ++ ++ if (rfbDCGeneration != serverGeneration) ++ { ++ rfbDCScreenIndex = AllocateScreenPrivateIndex (); ++ if (rfbDCScreenIndex < 0) ++ return FALSE; ++ rfbDCGeneration = serverGeneration; ++ } ++ pScreenPriv = (rfbDCScreenPtr) xalloc (sizeof (rfbDCScreenRec)); ++ if (!pScreenPriv) ++ return FALSE; ++ ++ /* ++ * initialize the entire private structure to zeros ++ */ ++ ++ pScreenPriv->pSourceGC = ++ pScreenPriv->pMaskGC = ++ pScreenPriv->pSaveGC = ++ pScreenPriv->pRestoreGC = ++ pScreenPriv->pMoveGC = ++ pScreenPriv->pPixSourceGC = ++ pScreenPriv->pPixMaskGC = NULL; ++#ifdef ARGB_CURSOR ++ pScreenPriv->pRootPicture = NULL; ++ pScreenPriv->pTempPicture = NULL; ++#endif ++ ++ pScreenPriv->pSave = pScreenPriv->pTemp = NULL; ++ ++ pScreenPriv->CloseScreen = pScreen->CloseScreen; ++ pScreen->CloseScreen = rfbDCCloseScreen; ++ ++ pScreen->devPrivates[rfbDCScreenIndex].ptr = (pointer) pScreenPriv; ++ ++ if (!rfbSpriteInitialize (pScreen, &rfbDCFuncs, screenFuncs)) ++ { ++ xfree ((pointer) pScreenPriv); ++ return FALSE; ++ } ++ return TRUE; ++} ++ ++#define tossGC(gc) (gc ? FreeGC (gc, (GContext) 0) : 0) ++#define tossPix(pix) (pix ? (*pScreen->DestroyPixmap) (pix) : TRUE) ++#define tossPict(pict) (pict ? FreePicture (pict, 0) : 0) ++ ++static Bool ++rfbDCCloseScreen (index, pScreen) ++ ScreenPtr pScreen; ++{ ++ rfbDCScreenPtr pScreenPriv; ++ ++ pScreenPriv = (rfbDCScreenPtr) pScreen->devPrivates[rfbDCScreenIndex].ptr; ++ pScreen->CloseScreen = pScreenPriv->CloseScreen; ++ tossGC (pScreenPriv->pSourceGC); ++ tossGC (pScreenPriv->pMaskGC); ++ tossGC (pScreenPriv->pSaveGC); ++ tossGC (pScreenPriv->pRestoreGC); ++ tossGC (pScreenPriv->pMoveGC); ++ tossGC (pScreenPriv->pPixSourceGC); ++ tossGC (pScreenPriv->pPixMaskGC); ++ tossPix (pScreenPriv->pSave); ++ tossPix (pScreenPriv->pTemp); ++#ifdef ARGB_CURSOR ++ tossPict (pScreenPriv->pRootPicture); ++ tossPict (pScreenPriv->pTempPicture); ++#endif ++ xfree ((pointer) pScreenPriv); ++ return (*pScreen->CloseScreen) (index, pScreen); ++} ++ ++static Bool ++rfbDCRealizeCursor (pScreen, pCursor) ++ ScreenPtr pScreen; ++ CursorPtr pCursor; ++{ ++ if (pCursor->bits->refcnt <= 1) ++ pCursor->bits->devPriv[pScreen->myNum] = (pointer)NULL; ++ return TRUE; ++} ++ ++#ifdef ARGB_CURSOR ++#define EnsurePicture(picture,draw,win) (picture || rfbDCMakePicture(&picture,draw,win)) ++ ++static VisualPtr ++rfbDCGetWindowVisual (WindowPtr pWin) ++{ ++ ScreenPtr pScreen = pWin->drawable.pScreen; ++ VisualID vid = wVisual (pWin); ++ int i; ++ ++ for (i = 0; i < pScreen->numVisuals; i++) ++ if (pScreen->visuals[i].vid == vid) ++ return &pScreen->visuals[i]; ++ return 0; ++} ++ ++static PicturePtr ++rfbDCMakePicture (PicturePtr *ppPicture, DrawablePtr pDraw, WindowPtr pWin) ++{ ++ ScreenPtr pScreen = pDraw->pScreen; ++ VisualPtr pVisual; ++ PictFormatPtr pFormat; ++ XID subwindow_mode = IncludeInferiors; ++ PicturePtr pPicture; ++ int error; ++ ++ pVisual = rfbDCGetWindowVisual (pWin); ++ if (!pVisual) ++ return 0; ++ pFormat = PictureMatchVisual (pScreen, pDraw->depth, pVisual); ++ if (!pFormat) ++ return 0; ++ pPicture = CreatePicture (0, pDraw, pFormat, ++ CPSubwindowMode, &subwindow_mode, ++ serverClient, &error); ++ *ppPicture = pPicture; ++ return pPicture; ++} ++#endif ++ ++static rfbDCCursorPtr ++rfbDCRealize (ScreenPtr pScreen, CursorPtr pCursor) ++{ ++ rfbDCCursorPtr pPriv; ++ GCPtr pGC; ++ XID gcvals[3]; ++ ++ pPriv = (rfbDCCursorPtr) xalloc (sizeof (rfbDCCursorRec)); ++ if (!pPriv) ++ return (rfbDCCursorPtr)NULL; ++#ifdef ARGB_CURSOR ++ if (pCursor->bits->argb) ++ { ++ PixmapPtr pPixmap; ++ PictFormatPtr pFormat; ++ int error; ++ ++ pFormat = PictureMatchFormat (pScreen, 32, PICT_a8r8g8b8); ++ if (!pFormat) ++ { ++ xfree ((pointer) pPriv); ++ return (rfbDCCursorPtr)NULL; ++ } ++ ++ pPriv->sourceBits = 0; ++ pPriv->maskBits = 0; ++ pPixmap = (*pScreen->CreatePixmap) (pScreen, pCursor->bits->width, ++ pCursor->bits->height, 32); ++ if (!pPixmap) ++ { ++ xfree ((pointer) pPriv); ++ return (rfbDCCursorPtr)NULL; ++ } ++ pGC = GetScratchGC (32, pScreen); ++ if (!pGC) ++ { ++ (*pScreen->DestroyPixmap) (pPixmap); ++ xfree ((pointer) pPriv); ++ return (rfbDCCursorPtr)NULL; ++ } ++ ValidateGC (&pPixmap->drawable, pGC); ++ (*pGC->ops->PutImage) (&pPixmap->drawable, pGC, 32, ++ 0, 0, pCursor->bits->width, ++ pCursor->bits->height, ++ 0, ZPixmap, (char *) pCursor->bits->argb); ++ FreeScratchGC (pGC); ++ pPriv->pPicture = CreatePicture (0, &pPixmap->drawable, ++ pFormat, 0, 0, serverClient, &error); ++ (*pScreen->DestroyPixmap) (pPixmap); ++ if (!pPriv->pPicture) ++ { ++ xfree ((pointer) pPriv); ++ return (rfbDCCursorPtr)NULL; ++ } ++ pCursor->bits->devPriv[pScreen->myNum] = (pointer) pPriv; ++ return pPriv; ++ } ++ pPriv->pPicture = 0; ++#endif ++ pPriv->sourceBits = (*pScreen->CreatePixmap) (pScreen, pCursor->bits->width, pCursor->bits->height, 1); ++ if (!pPriv->sourceBits) ++ { ++ xfree ((pointer) pPriv); ++ return (rfbDCCursorPtr)NULL; ++ } ++ pPriv->maskBits = (*pScreen->CreatePixmap) (pScreen, pCursor->bits->width, pCursor->bits->height, 1); ++ if (!pPriv->maskBits) ++ { ++ (*pScreen->DestroyPixmap) (pPriv->sourceBits); ++ xfree ((pointer) pPriv); ++ return (rfbDCCursorPtr)NULL; ++ } ++ pCursor->bits->devPriv[pScreen->myNum] = (pointer) pPriv; ++ ++ /* create the two sets of bits, clipping as appropriate */ ++ ++ pGC = GetScratchGC (1, pScreen); ++ if (!pGC) ++ { ++ (void) rfbDCUnrealizeCursor (pScreen, pCursor); ++ return (rfbDCCursorPtr)NULL; ++ } ++ ++ ValidateGC ((DrawablePtr)pPriv->sourceBits, pGC); ++ (*pGC->ops->PutImage) ((DrawablePtr)pPriv->sourceBits, pGC, 1, ++ 0, 0, pCursor->bits->width, pCursor->bits->height, ++ 0, XYPixmap, (char *)pCursor->bits->source); ++ gcvals[0] = GXand; ++ ChangeGC (pGC, GCFunction, gcvals); ++ ValidateGC ((DrawablePtr)pPriv->sourceBits, pGC); ++ (*pGC->ops->PutImage) ((DrawablePtr)pPriv->sourceBits, pGC, 1, ++ 0, 0, pCursor->bits->width, pCursor->bits->height, ++ 0, XYPixmap, (char *)pCursor->bits->mask); ++ ++ /* mask bits -- pCursor->mask & ~pCursor->source */ ++ gcvals[0] = GXcopy; ++ ChangeGC (pGC, GCFunction, gcvals); ++ ValidateGC ((DrawablePtr)pPriv->maskBits, pGC); ++ (*pGC->ops->PutImage) ((DrawablePtr)pPriv->maskBits, pGC, 1, ++ 0, 0, pCursor->bits->width, pCursor->bits->height, ++ 0, XYPixmap, (char *)pCursor->bits->mask); ++ gcvals[0] = GXandInverted; ++ ChangeGC (pGC, GCFunction, gcvals); ++ ValidateGC ((DrawablePtr)pPriv->maskBits, pGC); ++ (*pGC->ops->PutImage) ((DrawablePtr)pPriv->maskBits, pGC, 1, ++ 0, 0, pCursor->bits->width, pCursor->bits->height, ++ 0, XYPixmap, (char *)pCursor->bits->source); ++ FreeScratchGC (pGC); ++ return pPriv; ++} ++ ++static Bool ++rfbDCUnrealizeCursor (pScreen, pCursor) ++ ScreenPtr pScreen; ++ CursorPtr pCursor; ++{ ++ rfbDCCursorPtr pPriv; ++ ++ pPriv = (rfbDCCursorPtr) pCursor->bits->devPriv[pScreen->myNum]; ++ if (pPriv && (pCursor->bits->refcnt <= 1)) ++ { ++ if (pPriv->sourceBits) ++ (*pScreen->DestroyPixmap) (pPriv->sourceBits); ++ if (pPriv->maskBits) ++ (*pScreen->DestroyPixmap) (pPriv->maskBits); ++#ifdef ARGB_CURSOR ++ if (pPriv->pPicture) ++ FreePicture (pPriv->pPicture, 0); ++#endif ++ xfree ((pointer) pPriv); ++ pCursor->bits->devPriv[pScreen->myNum] = (pointer)NULL; ++ } ++ return TRUE; ++} ++ ++static void ++rfbDCPutBits (DrawablePtr pDrawable, rfbDCCursorPtr pPriv, GCPtr sourceGC, GCPtr maskGC, int x, int y, unsigned w, unsigned h, unsigned long source, unsigned long mask) ++{ ++ XID gcvals[1]; ++ ++ if (sourceGC->fgPixel != source) ++ { ++ gcvals[0] = source; ++ DoChangeGC (sourceGC, GCForeground, gcvals, 0); ++ } ++ if (sourceGC->serialNumber != pDrawable->serialNumber) ++ ValidateGC (pDrawable, sourceGC); ++ (*sourceGC->ops->PushPixels) (sourceGC, pPriv->sourceBits, pDrawable, w, h, x, y); ++ if (maskGC->fgPixel != mask) ++ { ++ gcvals[0] = mask; ++ DoChangeGC (maskGC, GCForeground, gcvals, 0); ++ } ++ if (maskGC->serialNumber != pDrawable->serialNumber) ++ ValidateGC (pDrawable, maskGC); ++ (*maskGC->ops->PushPixels) (maskGC, pPriv->maskBits, pDrawable, w, h, x, y); ++} ++ ++#define EnsureGC(gc,win) (gc || rfbDCMakeGC(&gc, win)) ++ ++static GCPtr ++rfbDCMakeGC(GCPtr *ppGC, WindowPtr pWin) ++{ ++ GCPtr pGC; ++ int status; ++ XID gcvals[2]; ++ ++ gcvals[0] = IncludeInferiors; ++ gcvals[1] = FALSE; ++ pGC = CreateGC((DrawablePtr)pWin, ++ GCSubwindowMode|GCGraphicsExposures, gcvals, &status); ++ if (pGC && pWin->drawable.pScreen->DrawGuarantee) ++ (*pWin->drawable.pScreen->DrawGuarantee) (pWin, pGC, GuaranteeVisBack); ++ *ppGC = pGC; ++ return pGC; ++} ++ ++static Bool ++rfbDCPutUpCursor (pScreen, pCursor, x, y, source, mask) ++ ScreenPtr pScreen; ++ CursorPtr pCursor; ++ int x, y; ++ unsigned long source, mask; ++{ ++ rfbDCScreenPtr pScreenPriv; ++ rfbDCCursorPtr pPriv; ++ WindowPtr pWin; ++ ++ pPriv = (rfbDCCursorPtr) pCursor->bits->devPriv[pScreen->myNum]; ++ if (!pPriv) ++ { ++ pPriv = rfbDCRealize(pScreen, pCursor); ++ if (!pPriv) ++ return FALSE; ++ } ++ pScreenPriv = (rfbDCScreenPtr) pScreen->devPrivates[rfbDCScreenIndex].ptr; ++ pWin = WindowTable[pScreen->myNum]; ++#ifdef ARGB_CURSOR ++ if (pPriv->pPicture) ++ { ++ if (!EnsurePicture(pScreenPriv->pRootPicture, &pWin->drawable, pWin)) ++ return FALSE; ++ CompositePicture (PictOpOver, ++ pPriv->pPicture, ++ NULL, ++ pScreenPriv->pRootPicture, ++ 0, 0, 0, 0, ++ x, y, ++ pCursor->bits->width, ++ pCursor->bits->height); ++ } ++ else ++#endif ++ { ++ if (!EnsureGC(pScreenPriv->pSourceGC, pWin)) ++ return FALSE; ++ if (!EnsureGC(pScreenPriv->pMaskGC, pWin)) ++ { ++ FreeGC (pScreenPriv->pSourceGC, (GContext) 0); ++ pScreenPriv->pSourceGC = 0; ++ return FALSE; ++ } ++ rfbDCPutBits ((DrawablePtr)pWin, pPriv, ++ pScreenPriv->pSourceGC, pScreenPriv->pMaskGC, ++ x, y, pCursor->bits->width, pCursor->bits->height, ++ source, mask); ++ } ++ return TRUE; ++} ++ ++static Bool ++rfbDCSaveUnderCursor (pScreen, x, y, w, h) ++ ScreenPtr pScreen; ++ int x, y, w, h; ++{ ++ rfbDCScreenPtr pScreenPriv; ++ PixmapPtr pSave; ++ WindowPtr pWin; ++ GCPtr pGC; ++ ++ pScreenPriv = (rfbDCScreenPtr) pScreen->devPrivates[rfbDCScreenIndex].ptr; ++ pSave = pScreenPriv->pSave; ++ pWin = WindowTable[pScreen->myNum]; ++ if (!pSave || pSave->drawable.width < w || pSave->drawable.height < h) ++ { ++ if (pSave) ++ (*pScreen->DestroyPixmap) (pSave); ++ pScreenPriv->pSave = pSave = ++ (*pScreen->CreatePixmap) (pScreen, w, h, pScreen->rootDepth); ++ if (!pSave) ++ return FALSE; ++ } ++ if (!EnsureGC(pScreenPriv->pSaveGC, pWin)) ++ return FALSE; ++ pGC = pScreenPriv->pSaveGC; ++ if (pSave->drawable.serialNumber != pGC->serialNumber) ++ ValidateGC ((DrawablePtr) pSave, pGC); ++ (*pGC->ops->CopyArea) ((DrawablePtr) pWin, (DrawablePtr) pSave, pGC, ++ x, y, w, h, 0, 0); ++ return TRUE; ++} ++ ++static Bool ++rfbDCRestoreUnderCursor (pScreen, x, y, w, h) ++ ScreenPtr pScreen; ++ int x, y, w, h; ++{ ++ rfbDCScreenPtr pScreenPriv; ++ PixmapPtr pSave; ++ WindowPtr pWin; ++ GCPtr pGC; ++ ++ pScreenPriv = (rfbDCScreenPtr) pScreen->devPrivates[rfbDCScreenIndex].ptr; ++ pSave = pScreenPriv->pSave; ++ pWin = WindowTable[pScreen->myNum]; ++ if (!pSave) ++ return FALSE; ++ if (!EnsureGC(pScreenPriv->pRestoreGC, pWin)) ++ return FALSE; ++ pGC = pScreenPriv->pRestoreGC; ++ if (pWin->drawable.serialNumber != pGC->serialNumber) ++ ValidateGC ((DrawablePtr) pWin, pGC); ++ (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC, ++ 0, 0, w, h, x, y); ++ return TRUE; ++} ++ ++static Bool ++rfbDCChangeSave (pScreen, x, y, w, h, dx, dy) ++ ScreenPtr pScreen; ++ int x, y, w, h, dx, dy; ++{ ++ rfbDCScreenPtr pScreenPriv; ++ PixmapPtr pSave; ++ WindowPtr pWin; ++ GCPtr pGC; ++ int sourcex, sourcey, destx, desty, copyw, copyh; ++ ++ pScreenPriv = (rfbDCScreenPtr) pScreen->devPrivates[rfbDCScreenIndex].ptr; ++ pSave = pScreenPriv->pSave; ++ pWin = WindowTable[pScreen->myNum]; ++ /* ++ * restore the bits which are about to get trashed ++ */ ++ if (!pSave) ++ return FALSE; ++ if (!EnsureGC(pScreenPriv->pRestoreGC, pWin)) ++ return FALSE; ++ pGC = pScreenPriv->pRestoreGC; ++ if (pWin->drawable.serialNumber != pGC->serialNumber) ++ ValidateGC ((DrawablePtr) pWin, pGC); ++ /* ++ * copy the old bits to the screen. ++ */ ++ if (dy > 0) ++ { ++ (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC, ++ 0, h - dy, w, dy, x + dx, y + h); ++ } ++ else if (dy < 0) ++ { ++ (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC, ++ 0, 0, w, -dy, x + dx, y + dy); ++ } ++ if (dy >= 0) ++ { ++ desty = y + dy; ++ sourcey = 0; ++ copyh = h - dy; ++ } ++ else ++ { ++ desty = y; ++ sourcey = - dy; ++ copyh = h + dy; ++ } ++ if (dx > 0) ++ { ++ (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC, ++ w - dx, sourcey, dx, copyh, x + w, desty); ++ } ++ else if (dx < 0) ++ { ++ (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC, ++ 0, sourcey, -dx, copyh, x + dx, desty); ++ } ++ if (!EnsureGC(pScreenPriv->pSaveGC, pWin)) ++ return FALSE; ++ pGC = pScreenPriv->pSaveGC; ++ if (pSave->drawable.serialNumber != pGC->serialNumber) ++ ValidateGC ((DrawablePtr) pSave, pGC); ++ /* ++ * move the bits that are still valid within the pixmap ++ */ ++ if (dx >= 0) ++ { ++ sourcex = 0; ++ destx = dx; ++ copyw = w - dx; ++ } ++ else ++ { ++ destx = 0; ++ sourcex = - dx; ++ copyw = w + dx; ++ } ++ if (dy >= 0) ++ { ++ sourcey = 0; ++ desty = dy; ++ copyh = h - dy; ++ } ++ else ++ { ++ desty = 0; ++ sourcey = -dy; ++ copyh = h + dy; ++ } ++ (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pSave, pGC, ++ sourcex, sourcey, copyw, copyh, destx, desty); ++ /* ++ * copy the new bits from the screen into the remaining areas of the ++ * pixmap ++ */ ++ if (dy > 0) ++ { ++ (*pGC->ops->CopyArea) ((DrawablePtr) pWin, (DrawablePtr) pSave, pGC, ++ x, y, w, dy, 0, 0); ++ } ++ else if (dy < 0) ++ { ++ (*pGC->ops->CopyArea) ((DrawablePtr) pWin, (DrawablePtr) pSave, pGC, ++ x, y + h + dy, w, -dy, 0, h + dy); ++ } ++ if (dy >= 0) ++ { ++ desty = dy; ++ sourcey = y + dy; ++ copyh = h - dy; ++ } ++ else ++ { ++ desty = 0; ++ sourcey = y; ++ copyh = h + dy; ++ } ++ if (dx > 0) ++ { ++ (*pGC->ops->CopyArea) ((DrawablePtr) pWin, (DrawablePtr) pSave, pGC, ++ x, sourcey, dx, copyh, 0, desty); ++ } ++ else if (dx < 0) ++ { ++ (*pGC->ops->CopyArea) ((DrawablePtr) pWin, (DrawablePtr) pSave, pGC, ++ x + w + dx, sourcey, -dx, copyh, w + dx, desty); ++ } ++ return TRUE; ++} ++ ++static Bool ++rfbDCMoveCursor (pScreen, pCursor, x, y, w, h, dx, dy, source, mask) ++ ScreenPtr pScreen; ++ CursorPtr pCursor; ++ int x, y, w, h, dx, dy; ++ unsigned long source, mask; ++{ ++ rfbDCCursorPtr pPriv; ++ rfbDCScreenPtr pScreenPriv; ++ int status; ++ WindowPtr pWin; ++ GCPtr pGC; ++ XID gcval = FALSE; ++ PixmapPtr pTemp; ++ ++ pPriv = (rfbDCCursorPtr) pCursor->bits->devPriv[pScreen->myNum]; ++ if (!pPriv) ++ { ++ pPriv = rfbDCRealize(pScreen, pCursor); ++ if (!pPriv) ++ return FALSE; ++ } ++ pScreenPriv = (rfbDCScreenPtr) pScreen->devPrivates[rfbDCScreenIndex].ptr; ++ pWin = WindowTable[pScreen->myNum]; ++ pTemp = pScreenPriv->pTemp; ++ if (!pTemp || ++ pTemp->drawable.width != pScreenPriv->pSave->drawable.width || ++ pTemp->drawable.height != pScreenPriv->pSave->drawable.height) ++ { ++ if (pTemp) ++ (*pScreen->DestroyPixmap) (pTemp); ++#ifdef ARGB_CURSOR ++ if (pScreenPriv->pTempPicture) ++ { ++ FreePicture (pScreenPriv->pTempPicture, 0); ++ pScreenPriv->pTempPicture = 0; ++ } ++#endif ++ pScreenPriv->pTemp = pTemp = (*pScreen->CreatePixmap) ++ (pScreen, w, h, pScreenPriv->pSave->drawable.depth); ++ if (!pTemp) ++ return FALSE; ++ } ++ if (!pScreenPriv->pMoveGC) ++ { ++ pScreenPriv->pMoveGC = CreateGC ((DrawablePtr)pTemp, ++ GCGraphicsExposures, &gcval, &status); ++ if (!pScreenPriv->pMoveGC) ++ return FALSE; ++ } ++ /* ++ * copy the saved area to a temporary pixmap ++ */ ++ pGC = pScreenPriv->pMoveGC; ++ if (pGC->serialNumber != pTemp->drawable.serialNumber) ++ ValidateGC ((DrawablePtr) pTemp, pGC); ++ (*pGC->ops->CopyArea)((DrawablePtr)pScreenPriv->pSave, ++ (DrawablePtr)pTemp, pGC, 0, 0, w, h, 0, 0); ++ ++ /* ++ * draw the cursor in the temporary pixmap ++ */ ++#ifdef ARGB_CURSOR ++ if (pPriv->pPicture) ++ { ++ if (!EnsurePicture(pScreenPriv->pTempPicture, &pTemp->drawable, pWin)) ++ return FALSE; ++ CompositePicture (PictOpOver, ++ pPriv->pPicture, ++ NULL, ++ pScreenPriv->pTempPicture, ++ 0, 0, 0, 0, ++ dx, dy, ++ pCursor->bits->width, ++ pCursor->bits->height); ++ } ++ else ++#endif ++ { ++ if (!pScreenPriv->pPixSourceGC) ++ { ++ pScreenPriv->pPixSourceGC = CreateGC ((DrawablePtr)pTemp, ++ GCGraphicsExposures, &gcval, &status); ++ if (!pScreenPriv->pPixSourceGC) ++ return FALSE; ++ } ++ if (!pScreenPriv->pPixMaskGC) ++ { ++ pScreenPriv->pPixMaskGC = CreateGC ((DrawablePtr)pTemp, ++ GCGraphicsExposures, &gcval, &status); ++ if (!pScreenPriv->pPixMaskGC) ++ return FALSE; ++ } ++ rfbDCPutBits ((DrawablePtr)pTemp, pPriv, ++ pScreenPriv->pPixSourceGC, pScreenPriv->pPixMaskGC, ++ dx, dy, pCursor->bits->width, pCursor->bits->height, ++ source, mask); ++ } ++ ++ /* ++ * copy the temporary pixmap onto the screen ++ */ ++ ++ if (!EnsureGC(pScreenPriv->pRestoreGC, pWin)) ++ return FALSE; ++ pGC = pScreenPriv->pRestoreGC; ++ if (pWin->drawable.serialNumber != pGC->serialNumber) ++ ValidateGC ((DrawablePtr) pWin, pGC); ++ ++ (*pGC->ops->CopyArea) ((DrawablePtr) pTemp, (DrawablePtr) pWin, ++ pGC, ++ 0, 0, w, h, x, y); ++ return TRUE; ++} +diff -pNur xorg-server-1.4.orig/hw/vnc/dpmsstubs.c xorg-server-1.4/hw/vnc/dpmsstubs.c +--- xorg-server-1.4.orig/hw/vnc/dpmsstubs.c 1969-12-31 16:00:00.000000000 -0800 ++++ xorg-server-1.4/hw/vnc/dpmsstubs.c 2007-09-06 16:09:45.000000000 -0700 +@@ -0,0 +1,52 @@ ++/* $Xorg: dpmsstubs.c,v 1.3 2000/08/17 19:47:56 cpqbld Exp $ */ ++/***************************************************************** ++ ++Copyright (c) 1996 Digital Equipment Corporation, Maynard, Massachusetts. ++ ++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. ++ ++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 ++DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING, ++BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL 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 Digital Equipment Corporation ++shall not be used in advertising or otherwise to promote the sale, use or other ++dealings in this Software without prior written authorization from Digital ++Equipment Corporation. ++ ++******************************************************************/ ++/* $XFree86: xc/programs/Xserver/Xext/dpmsstubs.c,v 3.3 1999/12/16 02:26:23 robin Exp $ */ ++ ++#ifdef HAVE_DIX_CONFIG_H ++#include ++#endif ++ ++#include "rfb.h" ++ ++#define FALSE 0 ++ ++Bool DPMSSupported(void) ++{ ++ return FALSE; ++} ++ ++int DPSMGet(int *level) ++{ ++ return -1; ++} ++ ++void DPMSSet(int level) ++{ ++ ++} +diff -pNur xorg-server-1.4.orig/hw/vnc/draw.c xorg-server-1.4/hw/vnc/draw.c +--- xorg-server-1.4.orig/hw/vnc/draw.c 1969-12-31 16:00:00.000000000 -0800 ++++ xorg-server-1.4/hw/vnc/draw.c 2007-09-06 16:09:45.000000000 -0700 +@@ -0,0 +1,2020 @@ ++/* ++ * draw.c - drawing routines for the RFB X server. This is a set of ++ * wrappers around the standard MI/MFB/CFB drawing routines which work out ++ * to a fair approximation the region of the screen being modified by the ++ * drawing. If the RFB client is ready then the modified region of the screen ++ * is sent to the client, otherwise the modified region will simply grow with ++ * each drawing request until the client is ready. ++ * ++ * Modified for XFree86 4.x by Alan Hourihane ++ */ ++ ++/* ++ * 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) 1989 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. ++*/ ++#ifdef HAVE_DIX_CONFIG_H ++#include ++#endif ++ ++#include "rfb.h" ++ ++int rfbDeferUpdateTime = 40; /* ms */ ++ ++ ++/****************************************************************************/ ++/* ++ * Macro definitions ++ */ ++/****************************************************************************/ ++ ++#define TRC(x) /* (rfbLog x) */ ++ ++/* ADD_TO_MODIFIED_REGION adds the given region to the modified region for each ++ client */ ++ ++#define ADD_TO_MODIFIED_REGION(pScreen,reg) \ ++ { \ ++ rfbClientPtr cl; \ ++ for (cl = rfbClientHead; cl; cl = cl->next) { \ ++ REGION_UNION((pScreen),&cl->modifiedRegion,&cl->modifiedRegion,reg);\ ++ } \ ++ } ++ ++/* SCHEDULE_FB_UPDATE is used at the end of each drawing routine to schedule an ++ update to be sent to each client if there is one pending and the client is ++ ready for it. */ ++ ++#define SCHEDULE_FB_UPDATE(pScreen,pVNC) \ ++ if (!pVNC->dontSendFramebufferUpdate) { \ ++ rfbClientPtr cl, nextCl; \ ++ for (cl = rfbClientHead; cl; cl = nextCl) { \ ++ nextCl = cl->next; \ ++ if (!cl->deferredUpdateScheduled && FB_UPDATE_PENDING(cl) && \ ++ REGION_NOTEMPTY(pScreen,&cl->requestedRegion)) \ ++ { \ ++ rfbScheduleDeferredUpdate(pScreen, cl); \ ++ } \ ++ } \ ++ } ++ ++/* function prototypes */ ++ ++static void rfbScheduleDeferredUpdate(ScreenPtr pScreen, rfbClientPtr cl); ++static void rfbCopyRegion(ScreenPtr pScreen, rfbClientPtr cl, ++ RegionPtr src, RegionPtr dst, int dx, int dy); ++#ifdef DEBUG ++static void PrintRegion(ScreenPtr pScreen, RegionPtr reg); ++#endif ++ ++/* GC funcs */ ++ ++static void rfbValidateGC(GCPtr, unsigned long /*changes*/, DrawablePtr); ++static void rfbChangeGC(GCPtr, unsigned long /*mask*/); ++static void rfbCopyGC(GCPtr /*src*/, unsigned long /*mask*/, GCPtr /*dst*/); ++static void rfbDestroyGC(GCPtr); ++static void rfbChangeClip(GCPtr, int /*type*/, pointer /*pValue*/, ++ int /*nrects*/); ++static void rfbDestroyClip(GCPtr); ++static void rfbCopyClip(GCPtr /*dst*/, GCPtr /*src*/); ++ ++/* GC ops */ ++ ++static void rfbFillSpans(DrawablePtr pDrawable, GCPtr pGC, int nInit, DDXPointPtr pptInit, int *pwidthInit, int fSorted); ++static void rfbSetSpans(DrawablePtr pDrawable, ++ GCPtr pGC, ++ char *psrc, ++ register DDXPointPtr ppt, ++ int *pwidth, ++ int nspans, ++ int fSorted); ++static void rfbPutImage(DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y, int w, int h, int leftPad, int format, char *pBits); ++static RegionPtr rfbCopyArea (DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, int srcx, int srcy, int w, int h, int dstx, int dsty); ++static RegionPtr rfbCopyPlane (DrawablePtr pSrc, DrawablePtr pDst, register GCPtr pGC, int srcx, int srcy, int w, int h, int dstx, int dsty, unsigned long plane); ++static void rfbPolyPoint (DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, xPoint *pts); ++static void rfbPolylines (DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, DDXPointPtr ppts); ++static void rfbPolySegment(DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment *segs); ++static void rfbPolyRectangle(DrawablePtr pDrawable, GCPtr pGC, int nrects, xRectangle *rects); ++static void rfbPolyArc(DrawablePtr pDrawable, register GCPtr pGC, int narcs, xArc *arcs); ++static void rfbFillPolygon(register DrawablePtr pDrawable, register GCPtr pGC, int shape, int mode, int count, DDXPointPtr pts); ++static void rfbPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrects, xRectangle *rects); ++static void rfbPolyFillArc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc *arcs); ++static int rfbPolyText8(DrawablePtr pDrawable, GCPtr pGC, int x, int y, int count, char *chars); ++static int rfbPolyText16(DrawablePtr pDrawable, GCPtr pGC, int x, int y, int count, unsigned short *chars); ++static void rfbImageText8(DrawablePtr pDrawable, GCPtr pGC, int x, int y, int count, char *chars); ++static void rfbImageText16(DrawablePtr pDrawable, GCPtr pGC, int x, int y, int count, unsigned short *chars); ++static void rfbImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x, int y, unsigned int nglyph, CharInfoPtr *ppci, pointer pglyphBase); ++static void rfbPolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x, int y, unsigned int nglyph, CharInfoPtr *ppci, pointer pglyphBase); ++static void rfbPushPixels(GCPtr pGC, PixmapPtr pBitMap, DrawablePtr pDrawable, int w, int h, int x, int y); ++ ++ ++static GCFuncs rfbGCFuncs = { ++ rfbValidateGC, ++ rfbChangeGC, ++ rfbCopyGC, ++ rfbDestroyGC, ++ rfbChangeClip, ++ rfbDestroyClip, ++ rfbCopyClip, ++}; ++ ++ ++static GCOps rfbGCOps = { ++ rfbFillSpans, rfbSetSpans, rfbPutImage, ++ rfbCopyArea, rfbCopyPlane, rfbPolyPoint, ++ rfbPolylines, rfbPolySegment, rfbPolyRectangle, ++ rfbPolyArc, rfbFillPolygon, rfbPolyFillRect, ++ rfbPolyFillArc, rfbPolyText8, rfbPolyText16, ++ rfbImageText8, rfbImageText16, rfbImageGlyphBlt, ++ rfbPolyGlyphBlt, rfbPushPixels ++}; ++ ++ ++ ++/****************************************************************************/ ++/* ++ * Screen functions wrapper stuff ++ */ ++/****************************************************************************/ ++ ++#define SCREEN_PROLOGUE(scrn, field) \ ++ ScreenPtr pScreen = scrn; \ ++ VNCSCREENPTR(pScreen); \ ++ pScreen->field = pVNC->field; ++ ++#define SCREEN_EPILOGUE(field, wrapper) \ ++ pScreen->field = wrapper; ++ ++ ++/* ++ * CloseScreen wrapper -- unwrap everything, free the private data ++ * and call the wrapped CloseScreen function. ++ */ ++ ++Bool ++rfbCloseScreen (int i, ScreenPtr pScreen) ++{ ++ VNCSCREENPTR(pScreen); ++#if XFREE86VNC ++ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; ++#endif ++ int sock; ++ ++ for (sock = 0; sock <= pVNC->maxFd; sock++) { ++ if (FD_ISSET(sock, &pVNC->allFds)) ++ if (sock != pVNC->rfbListenSock && sock != pVNC->httpListenSock) { ++ rfbCloseSock(pScreen, sock); ++ } ++ } ++ ++ if (pVNC->rfbListenSock > 0) ++ if (close(pVNC->rfbListenSock)) ++ ErrorF("Close of port %d failed\n",pVNC->rfbPort); ++ ++ if (pVNC->httpListenSock > 0) ++ if (close(pVNC->httpListenSock)) ++ ErrorF("Close of port %d failed\n",pVNC->httpPort); ++ ++ pScreen->CloseScreen = pVNC->CloseScreen; ++ pScreen->CreateGC = pVNC->CreateGC; ++ pScreen->PaintWindowBackground = pVNC->PaintWindowBackground; ++ pScreen->PaintWindowBorder = pVNC->PaintWindowBorder; ++ pScreen->CopyWindow = pVNC->CopyWindow; ++ pScreen->ClearToBackground = pVNC->ClearToBackground; ++ pScreen->RestoreAreas = pVNC->RestoreAreas; ++ pScreen->WakeupHandler = pVNC->WakeupHandler; ++ ++#if XFREE86VNC ++ pScreen->InstallColormap = pVNC->InstallColormap; ++ pScreen->UninstallColormap = pVNC->UninstallColormap; ++ pScreen->ListInstalledColormaps = pVNC->ListInstalledColormaps; ++ pScreen->StoreColors = pVNC->StoreColors; ++ pScrn->EnableDisableFBAccess = pVNC->EnableDisableFBAccess; ++ ++ xfree(pVNC); ++#endif ++ ++ TRC((stderr,"Unwrapped screen functions\n")); ++ ++ return (*pScreen->CloseScreen) (i, pScreen); ++} ++ ++#if XFREE86VNC ++void ++rfbEnableDisableFBAccess (int index, Bool enable) ++{ ++ ScrnInfoPtr pScrn = xf86Screens[index]; ++ VNCSCREENPTR(pScrn->pScreen); ++ ++ /* ++ * Blank the screen for security while inputs are disabled. ++ * When VT switching is fixed, we might be able to allow ++ * control even when switched away. ++ */ ++ if (!enable) { ++ WindowPtr pWin = WindowTable[index]; ++ ScreenPtr pScreen = pWin->drawable.pScreen; ++ GCPtr pGC; ++ xRectangle rect; ++ ++ rect.x = 0; ++ rect.y = 0; ++ rect.width = pScrn->virtualX; ++ rect.height = pScrn->virtualY; ++ ++ if (!(pGC = GetScratchGC(pScreen->rootDepth, pScreen))) { ++ ErrorF("Couldn't blank screen"); ++ } else { ++ CARD32 attributes[2]; ++ attributes[0] = pScreen->whitePixel; ++ attributes[1] = pScreen->blackPixel; ++ (void)ChangeGC(pGC, GCForeground | GCBackground, attributes); ++ ++ ValidateGC((DrawablePtr)pWin, pGC); ++ ++ (*pGC->ops->PolyFillRect)((DrawablePtr)pWin, pGC, 1, &rect); ++ ++ FreeScratchGC(pGC); ++ ++ /* Flush pending packets */ ++ rfbCheckFds(pScreen); ++ httpCheckFds(pScreen); ++ } ++ } ++ ++ pScrn->EnableDisableFBAccess = pVNC->EnableDisableFBAccess; ++ (*pScrn->EnableDisableFBAccess)(index, enable); ++ pScrn->EnableDisableFBAccess = rfbEnableDisableFBAccess; ++} ++#endif ++ ++/* ++ * CreateGC - wrap the GC funcs (the GC ops will be wrapped when the GC ++ * func "ValidateGC" is called). ++ */ ++ ++Bool ++rfbCreateGC (GCPtr pGC) ++{ ++ Bool ret; ++ rfbGCPtr pGCPriv; ++ ++ SCREEN_PROLOGUE(pGC->pScreen,CreateGC); ++ ++ pGCPriv = (rfbGCPtr)pGC->devPrivates[rfbGCIndex].ptr; ++ ++ ret = (*pScreen->CreateGC) (pGC); ++ ++ TRC((stderr,"rfbCreateGC called\n")); ++ ++ pGCPriv->wrapOps = NULL; ++ pGCPriv->wrapFuncs = pGC->funcs; ++ pGC->funcs = &rfbGCFuncs; ++ ++ SCREEN_EPILOGUE(CreateGC,rfbCreateGC); ++ ++ return ret; ++} ++ ++/* ++ * PaintWindowBackground - the region being modified is just the given region. ++ */ ++ ++void ++rfbPaintWindowBackground (WindowPtr pWin, RegionPtr pRegion, int what) ++{ ++ SCREEN_PROLOGUE(pWin->drawable.pScreen,PaintWindowBackground); ++ ++ TRC((stderr,"rfbPaintWindowBackground called\n")); ++ ++ ADD_TO_MODIFIED_REGION(pScreen,pRegion); ++ ++ (*pScreen->PaintWindowBackground) (pWin, pRegion, what); ++ ++ SCHEDULE_FB_UPDATE(pScreen, pVNC); ++ ++ SCREEN_EPILOGUE(PaintWindowBackground,rfbPaintWindowBackground); ++} ++ ++/* ++ * PaintWindowBorder - the region being modified is just the given region. ++ */ ++ ++void ++rfbPaintWindowBorder (WindowPtr pWin, RegionPtr pRegion, int what) ++{ ++ SCREEN_PROLOGUE(pWin->drawable.pScreen,PaintWindowBorder); ++ ++ TRC((stderr,"rfbPaintWindowBorder called\n")); ++ ++ ADD_TO_MODIFIED_REGION(pScreen,pRegion); ++ ++ (*pScreen->PaintWindowBorder) (pWin, pRegion, what); ++ ++ SCHEDULE_FB_UPDATE(pScreen, pVNC); ++ ++ SCREEN_EPILOGUE(PaintWindowBorder,rfbPaintWindowBorder); ++} ++ ++#ifdef CHROMIUM ++Bool ++rfbRealizeWindow(WindowPtr pWin) ++{ ++ CRWindowTable *wt = NULL, *nextWt = NULL; ++ Bool ret; ++ SCREEN_PROLOGUE(pWin->drawable.pScreen,RealizeWindow); ++ ++ for (wt = windowTable; wt; wt = nextWt) { ++ nextWt = wt->next; ++ if (wt->XwinId == pWin->drawable.id) { ++ rfbSendChromiumWindowShow(wt->CRwinId, 1); ++ } ++ } ++ ++ ret = (*pScreen->RealizeWindow)(pWin); ++ ++ SCREEN_EPILOGUE(RealizeWindow,rfbRealizeWindow); ++ ++ return ret; ++} ++ ++Bool ++rfbUnrealizeWindow(WindowPtr pWin) ++{ ++ CRWindowTable *wt = NULL, *nextWt = NULL; ++ Bool ret; ++ SCREEN_PROLOGUE(pWin->drawable.pScreen,UnrealizeWindow); ++ ++ for (wt = windowTable; wt; wt = nextWt) { ++ nextWt = wt->next; ++ if (wt->XwinId == pWin->drawable.id) { ++ rfbSendChromiumWindowShow(wt->CRwinId, 0); ++ } ++ } ++ ++ ret = (*pScreen->UnrealizeWindow)(pWin); ++ ++ SCREEN_EPILOGUE(UnrealizeWindow,rfbUnrealizeWindow); ++ ++ return ret; ++} ++ ++Bool ++rfbDestroyWindow(WindowPtr pWin) ++{ ++ CRWindowTable *wt = NULL, *nextWt = NULL, *prevWt = NULL; ++ Bool ret; ++ SCREEN_PROLOGUE(pWin->drawable.pScreen,DestroyWindow); ++ ++ /* loop over monitored windows */ ++ for (wt = windowTable; wt; wt = nextWt) { ++ nextWt = wt->next; ++ if (wt->XwinId == pWin->drawable.id) { ++ rfbSendChromiumWindowDestroy(wt->CRwinId); ++ /* also remove from list */ ++ if (prevWt) ++ prevWt->next = wt->next; ++ else ++ windowTable = wt->next; ++ xfree(wt); ++ } ++ else { ++ prevWt = wt; ++ } ++ } ++ ++ ret = (*pScreen->DestroyWindow)(pWin); ++ ++ SCREEN_EPILOGUE(DestroyWindow,rfbDestroyWindow); ++ ++ return ret; ++} ++ ++void ++rfbResizeWindow(WindowPtr pWin, int x, int y, unsigned int w, unsigned int h, WindowPtr pSib) ++{ ++ CRWindowTable *wt = NULL, *nextWt = NULL; ++ SCREEN_PROLOGUE(pWin->drawable.pScreen,ResizeWindow); ++ ++ for (wt = windowTable; wt; wt = nextWt) { ++ nextWt = wt->next; ++ if (wt->XwinId == pWin->drawable.id) { ++ rfbSendChromiumMoveResizeWindow(wt->CRwinId, pWin->drawable.x, pWin->drawable.y, w, h); ++ } ++ } ++ ++ (*pScreen->ResizeWindow)(pWin, x, y, w, h, pSib); ++ ++ SCREEN_EPILOGUE(ResizeWindow,rfbResizeWindow); ++} ++ ++Bool ++rfbPositionWindow(WindowPtr pWin, int x, int y) ++{ ++ Bool ret; ++ CRWindowTable *wt, *nextWt; ++ SCREEN_PROLOGUE(pWin->drawable.pScreen,PositionWindow); ++ ++ for (wt = windowTable; wt; wt = nextWt) { ++ nextWt = wt->next; ++ if (wt->XwinId == pWin->drawable.id) { ++ rfbSendChromiumMoveResizeWindow(wt->CRwinId, x, y, pWin->drawable.width, pWin->drawable.height); ++ } ++ } ++ ++ ret = (*pScreen->PositionWindow)(pWin, x, y); ++ ++ SCREEN_EPILOGUE(PositionWindow,rfbPositionWindow); ++ ++ return ret; ++} ++ ++void ++rfbClipNotify(WindowPtr pWin, int x, int y) ++{ ++ CRWindowTable *wt, *nextWt; ++ SCREEN_PROLOGUE(pWin->drawable.pScreen,ClipNotify); ++ ++ for (wt = windowTable; wt; wt = nextWt) { ++ nextWt = wt->next; ++ if (wt->XwinId == pWin->drawable.id) { ++ int numClipRects = REGION_NUM_RECTS(&pWin->clipList); ++ BoxPtr pClipRects = REGION_RECTS(&pWin->clipList); ++ ++ /* Possible optimization - has the cliplist really? changed */ ++ ++ rfbSendChromiumClipList(wt->CRwinId, pClipRects, numClipRects); ++ } ++ } ++ ++ if (*pScreen->ClipNotify) ++ (*pScreen->ClipNotify)(pWin, x, y); ++ ++ SCREEN_EPILOGUE(ClipNotify,rfbClipNotify); ++} ++#endif /* CHROMIUM */ ++ ++/* ++ * CopyWindow - the region being modified is the translation of the old ++ * region, clipped to the border clip region of the window. Note that any ++ * parts of the window which have become newly-visible will not be affected by ++ * this call - a separate PaintWindowBackground/Border will be called to do ++ * that. If the client will accept CopyRect messages then use rfbCopyRegion to ++ * optimise the pending screen changes into a single "copy region" plus the ++ * ordinary modified region. ++ */ ++ ++void ++rfbCopyWindow (WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr pOldRegion) ++{ ++ rfbClientPtr cl; ++ RegionRec srcRegion, dstRegion; ++ SCREEN_PROLOGUE(pWin->drawable.pScreen,CopyWindow); ++ ++ TRC((stderr,"rfbCopyWindow called\n")); ++ ++ REGION_NULL(pScreen,&dstRegion); ++ REGION_COPY(pScreen,&dstRegion,pOldRegion); ++ REGION_TRANSLATE(pWin->drawable.pScreen, &dstRegion, ++ pWin->drawable.x - ptOldOrg.x, ++ pWin->drawable.y - ptOldOrg.y); ++ REGION_INTERSECT(pWin->drawable.pScreen, &dstRegion, &dstRegion, ++ &pWin->borderClip); ++ ++ for (cl = rfbClientHead; cl; cl = cl->next) { ++ if (cl->useCopyRect) { ++ REGION_NULL(pScreen,&srcRegion); ++ REGION_COPY(pScreen,&srcRegion,pOldRegion); ++ ++ rfbCopyRegion(pScreen, cl, &srcRegion, &dstRegion, ++ pWin->drawable.x - ptOldOrg.x, ++ pWin->drawable.y - ptOldOrg.y); ++ ++ REGION_UNINIT(pScreen, &srcRegion); ++ ++ } else { ++ ++ REGION_UNION(pScreen, &cl->modifiedRegion, &cl->modifiedRegion, ++ &dstRegion); ++ } ++ } ++ ++ REGION_UNINIT(pScreen, &dstRegion); ++ ++ (*pScreen->CopyWindow) (pWin, ptOldOrg, pOldRegion); ++ ++ SCHEDULE_FB_UPDATE(pScreen, pVNC); ++ ++ SCREEN_EPILOGUE(CopyWindow,rfbCopyWindow); ++} ++ ++/* ++ * ClearToBackground - when generateExposures is false, the region being ++ * modified is the given rectangle (clipped to the "window clip region"). ++ */ ++ ++void ++rfbClearToBackground (WindowPtr pWin, int x, int y, int w, int h, ++ Bool generateExposures) ++{ ++ RegionRec tmpRegion; ++ BoxRec box; ++ SCREEN_PROLOGUE(pWin->drawable.pScreen,ClearToBackground); ++ ++ TRC((stderr,"rfbClearToBackground called\n")); ++ ++ if (!generateExposures) { ++ 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); ++ ++ SAFE_REGION_INIT(pScreen, &tmpRegion, &box, 0); ++ ++ REGION_INTERSECT(pScreen, &tmpRegion, &tmpRegion, &pWin->clipList); ++ ++ ADD_TO_MODIFIED_REGION(pScreen, &tmpRegion); ++ ++ REGION_UNINIT(pScreen, &tmpRegion); ++ } ++ ++ (*pScreen->ClearToBackground) (pWin, x, y, w, h, generateExposures); ++ ++ if (!generateExposures) { ++ SCHEDULE_FB_UPDATE(pScreen, pVNC); ++ } ++ ++ SCREEN_EPILOGUE(ClearToBackground,rfbClearToBackground); ++} ++ ++/* ++ * RestoreAreas - just be safe here - the region being modified is the whole ++ * exposed region. ++ */ ++ ++RegionPtr ++rfbRestoreAreas (WindowPtr pWin, RegionPtr prgnExposed) ++{ ++ RegionPtr result; ++ SCREEN_PROLOGUE(pWin->drawable.pScreen,RestoreAreas); ++ ++ TRC((stderr,"rfbRestoreAreas called\n")); ++ ++ ADD_TO_MODIFIED_REGION(pScreen, prgnExposed); ++ ++ result = (*pScreen->RestoreAreas) (pWin, prgnExposed); ++ ++ SCHEDULE_FB_UPDATE(pScreen, pVNC); ++ ++ SCREEN_EPILOGUE(RestoreAreas,rfbRestoreAreas); ++ ++ return result; ++} ++ ++ ++ ++/****************************************************************************/ ++/* ++ * GC funcs wrapper stuff ++ * ++ * We only really want to wrap the GC ops, but to do this we need to wrap ++ * ValidateGC and so all the other GC funcs must be wrapped as well. ++ */ ++/****************************************************************************/ ++ ++#define GC_FUNC_PROLOGUE(pGC) \ ++ rfbGCPtr pGCPriv = (rfbGCPtr) (pGC)->devPrivates[rfbGCIndex].ptr; \ ++ (pGC)->funcs = pGCPriv->wrapFuncs; \ ++ if (pGCPriv->wrapOps) \ ++ (pGC)->ops = pGCPriv->wrapOps; ++ ++#define GC_FUNC_EPILOGUE(pGC) \ ++ pGCPriv->wrapFuncs = (pGC)->funcs; \ ++ (pGC)->funcs = &rfbGCFuncs; \ ++ if (pGCPriv->wrapOps) { \ ++ pGCPriv->wrapOps = (pGC)->ops; \ ++ (pGC)->ops = &rfbGCOps; \ ++ } ++ ++ ++/* ++ * ValidateGC - call the wrapped ValidateGC, then wrap the resulting GC ops if ++ * the drawing will be to a viewable window. ++ */ ++ ++static void ++rfbValidateGC (GCPtr pGC, unsigned long changes, DrawablePtr pDrawable) ++{ ++ GC_FUNC_PROLOGUE(pGC); ++ ++ TRC((stderr,"rfbValidateGC called\n")); ++ ++ (*pGC->funcs->ValidateGC) (pGC, changes, pDrawable); ++ ++ pGCPriv->wrapOps = NULL; ++ 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)) { ++ pGCPriv->wrapOps = pGC->ops; ++ TRC((stderr,"rfbValidateGC: wrapped GC ops\n")); ++ } ++ } ++ ++ GC_FUNC_EPILOGUE(pGC); ++} ++ ++/* ++ * All other GC funcs simply unwrap the GC funcs and ops, call the wrapped ++ * function and then rewrap the funcs and ops. ++ */ ++ ++static void ++rfbChangeGC (pGC, mask) ++ GCPtr pGC; ++ unsigned long mask; ++{ ++ GC_FUNC_PROLOGUE(pGC); ++ (*pGC->funcs->ChangeGC) (pGC, mask); ++ GC_FUNC_EPILOGUE(pGC); ++} ++ ++static void ++rfbCopyGC (pGCSrc, mask, pGCDst) ++ GCPtr pGCSrc, pGCDst; ++ unsigned long mask; ++{ ++ GC_FUNC_PROLOGUE(pGCDst); ++ (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst); ++ GC_FUNC_EPILOGUE(pGCDst); ++} ++ ++static void ++rfbDestroyGC (pGC) ++ GCPtr pGC; ++{ ++ GC_FUNC_PROLOGUE(pGC); ++ (*pGC->funcs->DestroyGC) (pGC); ++ GC_FUNC_EPILOGUE(pGC); ++} ++ ++static void ++rfbChangeClip (pGC, type, pvalue, nrects) ++ GCPtr pGC; ++ int type; ++ pointer pvalue; ++ int nrects; ++{ ++ GC_FUNC_PROLOGUE(pGC); ++ (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects); ++ GC_FUNC_EPILOGUE(pGC); ++} ++ ++static void ++rfbDestroyClip(pGC) ++ GCPtr pGC; ++{ ++ GC_FUNC_PROLOGUE(pGC); ++ (* pGC->funcs->DestroyClip)(pGC); ++ GC_FUNC_EPILOGUE(pGC); ++} ++ ++static void ++rfbCopyClip(pgcDst, pgcSrc) ++ GCPtr pgcDst, pgcSrc; ++{ ++ GC_FUNC_PROLOGUE(pgcDst); ++ (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc); ++ GC_FUNC_EPILOGUE(pgcDst); ++} ++ ++ ++/****************************************************************************/ ++/* ++ * GC ops wrapper stuff ++ * ++ * Note that these routines will only have been wrapped for drawing to ++ * viewable windows so we don't need to check each time that the drawable ++ * is a viewable window. ++ */ ++/****************************************************************************/ ++ ++#define GC_OP_PROLOGUE(pDrawable,pGC) \ ++ ScreenPtr pScreen = pGC->pScreen; \ ++ VNCSCREENPTR(pScreen); \ ++ rfbGCPtr pGCPrivate = (rfbGCPtr) (pGC)->devPrivates[rfbGCIndex].ptr; \ ++ GCFuncs *oldFuncs = pGC->funcs; \ ++ (void) pScreen; /* silence compiler */ \ ++ (pGC)->funcs = pGCPrivate->wrapFuncs; \ ++ (pGC)->ops = pGCPrivate->wrapOps; ++ ++#define GC_OP_EPILOGUE(pGC) \ ++ pGCPrivate->wrapOps = (pGC)->ops; \ ++ (pGC)->funcs = oldFuncs; \ ++ (pGC)->ops = &rfbGCOps; ++ ++ ++/* ++ * FillSpans - being very safe - the region being modified is the border clip ++ * region of the window. ++ */ ++ ++static void ++rfbFillSpans(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted) ++ DrawablePtr pDrawable; ++ GCPtr pGC; ++ int nInit; /* number of spans to fill */ ++ DDXPointPtr pptInit; /* pointer to list of start points */ ++ int *pwidthInit; /* pointer to list of n widths */ ++ int fSorted; ++{ ++ GC_OP_PROLOGUE(pDrawable,pGC); ++ ++ TRC((stderr,"rfbFillSpans called\n")); ++ ++ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, ++ &((WindowPtr)pDrawable)->borderClip); ++ ++ (*pGC->ops->FillSpans) (pDrawable, pGC, nInit, pptInit,pwidthInit,fSorted); ++ ++ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); ++ ++ GC_OP_EPILOGUE(pGC); ++} ++ ++/* ++ * SetSpans - being very safe - the region being modified is the border clip ++ * region of the window. ++ */ ++ ++static void ++rfbSetSpans(DrawablePtr pDrawable, ++ GCPtr pGC, ++ char *psrc, ++ register DDXPointPtr ppt, ++ int *pwidth, ++ int nspans, ++ int fSorted) ++{ ++ GC_OP_PROLOGUE(pDrawable,pGC); ++ ++ TRC((stderr,"rfbSetSpans called\n")); ++ ++ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, ++ &((WindowPtr)pDrawable)->borderClip); ++ ++ (*pGC->ops->SetSpans) (pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted); ++ ++ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); ++ ++ GC_OP_EPILOGUE(pGC); ++} ++ ++/* ++ * PutImage - the region being modified is the rectangle of the ++ * PutImage (clipped to the window clip region). ++ */ ++ ++static void ++rfbPutImage(DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y, int w, int h, int leftPad, int format, char *pBits) ++{ ++ RegionRec tmpRegion; ++ BoxRec box; ++ GC_OP_PROLOGUE(pDrawable, pGC); ++ ++ TRC((stderr,"rfbPutImage called\n")); ++ ++ box.x1 = x + pDrawable->x; ++ box.y1 = y + pDrawable->y; ++ box.x2 = box.x1 + w; ++ box.y2 = box.y1 + h; ++ ++ SAFE_REGION_INIT(pDrawable->pScreen, &tmpRegion, &box, 0); ++ ++ REGION_INTERSECT(pDrawable->pScreen, &tmpRegion, &tmpRegion, ++ pGC->pCompositeClip); ++ ++ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, &tmpRegion); ++ ++ REGION_UNINIT(pDrawable->pScreen, &tmpRegion); ++ ++ (*pGC->ops->PutImage) (pDrawable, pGC, depth, x, y, w, h, ++ leftPad, format, pBits); ++ ++ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); ++ ++ GC_OP_EPILOGUE(pGC); ++} ++ ++/* ++ * CopyArea - the region being modified is the destination rectangle (clipped ++ * to the window clip region). ++ * If the client will accept CopyRect messages then use rfbCopyRegion ++ * to optimise the pending screen changes into a single "copy region" plus ++ * the ordinary modified region. ++ */ ++ ++static RegionPtr ++rfbCopyArea (DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, int srcx, int srcy, int w, int h, int dstx, int dsty) ++{ ++ rfbClientPtr cl; ++ RegionPtr rgn; ++ RegionRec srcRegion, dstRegion; ++ BoxRec box; ++ GC_OP_PROLOGUE(pDst, pGC); ++ ++ TRC((stderr,"rfbCopyArea called\n")); ++ ++ box.x1 = dstx + pDst->x; ++ box.y1 = dsty + pDst->y; ++ box.x2 = box.x1 + w; ++ box.y2 = box.y1 + h; ++ ++ SAFE_REGION_INIT(pDst->pScreen, &dstRegion, &box, 0); ++ REGION_INTERSECT(pDst->pScreen, &dstRegion, &dstRegion, ++ pGC->pCompositeClip); ++ ++ if ((pSrc->type == DRAWABLE_WINDOW) && (pSrc->pScreen == pDst->pScreen)) { ++ box.x1 = srcx + pSrc->x; ++ box.y1 = srcy + pSrc->y; ++ box.x2 = box.x1 + w; ++ box.y2 = box.y1 + h; ++ ++ for (cl = rfbClientHead; cl; cl = cl->next) { ++ if (cl->useCopyRect) { ++ SAFE_REGION_INIT(pSrc->pScreen, &srcRegion, &box, 0); ++ REGION_INTERSECT(pSrc->pScreen, &srcRegion, &srcRegion, ++ &((WindowPtr)pSrc)->clipList); ++ ++ rfbCopyRegion(pSrc->pScreen, cl, &srcRegion, &dstRegion, ++ dstx + pDst->x - srcx - pSrc->x, ++ dsty + pDst->y - srcy - pSrc->y); ++ ++ REGION_UNINIT(pSrc->pScreen, &srcRegion); ++ ++ } else { ++ ++ REGION_UNION(pScreen, &cl->modifiedRegion, &cl->modifiedRegion, ++ &dstRegion); ++ } ++ } ++ ++ } else { ++ ++ ADD_TO_MODIFIED_REGION(pDst->pScreen, &dstRegion); ++ } ++ ++ REGION_UNINIT(pDst->pScreen, &dstRegion); ++ ++ rgn = (*pGC->ops->CopyArea) (pSrc, pDst, pGC, srcx, srcy, w, h, ++ dstx, dsty); ++ ++ SCHEDULE_FB_UPDATE(pDst->pScreen, pVNC); ++ ++ GC_OP_EPILOGUE(pGC); ++ ++ return rgn; ++} ++ ++ ++/* ++ * CopyPlane - the region being modified is the destination rectangle (clipped ++ * to the window clip region). ++ */ ++ ++static RegionPtr ++rfbCopyPlane (DrawablePtr pSrc, DrawablePtr pDst, register GCPtr pGC, int srcx, int srcy, int w, int h, int dstx, int dsty, unsigned long plane) ++{ ++ RegionPtr rgn; ++ RegionRec tmpRegion; ++ BoxRec box; ++ GC_OP_PROLOGUE(pDst, pGC); ++ ++ TRC((stderr,"rfbCopyPlane called\n")); ++ ++ box.x1 = dstx + pDst->x; ++ box.y1 = dsty + pDst->y; ++ box.x2 = box.x1 + w; ++ box.y2 = box.y1 + h; ++ ++ SAFE_REGION_INIT(pDst->pScreen, &tmpRegion, &box, 0); ++ ++ REGION_INTERSECT(pDst->pScreen, &tmpRegion, &tmpRegion, ++ pGC->pCompositeClip); ++ ++ ADD_TO_MODIFIED_REGION(pDst->pScreen, &tmpRegion); ++ ++ REGION_UNINIT(pDst->pScreen, &tmpRegion); ++ ++ rgn = (*pGC->ops->CopyPlane) (pSrc, pDst, pGC, srcx, srcy, w, h, ++ dstx, dsty, plane); ++ ++ SCHEDULE_FB_UPDATE(pDst->pScreen, pVNC); ++ ++ GC_OP_EPILOGUE(pGC); ++ ++ return rgn; ++} ++ ++/* ++ * PolyPoint - find the smallest rectangle which encloses the points drawn ++ * (and clip). ++ */ ++ ++static void ++rfbPolyPoint (DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, xPoint *pts) ++{ ++ int i; ++ RegionRec tmpRegion; ++ BoxRec box; ++ GC_OP_PROLOGUE(pDrawable, pGC); ++ ++ TRC((stderr,"rfbPolyPoint called\n")); ++ ++ if (npt) { ++ int minX = pts[0].x, maxX = pts[0].x; ++ int minY = pts[0].y, maxY = pts[0].y; ++ ++ if (mode == CoordModePrevious) ++ { ++ int x = pts[0].x, y = pts[0].y; ++ ++ for (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 (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; ++ } ++ } ++ ++ box.x1 = minX + pDrawable->x; ++ box.y1 = minY + pDrawable->y; ++ box.x2 = maxX + 1 + pDrawable->x; ++ box.y2 = maxY + 1 + pDrawable->y; ++ ++ SAFE_REGION_INIT(pDrawable->pScreen, &tmpRegion, &box, 0); ++ ++ REGION_INTERSECT(pDrawable->pScreen, &tmpRegion, &tmpRegion, ++ pGC->pCompositeClip); ++ ++ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, &tmpRegion); ++ ++ REGION_UNINIT(pDrawable->pScreen, &tmpRegion); ++ } ++ ++ (*pGC->ops->PolyPoint) (pDrawable, pGC, mode, npt, pts); ++ ++ if (npt) { ++ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); ++ } ++ ++ GC_OP_EPILOGUE(pGC); ++} ++ ++/* ++ * PolyLines - take the union of bounding boxes around each line (and clip). ++ */ ++ ++static void ++rfbPolylines (DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, DDXPointPtr ppts) ++{ ++ RegionPtr tmpRegion; ++ xRectangle *rects; ++ int i, extra, nlines, lw; ++ int x1, x2, y1, y2; ++ GC_OP_PROLOGUE(pDrawable, pGC); ++ ++ TRC((stderr,"rfbPolylines called\n")); ++ ++ if (npt) { ++ lw = pGC->lineWidth; ++ if (lw == 0) ++ lw = 1; ++ ++ if (npt == 1) ++ { ++ nlines = 1; ++ rects = (xRectangle *)xalloc(sizeof(xRectangle)); ++ if (!rects) { ++ FatalError("rfbPolylines: xalloc failed\n"); ++ } ++ ++ rects[0].x = ppts[0].x - lw + pDrawable->x; /* being safe here */ ++ rects[0].y = ppts[0].y - lw + pDrawable->y; ++ rects[0].width = 2*lw; ++ rects[0].height = 2*lw; ++ } ++ else ++ { ++ nlines = npt - 1; ++ rects = (xRectangle *)xalloc(nlines*sizeof(xRectangle)); ++ if (!rects) { ++ FatalError("rfbPolylines: xalloc failed\n"); ++ } ++ ++ /* ++ * 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 ++ */ ++ ++ if (pGC->joinStyle == JoinMiter) { ++ extra = 6 * lw; ++ } else { ++ extra = lw / 2; ++ } ++ ++ x1 = ppts[0].x + pDrawable->x; ++ y1 = ppts[0].y + pDrawable->y; ++ ++ for (i = 0; i < nlines; i++) { ++ if (mode == CoordModeOrigin) { ++ x2 = pDrawable->x + ppts[i+1].x; ++ y2 = pDrawable->y + ppts[i+1].y; ++ } else { ++ x2 = x1 + ppts[i+1].x; ++ y2 = y1 + ppts[i+1].y; ++ } ++ ++ if (x1 > x2) { ++ rects[i].x = x2 - extra; ++ rects[i].width = x1 - x2 + 1 + 2 * extra; ++ } else { ++ rects[i].x = x1 - extra; ++ rects[i].width = x2 - x1 + 1 + 2 * extra; ++ } ++ ++ if (y1 > y2) { ++ rects[i].y = y2 - extra; ++ rects[i].height = y1 - y2 + 1 + 2 * extra; ++ } else { ++ rects[i].y = y1 - extra; ++ rects[i].height = y2 - y1 + 1 + 2 * extra; ++ } ++ ++ x1 = x2; ++ y1 = y2; ++ } ++ } ++ tmpRegion = RECTS_TO_REGION(pDrawable->pScreen, nlines, rects,CT_NONE); ++ REGION_INTERSECT(pDrawable->pScreen, tmpRegion, tmpRegion, ++ pGC->pCompositeClip); ++ ++ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, tmpRegion); ++ ++ REGION_DESTROY(pDrawable->pScreen, tmpRegion); ++ xfree((char *)rects); ++ } ++ ++ (*pGC->ops->Polylines) (pDrawable, pGC, mode, npt, ppts); ++ ++ if (npt) { ++ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); ++ } ++ ++ GC_OP_EPILOGUE(pGC); ++} ++ ++/* ++ * PolySegment - take the union of bounding boxes around each segment (and ++ * clip). ++ */ ++ ++static void ++rfbPolySegment(DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment *segs) ++{ ++ RegionPtr tmpRegion; ++ xRectangle *rects; ++ int i, extra, lw; ++ ++ GC_OP_PROLOGUE(pDrawable, pGC); ++ ++ TRC((stderr,"rfbPolySegment called\n")); ++ ++ if (nseg) { ++ rects = (xRectangle *)xalloc(nseg*sizeof(xRectangle)); ++ if (!rects) { ++ FatalError("rfbPolySegment: xalloc failed\n"); ++ } ++ ++ lw = pGC->lineWidth; ++ if (lw == 0) ++ lw = 1; ++ ++ extra = lw / 2; ++ ++ for (i = 0; i < nseg; i++) ++ { ++ if (segs[i].x1 > segs[i].x2) { ++ rects[i].x = segs[i].x2 - extra + pDrawable->x; ++ rects[i].width = segs[i].x1 - segs[i].x2 + 1 + 2 * extra; ++ } else { ++ rects[i].x = segs[i].x1 - extra + pDrawable->x; ++ rects[i].width = segs[i].x2 - segs[i].x1 + 1 + 2 * extra; ++ } ++ ++ if (segs[i].y1 > segs[i].y2) { ++ rects[i].y = segs[i].y2 - extra + pDrawable->y; ++ rects[i].height = segs[i].y1 - segs[i].y2 + 1 + 2 * extra; ++ } else { ++ rects[i].y = segs[i].y1 - extra + pDrawable->y; ++ rects[i].height = segs[i].y2 - segs[i].y1 + 1 + 2 * extra; ++ } ++ } ++ ++ tmpRegion = RECTS_TO_REGION(pDrawable->pScreen, nseg, rects, CT_NONE); ++ REGION_INTERSECT(pDrawable->pScreen, tmpRegion, tmpRegion, ++ pGC->pCompositeClip); ++ ++ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, tmpRegion); ++ ++ REGION_DESTROY(pDrawable->pScreen, tmpRegion); ++ xfree((char *)rects); ++ } ++ ++ (*pGC->ops->PolySegment) (pDrawable, pGC, nseg, segs); ++ ++ if (nseg) { ++ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); ++ } ++ ++ GC_OP_EPILOGUE(pGC); ++} ++ ++/* ++ * PolyRectangle (rectangle outlines) - take the union of bounding boxes ++ * around each line (and clip). ++ */ ++ ++static void ++rfbPolyRectangle(DrawablePtr pDrawable, GCPtr pGC, int nrects, xRectangle *rects) ++{ ++ int i, extra, lw; ++ RegionPtr tmpRegion; ++ xRectangle *regRects; ++ GC_OP_PROLOGUE(pDrawable, pGC); ++ ++ TRC((stderr,"rfbPolyRectangle called\n")); ++ ++ if (nrects) { ++ regRects = (xRectangle *)xalloc(nrects*4*sizeof(xRectangle)); ++ if (!regRects) { ++ FatalError("rfbPolyRectangle: xalloc failed\n"); ++ } ++ ++ lw = pGC->lineWidth; ++ if (lw == 0) ++ lw = 1; ++ ++ extra = lw / 2; ++ ++ for (i = 0; i < nrects; i++) ++ { ++ 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; ++ } ++ ++ tmpRegion = RECTS_TO_REGION(pDrawable->pScreen, nrects*4, ++ regRects, CT_NONE); ++ REGION_INTERSECT(pDrawable->pScreen, tmpRegion, tmpRegion, ++ pGC->pCompositeClip); ++ ++ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, tmpRegion); ++ ++ REGION_DESTROY(pDrawable->pScreen, tmpRegion); ++ xfree((char *)regRects); ++ } ++ ++ (*pGC->ops->PolyRectangle) (pDrawable, pGC, nrects, rects); ++ ++ if (nrects) { ++ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); ++ } ++ ++ GC_OP_EPILOGUE(pGC); ++} ++ ++/* ++ * PolyArc - take the union of bounding boxes around each arc (and clip). ++ * Bounding boxes assume each is a full circle / ellipse. ++ */ ++ ++static void ++rfbPolyArc(DrawablePtr pDrawable, register GCPtr pGC, int narcs, xArc *arcs) ++{ ++ int i, extra, lw; ++ RegionPtr tmpRegion; ++ xRectangle *rects; ++ GC_OP_PROLOGUE(pDrawable, pGC); ++ ++ TRC((stderr,"rfbPolyArc called\n")); ++ ++ if (narcs) { ++ rects = (xRectangle *)xalloc(narcs*sizeof(xRectangle)); ++ if (!rects) { ++ FatalError("rfbPolyArc: xalloc failed\n"); ++ } ++ ++ lw = pGC->lineWidth; ++ if (lw == 0) ++ lw = 1; ++ ++ extra = lw / 2; ++ ++ for (i = 0; i < narcs; i++) ++ { ++ rects[i].x = arcs[i].x - extra + pDrawable->x; ++ rects[i].y = arcs[i].y - extra + pDrawable->y; ++ rects[i].width = arcs[i].width + lw; ++ rects[i].height = arcs[i].height + lw; ++ } ++ ++ tmpRegion = RECTS_TO_REGION(pDrawable->pScreen, narcs, rects, CT_NONE); ++ REGION_INTERSECT(pDrawable->pScreen, tmpRegion, tmpRegion, ++ pGC->pCompositeClip); ++ ++ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, tmpRegion); ++ ++ REGION_DESTROY(pDrawable->pScreen, tmpRegion); ++ xfree((char *)rects); ++ } ++ ++ (*pGC->ops->PolyArc) (pDrawable, pGC, narcs, arcs); ++ ++ if (narcs) { ++ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); ++ } ++ ++ GC_OP_EPILOGUE(pGC); ++} ++ ++/* ++ * FillPolygon - take bounding box around polygon (and clip). ++ */ ++ ++static void ++rfbFillPolygon(register DrawablePtr pDrawable, register GCPtr pGC, int shape, int mode, int count, DDXPointPtr pts) ++{ ++ int i; ++ RegionRec tmpRegion; ++ BoxRec box; ++ GC_OP_PROLOGUE(pDrawable, pGC); ++ ++ TRC((stderr,"rfbFillPolygon called\n")); ++ ++ if (count) { ++ int minX = pts[0].x, maxX = pts[0].x; ++ int minY = pts[0].y, maxY = pts[0].y; ++ ++ if (mode == CoordModePrevious) ++ { ++ int x = pts[0].x, y = pts[0].y; ++ ++ for (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 (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; ++ } ++ } ++ ++ box.x1 = minX + pDrawable->x; ++ box.y1 = minY + pDrawable->y; ++ box.x2 = maxX + 1 + pDrawable->x; ++ box.y2 = maxY + 1 + pDrawable->y; ++ ++ SAFE_REGION_INIT(pDrawable->pScreen, &tmpRegion, &box, 0); ++ ++ REGION_INTERSECT(pDrawable->pScreen, &tmpRegion, &tmpRegion, ++ pGC->pCompositeClip); ++ ++ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, &tmpRegion); ++ ++ REGION_UNINIT(pDrawable->pScreen, &tmpRegion); ++ } ++ ++ (*pGC->ops->FillPolygon) (pDrawable, pGC, shape, mode, count, pts); ++ ++ if (count) { ++ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); ++ } ++ ++ GC_OP_EPILOGUE(pGC); ++} ++ ++/* ++ * PolyFillRect - take the union of the given rectangles (and clip). ++ */ ++ ++static void ++rfbPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrects, xRectangle *rects) ++{ ++ RegionPtr tmpRegion; ++ xRectangle *regRects; ++ int i; ++ GC_OP_PROLOGUE(pDrawable, pGC); ++ ++ TRC((stderr,"rfbPolyFillRect called\n")); ++ ++ if (nrects) { ++ regRects = (xRectangle *)xalloc(nrects*sizeof(xRectangle)); ++ if (!regRects) { ++ FatalError("rfbPolyFillRect: xalloc failed\n"); ++ } ++ ++ for (i = 0; i < nrects; i++) { ++ 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; ++ } ++ ++ tmpRegion = RECTS_TO_REGION(pDrawable->pScreen, nrects, regRects, ++ CT_NONE); ++ REGION_INTERSECT(pDrawable->pScreen, tmpRegion, tmpRegion, ++ pGC->pCompositeClip); ++ ++ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, tmpRegion); ++ ++ REGION_DESTROY(pDrawable->pScreen, tmpRegion); ++ xfree((char *)regRects); ++ } ++ ++ (*pGC->ops->PolyFillRect) (pDrawable, pGC, nrects, rects); ++ ++ if (nrects) { ++ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); ++ } ++ ++ GC_OP_EPILOGUE(pGC); ++} ++ ++/* ++ * PolyFillArc - take the union of bounding boxes around each arc (and clip). ++ * Bounding boxes assume each is a full circle / ellipse. ++ */ ++ ++static void ++rfbPolyFillArc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc *arcs) ++{ ++ int i, extra, lw; ++ RegionPtr tmpRegion; ++ xRectangle *rects; ++ GC_OP_PROLOGUE(pDrawable, pGC); ++ ++ TRC((stderr,"rfbPolyFillArc called\n")); ++ ++ if (narcs) { ++ rects = (xRectangle *)xalloc(narcs*sizeof(xRectangle)); ++ if (!rects) { ++ FatalError("rfbPolyFillArc: xalloc failed\n"); ++ } ++ ++ lw = pGC->lineWidth; ++ if (lw == 0) ++ lw = 1; ++ ++ extra = lw / 2; ++ ++ for (i = 0; i < narcs; i++) ++ { ++ rects[i].x = arcs[i].x - extra + pDrawable->x; ++ rects[i].y = arcs[i].y - extra + pDrawable->y; ++ rects[i].width = arcs[i].width + lw; ++ rects[i].height = arcs[i].height + lw; ++ } ++ ++ tmpRegion = RECTS_TO_REGION(pDrawable->pScreen, narcs, rects, CT_NONE); ++ REGION_INTERSECT(pDrawable->pScreen, tmpRegion, tmpRegion, ++ pGC->pCompositeClip); ++ ++ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, tmpRegion); ++ ++ REGION_DESTROY(pDrawable->pScreen, tmpRegion); ++ xfree((char *)rects); ++ } ++ ++ (*pGC->ops->PolyFillArc) (pDrawable, pGC, narcs, arcs); ++ ++ if (narcs) { ++ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); ++ } ++ ++ GC_OP_EPILOGUE(pGC); ++} ++ ++/* ++ * Get a rough bounding box around n characters of the given font. ++ */ ++ ++static void GetTextBoundingBox(DrawablePtr pDrawable, FontPtr font, int x, int y, int n, BoxPtr pbox) ++{ ++ int maxAscent, maxDescent, maxCharWidth; ++ ++ if (FONTASCENT(font) > FONTMAXBOUNDS(font,ascent)) ++ maxAscent = FONTASCENT(font); ++ else ++ maxAscent = FONTMAXBOUNDS(font,ascent); ++ ++ if (FONTDESCENT(font) > FONTMAXBOUNDS(font,descent)) ++ maxDescent = FONTDESCENT(font); ++ else ++ maxDescent = FONTMAXBOUNDS(font,descent); ++ ++ if (FONTMAXBOUNDS(font,rightSideBearing) > FONTMAXBOUNDS(font,characterWidth)) ++ maxCharWidth = FONTMAXBOUNDS(font,rightSideBearing); ++ else ++ maxCharWidth = FONTMAXBOUNDS(font,characterWidth); ++ ++ pbox->x1 = pDrawable->x + x; ++ pbox->y1 = pDrawable->y + y - maxAscent; ++ pbox->x2 = pbox->x1 + maxCharWidth * n; ++ pbox->y2 = pbox->y1 + maxAscent + maxDescent; ++ ++ if (FONTMINBOUNDS(font,leftSideBearing) < 0) { ++ pbox->x1 += FONTMINBOUNDS(font,leftSideBearing); ++ } ++} ++ ++ ++/* ++ * PolyText8 - use rough bounding box. ++ */ ++ ++static int ++rfbPolyText8(DrawablePtr pDrawable, GCPtr pGC, int x, int y, int count, char *chars) ++{ ++ int ret; ++ RegionRec tmpRegion; ++ BoxRec box; ++ GC_OP_PROLOGUE(pDrawable, pGC); ++ ++ TRC((stderr,"rfbPolyText8 called '%.*s'\n",count,chars)); ++ ++ if (count) { ++ GetTextBoundingBox(pDrawable, pGC->font, x, y, count, &box); ++ ++ SAFE_REGION_INIT(pDrawable->pScreen, &tmpRegion, &box, 0); ++ ++ REGION_INTERSECT(pDrawable->pScreen, &tmpRegion, &tmpRegion, ++ pGC->pCompositeClip); ++ ++ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, &tmpRegion); ++ ++ REGION_UNINIT(pDrawable->pScreen, &tmpRegion); ++ } ++ ++ ret = (*pGC->ops->PolyText8) (pDrawable, pGC, x, y, count, chars); ++ ++ if (count) { ++ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); ++ } ++ ++ GC_OP_EPILOGUE(pGC); ++ return ret; ++} ++ ++/* ++ * PolyText16 - use rough bounding box. ++ */ ++ ++static int ++rfbPolyText16(DrawablePtr pDrawable, GCPtr pGC, int x, int y, int count, unsigned short *chars) ++{ ++ int ret; ++ RegionRec tmpRegion; ++ BoxRec box; ++ GC_OP_PROLOGUE(pDrawable, pGC); ++ ++ TRC((stderr,"rfbPolyText16 called\n")); ++ ++ if (count) { ++ GetTextBoundingBox(pDrawable, pGC->font, x, y, count, &box); ++ ++ SAFE_REGION_INIT(pDrawable->pScreen, &tmpRegion, &box, 0); ++ ++ REGION_INTERSECT(pDrawable->pScreen, &tmpRegion, &tmpRegion, ++ pGC->pCompositeClip); ++ ++ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, &tmpRegion); ++ ++ REGION_UNINIT(pDrawable->pScreen, &tmpRegion); ++ } ++ ++ ret = (*pGC->ops->PolyText16) (pDrawable, pGC, x, y, count, chars); ++ ++ if (count) { ++ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); ++ } ++ ++ GC_OP_EPILOGUE(pGC); ++ return ret; ++} ++ ++/* ++ * ImageText8 - use rough bounding box. ++ */ ++ ++static void ++rfbImageText8(DrawablePtr pDrawable, GCPtr pGC, int x, int y, int count, char *chars) ++{ ++ RegionRec tmpRegion; ++ BoxRec box; ++ GC_OP_PROLOGUE(pDrawable, pGC); ++ ++ TRC((stderr,"rfbImageText8 called '%.*s'\n",count,chars)); ++ ++ if (count) { ++ GetTextBoundingBox(pDrawable, pGC->font, x, y, count, &box); ++ ++ SAFE_REGION_INIT(pDrawable->pScreen, &tmpRegion, &box, 0); ++ ++ REGION_INTERSECT(pDrawable->pScreen, &tmpRegion, &tmpRegion, ++ pGC->pCompositeClip); ++ ++ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, &tmpRegion); ++ ++ REGION_UNINIT(pDrawable->pScreen, &tmpRegion); ++ } ++ ++ (*pGC->ops->ImageText8) (pDrawable, pGC, x, y, count, chars); ++ ++ if (count) { ++ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); ++ } ++ ++ GC_OP_EPILOGUE(pGC); ++} ++ ++/* ++ * ImageText16 - use rough bounding box. ++ */ ++ ++static void ++rfbImageText16(DrawablePtr pDrawable, GCPtr pGC, int x, int y, int count, unsigned short *chars) ++{ ++ RegionRec tmpRegion; ++ BoxRec box; ++ GC_OP_PROLOGUE(pDrawable, pGC); ++ ++ TRC((stderr,"rfbImageText16 called\n")); ++ ++ if (count) { ++ GetTextBoundingBox(pDrawable, pGC->font, x, y, count, &box); ++ ++ SAFE_REGION_INIT(pDrawable->pScreen, &tmpRegion, &box, 0); ++ ++ REGION_INTERSECT(pDrawable->pScreen, &tmpRegion, &tmpRegion, ++ pGC->pCompositeClip); ++ ++ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, &tmpRegion); ++ ++ REGION_UNINIT(pDrawable->pScreen, &tmpRegion); ++ } ++ ++ (*pGC->ops->ImageText16) (pDrawable, pGC, x, y, count, chars); ++ ++ if (count) { ++ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); ++ } ++ ++ GC_OP_EPILOGUE(pGC); ++} ++ ++/* ++ * ImageGlyphBlt - use rough bounding box. ++ */ ++ ++static void ++rfbImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x, int y, unsigned int nglyph, CharInfoPtr *ppci, pointer pglyphBase) ++{ ++ RegionRec tmpRegion; ++ BoxRec box; ++ GC_OP_PROLOGUE(pDrawable, pGC); ++ ++ TRC((stderr,"rfbImageGlyphBlt called\n")); ++ ++ if (nglyph) { ++ GetTextBoundingBox(pDrawable, pGC->font, x, y, nglyph, &box); ++ ++ SAFE_REGION_INIT(pDrawable->pScreen, &tmpRegion, &box, 0); ++ ++ REGION_INTERSECT(pDrawable->pScreen, &tmpRegion, &tmpRegion, ++ pGC->pCompositeClip); ++ ++ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, &tmpRegion); ++ ++ REGION_UNINIT(pDrawable->pScreen, &tmpRegion); ++ } ++ ++ (*pGC->ops->ImageGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci,pglyphBase); ++ ++ if (nglyph) { ++ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); ++ } ++ ++ GC_OP_EPILOGUE(pGC); ++} ++ ++/* ++ * PolyGlyphBlt - use rough bounding box. ++ */ ++ ++static void ++rfbPolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x, int y, unsigned int nglyph, CharInfoPtr *ppci, pointer pglyphBase) ++{ ++ RegionRec tmpRegion; ++ BoxRec box; ++ GC_OP_PROLOGUE(pDrawable, pGC); ++ ++ TRC((stderr,"rfbPolyGlyphBlt called\n")); ++ ++ if (nglyph) { ++ GetTextBoundingBox(pDrawable, pGC->font, x, y, nglyph, &box); ++ ++ SAFE_REGION_INIT(pDrawable->pScreen, &tmpRegion, &box, 0); ++ ++ REGION_INTERSECT(pDrawable->pScreen, &tmpRegion, &tmpRegion, ++ pGC->pCompositeClip); ++ ++ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, &tmpRegion); ++ ++ REGION_UNINIT(pDrawable->pScreen, &tmpRegion); ++ } ++ ++ (*pGC->ops->PolyGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); ++ ++ if (nglyph) { ++ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); ++ } ++ ++ GC_OP_EPILOGUE(pGC); ++} ++ ++/* ++ * PushPixels - be fairly safe - region modified is intersection of the given ++ * rectangle with the window clip region. ++ */ ++ ++static void ++rfbPushPixels(GCPtr pGC, PixmapPtr pBitMap, DrawablePtr pDrawable, int w, int h, int x, int y) ++{ ++ RegionRec tmpRegion; ++ BoxRec box; ++ GC_OP_PROLOGUE(pDrawable, pGC); ++ ++ TRC((stderr,"rfbPushPixels called\n")); ++ ++ box.x1 = x + pDrawable->x; ++ box.y1 = y + pDrawable->y; ++ box.x2 = box.x1 + w; ++ box.y2 = box.y1 + h; ++ ++ SAFE_REGION_INIT(pDrawable->pScreen, &tmpRegion, &box, 0); ++ ++ REGION_INTERSECT(pDrawable->pScreen, &tmpRegion, &tmpRegion, ++ pGC->pCompositeClip); ++ ++ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, &tmpRegion); ++ ++ REGION_UNINIT(pDrawable->pScreen, &tmpRegion); ++ ++ (*pGC->ops->PushPixels) (pGC, pBitMap, pDrawable, w, h, x, y); ++ ++ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC); ++ ++ GC_OP_EPILOGUE(pGC); ++} ++ ++#ifdef RENDER ++void ++rfbComposite( ++ 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; ++ VNCSCREENPTR(pScreen); ++ RegionRec tmpRegion; ++ BoxRec box; ++ PictureScreenPtr ps = GetPictureScreen(pScreen); ++ ++ box.x1 = pDst->pDrawable->x + xDst; ++ box.y1 = pDst->pDrawable->y + yDst; ++ box.x2 = box.x1 + width; ++ box.y2 = box.y1 + height; ++ ++ REGION_INIT(pScreen, &tmpRegion, &box, 0); ++ ++ ADD_TO_MODIFIED_REGION(pScreen, &tmpRegion); ++ ++ ps->Composite = pVNC->Composite; ++ (*ps->Composite)(op, pSrc, pMask, pDst, xSrc, ySrc, ++ xMask, yMask, xDst, yDst, width, height); ++ ps->Composite = rfbComposite; ++ ++ SCHEDULE_FB_UPDATE(pScreen, pVNC); ++ ++ REGION_UNINIT(pScreen, &tmpRegion); ++} ++#endif /* RENDER */ ++ ++/****************************************************************************/ ++/* ++ * Other functions ++ */ ++/****************************************************************************/ ++ ++/* ++ * rfbCopyRegion. Args are src and dst regions plus a translation (dx,dy). ++ * Takes these args together with the existing modified region and possibly an ++ * existing copy region and translation. Produces a combined modified region ++ * plus copy region and translation. Note that the copy region is the ++ * destination of the copy. ++ * ++ * First we trim parts of src which are invalid (ie in the modified region). ++ * Then we see if there is any overlap between the src and the existing copy ++ * region. If not then the two copies cannot be combined, so we choose ++ * whichever is bigger to form the basis of a new copy, while the other copy is ++ * just done the hard way by being added to the modified region. So if the ++ * existing copy is bigger then we simply add the destination of the new copy ++ * to the modified region and we're done. If the new copy is bigger, we add ++ * the old copy region to the modified region and behave as though there is no ++ * existing copy region. ++ * ++ * At this stage we now know that either the two copies can be combined, or ++ * that there is no existing copy. We temporarily add both the existing copy ++ * region and dst to the modified region (this is the entire area of the screen ++ * affected in any way). Finally we calculate the new copy region, and remove ++ * it from the modified region. ++ * ++ * Note: ++ * 1. The src region is modified by this routine. ++ * 2. When the copy region is empty, copyDX and copyDY MUST be set to zero. ++ */ ++ ++static void ++rfbCopyRegion(pScreen, cl, src, dst, dx, dy) ++ ScreenPtr pScreen; ++ rfbClientPtr cl; ++ RegionPtr src; ++ RegionPtr dst; ++ int dx, dy; ++{ ++ RegionRec tmp; ++ ++ /* src = src - modifiedRegion */ ++ ++ REGION_SUBTRACT(pScreen, src, src, &cl->modifiedRegion); ++ ++ if (REGION_NOTEMPTY(pScreen, &cl->copyRegion)) { ++ ++ REGION_NULL(pScreen, &tmp); ++ REGION_INTERSECT(pScreen, &tmp, src, &cl->copyRegion); ++ ++ if (REGION_NOTEMPTY(pScreen, &tmp)) { ++ ++ /* if src and copyRegion overlap: ++ src = src intersect copyRegion */ ++ ++ REGION_COPY(pScreen, src, &tmp); ++ ++ } else { ++ ++ /* if no overlap, find bigger region */ ++ ++ int newArea = (((REGION_EXTENTS(pScreen,src))->x2 ++ - (REGION_EXTENTS(pScreen,src))->x1) ++ * ((REGION_EXTENTS(pScreen,src))->y2 ++ - (REGION_EXTENTS(pScreen,src))->y1)); ++ ++ int oldArea = (((REGION_EXTENTS(pScreen,&cl->copyRegion))->x2 ++ - (REGION_EXTENTS(pScreen,&cl->copyRegion))->x1) ++ * ((REGION_EXTENTS(pScreen,&cl->copyRegion))->y2 ++ - (REGION_EXTENTS(pScreen,&cl->copyRegion))->y1)); ++ ++ if (oldArea > newArea) { ++ ++ /* existing copy is bigger: ++ modifiedRegion = modifiedRegion union dst ++ copyRegion = copyRegion - dst ++ return */ ++ ++ REGION_UNION(pScreen, &cl->modifiedRegion, &cl->modifiedRegion, ++ dst); ++ REGION_SUBTRACT(pScreen, &cl->copyRegion, &cl->copyRegion, ++ dst); ++ if (!REGION_NOTEMPTY(pScreen, &cl->copyRegion)) { ++ cl->copyDX = 0; ++ cl->copyDY = 0; ++ } ++ return; ++ } ++ ++ /* new copy is bigger: ++ modifiedRegion = modifiedRegion union copyRegion ++ copyRegion = empty */ ++ ++ REGION_UNION(pScreen, &cl->modifiedRegion, &cl->modifiedRegion, ++ &cl->copyRegion); ++ REGION_EMPTY(pScreen, &cl->copyRegion); ++ cl->copyDX = cl->copyDY = 0; ++ } ++ } ++ ++ ++ /* modifiedRegion = modifiedRegion union dst union copyRegion */ ++ ++ REGION_UNION(pScreen, &cl->modifiedRegion, &cl->modifiedRegion, dst); ++ REGION_UNION(pScreen, &cl->modifiedRegion, &cl->modifiedRegion, ++ &cl->copyRegion); ++ ++ /* copyRegion = T(src) intersect dst */ ++ ++ REGION_TRANSLATE(pScreen, src, dx, dy); ++ REGION_INTERSECT(pScreen, &cl->copyRegion, src, dst); ++ ++ /* modifiedRegion = modifiedRegion - copyRegion */ ++ ++ REGION_SUBTRACT(pScreen, &cl->modifiedRegion, &cl->modifiedRegion, ++ &cl->copyRegion); ++ ++ /* combine new translation T with existing translation */ ++ ++ if (REGION_NOTEMPTY(pScreen, &cl->copyRegion)) { ++ cl->copyDX += dx; ++ cl->copyDY += dy; ++ } else { ++ cl->copyDX = 0; ++ cl->copyDY = 0; ++ } ++} ++ ++ ++/* ++ * rfbDeferredUpdateCallback() is called when a client's deferredUpdateTimer ++ * goes off. ++ */ ++ ++static CARD32 ++rfbDeferredUpdateCallback(OsTimerPtr timer, CARD32 now, pointer arg) ++{ ++ rfbClientPtr cl = (rfbClientPtr)arg; ++ ++ rfbSendFramebufferUpdate(cl->pScreen, cl); ++ ++ cl->deferredUpdateScheduled = FALSE; ++ return 0; ++} ++ ++ ++/* ++ * rfbScheduleDeferredUpdate() is called from the SCHEDULE_FB_UPDATE macro ++ * to schedule an update. ++ */ ++ ++static void ++rfbScheduleDeferredUpdate(ScreenPtr pScreen, rfbClientPtr cl) ++{ ++ if (rfbDeferUpdateTime != 0) { ++ cl->deferredUpdateTimer = TimerSet(cl->deferredUpdateTimer, 0, ++ rfbDeferUpdateTime, ++ rfbDeferredUpdateCallback, cl); ++ cl->deferredUpdateScheduled = TRUE; ++ } else { ++ rfbSendFramebufferUpdate(pScreen, cl); ++ } ++} ++ ++ ++/* ++ * PrintRegion is useful for debugging. ++ */ ++ ++#ifdef DEBUG ++static void ++PrintRegion(ScreenPtr pScreen, RegionPtr reg) ++{ ++ int nrects = REGION_NUM_RECTS(reg); ++ int i; ++ ++ ErrorF("Region num rects %d extents %d,%d %d,%d\n",nrects, ++ (REGION_EXTENTS(pScreen,reg))->x1, ++ (REGION_EXTENTS(pScreen,reg))->y1, ++ (REGION_EXTENTS(pScreen,reg))->x2, ++ (REGION_EXTENTS(pScreen,reg))->y2); ++ ++ for (i = 0; i < nrects; i++) { ++ ErrorF(" rect %d,%d %dx%d\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); ++ } ++} ++#endif ++ ++/** ++ * Allow scheduling updates from other functions in other files. ++ */ ++void ++rfbScheduleUpdate(ScreenPtr pScreen) ++{ ++ VNCSCREENPTR(pScreen); ++ SCHEDULE_FB_UPDATE(pScreen, pVNC); ++} +diff -pNur xorg-server-1.4.orig/hw/vnc/hextile.c xorg-server-1.4/hw/vnc/hextile.c +--- xorg-server-1.4.orig/hw/vnc/hextile.c 1969-12-31 16:00:00.000000000 -0800 ++++ xorg-server-1.4/hw/vnc/hextile.c 2007-09-06 16:09:45.000000000 -0700 +@@ -0,0 +1,350 @@ ++/* ++ * hextile.c ++ * ++ * Routines to implement Hextile Encoding ++ * ++ * Modified for XFree86 4.x by Alan Hourihane ++ */ ++ ++/* ++ * 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. ++ */ ++#ifdef HAVE_DIX_CONFIG_H ++#include ++#endif ++ ++#include ++#include "rfb.h" ++ ++static Bool sendHextiles8(rfbClientPtr cl, int x, int y, int w, int h); ++static Bool sendHextiles16(rfbClientPtr cl, int x, int y, int w, int h); ++static Bool sendHextiles32(rfbClientPtr cl, int x, int y, int w, int h); ++ ++ ++/* ++ * rfbSendRectEncodingHextile - send a rectangle using hextile encoding. ++ */ ++ ++Bool ++rfbSendRectEncodingHextile(cl, x, y, w, h) ++ rfbClientPtr cl; ++ int x, y, w, h; ++{ ++ VNCSCREENPTR(cl->pScreen); ++ rfbFramebufferUpdateRectHeader rect; ++ ++ if (pVNC->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) { ++ if (!rfbSendUpdateBuf(cl)) ++ return FALSE; ++ } ++ ++ rect.r.x = Swap16IfLE(x); ++ rect.r.y = Swap16IfLE(y); ++ rect.r.w = Swap16IfLE(w); ++ rect.r.h = Swap16IfLE(h); ++ rect.encoding = Swap32IfLE(rfbEncodingHextile); ++ ++ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&rect, ++ sz_rfbFramebufferUpdateRectHeader); ++ pVNC->ublen += sz_rfbFramebufferUpdateRectHeader; ++ ++ cl->rfbRectanglesSent[rfbEncodingHextile]++; ++ cl->rfbBytesSent[rfbEncodingHextile] += sz_rfbFramebufferUpdateRectHeader; ++ ++ switch (cl->format.bitsPerPixel) { ++ case 8: ++ return sendHextiles8(cl, x, y, w, h); ++ case 16: ++ return sendHextiles16(cl, x, y, w, h); ++ case 32: ++ return sendHextiles32(cl, x, y, w, h); ++ } ++ ++ rfbLog("rfbSendRectEncodingHextile: bpp %d?\n", cl->format.bitsPerPixel); ++ return FALSE; ++} ++ ++ ++#define PUT_PIXEL8(pix) (pVNC->updateBuf[pVNC->ublen++] = (pix)) ++ ++#define PUT_PIXEL16(pix) (pVNC->updateBuf[pVNC->ublen++] = ((char*)&(pix))[0], \ ++ pVNC->updateBuf[pVNC->ublen++] = ((char*)&(pix))[1]) ++ ++#define PUT_PIXEL32(pix) (pVNC->updateBuf[pVNC->ublen++] = ((char*)&(pix))[0], \ ++ pVNC->updateBuf[pVNC->ublen++] = ((char*)&(pix))[1], \ ++ pVNC->updateBuf[pVNC->ublen++] = ((char*)&(pix))[2], \ ++ pVNC->updateBuf[pVNC->ublen++] = ((char*)&(pix))[3]) ++ ++ ++#define DEFINE_SEND_HEXTILES(bpp) \ ++ \ ++ \ ++static Bool subrectEncode##bpp(ScreenPtr pScreen, CARD##bpp *data, int w, \ ++ int h, CARD##bpp bg, \ ++ CARD##bpp fg, Bool mono); \ ++static void testColours##bpp(CARD##bpp *data, int size, Bool *mono, \ ++ Bool *solid, CARD##bpp *bg, CARD##bpp *fg); \ ++ \ ++ \ ++/* \ ++ * rfbSendHextiles \ ++ */ \ ++ \ ++static Bool \ ++sendHextiles##bpp(cl, rx, ry, rw, rh) \ ++ rfbClientPtr cl; \ ++ int rx, ry, rw, rh; \ ++{ \ ++ VNCSCREENPTR(cl->pScreen); \ ++ int x, y, w, h; \ ++ int startUblen; \ ++ CARD##bpp bg = 0, fg = 0, newBg, newFg; \ ++ Bool mono, solid; \ ++ Bool validBg = FALSE; \ ++ Bool validFg = FALSE; \ ++ CARD##bpp clientPixelData[16*16*(bpp/8)]; \ ++ \ ++ for (y = ry; y < ry+rh; y += 16) { \ ++ for (x = rx; x < rx+rw; x += 16) { \ ++ w = h = 16; \ ++ if (rx+rw - x < 16) \ ++ w = rx+rw - x; \ ++ if (ry+rh - y < 16) \ ++ h = ry+rh - y; \ ++ \ ++ if ((pVNC->ublen + 1 + (2 + 16 * 16) * (bpp/8)) > UPDATE_BUF_SIZE) { \ ++ if (!rfbSendUpdateBuf(cl)) \ ++ return FALSE; \ ++ } \ ++ \ ++ (*cl->translateFn)(cl->pScreen, cl->translateLookupTable, \ ++ &pVNC->rfbServerFormat, \ ++ &cl->format, (unsigned char *)clientPixelData, \ ++ pVNC->paddedWidthInBytes, w, h, x, y); \ ++ \ ++ startUblen = pVNC->ublen; \ ++ pVNC->updateBuf[startUblen] = 0; \ ++ pVNC->ublen++; \ ++ \ ++ testColours##bpp(clientPixelData, w * h, \ ++ &mono, &solid, &newBg, &newFg); \ ++ \ ++ if (!validBg || (newBg != bg)) { \ ++ validBg = TRUE; \ ++ bg = newBg; \ ++ pVNC->updateBuf[startUblen] |= rfbHextileBackgroundSpecified; \ ++ PUT_PIXEL##bpp(bg); \ ++ } \ ++ \ ++ if (solid) { \ ++ cl->rfbBytesSent[rfbEncodingHextile] += pVNC->ublen - startUblen; \ ++ continue; \ ++ } \ ++ \ ++ pVNC->updateBuf[startUblen] |= rfbHextileAnySubrects; \ ++ \ ++ if (mono) { \ ++ if (!validFg || (newFg != fg)) { \ ++ validFg = TRUE; \ ++ fg = newFg; \ ++ pVNC->updateBuf[startUblen] |= rfbHextileForegroundSpecified; \ ++ PUT_PIXEL##bpp(fg); \ ++ } \ ++ } else { \ ++ validFg = FALSE; \ ++ pVNC->updateBuf[startUblen] |= rfbHextileSubrectsColoured; \ ++ } \ ++ \ ++ if (!subrectEncode##bpp(cl->pScreen, clientPixelData, w, h, bg, fg, mono)) { \ ++ /* encoding was too large, use raw */ \ ++ validBg = FALSE; \ ++ validFg = FALSE; \ ++ pVNC->ublen = startUblen; \ ++ pVNC->updateBuf[pVNC->ublen++] = rfbHextileRaw; \ ++ (*cl->translateFn)(cl->pScreen, cl->translateLookupTable, \ ++ &pVNC->rfbServerFormat, &cl->format, \ ++ (unsigned char *)clientPixelData, \ ++ pVNC->paddedWidthInBytes, w, h, x, y); \ ++ \ ++ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)clientPixelData,\ ++ w * h * (bpp/8)); \ ++ \ ++ pVNC->ublen += w * h * (bpp/8); \ ++ } \ ++ \ ++ cl->rfbBytesSent[rfbEncodingHextile] += pVNC->ublen - startUblen; \ ++ } \ ++ } \ ++ \ ++ return TRUE; \ ++} \ ++ \ ++ \ ++static Bool \ ++subrectEncode##bpp(ScreenPtr pScreen, CARD##bpp *data, int w, int h, \ ++ CARD##bpp bg, CARD##bpp fg, Bool mono) \ ++{ \ ++ VNCSCREENPTR(pScreen); \ ++ CARD##bpp clientdata; \ ++ int x,y; \ ++ int i,j; \ ++ int hx=0,hy,vx=0,vy; \ ++ int hyflag; \ ++ CARD##bpp *seg; \ ++ CARD##bpp *line; \ ++ int hw,hh,vw,vh; \ ++ int thex,they,thew,theh; \ ++ int numsubs = 0; \ ++ int newLen; \ ++ int nSubrectsUblen; \ ++ \ ++ nSubrectsUblen = pVNC->ublen; \ ++ pVNC->ublen++; \ ++ \ ++ for (y=0; y 0) && (i >= hx)) { \ ++ hy += 1; \ ++ } else { \ ++ hyflag = 0; \ ++ } \ ++ } \ ++ vy = j-1; \ ++ \ ++ /* We now have two possible subrects: (x,y,hx,hy) and \ ++ * (x,y,vx,vy). We'll choose the bigger of the two. \ ++ */ \ ++ hw = hx-x+1; \ ++ hh = hy-y+1; \ ++ vw = vx-x+1; \ ++ vh = vy-y+1; \ ++ \ ++ thex = x; \ ++ they = y; \ ++ \ ++ if ((hw*hh) > (vw*vh)) { \ ++ thew = hw; \ ++ theh = hh; \ ++ } else { \ ++ thew = vw; \ ++ theh = vh; \ ++ } \ ++ \ ++ if (mono) { \ ++ newLen = pVNC->ublen - nSubrectsUblen + 2; \ ++ } else { \ ++ newLen = pVNC->ublen - nSubrectsUblen + bpp/8 + 2; \ ++ } \ ++ \ ++ if (newLen > (w * h * (bpp/8))) \ ++ return FALSE; \ ++ \ ++ numsubs += 1; \ ++ \ ++ if (!mono) PUT_PIXEL##bpp(clientdata); \ ++ \ ++ pVNC->updateBuf[pVNC->ublen++] = rfbHextilePackXY(thex,they); \ ++ pVNC->updateBuf[pVNC->ublen++] = rfbHextilePackWH(thew,theh); \ ++ \ ++ /* \ ++ * Now mark the subrect as done. \ ++ */ \ ++ for (j=they; j < (they+theh); j++) { \ ++ for (i=thex; i < (thex+thew); i++) { \ ++ data[j*w+i] = bg; \ ++ } \ ++ } \ ++ } \ ++ } \ ++ } \ ++ \ ++ pVNC->updateBuf[nSubrectsUblen] = numsubs; \ ++ \ ++ return TRUE; \ ++} \ ++ \ ++ \ ++/* \ ++ * testColours() tests if there are one (solid), two (mono) or more \ ++ * colours in a tile and gets a reasonable guess at the best background \ ++ * pixel, and the foreground pixel for mono. \ ++ */ \ ++ \ ++static void \ ++testColours##bpp(data,size,mono,solid,bg,fg) \ ++ CARD##bpp *data; \ ++ int size; \ ++ Bool *mono; \ ++ Bool *solid; \ ++ CARD##bpp *bg; \ ++ CARD##bpp *fg; \ ++{ \ ++ CARD##bpp colour1 = 0, colour2 = 0; \ ++ int n1 = 0, n2 = 0; \ ++ *mono = TRUE; \ ++ *solid = TRUE; \ ++ \ ++ for (; size > 0; size--, data++) { \ ++ \ ++ if (n1 == 0) \ ++ colour1 = *data; \ ++ \ ++ if (*data == colour1) { \ ++ n1++; \ ++ continue; \ ++ } \ ++ \ ++ if (n2 == 0) { \ ++ *solid = FALSE; \ ++ colour2 = *data; \ ++ } \ ++ \ ++ if (*data == colour2) { \ ++ n2++; \ ++ continue; \ ++ } \ ++ \ ++ *mono = FALSE; \ ++ break; \ ++ } \ ++ \ ++ if (n1 > n2) { \ ++ *bg = colour1; \ ++ *fg = colour2; \ ++ } else { \ ++ *bg = colour2; \ ++ *fg = colour1; \ ++ } \ ++} ++ ++DEFINE_SEND_HEXTILES(8) ++DEFINE_SEND_HEXTILES(16) ++DEFINE_SEND_HEXTILES(32) +diff -pNur xorg-server-1.4.orig/hw/vnc/httpd.c xorg-server-1.4/hw/vnc/httpd.c +--- xorg-server-1.4.orig/hw/vnc/httpd.c 1969-12-31 16:00:00.000000000 -0800 ++++ xorg-server-1.4/hw/vnc/httpd.c 2007-09-06 16:09:45.000000000 -0700 +@@ -0,0 +1,519 @@ ++/* ++ * httpd.c - a simple HTTP server ++ * ++ * Modified for XFree86 4.x by Alan Hourihane ++ */ ++ ++/* ++ * Copyright (C) 2002 Constantin Kaplinsky. All Rights Reserved. ++ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. ++ * ++ * This is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This software is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this software; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, ++ * USA. ++ */ ++#ifdef HAVE_DIX_CONFIG_H ++#include ++#endif ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#ifndef USE_LIBWRAP ++#define USE_LIBWRAP 0 ++#endif ++#if USE_LIBWRAP ++#include ++#endif ++ ++#include "rfb.h" ++ ++#define NOT_FOUND_STR "HTTP/1.0 404 Not found\r\n\r\n" \ ++ "File Not Found\n" \ ++ "

File Not Found

\n" ++ ++#define OK_STR "HTTP/1.0 200 OK\r\n\r\n" ++ ++static void httpProcessInput(ScreenPtr pScreen); ++static Bool compareAndSkip(char **ptr, const char *str); ++static Bool parseParams(const char *request, char *result, int max_bytes); ++static Bool validateString(char *str); ++ ++/* ++ * httpInitSockets sets up the TCP socket to listen for HTTP connections. ++ */ ++ ++Bool ++httpInitSockets(ScreenPtr pScreen) ++{ ++ VNCSCREENPTR(pScreen); ++ ++ if (!pVNC->httpDir) ++ return FALSE; ++ ++ pVNC->buf_filled = 0; ++ ++ if (pVNC->httpPort == 0) { ++ pVNC->httpPort = 5800 + atoi(display) + pScreen->myNum; ++ } ++ ++ if ((pVNC->httpListenSock = ListenOnTCPPort(pScreen, pVNC->httpPort)) < 0) { ++ rfbLog("ListenOnTCPPort %d failed\n",pVNC->httpPort); ++ pVNC->httpPort = 0; ++ return FALSE; ++ } ++ ++ rfbLog("Listening for HTTP connections on TCP port %d\n", pVNC->httpPort); ++ rfbLog(" URL http://%s:%d\n",rfbThisHost,pVNC->httpPort); ++ ++ AddEnabledDevice(pVNC->httpListenSock); ++ ++ return TRUE; ++} ++ ++ ++/* ++ * httpCheckFds is called from ProcessInputEvents to check for input on the ++ * HTTP socket(s). If there is input to process, httpProcessInput is called. ++ */ ++ ++void ++httpCheckFds(ScreenPtr pScreen) ++{ ++ VNCSCREENPTR(pScreen); ++ int nfds; ++ fd_set fds; ++ struct timeval tv; ++ struct sockaddr_in addr; ++ SOCKLEN_T addrlen = sizeof(addr); ++ ++ if (!pVNC->httpDir) ++ return; ++ ++ FD_ZERO(&fds); ++ FD_SET(pVNC->httpListenSock, &fds); ++ if (pVNC->httpSock >= 0) { ++ FD_SET(pVNC->httpSock, &fds); ++ } ++ tv.tv_sec = 0; ++ tv.tv_usec = 0; ++ nfds = select(max(pVNC->httpSock,pVNC->httpListenSock) + 1, &fds, NULL, NULL, &tv); ++ if (nfds == 0) { ++ return; ++ } ++ if (nfds < 0) { ++ if (errno != EINTR) ++ rfbLogPerror("httpCheckFds: select"); ++ return; ++ } ++ ++ if ((pVNC->httpSock >= 0) && FD_ISSET(pVNC->httpSock, &fds)) { ++ httpProcessInput(pScreen); ++ } ++ ++ if (FD_ISSET(pVNC->httpListenSock, &fds)) { ++ int flags; ++ ++ if (pVNC->httpSock >= 0) close(pVNC->httpSock); ++ ++ if ((pVNC->httpSock = accept(pVNC->httpListenSock, ++ (struct sockaddr *)&addr, &addrlen)) < 0) { ++ rfbLogPerror("httpCheckFds: accept"); ++ return; ++ } ++ ++#if USE_LIBWRAP ++ if (!hosts_ctl("Xvnc", STRING_UNKNOWN, inet_ntoa(addr.sin_addr), ++ STRING_UNKNOWN)) { ++ rfbLog("Rejected HTTP connection from client %s\n", ++ inet_ntoa(addr.sin_addr)); ++ close(pVNC->httpSock); ++ pVNC->httpSock = -1; ++ return; ++ } ++#endif ++ ++ flags = fcntl (pVNC->httpSock, F_GETFL); ++ ++ if (flags == -1 || ++ fcntl (pVNC->httpSock, F_SETFL, flags | O_NONBLOCK) == -1) { ++ rfbLogPerror("httpCheckFds: fcntl"); ++ close (pVNC->httpSock); ++ pVNC->httpSock = -1; ++ return; ++ } ++ ++ AddEnabledDevice(pVNC->httpSock); ++ } ++} ++ ++ ++static void ++httpCloseSock(ScreenPtr pScreen) ++{ ++ VNCSCREENPTR(pScreen); ++ close(pVNC->httpSock); ++ RemoveEnabledDevice(pVNC->httpSock); ++ pVNC->httpSock = -1; ++ pVNC->buf_filled = 0; ++} ++ ++ ++/* ++ * httpProcessInput is called when input is received on the HTTP socket. ++ */ ++ ++static void ++httpProcessInput(ScreenPtr pScreen) ++{ ++ VNCSCREENPTR(pScreen); ++ struct sockaddr_in addr; ++ SOCKLEN_T addrlen = sizeof(addr); ++ char fullFname[512]; ++ char params[1024]; ++ char *ptr; ++ char *fname; ++ int maxFnameLen; ++ int fd; ++ Bool performSubstitutions = FALSE; ++ char str[256]; ++ struct passwd *user = getpwuid(getuid()); ++ ++ if (strlen(pVNC->httpDir) > 255) { ++ rfbLog("-httpd directory too long\n"); ++ httpCloseSock(pScreen); ++ return; ++ } ++ strcpy(fullFname, pVNC->httpDir); ++ fname = &fullFname[strlen(fullFname)]; ++ maxFnameLen = 511 - strlen(fullFname); ++ ++ /* Read data from the HTTP client until we get a complete request. */ ++ while (1) { ++ ssize_t got = read (pVNC->httpSock, pVNC->buf + pVNC->buf_filled, ++ sizeof (pVNC->buf) - pVNC->buf_filled - 1); ++ ++ if (got <= 0) { ++ if (got == 0) { ++ rfbLog("httpd: premature connection close\n"); ++ } else { ++ if (errno == EAGAIN) { ++ return; ++ } ++ rfbLogPerror("httpProcessInput: read"); ++ } ++ httpCloseSock(pScreen); ++ return; ++ } ++ ++ pVNC->buf_filled += got; ++ pVNC->buf[pVNC->buf_filled] = '\0'; ++ ++ /* Is it complete yet (is there a blank line)? */ ++ if (strstr (pVNC->buf, "\r\r") || strstr (pVNC->buf, "\n\n") || ++ strstr (pVNC->buf, "\r\n\r\n") || strstr (pVNC->buf, "\n\r\n\r")) ++ break; ++ } ++ ++ /* Process the request. */ ++ if (strncmp(pVNC->buf, "GET ", 4)) { ++ rfbLog("httpd: no GET line\n"); ++ httpCloseSock(pScreen); ++ return; ++ } else { ++ /* Only use the first line. */ ++ pVNC->buf[strcspn(pVNC->buf, "\n\r")] = '\0'; ++ } ++ ++ if (strlen(pVNC->buf) > maxFnameLen) { ++ rfbLog("httpd: GET line too long\n"); ++ httpCloseSock(pScreen); ++ return; ++ } ++ ++ if (sscanf(pVNC->buf, "GET %s HTTP/1.0", fname) != 1) { ++ rfbLog("httpd: couldn't parse GET line\n"); ++ httpCloseSock(pScreen); ++ return; ++ } ++ ++ if (fname[0] != '/') { ++ rfbLog("httpd: filename didn't begin with '/'\n"); ++ WriteExact(pVNC->httpSock, NOT_FOUND_STR, strlen(NOT_FOUND_STR)); ++ httpCloseSock(pScreen); ++ return; ++ } ++ ++ if (strchr(fname+1, '/') != NULL) { ++ rfbLog("httpd: asking for file in other directory\n"); ++ WriteExact(pVNC->httpSock, NOT_FOUND_STR, strlen(NOT_FOUND_STR)); ++ httpCloseSock(pScreen); ++ return; ++ } ++ ++ getpeername(pVNC->httpSock, (struct sockaddr *)&addr, &addrlen); ++ rfbLog("httpd: get '%s' for %s\n", fname+1, ++ inet_ntoa(addr.sin_addr)); ++ ++ /* Extract parameters from the URL string if necessary */ ++ ++ params[0] = '\0'; ++ ptr = strchr(fname, '?'); ++ if (ptr != NULL) { ++ *ptr = '\0'; ++ if (!parseParams(&ptr[1], params, 1024)) { ++ params[0] = '\0'; ++ rfbLog("httpd: bad parameters in the URL\n"); ++ } ++ } ++ ++ /* If we were asked for '/', actually read the file index.vnc */ ++ ++ if (strcmp(fname, "/") == 0) { ++ strcpy(fname, "/index.vnc"); ++ rfbLog("httpd: defaulting to '%s'\n", fname+1); ++ } ++ ++ /* Substitutions are performed on files ending .vnc */ ++ ++ if (strlen(fname) >= 4 && strcmp(&fname[strlen(fname)-4], ".vnc") == 0) { ++ performSubstitutions = TRUE; ++ } ++ ++ /* Open the file */ ++ ++ if ((fd = open(fullFname, O_RDONLY)) < 0) { ++ rfbLogPerror("httpProcessInput: open"); ++ WriteExact(pVNC->httpSock, NOT_FOUND_STR, strlen(NOT_FOUND_STR)); ++ httpCloseSock(pScreen); ++ return; ++ } ++ ++ WriteExact(pVNC->httpSock, OK_STR, strlen(OK_STR)); ++ ++ while (1) { ++ int n = read(fd, pVNC->buf, HTTP_BUF_SIZE-1); ++ if (n < 0) { ++ rfbLogPerror("httpProcessInput: read"); ++ close(fd); ++ httpCloseSock(pScreen); ++ return; ++ } ++ ++ if (n == 0) ++ break; ++ ++ if (performSubstitutions) { ++ ++ /* Substitute $WIDTH, $HEIGHT, etc with the appropriate values. ++ This won't quite work properly if the .vnc file is longer than ++ HTTP_BUF_SIZE, but it's reasonable to assume that .vnc files will ++ always be short. */ ++ ++ char *ptr = pVNC->buf; ++ char *dollar; ++ pVNC->buf[n] = 0; /* make sure it's null-terminated */ ++ ++ while ((dollar = strchr(ptr, '$'))) { ++ WriteExact(pVNC->httpSock, ptr, (dollar - ptr)); ++ ++ ptr = dollar; ++ ++ if (compareAndSkip(&ptr, "$WIDTH")) { ++ ++ sprintf(str, "%d", pVNC->width); ++ WriteExact(pVNC->httpSock, str, strlen(str)); ++ ++ } else if (compareAndSkip(&ptr, "$HEIGHT")) { ++ ++ sprintf(str, "%d", pVNC->height); ++ WriteExact(pVNC->httpSock, str, strlen(str)); ++ ++ } else if (compareAndSkip(&ptr, "$APPLETWIDTH")) { ++ ++ sprintf(str, "%d", pVNC->width); ++ WriteExact(pVNC->httpSock, str, strlen(str)); ++ ++ } else if (compareAndSkip(&ptr, "$APPLETHEIGHT")) { ++ ++ sprintf(str, "%d", pVNC->height + 32); ++ WriteExact(pVNC->httpSock, str, strlen(str)); ++ ++ } else if (compareAndSkip(&ptr, "$PORT")) { ++ ++ sprintf(str, "%d", pVNC->rfbPort); ++ WriteExact(pVNC->httpSock, str, strlen(str)); ++ ++ } else if (compareAndSkip(&ptr, "$DESKTOP")) { ++ ++ WriteExact(pVNC->httpSock, desktopName, strlen(desktopName)); ++ ++ } else if (compareAndSkip(&ptr, "$DISPLAY")) { ++ ++ sprintf(str, "%s:%s", rfbThisHost, display); ++ WriteExact(pVNC->httpSock, str, strlen(str)); ++ ++ } else if (compareAndSkip(&ptr, "$USER")) { ++ ++ if (user) { ++ WriteExact(pVNC->httpSock, user->pw_name, ++ strlen(user->pw_name)); ++ } else { ++ WriteExact(pVNC->httpSock, "?", 1); ++ } ++ ++ } else if (compareAndSkip(&ptr, "$PARAMS")) { ++ ++ if (params[0] != '\0') ++ WriteExact(pVNC->httpSock, params, strlen(params)); ++ ++ } else { ++ if (!compareAndSkip(&ptr, "$$")) ++ ptr++; ++ ++ if (WriteExact(pVNC->httpSock, "$", 1) < 0) { ++ close(fd); ++ httpCloseSock(pScreen); ++ return; ++ } ++ } ++ } ++ if (WriteExact(pVNC->httpSock, ptr, (&pVNC->buf[n] - ptr)) < 0) ++ break; ++ ++ } else { ++ ++ /* For files not ending .vnc, just write out the buffer */ ++ ++ if (WriteExact(pVNC->httpSock, pVNC->buf, n) < 0) ++ break; ++ } ++ } ++ ++ close(fd); ++ httpCloseSock(pScreen); ++} ++ ++ ++static Bool ++compareAndSkip(char **ptr, const char *str) ++{ ++ if (strncmp(*ptr, str, strlen(str)) == 0) { ++ *ptr += strlen(str); ++ return TRUE; ++ } ++ ++ return FALSE; ++} ++ ++/* ++ * Parse the request tail after the '?' character, and format a sequence ++ * of tags for inclusion into an HTML page with embedded applet. ++ */ ++ ++static Bool ++parseParams(const char *request, char *result, int max_bytes) ++{ ++ char param_request[128]; ++ char param_formatted[196]; ++ const char *tail; ++ char *delim_ptr; ++ char *value_str; ++ int cur_bytes, len; ++ ++ result[0] = '\0'; ++ cur_bytes = 0; ++ ++ tail = request; ++ for (;;) { ++ /* Copy individual "name=value" string into a buffer */ ++ delim_ptr = strchr((char *)tail, '&'); ++ if (delim_ptr == NULL) { ++ if (strlen(tail) >= sizeof(param_request)) { ++ return FALSE; ++ } ++ strcpy(param_request, tail); ++ } else { ++ len = delim_ptr - tail; ++ if (len >= sizeof(param_request)) { ++ return FALSE; ++ } ++ memcpy(param_request, tail, len); ++ param_request[len] = '\0'; ++ } ++ ++ /* Split the request into parameter name and value */ ++ value_str = strchr(¶m_request[1], '='); ++ if (value_str == NULL) { ++ return FALSE; ++ } ++ *value_str++ = '\0'; ++ if (strlen(value_str) == 0) { ++ return FALSE; ++ } ++ ++ /* Validate both parameter name and value */ ++ if (!validateString(param_request) || !validateString(value_str)) { ++ return FALSE; ++ } ++ ++ /* Prepare HTML-formatted representation of the name=value pair */ ++ len = sprintf(param_formatted, ++ "\n", ++ param_request, value_str); ++ if (cur_bytes + len + 1 > max_bytes) { ++ return FALSE; ++ } ++ strcat(result, param_formatted); ++ cur_bytes += len; ++ ++ /* Go to the next parameter */ ++ if (delim_ptr == NULL) { ++ break; ++ } ++ tail = delim_ptr + 1; ++ } ++ return TRUE; ++} ++ ++/* ++ * Check if the string consists only of alphanumeric characters, '+' ++ * signs, underscores, and dots. Replace all '+' signs with spaces. ++ */ ++ ++static Bool ++validateString(char *str) ++{ ++ char *ptr; ++ ++ for (ptr = str; *ptr != '\0'; ptr++) { ++ if (!isalnum(*ptr) && *ptr != '_' && *ptr != '.') { ++ if (*ptr == '+') { ++ *ptr = ' '; ++ } else { ++ return FALSE; ++ } ++ } ++ } ++ return TRUE; ++} ++ +diff -pNur xorg-server-1.4.orig/hw/vnc/init.c xorg-server-1.4/hw/vnc/init.c +--- xorg-server-1.4.orig/hw/vnc/init.c 1969-12-31 16:00:00.000000000 -0800 ++++ xorg-server-1.4/hw/vnc/init.c 2007-09-06 16:09:45.000000000 -0700 +@@ -0,0 +1,1075 @@ ++/* ++ * init.c ++ * ++ * Modified for XFree86 4.x by Alan Hourihane ++ */ ++ ++/* ++ * 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. ++ ++*/ ++ ++/* Use ``#define CORBA'' to enable CORBA control interface */ ++ ++/* XXX this definition should probably go elsewhere */ ++#ifdef HAVE_DIX_CONFIG_H ++#include ++#endif ++ ++#ifndef XVNCRELEASE ++#define XVNCRELEASE "X.org/xf4vnc custom version" ++#endif ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#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 "mibstore.h" ++#include "colormapst.h" ++#include "gcstruct.h" ++#include "input.h" ++#include "mipointer.h" ++#include "dixstruct.h" ++#include ++#include ++#include ++#include "dix.h" ++#include "micmap.h" ++#include "rfb.h" ++ ++#ifdef CORBA ++#include ++#endif ++ ++#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 ++ ++static unsigned long VNCGeneration = 0; ++rfbScreenInfo rfbScreen; ++int rfbGCIndex; ++extern char dispatchExceptionAtReset; ++ ++extern void VncExtensionInit(void); ++ ++static Bool initOutputCalled = FALSE; ++static Bool noCursor = FALSE; ++char *desktopName = "x11"; ++ ++char rfbThisHost[256]; ++ ++Atom VNC_LAST_CLIENT_ID; ++Atom VNC_CONNECT; ++ ++#if 0 ++static HWEventQueueType alwaysCheckForInput[2] = { 0, 1 }; ++static HWEventQueueType *mieqCheckForInput[2]; ++#endif ++ ++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(void); ++static unsigned char *rfbAllocateFramebufferMemory(rfbScreenInfoPtr prfb); ++static Bool rfbCursorOffScreen(ScreenPtr *ppScreen, int *x, int *y); ++static void rfbCrossScreen(ScreenPtr pScreen, Bool entering); ++ ++ ++ ++static void ++PointerWarpCursor(ScreenPtr pScreen, int x, int y) ++{ ++#if 0 ++ DeviceIntPtr pDev = NULL; ++ miPointerSetPosition(pDev, &x, &y, GetTimeInMillis()); ++#endif ++} ++ ++ ++static miPointerScreenFuncRec rfbPointerCursorFuncs = { ++ rfbCursorOffScreen, ++ rfbCrossScreen, ++ PointerWarpCursor, ++ NULL/*dmxeqEnqueue*/, ++ NULL/*dmxeqSwitchScreen*/ ++}; ++ ++ ++int inetdSock = -1; ++static char inetdDisplayNumStr[10]; ++ ++ ++void ++DDXRingBell(int volume, int pitch, int duration) ++{ ++ /* NO-OP - stub to solve link problem */ ++} ++ ++ ++/* ++ * 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; ++{ ++ VNCSCREENPTR(screenInfo.screens[i]); ++ static Bool firstTime = TRUE; ++ ++ if (firstTime) ++ { ++ pVNC->width = RFB_DEFAULT_WIDTH; ++ pVNC->height = RFB_DEFAULT_HEIGHT; ++ pVNC->depth = RFB_DEFAULT_DEPTH; ++ pVNC->blackPixel = RFB_DEFAULT_BLACKPIXEL; ++ pVNC->whitePixel = RFB_DEFAULT_WHITEPIXEL; ++ pVNC->pfbMemory = NULL; ++ pVNC->httpPort = 0; ++ pVNC->httpDir = NULL; ++ pVNC->rfbAuthPasswdFile = NULL; ++ pVNC->udpPort = 0; ++ pVNC->rfbPort = 0; ++ pVNC->rdpPort = 3389; ++ noCursor = FALSE; ++ pVNC->loginAuthEnabled = FALSE; ++ pVNC->rfbAlwaysShared = FALSE; ++ pVNC->rfbNeverShared = FALSE; ++ pVNC->rfbDontDisconnect = FALSE; ++ pVNC->rfbViewOnly = FALSE; ++ ++ gethostname(rfbThisHost, 255); ++ pVNC->interface.s_addr = htonl (INADDR_ANY); ++ firstTime = FALSE; ++ } ++ ++ if (strcmp (argv[i], "-geometry") == 0) /* -geometry WxH */ ++ { ++ if (i + 1 >= argc) UseMsg(); ++ if (sscanf(argv[i+1],"%dx%d", ++ &pVNC->width,&pVNC->height) != 2) { ++ ErrorF("Invalid geometry %s\n", argv[i+1]); ++ UseMsg(); ++ } ++#ifdef CORBA ++ screenWidth= pVNC->width; ++ screenHeight= pVNC->height; ++#endif ++ return 2; ++ } ++ ++ if (strcmp (argv[i], "-depth") == 0) /* -depth D */ ++ { ++ if (i + 1 >= argc) UseMsg(); ++ pVNC->depth = atoi(argv[i+1]); ++#ifdef CORBA ++ screenDepth= pVNC->depth; ++#endif ++ return 2; ++ } ++ ++ if (strcmp (argv[i], "-pixelformat") == 0) { ++ if (i + 1 >= argc) UseMsg(); ++ if (sscanf(argv[i+1], "%3s", primaryOrder) < 1) { ++ ErrorF("Invalid pixel format %s\n", argv[i+1]); ++ UseMsg(); ++ } ++ ++ return 2; ++ } ++ ++ if (strcmp (argv[i], "-blackpixel") == 0) { /* -blackpixel n */ ++ if (i + 1 >= argc) UseMsg(); ++ pVNC->blackPixel = atoi(argv[i+1]); ++ return 2; ++ } ++ ++ if (strcmp (argv[i], "-whitepixel") == 0) { /* -whitepixel n */ ++ if (i + 1 >= argc) UseMsg(); ++ pVNC->whitePixel = atoi(argv[i+1]); ++ return 2; ++ } ++ ++ if (strcmp(argv[i], "-udpinputport") == 0) { /* -udpinputport port */ ++ if (i + 1 >= argc) UseMsg(); ++ pVNC->udpPort = atoi(argv[i+1]); ++ return 2; ++ } ++ ++ if (strcmp(argv[i], "-rfbport") == 0) { /* -rfbport port */ ++ if (i + 1 >= argc) UseMsg(); ++ pVNC->rfbPort = atoi(argv[i+1]); ++ return 2; ++ } ++ ++ if (strcmp(argv[i], "-rfbwait") == 0) { /* -rfbwait ms */ ++ if (i + 1 >= argc) UseMsg(); ++ rfbMaxClientWait = atoi(argv[i+1]); ++ return 2; ++ } ++ ++ if (strcmp(argv[i], "-nocursor") == 0) { ++ noCursor = TRUE; ++ return 1; ++ } ++ ++ if (strcmp(argv[i], "-rfbauth") == 0) { /* -rfbauth passwd-file */ ++ if (i + 1 >= argc) UseMsg(); ++ pVNC->rfbAuthPasswdFile = argv[i+1]; ++ return 2; ++ } ++ ++ if (strcmp(argv[i], "-loginauth") == 0) { ++ if (geteuid() == 0) { ++ /* Only when run as root! */ ++ pVNC->loginAuthEnabled = TRUE; ++ } ++ return 1; ++ } ++ ++ if (strcmp(argv[i], "-httpd") == 0) { ++ if (i + 1 >= argc) UseMsg(); ++ pVNC->httpDir = argv[i+1]; ++ return 2; ++ } ++ ++ if (strcmp(argv[i], "-httpport") == 0) { ++ if (i + 1 >= argc) UseMsg(); ++ pVNC->httpPort = atoi(argv[i+1]); ++ return 2; ++ } ++ ++ if (strcmp(argv[i], "-deferupdate") == 0) { /* -deferupdate ms */ ++ if (i + 1 >= argc) UseMsg(); ++ rfbDeferUpdateTime = atoi(argv[i+1]); ++ return 2; ++ } ++ ++ if (strcmp(argv[i], "-economictranslate") == 0) { ++ rfbEconomicTranslate = TRUE; ++ return 1; ++ } ++ ++ if (strcmp(argv[i], "-lazytight") == 0) { ++ rfbTightDisableGradient = TRUE; ++ return 1; ++ } ++ ++ if (strcmp(argv[i], "-desktop") == 0) { /* -desktop desktop-name */ ++ if (i + 1 >= argc) UseMsg(); ++ desktopName = argv[i+1]; ++ return 2; ++ } ++ ++#if 0 /* not deemed useful on standalone server - leave for completeness */ ++ if (strcmp(argv[i], "-useraccept") == 0) { ++ pVNC->rfbUserAccept = TRUE; ++ return 1; ++ } ++#endif ++ ++ if (strcmp(argv[i], "-alwaysshared") == 0) { ++ pVNC->rfbAlwaysShared = TRUE; ++ return 1; ++ } ++ ++ if (strcmp(argv[i], "-nevershared") == 0) { ++ pVNC->rfbNeverShared = TRUE; ++ return 1; ++ } ++ ++ if (strcmp(argv[i], "-dontdisconnect") == 0) { ++ pVNC->rfbDontDisconnect = TRUE; ++ return 1; ++ } ++ ++ /* Run server in view-only mode - Ehud Karni SW */ ++ if (strcmp(argv[i], "-viewonly") == 0) { ++ pVNC->rfbViewOnly = TRUE; ++ return 1; ++ } ++ ++ if (strcmp(argv[i], "-localhost") == 0) { ++ pVNC->interface.s_addr = htonl (INADDR_LOOPBACK); ++ return 1; ++ } ++ ++ if (strcmp(argv[i], "-interface") == 0) { /* -interface ipaddr */ ++ struct in_addr got; ++ unsigned long octet; ++ char *p, *end; ++ int q; ++ got.s_addr = 0; ++ if (i + 1 >= argc) { ++ UseMsg(); ++ return 2; ++ } ++ if (pVNC->interface.s_addr != htonl (INADDR_ANY)) { ++ /* Already set (-localhost?). */ ++ return 2; ++ } ++ p = argv[i + 1]; ++ for (q = 0; q < 4; q++) { ++ octet = strtoul (p, &end, 10); ++ if (p == end || octet > 255) { ++ UseMsg (); ++ return 2; ++ } ++ if ((q < 3 && *end != '.') || ++ (q == 3 && *end != '\0')) { ++ UseMsg (); ++ return 2; ++ } ++ got.s_addr = (got.s_addr << 8) | octet; ++ p = end + 1; ++ } ++ pVNC->interface.s_addr = htonl (got.s_addr); ++ return 2; ++ } ++ ++ if (strcmp(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 (strcmp(argv[i], "-version") == 0) { ++ ErrorF("Xvnc version %s\n", XVNCRELEASE); ++ exit(0); ++ } ++ ++ 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 (FIXME - but we only ever have one), ++ * and in turn this will call rfbScreenInit. ++ */ ++ ++/* Common pixmap formats */ ++ ++static PixmapFormatRec formats[MAXFORMATS] = { ++ { 1, 1, BITMAP_SCANLINE_PAD }, ++ { 4, 8, BITMAP_SCANLINE_PAD }, ++ { 8, 8, BITMAP_SCANLINE_PAD }, ++ { 15, 16, BITMAP_SCANLINE_PAD }, ++ { 16, 16, BITMAP_SCANLINE_PAD }, ++ { 24, 32, BITMAP_SCANLINE_PAD }, ++#ifdef RENDER ++ { 32, 32, BITMAP_SCANLINE_PAD }, ++#endif ++}; ++#ifdef RENDER ++static int numFormats = 7; ++#else ++static int numFormats = 6; ++#endif ++ ++void ++InitOutput(screenInfo, argc, argv) ++ ScreenInfo *screenInfo; ++ int argc; ++ char **argv; ++{ ++ int i; ++ initOutputCalled = TRUE; ++ ++ rfbLog("Xvnc version %s\n", XVNCRELEASE); ++ rfbLog("Copyright (C) 2001-2004 Alan Hourihane.\n"); ++ rfbLog("Copyright (C) 2000-2004 Constantin Kaplinsky\n"); ++ rfbLog("Copyright (C) 1999 AT&T Laboratories Cambridge\n"); ++ rfbLog("All Rights Reserved.\n"); ++ rfbLog("See http://www.tightvnc.com/ for information on TightVNC\n"); ++ rfbLog("See http://xf4vnc.sf.net for xf4vnc-specific information\n"); ++ rfbLog("Desktop name '%s' (%s:%s)\n",desktopName,rfbThisHost,display); ++ rfbLog("Protocol versions supported: %d.%d, %d.%d\n", ++ rfbProtocolMajorVersion, rfbProtocolMinorVersion, ++ rfbProtocolMajorVersion, rfbProtocolFallbackMinorVersion); ++ ++ VNC_LAST_CLIENT_ID = MakeAtom("VNC_LAST_CLIENT_ID", ++ strlen("VNC_LAST_CLIENT_ID"), TRUE); ++ VNC_CONNECT = MakeAtom("VNC_CONNECT", strlen("VNC_CONNECT"), TRUE); ++ ++ /* 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 = numFormats; ++ for (i = 0; i < numFormats; i++) ++ screenInfo->formats[i] = formats[i]; ++ ++ rfbGCIndex = AllocateGCPrivateIndex(); ++ if (rfbGCIndex < 0) { ++ FatalError("InitOutput: AllocateGCPrivateIndex failed\n"); ++ } ++ ++ /* initialize screen */ ++ ++ if (AddScreen(rfbScreenInit, argc, argv) == -1) { ++ FatalError("Couldn't add screen"); ++ } ++ ++#ifdef CORBA ++ initialiseCORBA(argc, argv, desktopName); ++#endif ++} ++ ++static void ++rfbWakeupHandler ( ++ int i, ++ pointer blockData, ++ unsigned long err, ++ pointer pReadmask ++){ ++ ScreenPtr pScreen = screenInfo.screens[i]; ++ VNCSCREENPTR(pScreen); ++ int e = (int)err; ++ ++ if (e < 0) ++ goto SKIPME; ++ ++ rfbRootPropertyChange(pScreen); ++ ++#if XFREE86VNC ++ if (pScrn->vtSema) { ++ rfbCheckFds(pScreen); ++ httpCheckFds(pScreen); ++#if 0 ++ rdpCheckFds(pScreen); ++#endif ++#ifdef CORBA ++ corbaCheckFds(); ++#endif ++ } else { ++ rfbCheckFds(pScreen); ++#if 0 ++ rdpCheckFds(pScreen); ++#endif ++ } ++#else ++ rfbCheckFds(pScreen); ++ httpCheckFds(pScreen); ++#if 0 ++ rdpCheckFds(pScreen); ++#endif ++#ifdef CORBA ++ corbaCheckFds(); ++#endif ++#endif ++ ++SKIPME: ++ ++ pScreen->WakeupHandler = pVNC->WakeupHandler; ++ (*pScreen->WakeupHandler) (i, blockData, err, pReadmask); ++ pScreen->WakeupHandler = rfbWakeupHandler; ++} ++ ++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; ++ unsigned char *pbits; ++ VisualPtr vis; ++#ifdef RENDER ++ PictureScreenPtr ps; ++#endif ++ ++ if (VNCGeneration != serverGeneration) { ++ VncExtensionInit(); ++ VNCGeneration = serverGeneration; ++ } ++ ++ if (monitorResolution != 0) { ++ dpix = monitorResolution; ++ dpiy = monitorResolution; ++ } ++ ++ prfb->rfbAuthTries = 0; ++ prfb->rfbAuthTooManyTries = FALSE; ++ prfb->rfbUserAccept = FALSE; ++ prfb->udpSockConnected = FALSE; ++ prfb->timer = NULL; ++ prfb->httpListenSock = -1; ++ prfb->httpSock = -1; ++ prfb->rfbListenSock = -1; ++ prfb->rdpListenSock = -1; ++ prfb->paddedWidthInBytes = PixmapBytePad(prfb->width, prfb->depth); ++ prfb->bitsPerPixel = rfbBitsPerPixel(prfb->depth); ++ pbits = rfbAllocateFramebufferMemory(prfb); ++ if (!pbits) return FALSE; ++ ++ miClearVisualTypes(); ++ ++ if (defaultColorVisualClass == -1) ++ defaultColorVisualClass = TrueColor; ++ ++ if (!miSetVisualTypes(prfb->depth, miGetDefaultVisualMask(prfb->depth), 8, ++ defaultColorVisualClass) ) ++ return FALSE; ++ ++ miSetPixmapDepths(); ++ ++ switch (prfb->bitsPerPixel) ++ { ++ case 8: ++ ret = fbScreenInit(pScreen, pbits, prfb->width, prfb->height, ++ dpix, dpiy, prfb->paddedWidthInBytes, 8); ++ break; ++ case 16: ++ ret = fbScreenInit(pScreen, pbits, prfb->width, prfb->height, ++ dpix, dpiy, prfb->paddedWidthInBytes / 2, 16); ++ if (prfb->depth == 15) { ++ blueBits = 5; greenBits = 5; redBits = 5; ++ } else { ++ blueBits = 5; greenBits = 6; redBits = 5; ++ } ++ break; ++ case 32: ++ ret = fbScreenInit(pScreen, pbits, prfb->width, prfb->height, ++ dpix, dpiy, prfb->paddedWidthInBytes / 4, 32); ++ blueBits = 8; greenBits = 8; redBits = 8; ++ break; ++ default: ++ return FALSE; ++ } ++ ++ if (!ret) return FALSE; ++ ++ miInitializeBackingStore(pScreen); ++ ++ if (prfb->bitsPerPixel > 8) { ++ if (strcasecmp(primaryOrder, "bgr") == 0) { ++ rfbLog("BGR format %d %d %d\n", blueBits, greenBits, redBits); ++ vis = pScreen->visuals + pScreen->numVisuals; ++ while (--vis >= pScreen->visuals) { ++ if ((vis->class | DynamicClass) == DirectColor) { ++ vis->offsetRed = 0; ++ vis->redMask = (1 << redBits) - 1; ++ vis->offsetGreen = redBits; ++ vis->greenMask = ((1 << greenBits) - 1) << vis->offsetGreen; ++ vis->offsetBlue = redBits + greenBits; ++ vis->blueMask = ((1 << blueBits) - 1) << vis->offsetBlue; ++ } ++ } ++ } else { ++ rfbLog("RGB format %d %d %d\n", blueBits, greenBits, redBits); ++ vis = pScreen->visuals + pScreen->numVisuals; ++ while (--vis >= pScreen->visuals) { ++ if ((vis->class | DynamicClass) == DirectColor) { ++ vis->offsetBlue = 0; ++ vis->blueMask = (1 << blueBits) - 1; ++ vis->offsetGreen = blueBits; ++ vis->greenMask = ((1 << greenBits) - 1) << vis->offsetGreen; ++ vis->offsetRed = blueBits + greenBits; ++ vis->redMask = ((1 << redBits) - 1) << vis->offsetRed; ++ } ++ } ++ } ++ } ++ ++ if (prfb->bitsPerPixel > 4) ++ fbPictureInit(pScreen, 0, 0); ++ ++ if (!AllocateGCPrivate(pScreen, rfbGCIndex, sizeof(rfbGCRec))) { ++ FatalError("rfbScreenInit: AllocateGCPrivate failed\n"); ++ } ++ ++ prfb->cursorIsDrawn = FALSE; ++ prfb->dontSendFramebufferUpdate = FALSE; ++ ++ prfb->CloseScreen = pScreen->CloseScreen; ++ prfb->WakeupHandler = pScreen->WakeupHandler; ++ prfb->CreateGC = pScreen->CreateGC; ++ prfb->PaintWindowBackground = pScreen->PaintWindowBackground; ++ prfb->PaintWindowBorder = pScreen->PaintWindowBorder; ++ prfb->CopyWindow = pScreen->CopyWindow; ++ prfb->ClearToBackground = pScreen->ClearToBackground; ++ prfb->RestoreAreas = pScreen->RestoreAreas; ++#ifdef CHROMIUM ++ prfb->RealizeWindow = pScreen->RealizeWindow; ++ prfb->UnrealizeWindow = pScreen->UnrealizeWindow; ++ prfb->DestroyWindow = pScreen->DestroyWindow; ++ prfb->PositionWindow = pScreen->PositionWindow; ++ prfb->ResizeWindow = pScreen->ResizeWindow; ++ prfb->ClipNotify = pScreen->ClipNotify; ++#endif ++#ifdef RENDER ++ ps = GetPictureScreenIfSet(pScreen); ++ if (ps) ++ prfb->Composite = ps->Composite; ++#endif ++ pScreen->CloseScreen = rfbCloseScreen; ++ pScreen->WakeupHandler = rfbWakeupHandler; ++ pScreen->CreateGC = rfbCreateGC; ++ pScreen->PaintWindowBackground = rfbPaintWindowBackground; ++ pScreen->PaintWindowBorder = rfbPaintWindowBorder; ++ pScreen->CopyWindow = rfbCopyWindow; ++ pScreen->ClearToBackground = rfbClearToBackground; ++ pScreen->RestoreAreas = rfbRestoreAreas; ++#ifdef CHROMIUM ++ pScreen->RealizeWindow = rfbRealizeWindow; ++ pScreen->UnrealizeWindow = rfbUnrealizeWindow; ++ pScreen->DestroyWindow = rfbDestroyWindow; ++ pScreen->PositionWindow = rfbPositionWindow; ++ pScreen->ResizeWindow = rfbResizeWindow; ++ pScreen->ClipNotify = rfbClipNotify; ++#endif ++#ifdef RENDER ++ if (ps) ++ ps->Composite = rfbComposite; ++#endif ++ ++ pScreen->InstallColormap = rfbInstallColormap; ++ pScreen->UninstallColormap = rfbUninstallColormap; ++ pScreen->ListInstalledColormaps = rfbListInstalledColormaps; ++ pScreen->StoreColors = rfbStoreColors; ++ ++ pScreen->SaveScreen = (SaveScreenProcPtr)rfbAlwaysTrue; ++ ++ rfbDCInitialize(pScreen, &rfbPointerCursorFuncs); ++ ++ if (noCursor) { ++ pScreen->DisplayCursor = (DisplayCursorProcPtr)rfbAlwaysTrue; ++ prfb->cursorIsDrawn = TRUE; ++ } ++ ++ pScreen->blackPixel = prfb->blackPixel; ++ pScreen->whitePixel = prfb->whitePixel; ++ ++ prfb->rfbServerFormat.bitsPerPixel = prfb->bitsPerPixel; ++ prfb->rfbServerFormat.depth = prfb->depth; ++ prfb->rfbServerFormat.bigEndian = !(*(char *)&rfbEndianTest); ++ ++ /* Find the root visual and set the server format */ ++ for (vis = pScreen->visuals; vis->vid != pScreen->rootVisual; vis++) ++ ; ++ prfb->rfbServerFormat.trueColour = (vis->class == TrueColor); ++ ++ if ( (vis->class == TrueColor) || (vis->class == DirectColor) ) { ++ prfb->rfbServerFormat.redMax = vis->redMask >> vis->offsetRed; ++ prfb->rfbServerFormat.greenMax = vis->greenMask >> vis->offsetGreen; ++ prfb->rfbServerFormat.blueMax = vis->blueMask >> vis->offsetBlue; ++ prfb->rfbServerFormat.redShift = vis->offsetRed; ++ prfb->rfbServerFormat.greenShift = vis->offsetGreen; ++ prfb->rfbServerFormat.blueShift = vis->offsetBlue; ++ } else { ++ prfb->rfbServerFormat.redMax ++ = prfb->rfbServerFormat.greenMax ++ = prfb->rfbServerFormat.blueMax = 0; ++ prfb->rfbServerFormat.redShift ++ = prfb->rfbServerFormat.greenShift ++ = prfb->rfbServerFormat.blueShift = 0; ++ } ++ ++ ret = fbCreateDefColormap(pScreen); ++ ++ rfbInitSockets(pScreen); ++#if 0 ++ rdpInitSockets(pScreen); ++#endif ++ if (inetdSock == -1) ++ httpInitSockets(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); ++ ++ mieqInit(); ++ ++#if 0 ++ mieqCheckForInput[0] = checkForInput[0]; ++ mieqCheckForInput[1] = checkForInput[1]; ++ SetInputCheck(&alwaysCheckForInput[0], &alwaysCheckForInput[1]); ++#endif ++} ++ ++ ++static int ++rfbKeybdProc(pDevice, onoff) ++ DeviceIntPtr pDevice; ++ int onoff; ++{ ++ KeySymsRec keySyms; ++ CARD8 modMap[MAP_LENGTH]; ++ DevicePtr pDev = (DevicePtr)pDevice; ++ ++ switch (onoff) ++ { ++ case DEVICE_INIT: ++ vncSetKeyboardDevice(pDevice); ++ 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, ++ GetMotionHistory, ++ PtrDeviceControl, ++ GetMaximumEventsNum(), 2 /* numAxes */); ++ vncSetPointerDevice(pDevice); ++ 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(unsigned int key, DeviceIntPtr pDev) ++{ ++ return TRUE; ++} ++ ++ ++void ++ProcessInputEvents(void) ++{ ++#if 0 ++ if (*mieqCheckForInput[0] != *mieqCheckForInput[1]) { ++#endif ++ mieqProcessInputEvents(); ++#if 0 ++ } ++#endif ++} ++ ++ ++static Bool CheckDisplayNumber(int n) ++{ ++ char fname[32]; ++ int sock; ++ struct sockaddr_in addr; ++ ++ sock = socket(AF_INET, SOCK_STREAM, 0); ++ ++ memset(&addr, 0, sizeof(addr)); ++ 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; ++ ++ return TRUE; ++} ++ ++static Bool ++rfbAlwaysTrue(void) ++{ ++ return TRUE; ++} ++ ++ ++static unsigned char * ++rfbAllocateFramebufferMemory(prfb) ++ rfbScreenInfoPtr prfb; ++{ ++ if (prfb->pfbMemory) return prfb->pfbMemory; /* already done */ ++ ++ prfb->sizeInBytes = (prfb->paddedWidthInBytes * prfb->height); ++ ++ prfb->pfbMemory = (unsigned 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; ++{ ++} ++ ++void ++ddxGiveUp() ++{ ++ Xfree(rfbScreen.pfbMemory); ++ if (initOutputCalled) { ++ char unixSocketName[32]; ++ sprintf(unixSocketName,"/tmp/.X11-unix/X%s",display); ++ unlink(unixSocketName); ++#ifdef CORBA ++ shutdownCORBA(); ++#endif ++ } ++} ++ ++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("-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("-udpinputport port UDP port for keyboard/pointer data\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("-loginauth use login-style Unix authentication\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("-lazytight disable \"gradient\" filter in tight " ++ "encoding\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" ++ " to the vnc ports. Use -nolisten tcp to disable\n" ++ " remote X clients as well.\n"); ++ ErrorF("-viewonly let clients only view the desktop\n"); ++ ErrorF("-interface ipaddr only bind to specified interface " ++ "address\n"); ++ ErrorF("-inetd Xvnc is launched by inetd\n"); ++ exit(1); ++} ++ ++ ++void ddxInitGlobals(void) ++{ ++ /* dummy function called by InitGlobals in os/utils.c */ ++} ++ ++ ++/* ++ * 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 %H:%M:%S ", localtime(&clock)); ++ fprintf(stderr, buf); ++ ++ vfprintf(stderr, format, args); ++ fflush(stderr); ++ ++ va_end(args); ++} ++ ++void rfbLogPerror(char *str) ++{ ++ rfbLog(""); ++ perror(str); ++} +diff -pNur xorg-server-1.4.orig/hw/vnc/kbdptr.c xorg-server-1.4/hw/vnc/kbdptr.c +--- xorg-server-1.4.orig/hw/vnc/kbdptr.c 1969-12-31 16:00:00.000000000 -0800 ++++ xorg-server-1.4/hw/vnc/kbdptr.c 2007-09-06 16:09:45.000000000 -0700 +@@ -0,0 +1,458 @@ ++/* ++ * kbdptr.c - deal with keyboard and pointer device over TCP & UDP. ++ * ++ * Modified for XFree86 4.x by Alan Hourihane ++ * ++ */ ++ ++/* ++ * 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. ++ */ ++#ifdef HAVE_DIX_CONFIG_H ++#include ++#endif ++ ++ ++#include "rfb.h" ++#include "X11/X.h" ++#define NEED_EVENTS ++#include "X11/Xproto.h" ++#include "inputstr.h" ++#define XK_CYRILLIC ++#include ++#include ++#include "mi.h" ++#include "mipointer.h" ++#include "keyboard.h" ++ ++#ifdef DMXVNC ++#include "dmxinput.h" ++#endif ++ ++#define KEY_IS_PRESSED(keycode) \ ++ (kbdDevice->key->down[(keycode) >> 3] & (1 << ((keycode) & 7))) ++ ++static void vncXConvertCase(KeySym sym, KeySym *lower, KeySym *upper); ++ ++static DeviceIntPtr ptrDevice = NULL, kbdDevice = NULL; ++ ++ ++void ++vncSetKeyboardDevice(DeviceIntPtr kbd) ++{ ++ if (kbdDevice && kbd) ++ return; /* set once */ ++ kbdDevice = kbd; ++} ++ ++ ++void ++vncSetPointerDevice(DeviceIntPtr ptr) ++{ ++ if (ptrDevice && ptr) ++ return; /* set once */ ++ ptrDevice = ptr; ++} ++ ++ ++#ifndef DMXVNC ++static void ++EnqueueMotion(DeviceIntPtr ptrDev, int x, int y) ++{ ++ xEvent *events = (xEvent*) calloc(sizeof(xEvent), GetMaximumEventsNum()); ++ int detail = 0, valuators[2], nevents, i; ++ valuators[0] = x; ++ valuators[1] = y; ++ if (!ptrDev) { ++ ErrorF("VNC: In EnqueueMotion() ptrDev=NULL\n"); ++ return; ++ } ++ nevents = GetPointerEvents(events, ptrDev, MotionNotify, detail, ++ POINTER_ABSOLUTE, 0, 2, valuators); ++ for (i = 0; i < nevents; i++) ++ mieqEnqueue(ptrDev, events + i); ++ free(events); ++} ++#endif ++ ++ ++static void ++EnqueueButton(DeviceIntPtr ptrDev, int type, int detail) ++{ ++ xEvent *events = (xEvent*) calloc(sizeof(xEvent), GetMaximumEventsNum()); ++ int nevents, i; ++ if (!ptrDev) { ++ ErrorF("VNC: In EnqueueButton() ptrDev=NULL\n"); ++ return; ++ } ++ nevents = GetPointerEvents(events, ptrDev, type, detail, ++ POINTER_ABSOLUTE, 0, 0, NULL/*valuators*/); ++ for (i = 0; i < nevents; i++) ++ mieqEnqueue(ptrDev, events + i); ++ free(events); ++} ++ ++ ++static void ++EnqueueKey(DeviceIntPtr kbdDev, int type, int detail) ++{ ++ xEvent *events = (xEvent*) calloc(sizeof(xEvent), GetMaximumEventsNum()); ++ int nevents, i; ++ if (!kbdDev) { ++ ErrorF("VNC: In EnqueueKey() kbdDev=NULL\n"); ++ return; ++ } ++ nevents = GetKeyboardEvents(events, kbdDev, type, detail); ++ for (i = 0; i < nevents; i++) ++ mieqEnqueue(kbdDev, events + i); ++ free(events); ++} ++ ++ ++/* ++ * Called when the rfbserver receives a rfbKeyEvent event from a client. ++ * Put an X keyboard event into the event queue. ++ */ ++void ++KbdAddEvent(Bool down, KeySym keySym, rfbClientPtr cl) ++{ ++ const int type = down ? KeyPress : KeyRelease; ++ KeySymsPtr keySyms; ++ int i; ++ int keyCode = 0; ++ int freeIndex = -1; ++ Bool fakeShiftPress = FALSE; ++ Bool fakeShiftLRelease = FALSE; ++ Bool fakeShiftRRelease = FALSE; ++ Bool shiftMustBeReleased = FALSE; ++ Bool shiftMustBePressed = FALSE; ++ ++ if (!kbdDevice) ++ return; ++ ++ keySyms = &kbdDevice->key->curKeySyms; ++ ++#ifdef CORBA ++ if (cl) { ++ CARD32 clientId = cl->sock; ++ ChangeWindowProperty(WindowTable[0], VNC_LAST_CLIENT_ID, XA_INTEGER, ++ 32, PropModeReplace, 1, (pointer)&clientId, TRUE); ++ } ++#endif ++ ++ /* NOTE: This is where it gets hairy for XFree86 servers. ++ * I think the best way to deal with this is invent a new protocol ++ * to send over the wire the remote keyboard type and correctly ++ * handle that as XINPUT extension device (we're part of the way ++ * there for that. ++ * ++ * Alan. ++ */ ++#if !XFREE86VNC ++ /* First check if it's one of our predefined keys. If so then we can make ++ some attempt at allowing an xmodmap inside a VNC desktop behave ++ something like you'd expect - e.g. if keys A & B are swapped over and ++ the VNC client sends an A, then map it to a B when generating the X ++ event. We don't attempt to do this for keycodes which we make up on the ++ fly because it's too hard... */ ++ ++ for (i = 0; i < N_PREDEFINED_KEYS * GLYPHS_PER_KEY; i++) { ++ if (keySym == map[i]) { ++ keyCode = MIN_KEY_CODE + i / GLYPHS_PER_KEY; ++ ++ if (map[(i/GLYPHS_PER_KEY) * GLYPHS_PER_KEY + 1] != NoSymbol) { ++ ++ /* this keycode has more than one symbol associated with it, ++ so shift state is important */ ++ ++ if ((i % GLYPHS_PER_KEY) == 0) ++ shiftMustBeReleased = TRUE; ++ else ++ shiftMustBePressed = TRUE; ++ } ++ break; ++ } ++ } ++#endif ++ ++ if (!keyCode) { ++ ++ /* not one of our predefined keys - see if it's in the current keyboard ++ mapping (i.e. we've already allocated an extra keycode for it) */ ++ ++ if (keySyms->mapWidth < 2) { ++ ErrorF("KbdAddEvent: Sanity check failed - Keyboard mapping has " ++ "less than 2 keysyms per keycode (KeySym 0x%x)\n", (int)keySym); ++ return; ++ } ++ ++ for (i = 0; i < NO_OF_KEYS * keySyms->mapWidth; i++) { ++ if (keySym == keySyms->map[i]) { ++ keyCode = MIN_KEY_CODE + i / keySyms->mapWidth; ++ ++ if (keySyms->map[(i / keySyms->mapWidth) ++ * keySyms->mapWidth + 1] != NoSymbol) { ++ ++ /* this keycode has more than one symbol associated with ++ it, so shift state is important */ ++ ++ if ((i % keySyms->mapWidth) == 0) ++ shiftMustBeReleased = TRUE; ++ else ++ shiftMustBePressed = TRUE; ++ } ++ break; ++ } ++ if ((freeIndex == -1) && (keySyms->map[i] == NoSymbol) ++ && (i % keySyms->mapWidth) == 0) ++ { ++ freeIndex = i; ++ } ++ } ++ } ++ ++ if (!keyCode) { ++ KeySym lower, upper; ++ ++ /* we don't have an existing keycode - make one up on the fly and add ++ it to the keyboard mapping. Thanks to Vlad Harchev for pointing ++ out problems with non-ascii capitalisation. */ ++ ++ if (freeIndex == -1) { ++ ErrorF("KbdAddEvent: ignoring KeySym 0x%x - no free KeyCodes\n", ++ (int)keySym); ++ return; ++ } ++ ++ keyCode = MIN_KEY_CODE + freeIndex / keySyms->mapWidth; ++ ++ vncXConvertCase(keySym, &lower, &upper); ++ ++ if (lower == upper) { ++ keySyms->map[freeIndex] = keySym; ++ ++ } else { ++ keySyms->map[freeIndex] = lower; ++ keySyms->map[freeIndex+1] = upper; ++ ++ if (keySym == lower) ++ shiftMustBeReleased = TRUE; ++ else ++ shiftMustBePressed = TRUE; ++ } ++ ++ SendMappingNotify(MappingKeyboard, keyCode, 1, serverClient); ++ ++ ErrorF("KbdAddEvent: unknown KeySym 0x%x - allocating KeyCode %d\n", ++ (int)keySym, keyCode); ++ } ++ ++ if (down) { ++ if (shiftMustBePressed && !(kbdDevice->key->state & ShiftMask)) { ++ fakeShiftPress = TRUE; ++ EnqueueKey(kbdDevice, KeyPress, SHIFT_L_KEY_CODE); ++ } ++ if (shiftMustBeReleased && (kbdDevice->key->state & ShiftMask)) { ++ if (KEY_IS_PRESSED(SHIFT_L_KEY_CODE)) { ++ fakeShiftLRelease = TRUE; ++ EnqueueKey(kbdDevice, KeyRelease, SHIFT_L_KEY_CODE); ++ } ++ if (KEY_IS_PRESSED(SHIFT_R_KEY_CODE)) { ++ fakeShiftRRelease = TRUE; ++ EnqueueKey(kbdDevice, KeyRelease, SHIFT_R_KEY_CODE); ++ } ++ } ++ } ++ ++ EnqueueKey(kbdDevice, type, keyCode); ++ ++ if (fakeShiftPress) { ++ EnqueueKey(kbdDevice, KeyRelease, SHIFT_L_KEY_CODE); ++ } ++ if (fakeShiftLRelease) { ++ EnqueueKey(kbdDevice, KeyPress, SHIFT_L_KEY_CODE); ++ } ++ if (fakeShiftRRelease) { ++ EnqueueKey(kbdDevice, KeyPress, SHIFT_R_KEY_CODE); ++ } ++} ++ ++ ++/* ++ * Called when the rfbserver receives a rfbPointerEvent event from a client. ++ * Put an X mouse event into the event queue. ++ */ ++void ++PtrAddEvent(int buttonMask, int x, int y, rfbClientPtr cl) ++{ ++ int i; ++ static int oldButtonMask = 0; ++ ++#ifdef CORBA ++ if (cl) { ++ CARD32 clientId = cl->sock; ++ ChangeWindowProperty(WindowTable[0], VNC_LAST_CLIENT_ID, XA_INTEGER, ++ 32, PropModeReplace, 1, (pointer)&clientId, TRUE); ++ } ++#endif ++ ++#ifdef DMXVNC ++ dmxCoreMotion(&ptrDevice->public, x, y, 0, DMX_BLOCK); ++#else ++ EnqueueMotion(ptrDevice, x, y ); ++#endif ++ ++ for (i = 0; i < 5; i++) { ++ if ((buttonMask ^ oldButtonMask) & (1<key->down[i] != 0) { ++ for (j = 0; j < 8; j++) { ++ if (kbdDevice->key->down[i] & (1 << j)) { ++ int detail = (i << 3) | j; ++ EnqueueKey(kbdDevice, KeyRelease, detail); ++ } ++ } ++ } ++ } ++} ++ ++ ++/* copied from Xlib source */ ++ ++static void vncXConvertCase(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; ++ } ++} +diff -pNur xorg-server-1.4.orig/hw/vnc/keyboard.h xorg-server-1.4/hw/vnc/keyboard.h +--- xorg-server-1.4.orig/hw/vnc/keyboard.h 1969-12-31 16:00:00.000000000 -0800 ++++ xorg-server-1.4/hw/vnc/keyboard.h 2007-09-06 16:09:45.000000000 -0700 +@@ -0,0 +1,167 @@ ++/* ++ * Copyright (C) 2002 Alan Hourihane. 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. ++ * ++ * Author: Alan Hourihane ++ */ ++ ++#define MIN_KEY_CODE 8 ++#define MAX_KEY_CODE 255 ++#define NO_OF_KEYS (MAX_KEY_CODE - MIN_KEY_CODE + 1) ++#define GLYPHS_PER_KEY 4 ++ ++#define CONTROL_L_KEY_CODE (MIN_KEY_CODE + 29) ++#define CONTROL_R_KEY_CODE (MIN_KEY_CODE + 101) ++#define SHIFT_L_KEY_CODE (MIN_KEY_CODE + 42) ++#define SHIFT_R_KEY_CODE (MIN_KEY_CODE + 54) ++#define META_L_KEY_CODE (MIN_KEY_CODE + 107) ++#define META_R_KEY_CODE (MIN_KEY_CODE + 108) ++#define ALT_L_KEY_CODE (MIN_KEY_CODE + 56) ++#define ALT_R_KEY_CODE (MIN_KEY_CODE + 105) ++ ++static KeySym map[MAX_KEY_CODE * GLYPHS_PER_KEY] = { ++ /* 0x00 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, ++ /* 0x01 */ XK_Escape, NoSymbol, NoSymbol, NoSymbol, ++ /* 0x02 */ XK_1, XK_exclam, NoSymbol, NoSymbol, ++ /* 0x03 */ XK_2, XK_at, NoSymbol, NoSymbol, ++ /* 0x04 */ XK_3, XK_numbersign, NoSymbol, NoSymbol, ++ /* 0x05 */ XK_4, XK_dollar, NoSymbol, NoSymbol, ++ /* 0x06 */ XK_5, XK_percent, NoSymbol, NoSymbol, ++ /* 0x07 */ XK_6, XK_asciicircum, NoSymbol, NoSymbol, ++ /* 0x08 */ XK_7, XK_ampersand, NoSymbol, NoSymbol, ++ /* 0x09 */ XK_8, XK_asterisk, NoSymbol, NoSymbol, ++ /* 0x0a */ XK_9, XK_parenleft, NoSymbol, NoSymbol, ++ /* 0x0b */ XK_0, XK_parenright, NoSymbol, NoSymbol, ++ /* 0x0c */ XK_minus, XK_underscore, NoSymbol, NoSymbol, ++ /* 0x0d */ XK_equal, XK_plus, NoSymbol, NoSymbol, ++ /* 0x0e */ XK_BackSpace, NoSymbol, NoSymbol, NoSymbol, ++ /* 0x0f */ XK_Tab, XK_ISO_Left_Tab,NoSymbol, NoSymbol, ++ /* 0x10 */ XK_q, XK_Q, NoSymbol, NoSymbol, ++ /* 0x11 */ XK_w, XK_W, NoSymbol, NoSymbol, ++ /* 0x12 */ XK_e, XK_E, NoSymbol, NoSymbol, ++ /* 0x13 */ XK_r, XK_R, NoSymbol, NoSymbol, ++ /* 0x14 */ XK_t, XK_T, NoSymbol, NoSymbol, ++ /* 0x15 */ XK_y, XK_Y, NoSymbol, NoSymbol, ++ /* 0x16 */ XK_u, XK_U, NoSymbol, NoSymbol, ++ /* 0x17 */ XK_i, XK_I, NoSymbol, NoSymbol, ++ /* 0x18 */ XK_o, XK_O, NoSymbol, NoSymbol, ++ /* 0x19 */ XK_p, XK_P, NoSymbol, NoSymbol, ++ /* 0x1a */ XK_bracketleft, XK_braceleft, NoSymbol, NoSymbol, ++ /* 0x1b */ XK_bracketright,XK_braceright, NoSymbol, NoSymbol, ++ /* 0x1c */ XK_Return, NoSymbol, NoSymbol, NoSymbol, ++ /* 0x1d */ XK_Control_L, NoSymbol, NoSymbol, NoSymbol, ++ /* 0x1e */ XK_a, XK_A, NoSymbol, NoSymbol, ++ /* 0x1f */ XK_s, XK_S, NoSymbol, NoSymbol, ++ /* 0x20 */ XK_d, XK_D, NoSymbol, NoSymbol, ++ /* 0x21 */ XK_f, XK_F, NoSymbol, NoSymbol, ++ /* 0x22 */ XK_g, XK_G, NoSymbol, NoSymbol, ++ /* 0x23 */ XK_h, XK_H, NoSymbol, NoSymbol, ++ /* 0x24 */ XK_j, XK_J, NoSymbol, NoSymbol, ++ /* 0x25 */ XK_k, XK_K, NoSymbol, NoSymbol, ++ /* 0x26 */ XK_l, XK_L, NoSymbol, NoSymbol, ++ /* 0x27 */ XK_semicolon, XK_colon, NoSymbol, NoSymbol, ++ /* 0x28 */ XK_quoteright, XK_quotedbl, NoSymbol, NoSymbol, ++ /* 0x29 */ XK_quoteleft, XK_asciitilde, NoSymbol, NoSymbol, ++ /* 0x2a */ XK_Shift_L, NoSymbol, NoSymbol, NoSymbol, ++ /* 0x2b */ XK_backslash, XK_bar, NoSymbol, NoSymbol, ++ /* 0x2c */ XK_z, XK_Z, NoSymbol, NoSymbol, ++ /* 0x2d */ XK_x, XK_X, NoSymbol, NoSymbol, ++ /* 0x2e */ XK_c, XK_C, NoSymbol, NoSymbol, ++ /* 0x2f */ XK_v, XK_V, NoSymbol, NoSymbol, ++ /* 0x30 */ XK_b, XK_B, NoSymbol, NoSymbol, ++ /* 0x31 */ XK_n, XK_N, NoSymbol, NoSymbol, ++ /* 0x32 */ XK_m, XK_M, NoSymbol, NoSymbol, ++ /* 0x33 */ XK_comma, XK_less, NoSymbol, NoSymbol, ++ /* 0x34 */ XK_period, XK_greater, NoSymbol, NoSymbol, ++ /* 0x35 */ XK_slash, XK_question, NoSymbol, NoSymbol, ++ /* 0x36 */ XK_Shift_R, NoSymbol, NoSymbol, NoSymbol, ++ /* 0x37 */ XK_KP_Multiply, NoSymbol, NoSymbol, NoSymbol, ++ /* 0x38 */ XK_Alt_L, XK_Meta_L, NoSymbol, NoSymbol, ++ /* 0x39 */ XK_space, NoSymbol, NoSymbol, NoSymbol, ++ /* 0x3a */ XK_Caps_Lock, NoSymbol, NoSymbol, NoSymbol, ++ /* 0x3b */ XK_F1, NoSymbol, NoSymbol, NoSymbol, ++ /* 0x3c */ XK_F2, NoSymbol, NoSymbol, NoSymbol, ++ /* 0x3d */ XK_F3, NoSymbol, NoSymbol, NoSymbol, ++ /* 0x3e */ XK_F4, NoSymbol, NoSymbol, NoSymbol, ++ /* 0x3f */ XK_F5, NoSymbol, NoSymbol, NoSymbol, ++ /* 0x40 */ XK_F6, NoSymbol, NoSymbol, NoSymbol, ++ /* 0x41 */ XK_F7, NoSymbol, NoSymbol, NoSymbol, ++ /* 0x42 */ XK_F8, NoSymbol, NoSymbol, NoSymbol, ++ /* 0x43 */ XK_F9, NoSymbol, NoSymbol, NoSymbol, ++ /* 0x44 */ XK_F10, NoSymbol, NoSymbol, NoSymbol, ++ /* 0x45 */ XK_Num_Lock, NoSymbol, NoSymbol, NoSymbol, ++ /* 0x46 */ XK_Scroll_Lock, NoSymbol, NoSymbol, NoSymbol, ++ /* 0x47 */ XK_KP_Home, XK_KP_7, NoSymbol, NoSymbol, ++ /* 0x48 */ XK_KP_Up, XK_KP_8, NoSymbol, NoSymbol, ++ /* 0x49 */ XK_KP_Prior, XK_KP_9, NoSymbol, NoSymbol, ++ /* 0x4a */ XK_KP_Subtract, NoSymbol, NoSymbol, NoSymbol, ++ /* 0x4b */ XK_KP_Left, XK_KP_4, NoSymbol, NoSymbol, ++ /* 0x4c */ XK_KP_Begin, XK_KP_5, NoSymbol, NoSymbol, ++ /* 0x4d */ XK_KP_Right, XK_KP_6, NoSymbol, NoSymbol, ++ /* 0x4e */ XK_KP_Add, NoSymbol, NoSymbol, NoSymbol, ++ /* 0x4f */ XK_KP_End, XK_KP_1, NoSymbol, NoSymbol, ++ /* 0x50 */ XK_KP_Down, XK_KP_2, NoSymbol, NoSymbol, ++ /* 0x51 */ XK_KP_Next, XK_KP_3, NoSymbol, NoSymbol, ++ /* 0x52 */ XK_KP_Insert, XK_KP_0, NoSymbol, NoSymbol, ++ /* 0x53 */ XK_KP_Delete, XK_KP_Decimal, NoSymbol, NoSymbol, ++ /* 0x54 */ XK_Sys_Req, NoSymbol, NoSymbol, NoSymbol, ++ /* 0x55 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, ++ /* 0x56 */ XK_less, XK_greater, NoSymbol, NoSymbol, ++ /* 0x57 */ XK_F11, NoSymbol, NoSymbol, NoSymbol, ++ /* 0x58 */ XK_F12, NoSymbol, NoSymbol, NoSymbol, ++ /* 0x59 */ XK_Home, NoSymbol, NoSymbol, NoSymbol, ++ /* 0x5a */ XK_Up, NoSymbol, NoSymbol, NoSymbol, ++ /* 0x5b */ XK_Prior, NoSymbol, NoSymbol, NoSymbol, ++ /* 0x5c */ XK_Left, NoSymbol, NoSymbol, NoSymbol, ++ /* 0x5d */ XK_Begin, NoSymbol, NoSymbol, NoSymbol, ++ /* 0x5e */ XK_Right, NoSymbol, NoSymbol, NoSymbol, ++ /* 0x5f */ XK_End, NoSymbol, NoSymbol, NoSymbol, ++ /* 0x60 */ XK_Down, NoSymbol, NoSymbol, NoSymbol, ++ /* 0x61 */ XK_Next, NoSymbol, NoSymbol, NoSymbol, ++ /* 0x62 */ XK_Insert, NoSymbol, NoSymbol, NoSymbol, ++ /* 0x63 */ XK_Delete, NoSymbol, NoSymbol, NoSymbol, ++ /* 0x64 */ XK_KP_Enter, NoSymbol, NoSymbol, NoSymbol, ++ /* 0x65 */ XK_Control_R, NoSymbol, NoSymbol, NoSymbol, ++ /* 0x66 */ XK_Pause, NoSymbol, NoSymbol, NoSymbol, ++ /* 0x67 */ XK_Print, NoSymbol, NoSymbol, NoSymbol, ++ /* 0x68 */ XK_KP_Divide, NoSymbol, NoSymbol, NoSymbol, ++ /* 0x69 */ XK_Alt_R, XK_Meta_R, NoSymbol, NoSymbol, ++ /* 0x6a */ XK_Break, NoSymbol, NoSymbol, NoSymbol, ++ /* 0x6b */ XK_Meta_L, NoSymbol, NoSymbol, NoSymbol, ++ /* 0x6c */ XK_Meta_R, NoSymbol, NoSymbol, NoSymbol, ++ /* 0x6d */ XK_Menu, NoSymbol, NoSymbol, NoSymbol, ++ /* 0x6e */ XK_F13, NoSymbol, NoSymbol, NoSymbol, ++ /* 0x6f */ XK_F14, NoSymbol, NoSymbol, NoSymbol, ++ /* 0x70 */ XK_F15, NoSymbol, NoSymbol, NoSymbol, ++ /* 0x71 */ XK_F16, NoSymbol, NoSymbol, NoSymbol, ++ /* 0x72 */ XK_F17, NoSymbol, NoSymbol, NoSymbol, ++ /* 0x73 */ XK_backslash, XK_underscore, NoSymbol, NoSymbol, ++ /* 0x74 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, ++ /* 0x75 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, ++ /* 0x76 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, ++ /* 0x77 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, ++ /* 0x78 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, ++ /* 0x79 */ XK_Henkan, XK_Mode_switch, NoSymbol, NoSymbol, ++ /* 0x7a */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, ++ /* 0x7b */ XK_Muhenkan, NoSymbol, NoSymbol, NoSymbol, ++ /* 0x7c */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, ++ /* 0x7d */ XK_backslash, XK_bar, NoSymbol, NoSymbol, ++ /* 0x7e */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, ++ /* 0x7f */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, ++}; ++ ++#define N_PREDEFINED_KEYS (sizeof(map) / (sizeof(KeySym) * GLYPHS_PER_KEY)) +diff -pNur xorg-server-1.4.orig/hw/vnc/LICENCE.TXT xorg-server-1.4/hw/vnc/LICENCE.TXT +--- xorg-server-1.4.orig/hw/vnc/LICENCE.TXT 1969-12-31 16:00:00.000000000 -0800 ++++ xorg-server-1.4/hw/vnc/LICENCE.TXT 2007-09-06 16:09:45.000000000 -0700 +@@ -0,0 +1,340 @@ ++ GNU GENERAL PUBLIC LICENSE ++ Version 2, June 1991 ++ ++ Copyright (C) 1989, 1991 Free Software Foundation, Inc. ++ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA ++ Everyone is permitted to copy and distribute verbatim copies ++ of this license document, but changing it is not allowed. ++ ++ Preamble ++ ++ The licenses for most software are designed to take away your ++freedom to share and change it. By contrast, the GNU General Public ++License is intended to guarantee your freedom to share and change free ++software--to make sure the software is free for all its users. This ++General Public License applies to most of the Free Software ++Foundation's software and to any other program whose authors commit to ++using it. (Some other Free Software Foundation software is covered by ++the GNU Library General Public License instead.) You can apply it to ++your programs, too. ++ ++ When we speak of free software, we are referring to freedom, not ++price. Our General Public Licenses are designed to make sure that you ++have the freedom to distribute copies of free software (and charge for ++this service if you wish), that you receive source code or can get it ++if you want it, that you can change the software or use pieces of it ++in new free programs; and that you know you can do these things. ++ ++ To protect your rights, we need to make restrictions that forbid ++anyone to deny you these rights or to ask you to surrender the rights. ++These restrictions translate to certain responsibilities for you if you ++distribute copies of the software, or if you modify it. ++ ++ For example, if you distribute copies of such a program, whether ++gratis or for a fee, you must give the recipients all the rights that ++you have. You must make sure that they, too, receive or can get the ++source code. And you must show them these terms so they know their ++rights. ++ ++ We protect your rights with two steps: (1) copyright the software, and ++(2) offer you this license which gives you legal permission to copy, ++distribute and/or modify the software. ++ ++ Also, for each author's protection and ours, we want to make certain ++that everyone understands that there is no warranty for this free ++software. If the software is modified by someone else and passed on, we ++want its recipients to know that what they have is not the original, so ++that any problems introduced by others will not reflect on the original ++authors' reputations. ++ ++ Finally, any free program is threatened constantly by software ++patents. We wish to avoid the danger that redistributors of a free ++program will individually obtain patent licenses, in effect making the ++program proprietary. To prevent this, we have made it clear that any ++patent must be licensed for everyone's free use or not licensed at all. ++ ++ The precise terms and conditions for copying, distribution and ++modification follow. ++ ++ GNU GENERAL PUBLIC LICENSE ++ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION ++ ++ 0. This License applies to any program or other work which contains ++a notice placed by the copyright holder saying it may be distributed ++under the terms of this General Public License. The "Program", below, ++refers to any such program or work, and a "work based on the Program" ++means either the Program or any derivative work under copyright law: ++that is to say, a work containing the Program or a portion of it, ++either verbatim or with modifications and/or translated into another ++language. (Hereinafter, translation is included without limitation in ++the term "modification".) Each licensee is addressed as "you". ++ ++Activities other than copying, distribution and modification are not ++covered by this License; they are outside its scope. The act of ++running the Program is not restricted, and the output from the Program ++is covered only if its contents constitute a work based on the ++Program (independent of having been made by running the Program). ++Whether that is true depends on what the Program does. ++ ++ 1. You may copy and distribute verbatim copies of the Program's ++source code as you receive it, in any medium, provided that you ++conspicuously and appropriately publish on each copy an appropriate ++copyright notice and disclaimer of warranty; keep intact all the ++notices that refer to this License and to the absence of any warranty; ++and give any other recipients of the Program a copy of this License ++along with the Program. ++ ++You may charge a fee for the physical act of transferring a copy, and ++you may at your option offer warranty protection in exchange for a fee. ++ ++ 2. You may modify your copy or copies of the Program or any portion ++of it, thus forming a work based on the Program, and copy and ++distribute such modifications or work under the terms of Section 1 ++above, provided that you also meet all of these conditions: ++ ++ a) You must cause the modified files to carry prominent notices ++ stating that you changed the files and the date of any change. ++ ++ b) You must cause any work that you distribute or publish, that in ++ whole or in part contains or is derived from the Program or any ++ part thereof, to be licensed as a whole at no charge to all third ++ parties under the terms of this License. ++ ++ c) If the modified program normally reads commands interactively ++ when run, you must cause it, when started running for such ++ interactive use in the most ordinary way, to print or display an ++ announcement including an appropriate copyright notice and a ++ notice that there is no warranty (or else, saying that you provide ++ a warranty) and that users may redistribute the program under ++ these conditions, and telling the user how to view a copy of this ++ License. (Exception: if the Program itself is interactive but ++ does not normally print such an announcement, your work based on ++ the Program is not required to print an announcement.) ++ ++These requirements apply to the modified work as a whole. If ++identifiable sections of that work are not derived from the Program, ++and can be reasonably considered independent and separate works in ++themselves, then this License, and its terms, do not apply to those ++sections when you distribute them as separate works. But when you ++distribute the same sections as part of a whole which is a work based ++on the Program, the distribution of the whole must be on the terms of ++this License, whose permissions for other licensees extend to the ++entire whole, and thus to each and every part regardless of who wrote it. ++ ++Thus, it is not the intent of this section to claim rights or contest ++your rights to work written entirely by you; rather, the intent is to ++exercise the right to control the distribution of derivative or ++collective works based on the Program. ++ ++In addition, mere aggregation of another work not based on the Program ++with the Program (or with a work based on the Program) on a volume of ++a storage or distribution medium does not bring the other work under ++the scope of this License. ++ ++ 3. You may copy and distribute the Program (or a work based on it, ++under Section 2) in object code or executable form under the terms of ++Sections 1 and 2 above provided that you also do one of the following: ++ ++ a) Accompany it with the complete corresponding machine-readable ++ source code, which must be distributed under the terms of Sections ++ 1 and 2 above on a medium customarily used for software interchange; or, ++ ++ b) Accompany it with a written offer, valid for at least three ++ years, to give any third party, for a charge no more than your ++ cost of physically performing source distribution, a complete ++ machine-readable copy of the corresponding source code, to be ++ distributed under the terms of Sections 1 and 2 above on a medium ++ customarily used for software interchange; or, ++ ++ c) Accompany it with the information you received as to the offer ++ to distribute corresponding source code. (This alternative is ++ allowed only for noncommercial distribution and only if you ++ received the program in object code or executable form with such ++ an offer, in accord with Subsection b above.) ++ ++The source code for a work means the preferred form of the work for ++making modifications to it. For an executable work, complete source ++code means all the source code for all modules it contains, plus any ++associated interface definition files, plus the scripts used to ++control compilation and installation of the executable. However, as a ++special exception, the source code distributed need not include ++anything that is normally distributed (in either source or binary ++form) with the major components (compiler, kernel, and so on) of the ++operating system on which the executable runs, unless that component ++itself accompanies the executable. ++ ++If distribution of executable or object code is made by offering ++access to copy from a designated place, then offering equivalent ++access to copy the source code from the same place counts as ++distribution of the source code, even though third parties are not ++compelled to copy the source along with the object code. ++ ++ 4. You may not copy, modify, sublicense, or distribute the Program ++except as expressly provided under this License. Any attempt ++otherwise to copy, modify, sublicense or distribute the Program is ++void, and will automatically terminate your rights under this License. ++However, parties who have received copies, or rights, from you under ++this License will not have their licenses terminated so long as such ++parties remain in full compliance. ++ ++ 5. You are not required to accept this License, since you have not ++signed it. However, nothing else grants you permission to modify or ++distribute the Program or its derivative works. These actions are ++prohibited by law if you do not accept this License. Therefore, by ++modifying or distributing the Program (or any work based on the ++Program), you indicate your acceptance of this License to do so, and ++all its terms and conditions for copying, distributing or modifying ++the Program or works based on it. ++ ++ 6. Each time you redistribute the Program (or any work based on the ++Program), the recipient automatically receives a license from the ++original licensor to copy, distribute or modify the Program subject to ++these terms and conditions. You may not impose any further ++restrictions on the recipients' exercise of the rights granted herein. ++You are not responsible for enforcing compliance by third parties to ++this License. ++ ++ 7. If, as a consequence of a court judgment or allegation of patent ++infringement or for any other reason (not limited to patent issues), ++conditions are imposed on you (whether by court order, agreement or ++otherwise) that contradict the conditions of this License, they do not ++excuse you from the conditions of this License. If you cannot ++distribute so as to satisfy simultaneously your obligations under this ++License and any other pertinent obligations, then as a consequence you ++may not distribute the Program at all. For example, if a patent ++license would not permit royalty-free redistribution of the Program by ++all those who receive copies directly or indirectly through you, then ++the only way you could satisfy both it and this License would be to ++refrain entirely from distribution of the Program. ++ ++If any portion of this section is held invalid or unenforceable under ++any particular circumstance, the balance of the section is intended to ++apply and the section as a whole is intended to apply in other ++circumstances. ++ ++It is not the purpose of this section to induce you to infringe any ++patents or other property right claims or to contest validity of any ++such claims; this section has the sole purpose of protecting the ++integrity of the free software distribution system, which is ++implemented by public license practices. Many people have made ++generous contributions to the wide range of software distributed ++through that system in reliance on consistent application of that ++system; it is up to the author/donor to decide if he or she is willing ++to distribute software through any other system and a licensee cannot ++impose that choice. ++ ++This section is intended to make thoroughly clear what is believed to ++be a consequence of the rest of this License. ++ ++ 8. If the distribution and/or use of the Program is restricted in ++certain countries either by patents or by copyrighted interfaces, the ++original copyright holder who places the Program under this License ++may add an explicit geographical distribution limitation excluding ++those countries, so that distribution is permitted only in or among ++countries not thus excluded. In such case, this License incorporates ++the limitation as if written in the body of this License. ++ ++ 9. The Free Software Foundation may publish revised and/or new versions ++of the General Public License from time to time. Such new versions will ++be similar in spirit to the present version, but may differ in detail to ++address new problems or concerns. ++ ++Each version is given a distinguishing version number. If the Program ++specifies a version number of this License which applies to it and "any ++later version", you have the option of following the terms and conditions ++either of that version or of any later version published by the Free ++Software Foundation. If the Program does not specify a version number of ++this License, you may choose any version ever published by the Free Software ++Foundation. ++ ++ 10. If you wish to incorporate parts of the Program into other free ++programs whose distribution conditions are different, write to the author ++to ask for permission. For software which is copyrighted by the Free ++Software Foundation, write to the Free Software Foundation; we sometimes ++make exceptions for this. Our decision will be guided by the two goals ++of preserving the free status of all derivatives of our free software and ++of promoting the sharing and reuse of software generally. ++ ++ NO WARRANTY ++ ++ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY ++FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN ++OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES ++PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED ++OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF ++MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS ++TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE ++PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, ++REPAIR OR CORRECTION. ++ ++ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING ++WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR ++REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, ++INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING ++OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED ++TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY ++YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER ++PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE ++POSSIBILITY OF SUCH DAMAGES. ++ ++ END OF TERMS AND CONDITIONS ++ ++ Appendix: How to Apply These Terms to Your New Programs ++ ++ If you develop a new program, and you want it to be of the greatest ++possible use to the public, the best way to achieve this is to make it ++free software which everyone can redistribute and change under these terms. ++ ++ To do so, attach the following notices to the program. It is safest ++to attach them to the start of each source file to most effectively ++convey the exclusion of warranty; and each file should have at least ++the "copyright" line and a pointer to where the full notice is found. ++ ++ ++ Copyright (C) 19yy ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 2 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, write to the Free Software ++ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, ++ USA. ++ ++Also add information on how to contact you by electronic and paper mail. ++ ++If the program is interactive, make it output a short notice like this ++when it starts in an interactive mode: ++ ++ Gnomovision version 69, Copyright (C) 19yy name of author ++ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. ++ This is free software, and you are welcome to redistribute it ++ under certain conditions; type `show c' for details. ++ ++The hypothetical commands `show w' and `show c' should show the appropriate ++parts of the General Public License. Of course, the commands you use may ++be called something other than `show w' and `show c'; they could even be ++mouse-clicks or menu items--whatever suits your program. ++ ++You should also get your employer (if you work as a programmer) or your ++school, if any, to sign a "copyright disclaimer" for the program, if ++necessary. Here is a sample; alter the names: ++ ++ Yoyodyne, Inc., hereby disclaims all copyright interest in the program ++ `Gnomovision' (which makes passes at compilers) written by James Hacker. ++ ++ , 1 April 1989 ++ Ty Coon, President of Vice ++ ++This General Public License does not permit incorporating your program into ++proprietary programs. If your program is a subroutine library, you may ++consider it more useful to permit linking proprietary applications with the ++library. If this is what you want to do, use the GNU Library General ++Public License instead of this License. +diff -pNur xorg-server-1.4.orig/hw/vnc/loginauth.c xorg-server-1.4/hw/vnc/loginauth.c +--- xorg-server-1.4.orig/hw/vnc/loginauth.c 1969-12-31 16:00:00.000000000 -0800 ++++ xorg-server-1.4/hw/vnc/loginauth.c 2007-09-06 16:09:45.000000000 -0700 +@@ -0,0 +1,143 @@ ++/* ++ * loginauth.c - deal with login-style Unix authentication. ++ * ++ * This file implements the UnixLogin authentication protocol when setting up ++ * an RFB connection. ++ * ++ * Modified for XFree86 4.x by Alan Hourihane ++ */ ++ ++/* ++ * Copyright (C) 2003 Constantin Kaplinsky. 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. ++ */ ++#ifdef HAVE_DIX_CONFIG_H ++#include ++#endif ++ ++ ++#ifdef linux ++#include "/usr/include/shadow.h" ++#endif ++#include ++#include ++#define _XOPEN_SOURCE ++#include ++#include ++#include ++#include "rfb.h" ++ ++void rfbLoginAuthProcessClientMessage(rfbClientPtr cl) ++{ ++ int n1 = 0, n2 = 0; ++ CARD32 loginLen, passwdLen, authResult; ++ char *loginBuf, *passwdBuf; ++ struct passwd *ps; ++ char *encPasswd1, *encPasswd2; ++ Bool ok; ++ ++ if ((n1 = ReadExact(cl->sock, (char *)&loginLen, ++ sizeof(loginLen))) <= 0 || ++ (n2 = ReadExact(cl->sock, (char *)&passwdLen, ++ sizeof(passwdLen))) <= 0) { ++ if (n1 != 0 || n2 != 0) ++ rfbLogPerror("rfbLoginAuthProcessClientMessage: read"); ++ rfbCloseSock(cl->pScreen, cl->sock); ++ return; ++ } ++ loginLen = Swap32IfLE(loginLen); ++ passwdLen = Swap32IfLE(passwdLen); ++ loginBuf = (char *)xalloc(loginLen + 1); ++ passwdBuf = (char *)xalloc(passwdLen + 1); ++ ++ n1 = n2 = 0; ++ if ((n1 = ReadExact(cl->sock, loginBuf, loginLen)) <= 0 || ++ (n2 = ReadExact(cl->sock, passwdBuf, passwdLen)) <= 0) { ++ if (n1 != 0 || n2 != 0) ++ rfbLogPerror("rfbLoginAuthProcessClientMessage: read"); ++ rfbCloseSock(cl->pScreen, cl->sock); ++ return; ++ } ++ loginBuf[loginLen] = '\0'; ++ passwdBuf[passwdLen] = '\0'; ++ ++ encPasswd1 = encPasswd2 = NULL; ++ ++ ps = getpwnam(loginBuf); ++ if (ps == NULL) { ++ rfbLog("rfbLoginAuthProcessClientMessage: " ++ "Cannot get password file entry for \"%s\"\n", loginBuf); ++ } else { ++ encPasswd1 = ps->pw_passwd; ++#ifdef linux ++ if (strlen(ps->pw_passwd) == 1) { ++ struct spwd *sps; ++ ++ sps = getspnam(loginBuf); ++ if (sps == NULL) { ++ rfbLog("rfbLoginAuthProcessClientMessage:" ++ " getspnam() failed for user \"%s\"\n", loginBuf); ++ } else { ++ encPasswd1 = sps->sp_pwdp; ++ } ++ } ++#endif ++ encPasswd2 = (char *)crypt(passwdBuf, encPasswd1); ++ memset(passwdBuf, 0, strlen(passwdBuf)); ++ } ++ ++ ok = FALSE; ++ if (encPasswd1 != NULL && encPasswd2 != NULL) { ++ if (strcmp(encPasswd1, encPasswd2) == 0) ++ ok = TRUE; ++ } ++ ++ if (!ok) { ++ rfbLog("rfbAuthProcessClientMessage: authentication failed from %s\n", ++ cl->host); ++ ++ if (rfbAuthConsiderBlocking(cl)) { ++ authResult = Swap32IfLE(rfbVncAuthTooMany); ++ } else { ++ authResult = Swap32IfLE(rfbVncAuthFailed); ++ } ++ ++ if (WriteExact(cl->sock, (char *)&authResult, ++ sizeof(authResult)) < 0) { ++ rfbLogPerror("rfbLoginAuthProcessClientMessage: write"); ++ } ++ rfbCloseSock(cl->pScreen, cl->sock); ++ return; ++ } ++ ++ rfbAuthUnblock(cl); ++ ++ cl->login = strdup(loginBuf); ++ rfbLog("Login-style authentication passed for user %s at %s\n", ++ cl->login, cl->host); ++ ++ authResult = Swap32IfLE(rfbVncAuthOK); ++ ++ if (WriteExact(cl->sock, (char *)&authResult, sizeof(authResult)) < 0) { ++ rfbLogPerror("rfbLoginAuthProcessClientMessage: write"); ++ rfbCloseSock(cl->pScreen, cl->sock); ++ return; ++ } ++ ++ cl->state = RFB_INITIALISATION; ++} ++ +diff -pNur xorg-server-1.4.orig/hw/vnc/Makefile.am xorg-server-1.4/hw/vnc/Makefile.am +--- xorg-server-1.4.orig/hw/vnc/Makefile.am 1969-12-31 16:00:00.000000000 -0800 ++++ xorg-server-1.4/hw/vnc/Makefile.am 2007-09-06 16:09:51.000000000 -0700 +@@ -0,0 +1,54 @@ ++# XXX This Makefile.am probably needs some work. ++ ++bin_PROGRAMS = Xvnc ++ ++Xvnc_SOURCES = \ ++ $(top_srcdir)/fb/fbcmap_mi.c \ ++ $(top_srcdir)/Xi/stubs.c \ ++ $(top_srcdir)/mi/miinitext.c \ ++ auth.c \ ++ cmap.c \ ++ corre.c \ ++ cursor.c \ ++ cutpaste.c \ ++ d3des.c \ ++ dispcur.c \ ++ dpmsstubs.c \ ++ draw.c \ ++ hextile.c \ ++ httpd.c \ ++ init.c \ ++ kbdptr.c \ ++ loginauth.c \ ++ rfbkeyb.c \ ++ rfbmouse.c \ ++ rfbserver.c \ ++ rre.c \ ++ sprite.c \ ++ sockets.c \ ++ stats.c \ ++ tight.c \ ++ translate.c \ ++ vncauth.c \ ++ vncext.c \ ++ zlib.c ++ ++ ++JPEG_LIBS = -ljpeg ++CRYPT_LIBS = -lcrypt ++FB_LIBS = ../../fb/.libs/libfb.a ++ ++AM_CFLAGS = $(DIX_CFLAGS) $(XVNC_CFLAGS) -I$(top_srcdir)/hw/dmx/vnc -DCHROMIUM=1 ++ ++Xvnc_LDFLAGS = $(LD_EXPORT_SYMBOLS_FLAG) ++Xvnc_LDADD = \ ++ $(XORG_CORE_LIBS) \ ++ $(XVNC_LIBS) \ ++ $(JPEG_LIBS) \ ++ $(CRYPT_LIBS) \ ++ $(VNCMODULES_LIBS) \ ++ $(XSERVER_LIBS) ++ ++ ++relink: ++ rm -f Xvnc && $(MAKE) Xvnc +diff -pNur xorg-server-1.4.orig/hw/vnc/rdp.c xorg-server-1.4/hw/vnc/rdp.c +--- xorg-server-1.4.orig/hw/vnc/rdp.c 1969-12-31 16:00:00.000000000 -0800 ++++ xorg-server-1.4/hw/vnc/rdp.c 2007-09-06 16:09:45.000000000 -0700 +@@ -0,0 +1,147 @@ ++/* ++ * Copyright (C) 2004 Alan Hourihane. 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. ++ */ ++#ifdef HAVE_DIX_CONFIG_H ++#include ++#endif ++ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "rfb.h" ++ ++typedef struct rdpClientRec { ++ ScreenPtr pScreen; ++} rdpClientRec, *rdpClientPtr; ++ ++typedef struct rdpInRec { ++ char version; ++ char pad; ++ short length; ++ char hdrlen; ++ unsigned char pdu; ++} rdpInRec, *rdpInPtr; ++ ++static void ++rdpCloseSock(ScreenPtr pScreen) ++{ ++ VNCSCREENPTR(pScreen); ++ close(pVNC->rdpListenSock); ++ RemoveEnabledDevice(pVNC->rdpListenSock); ++ pVNC->rdpListenSock = -1; ++} ++ ++/* ++ * rdpNewClient is called when a new connection has been made by whatever ++ * means. ++ */ ++ ++static rdpClientPtr ++rdpNewClient(ScreenPtr pScreen, int sock) ++{ ++ rdpInRec in; ++ rdpClientPtr cl; ++ BoxRec box; ++ struct sockaddr_in addr; ++ SOCKLEN_T addrlen = sizeof(struct sockaddr_in); ++ VNCSCREENPTR(pScreen); ++ int i; ++ ++ cl = (rdpClientPtr)xalloc(sizeof(rdpClientRec)); ++ ++ cl->pScreen = pScreen; ++ ++ in.version = 3; ++ in.pad = 0; ++ in.length = 0x600; /* big endian */ ++ in.hdrlen = 0x00; ++ in.pdu = 0xCC; ++ ++ if (WriteExact(sock, (char *)&in, sizeof(rdpInRec)) < 0) { ++ rfbLogPerror("rfbNewClient: write"); ++ rdpCloseSock(pScreen); ++ return NULL; ++ } ++ ++ return cl; ++} ++/* ++ * rdpCheckFds is called from ProcessInputEvents to check for input on the ++ * HTTP socket(s). If there is input to process, rdpProcessInput is called. ++ */ ++ ++void ++rdpCheckFds(ScreenPtr pScreen) ++{ ++ VNCSCREENPTR(pScreen); ++ int nfds; ++ fd_set fds; ++ struct timeval tv; ++ struct sockaddr_in addr; ++ int sock; ++ const int one =1; ++ SOCKLEN_T addrlen = sizeof(addr); ++ ++ FD_ZERO(&fds); ++ FD_SET(pVNC->rdpListenSock, &fds); ++ tv.tv_sec = 0; ++ tv.tv_usec = 0; ++ nfds = select(pVNC->rdpListenSock + 1, &fds, NULL, NULL, &tv); ++ if (nfds == 0) { ++ return; ++ } ++ if (nfds < 0) { ++ if (errno != EINTR) ++ rfbLogPerror("httpCheckFds: select"); ++ return; ++ } ++ ++ if (pVNC->rdpListenSock != -1 && FD_ISSET(pVNC->rdpListenSock, &fds)) { ++ ++ if ((sock = accept(pVNC->rdpListenSock, ++ (struct sockaddr *)&addr, &addrlen)) < 0) { ++ rfbLogPerror("rdpCheckFds: accept"); ++ return; ++ } ++ ++ if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) { ++ rfbLogPerror("rdpCheckFds: fcntl"); ++ close(sock); ++ return; ++ } ++ ++ if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, ++ (char *)&one, sizeof(one)) < 0) { ++ rfbLogPerror("rdpCheckFds: setsockopt"); ++ close(sock); ++ return; ++ } ++ ++ rfbLog("\n"); ++ ++ rfbLog("Got RDP connection from client %s\n", inet_ntoa(addr.sin_addr)); ++ ++ AddEnabledDevice(sock); ++ ++ rdpNewClient(pScreen, sock); ++ } ++} +diff -pNur xorg-server-1.4.orig/hw/vnc/README xorg-server-1.4/hw/vnc/README +--- xorg-server-1.4.orig/hw/vnc/README 1969-12-31 16:00:00.000000000 -0800 ++++ xorg-server-1.4/hw/vnc/README 2007-09-06 16:09:45.000000000 -0700 +@@ -0,0 +1,14 @@ ++ ++This is the directory containing the code specific to the TightVNC X server (Xvnc). ++Note that within this directory the name RFB is still used instead of VNC. ++ ++NOTE: ++ ++The is the new XFree86 v4 architecture VNC server code. ++ ++Modified entirely by Alan Hourihane ++ ++For information please visit http://xf4vnc.sourceforge.net ++ ++Moved to X.org modular tree by Brian Paul. ++ +diff -pNur xorg-server-1.4.orig/hw/vnc/rfb.h xorg-server-1.4/hw/vnc/rfb.h +--- xorg-server-1.4.orig/hw/vnc/rfb.h 1969-12-31 16:00:00.000000000 -0800 ++++ xorg-server-1.4/hw/vnc/rfb.h 2007-09-06 16:09:45.000000000 -0700 +@@ -0,0 +1,749 @@ ++/* ++ * rfb.h - header file for RFB DDX implementation. ++ * ++ * Modified for XFree86 4.x by Alan Hourihane ++ */ ++ ++/* ++ * Copyright (C) 2000-2004 Const Kaplinsky. All Rights Reserved. ++ * Copyright (C) 2000 Tridia Corporation. All Rights Reserved. ++ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. ++ * ++ * This is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This software is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this software; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, ++ * USA. ++ */ ++ ++#ifndef RFB_H_INCLUDED ++#define RFB_H_INCLUDED ++ ++#ifdef HAVE_DMX_CONFIG_H ++#include "dmx-config.h" ++#endif ++ ++#ifdef DMXVNC ++#include ++#else ++#include ++#endif ++ ++#include ++#ifdef XFREE86VNC ++#include "xf86.h" ++#endif ++#include "scrnintstr.h" ++#include "colormapst.h" ++#include "dixstruct.h" ++#include "gcstruct.h" ++#include "regionstr.h" ++#include "windowstr.h" ++#include "dixfontstr.h" ++#include "mipointer.h" ++#include ++#include ++#define _VNC_SERVER ++#include ++#include "picturestr.h" ++ ++#if defined(sun) || defined(hpux) ++#define SOCKLEN_T int ++#else ++#define SOCKLEN_T socklen_t ++#endif ++ ++/* It's a good idea to keep these values a bit greater than required. */ ++#define MAX_ENCODINGS 10 ++#define MAX_SECURITY_TYPES 4 ++#define MAX_TUNNELING_CAPS 16 ++#define MAX_AUTH_CAPS 16 ++ ++/* ++ * HTTP_BUF_SIZE for http transfers ++ */ ++#define HTTP_BUF_SIZE 32768 ++ ++/* ++ * UPDATE_BUF_SIZE must be big enough to send at least one whole line of the ++ * framebuffer. So for a max screen width of say 2K with 32-bit pixels this ++ * means 8K minimum. ++ */ ++#define UPDATE_BUF_SIZE 30000 ++ ++#if XFREE86VNC || defined(DMXVNC) ++#include "vncint.h" ++#define VNCSCREENPTR(ptr) \ ++ vncScreenPtr pVNC = VNCPTR(ptr) ++#else ++#define VNCSCREENPTR(ptr) \ ++/* Soon \ ++ rfbScreenInfoPtr pVNC = rfbScreen[ptr->myNum] \ ++*/ \ ++ rfbScreenInfoPtr pVNC = &rfbScreen ++#endif ++ ++/* ++ * Per-screen (framebuffer) structure. There is only one of these, since we ++ * don't allow the X server to have multiple screens. ++ */ ++ ++typedef struct ++{ ++ int rfbPort; ++ int rdpPort; ++ int udpPort; ++ int rfbListenSock; ++ int rdpListenSock; ++ int udpSock; ++ int httpPort; ++ int httpListenSock; ++ int httpSock; ++ char * httpDir; ++ char buf[HTTP_BUF_SIZE]; ++ Bool udpSockConnected; ++ char * rfbAuthPasswdFile; ++ size_t buf_filled; ++ int maxFd; ++ fd_set allFds; ++ Bool noCursor; ++ Bool rfbAlwaysShared; ++ Bool rfbNeverShared; ++ Bool rfbDontDisconnect; ++ Bool rfbUserAccept; ++ Bool rfbViewOnly; ++ ColormapPtr savedColormap; ++ ColormapPtr rfbInstalledColormap; ++ rfbPixelFormat rfbServerFormat; ++ Bool rfbAuthTooManyTries; ++ int rfbAuthTries; ++ Bool loginAuthEnabled; ++ struct in_addr interface; ++ OsTimerPtr timer; ++ unsigned char updateBuf[UPDATE_BUF_SIZE]; ++ int ublen; ++ int width; ++ int paddedWidthInBytes; ++ int height; ++ int depth; ++ int bitsPerPixel; ++ int sizeInBytes; ++ unsigned char *pfbMemory; ++ Pixel blackPixel; ++ Pixel whitePixel; ++ ++ /* The following two members are used to minimise the amount of unnecessary ++ drawing caused by cursor movement. Whenever any drawing affects the ++ part of the screen where the cursor is, the cursor is removed first and ++ then the drawing is done (this is what the sprite routines test for). ++ Afterwards, however, we do not replace the cursor, even when the cursor ++ is logically being moved across the screen. We only draw the cursor ++ again just as we are about to send the client a framebuffer update. ++ ++ We need to be careful when removing and drawing the cursor because of ++ their relationship with the normal drawing routines. The drawing ++ routines can invoke the cursor routines, but also the cursor routines ++ themselves end up invoking drawing routines. ++ ++ Removing the cursor (rfbSpriteRemoveCursor) is eventually achieved by ++ doing a CopyArea from a pixmap to the screen, where the pixmap contains ++ the saved contents of the screen under the cursor. Before doing this, ++ however, we set cursorIsDrawn to FALSE. Then, when CopyArea is called, ++ it sees that cursorIsDrawn is FALSE and so doesn't feel the need to ++ (recursively!) remove the cursor before doing it. ++ ++ Putting up the cursor (rfbSpriteRestoreCursor) involves a call to ++ PushPixels. While this is happening, cursorIsDrawn must be FALSE so ++ that PushPixels doesn't think it has to remove the cursor first. ++ Obviously cursorIsDrawn is set to TRUE afterwards. ++ ++ Another problem we face is that drawing routines sometimes cause a ++ framebuffer update to be sent to the RFB client. When the RFB client is ++ already waiting for a framebuffer update and some drawing to the ++ framebuffer then happens, the drawing routine sees that the client is ++ ready, so it calls rfbSendFramebufferUpdate. If the cursor is not drawn ++ at this stage, it must be put up, and so rfbSpriteRestoreCursor is ++ called. However, if the original drawing routine was actually called ++ from within rfbSpriteRestoreCursor or rfbSpriteRemoveCursor we don't ++ want this to happen. So both the cursor routines set ++ dontSendFramebufferUpdate to TRUE, and all the drawing routines check ++ this before calling rfbSendFramebufferUpdate. */ ++ ++ Bool cursorIsDrawn; /* TRUE if the cursor is currently drawn */ ++ Bool dontSendFramebufferUpdate; /* TRUE while removing or drawing the ++ cursor */ ++ ++ /* wrapped screen functions */ ++ ++ CloseScreenProcPtr CloseScreen; ++ CreateGCProcPtr CreateGC; ++ PaintWindowBackgroundProcPtr PaintWindowBackground; ++ PaintWindowBorderProcPtr PaintWindowBorder; ++ CopyWindowProcPtr CopyWindow; ++ ClearToBackgroundProcPtr ClearToBackground; ++ RestoreAreasProcPtr RestoreAreas; ++ ScreenWakeupHandlerProcPtr WakeupHandler; ++#ifdef CHROMIUM ++ RealizeWindowProcPtr RealizeWindow; ++ UnrealizeWindowProcPtr UnrealizeWindow; ++ DestroyWindowProcPtr DestroyWindow; ++ ResizeWindowProcPtr ResizeWindow; ++ PositionWindowProcPtr PositionWindow; ++ ClipNotifyProcPtr ClipNotify; ++#endif ++#ifdef RENDER ++ CompositeProcPtr Composite; ++#endif ++ ++} rfbScreenInfo, *rfbScreenInfoPtr; ++ ++ ++/* ++ * rfbTranslateFnType is the type of translation functions. ++ */ ++ ++struct rfbClientRec; ++typedef void (*rfbTranslateFnType)(ScreenPtr pScreen, ++ char *table, rfbPixelFormat *in, ++ rfbPixelFormat *out, ++ unsigned char *optr, ++ int bytesBetweenInputLines, ++ int width, int height, ++ int x, int y); ++ ++ ++/* ++ * Per-client structure. ++ */ ++ ++typedef struct rfbClientRec { ++ int sock; ++ char *host; ++ char *login; ++ ++ int protocol_minor_ver; /* RFB protocol minor version in use. */ ++ Bool protocol_tightvnc; /* TightVNC protocol extensions enabled */ ++ ++ /* Possible client states: */ ++ ++ enum { ++ RFB_PROTOCOL_VERSION, /* establishing protocol version */ ++ RFB_SECURITY_TYPE, /* negotiating security (RFB v.3.7) */ ++ RFB_TUNNELING_TYPE, /* establishing tunneling (RFB v.3.7t) */ ++ RFB_AUTH_TYPE, /* negotiating authentication (RFB v.3.7t) */ ++ RFB_AUTHENTICATION, /* authenticating (VNC authentication) */ ++ RFB_INITIALISATION, /* sending initialisation messages */ ++ RFB_NORMAL /* normal protocol messages */ ++ } state; ++ ++ Bool viewOnly; /* Do not accept input from this client. */ ++ ++ Bool reverseConnection; ++ ++ Bool readyForSetColourMapEntries; ++ ++ Bool useCopyRect; ++ int preferredEncoding; ++ int correMaxWidth, correMaxHeight; ++ ++ /* The list of security types sent to this client (protocol 3.7). ++ Note that the first entry is the number of list items following. */ ++ ++ CARD8 securityTypes[MAX_SECURITY_TYPES + 1]; ++ ++ /* Lists of capability codes sent to clients. We remember these ++ lists to restrict clients from choosing those tunneling and ++ authentication types that were not advertised. */ ++ ++ int nAuthCaps; ++ CARD32 authCaps[MAX_AUTH_CAPS]; ++ ++ /* This is not useful while we don't support tunneling: ++ int nTunnelingCaps; ++ CARD32 tunnelingCaps[MAX_TUNNELING_CAPS]; */ ++ ++ /* The following member is only used during VNC authentication */ ++ ++ CARD8 authChallenge[CHALLENGESIZE]; ++ ++ /* The following members represent the update needed to get the client's ++ framebuffer from its present state to the current state of our ++ framebuffer. ++ ++ If the client does not accept CopyRect encoding then the update is ++ simply represented as the region of the screen which has been modified ++ (modifiedRegion). ++ ++ If the client does accept CopyRect encoding, then the update consists of ++ two parts. First we have a single copy from one region of the screen to ++ another (the destination of the copy is copyRegion), and second we have ++ the region of the screen which has been modified in some other way ++ (modifiedRegion). ++ ++ Although the copy is of a single region, this region may have many ++ rectangles. When sending an update, the copyRegion is always sent ++ before the modifiedRegion. This is because the modifiedRegion may ++ overlap parts of the screen which are in the source of the copy. ++ ++ In fact during normal processing, the modifiedRegion may even overlap ++ the destination copyRegion. Just before an update is sent we remove ++ from the copyRegion anything in the modifiedRegion. */ ++ ++ RegionRec copyRegion; /* the destination region of the copy */ ++ int copyDX, copyDY; /* the translation by which the copy happens */ ++ ++ RegionRec modifiedRegion; /* the region of the screen modified in any ++ other way */ ++ ++ /* As part of the FramebufferUpdateRequest, a client can express interest ++ in a subrectangle of the whole framebuffer. This is stored in the ++ requestedRegion member. In the normal case this is the whole ++ framebuffer if the client is ready, empty if it's not. */ ++ ++ RegionRec requestedRegion; ++ ++ /* The following members represent the state of the "deferred update" timer ++ - when the framebuffer is modified and the client is ready, in most ++ cases it is more efficient to defer sending the update by a few ++ milliseconds so that several changes to the framebuffer can be combined ++ into a single update. */ ++ ++ Bool deferredUpdateScheduled; ++ OsTimerPtr deferredUpdateTimer; ++ ++ /* translateFn points to the translation function which is used to copy ++ and translate a rectangle from the framebuffer to an output buffer. */ ++ ++ rfbTranslateFnType translateFn; ++ ++ char *translateLookupTable; ++ ++ rfbPixelFormat format; ++ ++ /* statistics */ ++ ++ int rfbBytesSent[MAX_ENCODINGS]; ++ int rfbRectanglesSent[MAX_ENCODINGS]; ++ int rfbLastRectMarkersSent; ++ int rfbLastRectBytesSent; ++ int rfbCursorShapeBytesSent; ++ int rfbCursorShapeUpdatesSent; ++ int rfbCursorPosBytesSent; ++ int rfbCursorPosUpdatesSent; ++ int rfbFramebufferUpdateMessagesSent; ++ int rfbRawBytesEquivalent; ++ int rfbKeyEventsRcvd; ++ int rfbPointerEventsRcvd; ++ ++ /* zlib encoding -- necessary compression state info per client */ ++ ++ struct z_stream_s compStream; ++ Bool compStreamInited; ++ ++ CARD32 zlibCompressLevel; ++ ++ /* tight encoding -- preserve zlib streams' state for each client */ ++ ++ z_stream zsStruct[4]; ++ Bool zsActive[4]; ++ int zsLevel[4]; ++ int tightCompressLevel; ++ int tightQualityLevel; ++ ++ Bool enableLastRectEncoding; /* client supports LastRect encoding */ ++ Bool enableCursorShapeUpdates; /* client supports cursor shape updates */ ++ Bool enableCursorPosUpdates; /* client supports PointerPos updates */ ++#ifdef CHROMIUM ++ Bool enableChromiumEncoding; /* client supports Chromium encoding */ ++#endif ++ Bool useRichCursorEncoding; /* rfbEncodingRichCursor is preferred */ ++ Bool cursorWasChanged; /* cursor shape update should be sent */ ++ Bool cursorWasMoved; /* cursor position update should be sent */ ++ ++ int cursorX, cursorY; /* client's cursor position */ ++ ++ struct rfbClientRec *next; ++ ++ ScreenPtr pScreen; ++ int userAccepted; ++ ++#ifdef CHROMIUM ++ unsigned int chromium_port; ++ unsigned int chromium_msport; ++#endif ++} rfbClientRec, *rfbClientPtr; ++ ++#ifdef CHROMIUM ++typedef struct CRWindowTable { ++ unsigned long CRwinId; ++ unsigned long XwinId; ++ BoxPtr clipRects; ++ int numRects; ++ struct CRWindowTable *next; ++} CRWindowTable, *CRWindowTablePtr; ++ ++extern struct CRWindowTable *windowTable; ++#endif ++ ++/* ++ * This macro is used to test whether there is a framebuffer update needing to ++ * be sent to the client. ++ */ ++ ++#define FB_UPDATE_PENDING(cl) \ ++ ((!(cl)->enableCursorShapeUpdates && !pVNC->cursorIsDrawn) || \ ++ ((cl)->enableCursorShapeUpdates && (cl)->cursorWasChanged) || \ ++ ((cl)->enableCursorPosUpdates && (cl)->cursorWasMoved) || \ ++ REGION_NOTEMPTY(((cl)->pScreen),&(cl)->copyRegion) || \ ++ REGION_NOTEMPTY(((cl)->pScreen),&(cl)->modifiedRegion)) ++ ++/* ++ * This macro creates an empty region (ie. a region with no areas) if it is ++ * given a rectangle with a width or height of zero. It appears that ++ * REGION_INTERSECT does not quite do the right thing with zero-width ++ * rectangles, but it should with completely empty regions. ++ */ ++ ++#define SAFE_REGION_INIT(pscreen, preg, rect, size) \ ++{ \ ++ if ( ( (rect) ) && \ ++ ( ( (rect)->x2 == (rect)->x1 ) || \ ++ ( (rect)->y2 == (rect)->y1 ) ) ) { \ ++ REGION_NULL( (pscreen), (preg) ); \ ++ } else { \ ++ REGION_INIT( (pscreen), (preg), (rect), (size) ); \ ++ } \ ++} ++ ++/* ++ * An rfbGCRec is where we store the pointers to the original GC funcs and ops ++ * which we wrap (NULL means not wrapped). ++ */ ++ ++typedef struct { ++ GCFuncs *wrapFuncs; ++ GCOps *wrapOps; ++} rfbGCRec, *rfbGCPtr; ++ ++ ++ ++/* ++ * Macros for endian swapping. ++ */ ++ ++#define Swap16(s) ((((s) & 0xff) << 8) | (((s) >> 8) & 0xff)) ++ ++#define Swap32(l) (((l) >> 24) | \ ++ (((l) & 0x00ff0000) >> 8) | \ ++ (((l) & 0x0000ff00) << 8) | \ ++ ((l) << 24)) ++ ++static const int rfbEndianTest = 1; ++ ++#define Swap16IfLE(s) (*(const char *)&rfbEndianTest ? Swap16(s) : (s)) ++ ++#define Swap32IfLE(l) (*(const char *)&rfbEndianTest ? Swap32(l) : (l)) ++ ++ ++/* ++ * Macro to fill in an rfbCapabilityInfo structure (protocol 3.130). ++ * Normally, using macros is no good, but this macro saves us from ++ * writing constants twice -- it constructs signature names from codes. ++ * Note that "code_sym" argument should be a single symbol, not an expression. ++ */ ++ ++#define SetCapInfo(cap_ptr, code_sym, vendor) \ ++{ \ ++ rfbCapabilityInfo *pcap; \ ++ pcap = (cap_ptr); \ ++ pcap->code = Swap32IfLE(code_sym); \ ++ memcpy(pcap->vendorSignature, (vendor), \ ++ sz_rfbCapabilityInfoVendor); \ ++ memcpy(pcap->nameSignature, sig_##code_sym, \ ++ sz_rfbCapabilityInfoName); \ ++} ++ ++ ++/* init.c */ ++ ++extern char *desktopName; ++extern char rfbThisHost[]; ++extern Atom VNC_LAST_CLIENT_ID; ++ ++extern rfbScreenInfo rfbScreen; ++extern int rfbGCIndex; ++ ++extern int inetdSock; ++ ++extern int rfbBitsPerPixel(int depth); ++extern void rfbLog(char *format, ...); ++extern void rfbLogPerror(char *str); ++ ++ ++/* sockets.c */ ++ ++extern int rfbMaxClientWait; ++ ++extern Bool rfbInitSockets(ScreenPtr pScreen); ++extern void rfbDisconnectUDPSock(ScreenPtr pScreen); ++extern void rfbCloseSock(ScreenPtr pScreen, int sock); ++extern void rfbCheckFds(ScreenPtr pScreen); ++extern void rfbWaitForClient(int sock); ++extern int rfbConnect(ScreenPtr pScreen, char *host, int port); ++ ++extern int ReadExact(int sock, char *buf, int len); ++extern int WriteExact(int sock, char *buf, int len); ++extern int ListenOnTCPPort(ScreenPtr pScreen, int port); ++extern int ListenOnUDPPort(ScreenPtr pScreen, int port); ++extern int ConnectToTcpAddr(char *host, int port); ++ ++ ++/* cmap.c */ ++ ++ ++extern int rfbListInstalledColormaps(ScreenPtr pScreen, Colormap *pmaps); ++extern void rfbInstallColormap(ColormapPtr pmap); ++extern void rfbUninstallColormap(ColormapPtr pmap); ++extern void rfbStoreColors(ColormapPtr pmap, int ndef, xColorItem *pdefs); ++ ++ ++/* draw.c */ ++ ++extern int rfbDeferUpdateTime; ++ ++extern void ++rfbComposite( ++ CARD8 op, ++ PicturePtr pSrc, ++ PicturePtr pMask, ++ PicturePtr pDst, ++ INT16 xSrc, ++ INT16 ySrc, ++ INT16 xMask, ++ INT16 yMask, ++ INT16 xDst, ++ INT16 yDst, ++ CARD16 width, ++ CARD16 height ++); ++ ++extern void rfbGlyphs( ++ CARD8 op, ++ PicturePtr pSrc, ++ PicturePtr pDst, ++ PictFormatPtr maskFormat, ++ INT16 xSrc, ++ INT16 ySrc, ++ int nlistInit, ++ GlyphListPtr listInit, ++ GlyphPtr *glyphsInit ++); ++extern Bool rfbCloseScreen(int,ScreenPtr); ++extern Bool rfbCreateGC(GCPtr); ++extern void rfbPaintWindowBackground(WindowPtr, RegionPtr, int what); ++extern void rfbPaintWindowBorder(WindowPtr, RegionPtr, int what); ++extern void rfbCopyWindow(WindowPtr, DDXPointRec, RegionPtr); ++#ifdef CHROMIUM ++extern Bool rfbRealizeWindow(WindowPtr); ++extern Bool rfbUnrealizeWindow(WindowPtr); ++extern Bool rfbDestroyWindow(WindowPtr); ++extern void rfbResizeWindow(WindowPtr, int x, int y, unsigned int w, unsigned int h, WindowPtr pSib); ++extern Bool rfbPositionWindow(WindowPtr, int x, int y); ++extern void rfbClipNotify(WindowPtr, int x, int y); ++#endif ++extern void rfbClearToBackground(WindowPtr, int x, int y, int w, ++ int h, Bool generateExposures); ++extern RegionPtr rfbRestoreAreas(WindowPtr, RegionPtr); ++extern void rfbScheduleUpdate(ScreenPtr pScreen); ++ ++/* dispcur.c */ ++extern Bool rfbDCInitialize(ScreenPtr pScreen, miPointerScreenFuncPtr screenFuncs); ++ ++ ++/* cutpaste.c */ ++ ++extern void rfbSetXCutText(char *str, int len); ++extern void rfbGotXCutText(char *str, int len); ++ ++ ++/* kbdptr.c */ ++ ++extern Bool compatibleKbd; ++extern unsigned char ptrAcceleration; ++ ++extern void PtrDeviceInit(void); ++extern void PtrDeviceOn(DeviceIntPtr pDev); ++extern void PtrDeviceOff(void); ++extern void PtrDeviceControl(DeviceIntPtr dev, PtrCtrl *ctrl); ++extern void PtrAddEvent(int buttonMask, int x, int y, rfbClientPtr cl); ++ ++extern void KbdDeviceInit(DeviceIntPtr pDevice, KeySymsPtr pKeySyms, CARD8 *pModMap); ++extern void KbdDeviceOn(void); ++extern void KbdDeviceOff(void); ++extern void KbdAddEvent(Bool down, KeySym keySym, rfbClientPtr cl); ++extern void KbdReleaseAllKeys(void); ++ ++extern void vncSetKeyboardDevice(DeviceIntPtr kbd); ++extern void vncSetPointerDevice(DeviceIntPtr ptr); ++ ++ ++/* rfbserver.c */ ++ ++ ++extern rfbClientPtr rfbClientHead; ++extern rfbClientPtr pointerClient; ++ ++extern void rfbNewClientConnection(ScreenPtr pScreen, int sock); ++extern rfbClientPtr rfbReverseConnection(ScreenPtr pScreen, char *host, int port); ++extern void rfbRootPropertyChange(ScreenPtr pScreen); ++extern void rfbClientConnectionGone(int sock); ++extern void rfbProcessClientMessage(ScreenPtr pScreen, int sock); ++extern void rfbClientConnFailed(rfbClientPtr cl, char *reason); ++extern void rfbNewUDPConnection(int sock); ++extern void rfbProcessUDPInput(ScreenPtr pScreen, int sock); ++extern Bool rfbSendFramebufferUpdate(ScreenPtr pScreen, rfbClientPtr cl); ++extern Bool rfbSendRectEncodingRaw(rfbClientPtr cl, int x,int y,int w,int h); ++extern Bool rfbSendUpdateBuf(rfbClientPtr cl); ++extern Bool rfbSendSetColourMapEntries(rfbClientPtr cl, int firstColour, ++ int nColours); ++extern void rfbSendBell(void); ++extern void rfbSendServerCutText(char *str, int len); ++extern void rfbUserAllow(int sock, int accept); ++extern void rfbSetClip (WindowPtr pWin, BOOL enable); ++ ++extern int GenerateVncConnectedEvent(int sock); ++extern int GenerateVncDisconnectedEvent(int sock); ++ ++#ifdef CHROMIUM ++extern void rfbSendChromiumWindowShow(unsigned int winid, unsigned int show); ++extern void rfbSendChromiumWindowDestroy(unsigned int winid); ++extern void rfbSendChromiumMoveResizeWindow(unsigned int winid, int x, int y, unsigned int w, unsigned int h); ++extern void rfbSendChromiumClipList(unsigned int winid, BoxPtr pClipRects, int numClipRects); ++#endif ++ ++/* translate.c */ ++ ++extern Bool rfbEconomicTranslate; ++ ++extern void rfbTranslateNone(ScreenPtr pScreen, char *table, rfbPixelFormat *in, ++ rfbPixelFormat *out, ++ unsigned char *optr, ++ int bytesBetweenInputLines, ++ int width, int height, ++ int x, int y); ++extern Bool rfbSetTranslateFunction(rfbClientPtr cl); ++extern void rfbSetClientColourMaps(int firstColour, int nColours); ++extern Bool rfbSetClientColourMap(rfbClientPtr cl, int firstColour, ++ int nColours); ++ ++ ++/* httpd.c */ ++ ++extern Bool httpInitSockets(ScreenPtr pScreen); ++extern void httpCheckFds(ScreenPtr pScreen); ++ ++ ++/* vncInit.c */ ++extern void VNCInitForDMX(void); ++extern void rfbWakeupHandlerDMX(void); ++ ++ ++/* vncext.c */ ++ ++#ifdef CHROMIUM ++extern void rfbSendChromiumStart(unsigned int ipaddress, unsigned int crServerPort, unsigned int mothershipPort); ++extern void rfbChromiumMonitorWindowID(unsigned int cr_windowid, unsigned long windowid); ++int GenerateVncChromiumConnectedEvent(int sock); ++#endif ++ ++ ++/* auth.c */ ++ ++extern void rfbAuthNewClient(rfbClientPtr cl); ++extern void rfbProcessClientSecurityType(rfbClientPtr cl); ++extern void rfbProcessClientTunnelingType(rfbClientPtr cl); ++extern void rfbProcessClientAuthType(rfbClientPtr cl); ++extern void rfbVncAuthProcessResponse(rfbClientPtr cl); ++ ++/* Functions to prevent too many successive authentication failures */ ++extern Bool rfbAuthConsiderBlocking(rfbClientPtr cl); ++extern void rfbAuthUnblock(rfbClientPtr cl); ++extern Bool rfbAuthIsBlocked(rfbClientPtr cl); ++ ++/* loginauth.c */ ++ ++extern void rfbLoginAuthProcessClientMessage(rfbClientPtr cl); ++ ++/* rre.c */ ++ ++extern Bool rfbSendRectEncodingRRE(rfbClientPtr cl, int x,int y,int w,int h); ++ ++ ++/* corre.c */ ++ ++extern Bool rfbSendRectEncodingCoRRE(rfbClientPtr cl, int x,int y,int w,int h); ++ ++ ++/* hextile.c */ ++ ++extern Bool rfbSendRectEncodingHextile(rfbClientPtr cl, int x, int y, int w, ++ int h); ++ ++ ++/* zlib.c */ ++ ++/* Minimum zlib rectangle size in bytes. Anything smaller will ++ * not compress well due to overhead. ++ */ ++#define VNC_ENCODE_ZLIB_MIN_COMP_SIZE (17) ++ ++/* Set maximum zlib rectangle size in pixels. Always allow at least ++ * two scan lines. ++ */ ++#define ZLIB_MAX_RECT_SIZE (128*256) ++#define ZLIB_MAX_SIZE(min) ((( min * 2 ) > ZLIB_MAX_RECT_SIZE ) ? \ ++ ( min * 2 ) : ZLIB_MAX_RECT_SIZE ) ++ ++extern Bool rfbSendRectEncodingZlib(rfbClientPtr cl, int x, int y, int w, ++ int h); ++ ++ ++/* tight.c */ ++ ++#define TIGHT_DEFAULT_COMPRESSION 6 ++ ++extern Bool rfbTightDisableGradient; ++ ++extern int rfbNumCodedRectsTight(rfbClientPtr cl, int x,int y,int w,int h); ++extern Bool rfbSendRectEncodingTight(rfbClientPtr cl, int x,int y,int w,int h); ++ ++ ++/* cursor.c */ ++ ++extern Bool rfbSendCursorShape(rfbClientPtr cl, ScreenPtr pScreen); ++extern Bool rfbSendCursorPos(rfbClientPtr cl, ScreenPtr pScreen); ++ ++ ++/* stats.c */ ++ ++extern void rfbResetStats(rfbClientPtr cl); ++extern void rfbPrintStats(rfbClientPtr cl); ++ ++ ++/* dpms.c */ ++ ++extern Bool DPMSSupported(void); ++extern int DPSMGet(int *level); ++extern void DPMSSet(int level); ++ ++ ++#endif /* RFB_H_INCLUDED */ +diff -pNur xorg-server-1.4.orig/hw/vnc/rfbkeyb.c xorg-server-1.4/hw/vnc/rfbkeyb.c +--- xorg-server-1.4.orig/hw/vnc/rfbkeyb.c 1969-12-31 16:00:00.000000000 -0800 ++++ xorg-server-1.4/hw/vnc/rfbkeyb.c 2007-09-06 16:09:45.000000000 -0700 +@@ -0,0 +1,405 @@ ++/* ++ * Copyright (C) 2002 Alan Hourihane. 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. ++ * ++ * Author: Alan Hourihane ++ */ ++ ++#ifdef HAVE_DIX_CONFIG_H ++#include ++#endif ++ ++#if XFREE86VNC ++#ifndef XFree86LOADER ++#include ++#include ++#endif ++ ++#include ++#include ++#if !defined(DGUX) ++#include ++#endif ++#include ++#include /* Needed for InitValuator/Proximity stuff */ ++#include ++ ++#ifdef XFree86LOADER ++#include ++#endif ++#else ++#include ++#include ++#endif ++#include "rfb.h" ++ ++ ++extern void rfbSendBell(void); ++extern DeviceIntPtr kbdDevice; ++ ++static const char *DEFAULTS[] = { ++ NULL ++}; ++ ++#include ++#include "keyboard.h" ++ ++#ifdef XKB ++#include ++#include ++#include ++ ++#if XFREE86VNC ++ /* ++ * would like to use an XkbComponentNamesRec here but can't without ++ * pulling in a bunch of header files. :-( ++ */ ++static char * xkbkeymap; ++static char * xkbkeycodes; ++static char * xkbtypes; ++static char * xkbcompat; ++static char * xkbsymbols; ++static char * xkbgeometry; ++static Bool xkbcomponents_specified; ++static char * xkbrules; ++static char * xkbmodel; ++static char * xkblayout; ++static char * xkbvariant; ++static char * xkboptions; ++#endif ++#endif ++ ++void ++KbdDeviceInit(DeviceIntPtr pDevice, KeySymsPtr pKeySyms, CARD8 *pModMap) ++{ ++ int i; ++ ++ for (i = 0; i < MAP_LENGTH; i++) ++ pModMap[i] = NoSymbol; ++ ++ pModMap[CONTROL_L_KEY_CODE] = ControlMask; ++ pModMap[CONTROL_R_KEY_CODE] = ControlMask; ++ pModMap[SHIFT_L_KEY_CODE] = ShiftMask; ++ pModMap[SHIFT_R_KEY_CODE] = ShiftMask; ++ pModMap[META_L_KEY_CODE] = Mod1Mask; ++ pModMap[META_R_KEY_CODE] = Mod1Mask; ++ pModMap[ALT_L_KEY_CODE] = Mod1Mask; ++ pModMap[ALT_R_KEY_CODE] = Mod1Mask; ++ ++ pKeySyms->minKeyCode = MIN_KEY_CODE; ++ pKeySyms->maxKeyCode = MAX_KEY_CODE; ++ pKeySyms->mapWidth = GLYPHS_PER_KEY; ++ ++ pKeySyms->map = (KeySym *)xalloc(sizeof(KeySym) ++ * MAP_LENGTH * GLYPHS_PER_KEY); ++ ++ if (!pKeySyms->map) { ++ ErrorF("xalloc failed\n"); ++ exit(1); ++ } ++ ++ for (i = 0; i < MAP_LENGTH * GLYPHS_PER_KEY; i++) ++ pKeySyms->map[i] = NoSymbol; ++ ++ for (i = 0; i < N_PREDEFINED_KEYS * GLYPHS_PER_KEY; i++) { ++ pKeySyms->map[i] = map[i]; ++ } ++} ++ ++void ++KbdDeviceOn(void) ++{ ++} ++ ++ ++void ++KbdDeviceOff(void) ++{ ++} ++ ++#if XFREE86VNC ++static int ++xf86rfbKeybControlProc(DeviceIntPtr device, int onoff) ++{ ++ KeySymsRec keySyms; ++ CARD8 modMap[MAP_LENGTH]; ++ DevicePtr pDev = (DevicePtr)device; ++ ++ switch (onoff) ++ { ++ case DEVICE_INIT: ++ vncSetKeyboardDevice(device); ++ KbdDeviceInit(device, &keySyms, modMap); ++#ifdef XKB ++ if (noXkbExtension) { ++#endif ++ InitKeyboardDeviceStruct(pDev, &keySyms, modMap, ++ (BellProcPtr)rfbSendBell, ++ (KbdCtrlProcPtr)NoopDDA); ++#ifdef XKB ++ } else { ++ XkbComponentNamesRec names; ++ if (xkbkeymap) { ++ names.keymap = xkbkeymap; ++ names.keycodes = NULL; ++ names.types = NULL; ++ names.compat = NULL; ++ names.symbols = NULL; ++ names.geometry = NULL; ++ } else { ++ names.keymap = NULL; ++ names.keycodes = xkbkeycodes; ++ names.types = xkbtypes; ++ names.compat = xkbcompat; ++ names.symbols = xkbsymbols; ++ names.geometry = xkbgeometry; ++ } ++ if ((xkbkeymap || xkbcomponents_specified) ++ && (xkbmodel == NULL || xkblayout == NULL)) { ++ xkbrules = NULL; ++ } ++#if 0 ++ XkbSetRulesDflts(xkbrules, xkbmodel, ++ xkblayout, xkbvariant, ++ xkboptions); ++#endif ++ XkbInitKeyboardDeviceStruct(device, ++ &names, ++ &keySyms, ++ modMap, ++ (BellProcPtr)rfbSendBell, ++ (KbdCtrlProcPtr)NoopDDA); ++ } ++#endif ++ break; ++ case DEVICE_ON: ++ pDev->on = TRUE; ++ KbdDeviceOn(); ++ break; ++ case DEVICE_OFF: ++ pDev->on = FALSE; ++ KbdDeviceOff(); ++ break; ++ case DEVICE_CLOSE: ++ vncSetKeyboardDevice(NULL); ++ if (pDev->on) ++ KbdDeviceOff(); ++ break; ++ } ++ return Success; ++} ++ ++static void ++xf86rfbKeybUninit(InputDriverPtr drv, ++ InputInfoPtr pInfo, ++ int flags) ++{ ++ xf86rfbKeybControlProc(pInfo->dev, DEVICE_OFF); ++} ++ ++static InputInfoPtr ++xf86rfbKeybInit(InputDriverPtr drv, ++ IDevPtr dev, ++ int flags) ++{ ++ InputInfoPtr pInfo; ++ char *s; ++ Bool from; ++ ++ if (!(pInfo = xf86AllocateInput(drv, 0))) ++ return NULL; ++ ++ /* Initialise the InputInfoRec. */ ++ pInfo->name = dev->identifier; ++ pInfo->type_name = "rfbKeyb"; ++ pInfo->flags = XI86_KEYBOARD_CAPABLE; ++ pInfo->device_control = xf86rfbKeybControlProc; ++ pInfo->read_input = NULL; ++#if 0 ++ pInfo->motion_history_proc = NULL; ++#endif ++ pInfo->history_size = 0; ++ pInfo->control_proc = NULL; ++ pInfo->close_proc = NULL; ++ pInfo->switch_mode = NULL; ++ pInfo->conversion_proc = NULL; ++ pInfo->reverse_conversion_proc = NULL; ++ pInfo->fd = -1; ++ pInfo->dev = NULL; ++ pInfo->private_flags = 0; ++ pInfo->always_core_feedback = 0; ++ pInfo->conf_idev = dev; ++ ++ /* Collect the options, and process the common options. */ ++ xf86CollectInputOptions(pInfo, DEFAULTS, NULL); ++ xf86ProcessCommonOptions(pInfo, pInfo->options); ++ ++ /* Mark the device configured */ ++ pInfo->flags |= XI86_CONFIGURED; ++ ++#ifdef XKB ++ from = X_DEFAULT; ++ if (noXkbExtension) ++ from = X_CMDLINE; ++ else if (xf86FindOption(dev->commonOptions, "XkbDisable")) { ++ noXkbExtension = ++ xf86SetBoolOption(dev->commonOptions, "XkbDisable", FALSE); ++ from = X_CONFIG; ++ } ++ if (noXkbExtension) ++ xf86Msg(from, "XKB: disabled\n"); ++ ++#define NULL_IF_EMPTY(s) (s[0] ? s : (xfree(s), (char *)NULL)) ++ ++ if (!noXkbExtension) { ++ if ((s = xf86SetStrOption(dev->commonOptions, "XkbKeymap", NULL))) { ++ xkbkeymap = NULL_IF_EMPTY(s); ++ xf86Msg(X_CONFIG, "XKB: keymap: \"%s\" " ++ "(overrides other XKB settings)\n", xkbkeymap); ++ } else { ++ if ((s = xf86SetStrOption(dev->commonOptions, "XkbCompat", NULL))) { ++ xkbcompat = NULL_IF_EMPTY(s); ++ xkbcomponents_specified = TRUE; ++ xf86Msg(X_CONFIG, "XKB: compat: \"%s\"\n", s); ++ } ++ ++ if ((s = xf86SetStrOption(dev->commonOptions, "XkbTypes", NULL))) { ++ xkbtypes = NULL_IF_EMPTY(s); ++ xkbcomponents_specified = TRUE; ++ xf86Msg(X_CONFIG, "XKB: types: \"%s\"\n", s); ++ } ++ ++ if ((s = xf86SetStrOption(dev->commonOptions, "XkbKeycodes", NULL))) { ++ xkbkeycodes = NULL_IF_EMPTY(s); ++ xkbcomponents_specified = TRUE; ++ xf86Msg(X_CONFIG, "XKB: keycodes: \"%s\"\n", s); ++ } ++ ++ if ((s = xf86SetStrOption(dev->commonOptions, "XkbGeometry", NULL))) { ++ xkbgeometry = NULL_IF_EMPTY(s); ++ xkbcomponents_specified = TRUE; ++ xf86Msg(X_CONFIG, "XKB: geometry: \"%s\"\n", s); ++ } ++ ++ if ((s = xf86SetStrOption(dev->commonOptions, "XkbSymbols", NULL))) { ++ xkbsymbols = NULL_IF_EMPTY(s); ++ xkbcomponents_specified = TRUE; ++ xf86Msg(X_CONFIG, "XKB: symbols: \"%s\"\n", s); ++ } ++ ++ if ((s = xf86SetStrOption(dev->commonOptions, "XkbRules", NULL))) { ++ xkbrules = NULL_IF_EMPTY(s); ++ xkbcomponents_specified = TRUE; ++ xf86Msg(X_CONFIG, "XKB: rules: \"%s\"\n", s); ++ } ++ ++ if ((s = xf86SetStrOption(dev->commonOptions, "XkbModel", NULL))) { ++ xkbmodel = NULL_IF_EMPTY(s); ++ xkbcomponents_specified = TRUE; ++ xf86Msg(X_CONFIG, "XKB: model: \"%s\"\n", s); ++ } ++ ++ if ((s = xf86SetStrOption(dev->commonOptions, "XkbLayout", NULL))) { ++ xkblayout = NULL_IF_EMPTY(s); ++ xkbcomponents_specified = TRUE; ++ xf86Msg(X_CONFIG, "XKB: layout: \"%s\"\n", s); ++ } ++ ++ if ((s = xf86SetStrOption(dev->commonOptions, "XkbVariant", NULL))) { ++ xkbvariant = NULL_IF_EMPTY(s); ++ xkbcomponents_specified = TRUE; ++ xf86Msg(X_CONFIG, "XKB: variant: \"%s\"\n", s); ++ } ++ ++ if ((s = xf86SetStrOption(dev->commonOptions, "XkbOptions", NULL))) { ++ xkboptions = NULL_IF_EMPTY(s); ++ xkbcomponents_specified = TRUE; ++ xf86Msg(X_CONFIG, "XKB: options: \"%s\"\n", s); ++ } ++ } ++ } ++#undef NULL_IF_EMPTY ++#endif ++ ++ /* Return the configured device */ ++ return (pInfo); ++} ++ ++#ifdef XFree86LOADER ++static ++#endif ++InputDriverRec RFBKEYB = { ++ 1, /* driver version */ ++ "rfbkeyb", /* driver name */ ++ NULL, /* identify */ ++ xf86rfbKeybInit, /* pre-init */ ++ xf86rfbKeybUninit, /* un-init */ ++ NULL, /* module */ ++ 0 /* ref count */ ++}; ++ ++/* ++ *************************************************************************** ++ * ++ * Dynamic loading functions ++ * ++ *************************************************************************** ++ */ ++#ifdef XFree86LOADER ++static void ++xf86rfbKeybUnplug(pointer p) ++{ ++} ++ ++static pointer ++xf86rfbKeybPlug(pointer module, ++ pointer options, ++ int *errmaj, ++ int *errmin) ++{ ++ xf86AddInputDriver(&RFBKEYB, module, 0); ++ ++ return module; ++} ++ ++void ++vncInitKeyb(void) ++{ ++ xf86AddInputDriver(&RFBKEYB, NULL, 0); ++} ++ ++static XF86ModuleVersionInfo xf86rfbKeybVersionRec = ++{ ++ "rfbkeyb", ++ "xf4vnc Project, see http://xf4vnc.sf.net", ++ MODINFOSTRING1, ++ MODINFOSTRING2, ++ XF86_VERSION_CURRENT, ++ 1, 0, 0, ++ ABI_CLASS_XINPUT, ++ ABI_XINPUT_VERSION, ++ MOD_CLASS_XINPUT, ++ {0, 0, 0, 0} /* signature, to be patched into the file by */ ++ /* a tool */ ++}; ++ ++XF86ModuleData rfbkeybModuleData = {&xf86rfbKeybVersionRec, ++ xf86rfbKeybPlug, ++ xf86rfbKeybUnplug}; ++ ++#endif /* XFree86LOADER */ ++#endif +diff -pNur xorg-server-1.4.orig/hw/vnc/rfbmouse.c xorg-server-1.4/hw/vnc/rfbmouse.c +--- xorg-server-1.4.orig/hw/vnc/rfbmouse.c 1969-12-31 16:00:00.000000000 -0800 ++++ xorg-server-1.4/hw/vnc/rfbmouse.c 2007-09-06 16:09:45.000000000 -0700 +@@ -0,0 +1,260 @@ ++/* ++ * Copyright (C) 2002 Alan Hourihane. 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. ++ * ++ * Author: Alan Hourihane ++ */ ++#ifdef HAVE_DIX_CONFIG_H ++#include ++#endif ++ ++ ++#include ++#if XFREE86VNC ++#ifndef XFree86LOADER ++#include ++#include ++#endif ++ ++#include ++#include ++#if !defined(DGUX) ++#include ++#endif ++#include ++#include /* Needed for InitValuator/Proximity stuff */ ++#include ++ ++#ifdef XFree86LOADER ++#include ++#endif ++ ++static const char *DEFAULTS[] = { ++ NULL ++}; ++#else ++#include ++#include ++#endif ++#include "rfb.h" ++ ++ ++unsigned char ptrAcceleration = 50; ++ ++void ++PtrDeviceOn(DeviceIntPtr pDev) ++{ ++#if 0 ++ ptrAcceleration = (unsigned char)pDev->ptrfeed->ctrl.num; ++#endif ++} ++ ++void ++PtrDeviceInit(void) ++{ ++} ++ ++void ++PtrDeviceOff(void) ++{ ++} ++ ++ ++void ++PtrDeviceControl(DeviceIntPtr dev, PtrCtrl *ctrl) ++{ ++#if 0 ++ ptrAcceleration = (char)ctrl->num; ++ ++ if (udpSockConnected) { ++ if (write(udpSock, &ptrAcceleration, 1) <= 0) { ++ ErrorF("PtrDeviceControl: UDP input: write"); ++ rfbDisconnectUDPSock(); ++ } ++ } ++#endif ++} ++ ++#if XFREE86VNC ++static int ++xf86rfbMouseControlProc(DeviceIntPtr device, int onoff) ++{ ++ BYTE map[6]; ++ DevicePtr pDev = (DevicePtr)device; ++ void *func1; ++ int (*func2)(void); ++ ++ if (LoaderSymbol("GetMotionHistory")) ++ func1 = LoaderSymbol("GetMotionHistory"); ++ else ++ func1 = LoaderSymbol("miPointerGetMotionEvents"); ++ ++ if (LoaderSymbol("GetMotionHistorySize")) ++ func2 = LoaderSymbol("GetMotionHistorySize"); ++ else ++ func2 = LoaderSymbol("miPointerGetMotionBufferSize"); ++ ++ ++ switch (onoff) ++ { ++ case DEVICE_INIT: ++ vncSetPointerDevice(device); ++ PtrDeviceInit(); ++ map[1] = 1; ++ map[2] = 2; ++ map[3] = 3; ++ map[4] = 4; ++ map[5] = 5; ++ InitPointerDeviceStruct(pDev, map, 5, ++ func1, ++ PtrDeviceControl, ++ (*func2)(), 2); ++ break; ++ ++ case DEVICE_ON: ++ pDev->on = TRUE; ++ PtrDeviceOn(device); ++ break; ++ ++ case DEVICE_OFF: ++ pDev->on = FALSE; ++ PtrDeviceOff(); ++ break; ++ ++ case DEVICE_CLOSE: ++ vncSetPointerDevice(NULL); ++ if (pDev->on) ++ PtrDeviceOff(); ++ break; ++ } ++ return Success; ++} ++ ++static void ++xf86rfbMouseUninit(InputDriverPtr drv, ++ InputInfoPtr pInfo, ++ int flags) ++{ ++ xf86rfbMouseControlProc(pInfo->dev, DEVICE_OFF); ++} ++ ++static InputInfoPtr ++xf86rfbMouseInit(InputDriverPtr drv, ++ IDevPtr dev, ++ int flags) ++{ ++ InputInfoPtr pInfo; ++ ++ if (!(pInfo = xf86AllocateInput(drv, 0))) ++ return NULL; ++ ++ /* Initialise the InputInfoRec. */ ++ pInfo->name = dev->identifier; ++ pInfo->type_name = "rfbMouse"; ++ pInfo->flags = XI86_POINTER_CAPABLE | XI86_SEND_DRAG_EVENTS; ++ pInfo->device_control = xf86rfbMouseControlProc; ++ pInfo->read_input = NULL; ++#if 0 ++ pInfo->motion_history_proc = xf86GetMotionEvents; ++#endif ++ pInfo->history_size = 0; ++ pInfo->control_proc = NULL; ++ pInfo->close_proc = NULL; ++ pInfo->switch_mode = NULL; ++ pInfo->conversion_proc = NULL; ++ pInfo->reverse_conversion_proc = NULL; ++ pInfo->fd = -1; ++ pInfo->dev = NULL; ++ pInfo->private_flags = 0; ++ pInfo->always_core_feedback = 0; ++ pInfo->conf_idev = dev; ++ ++ /* Collect the options, and process the common options. */ ++ xf86CollectInputOptions(pInfo, DEFAULTS, NULL); ++ xf86ProcessCommonOptions(pInfo, pInfo->options); ++ ++ /* Mark the device configured */ ++ pInfo->flags |= XI86_CONFIGURED; ++ ++ /* Return the configured device */ ++ return (pInfo); ++} ++ ++#ifdef XFree86LOADER ++static ++#endif ++InputDriverRec RFBMOUSE = { ++ 1, /* driver version */ ++ "rfbmouse", /* driver name */ ++ NULL, /* identify */ ++ xf86rfbMouseInit, /* pre-init */ ++ xf86rfbMouseUninit, /* un-init */ ++ NULL, /* module */ ++ 0 /* ref count */ ++}; ++ ++/* ++ *************************************************************************** ++ * ++ * Dynamic loading functions ++ * ++ *************************************************************************** ++ */ ++#ifdef XFree86LOADER ++static void ++xf86rfbMouseUnplug(pointer p) ++{ ++} ++ ++static pointer ++xf86rfbMousePlug(pointer module, ++ pointer options, ++ int *errmaj, ++ int *errmin) ++{ ++ xf86AddInputDriver(&RFBMOUSE, module, 0); ++ ++ return module; ++} ++ ++void ++vncInitMouse(void) ++{ ++ xf86AddInputDriver(&RFBMOUSE, NULL, 0); ++} ++ ++static XF86ModuleVersionInfo xf86rfbMouseVersionRec = ++{ ++ "rfbmouse", ++ "xf4vnc Project, see http://xf4vnc.sf.net", ++ MODINFOSTRING1, ++ MODINFOSTRING2, ++ XF86_VERSION_CURRENT, ++ 1, 0, 0, ++ ABI_CLASS_XINPUT, ++ ABI_XINPUT_VERSION, ++ MOD_CLASS_XINPUT, ++ {0, 0, 0, 0} /* signature, to be patched into the file by */ ++ /* a tool */ ++}; ++ ++XF86ModuleData rfbmouseModuleData = {&xf86rfbMouseVersionRec, ++ xf86rfbMousePlug, ++ xf86rfbMouseUnplug}; ++ ++#endif /* XFree86LOADER */ ++#endif +diff -pNur xorg-server-1.4.orig/hw/vnc/rfbproto.h xorg-server-1.4/hw/vnc/rfbproto.h +--- xorg-server-1.4.orig/hw/vnc/rfbproto.h 1969-12-31 16:00:00.000000000 -0800 ++++ xorg-server-1.4/hw/vnc/rfbproto.h 2007-09-06 16:09:45.000000000 -0700 +@@ -0,0 +1,1362 @@ ++/* ++ * Copyright (C) 2000-2004 Constantin Kaplinsky. All Rights Reserved. ++ * Copyright (C) 2000 Tridia Corporation. All Rights Reserved. ++ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. ++ * ++ * This is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This software is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this software; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, ++ * USA. ++ */ ++ ++/* ++ * rfbproto.h - header file for the RFB protocol, versions 3.3, 3.7 and 3.7t ++ * (protocol 3.7t is effectively 3.7 with TightVNC extensions enabled) ++ * ++ * Uses types CARD for an n-bit unsigned integer, INT for an n-bit signed ++ * integer (for n = 8, 16 and 32). ++ * ++ * All multiple byte integers are in big endian (network) order (most ++ * significant byte first). Unless noted otherwise there is no special ++ * alignment of protocol structures. ++ * ++ * ++ * Once the initial handshaking is done, all messages start with a type byte, ++ * (usually) followed by message-specific data. The order of definitions in ++ * this file is as follows: ++ * ++ * (1) Structures used in several types of message. ++ * (2) Structures used in the initial handshaking. ++ * (3) Message types. ++ * (4) Encoding types. ++ * (5) For each message type, the form of the data following the type byte. ++ * Sometimes this is defined by a single structure but the more complex ++ * messages have to be explained by comments. ++ */ ++ ++ ++/***************************************************************************** ++ * ++ * Structures used in several messages ++ * ++ *****************************************************************************/ ++ ++/*----------------------------------------------------------------------------- ++ * Structure used to specify a rectangle. This structure is a multiple of 4 ++ * bytes so that it can be interspersed with 32-bit pixel data without ++ * affecting alignment. ++ */ ++ ++typedef struct _rfbRectangle { ++ CARD16 x; ++ CARD16 y; ++ CARD16 w; ++ CARD16 h; ++} rfbRectangle; ++ ++#define sz_rfbRectangle 8 ++ ++ ++/*----------------------------------------------------------------------------- ++ * Structure used to specify pixel format. ++ */ ++ ++typedef struct _rfbPixelFormat { ++ ++ CARD8 bitsPerPixel; /* 8,16,32 only */ ++ ++ CARD8 depth; /* 8 to 32 */ ++ ++ CARD8 bigEndian; /* True if multi-byte pixels are interpreted ++ as big endian, or if single-bit-per-pixel ++ has most significant bit of the byte ++ corresponding to first (leftmost) pixel. Of ++ course this is meaningless for 8 bits/pix */ ++ ++ CARD8 trueColour; /* If false then we need a "colour map" to ++ convert pixels to RGB. If true, xxxMax and ++ xxxShift specify bits used for red, green ++ and blue */ ++ ++ /* the following fields are only meaningful if trueColour is true */ ++ ++ CARD16 redMax; /* maximum red value (= 2^n - 1 where n is the ++ number of bits used for red). Note this ++ value is always in big endian order. */ ++ ++ CARD16 greenMax; /* similar for green */ ++ ++ CARD16 blueMax; /* and blue */ ++ ++ CARD8 redShift; /* number of shifts needed to get the red ++ value in a pixel to the least significant ++ bit. To find the red value from a given ++ pixel, do the following: ++ 1) Swap pixel value according to bigEndian ++ (e.g. if bigEndian is false and host byte ++ order is big endian, then swap). ++ 2) Shift right by redShift. ++ 3) AND with redMax (in host byte order). ++ 4) You now have the red value between 0 and ++ redMax. */ ++ ++ CARD8 greenShift; /* similar for green */ ++ ++ CARD8 blueShift; /* and blue */ ++ ++ CARD8 pad1; ++ CARD16 pad2; ++ ++} rfbPixelFormat; ++ ++#define sz_rfbPixelFormat 16 ++ ++ ++/*----------------------------------------------------------------------------- ++ * Structure used to describe protocol options such as tunneling methods, ++ * authentication schemes and message types (protocol version 3.7t). ++ */ ++ ++typedef struct _rfbCapabilityInfo { ++ ++ CARD32 code; /* numeric identifier */ ++ CARD8 vendorSignature[4]; /* vendor identification */ ++ CARD8 nameSignature[8]; /* abbreviated option name */ ++ ++} rfbCapabilityInfo; ++ ++#define sz_rfbCapabilityInfoVendor 4 ++#define sz_rfbCapabilityInfoName 8 ++#define sz_rfbCapabilityInfo 16 ++ ++/* ++ * Vendors known by TightVNC: standard VNC/RealVNC, TridiaVNC, and TightVNC. ++ */ ++ ++#define rfbStandardVendor "STDV" ++#define rfbTridiaVncVendor "TRDV" ++#define rfbTightVncVendor "TGHT" ++#define rfbTungstenGraphicsVendor "TGIV" ++ ++ ++/***************************************************************************** ++ * ++ * Initial handshaking messages ++ * ++ *****************************************************************************/ ++ ++/*----------------------------------------------------------------------------- ++ * Protocol Version ++ * ++ * The server always sends 12 bytes to start which identifies the latest RFB ++ * protocol version number which it supports. These bytes are interpreted ++ * as a string of 12 ASCII characters in the format "RFB xxx.yyy\n" where ++ * xxx and yyy are the major and minor version numbers (for version 3.7 ++ * this is "RFB 003.007\n"). ++ * ++ * The client then replies with a similar 12-byte message giving the version ++ * number of the protocol which should actually be used (which may be different ++ * to that quoted by the server). ++ * ++ * It is intended that both clients and servers may provide some level of ++ * backwards compatibility by this mechanism. Servers in particular should ++ * attempt to provide backwards compatibility, and even forwards compatibility ++ * to some extent. For example if a client demands version 3.1 of the ++ * protocol, a 3.0 server can probably assume that by ignoring requests for ++ * encoding types it doesn't understand, everything will still work OK. This ++ * will probably not be the case for changes in the major version number. ++ * ++ * The format string below can be used in sprintf or sscanf to generate or ++ * decode the version string respectively. ++ */ ++ ++#define rfbProtocolVersionFormat "RFB %03d.%03d\n" ++#define rfbProtocolMajorVersion 3 ++#define rfbProtocolMinorVersion 7 ++#define rfbProtocolFallbackMinorVersion 3 ++ ++typedef char rfbProtocolVersionMsg[13]; /* allow extra byte for null */ ++ ++#define sz_rfbProtocolVersionMsg 12 ++ ++ ++/* ++ * Negotiation of the security type (protocol version 3.7) ++ * ++ * Once the protocol version has been decided, the server either sends a list ++ * of supported security types, or informs the client about an error (when the ++ * number of security types is 0). Security type rfbSecTypeTight is used to ++ * enable TightVNC-specific protocol extensions. The value rfbSecTypeVncAuth ++ * stands for classic VNC authentication. ++ * ++ * The client selects a particular security type from the list provided by the ++ * server. ++ */ ++ ++#define rfbSecTypeInvalid 0 ++#define rfbSecTypeNone 1 ++#define rfbSecTypeVncAuth 2 ++#define rfbSecTypeTight 16 ++ ++ ++/*----------------------------------------------------------------------------- ++ * Negotiation of Tunneling Capabilities (protocol version 3.7t) ++ * ++ * If the chosen security type is rfbSecTypeTight, the server sends a list of ++ * supported tunneling methods ("tunneling" refers to any additional layer of ++ * data transformation, such as encryption or external compression.) ++ * ++ * nTunnelTypes specifies the number of following rfbCapabilityInfo structures ++ * that list all supported tunneling methods in the order of preference. ++ * ++ * NOTE: If nTunnelTypes is 0, that tells the client that no tunneling can be ++ * used, and the client should not send a response requesting a tunneling ++ * method. ++ */ ++ ++typedef struct _rfbTunnelingCapsMsg { ++ CARD32 nTunnelTypes; ++ /* followed by nTunnelTypes * rfbCapabilityInfo structures */ ++} rfbTunnelingCapsMsg; ++ ++#define sz_rfbTunnelingCapsMsg 4 ++ ++/*----------------------------------------------------------------------------- ++ * Tunneling Method Request (protocol version 3.7t) ++ * ++ * If the list of tunneling capabilities sent by the server was not empty, the ++ * client should reply with a 32-bit code specifying a particular tunneling ++ * method. The following code should be used for no tunneling. ++ */ ++ ++#define rfbNoTunneling 0 ++#define sig_rfbNoTunneling "NOTUNNEL" ++ ++ ++/*----------------------------------------------------------------------------- ++ * Negotiation of Authentication Capabilities (protocol version 3.7t) ++ * ++ * After setting up tunneling, the server sends a list of supported ++ * authentication schemes. ++ * ++ * nAuthTypes specifies the number of following rfbCapabilityInfo structures ++ * that list all supported authentication schemes in the order of preference. ++ * ++ * NOTE: If nAuthTypes is 0, that tells the client that no authentication is ++ * necessary, and the client should not send a response requesting an ++ * authentication scheme. ++ */ ++ ++typedef struct _rfbAuthenticationCapsMsg { ++ CARD32 nAuthTypes; ++ /* followed by nAuthTypes * rfbCapabilityInfo structures */ ++} rfbAuthenticationCapsMsg; ++ ++#define sz_rfbAuthenticationCapsMsg 4 ++ ++/*----------------------------------------------------------------------------- ++ * Authentication Scheme Request (protocol version 3.7t) ++ * ++ * If the list of authentication capabilities sent by the server was not empty, ++ * the client should reply with a 32-bit code specifying a particular ++ * authentication scheme. The following codes are supported. ++ */ ++ ++#define rfbAuthNone 1 ++#define rfbAuthVNC 2 ++#define rfbAuthUnixLogin 129 ++#define rfbAuthExternal 130 ++ ++#define sig_rfbAuthNone "NOAUTH__" ++#define sig_rfbAuthVNC "VNCAUTH_" ++#define sig_rfbAuthUnixLogin "ULGNAUTH" ++#define sig_rfbAuthExternal "XTRNAUTH" ++ ++ ++/*----------------------------------------------------------------------------- ++ * Standard VNC Authentication (all protocol versions) ++ * ++ * Standard authentication result codes are defined below. ++ */ ++ ++#define rfbVncAuthOK 0 ++#define rfbVncAuthFailed 1 ++#define rfbVncAuthTooMany 2 ++ ++ ++/*----------------------------------------------------------------------------- ++ * Client Initialisation Message ++ * ++ * Once the client and server are sure that they're happy to talk to one ++ * another, the client sends an initialisation message. At present this ++ * message only consists of a boolean indicating whether the server should try ++ * to share the desktop by leaving other clients connected, or give exclusive ++ * access to this client by disconnecting all other clients. ++ */ ++ ++typedef struct _rfbClientInitMsg { ++ CARD8 shared; ++} rfbClientInitMsg; ++ ++#define sz_rfbClientInitMsg 1 ++ ++ ++/*----------------------------------------------------------------------------- ++ * Server Initialisation Message ++ * ++ * After the client initialisation message, the server sends one of its own. ++ * This tells the client the width and height of the server's framebuffer, ++ * its pixel format and the name associated with the desktop. ++ */ ++ ++typedef struct _rfbServerInitMsg { ++ CARD16 framebufferWidth; ++ CARD16 framebufferHeight; ++ rfbPixelFormat format; /* the server's preferred pixel format */ ++ CARD32 nameLength; ++ /* followed by char name[nameLength] */ ++} rfbServerInitMsg; ++ ++#define sz_rfbServerInitMsg (8 + sz_rfbPixelFormat) ++ ++ ++/*----------------------------------------------------------------------------- ++ * Server Interaction Capabilities Message (protocol version 3.7t) ++ * ++ * In the protocol version 3.7t, the server informs the client what message ++ * types it supports in addition to ones defined in the protocol version 3.7. ++ * Also, the server sends the list of all supported encodings (note that it's ++ * not necessary to advertise the "raw" encoding sinse it MUST be supported in ++ * RFB 3.x protocols). ++ * ++ * This data immediately follows the server initialisation message. ++ */ ++ ++typedef struct _rfbInteractionCapsMsg { ++ CARD16 nServerMessageTypes; ++ CARD16 nClientMessageTypes; ++ CARD16 nEncodingTypes; ++ CARD16 pad; /* reserved, must be 0 */ ++ /* followed by nServerMessageTypes * rfbCapabilityInfo structures */ ++ /* followed by nClientMessageTypes * rfbCapabilityInfo structures */ ++} rfbInteractionCapsMsg; ++ ++#define sz_rfbInteractionCapsMsg 8 ++ ++ ++/* ++ * Following the server initialisation message it's up to the client to send ++ * whichever protocol messages it wants. Typically it will send a ++ * SetPixelFormat message and a SetEncodings message, followed by a ++ * FramebufferUpdateRequest. From then on the server will send ++ * FramebufferUpdate messages in response to the client's ++ * FramebufferUpdateRequest messages. The client should send ++ * FramebufferUpdateRequest messages with incremental set to true when it has ++ * finished processing one FramebufferUpdate and is ready to process another. ++ * With a fast client, the rate at which FramebufferUpdateRequests are sent ++ * should be regulated to avoid hogging the network. ++ */ ++ ++ ++ ++/***************************************************************************** ++ * ++ * Message types ++ * ++ *****************************************************************************/ ++ ++/* server -> client */ ++ ++#define rfbFramebufferUpdate 0 ++#define rfbSetColourMapEntries 1 ++#define rfbBell 2 ++#define rfbServerCutText 3 ++/* Chromium extensions, use higher values */ ++#define rfbChromiumStart 50 ++#define rfbChromiumMoveResizeWindow 51 ++#define rfbChromiumClipList 52 ++#define rfbChromiumWindowShow 53 ++#define rfbChromiumWindowDestroy 54 ++ ++#define rfbFileListData 130 ++#define rfbFileDownloadData 131 ++#define rfbFileUploadCancel 132 ++#define rfbFileDownloadFailed 133 ++ ++/* signatures for non-standard messages */ ++#define sig_rfbFileListData "FTS_LSDT" ++#define sig_rfbFileDownloadData "FTS_DNDT" ++#define sig_rfbFileUploadCancel "FTS_UPCN" ++#define sig_rfbFileDownloadFailed "FTS_DNFL" ++ ++ ++/* client -> server */ ++ ++#define rfbSetPixelFormat 0 ++#define rfbFixColourMapEntries 1 /* not currently supported */ ++#define rfbSetEncodings 2 ++#define rfbFramebufferUpdateRequest 3 ++#define rfbKeyEvent 4 ++#define rfbPointerEvent 5 ++#define rfbClientCutText 6 ++/* Chromium extensions, use higher values */ ++#define rfbChromiumStop 50 ++#define rfbChromiumExpose 51 ++ ++#define rfbFileListRequest 130 ++#define rfbFileDownloadRequest 131 ++#define rfbFileUploadRequest 132 ++#define rfbFileUploadData 133 ++#define rfbFileDownloadCancel 134 ++#define rfbFileUploadFailed 135 ++#define rfbFileCreateDirRequest 136 ++ ++/* signatures for non-standard messages */ ++#define sig_rfbFileListRequest "FTC_LSRQ" ++#define sig_rfbFileDownloadRequest "FTC_DNRQ" ++#define sig_rfbFileUploadRequest "FTC_UPRQ" ++#define sig_rfbFileUploadData "FTC_UPDT" ++#define sig_rfbFileDownloadCancel "FTC_DNCN" ++#define sig_rfbFileUploadFailed "FTC_UPFL" ++#define sig_rfbFileCreateDirRequest "FTC_FCDR" ++ ++/***************************************************************************** ++ * ++ * Encoding types ++ * ++ *****************************************************************************/ ++ ++#define rfbEncodingRaw 0 ++#define rfbEncodingCopyRect 1 ++#define rfbEncodingRRE 2 ++#define rfbEncodingCoRRE 4 ++#define rfbEncodingHextile 5 ++#define rfbEncodingZlib 6 ++#define rfbEncodingTight 7 ++#define rfbEncodingZlibHex 8 ++ ++/* signatures for basic encoding types */ ++#define sig_rfbEncodingRaw "RAW_____" ++#define sig_rfbEncodingCopyRect "COPYRECT" ++#define sig_rfbEncodingRRE "RRE_____" ++#define sig_rfbEncodingCoRRE "CORRE___" ++#define sig_rfbEncodingHextile "HEXTILE_" ++#define sig_rfbEncodingZlib "ZLIB____" ++#define sig_rfbEncodingTight "TIGHT___" ++#define sig_rfbEncodingZlibHex "ZLIBHEX_" ++#define sig_rfbEncodingChromium "CHROMIUM" ++ ++/* ++ * Special encoding numbers: ++ * 0xFFFFFF00 .. 0xFFFFFF0F -- encoding-specific compression levels; ++ * 0xFFFFFF10 .. 0xFFFFFF1F -- mouse cursor shape data; ++ * 0xFFFFFF20 .. 0xFFFFFF2F -- various protocol extensions; ++ * 0xFFFFFF30 .. 0xFFFFFFDF -- not allocated yet; ++ * 0xFFFFFFE0 .. 0xFFFFFFEF -- quality level for JPEG compressor; ++ * 0xFFFFFFF0 .. 0xFFFFFFFF -- not allocated yet. ++ */ ++ ++#define rfbEncodingCompressLevel0 0xFFFFFF00 ++#define rfbEncodingCompressLevel1 0xFFFFFF01 ++#define rfbEncodingCompressLevel2 0xFFFFFF02 ++#define rfbEncodingCompressLevel3 0xFFFFFF03 ++#define rfbEncodingCompressLevel4 0xFFFFFF04 ++#define rfbEncodingCompressLevel5 0xFFFFFF05 ++#define rfbEncodingCompressLevel6 0xFFFFFF06 ++#define rfbEncodingCompressLevel7 0xFFFFFF07 ++#define rfbEncodingCompressLevel8 0xFFFFFF08 ++#define rfbEncodingCompressLevel9 0xFFFFFF09 ++ ++#define rfbEncodingXCursor 0xFFFFFF10 ++#define rfbEncodingRichCursor 0xFFFFFF11 ++#define rfbEncodingPointerPos 0xFFFFFF18 ++ ++#define rfbEncodingLastRect 0xFFFFFF20 ++#define rfbEncodingNewFBSize 0xFFFFFF21 ++#define rfbEncodingChromium 0xFFFFFF2F ++#define rfbEncodingChromium2 0xFFFFFF30 ++ ++#define rfbEncodingQualityLevel0 0xFFFFFFE0 ++#define rfbEncodingQualityLevel1 0xFFFFFFE1 ++#define rfbEncodingQualityLevel2 0xFFFFFFE2 ++#define rfbEncodingQualityLevel3 0xFFFFFFE3 ++#define rfbEncodingQualityLevel4 0xFFFFFFE4 ++#define rfbEncodingQualityLevel5 0xFFFFFFE5 ++#define rfbEncodingQualityLevel6 0xFFFFFFE6 ++#define rfbEncodingQualityLevel7 0xFFFFFFE7 ++#define rfbEncodingQualityLevel8 0xFFFFFFE8 ++#define rfbEncodingQualityLevel9 0xFFFFFFE9 ++ ++/* signatures for "fake" encoding types */ ++#define sig_rfbEncodingCompressLevel0 "COMPRLVL" ++#define sig_rfbEncodingXCursor "X11CURSR" ++#define sig_rfbEncodingRichCursor "RCHCURSR" ++#define sig_rfbEncodingPointerPos "POINTPOS" ++#define sig_rfbEncodingLastRect "LASTRECT" ++#define sig_rfbEncodingNewFBSize "NEWFBSIZ" ++#define sig_rfbEncodingQualityLevel0 "JPEGQLVL" ++ ++ ++/***************************************************************************** ++ * ++ * Server -> client message definitions ++ * ++ *****************************************************************************/ ++ ++ ++/*----------------------------------------------------------------------------- ++ * FramebufferUpdate - a block of rectangles to be copied to the framebuffer. ++ * ++ * This message consists of a header giving the number of rectangles of pixel ++ * data followed by the rectangles themselves. The header is padded so that ++ * together with the type byte it is an exact multiple of 4 bytes (to help ++ * with alignment of 32-bit pixels): ++ */ ++ ++typedef struct _rfbFramebufferUpdateMsg { ++ CARD8 type; /* always rfbFramebufferUpdate */ ++ CARD8 pad; ++ CARD16 nRects; ++ /* followed by nRects rectangles */ ++} rfbFramebufferUpdateMsg; ++ ++#define sz_rfbFramebufferUpdateMsg 4 ++ ++/* ++ * Each rectangle of pixel data consists of a header describing the position ++ * and size of the rectangle and a type word describing the encoding of the ++ * pixel data, followed finally by the pixel data. Note that if the client has ++ * not sent a SetEncodings message then it will only receive raw pixel data. ++ * Also note again that this structure is a multiple of 4 bytes. ++ */ ++ ++typedef struct _rfbFramebufferUpdateRectHeader { ++ rfbRectangle r; ++ CARD32 encoding; /* one of the encoding types rfbEncoding... */ ++} rfbFramebufferUpdateRectHeader; ++ ++#define sz_rfbFramebufferUpdateRectHeader (sz_rfbRectangle + 4) ++ ++ ++/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ++ * Raw Encoding. Pixels are sent in top-to-bottom scanline order, ++ * left-to-right within a scanline with no padding in between. ++ */ ++ ++ ++/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ++ * CopyRect Encoding. The pixels are specified simply by the x and y position ++ * of the source rectangle. ++ */ ++ ++typedef struct _rfbCopyRect { ++ CARD16 srcX; ++ CARD16 srcY; ++} rfbCopyRect; ++ ++#define sz_rfbCopyRect 4 ++ ++ ++/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ++ * RRE - Rise-and-Run-length Encoding. We have an rfbRREHeader structure ++ * giving the number of subrectangles following. Finally the data follows in ++ * the form [...] where each is ++ * []. ++ */ ++ ++typedef struct _rfbRREHeader { ++ CARD32 nSubrects; ++} rfbRREHeader; ++ ++#define sz_rfbRREHeader 4 ++ ++ ++/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ++ * CoRRE - Compact RRE Encoding. We have an rfbRREHeader structure giving ++ * the number of subrectangles following. Finally the data follows in the form ++ * [...] where each is ++ * []. This means that ++ * the whole rectangle must be at most 255x255 pixels. ++ */ ++ ++typedef struct _rfbCoRRERectangle { ++ CARD8 x; ++ CARD8 y; ++ CARD8 w; ++ CARD8 h; ++} rfbCoRRERectangle; ++ ++#define sz_rfbCoRRERectangle 4 ++ ++ ++/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ++ * Hextile Encoding. The rectangle is divided up into "tiles" of 16x16 pixels, ++ * starting at the top left going in left-to-right, top-to-bottom order. If ++ * the width of the rectangle is not an exact multiple of 16 then the width of ++ * the last tile in each row will be correspondingly smaller. Similarly if the ++ * height is not an exact multiple of 16 then the height of each tile in the ++ * final row will also be smaller. Each tile begins with a "subencoding" type ++ * byte, which is a mask made up of a number of bits. If the Raw bit is set ++ * then the other bits are irrelevant; w*h pixel values follow (where w and h ++ * are the width and height of the tile). Otherwise the tile is encoded in a ++ * similar way to RRE, except that the position and size of each subrectangle ++ * can be specified in just two bytes. The other bits in the mask are as ++ * follows: ++ * ++ * BackgroundSpecified - if set, a pixel value follows which specifies ++ * the background colour for this tile. The first non-raw tile in a ++ * rectangle must have this bit set. If this bit isn't set then the ++ * background is the same as the last tile. ++ * ++ * ForegroundSpecified - if set, a pixel value follows which specifies ++ * the foreground colour to be used for all subrectangles in this tile. ++ * If this bit is set then the SubrectsColoured bit must be zero. ++ * ++ * AnySubrects - if set, a single byte follows giving the number of ++ * subrectangles following. If not set, there are no subrectangles (i.e. ++ * the whole tile is just solid background colour). ++ * ++ * SubrectsColoured - if set then each subrectangle is preceded by a pixel ++ * value giving the colour of that subrectangle. If not set, all ++ * subrectangles are the same colour, the foreground colour; if the ++ * ForegroundSpecified bit wasn't set then the foreground is the same as ++ * the last tile. ++ * ++ * The position and size of each subrectangle is specified in two bytes. The ++ * Pack macros below can be used to generate the two bytes from x, y, w, h, ++ * and the Extract macros can be used to extract the x, y, w, h values from ++ * the two bytes. ++ */ ++ ++#define rfbHextileRaw (1 << 0) ++#define rfbHextileBackgroundSpecified (1 << 1) ++#define rfbHextileForegroundSpecified (1 << 2) ++#define rfbHextileAnySubrects (1 << 3) ++#define rfbHextileSubrectsColoured (1 << 4) ++ ++#define rfbHextilePackXY(x,y) (((x) << 4) | (y)) ++#define rfbHextilePackWH(w,h) ((((w)-1) << 4) | ((h)-1)) ++#define rfbHextileExtractX(byte) ((byte) >> 4) ++#define rfbHextileExtractY(byte) ((byte) & 0xf) ++#define rfbHextileExtractW(byte) (((byte) >> 4) + 1) ++#define rfbHextileExtractH(byte) (((byte) & 0xf) + 1) ++ ++/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ++ * ZLIB - zlib compression Encoding. We have an rfbZlibHeader structure ++ * giving the number of bytes to follow. Finally the data follows in ++ * zlib compressed format. ++ */ ++ ++typedef struct _rfbZlibHeader { ++ CARD32 nBytes; ++} rfbZlibHeader; ++ ++#define sz_rfbZlibHeader 4 ++ ++ ++/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ++ * Tight Encoding. ++ * ++ *-- The first byte of each Tight-encoded rectangle is a "compression control ++ * byte". Its format is as follows (bit 0 is the least significant one): ++ * ++ * bit 0: if 1, then compression stream 0 should be reset; ++ * bit 1: if 1, then compression stream 1 should be reset; ++ * bit 2: if 1, then compression stream 2 should be reset; ++ * bit 3: if 1, then compression stream 3 should be reset; ++ * bits 7-4: if 1000 (0x08), then the compression type is "fill", ++ * if 1001 (0x09), then the compression type is "jpeg", ++ * if 0xxx, then the compression type is "basic", ++ * values greater than 1001 are not valid. ++ * ++ * If the compression type is "basic", then bits 6..4 of the ++ * compression control byte (those xxx in 0xxx) specify the following: ++ * ++ * bits 5-4: decimal representation is the index of a particular zlib ++ * stream which should be used for decompressing the data; ++ * bit 6: if 1, then a "filter id" byte is following this byte. ++ * ++ *-- The data that follows after the compression control byte described ++ * above depends on the compression type ("fill", "jpeg" or "basic"). ++ * ++ *-- If the compression type is "fill", then the only pixel value follows, in ++ * client pixel format (see NOTE 1). This value applies to all pixels of the ++ * rectangle. ++ * ++ *-- If the compression type is "jpeg", the following data stream looks like ++ * this: ++ * ++ * 1..3 bytes: data size (N) in compact representation; ++ * N bytes: JPEG image. ++ * ++ * Data size is compactly represented in one, two or three bytes, according ++ * to the following scheme: ++ * ++ * 0xxxxxxx (for values 0..127) ++ * 1xxxxxxx 0yyyyyyy (for values 128..16383) ++ * 1xxxxxxx 1yyyyyyy zzzzzzzz (for values 16384..4194303) ++ * ++ * Here each character denotes one bit, xxxxxxx are the least significant 7 ++ * bits of the value (bits 0-6), yyyyyyy are bits 7-13, and zzzzzzzz are the ++ * most significant 8 bits (bits 14-21). For example, decimal value 10000 ++ * should be represented as two bytes: binary 10010000 01001110, or ++ * hexadecimal 90 4E. ++ * ++ *-- If the compression type is "basic" and bit 6 of the compression control ++ * byte was set to 1, then the next (second) byte specifies "filter id" which ++ * tells the decoder what filter type was used by the encoder to pre-process ++ * pixel data before the compression. The "filter id" byte can be one of the ++ * following: ++ * ++ * 0: no filter ("copy" filter); ++ * 1: "palette" filter; ++ * 2: "gradient" filter. ++ * ++ *-- If bit 6 of the compression control byte is set to 0 (no "filter id" ++ * byte), or if the filter id is 0, then raw pixel values in the client ++ * format (see NOTE 1) will be compressed. See below details on the ++ * compression. ++ * ++ *-- The "gradient" filter pre-processes pixel data with a simple algorithm ++ * which converts each color component to a difference between a "predicted" ++ * intensity and the actual intensity. Such a technique does not affect ++ * uncompressed data size, but helps to compress photo-like images better. ++ * Pseudo-code for converting intensities to differences is the following: ++ * ++ * P[i,j] := V[i-1,j] + V[i,j-1] - V[i-1,j-1]; ++ * if (P[i,j] < 0) then P[i,j] := 0; ++ * if (P[i,j] > MAX) then P[i,j] := MAX; ++ * D[i,j] := V[i,j] - P[i,j]; ++ * ++ * Here V[i,j] is the intensity of a color component for a pixel at ++ * coordinates (i,j). MAX is the maximum value of intensity for a color ++ * component. ++ * ++ *-- The "palette" filter converts true-color pixel data to indexed colors ++ * and a palette which can consist of 2..256 colors. If the number of colors ++ * is 2, then each pixel is encoded in 1 bit, otherwise 8 bits is used to ++ * encode one pixel. 1-bit encoding is performed such way that the most ++ * significant bits correspond to the leftmost pixels, and each raw of pixels ++ * is aligned to the byte boundary. When "palette" filter is used, the ++ * palette is sent before the pixel data. The palette begins with an unsigned ++ * byte which value is the number of colors in the palette minus 1 (i.e. 1 ++ * means 2 colors, 255 means 256 colors in the palette). Then follows the ++ * palette itself which consist of pixel values in client pixel format (see ++ * NOTE 1). ++ * ++ *-- The pixel data is compressed using the zlib library. But if the data ++ * size after applying the filter but before the compression is less then 12, ++ * then the data is sent as is, uncompressed. Four separate zlib streams ++ * (0..3) can be used and the decoder should read the actual stream id from ++ * the compression control byte (see NOTE 2). ++ * ++ * If the compression is not used, then the pixel data is sent as is, ++ * otherwise the data stream looks like this: ++ * ++ * 1..3 bytes: data size (N) in compact representation; ++ * N bytes: zlib-compressed data. ++ * ++ * Data size is compactly represented in one, two or three bytes, just like ++ * in the "jpeg" compression method (see above). ++ * ++ *-- NOTE 1. If the color depth is 24, and all three color components are ++ * 8-bit wide, then one pixel in Tight encoding is always represented by ++ * three bytes, where the first byte is red component, the second byte is ++ * green component, and the third byte is blue component of the pixel color ++ * value. This applies to colors in palettes as well. ++ * ++ *-- NOTE 2. The decoder must reset compression streams' states before ++ * decoding the rectangle, if some of bits 0,1,2,3 in the compression control ++ * byte are set to 1. Note that the decoder must reset zlib streams even if ++ * the compression type is "fill" or "jpeg". ++ * ++ *-- NOTE 3. The "gradient" filter and "jpeg" compression may be used only ++ * when bits-per-pixel value is either 16 or 32, not 8. ++ * ++ *-- NOTE 4. The width of any Tight-encoded rectangle cannot exceed 2048 ++ * pixels. If a rectangle is wider, it must be split into several rectangles ++ * and each one should be encoded separately. ++ * ++ */ ++ ++#define rfbTightExplicitFilter 0x04 ++#define rfbTightFill 0x08 ++#define rfbTightJpeg 0x09 ++#define rfbTightMaxSubencoding 0x09 ++ ++/* Filters to improve compression efficiency */ ++#define rfbTightFilterCopy 0x00 ++#define rfbTightFilterPalette 0x01 ++#define rfbTightFilterGradient 0x02 ++ ++ ++/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ++ * ZLIBHEX - zlib compressed Hextile Encoding. Essentially, this is the ++ * hextile encoding with zlib compression on the tiles that can not be ++ * efficiently encoded with one of the other hextile subencodings. The ++ * new zlib subencoding uses two bytes to specify the length of the ++ * compressed tile and then the compressed data follows. As with the ++ * raw sub-encoding, the zlib subencoding invalidates the other ++ * values, if they are also set. ++ */ ++ ++#define rfbHextileZlibRaw (1 << 5) ++#define rfbHextileZlibHex (1 << 6) ++ ++ ++/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ++ * XCursor encoding. This is a special encoding used to transmit X-style ++ * cursor shapes from server to clients. Note that for this encoding, ++ * coordinates in rfbFramebufferUpdateRectHeader structure hold hotspot ++ * position (r.x, r.y) and cursor size (r.w, r.h). If (w * h != 0), two RGB ++ * samples are sent after header in the rfbXCursorColors structure. They ++ * denote foreground and background colors of the cursor. If a client ++ * supports only black-and-white cursors, it should ignore these colors and ++ * assume that foreground is black and background is white. Next, two bitmaps ++ * (1 bits per pixel) follow: first one with actual data (value 0 denotes ++ * background color, value 1 denotes foreground color), second one with ++ * transparency data (bits with zero value mean that these pixels are ++ * transparent). Both bitmaps represent cursor data in a byte stream, from ++ * left to right, from top to bottom, and each row is byte-aligned. Most ++ * significant bits correspond to leftmost pixels. The number of bytes in ++ * each row can be calculated as ((w + 7) / 8). If (w * h == 0), cursor ++ * should be hidden (or default local cursor should be set by the client). ++ */ ++ ++typedef struct _rfbXCursorColors { ++ CARD8 foreRed; ++ CARD8 foreGreen; ++ CARD8 foreBlue; ++ CARD8 backRed; ++ CARD8 backGreen; ++ CARD8 backBlue; ++} rfbXCursorColors; ++ ++#define sz_rfbXCursorColors 6 ++ ++ ++/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ++ * RichCursor encoding. This is a special encoding used to transmit cursor ++ * shapes from server to clients. It is similar to the XCursor encoding but ++ * uses client pixel format instead of two RGB colors to represent cursor ++ * image. For this encoding, coordinates in rfbFramebufferUpdateRectHeader ++ * structure hold hotspot position (r.x, r.y) and cursor size (r.w, r.h). ++ * After header, two pixmaps follow: first one with cursor image in current ++ * client pixel format (like in raw encoding), second with transparency data ++ * (1 bit per pixel, exactly the same format as used for transparency bitmap ++ * in the XCursor encoding). If (w * h == 0), cursor should be hidden (or ++ * default local cursor should be set by the client). ++ */ ++ ++ ++/*----------------------------------------------------------------------------- ++ * SetColourMapEntries - these messages are only sent if the pixel ++ * format uses a "colour map" (i.e. trueColour false) and the client has not ++ * fixed the entire colour map using FixColourMapEntries. In addition they ++ * will only start being sent after the client has sent its first ++ * FramebufferUpdateRequest. So if the client always tells the server to use ++ * trueColour then it never needs to process this type of message. ++ */ ++ ++typedef struct _rfbSetColourMapEntriesMsg { ++ CARD8 type; /* always rfbSetColourMapEntries */ ++ CARD8 redIndex; /* used to be pad, but used for DirectColor */ ++ CARD16 firstColour; ++ CARD16 nColours; ++ ++ /* Followed by nColours * 3 * CARD16 ++ r1, g1, b1, r2, g2, b2, r3, g3, b3, ..., rn, bn, gn */ ++ ++} rfbSetColourMapEntriesMsg; ++ ++#define sz_rfbSetColourMapEntriesMsg 6 ++ ++ ++ ++/*----------------------------------------------------------------------------- ++ * Bell - ring a bell on the client if it has one. ++ */ ++ ++typedef struct _rfbBellMsg { ++ CARD8 type; /* always rfbBell */ ++} rfbBellMsg; ++ ++#define sz_rfbBellMsg 1 ++ ++ ++ ++/*----------------------------------------------------------------------------- ++ * ServerCutText - the server has new text in its cut buffer. ++ */ ++ ++typedef struct _rfbServerCutTextMsg { ++ CARD8 type; /* always rfbServerCutText */ ++ CARD8 pad1; ++ CARD16 pad2; ++ CARD32 length; ++ /* followed by char text[length] */ ++} rfbServerCutTextMsg; ++ ++#define sz_rfbServerCutTextMsg 8 ++ ++/*----------------------------------------------------------------------------- ++ * ChromiumStart - a port number for the crserver ++ */ ++ ++typedef struct { ++ CARD8 type; /* always rfbChromiumStart */ ++ CARD8 pad1; ++ CARD16 pad2; ++ CARD32 crServerPort; ++ CARD32 mothershipPort; ++} rfbChromiumStartMsg; ++ ++#define sz_rfbChromiumStartMsg 12 ++ ++ ++/*----------------------------------------------------------------------------- ++ * ChromiumMoveResizeWindow - move a chromium window ++ */ ++ ++typedef struct { ++ CARD8 type; /* always rfbChromiumMoveResizeWindow */ ++ CARD8 pad1; ++ CARD16 pad2; ++ CARD32 winid; ++ CARD32 x; ++ CARD32 y; ++ CARD32 w; ++ CARD32 h; ++} rfbChromiumMoveResizeWindowMsg; ++ ++#define sz_rfbChromiumMoveResizeWindowMsg 24 ++ ++/*----------------------------------------------------------------------------- ++ * ChromiumClipList - send clip list ++ */ ++ ++typedef struct { ++ CARD8 type; /* always rfbChromiumClipList */ ++ CARD8 pad1; ++ CARD16 pad2; ++ CARD32 winid; ++ CARD32 length; ++} rfbChromiumClipListMsg; ++ ++#define sz_rfbChromiumClipListMsg 12 ++ ++/*----------------------------------------------------------------------------- ++ * ChromiumWindowShow - map or unmap a window ++ */ ++ ++typedef struct { ++ CARD8 type; /* always rfbChromiumWindowShow */ ++ CARD8 pad1; ++ CARD16 pad2; ++ CARD32 winid; ++ CARD32 show; ++} rfbChromiumWindowShowMsg; ++ ++#define sz_rfbChromiumWindowShowMsg 12 ++ ++/*----------------------------------------------------------------------------- ++ * ChromiumWindowDestroy - destroy a window ++ */ ++ ++typedef struct { ++ CARD8 type; /* always rfbChromiumWindowDestroy */ ++ CARD8 pad1; ++ CARD16 pad2; ++ CARD32 winid; ++} rfbChromiumWindowDestroyMsg; ++ ++#define sz_rfbChromiumWindowDestroyMsg 8 ++ ++/*----------------------------------------------------------------------------- ++ * FileListData ++ */ ++ ++typedef struct _rfbFileListDataMsg { ++ CARD8 type; ++ CARD8 flags; ++ CARD16 numFiles; ++ CARD16 dataSize; ++ CARD16 compressedSize; ++ /* Followed by SizeData[numFiles] */ ++ /* Followed by Filenames[compressedSize] */ ++} rfbFileListDataMsg; ++ ++#define sz_rfbFileListDataMsg 8 ++ ++/*----------------------------------------------------------------------------- ++ * FileDownloadData ++ */ ++ ++typedef struct _rfbFileDownloadDataMsg { ++ CARD8 type; ++ CARD8 compressLevel; ++ CARD16 realSize; ++ CARD16 compressedSize; ++ /* Followed by File[copressedSize] */ ++} rfbFileDownloadDataMsg; ++ ++#define sz_rfbFileDownloadDataMsg 6 ++ ++ ++/*----------------------------------------------------------------------------- ++ * FileUploadCancel ++ */ ++ ++typedef struct _rfbFileUploadCancelMsg { ++ CARD8 type; ++ CARD8 unused; ++ CARD16 reasonLen; ++ /* Followed by reason[reasonLen] */ ++} rfbFileUploadCancelMsg; ++ ++#define sz_rfbFileUploadCancelMsg 4 ++ ++/*----------------------------------------------------------------------------- ++ * FileDownloadFailed ++ */ ++ ++typedef struct _rfbFileDownloadFailedMsg { ++ CARD8 type; ++ CARD8 unused; ++ CARD16 reasonLen; ++ /* Followed by reason[reasonLen] */ ++} rfbFileDownloadFailedMsg; ++ ++#define sz_rfbFileDownloadFailedMsg 4 ++ ++/*----------------------------------------------------------------------------- ++ * Union of all server->client messages. ++ */ ++ ++typedef union _rfbServerToClientMsg { ++ CARD8 type; ++ rfbFramebufferUpdateMsg fu; ++ rfbSetColourMapEntriesMsg scme; ++ rfbBellMsg b; ++ rfbServerCutTextMsg sct; ++ rfbFileListDataMsg fld; ++ rfbFileDownloadDataMsg fdd; ++ rfbFileUploadCancelMsg fuc; ++ rfbFileDownloadFailedMsg fdf; ++ rfbChromiumStartMsg scd; ++ rfbChromiumMoveResizeWindowMsg scm; ++ rfbChromiumClipListMsg sccl; ++ rfbChromiumWindowShowMsg scws; ++ rfbChromiumWindowDestroyMsg scwd; ++} rfbServerToClientMsg; ++ ++ ++ ++/***************************************************************************** ++ * ++ * Message definitions (client -> server) ++ * ++ *****************************************************************************/ ++ ++ ++/*----------------------------------------------------------------------------- ++ * SetPixelFormat - tell the RFB server the format in which the client wants ++ * pixels sent. ++ */ ++ ++typedef struct _rfbSetPixelFormatMsg { ++ CARD8 type; /* always rfbSetPixelFormat */ ++ CARD8 pad1; ++ CARD16 pad2; ++ rfbPixelFormat format; ++} rfbSetPixelFormatMsg; ++ ++#define sz_rfbSetPixelFormatMsg (sz_rfbPixelFormat + 4) ++ ++ ++/*----------------------------------------------------------------------------- ++ * FixColourMapEntries - when the pixel format uses a "colour map", fix ++ * read-only colour map entries. ++ * ++ * ***************** NOT CURRENTLY SUPPORTED ***************** ++ */ ++ ++typedef struct _rfbFixColourMapEntriesMsg { ++ CARD8 type; /* always rfbFixColourMapEntries */ ++ CARD8 pad; ++ CARD16 firstColour; ++ CARD16 nColours; ++ ++ /* Followed by nColours * 3 * CARD16 ++ r1, g1, b1, r2, g2, b2, r3, g3, b3, ..., rn, bn, gn */ ++ ++} rfbFixColourMapEntriesMsg; ++ ++#define sz_rfbFixColourMapEntriesMsg 6 ++ ++ ++/*----------------------------------------------------------------------------- ++ * SetEncodings - tell the RFB server which encoding types we accept. Put them ++ * in order of preference, if we have any. We may always receive raw ++ * encoding, even if we don't specify it here. ++ */ ++ ++typedef struct _rfbSetEncodingsMsg { ++ CARD8 type; /* always rfbSetEncodings */ ++ CARD8 pad; ++ CARD16 nEncodings; ++ /* followed by nEncodings * CARD32 encoding types */ ++} rfbSetEncodingsMsg; ++ ++#define sz_rfbSetEncodingsMsg 4 ++ ++ ++/*----------------------------------------------------------------------------- ++ * FramebufferUpdateRequest - request for a framebuffer update. If incremental ++ * is true then the client just wants the changes since the last update. If ++ * false then it wants the whole of the specified rectangle. ++ */ ++ ++typedef struct _rfbFramebufferUpdateRequestMsg { ++ CARD8 type; /* always rfbFramebufferUpdateRequest */ ++ CARD8 incremental; ++ CARD16 x; ++ CARD16 y; ++ CARD16 w; ++ CARD16 h; ++} rfbFramebufferUpdateRequestMsg; ++ ++#define sz_rfbFramebufferUpdateRequestMsg 10 ++ ++ ++/*----------------------------------------------------------------------------- ++ * KeyEvent - key press or release ++ * ++ * Keys are specified using the "keysym" values defined by the X Window System. ++ * For most ordinary keys, the keysym is the same as the corresponding ASCII ++ * value. Other common keys are: ++ * ++ * BackSpace 0xff08 ++ * Tab 0xff09 ++ * Return or Enter 0xff0d ++ * Escape 0xff1b ++ * Insert 0xff63 ++ * Delete 0xffff ++ * Home 0xff50 ++ * End 0xff57 ++ * Page Up 0xff55 ++ * Page Down 0xff56 ++ * Left 0xff51 ++ * Up 0xff52 ++ * Right 0xff53 ++ * Down 0xff54 ++ * F1 0xffbe ++ * F2 0xffbf ++ * ... ... ++ * F12 0xffc9 ++ * Shift 0xffe1 ++ * Control 0xffe3 ++ * Meta 0xffe7 ++ * Alt 0xffe9 ++ */ ++ ++typedef struct _rfbKeyEventMsg { ++ CARD8 type; /* always rfbKeyEvent */ ++ CARD8 down; /* true if down (press), false if up */ ++ CARD16 pad; ++ CARD32 key; /* key is specified as an X keysym */ ++} rfbKeyEventMsg; ++ ++#define sz_rfbKeyEventMsg 8 ++ ++ ++/*----------------------------------------------------------------------------- ++ * PointerEvent - mouse/pen move and/or button press. ++ */ ++ ++typedef struct _rfbPointerEventMsg { ++ CARD8 type; /* always rfbPointerEvent */ ++ CARD8 buttonMask; /* bits 0-7 are buttons 1-8, 0=up, 1=down */ ++ CARD16 x; ++ CARD16 y; ++} rfbPointerEventMsg; ++ ++#define rfbButton1Mask 1 ++#define rfbButton2Mask 2 ++#define rfbButton3Mask 4 ++#define rfbButton4Mask 8 ++#define rfbButton5Mask 16 ++ ++#define sz_rfbPointerEventMsg 6 ++ ++ ++ ++/*----------------------------------------------------------------------------- ++ * ClientCutText - the client has new text in its cut buffer. ++ */ ++ ++typedef struct _rfbClientCutTextMsg { ++ CARD8 type; /* always rfbClientCutText */ ++ CARD8 pad1; ++ CARD16 pad2; ++ CARD32 length; ++ /* followed by char text[length] */ ++} rfbClientCutTextMsg; ++ ++#define sz_rfbClientCutTextMsg 8 ++ ++/*----------------------------------------------------------------------------- ++ * FileListRequest ++ */ ++ ++typedef struct _rfbFileListRequestMsg { ++ CARD8 type; ++ CARD8 flags; ++ CARD16 dirNameSize; ++ /* Followed by char Dirname[dirNameSize] */ ++} rfbFileListRequestMsg; ++ ++#define sz_rfbFileListRequestMsg 4 ++ ++/*----------------------------------------------------------------------------- ++ * FileDownloadRequest ++ */ ++ ++typedef struct _rfbFileDownloadRequestMsg { ++ CARD8 type; ++ CARD8 compressedLevel; ++ CARD16 fNameSize; ++ CARD32 position; ++ /* Followed by char Filename[fNameSize] */ ++} rfbFileDownloadRequestMsg; ++ ++#define sz_rfbFileDownloadRequestMsg 8 ++ ++/*----------------------------------------------------------------------------- ++ * FileUploadRequest ++ */ ++ ++typedef struct _rfbFileUploadRequestMsg { ++ CARD8 type; ++ CARD8 compressedLevel; ++ CARD16 fNameSize; ++ CARD32 position; ++ /* Followed by char Filename[fNameSize] */ ++} rfbFileUploadRequestMsg; ++ ++#define sz_rfbFileUploadRequestMsg 8 ++ ++ ++/*----------------------------------------------------------------------------- ++ * FileUploadData ++ */ ++ ++typedef struct _rfbFileUploadDataMsg { ++ CARD8 type; ++ CARD8 compressedLevel; ++ CARD16 realSize; ++ CARD16 compressedSize; ++ /* Followed by File[compressedSize] */ ++} rfbFileUploadDataMsg; ++ ++#define sz_rfbFileUploadDataMsg 8 ++ ++/*----------------------------------------------------------------------------- ++ * FileDownloadCancel ++ */ ++ ++typedef struct _rfbFileDownloadCancelMsg { ++ CARD8 type; ++ CARD8 unused; ++ CARD16 reasonLen; ++ /* Followed by reason[reasonLen] */ ++} rfbFileDownloadCancelMsg; ++ ++#define sz_rfbFileDownloadCancelMsg 4 ++ ++/*----------------------------------------------------------------------------- ++ * FileUploadFailed ++ */ ++ ++typedef struct _rfbFileUploadFailedMsg { ++ CARD8 type; ++ CARD8 unused; ++ CARD16 reasonLen; ++ /* Followed by reason[reasonLen] */ ++} rfbFileUploadFailedMsg; ++ ++#define sz_rfbFileUploadFailedMsg 4 ++ ++/*----------------------------------------------------------------------------- ++ * FileCreateDirRequest ++ */ ++ ++typedef struct _rfbFileCreateDirRequestMsg { ++ CARD8 type; ++ CARD8 unused; ++ CARD16 dNameLen; ++ CARD32 dModTime; ++ /* Followed by dName[dNameLen] */ ++} rfbFileCreateDirRequestMsg; ++ ++#define sz_rfbFileCreateDirRequestMsg 8 ++ ++/*----------------------------------------------------------------------------- ++ * ChromiumStop - the client has stopped the GL app. ++ */ ++ ++typedef struct { ++ CARD8 type; /* always rfbChromiumStop */ ++ CARD8 pad1; ++ CARD16 pad2; ++ CARD32 port; ++} rfbChromiumStopMsg; ++ ++#define sz_rfbChromiumStopMsg 8 ++ ++/*----------------------------------------------------------------------------- ++ * ChromiumExpose - redraw the window ++ */ ++ ++typedef struct { ++ CARD8 type; /* always rfbChromiumExpose */ ++ CARD8 pad1; ++ CARD16 pad2; ++ CARD32 winid; ++} rfbChromiumExposeMsg; ++ ++#define sz_rfbChromiumExposeMsg 8 ++ ++/*----------------------------------------------------------------------------- ++ * Union of all client->server messages. ++ */ ++ ++typedef union _rfbClientToServerMsg { ++ CARD8 type; ++ rfbSetPixelFormatMsg spf; ++ rfbFixColourMapEntriesMsg fcme; ++ rfbSetEncodingsMsg se; ++ rfbFramebufferUpdateRequestMsg fur; ++ rfbKeyEventMsg ke; ++ rfbPointerEventMsg pe; ++ rfbClientCutTextMsg cct; ++ rfbFileListRequestMsg flr; ++ rfbFileDownloadRequestMsg fdr; ++ rfbFileUploadRequestMsg fupr; ++ rfbFileUploadDataMsg fud; ++ rfbFileDownloadCancelMsg fdc; ++ rfbFileUploadFailedMsg fuf; ++ rfbFileCreateDirRequestMsg fcdr; ++ rfbChromiumStopMsg csd; ++ rfbChromiumExposeMsg cse; ++} rfbClientToServerMsg; +diff -pNur xorg-server-1.4.orig/hw/vnc/rfbserver.c xorg-server-1.4/hw/vnc/rfbserver.c +--- xorg-server-1.4.orig/hw/vnc/rfbserver.c 1969-12-31 16:00:00.000000000 -0800 ++++ xorg-server-1.4/hw/vnc/rfbserver.c 2007-09-06 16:09:45.000000000 -0700 +@@ -0,0 +1,2308 @@ ++/* ++ * rfbserver.c - deal with server-side of the RFB protocol. ++ * ++ * Modified for XFree86 4.x by Alan Hourihane ++ */ ++ ++/* ++ * Copyright (C) 2000-2004 Constantin Kaplinsky. All Rights Reserved. ++ * Copyright (C) 2000 Tridia Corporation. All Rights Reserved. ++ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. ++ * ++ * This is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This software is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this software; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, ++ * USA. ++ */ ++ ++/* Use ``#define CORBA'' to enable CORBA control interface */ ++#ifdef HAVE_DIX_CONFIG_H ++#include ++#endif ++ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "input.h" ++#include "mipointer.h" ++#if XFREE86VNC ++#include ++#endif ++#ifdef CHROMIUM ++#include "mivalidate.h" ++#endif ++#include "rfb.h" ++#include "windowstr.h" ++#include "sprite.h" ++#include "propertyst.h" ++#include ++#include ++ ++#ifdef CORBA ++#include ++#endif ++ ++#ifdef CHROMIUM ++struct CRWindowTable *windowTable = NULL; ++#endif ++ ++extern Atom VNC_CONNECT; ++ ++rfbClientPtr rfbClientHead = NULL; /* list of all VNC clients/viewers */ ++rfbClientPtr pointerClient = NULL; /* Mutex for pointer events */ ++ ++static rfbClientPtr rfbNewClient(ScreenPtr pScreen, int sock); ++static void rfbProcessClientProtocolVersion(rfbClientPtr cl); ++static void rfbProcessClientInitMessage(rfbClientPtr cl); ++static void rfbSendInteractionCaps(rfbClientPtr cl); ++static void rfbProcessClientNormalMessage(rfbClientPtr cl); ++static Bool rfbSendCopyRegion(rfbClientPtr cl, RegionPtr reg, int dx, int dy); ++static Bool rfbSendLastRectMarker(rfbClientPtr cl); ++ ++static char *text = NULL; ++ ++void ++rfbRootPropertyChange(ScreenPtr pScreen) ++{ ++ PropertyPtr pProp; ++ WindowPtr pWin = WindowTable[pScreen->myNum]; ++ ++ pProp = wUserProps (pWin); ++ ++ while (pProp) { ++ if ((pProp->propertyName == XA_CUT_BUFFER0) && ++ (pProp->type == XA_STRING) && ++ (pProp->format == 8)) ++ { ++ /* Ensure we don't keep re-sending cut buffer */ ++ ++ if ( (text && pProp->data && strncmp(text, pProp->data, pProp->size)) || !text) ++ rfbGotXCutText(pProp->data, pProp->size); ++ ++ if (text) xfree(text); ++ text = xalloc(1 + pProp->size); ++ if (! text) return; ++ if (pProp->data) memcpy(text, pProp->data, pProp->size); ++ text[pProp->size] = '\0'; ++ ++ return; ++ } ++ if ((pProp->propertyName == VNC_CONNECT) && (pProp->type == XA_STRING) ++ && (pProp->format == 8) && (pProp->size > 0)) ++ { ++ 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(pScreen, host, port); ++ ++#ifdef CORBA ++ if (cl != NULL) ++ newConnection(cl, (KEYBOARD_DEVICE|POINTER_DEVICE), 1, 1, 1); ++#endif ++ ++ ChangeWindowProperty(pWin, ++ pProp->propertyName, pProp->type, ++ pProp->format, PropModeReplace, ++ 0, NULL, ++ FALSE ++ ); ++ ++ free(host); ++ } ++ pProp = pProp->next; ++ } ++} ++ ++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; ++} ++ ++void ++rfbUserAllow(int sock, int accept) ++{ ++ rfbClientPtr cl; ++ ++ for (cl = rfbClientHead; cl; cl = cl->next) { ++ if (cl->sock == sock) { ++ cl->userAccepted = accept; ++ } ++ } ++} ++ ++/* ++ * rfbNewClientConnection is called from sockets.c when a new connection ++ * comes in. ++ */ ++ ++void ++rfbNewClientConnection(ScreenPtr pScreen, int sock) ++{ ++ rfbClientPtr cl; ++ ++ cl = rfbNewClient(pScreen, sock); ++ ++ GenerateVncConnectedEvent(sock); ++ ++#if XFREE86VNC ++ /* Someone is connected - disable VT switching */ ++ xf86EnableVTSwitch(FALSE); ++#endif ++ ++#ifdef CORBA ++ if (cl != NULL) ++ newConnection(cl, (KEYBOARD_DEVICE|POINTER_DEVICE), 1, 1, 1); ++#endif ++} ++ ++ ++/* ++ * rfbReverseConnection is called by the CORBA stuff to make an outward ++ * connection to a "listening" RFB client. ++ */ ++ ++rfbClientPtr ++rfbReverseConnection(ScreenPtr pScreen, char *host, int port) ++{ ++ int sock; ++ rfbClientPtr cl; ++ ++ if ((sock = rfbConnect(pScreen, host, port)) < 0) ++ return (rfbClientPtr)NULL; ++ ++ cl = rfbNewClient(pScreen, sock); ++ ++ if (cl) { ++ cl->reverseConnection = TRUE; ++ } ++ ++ return cl; ++} ++ ++ ++#ifdef CHROMIUM ++/* ++ * rfbSetClip -- ++ * Generate expose event. ++ * This function is overkill and should be cleaned up, but it ++ * works for now. ++ */ ++ ++void ++rfbSetClip (WindowPtr pWin, BOOL enable) ++{ ++ ScreenPtr pScreen = pWin->drawable.pScreen; ++ WindowPtr pChild; ++ Bool WasViewable = (Bool)(pWin->viewable); ++ Bool anyMarked = FALSE; ++ RegionPtr pOldClip = NULL, bsExposed; ++#ifdef DO_SAVE_UNDERS ++ Bool dosave = FALSE; ++#endif ++ WindowPtr pLayerWin; ++ BoxRec box; ++ ++ if (WasViewable) ++ { ++ for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) ++ { ++ (void) (*pScreen->MarkOverlappedWindows)(pChild, ++ pChild, ++ &pLayerWin); ++ } ++ (*pScreen->MarkWindow) (pWin); ++ anyMarked = TRUE; ++ if (pWin->valdata) ++ { ++ if (HasBorder (pWin)) ++ { ++ RegionPtr borderVisible; ++ ++ borderVisible = REGION_CREATE(pScreen, NullBox, 1); ++ REGION_SUBTRACT(pScreen, borderVisible, ++ &pWin->borderClip, &pWin->winSize); ++ pWin->valdata->before.borderVisible = borderVisible; ++ } ++ pWin->valdata->before.resized = TRUE; ++ } ++ } ++ ++ /* ++ * Use REGION_BREAK to avoid optimizations in ValidateTree ++ * that assume the root borderClip can't change well, normally ++ * it doesn't...) ++ */ ++ if (enable) ++ { ++ box.x1 = 0; ++ box.y1 = 0; ++ box.x2 = pScreen->width; ++ box.y2 = pScreen->height; ++ REGION_INIT (pScreen, &pWin->winSize, &box, 1); ++ REGION_INIT (pScreen, &pWin->borderSize, &box, 1); ++ if (WasViewable) ++ REGION_RESET(pScreen, &pWin->borderClip, &box); ++ pWin->drawable.width = pScreen->width; ++ pWin->drawable.height = pScreen->height; ++ REGION_BREAK (pWin->drawable.pScreen, &pWin->clipList); ++ } ++ else ++ { ++ REGION_EMPTY(pScreen, &pWin->borderClip); ++ REGION_BREAK (pWin->drawable.pScreen, &pWin->clipList); ++ } ++ ++ ResizeChildrenWinSize (pWin, 0, 0, 0, 0); ++ ++ if (WasViewable) ++ { ++ if (pWin->backStorage) ++ { ++ pOldClip = REGION_CREATE(pScreen, NullBox, 1); ++ REGION_COPY(pScreen, pOldClip, &pWin->clipList); ++ } ++ ++ if (pWin->firstChild) ++ { ++ anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin->firstChild, ++ pWin->firstChild, ++ (WindowPtr *)NULL); ++ } ++ else ++ { ++ (*pScreen->MarkWindow) (pWin); ++ anyMarked = TRUE; ++ } ++ ++#ifdef DO_SAVE_UNDERS ++ if (DO_SAVE_UNDERS(pWin)) ++ { ++ dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, pLayerWin); ++ } ++#endif /* DO_SAVE_UNDERS */ ++ ++ if (anyMarked) ++ (*pScreen->ValidateTree)(pWin, NullWindow, VTOther); ++ } ++ ++ if (pWin->backStorage && ++ ((pWin->backingStore == Always) || WasViewable)) ++ { ++ if (!WasViewable) ++ pOldClip = &pWin->clipList; /* a convenient empty region */ ++ bsExposed = (*pScreen->TranslateBackingStore) ++ (pWin, 0, 0, pOldClip, ++ pWin->drawable.x, pWin->drawable.y); ++ if (WasViewable) ++ REGION_DESTROY(pScreen, pOldClip); ++ if (bsExposed) ++ { ++ RegionPtr valExposed = NullRegion; ++ ++ if (pWin->valdata) ++ valExposed = &pWin->valdata->after.exposed; ++ (*pScreen->WindowExposures) (pWin, valExposed, bsExposed); ++ if (valExposed) ++ REGION_EMPTY(pScreen, valExposed); ++ REGION_DESTROY(pScreen, bsExposed); ++ } ++ } ++ if (WasViewable) ++ { ++ if (anyMarked) ++ (*pScreen->HandleExposures)(pWin); ++#ifdef DO_SAVE_UNDERS ++ if (dosave) ++ (*pScreen->PostChangeSaveUnder)(pLayerWin, pLayerWin); ++#endif /* DO_SAVE_UNDERS */ ++ if (anyMarked && pScreen->PostValidateTree) ++ (*pScreen->PostValidateTree)(pWin, NullWindow, VTOther); ++ } ++ if (pWin->realized) ++ WindowsRestructured (); ++ FlushAllOutput (); ++} ++#endif /* CHROMIUM */ ++ ++/* ++ * rfbNewClient is called when a new connection has been made by whatever ++ * means. ++ */ ++ ++static rfbClientPtr ++rfbNewClient(ScreenPtr pScreen, int sock) ++{ ++ rfbProtocolVersionMsg pv; ++ rfbClientPtr cl; ++ BoxRec box; ++ struct sockaddr_in addr; ++ SOCKLEN_T addrlen = sizeof(struct sockaddr_in); ++ VNCSCREENPTR(pScreen); ++ int i; ++ ++ if (rfbClientHead == NULL) { ++ /* no other clients - make sure we don't think any keys are pressed */ ++ KbdReleaseAllKeys(); ++ } else { ++ rfbLog(" (other clients"); ++ for (cl = rfbClientHead; cl; cl = cl->next) { ++ rfbLog(" %s",cl->host); ++ } ++ rfbLog(")\n"); ++ } ++ ++ cl = (rfbClientPtr)xalloc(sizeof(rfbClientRec)); ++ ++#ifdef CHROMIUM ++ cl->chromium_port = 0; /* no GL application on this port, yet */ ++#endif ++ cl->userAccepted = 0; /* user hasn't even approached this yet .... */ ++ cl->sock = sock; ++ getpeername(sock, (struct sockaddr *)&addr, &addrlen); ++ cl->host = strdup(inet_ntoa(addr.sin_addr)); ++ cl->login = NULL; ++ ++ /* Dispatch client input to rfbProcessClientProtocolVersion(). */ ++ cl->state = RFB_PROTOCOL_VERSION; ++ ++ cl->viewOnly = FALSE; ++ cl->reverseConnection = FALSE; ++ cl->readyForSetColourMapEntries = FALSE; ++ cl->useCopyRect = FALSE; ++ cl->preferredEncoding = rfbEncodingRaw; ++ cl->correMaxWidth = 48; ++ cl->correMaxHeight = 48; ++ cl->pScreen = pScreen; ++ ++ REGION_NULL(pScreen,&cl->copyRegion); ++ cl->copyDX = 0; ++ cl->copyDY = 0; ++ ++ box.x1 = box.y1 = 0; ++ box.x2 = pVNC->width; ++ box.y2 = pVNC->height; ++ REGION_INIT(pScreen,&cl->modifiedRegion,&box,0); ++ ++ REGION_NULL(pScreen,&cl->requestedRegion); ++ ++ cl->deferredUpdateScheduled = FALSE; ++ cl->deferredUpdateTimer = NULL; ++ ++ cl->format = pVNC->rfbServerFormat; ++ cl->translateFn = rfbTranslateNone; ++ cl->translateLookupTable = NULL; ++ ++ cl->tightCompressLevel = TIGHT_DEFAULT_COMPRESSION; ++ cl->tightQualityLevel = -1; ++ for (i = 0; i < 4; i++) ++ cl->zsActive[i] = FALSE; ++ ++ cl->enableCursorShapeUpdates = FALSE; ++ cl->enableCursorPosUpdates = FALSE; ++ cl->enableLastRectEncoding = FALSE; ++#ifdef CHROMIUM ++ cl->enableChromiumEncoding = FALSE; ++#endif ++ ++ cl->next = rfbClientHead; ++ rfbClientHead = cl; ++ ++ rfbResetStats(cl); ++ ++ cl->compStreamInited = FALSE; ++ cl->compStream.total_in = 0; ++ cl->compStream.total_out = 0; ++ cl->compStream.zalloc = Z_NULL; ++ cl->compStream.zfree = Z_NULL; ++ cl->compStream.opaque = Z_NULL; ++ ++ cl->zlibCompressLevel = 5; ++ ++ sprintf(pv,rfbProtocolVersionFormat,rfbProtocolMajorVersion, ++ rfbProtocolMinorVersion); ++ ++ if (WriteExact(sock, pv, sz_rfbProtocolVersionMsg) < 0) { ++ rfbLogPerror("rfbNewClient: write"); ++ rfbCloseSock(pScreen, sock); ++ return NULL; ++ } ++ ++ return cl; ++} ++ ++ ++/* ++ * rfbClientConnectionGone is called from sockets.c just after a connection ++ * has gone away. ++ */ ++ ++void ++rfbClientConnectionGone(sock) ++ int sock; ++{ ++ rfbClientPtr cl, prev; ++ int i; ++#if XFREE86VNC ++ int allowvt = TRUE; ++#endif ++ ++ for (prev = NULL, cl = rfbClientHead; cl; prev = cl, cl = cl->next) { ++ if (sock == cl->sock) ++ break; ++ } ++ ++ if (!cl) { ++ rfbLog("rfbClientConnectionGone: unknown socket %d\n",sock); ++ return; ++ } ++ ++ rfbLog("rfbClientConnectionGone\n"); ++ ++ if (cl->login != NULL) { ++ rfbLog("VNC Client %s (%s) gone\n", cl->login, cl->host); ++ free(cl->login); ++ } else { ++ rfbLog("VNC Client %s gone\n", cl->host); ++ } ++ free(cl->host); ++ ++ /* Release the compression state structures if any. */ ++ if ( cl->compStreamInited == TRUE ) { ++ deflateEnd( &(cl->compStream) ); ++ } ++ ++ for (i = 0; i < 4; i++) { ++ if (cl->zsActive[i]) ++ deflateEnd(&cl->zsStruct[i]); ++ } ++ ++ if (pointerClient == cl) ++ pointerClient = NULL; ++ ++#ifdef CORBA ++ destroyConnection(cl); ++#endif ++ ++ if (prev) ++ prev->next = cl->next; ++ else ++ rfbClientHead = cl->next; ++ ++ REGION_UNINIT(cl->pScreen,&cl->copyRegion); ++ REGION_UNINIT(cl->pScreen,&cl->modifiedRegion); ++ TimerFree(cl->deferredUpdateTimer); ++ ++ rfbPrintStats(cl); ++ ++ if (cl->translateLookupTable) free(cl->translateLookupTable); ++ ++ xfree(cl); ++ ++ GenerateVncDisconnectedEvent(sock); ++ ++#if XFREE86VNC ++ for (cl = rfbClientHead; cl; cl = cl->next) { ++ /* still someone connected */ ++ allowvt = FALSE; ++ } ++ ++ xf86EnableVTSwitch(allowvt); ++#endif ++} ++ ++ ++/* ++ * rfbProcessClientMessage is called when there is data to read from a client. ++ */ ++ ++void ++rfbProcessClientMessage(ScreenPtr pScreen, int sock) ++{ ++ rfbClientPtr cl; ++ ++ for (cl = rfbClientHead; cl; cl = cl->next) { ++ if (sock == cl->sock) ++ break; ++ } ++ ++ if (!cl) { ++ rfbLog("rfbProcessClientMessage: unknown socket %d\n",sock); ++ rfbCloseSock(pScreen, sock); ++ return; ++ } ++ ++#ifdef CORBA ++ if (isClosePending(cl)) { ++ rfbLog("Closing connection to client %s\n", cl->host); ++ rfbCloseSock(pScreen, sock); ++ return; ++ } ++#endif ++ ++ switch (cl->state) { ++ case RFB_PROTOCOL_VERSION: ++ rfbProcessClientProtocolVersion(cl); ++ break; ++ case RFB_SECURITY_TYPE: /* protocol 3.7 */ ++ rfbProcessClientSecurityType(cl); ++ break; ++ case RFB_TUNNELING_TYPE: /* protocol 3.7t */ ++ rfbProcessClientTunnelingType(cl); ++ break; ++ case RFB_AUTH_TYPE: /* protocol 3.7t */ ++ rfbProcessClientAuthType(cl); ++ break; ++ case RFB_AUTHENTICATION: ++ rfbVncAuthProcessResponse(cl); ++ break; ++ case RFB_INITIALISATION: ++ rfbProcessClientInitMessage(cl); ++ break; ++ default: ++ rfbProcessClientNormalMessage(cl); ++ } ++} ++ ++ ++/* ++ * rfbProcessClientProtocolVersion is called when the client sends its ++ * protocol version. ++ */ ++ ++static void ++rfbProcessClientProtocolVersion(cl) ++ rfbClientPtr cl; ++{ ++ rfbProtocolVersionMsg pv; ++ int n, major, minor; ++ ++ if ((n = ReadExact(cl->sock, pv, sz_rfbProtocolVersionMsg)) <= 0) { ++ if (n == 0) ++ rfbLog("rfbProcessClientProtocolVersion: client gone\n"); ++ else ++ rfbLogPerror("rfbProcessClientProtocolVersion: read"); ++ rfbCloseSock(cl->pScreen, cl->sock); ++ return; ++ } ++ ++ pv[sz_rfbProtocolVersionMsg] = 0; ++ if (sscanf(pv,rfbProtocolVersionFormat,&major,&minor) != 2) { ++ rfbLog("rfbProcessClientProtocolVersion: not a valid RFB client\n"); ++ rfbCloseSock(cl->pScreen, cl->sock); ++ return; ++ } ++ rfbLog("Using protocol version %d.%d\n", major, minor); ++ ++ if (major != rfbProtocolMajorVersion) { ++ rfbLog("RFB protocol version mismatch - server %d.%d, client %d.%d\n", ++ rfbProtocolMajorVersion,rfbProtocolMinorVersion,major,minor); ++ rfbCloseSock(cl->pScreen, cl->sock); ++ return; ++ } ++ ++ /* Always use one of the two standard versions of the RFB protocol. */ ++ cl->protocol_minor_ver = minor; ++ if (minor > rfbProtocolMinorVersion) { ++ cl->protocol_minor_ver = rfbProtocolMinorVersion; ++ } else if (minor < rfbProtocolMinorVersion) { ++ cl->protocol_minor_ver = rfbProtocolFallbackMinorVersion; ++ } ++ if (minor != rfbProtocolMinorVersion && ++ minor != rfbProtocolFallbackMinorVersion) { ++ rfbLog("Non-standard protocol version %d.%d, using %d.%d instead\n", ++ major, minor, rfbProtocolMajorVersion, cl->protocol_minor_ver); ++ } ++ ++ /* TightVNC protocol extensions are not enabled yet. */ ++ cl->protocol_tightvnc = FALSE; ++ ++ rfbAuthNewClient(cl); ++} ++ ++/* ++ * rfbClientConnFailed is called when a client connection has failed ++ * before the authentication stage. ++ */ ++ ++void ++rfbClientConnFailed(cl, reason) ++ rfbClientPtr cl; ++ char *reason; ++{ ++ int headerLen, reasonLen; ++ char buf[8]; ++ ++ headerLen = (cl->protocol_minor_ver >= 7) ? 1 : 4; ++ reasonLen = strlen(reason); ++ ((CARD32 *)buf)[0] = 0; ++ ((CARD32 *)buf)[1] = Swap32IfLE(reasonLen); ++ ++ if ( WriteExact(cl->sock, buf, headerLen) < 0 || ++ WriteExact(cl->sock, buf + 4, 4) < 0 || ++ WriteExact(cl->sock, reason, reasonLen) < 0 ) { ++ rfbLogPerror("rfbClientConnFailed: write"); ++ } ++ ++ rfbCloseSock(cl->pScreen, cl->sock); ++} ++ ++ ++/* ++ * rfbProcessClientInitMessage is called when the client sends its ++ * initialisation message. ++ */ ++ ++static void ++rfbProcessClientInitMessage(cl) ++ rfbClientPtr cl; ++{ ++ VNCSCREENPTR(cl->pScreen); ++ rfbClientInitMsg ci; ++ char buf[256]; ++ rfbServerInitMsg *si = (rfbServerInitMsg *)buf; ++ struct passwd *user; ++ int len, n; ++ rfbClientPtr otherCl, nextCl; ++ ++ if ((n = ReadExact(cl->sock, (char *)&ci,sz_rfbClientInitMsg)) <= 0) { ++ if (n == 0) ++ rfbLog("rfbProcessClientInitMessage: client gone\n"); ++ else ++ rfbLogPerror("rfbProcessClientInitMessage: read"); ++ rfbCloseSock(cl->pScreen, cl->sock); ++ return; ++ } ++ ++ si->framebufferWidth = Swap16IfLE(pVNC->width); ++ si->framebufferHeight = Swap16IfLE(pVNC->height); ++ si->format = pVNC->rfbServerFormat; ++ si->format.redMax = Swap16IfLE(si->format.redMax); ++ si->format.greenMax = Swap16IfLE(si->format.greenMax); ++ si->format.blueMax = Swap16IfLE(si->format.blueMax); ++ ++ user = getpwuid(getuid()); ++ ++ if (strlen(desktopName) > 128) /* sanity check on desktop name len */ ++ desktopName[128] = 0; ++ ++ if (user) { ++ sprintf(buf + sz_rfbServerInitMsg, "%s's %s desktop (%s:%s)", ++ user->pw_name, desktopName, rfbThisHost, display); ++ } else { ++ sprintf(buf + sz_rfbServerInitMsg, "%s desktop (%s:%s)", ++ desktopName, rfbThisHost, display); ++ } ++ len = strlen(buf + sz_rfbServerInitMsg); ++ si->nameLength = Swap32IfLE(len); ++ ++ if (WriteExact(cl->sock, buf, sz_rfbServerInitMsg + len) < 0) { ++ rfbLogPerror("rfbProcessClientInitMessage: write"); ++ rfbCloseSock(cl->pScreen, cl->sock); ++ return; ++ } ++ ++ if (cl->protocol_tightvnc) ++ rfbSendInteractionCaps(cl); /* protocol 3.7t */ ++ ++ /* Dispatch client input to rfbProcessClientNormalMessage(). */ ++ cl->state = RFB_NORMAL; ++ ++ if (!cl->reverseConnection && ++ (pVNC->rfbNeverShared || (!pVNC->rfbAlwaysShared && !ci.shared))) { ++ ++ if (pVNC->rfbDontDisconnect) { ++ for (otherCl = rfbClientHead; otherCl; otherCl = otherCl->next) { ++ if ((otherCl != cl) && (otherCl->state == RFB_NORMAL)) { ++ rfbLog("-dontdisconnect: Not shared & existing client\n"); ++ rfbLog(" refusing new client %s\n", cl->host); ++ rfbCloseSock(cl->pScreen, cl->sock); ++ return; ++ } ++ } ++ } else { ++ for (otherCl = rfbClientHead; otherCl; otherCl = nextCl) { ++ nextCl = otherCl->next; ++ if ((otherCl != cl) && (otherCl->state == RFB_NORMAL)) { ++ rfbLog("Not shared - closing connection to client %s\n", ++ otherCl->host); ++ rfbCloseSock(otherCl->pScreen, otherCl->sock); ++ } ++ } ++ } ++ } ++} ++ ++ ++/* ++ * rfbSendInteractionCaps is called after sending the server ++ * initialisation message, only if the protocol version is 3.130. ++ * In this function, we send the lists of supported protocol messages ++ * and encodings. ++ */ ++ ++/* Update these constants on changing capability lists below! */ ++#define N_SMSG_CAPS 0 ++#define N_CMSG_CAPS 0 ++#define N_ENC_CAPS 12 ++ ++void ++rfbSendInteractionCaps(cl) ++ rfbClientPtr cl; ++{ ++ rfbInteractionCapsMsg intr_caps; ++ rfbCapabilityInfo enc_list[N_ENC_CAPS]; ++ int i; ++ ++ /* Fill in the header structure sent prior to capability lists. */ ++ intr_caps.nServerMessageTypes = Swap16IfLE(N_SMSG_CAPS); ++ intr_caps.nClientMessageTypes = Swap16IfLE(N_CMSG_CAPS); ++ intr_caps.nEncodingTypes = Swap16IfLE(N_ENC_CAPS); ++ intr_caps.pad = 0; ++ ++ /* Supported server->client message types. */ ++ /* For future file transfer support: ++ i = 0; ++ SetCapInfo(&smsg_list[i++], rfbFileListData, rfbTightVncVendor); ++ SetCapInfo(&smsg_list[i++], rfbFileDownloadData, rfbTightVncVendor); ++ SetCapInfo(&smsg_list[i++], rfbFileUploadCancel, rfbTightVncVendor); ++ SetCapInfo(&smsg_list[i++], rfbFileDownloadFailed, rfbTightVncVendor); ++ if (i != N_SMSG_CAPS) { ++ rfbLog("rfbSendInteractionCaps: assertion failed, i != N_SMSG_CAPS\n"); ++ rfbCloseSock(cl->pScreen, cl->sock); ++ return; ++ } ++ */ ++ ++ /* Supported client->server message types. */ ++ /* For future file transfer support: ++ i = 0; ++ SetCapInfo(&cmsg_list[i++], rfbFileListRequest, rfbTightVncVendor); ++ SetCapInfo(&cmsg_list[i++], rfbFileDownloadRequest, rfbTightVncVendor); ++ SetCapInfo(&cmsg_list[i++], rfbFileUploadRequest, rfbTightVncVendor); ++ SetCapInfo(&cmsg_list[i++], rfbFileUploadData, rfbTightVncVendor); ++ SetCapInfo(&cmsg_list[i++], rfbFileDownloadCancel, rfbTightVncVendor); ++ SetCapInfo(&cmsg_list[i++], rfbFileUploadFailed, rfbTightVncVendor); ++ if (i != N_CMSG_CAPS) { ++ rfbLog("rfbSendInteractionCaps: assertion failed, i != N_CMSG_CAPS\n"); ++ rfbCloseSock(cl->pScreen, cl->sock); ++ return; ++ } ++ */ ++ ++ /* Encoding types. */ ++ i = 0; ++ SetCapInfo(&enc_list[i++], rfbEncodingCopyRect, rfbStandardVendor); ++ SetCapInfo(&enc_list[i++], rfbEncodingRRE, rfbStandardVendor); ++ SetCapInfo(&enc_list[i++], rfbEncodingCoRRE, rfbStandardVendor); ++ SetCapInfo(&enc_list[i++], rfbEncodingHextile, rfbStandardVendor); ++ SetCapInfo(&enc_list[i++], rfbEncodingZlib, rfbTridiaVncVendor); ++ SetCapInfo(&enc_list[i++], rfbEncodingTight, rfbTightVncVendor); ++ SetCapInfo(&enc_list[i++], rfbEncodingCompressLevel0, rfbTightVncVendor); ++ SetCapInfo(&enc_list[i++], rfbEncodingQualityLevel0, rfbTightVncVendor); ++ SetCapInfo(&enc_list[i++], rfbEncodingXCursor, rfbTightVncVendor); ++ SetCapInfo(&enc_list[i++], rfbEncodingRichCursor, rfbTightVncVendor); ++ SetCapInfo(&enc_list[i++], rfbEncodingPointerPos, rfbTightVncVendor); ++ SetCapInfo(&enc_list[i++], rfbEncodingLastRect, rfbTightVncVendor); ++ if (i != N_ENC_CAPS) { ++ rfbLog("rfbSendInteractionCaps: assertion failed, i != N_ENC_CAPS\n"); ++ rfbCloseSock(cl->pScreen, cl->sock); ++ return; ++ } ++ ++ /* Send header and capability lists */ ++ if (WriteExact(cl->sock, (char *)&intr_caps, ++ sz_rfbInteractionCapsMsg) < 0 || ++ WriteExact(cl->sock, (char *)&enc_list[0], ++ sz_rfbCapabilityInfo * N_ENC_CAPS) < 0) { ++ rfbLogPerror("rfbSendInteractionCaps: write"); ++ rfbCloseSock(cl->pScreen, cl->sock); ++ return; ++ } ++ ++ /* Dispatch client input to rfbProcessClientNormalMessage(). */ ++ cl->state = RFB_NORMAL; ++} ++ ++ ++/* ++ * rfbProcessClientNormalMessage is called when the client has sent a normal ++ * protocol message. ++ */ ++ ++static void ++rfbProcessClientNormalMessage(cl) ++ rfbClientPtr cl; ++{ ++ VNCSCREENPTR(cl->pScreen); ++ int n; ++ rfbClientToServerMsg msg; ++ char *str; ++ ++ if (pVNC->rfbUserAccept) { ++ /* ++ * We've asked for another level of user authentication ++ * If the user has not validated this connected, don't ++ * process it. ++ */ ++ /* ++ * NOTE: we do it here, so the vncviewer knows it's ++ * connected, but waiting for the first screen update ++ */ ++ if (cl->userAccepted == VNC_USER_UNDEFINED) { ++ usleep(10); ++ return; ++ } ++ if (cl->userAccepted == VNC_USER_DISCONNECT) { ++ rfbCloseSock(cl->pScreen, cl->sock); ++ return; ++ } ++ } ++ ++ if ((n = ReadExact(cl->sock, (char *)&msg, 1)) <= 0) { ++ if (n != 0) ++ rfbLogPerror("rfbProcessClientNormalMessage: read"); ++ rfbCloseSock(cl->pScreen, cl->sock); ++ return; ++ } ++ ++ switch (msg.type) { ++ ++ case rfbSetPixelFormat: ++ ++ if ((n = ReadExact(cl->sock, ((char *)&msg) + 1, ++ sz_rfbSetPixelFormatMsg - 1)) <= 0) { ++ if (n != 0) ++ rfbLogPerror("rfbProcessClientNormalMessage: read"); ++ rfbCloseSock(cl->pScreen, cl->sock); ++ return; ++ } ++ ++ cl->format.bitsPerPixel = msg.spf.format.bitsPerPixel; ++ cl->format.depth = msg.spf.format.depth; ++ cl->format.bigEndian = (msg.spf.format.bigEndian ? 1 : 0); ++ cl->format.trueColour = (msg.spf.format.trueColour ? 1 : 0); ++ cl->format.redMax = Swap16IfLE(msg.spf.format.redMax); ++ cl->format.greenMax = Swap16IfLE(msg.spf.format.greenMax); ++ cl->format.blueMax = Swap16IfLE(msg.spf.format.blueMax); ++ cl->format.redShift = msg.spf.format.redShift; ++ cl->format.greenShift = msg.spf.format.greenShift; ++ cl->format.blueShift = msg.spf.format.blueShift; ++ ++ cl->readyForSetColourMapEntries = TRUE; ++ ++ rfbSetTranslateFunction(cl); ++ return; ++ ++ ++ case rfbFixColourMapEntries: ++ if ((n = ReadExact(cl->sock, ((char *)&msg) + 1, ++ sz_rfbFixColourMapEntriesMsg - 1)) <= 0) { ++ if (n != 0) ++ rfbLogPerror("rfbProcessClientNormalMessage: read"); ++ rfbCloseSock(cl->pScreen, cl->sock); ++ return; ++ } ++ rfbLog("rfbProcessClientNormalMessage: %s", ++ "FixColourMapEntries unsupported\n"); ++ rfbCloseSock(cl->pScreen, cl->sock); ++ return; ++ ++ ++ case rfbSetEncodings: ++ { ++ int i; ++ CARD32 enc; ++ ++ if ((n = ReadExact(cl->sock, ((char *)&msg) + 1, ++ sz_rfbSetEncodingsMsg - 1)) <= 0) { ++ if (n != 0) ++ rfbLogPerror("rfbProcessClientNormalMessage: read"); ++ rfbCloseSock(cl->pScreen, cl->sock); ++ return; ++ } ++ ++ msg.se.nEncodings = Swap16IfLE(msg.se.nEncodings); ++ ++ cl->preferredEncoding = -1; ++ cl->useCopyRect = FALSE; ++ cl->enableCursorShapeUpdates = FALSE; ++ cl->enableCursorPosUpdates = FALSE; ++ cl->enableLastRectEncoding = FALSE; ++#ifdef CHROMIUM ++ cl->enableChromiumEncoding = FALSE; ++#endif ++ cl->tightCompressLevel = TIGHT_DEFAULT_COMPRESSION; ++ cl->tightQualityLevel = -1; ++ ++ for (i = 0; i < msg.se.nEncodings; i++) { ++ if ((n = ReadExact(cl->sock, (char *)&enc, 4)) <= 0) { ++ if (n != 0) ++ rfbLogPerror("rfbProcessClientNormalMessage: read"); ++ rfbCloseSock(cl->pScreen, cl->sock); ++ return; ++ } ++ enc = Swap32IfLE(enc); ++ ++ switch (enc) { ++ ++ case rfbEncodingCopyRect: ++ cl->useCopyRect = TRUE; ++ rfbLog("Using copyrect encoding for client %s\n", ++ cl->host); ++ break; ++ case rfbEncodingRaw: ++ if (cl->preferredEncoding == -1) { ++ cl->preferredEncoding = enc; ++ rfbLog("Using raw encoding for client %s\n", ++ cl->host); ++ } ++ break; ++ case rfbEncodingRRE: ++ if (cl->preferredEncoding == -1) { ++ cl->preferredEncoding = enc; ++ rfbLog("Using rre encoding for client %s\n", ++ cl->host); ++ } ++ break; ++ case rfbEncodingCoRRE: ++ if (cl->preferredEncoding == -1) { ++ cl->preferredEncoding = enc; ++ rfbLog("Using CoRRE encoding for client %s\n", ++ cl->host); ++ } ++ break; ++ case rfbEncodingHextile: ++ if (cl->preferredEncoding == -1) { ++ cl->preferredEncoding = enc; ++ rfbLog("Using hextile encoding for client %s\n", ++ cl->host); ++ } ++ break; ++ case rfbEncodingZlib: ++ if (cl->preferredEncoding == -1) { ++ cl->preferredEncoding = enc; ++ rfbLog("Using zlib encoding for client %s\n", ++ cl->host); ++ } ++ break; ++ case rfbEncodingTight: ++ if (cl->preferredEncoding == -1) { ++ cl->preferredEncoding = enc; ++ rfbLog("Using tight encoding for client %s\n", ++ cl->host); ++ } ++ break; ++ case rfbEncodingXCursor: ++ rfbLog("Enabling X-style cursor updates for client %s\n", ++ cl->host); ++ cl->enableCursorShapeUpdates = TRUE; ++ cl->useRichCursorEncoding = FALSE; ++ cl->cursorWasChanged = TRUE; ++ break; ++ case rfbEncodingRichCursor: ++ if (!cl->enableCursorShapeUpdates) { ++ rfbLog("Enabling full-color cursor updates for client " ++ "%s\n", cl->host); ++ cl->enableCursorShapeUpdates = TRUE; ++ cl->useRichCursorEncoding = TRUE; ++ cl->cursorWasChanged = TRUE; ++ } ++ break; ++ case rfbEncodingPointerPos: ++ if (!cl->enableCursorPosUpdates) { ++ rfbLog("Enabling cursor position updates for client %s\n", ++ cl->host); ++ cl->enableCursorPosUpdates = TRUE; ++ cl->cursorWasMoved = TRUE; ++ cl->cursorX = -1; ++ cl->cursorY = -1; ++ } ++ break; ++ case rfbEncodingLastRect: ++ if (!cl->enableLastRectEncoding) { ++ rfbLog("Enabling LastRect protocol extension for client " ++ "%s\n", cl->host); ++ cl->enableLastRectEncoding = TRUE; ++ } ++ break; ++#ifdef CHROMIUM ++ case rfbEncodingChromium: ++ case rfbEncodingChromium2: ++ if (!cl->enableChromiumEncoding) { ++ cl->enableChromiumEncoding = TRUE; ++ /* This tells OpenGL apps/replicate SPUs that new viewer ++ * has attached. ++ */ ++ GenerateVncChromiumConnectedEvent(cl->sock); ++ if (enc == rfbEncodingChromium) { ++ /* Generate exposures for all windows */ ++ WindowPtr pWin = WindowTable[cl->pScreen->myNum]; ++ rfbSetClip(pWin, 1); ++ } ++ else { ++ /* don't generate exposures for Chromium2 because ++ * that confused DMX. ++ */ ++ } ++ } ++ break; ++#endif ++ default: ++ if ( enc >= (CARD32)rfbEncodingCompressLevel0 && ++ enc <= (CARD32)rfbEncodingCompressLevel9 ) { ++ cl->zlibCompressLevel = enc & 0x0F; ++ cl->tightCompressLevel = enc & 0x0F; ++ rfbLog("Using compression level %d for client %s\n", ++ cl->tightCompressLevel, cl->host); ++ } else if ( enc >= (CARD32)rfbEncodingQualityLevel0 && ++ enc <= (CARD32)rfbEncodingQualityLevel9 ) { ++ cl->tightQualityLevel = enc & 0x0F; ++ rfbLog("Using image quality level %d for client %s\n", ++ cl->tightQualityLevel, cl->host); ++ } else { ++ rfbLog("rfbProcessClientNormalMessage: ignoring unknown " ++ "encoding %d\n", (int)enc); ++ } ++ } ++ } ++ ++ if (cl->preferredEncoding == -1) { ++ cl->preferredEncoding = rfbEncodingRaw; ++ rfbLog("No encoding specified - using raw encoding for client %s\n", ++ cl->host); ++ } ++ ++ if (cl->enableCursorPosUpdates && !cl->enableCursorShapeUpdates) { ++ rfbLog("Disabling cursor position updates for client %s\n", ++ cl->host); ++ cl->enableCursorPosUpdates = FALSE; ++ } ++ ++#if XFREE86VNC ++ /* ++ * With XFree86 and the hardware cursor's we need to put up the ++ * cursor again, and if we've detected a cursor shapeless client ++ * we need to disable hardware cursors. ++ */ ++ if (!cl->enableCursorShapeUpdates) ++ pVNC->SWCursor = (Bool *)TRUE; ++ else ++ pVNC->SWCursor = (Bool *)FALSE; ++ ++ { ++ int x, y; ++ miPointerPosition(&x, &y); /*XXX deprecated*/ ++ (*pVNC->spriteFuncs->SetCursor)(cl->pScreen, pVNC->pCurs, x, y); ++ } ++#endif ++ ++ return; ++ } ++ ++ ++ case rfbFramebufferUpdateRequest: ++ { ++ RegionRec tmpRegion; ++ BoxRec box; ++ ++#ifdef CORBA ++ addCapability(cl, DISPLAY_DEVICE); ++#endif ++ ++ if ((n = ReadExact(cl->sock, ((char *)&msg) + 1, ++ sz_rfbFramebufferUpdateRequestMsg-1)) <= 0) { ++ if (n != 0) ++ rfbLogPerror("rfbProcessClientNormalMessage: read"); ++ rfbCloseSock(cl->pScreen, cl->sock); ++ return; ++ } ++ ++ box.x1 = Swap16IfLE(msg.fur.x); ++ box.y1 = Swap16IfLE(msg.fur.y); ++ box.x2 = box.x1 + Swap16IfLE(msg.fur.w); ++ box.y2 = box.y1 + Swap16IfLE(msg.fur.h); ++ SAFE_REGION_INIT(cl->pScreen,&tmpRegion,&box,0); ++ ++ REGION_UNION(cl->pScreen, &cl->requestedRegion, &cl->requestedRegion, ++ &tmpRegion); ++ ++ if (!cl->readyForSetColourMapEntries) { ++ /* client hasn't sent a SetPixelFormat so is using server's */ ++ cl->readyForSetColourMapEntries = TRUE; ++ if (!cl->format.trueColour) { ++ if (!rfbSetClientColourMap(cl, 0, 0)) { ++ REGION_UNINIT(cl->pScreen,&tmpRegion); ++ return; ++ } ++ } ++ } ++ ++ if (!msg.fur.incremental) { ++ REGION_UNION(cl->pScreen,&cl->modifiedRegion,&cl->modifiedRegion, ++ &tmpRegion); ++ REGION_SUBTRACT(cl->pScreen,&cl->copyRegion,&cl->copyRegion, ++ &tmpRegion); ++ } ++ ++#ifndef DMXVNC ++ /* don't try to send any pixel data - we'll crash */ ++ if (FB_UPDATE_PENDING(cl)) { ++ rfbSendFramebufferUpdate(cl->pScreen, cl); ++ } ++#endif ++ ++ REGION_UNINIT(cl->pScreen,&tmpRegion); ++ return; ++ } ++ ++ case rfbKeyEvent: ++ ++ cl->rfbKeyEventsRcvd++; ++ ++ if ((n = ReadExact(cl->sock, ((char *)&msg) + 1, ++ sz_rfbKeyEventMsg - 1)) <= 0) { ++ if (n != 0) ++ rfbLogPerror("rfbProcessClientNormalMessage: read"); ++ rfbCloseSock(cl->pScreen, cl->sock); ++ return; ++ } ++ ++#ifdef CORBA ++ addCapability(cl, KEYBOARD_DEVICE); ++ ++ if (!isKeyboardEnabled(cl)) ++ return; ++#endif ++ /*ErrorF("Key event: %d\n", msg.ke.key);*/ ++ if (!pVNC->rfbViewOnly && !cl->viewOnly) { ++ KbdAddEvent(msg.ke.down, (KeySym)Swap32IfLE(msg.ke.key), cl); ++ } ++ return; ++ ++ ++ case rfbPointerEvent: ++ ++ cl->rfbPointerEventsRcvd++; ++ ++ if ((n = ReadExact(cl->sock, ((char *)&msg) + 1, ++ sz_rfbPointerEventMsg - 1)) <= 0) { ++ if (n != 0) ++ rfbLogPerror("rfbProcessClientNormalMessage: read"); ++ rfbCloseSock(cl->pScreen, cl->sock); ++ return; ++ } ++ ++#ifdef CORBA ++ addCapability(cl, POINTER_DEVICE); ++ ++ if (!isPointerEnabled(cl)) ++ return; ++#endif ++ ++ if (pointerClient && (pointerClient != cl)) ++ return; ++ ++ if (msg.pe.buttonMask == 0) ++ pointerClient = NULL; ++ else ++ pointerClient = cl; ++ ++ if (!pVNC->rfbViewOnly && !cl->viewOnly) { ++ cl->cursorX = (int)Swap16IfLE(msg.pe.x); ++ cl->cursorY = (int)Swap16IfLE(msg.pe.y); ++ PtrAddEvent(msg.pe.buttonMask, cl->cursorX, cl->cursorY, cl); ++ } ++ return; ++ ++ ++ case rfbClientCutText: ++ ++ if ((n = ReadExact(cl->sock, ((char *)&msg) + 1, ++ sz_rfbClientCutTextMsg - 1)) <= 0) { ++ if (n != 0) ++ rfbLogPerror("rfbProcessClientNormalMessage: read"); ++ rfbCloseSock(cl->pScreen, cl->sock); ++ return; ++ } ++ ++ msg.cct.length = Swap32IfLE(msg.cct.length); ++ ++ str = (char *)xalloc(msg.cct.length); ++ ++ if ((n = ReadExact(cl->sock, str, msg.cct.length)) <= 0) { ++ if (n != 0) ++ rfbLogPerror("rfbProcessClientNormalMessage: read"); ++ xfree(str); ++ rfbCloseSock(cl->pScreen, cl->sock); ++ return; ++ } ++ ++ /* NOTE: We do not accept cut text from a view-only client */ ++ if (!cl->viewOnly) ++ rfbSetXCutText(str, msg.cct.length); ++ ++ xfree(str); ++ return; ++ ++#ifdef CHROMIUM ++ case rfbChromiumStop: ++ if ((n = ReadExact(cl->sock, ((char *)&msg) + 1, ++ sz_rfbChromiumStopMsg - 1)) <= 0) { ++ if (n != 0) ++ rfbLogPerror("rfbProcessClientNormalMessage: read"); ++ rfbCloseSock(cl->pScreen, cl->sock); ++ return; ++ } ++ ++ /* would we use msg.csd.port ??? */ ++ ++ cl->chromium_port = 0; ++ ++ /* tear down window information */ ++ { ++ CRWindowTable *wt, *nextWt = NULL; ++ ++ for (wt = windowTable; wt; wt = nextWt) { ++ nextWt = wt->next; ++ xfree(wt); ++ } ++ ++ windowTable = NULL; ++ } ++ ++ return; ++ ++ case rfbChromiumExpose: ++ if ((n = ReadExact(cl->sock, ((char *)&msg) + 1, ++ sz_rfbChromiumExposeMsg - 1)) <= 0) { ++ if (n != 0) ++ rfbLogPerror("rfbProcessClientNormalMessage: read"); ++ rfbCloseSock(cl->pScreen, cl->sock); ++ return; ++ } ++ ++ /* find the window and re-expose it */ ++ { ++ CRWindowTable *wt, *nextWt = NULL; ++ ++ for (wt = windowTable; wt; wt = nextWt) { ++ nextWt = wt->next; ++ if (wt->CRwinId == msg.cse.winid) { ++ WindowPtr pWin; ++ pWin = LookupIDByType(wt->XwinId, RT_WINDOW); ++ if (pWin) { ++ miSendExposures(pWin, &pWin->clipList, ++ pWin->drawable.x, ++ pWin->drawable.y); ++ FlushAllOutput(); ++ } ++ } ++ } ++ } ++ ++ return; ++#endif ++ ++ default: ++ ++ rfbLog("rfbProcessClientNormalMessage: unknown message type %d\n", ++ msg.type); ++ rfbLog(" ... closing connection\n"); ++ rfbCloseSock(cl->pScreen, cl->sock); ++ return; ++ } ++} ++ ++ ++ ++/* ++ * rfbSendFramebufferUpdate - send the currently pending framebuffer update to ++ * the RFB client. ++ */ ++ ++Bool ++rfbSendFramebufferUpdate(pScreen, cl) ++ ScreenPtr pScreen; ++ rfbClientPtr cl; ++{ ++ VNCSCREENPTR(pScreen); ++ int i; ++ int nUpdateRegionRects; ++ rfbFramebufferUpdateMsg *fu = (rfbFramebufferUpdateMsg *)pVNC->updateBuf; ++ RegionRec updateRegion, updateCopyRegion; ++ int dx, dy; ++ Bool sendCursorShape = FALSE; ++ Bool sendCursorPos = FALSE; ++ ++ /* ++ * If this client understands cursor shape updates, cursor should be ++ * removed from the framebuffer. Otherwise, make sure it's put up. ++ */ ++ ++#if !XFREE86VNC ++ if (cl->enableCursorShapeUpdates) { ++ if (pVNC->cursorIsDrawn) ++ rfbSpriteRemoveCursor(pScreen); ++ if (!pVNC->cursorIsDrawn && cl->cursorWasChanged) ++ sendCursorShape = TRUE; ++ } else { ++ if (!pVNC->cursorIsDrawn) ++ rfbSpriteRestoreCursor(pScreen); ++ } ++#else ++ if (cl->enableCursorShapeUpdates) ++ if (cl->cursorWasChanged) ++ sendCursorShape = TRUE; ++#endif ++ ++ /* ++ * Do we plan to send cursor position update? ++ */ ++ ++ if (cl->enableCursorPosUpdates && cl->cursorWasMoved) ++ sendCursorPos = TRUE; ++ ++ /* ++ * The modifiedRegion may overlap the destination copyRegion. We remove ++ * any overlapping bits from the copyRegion (since they'd only be ++ * overwritten anyway). ++ */ ++ ++ REGION_SUBTRACT(pScreen, &cl->copyRegion, &cl->copyRegion, ++ &cl->modifiedRegion); ++ ++ /* ++ * The client is interested in the region requestedRegion. The region ++ * which should be updated now is the intersection of requestedRegion ++ * and the union of modifiedRegion and copyRegion. If it's empty then ++ * no update is needed. ++ */ ++ ++ REGION_NULL(pScreen,&updateRegion); ++ REGION_UNION(pScreen, &updateRegion, &cl->copyRegion, ++ &cl->modifiedRegion); ++ REGION_INTERSECT(pScreen, &updateRegion, &cl->requestedRegion, ++ &updateRegion); ++ ++ if ( !REGION_NOTEMPTY(pScreen,&updateRegion) && ++ !sendCursorShape && !sendCursorPos ) { ++ REGION_UNINIT(pScreen,&updateRegion); ++ return TRUE; ++ } ++ ++ /* ++ * We assume that the client doesn't have any pixel data outside the ++ * requestedRegion. In other words, both the source and destination of a ++ * copy must lie within requestedRegion. So the region we can send as a ++ * copy is the intersection of the copyRegion with both the requestedRegion ++ * and the requestedRegion translated by the amount of the copy. We set ++ * updateCopyRegion to this. ++ */ ++ ++ REGION_NULL(pScreen,&updateCopyRegion); ++ REGION_INTERSECT(pScreen, &updateCopyRegion, &cl->copyRegion, ++ &cl->requestedRegion); ++ REGION_TRANSLATE(pScreen, &cl->requestedRegion, cl->copyDX, cl->copyDY); ++ REGION_INTERSECT(pScreen, &updateCopyRegion, &updateCopyRegion, ++ &cl->requestedRegion); ++ dx = cl->copyDX; ++ dy = cl->copyDY; ++ ++ /* ++ * Next we remove updateCopyRegion from updateRegion so that updateRegion ++ * is the part of this update which is sent as ordinary pixel data (i.e not ++ * a copy). ++ */ ++ ++ REGION_SUBTRACT(pScreen, &updateRegion, &updateRegion, &updateCopyRegion); ++ ++ /* ++ * Finally we leave modifiedRegion to be the remainder (if any) of parts of ++ * the screen which are modified but outside the requestedRegion. We also ++ * empty both the requestedRegion and the copyRegion - note that we never ++ * carry over a copyRegion for a future update. ++ */ ++ ++ REGION_UNION(pScreen, &cl->modifiedRegion, &cl->modifiedRegion, ++ &cl->copyRegion); ++ REGION_SUBTRACT(pScreen, &cl->modifiedRegion, &cl->modifiedRegion, ++ &updateRegion); ++ REGION_SUBTRACT(pScreen, &cl->modifiedRegion, &cl->modifiedRegion, ++ &updateCopyRegion); ++ ++ REGION_EMPTY(pScreen, &cl->requestedRegion); ++ REGION_EMPTY(pScreen, &cl->copyRegion); ++ cl->copyDX = 0; ++ cl->copyDY = 0; ++ ++ /* ++ * Now send the update. ++ */ ++ ++ cl->rfbFramebufferUpdateMessagesSent++; ++ ++ if (cl->preferredEncoding == rfbEncodingCoRRE) { ++ nUpdateRegionRects = 0; ++ ++ for (i = 0; i < REGION_NUM_RECTS(&updateRegion); i++) { ++ int x = REGION_RECTS(&updateRegion)[i].x1; ++ int y = REGION_RECTS(&updateRegion)[i].y1; ++ int w = REGION_RECTS(&updateRegion)[i].x2 - x; ++ int h = REGION_RECTS(&updateRegion)[i].y2 - y; ++ nUpdateRegionRects += (((w-1) / cl->correMaxWidth + 1) ++ * ((h-1) / cl->correMaxHeight + 1)); ++ } ++ } else if (cl->preferredEncoding == rfbEncodingZlib) { ++ nUpdateRegionRects = 0; ++ ++ for (i = 0; i < REGION_NUM_RECTS(&updateRegion); i++) { ++ int x = REGION_RECTS(&updateRegion)[i].x1; ++ int y = REGION_RECTS(&updateRegion)[i].y1; ++ int w = REGION_RECTS(&updateRegion)[i].x2 - x; ++ int h = REGION_RECTS(&updateRegion)[i].y2 - y; ++ nUpdateRegionRects += (((h-1) / (ZLIB_MAX_SIZE( w ) / w)) + 1); ++ } ++ } else if (cl->preferredEncoding == rfbEncodingTight) { ++ nUpdateRegionRects = 0; ++ ++ for (i = 0; i < REGION_NUM_RECTS(&updateRegion); i++) { ++ int x = REGION_RECTS(&updateRegion)[i].x1; ++ int y = REGION_RECTS(&updateRegion)[i].y1; ++ int w = REGION_RECTS(&updateRegion)[i].x2 - x; ++ int h = REGION_RECTS(&updateRegion)[i].y2 - y; ++ int n = rfbNumCodedRectsTight(cl, x, y, w, h); ++ if (n == 0) { ++ nUpdateRegionRects = 0xFFFF; ++ break; ++ } ++ nUpdateRegionRects += n; ++ } ++ } else { ++ nUpdateRegionRects = REGION_NUM_RECTS(&updateRegion); ++ } ++ ++ fu->type = rfbFramebufferUpdate; ++ if (nUpdateRegionRects != 0xFFFF) { ++ fu->nRects = Swap16IfLE(REGION_NUM_RECTS(&updateCopyRegion) + ++ nUpdateRegionRects + ++ !!sendCursorShape + !!sendCursorPos); ++ } else { ++ fu->nRects = 0xFFFF; ++ } ++ pVNC->ublen = sz_rfbFramebufferUpdateMsg; ++ ++ if (sendCursorShape) { ++ cl->cursorWasChanged = FALSE; ++ if (!rfbSendCursorShape(cl, pScreen)) ++ return FALSE; ++ } ++ ++ if (sendCursorPos) { ++ cl->cursorWasMoved = FALSE; ++ if (!rfbSendCursorPos(cl, pScreen)) ++ return FALSE; ++ } ++ ++ if (REGION_NOTEMPTY(pScreen,&updateCopyRegion)) { ++ if (!rfbSendCopyRegion(cl,&updateCopyRegion,dx,dy)) { ++ REGION_UNINIT(pScreen,&updateRegion); ++ REGION_UNINIT(pScreen,&updateCopyRegion); ++ return FALSE; ++ } ++ } ++ ++ REGION_UNINIT(pScreen,&updateCopyRegion); ++ ++ for (i = 0; i < REGION_NUM_RECTS(&updateRegion); i++) { ++ int x = REGION_RECTS(&updateRegion)[i].x1; ++ int y = REGION_RECTS(&updateRegion)[i].y1; ++ int w = REGION_RECTS(&updateRegion)[i].x2 - x; ++ int h = REGION_RECTS(&updateRegion)[i].y2 - y; ++ ++ cl->rfbRawBytesEquivalent += (sz_rfbFramebufferUpdateRectHeader ++ + w * (cl->format.bitsPerPixel / 8) * h); ++ ++ switch (cl->preferredEncoding) { ++ case rfbEncodingRaw: ++ if (!rfbSendRectEncodingRaw(cl, x, y, w, h)) { ++ REGION_UNINIT(pScreen,&updateRegion); ++ return FALSE; ++ } ++ break; ++ case rfbEncodingRRE: ++ if (!rfbSendRectEncodingRRE(cl, x, y, w, h)) { ++ REGION_UNINIT(pScreen,&updateRegion); ++ return FALSE; ++ } ++ break; ++ case rfbEncodingCoRRE: ++ if (!rfbSendRectEncodingCoRRE(cl, x, y, w, h)) { ++ REGION_UNINIT(pScreen,&updateRegion); ++ return FALSE; ++ } ++ break; ++ case rfbEncodingHextile: ++ if (!rfbSendRectEncodingHextile(cl, x, y, w, h)) { ++ REGION_UNINIT(pScreen,&updateRegion); ++ return FALSE; ++ } ++ break; ++ case rfbEncodingZlib: ++ if (!rfbSendRectEncodingZlib(cl, x, y, w, h)) { ++ REGION_UNINIT(pScreen,&updateRegion); ++ return FALSE; ++ } ++ break; ++ case rfbEncodingTight: ++ if (!rfbSendRectEncodingTight(cl, x, y, w, h)) { ++ REGION_UNINIT(pScreen,&updateRegion); ++ return FALSE; ++ } ++ break; ++ } ++ } ++ ++ REGION_UNINIT(pScreen,&updateRegion); ++ ++ if (nUpdateRegionRects == 0xFFFF && !rfbSendLastRectMarker(cl)) ++ return FALSE; ++ ++ if (!rfbSendUpdateBuf(cl)) ++ return FALSE; ++ ++ return TRUE; ++} ++ ++ ++ ++/* ++ * Send the copy region as a string of CopyRect encoded rectangles. ++ * The only slightly tricky thing is that we should send the messages in ++ * the correct order so that an earlier CopyRect will not corrupt the source ++ * of a later one. ++ */ ++ ++static Bool ++rfbSendCopyRegion(cl, reg, dx, dy) ++ rfbClientPtr cl; ++ RegionPtr reg; ++ int dx, dy; ++{ ++ VNCSCREENPTR(cl->pScreen); ++ int nrects, nrectsInBand, x_inc, y_inc, thisRect, firstInNextBand; ++ int x, y, w, h; ++ rfbFramebufferUpdateRectHeader rect; ++ rfbCopyRect cr; ++ ++ nrects = REGION_NUM_RECTS(reg); ++ ++ if (dx <= 0) { ++ x_inc = 1; ++ } else { ++ x_inc = -1; ++ } ++ ++ if (dy <= 0) { ++ thisRect = 0; ++ y_inc = 1; ++ } else { ++ thisRect = nrects - 1; ++ y_inc = -1; ++ } ++ ++ while (nrects > 0) { ++ ++ firstInNextBand = thisRect; ++ nrectsInBand = 0; ++ ++ while ((nrects > 0) && ++ (REGION_RECTS(reg)[firstInNextBand].y1 ++ == REGION_RECTS(reg)[thisRect].y1)) ++ { ++ firstInNextBand += y_inc; ++ nrects--; ++ nrectsInBand++; ++ } ++ ++ if (x_inc != y_inc) { ++ thisRect = firstInNextBand - y_inc; ++ } ++ ++ while (nrectsInBand > 0) { ++ if ((pVNC->ublen + sz_rfbFramebufferUpdateRectHeader ++ + sz_rfbCopyRect) > UPDATE_BUF_SIZE) ++ { ++ if (!rfbSendUpdateBuf(cl)) ++ return FALSE; ++ } ++ ++ x = REGION_RECTS(reg)[thisRect].x1; ++ y = REGION_RECTS(reg)[thisRect].y1; ++ w = REGION_RECTS(reg)[thisRect].x2 - x; ++ h = REGION_RECTS(reg)[thisRect].y2 - y; ++ ++ rect.r.x = Swap16IfLE(x); ++ rect.r.y = Swap16IfLE(y); ++ rect.r.w = Swap16IfLE(w); ++ rect.r.h = Swap16IfLE(h); ++ rect.encoding = Swap32IfLE(rfbEncodingCopyRect); ++ ++ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&rect, ++ sz_rfbFramebufferUpdateRectHeader); ++ pVNC->ublen += sz_rfbFramebufferUpdateRectHeader; ++ ++ cr.srcX = Swap16IfLE(x - dx); ++ cr.srcY = Swap16IfLE(y - dy); ++ ++ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&cr, sz_rfbCopyRect); ++ pVNC->ublen += sz_rfbCopyRect; ++ ++ cl->rfbRectanglesSent[rfbEncodingCopyRect]++; ++ cl->rfbBytesSent[rfbEncodingCopyRect] ++ += sz_rfbFramebufferUpdateRectHeader + sz_rfbCopyRect; ++ ++ thisRect += x_inc; ++ nrectsInBand--; ++ } ++ ++ thisRect = firstInNextBand; ++ } ++ ++ return TRUE; ++} ++ ++ ++/* ++ * Send a given rectangle in raw encoding (rfbEncodingRaw). ++ */ ++ ++Bool ++rfbSendRectEncodingRaw(cl, x, y, w, h) ++ rfbClientPtr cl; ++ int x, y, w, h; ++{ ++ VNCSCREENPTR(cl->pScreen); ++ rfbFramebufferUpdateRectHeader rect; ++ int nlines; ++ int bytesPerLine = w * (cl->format.bitsPerPixel / 8); ++ int newy = y; ++ ++ /* Flush the buffer to guarantee correct alignment for translateFn(). */ ++ if (pVNC->ublen > 0) { ++ if (!rfbSendUpdateBuf(cl)) ++ return FALSE; ++ } ++ ++ rect.r.x = Swap16IfLE(x); ++ rect.r.y = Swap16IfLE(y); ++ rect.r.w = Swap16IfLE(w); ++ rect.r.h = Swap16IfLE(h); ++ rect.encoding = Swap32IfLE(rfbEncodingRaw); ++ ++ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&rect,sz_rfbFramebufferUpdateRectHeader); ++ pVNC->ublen += sz_rfbFramebufferUpdateRectHeader; ++ ++ cl->rfbRectanglesSent[rfbEncodingRaw]++; ++ cl->rfbBytesSent[rfbEncodingRaw] ++ += sz_rfbFramebufferUpdateRectHeader + bytesPerLine * h; ++ ++ nlines = (UPDATE_BUF_SIZE - pVNC->ublen) / bytesPerLine; ++ ++ while (TRUE) { ++ if (nlines > h) ++ nlines = h; ++ ++ (*cl->translateFn)(cl->pScreen, cl->translateLookupTable, &pVNC->rfbServerFormat, ++ &cl->format, &pVNC->updateBuf[pVNC->ublen], ++ pVNC->paddedWidthInBytes, w, nlines, x, newy); ++ ++ pVNC->ublen += nlines * bytesPerLine; ++ h -= nlines; ++ newy += nlines; ++ ++ if (h == 0) /* rect fitted in buffer, do next one */ ++ return TRUE; ++ ++ /* buffer full - flush partial rect and do another nlines */ ++ ++ if (!rfbSendUpdateBuf(cl)) ++ return FALSE; ++ ++ nlines = (UPDATE_BUF_SIZE - pVNC->ublen) / bytesPerLine; ++ if (nlines == 0) { ++ rfbLog("rfbSendRectEncodingRaw: send buffer too small for %d " ++ "bytes per line\n", bytesPerLine); ++ rfbCloseSock(cl->pScreen, cl->sock); ++ return FALSE; ++ } ++ } ++} ++ ++ ++/* ++ * Send an empty rectangle with encoding field set to value of ++ * rfbEncodingLastRect to notify client that this is the last ++ * rectangle in framebuffer update ("LastRect" extension of RFB ++ * protocol). ++ */ ++ ++static Bool ++rfbSendLastRectMarker(cl) ++ rfbClientPtr cl; ++{ ++ VNCSCREENPTR(cl->pScreen); ++ rfbFramebufferUpdateRectHeader rect; ++ ++ if (pVNC->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) { ++ if (!rfbSendUpdateBuf(cl)) ++ return FALSE; ++ } ++ ++ rect.encoding = Swap32IfLE(rfbEncodingLastRect); ++ rect.r.x = 0; ++ rect.r.y = 0; ++ rect.r.w = 0; ++ rect.r.h = 0; ++ ++ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&rect,sz_rfbFramebufferUpdateRectHeader); ++ pVNC->ublen += sz_rfbFramebufferUpdateRectHeader; ++ ++ cl->rfbLastRectMarkersSent++; ++ cl->rfbLastRectBytesSent += sz_rfbFramebufferUpdateRectHeader; ++ ++ return TRUE; ++} ++ ++ ++/* ++ * Send the contents of pVNC->updateBuf. Returns 1 if successful, -1 if ++ * not (errno should be set). ++ */ ++ ++Bool ++rfbSendUpdateBuf(cl) ++ rfbClientPtr cl; ++{ ++ VNCSCREENPTR(cl->pScreen); ++ ++ /* ++ int i; ++ for (i = 0; i < pVNC->ublen; i++) { ++ rfbLog("%02x ",((unsigned char *)pVNC->updateBuf)[i]); ++ } ++ rfbLog("\n"); ++ */ ++ ++ if (pVNC->ublen > 0 && WriteExact(cl->sock, (char*)pVNC->updateBuf, pVNC->ublen) < 0) { ++ rfbLogPerror("rfbSendUpdateBuf: write"); ++ rfbCloseSock(cl->pScreen, cl->sock); ++ return FALSE; ++ } ++ ++ pVNC->ublen = 0; ++ return TRUE; ++} ++ ++ ++ ++/* ++ * rfbSendSetColourMapEntries sends a SetColourMapEntries message to the ++ * client, using values from the currently installed colormap. ++ */ ++ ++Bool ++rfbSendSetColourMapEntries(cl, firstColour, nColours) ++ rfbClientPtr cl; ++ int firstColour; ++ int nColours; ++{ ++#if !XFREE86VNC ++ VNCSCREENPTR(cl->pScreen); ++#endif ++ char buf[sz_rfbSetColourMapEntriesMsg + 256 * 3 * 2]; ++ rfbSetColourMapEntriesMsg *scme = (rfbSetColourMapEntriesMsg *)buf; ++ CARD16 *rgb = (CARD16 *)(&buf[sz_rfbSetColourMapEntriesMsg]); ++ EntryPtr pent; ++ EntryPtr redEntry, greenEntry, blueEntry; ++ unsigned short redPart, greenPart, bluePart; ++ int i, len; ++ ++ scme->type = rfbSetColourMapEntries; ++ scme->nColours = Swap16IfLE(nColours); ++ ++ len = sz_rfbSetColourMapEntriesMsg; ++ ++ /* PseudoColor */ ++#if XFREE86VNC ++ if (miInstalledMaps[cl->pScreen->myNum]->class == PseudoColor) { ++#else ++ if (pVNC->rfbInstalledColormap->class == PseudoColor) { ++#endif ++ scme->firstColour = Swap16IfLE(firstColour); ++#if XFREE86VNC ++ pent = (EntryPtr)&miInstalledMaps[cl->pScreen->myNum]->red[firstColour]; ++#else ++ pent = (EntryPtr)&pVNC->rfbInstalledColormap->red[firstColour]; ++#endif ++ for (i = 0; i < nColours; i++) { ++ if (pent->fShared) { ++ rgb[i*3] = Swap16IfLE(pent->co.shco.red->color); ++ rgb[i*3+1] = Swap16IfLE(pent->co.shco.green->color); ++ rgb[i*3+2] = Swap16IfLE(pent->co.shco.blue->color); ++ } else { ++ rgb[i*3] = Swap16IfLE(pent->co.local.red); ++ rgb[i*3+1] = Swap16IfLE(pent->co.local.green); ++ rgb[i*3+2] = Swap16IfLE(pent->co.local.blue); ++ } ++ pent++; ++ } ++ } ++ ++ else { ++ ++ /* Break the DirectColor pixel into its r/g/b components */ ++#if XFREE86VNC ++ redPart = (firstColour & miInstalledMaps[cl->pScreen->myNum]->pVisual->redMask) ++ >> miInstalledMaps[cl->pScreen->myNum]->pVisual->offsetRed; ++ greenPart = (firstColour & miInstalledMaps[cl->pScreen->myNum]->pVisual->greenMask) ++ >> miInstalledMaps[cl->pScreen->myNum]->pVisual->offsetGreen; ++ bluePart = (firstColour & miInstalledMaps[cl->pScreen->myNum]->pVisual->blueMask) ++ >> miInstalledMaps[cl->pScreen->myNum]->pVisual->offsetBlue; ++#else ++ redPart = (firstColour & pVNC->rfbInstalledColormap->pVisual->redMask) ++ >> pVNC->rfbInstalledColormap->pVisual->offsetRed; ++ greenPart = (firstColour & pVNC->rfbInstalledColormap->pVisual->greenMask) ++ >> pVNC->rfbInstalledColormap->pVisual->offsetGreen; ++ bluePart = (firstColour & pVNC->rfbInstalledColormap->pVisual->blueMask) ++ >> pVNC->rfbInstalledColormap->pVisual->offsetBlue; ++#endif ++ ++ /* ++ * The firstColour field is only 16 bits. To support 24-bit pixels we ++ * sneak the red component in the 8-bit padding field which we renamed ++ * to redIndex. Green and blue are in firstColour (MSB, LSB respectively). ++ */ ++ scme->redIndex = Swap16IfLE(redPart); ++ scme->firstColour = Swap16IfLE((greenPart << 8) | bluePart); ++ ++#if XFREE86VNC ++ redEntry = (EntryPtr)&miInstalledMaps[cl->pScreen->myNum]->red[redPart]; ++ greenEntry = (EntryPtr)&miInstalledMaps[cl->pScreen->myNum]->green[greenPart]; ++ blueEntry = (EntryPtr)&miInstalledMaps[cl->pScreen->myNum]->blue[bluePart]; ++#else ++ redEntry = (EntryPtr)&pVNC->rfbInstalledColormap->red[redPart]; ++ greenEntry = (EntryPtr)&pVNC->rfbInstalledColormap->green[greenPart]; ++ blueEntry = (EntryPtr)&pVNC->rfbInstalledColormap->blue[bluePart]; ++#endif ++ for (i = 0; i < nColours; i++) { ++ if (redEntry->fShared) ++ rgb[i*3] = Swap16IfLE(redEntry->co.shco.red->color); ++ else ++ rgb[i*3] = Swap16IfLE(redEntry->co.local.red); ++ ++ if (greenEntry->fShared) ++ rgb[i*3+1] = Swap16IfLE(greenEntry->co.shco.green->color); ++ else ++ rgb[i*3+1] = Swap16IfLE(greenEntry->co.local.green); ++ ++ if (blueEntry->fShared) ++ rgb[i*3+2] = Swap16IfLE(blueEntry->co.shco.blue->color); ++ else ++ rgb[i*3+2] = Swap16IfLE(blueEntry->co.local.blue); ++ ++ redEntry++; ++ greenEntry++; ++ blueEntry++; ++ } ++ } ++ ++ len += nColours * 3 * 2; ++ ++ if (WriteExact(cl->sock, buf, len) < 0) { ++ rfbLogPerror("rfbSendSetColourMapEntries: write"); ++ rfbCloseSock(cl->pScreen, cl->sock); ++ return FALSE; ++ } ++ return TRUE; ++} ++ ++ ++/* ++ * rfbSendBell sends a Bell message to all the clients. ++ */ ++ ++void ++rfbSendBell(void) ++{ ++ rfbClientPtr cl, nextCl; ++ rfbBellMsg b; ++ ++ for (cl = rfbClientHead; cl; cl = nextCl) { ++ nextCl = cl->next; ++ b.type = rfbBell; ++ if (WriteExact(cl->sock, (char *)&b, sz_rfbBellMsg) < 0) { ++ rfbLogPerror("rfbSendBell: write"); ++ rfbCloseSock(cl->pScreen, cl->sock); ++ } ++ } ++} ++ ++#ifdef CHROMIUM ++#ifdef sun ++extern int inet_aton(const char *cp, struct in_addr *inp); ++#endif ++ ++ ++/** ++ * This sends a ChromiumStart message to all VNC viewers running on the ++ * host named by ipaddress. ++ * This is done in response to an OpenGL/Chromium app calling ++ * XVncChromiumStart(). ++ */ ++void ++rfbSendChromiumStart(unsigned int ipaddress, unsigned int crServerPort, ++ unsigned int mothershipPort) ++{ ++ rfbClientPtr cl, nextCl; ++ rfbChromiumStartMsg scd; ++ struct in_addr ip; ++ unsigned int vncipaddress; ++ ++ /*rfbLog("Enter %s\n", __func__);*/ ++ /* loop over vnc viewers/clients */ ++ for (cl = rfbClientHead; cl; cl = nextCl) { ++ nextCl = cl->next; ++ /*rfbLog("%s: cl=%p enableCr=%d\n", __func__, ++ (void*) cl, cl->enableChromiumEncoding); ++ */ ++ if (!cl->enableChromiumEncoding) { ++ /* viewer is not chromium-enhanced */ ++ continue; ++ } ++ inet_aton(cl->host, &ip); ++ memcpy(&vncipaddress, &ip, sizeof(unsigned int)); ++ rfbLog("%s: ipaddr=0x%x vncipaddr=0x%x cl->port=%d\n", ++ __func__, ipaddress, vncipaddress, cl->chromium_port); ++ if (ipaddress == vncipaddress /**&& !cl->chromium_port**/) { ++ cl->chromium_port = crServerPort; ++ cl->chromium_msport = mothershipPort; ++ scd.type = rfbChromiumStart; ++ scd.crServerPort = crServerPort; ++ scd.mothershipPort = mothershipPort; ++ if (WriteExact(cl->sock, (char *)&scd, ++ sz_rfbChromiumStartMsg) < 0) { ++ rfbLogPerror("rfbSendChromiumStart: write"); ++ rfbCloseSock(cl->pScreen, cl->sock); ++ } ++ /* We only start one client at a time, so break now! */ ++ break; ++ } ++ } ++ /*rfbLog("Leave %s\n", __func__);*/ ++} ++ ++ ++/** ++ * Begin monitoring the given X windowid. ++ * When we detect size/position/visibility changes we'll send a ++ * rfbChromiumMoveResizeWindow, rfbChromiumClipList, or rfbChromiumWindowShow ++ * message to the VNC viewer, passing the corresponding Chromium window id. ++ */ ++void ++rfbChromiumMonitorWindowID(unsigned int cr_windowid, unsigned long xwindowid) ++{ ++ CRWindowTable *newRec, *wt, *nextWt = NULL; ++ ++ if (xwindowid && !cr_windowid) { ++ /* stop monitoring the X window, remove from list */ ++ CRWindowTable *prev = NULL; ++ for (wt = windowTable; wt; wt = nextWt) { ++ nextWt = wt->next; ++ if (wt->XwinId == xwindowid) { ++ /* remove */ ++ if (prev) ++ prev->next = wt->next; ++ else ++ windowTable = wt->next; ++ xfree(wt); ++ } ++ else { ++ prev = wt; ++ } ++ } ++ return; ++ } ++ ++ /* See if we're already monitoring this window */ ++ for (wt = windowTable; wt; wt = nextWt) { ++ nextWt = wt->next; ++ /* and if so, update it's window ID */ ++ if (wt->CRwinId == cr_windowid) { ++ wt->XwinId = xwindowid; ++ return; ++ } ++ } ++ ++ /* o.k, new window so create new slot information */ ++ newRec = (CRWindowTable *)xalloc(sizeof(CRWindowTable)); ++ if (!newRec) { ++ rfbLog("Out of memory allocating CRWindowTable.\n"); ++ return; ++ } ++ ++ newRec->next = NULL; ++ newRec->CRwinId = cr_windowid; ++ newRec->XwinId = xwindowid; ++ newRec->clipRects = NULL; ++ newRec->numRects = 0; ++ ++ if (!windowTable) { ++ windowTable = newRec; ++ } ++ else { ++ for (wt = windowTable; wt; wt = nextWt) { ++ nextWt = wt->next; ++ if (!wt->next) /* found the next slot */ ++ wt->next = newRec; ++ } ++ } ++} ++ ++ ++void ++rfbSendChromiumMoveResizeWindow(unsigned int winid, int x, int y, unsigned int w, unsigned int h) ++{ ++ rfbClientPtr cl, nextCl; ++ rfbChromiumMoveResizeWindowMsg scm; ++ ++ for (cl = rfbClientHead; cl; cl = nextCl) { ++ nextCl = cl->next; ++ if (!cl->enableChromiumEncoding) ++ continue; ++ if (cl->chromium_port) { ++ scm.type = rfbChromiumMoveResizeWindow; ++ scm.winid = winid; ++ scm.x = x; ++ scm.y = y; ++ scm.w = w; ++ scm.h = h; ++ if (WriteExact(cl->sock, (char *)&scm, ++ sz_rfbChromiumMoveResizeWindowMsg) < 0) { ++ rfbLogPerror("rfbSendChromiumMoveResizeWindow: write\n"); ++ rfbCloseSock(cl->pScreen, cl->sock); ++ continue; ++ } ++ } ++ } ++} ++ ++void ++rfbSendChromiumClipList(unsigned int winid, BoxPtr pClipRects, int numClipRects) ++{ ++ rfbClientPtr cl, nextCl; ++ rfbChromiumClipListMsg sccl; ++ int len = sizeof(BoxRec) * numClipRects; ++ ++ for (cl = rfbClientHead; cl; cl = nextCl) { ++ nextCl = cl->next; ++ if (!cl->enableChromiumEncoding) ++ continue; ++ if (cl->chromium_port) { ++ sccl.type = rfbChromiumClipList; ++ sccl.winid = winid; ++ sccl.length = Swap32IfLE(len); ++ if (WriteExact(cl->sock, (char *)&sccl, ++ sz_rfbChromiumClipListMsg) < 0) { ++ rfbLogPerror("rfbSendChromiumClipList: write\n"); ++ rfbCloseSock(cl->pScreen, cl->sock); ++ continue; ++ } ++ if (WriteExact(cl->sock, (char *)pClipRects, len) < 0) { ++ rfbLogPerror("rfbSendChromiumClipList: write\n"); ++ rfbCloseSock(cl->pScreen, cl->sock); ++ continue; ++ } ++ } ++ } ++} ++ ++void ++rfbSendChromiumWindowShow(unsigned int winid, unsigned int show) ++{ ++ rfbClientPtr cl, nextCl; ++ rfbChromiumWindowShowMsg scws; ++ ++ for (cl = rfbClientHead; cl; cl = nextCl) { ++ nextCl = cl->next; ++ if (!cl->enableChromiumEncoding) ++ continue; ++ if (cl->chromium_port) { ++ scws.type = rfbChromiumWindowShow; ++ scws.winid = winid; ++ scws.show = show; ++ if (WriteExact(cl->sock, (char *)&scws, ++ sz_rfbChromiumWindowShowMsg) < 0) { ++ rfbLogPerror("rfbSendChromiumWindowShow: write\n"); ++ rfbCloseSock(cl->pScreen, cl->sock); ++ continue; ++ } ++ } ++ } ++} ++ ++void ++rfbSendChromiumWindowDestroy(unsigned int winid) ++{ ++ rfbClientPtr cl, nextCl; ++ rfbChromiumWindowDestroyMsg scwd; ++ ++ for (cl = rfbClientHead; cl; cl = nextCl) { ++ nextCl = cl->next; ++ if (!cl->enableChromiumEncoding) ++ continue; ++ if (cl->chromium_port) { ++ scwd.type = rfbChromiumWindowDestroy; ++ scwd.winid = winid; ++ if (WriteExact(cl->sock, (char *)&scwd, ++ sz_rfbChromiumWindowDestroyMsg) < 0) { ++ rfbLogPerror("rfbSendChromiumWindowDestroy: write\n"); ++ rfbCloseSock(cl->pScreen, cl->sock); ++ continue; ++ } ++ } ++ } ++} ++#endif /* CHROMIUM */ ++ ++/* ++ * rfbSendServerCutText sends a ServerCutText message to all the clients. ++ */ ++ ++void ++rfbSendServerCutText(char *str, int len) ++{ ++ rfbClientPtr cl, nextCl = NULL; ++ rfbServerCutTextMsg sct; ++ ++ for (cl = rfbClientHead; cl; cl = nextCl) { ++ if (cl->state != RFB_NORMAL) continue; ++ nextCl = cl->next; ++ sct.type = rfbServerCutText; ++ sct.length = Swap32IfLE(len); ++ if (WriteExact(cl->sock, (char *)&sct, ++ sz_rfbServerCutTextMsg) < 0) { ++ rfbLogPerror("rfbSendServerCutText: write\n"); ++ rfbCloseSock(cl->pScreen, cl->sock); ++ continue; ++ } ++ if (WriteExact(cl->sock, str, len) < 0) { ++ rfbLogPerror("rfbSendServerCutText: write\n"); ++ rfbCloseSock(cl->pScreen, cl->sock); ++ } ++ } ++} ++ ++ ++ ++ ++/***************************************************************************** ++ * ++ * UDP can be used for keyboard and pointer events when the underlying ++ * network is highly reliable. This is really here to support ORL's ++ * videotile, whose TCP implementation doesn't like sending lots of small ++ * packets (such as 100s of pen readings per second!). ++ */ ++ ++void ++rfbNewUDPConnection(sock) ++ int sock; ++{ ++ if (write(sock, &ptrAcceleration, 1) < 0) { ++ rfbLogPerror("rfbNewUDPConnection: write"); ++ } ++} ++ ++/* ++ * Because UDP is a message based service, we can't read the first byte and ++ * then the rest of the packet separately like we do with TCP. We will always ++ * get a whole packet delivered in one go, so we ask read() for the maximum ++ * number of bytes we can possibly get. ++ */ ++ ++void ++rfbProcessUDPInput(ScreenPtr pScreen, int sock) ++{ ++ VNCSCREENPTR(pScreen); ++ int n; ++ rfbClientToServerMsg msg; ++ ++ if ((n = read(sock, (char *)&msg, sizeof(msg))) <= 0) { ++ if (n < 0) { ++ rfbLogPerror("rfbProcessUDPInput: read"); ++ } ++ rfbDisconnectUDPSock(pScreen); ++ return; ++ } ++ ++ switch (msg.type) { ++ ++ case rfbKeyEvent: ++ if (n != sz_rfbKeyEventMsg) { ++ rfbLog("rfbProcessUDPInput: key event incorrect length\n"); ++ rfbDisconnectUDPSock(pScreen); ++ return; ++ } ++ if (!pVNC->rfbViewOnly) { ++ KbdAddEvent(msg.ke.down, (KeySym)Swap32IfLE(msg.ke.key), 0); ++ } ++ break; ++ ++ case rfbPointerEvent: ++ if (n != sz_rfbPointerEventMsg) { ++ rfbLog("rfbProcessUDPInput: ptr event incorrect length\n"); ++ rfbDisconnectUDPSock(pScreen); ++ return; ++ } ++ if (!pVNC->rfbViewOnly) { ++ PtrAddEvent(msg.pe.buttonMask, ++ Swap16IfLE(msg.pe.x), Swap16IfLE(msg.pe.y), 0); ++ } ++ break; ++ ++ default: ++ rfbLog("rfbProcessUDPInput: unknown message type %d\n", ++ msg.type); ++ rfbDisconnectUDPSock(pScreen); ++ } ++} +diff -pNur xorg-server-1.4.orig/hw/vnc/rre.c xorg-server-1.4/hw/vnc/rre.c +--- xorg-server-1.4.orig/hw/vnc/rre.c 1969-12-31 16:00:00.000000000 -0800 ++++ xorg-server-1.4/hw/vnc/rre.c 2007-09-06 16:09:45.000000000 -0700 +@@ -0,0 +1,324 @@ ++/* ++ * rre.c ++ * ++ * Routines to implement Rise-and-Run-length Encoding (RRE). This ++ * code is based on krw's original javatel rfbserver. ++ * ++ * Modified for XFree86 4.x by Alan Hourihane ++ */ ++ ++/* ++ * 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. ++ */ ++#ifdef HAVE_DIX_CONFIG_H ++#include ++#endif ++ ++ ++#include ++#include "rfb.h" ++ ++/* ++ * rreBeforeBuf contains pixel data in the client's format. ++ * rreAfterBuf contains the RRE encoded version. If the RRE encoded version is ++ * larger than the raw data or if it exceeds rreAfterBufSize then ++ * raw encoding is used instead. ++ */ ++ ++static int rreBeforeBufSize = 0; ++static unsigned char *rreBeforeBuf = NULL; ++ ++static int rreAfterBufSize = 0; ++static unsigned char *rreAfterBuf = NULL; ++static int rreAfterBufLen; ++ ++static int subrectEncode8(CARD8 *data, int w, int h); ++static int subrectEncode16(CARD16 *data, int w, int h); ++static int subrectEncode32(CARD32 *data, int w, int h); ++static CARD32 getBgColour(char *data, int size, int bpp); ++ ++ ++/* ++ * rfbSendRectEncodingRRE - send a given rectangle using RRE encoding. ++ */ ++ ++Bool ++rfbSendRectEncodingRRE(cl, x, y, w, h) ++ rfbClientPtr cl; ++ int x, y, w, h; ++{ ++ VNCSCREENPTR(cl->pScreen); ++ rfbFramebufferUpdateRectHeader rect; ++ rfbRREHeader hdr; ++ int nSubrects; ++ int i; ++ int maxRawSize = (pVNC->width * pVNC->height ++ * (cl->format.bitsPerPixel / 8)); ++ ++ if (rreBeforeBufSize < maxRawSize) { ++ rreBeforeBufSize = maxRawSize; ++ if (rreBeforeBuf == NULL) ++ rreBeforeBuf = (unsigned char *)xalloc(rreBeforeBufSize); ++ else ++ rreBeforeBuf = (unsigned char *)xrealloc(rreBeforeBuf, rreBeforeBufSize); ++ } ++ ++ if (rreAfterBufSize < maxRawSize) { ++ rreAfterBufSize = maxRawSize; ++ if (rreAfterBuf == NULL) ++ rreAfterBuf = (unsigned char *)xalloc(rreAfterBufSize); ++ else ++ rreAfterBuf = (unsigned char *)xrealloc(rreAfterBuf, rreAfterBufSize); ++ } ++ ++ (*cl->translateFn)(cl->pScreen, cl->translateLookupTable, ++ &pVNC->rfbServerFormat, ++ &cl->format, rreBeforeBuf, ++ pVNC->paddedWidthInBytes, w, h, x, y); ++ ++ switch (cl->format.bitsPerPixel) { ++ case 8: ++ nSubrects = subrectEncode8((CARD8 *)rreBeforeBuf, w, h); ++ break; ++ case 16: ++ nSubrects = subrectEncode16((CARD16 *)rreBeforeBuf, w, h); ++ break; ++ case 32: ++ nSubrects = subrectEncode32((CARD32 *)rreBeforeBuf, w, h); ++ break; ++ default: ++ rfbLog("getBgColour: bpp %d?\n",cl->format.bitsPerPixel); ++ exit(1); ++ } ++ ++ if (nSubrects < 0) { ++ ++ /* RRE encoding was too large, use raw */ ++ ++ return rfbSendRectEncodingRaw(cl, x, y, w, h); ++ } ++ ++ cl->rfbRectanglesSent[rfbEncodingRRE]++; ++ cl->rfbBytesSent[rfbEncodingRRE] += (sz_rfbFramebufferUpdateRectHeader ++ + sz_rfbRREHeader + rreAfterBufLen); ++ ++ if (pVNC->ublen + sz_rfbFramebufferUpdateRectHeader + sz_rfbRREHeader ++ > UPDATE_BUF_SIZE) ++ { ++ if (!rfbSendUpdateBuf(cl)) ++ return FALSE; ++ } ++ ++ rect.r.x = Swap16IfLE(x); ++ rect.r.y = Swap16IfLE(y); ++ rect.r.w = Swap16IfLE(w); ++ rect.r.h = Swap16IfLE(h); ++ rect.encoding = Swap32IfLE(rfbEncodingRRE); ++ ++ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&rect, ++ sz_rfbFramebufferUpdateRectHeader); ++ pVNC->ublen += sz_rfbFramebufferUpdateRectHeader; ++ ++ hdr.nSubrects = Swap32IfLE(nSubrects); ++ ++ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&hdr, sz_rfbRREHeader); ++ pVNC->ublen += sz_rfbRREHeader; ++ ++ for (i = 0; i < rreAfterBufLen;) { ++ ++ int bytesToCopy = UPDATE_BUF_SIZE - pVNC->ublen; ++ ++ if (i + bytesToCopy > rreAfterBufLen) { ++ bytesToCopy = rreAfterBufLen - i; ++ } ++ ++ memcpy(&pVNC->updateBuf[pVNC->ublen], &rreAfterBuf[i], bytesToCopy); ++ ++ pVNC->ublen += bytesToCopy; ++ i += bytesToCopy; ++ ++ if (pVNC->ublen == UPDATE_BUF_SIZE) { ++ if (!rfbSendUpdateBuf(cl)) ++ return FALSE; ++ } ++ } ++ ++ return TRUE; ++} ++ ++ ++ ++/* ++ * subrectEncode() encodes the given multicoloured rectangle as a background ++ * colour overwritten by single-coloured rectangles. It returns the number ++ * of subrectangles in the encoded buffer, or -1 if subrect encoding won't ++ * fit in the buffer. It puts the encoded rectangles in rreAfterBuf. The ++ * single-colour rectangle partition is not optimal, but does find the biggest ++ * horizontal or vertical rectangle top-left anchored to each consecutive ++ * coordinate position. ++ * ++ * The coding scheme is simply [...] where each ++ * is []. ++ */ ++ ++#define DEFINE_SUBRECT_ENCODE(bpp) \ ++static int \ ++subrectEncode##bpp(data,w,h) \ ++ CARD##bpp *data; \ ++ int w; \ ++ int h; \ ++{ \ ++ CARD##bpp cl; \ ++ rfbRectangle subrect; \ ++ int x,y; \ ++ int i,j; \ ++ int hx=0,hy,vx=0,vy; \ ++ int hyflag; \ ++ CARD##bpp *seg; \ ++ CARD##bpp *line; \ ++ int hw,hh,vw,vh; \ ++ int thex,they,thew,theh; \ ++ int numsubs = 0; \ ++ int newLen; \ ++ CARD##bpp bg = (CARD##bpp)getBgColour((char*)data,w*h,bpp); \ ++ \ ++ *((CARD##bpp*)rreAfterBuf) = bg; \ ++ \ ++ rreAfterBufLen = (bpp/8); \ ++ \ ++ for (y=0; y 0) && (i >= hx)) {hy += 1;} else {hyflag = 0;} \ ++ } \ ++ vy = j-1; \ ++ \ ++ /* We now have two possible subrects: (x,y,hx,hy) and (x,y,vx,vy) \ ++ * We'll choose the bigger of the two. \ ++ */ \ ++ hw = hx-x+1; \ ++ hh = hy-y+1; \ ++ vw = vx-x+1; \ ++ vh = vy-y+1; \ ++ \ ++ thex = x; \ ++ they = y; \ ++ \ ++ if ((hw*hh) > (vw*vh)) { \ ++ thew = hw; \ ++ theh = hh; \ ++ } else { \ ++ thew = vw; \ ++ theh = vh; \ ++ } \ ++ \ ++ subrect.x = Swap16IfLE(thex); \ ++ subrect.y = Swap16IfLE(they); \ ++ subrect.w = Swap16IfLE(thew); \ ++ subrect.h = Swap16IfLE(theh); \ ++ \ ++ newLen = rreAfterBufLen + (bpp/8) + sz_rfbRectangle; \ ++ if ((newLen > (w * h * (bpp/8))) || (newLen > rreAfterBufSize)) \ ++ return -1; \ ++ \ ++ numsubs += 1; \ ++ *((CARD##bpp*)(rreAfterBuf + rreAfterBufLen)) = cl; \ ++ rreAfterBufLen += (bpp/8); \ ++ memcpy(&rreAfterBuf[rreAfterBufLen],&subrect,sz_rfbRectangle); \ ++ rreAfterBufLen += sz_rfbRectangle; \ ++ \ ++ /* \ ++ * Now mark the subrect as done. \ ++ */ \ ++ for (j=they; j < (they+theh); j++) { \ ++ for (i=thex; i < (thex+thew); i++) { \ ++ data[j*w+i] = bg; \ ++ } \ ++ } \ ++ } \ ++ } \ ++ } \ ++ \ ++ return numsubs; \ ++} ++ ++DEFINE_SUBRECT_ENCODE(8) ++DEFINE_SUBRECT_ENCODE(16) ++DEFINE_SUBRECT_ENCODE(32) ++ ++ ++/* ++ * getBgColour() gets the most prevalent colour in a byte array. ++ */ ++static CARD32 ++getBgColour(data,size,bpp) ++ char *data; ++ int size; ++ int bpp; ++{ ++ ++#define NUMCLRS 256 ++ ++ static int counts[NUMCLRS]; ++ int i,j,k; ++ ++ int maxcount = 0; ++ CARD8 maxclr = 0; ++ ++ if (bpp != 8) { ++ if (bpp == 16) { ++ return ((CARD16 *)data)[0]; ++ } else if (bpp == 32) { ++ return ((CARD32 *)data)[0]; ++ } else { ++ rfbLog("getBgColour: bpp %d?\n",bpp); ++ exit(1); ++ } ++ } ++ ++ for (i=0; i= NUMCLRS) { ++ rfbLog("getBgColour: unusual colour = %d\n", k); ++ exit(1); ++ } ++ counts[k] += 1; ++ if (counts[k] > maxcount) { ++ maxcount = counts[k]; ++ maxclr = ((CARD8 *)data)[j]; ++ } ++ } ++ ++ return maxclr; ++} +diff -pNur xorg-server-1.4.orig/hw/vnc/sockets.c xorg-server-1.4/hw/vnc/sockets.c +--- xorg-server-1.4.orig/hw/vnc/sockets.c 1969-12-31 16:00:00.000000000 -0800 ++++ xorg-server-1.4/hw/vnc/sockets.c 2007-09-06 16:09:45.000000000 -0700 +@@ -0,0 +1,656 @@ ++/* ++ * sockets.c - deal with TCP & UDP sockets. ++ * ++ * This code should be independent of any changes in the RFB protocol. It just ++ * deals with the X server scheduling stuff, calling rfbNewClientConnection and ++ * rfbProcessClientMessage to actually deal with the protocol. If a socket ++ * needs to be closed for any reason then rfbCloseSock should be called, and ++ * this in turn will call rfbClientConnectionGone. To make an active ++ * connection out, call rfbConnect - note that this does _not_ call ++ * rfbNewClientConnection. ++ * ++ * This file is divided into two types of function. Those beginning with ++ * "rfb" are specific to sockets using the RFB protocol. Those without the ++ * "rfb" prefix are more general socket routines (which are used by the http ++ * code). ++ * ++ * Thanks to Karl Hakimian for pointing out that some platforms return EAGAIN ++ * not EWOULDBLOCK. ++ * ++ * Modified for XFree86 4.x by Alan Hourihane ++ */ ++ ++/* ++ * 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. ++ */ ++#ifdef HAVE_DIX_CONFIG_H ++#include ++#endif ++ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "windowstr.h" ++ ++#ifndef USE_LIBWRAP ++#define USE_LIBWRAP 0 ++#endif ++#if USE_LIBWRAP ++#include ++#include ++int allow_severity = LOG_INFO; ++int deny_severity = LOG_WARNING; ++#endif ++ ++#include "rfb.h" ++ ++int rfbMaxClientWait = 20000; /* time (ms) after which we decide client has ++ gone away - needed to stop us hanging */ ++ ++static struct sockaddr_in udpRemoteAddr; ++ ++/* ++ * rfbInitSockets sets up the TCP and UDP sockets to listen for RFB ++ * connections. It does nothing if called again. ++ */ ++ ++Bool ++rfbInitSockets(ScreenPtr pScreen) ++{ ++ VNCSCREENPTR(pScreen); ++ ++ if (inetdSock != -1) { ++ const int one = 1; ++ ++ if (fcntl(inetdSock, F_SETFL, O_NONBLOCK) < 0) { ++ rfbLogPerror("fcntl"); ++ return FALSE; ++ } ++ ++ if (setsockopt(inetdSock, IPPROTO_TCP, TCP_NODELAY, ++ (char *)&one, sizeof(one)) < 0) { ++ rfbLogPerror("setsockopt"); ++ return FALSE; ++ } ++ ++ AddEnabledDevice(inetdSock); ++ FD_ZERO(&pVNC->allFds); ++ FD_SET(inetdSock, &pVNC->allFds); ++ pVNC->maxFd = inetdSock; ++ return TRUE; ++ } ++ ++ if (pVNC->rfbPort == 0) { ++ pVNC->rfbPort = 5900 + atoi(display) + pScreen->myNum; ++ } ++ ++ if ((pVNC->rfbListenSock = ListenOnTCPPort(pScreen, pVNC->rfbPort)) < 0) { ++ rfbLogPerror("ListenOnTCPPort"); ++ pVNC->rfbPort = 0; ++ return FALSE; ++ } ++ ++ rfbLog("Listening for VNC connections on TCP port %d\n", pVNC->rfbPort); ++ ++ AddEnabledDevice(pVNC->rfbListenSock); ++ ++ FD_ZERO(&pVNC->allFds); ++ FD_SET(pVNC->rfbListenSock, &pVNC->allFds); ++ pVNC->maxFd = pVNC->rfbListenSock; ++ ++ if (pVNC->udpPort != 0) { ++ rfbLog("rfbInitSockets: listening for input on UDP port %d\n",pVNC->udpPort); ++ ++ if ((pVNC->udpSock = ListenOnUDPPort(pScreen, pVNC->udpPort)) < 0) { ++ rfbLogPerror("ListenOnUDPPort"); ++ return FALSE; ++ } ++ AddEnabledDevice(pVNC->udpSock); ++ FD_SET(pVNC->udpSock, &pVNC->allFds); ++ pVNC->maxFd = max(pVNC->udpSock,pVNC->maxFd); ++ } ++ ++ return TRUE; ++} ++ ++ ++/* ++ * rfbCheckFds is called from ProcessInputEvents to check for input on the RFB ++ * socket(s). If there is input to process, the appropriate function in the ++ * RFB server code will be called (rfbNewClientConnection, ++ * rfbProcessClientMessage, etc). ++ */ ++ ++void ++rfbCheckFds(ScreenPtr pScreen) ++{ ++ VNCSCREENPTR(pScreen); ++#if XFREE86VNC ++ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; ++#endif ++ int nfds; ++ fd_set fds; ++ struct timeval tv; ++ struct sockaddr_in addr; ++ SOCKLEN_T addrlen = sizeof(addr); ++ char buf[6]; ++ const int one = 1; ++ int sock; ++ static Bool inetdInitDone = FALSE; ++ ++ if (!inetdInitDone && inetdSock != -1) { ++ rfbNewClientConnection(pScreen, inetdSock); ++ inetdInitDone = TRUE; ++ } ++ ++ memcpy((char *)&fds, (char *)&pVNC->allFds, sizeof(fd_set)); ++ tv.tv_sec = 0; ++ tv.tv_usec = 0; ++ nfds = select(pVNC->maxFd + 1, &fds, NULL, NULL, &tv); ++ if (nfds == 0) { ++ return; ++ } ++ if (nfds < 0) { ++ if (errno != EINTR) ++ rfbLogPerror("rfbCheckFds: select"); ++ return; ++ } ++ ++ if (pVNC->rfbListenSock != -1 && FD_ISSET(pVNC->rfbListenSock, &fds)) { ++ ++ if ((sock = accept(pVNC->rfbListenSock, ++ (struct sockaddr *)&addr, &addrlen)) < 0) { ++ rfbLogPerror("rfbCheckFds: accept"); ++ return; ++ } ++ ++ if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) { ++ rfbLogPerror("rfbCheckFds: fcntl"); ++ close(sock); ++ return; ++ } ++ ++ if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, ++ (char *)&one, sizeof(one)) < 0) { ++ rfbLogPerror("rfbCheckFds: setsockopt"); ++ close(sock); ++ return; ++ } ++ ++ rfbLog("\n"); ++ ++#if USE_LIBWRAP ++ if (!hosts_ctl("Xvnc", STRING_UNKNOWN, inet_ntoa(addr.sin_addr), ++ STRING_UNKNOWN)) { ++ rfbLog("Rejected connection from client %s\n", ++ inet_ntoa(addr.sin_addr)); ++ close(sock); ++ return; ++ } ++#endif ++ ++ rfbLog("Got VNC connection from client %s\n", inet_ntoa(addr.sin_addr)); ++ ++ AddEnabledDevice(sock); ++ FD_SET(sock, &pVNC->allFds); ++ pVNC->maxFd = max(sock,pVNC->maxFd); ++ ++ rfbNewClientConnection(pScreen, sock); ++ ++ FD_CLR(pVNC->rfbListenSock, &fds); ++ if (--nfds == 0) ++ return; ++ } ++ ++ if ((pVNC->udpSock != -1) && FD_ISSET(pVNC->udpSock, &fds)) { ++ ++ if (recvfrom(pVNC->udpSock, buf, 1, MSG_PEEK, ++ (struct sockaddr *)&addr, &addrlen) < 0) { ++ ++ rfbLogPerror("rfbCheckFds: UDP: recvfrom"); ++ rfbDisconnectUDPSock(pScreen); ++ ++ } else { ++ ++ if (!pVNC->udpSockConnected || ++ (memcmp(&addr, &udpRemoteAddr, addrlen) != 0)) ++ { ++ /* new remote end */ ++ rfbLog("rfbCheckFds: UDP: got connection\n"); ++ ++ memcpy(&udpRemoteAddr, &addr, addrlen); ++ pVNC->udpSockConnected = TRUE; ++ ++ if (connect(pVNC->udpSock, ++ (struct sockaddr *)&addr, addrlen) < 0) { ++ rfbLogPerror("rfbCheckFds: UDP: connect"); ++ rfbDisconnectUDPSock(pScreen); ++ return; ++ } ++ ++ rfbNewUDPConnection(pVNC->udpSock); ++ } ++ ++ rfbProcessUDPInput(pScreen, pVNC->udpSock); ++ } ++ ++ FD_CLR(pVNC->udpSock, &fds); ++ if (--nfds == 0) ++ return; ++ } ++ ++ for (sock = 0; sock <= pVNC->maxFd; sock++) { ++ if (FD_ISSET(sock, &fds) && FD_ISSET(sock, &pVNC->allFds)) { ++#if XFREE86VNC ++ if (!pScrn->vtSema) ++ rfbCloseSock(pScreen, sock); ++ else ++#endif ++ rfbProcessClientMessage(pScreen, sock); ++ } ++ } ++} ++ ++ ++void ++rfbDisconnectUDPSock(ScreenPtr pScreen) ++{ ++ VNCSCREENPTR(pScreen); ++ pVNC->udpSockConnected = FALSE; ++} ++ ++ ++void ++rfbCloseSock(ScreenPtr pScreen, int sock) ++{ ++ VNCSCREENPTR(pScreen); ++ close(sock); ++ RemoveEnabledDevice(sock); ++ FD_CLR(sock, &pVNC->allFds); ++ rfbClientConnectionGone(sock); ++ if (sock == inetdSock) ++ GiveUp(0); ++} ++ ++#if 0 ++/* ++ * rfbWaitForClient can be called to wait for the RFB client to send us a ++ * message. When one is received it is processed by calling ++ * rfbProcessClientMessage(). ++ */ ++ ++void ++rfbWaitForClient(sock) ++ int sock; ++{ ++ int n; ++ fd_set fds; ++ struct timeval tv; ++ ++ FD_ZERO(&fds); ++ FD_SET(sock, &fds); ++ tv.tv_sec = rfbMaxClientWait / 1000; ++ tv.tv_usec = (rfbMaxClientWait % 1000) * 1000; ++ n = select(sock+1, &fds, NULL, NULL, &tv); ++ if (n < 0) { ++ rfbLogPerror("rfbWaitForClient: select"); ++ exit(1); ++ } ++ if (n == 0) { ++ rfbCloseSock(sock); ++ return; ++ } ++ ++ rfbProcessClientMessage(sock); ++} ++#endif ++ ++/* ++ * rfbConnect is called to make a connection out to a given TCP address. ++ */ ++ ++int ++rfbConnect(ScreenPtr pScreen, char *host, int port) ++{ ++ VNCSCREENPTR(pScreen); ++ int sock; ++ int one = 1; ++ ++ rfbLog("\n"); ++ rfbLog("Making connection to client on host %s port %d\n", ++ host,port); ++ ++ if ((sock = ConnectToTcpAddr(host, port)) < 0) { ++ rfbLogPerror("connection failed"); ++ return -1; ++ } ++ ++ if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) { ++ rfbLogPerror("fcntl failed"); ++ close(sock); ++ return -1; ++ } ++ ++ if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, ++ (char *)&one, sizeof(one)) < 0) { ++ rfbLogPerror("setsockopt failed"); ++ close(sock); ++ return -1; ++ } ++ ++ AddEnabledDevice(sock); ++ FD_SET(sock, &pVNC->allFds); ++ pVNC->maxFd = max(sock,pVNC->maxFd); ++ ++ return sock; ++} ++ ++ ++ ++ ++/* ++ * ReadExact reads an exact number of bytes on a TCP socket. Returns 1 if ++ * those bytes have been read, 0 if the other end has closed, or -1 if an error ++ * occurred (errno is set to ETIMEDOUT if it timed out). ++ */ ++ ++int ++ReadExact(sock, buf, len) ++ int sock; ++ char *buf; ++ int len; ++{ ++ int n; ++ fd_set fds; ++ int tries = 5; ++ struct timeval tv; ++ ++ while (len > 0) { ++ n = read(sock, buf, len); ++ ++ if (n > 0) { ++ ++ buf += n; ++ len -= n; ++ ++ } else if (n == 0) { ++ ++ return 0; ++ ++ } else { ++ if (errno != EWOULDBLOCK && errno != EAGAIN) { ++ return n; ++ } ++ ++ do { ++ FD_ZERO(&fds); ++ FD_SET(sock, &fds); ++ tv.tv_sec = rfbMaxClientWait / 1000; ++ tv.tv_usec = (rfbMaxClientWait % 1000) * 1000; ++ n = select(sock+1, &fds, NULL, NULL, &tv); ++ tries--; ++ ++ /* We really need to retry if we get EINTR, so spin */ ++ /* If after 5 attempts we're still broke, abort.... */ ++ ++ } while ((n < 0 && errno == EINTR) && tries > 0); ++ ++ if (n < 0) { ++ rfbLogPerror("ReadExact: select"); ++ return n; ++ } ++ if (n == 0) { ++ errno = ETIMEDOUT; ++ return -1; ++ } ++ } ++ } ++ return 1; ++} ++ ++ ++ ++/* ++ * WriteExact writes an exact number of bytes on a TCP socket. Returns 1 if ++ * those bytes have been written, or -1 if an error occurred (errno is set to ++ * ETIMEDOUT if it timed out). ++ */ ++ ++int ++WriteExact(sock, buf, len) ++ int sock; ++ char *buf; ++ int len; ++{ ++ int n; ++ fd_set fds; ++ struct timeval tv; ++#if 0 ++ int totalTimeWaited = 0; ++#endif ++ ++ while (len > 0) { ++ n = write(sock, buf, len); ++ ++ if (n > 0) { ++ ++ buf += n; ++ len -= n; ++ ++ } else if (n == 0) { ++ ++ rfbLog("WriteExact: write returned 0?\n"); ++ return -1; ++ ++ } else { ++ if (errno != EWOULDBLOCK && errno != EAGAIN) { ++ return n; ++ } ++ ++#if 0 ++ /* Retry every 5 seconds until we exceed rfbMaxClientWait. We ++ need to do this because select doesn't necessarily return ++ immediately when the other end has gone away */ ++ ++ FD_ZERO(&fds); ++ FD_SET(sock, &fds); ++ tv.tv_sec = 5; ++ tv.tv_usec = 0; ++#else ++ /* We're in the WakeupHandler now, so don't wait */ ++ ++ FD_ZERO(&fds); ++ FD_SET(sock, &fds); ++ tv.tv_sec = 0; ++ tv.tv_usec = 0; ++#endif ++ n = select(sock+1, NULL, &fds, NULL, &tv); ++#if 0 ++ if (n < 0) { ++ rfbLogPerror("WriteExact: select"); ++ return n; ++ } ++ if (n == 0) { ++ totalTimeWaited += 5000; ++ if (totalTimeWaited >= rfbMaxClientWait) { ++ errno = ETIMEDOUT; ++ return -1; ++ } ++ } else { ++ totalTimeWaited = 0; ++ } ++#endif ++ } ++ } ++ return 1; ++} ++ ++ ++int ++ListenOnTCPPort(ScreenPtr pScreen, int port) ++{ ++ VNCSCREENPTR(pScreen); ++ struct sockaddr_in addr; ++ int sock; ++ int one = 1; ++ ++ memset(&addr, 0, sizeof(addr)); ++ addr.sin_family = AF_INET; ++ addr.sin_port = htons(port); ++ addr.sin_addr.s_addr = pVNC->interface.s_addr; ++ ++ if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { ++ return -1; ++ } ++ if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, ++ (char *)&one, sizeof(one)) < 0) { ++ close(sock); ++ return -1; ++ } ++ if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { ++ close(sock); ++ return -1; ++ } ++ if (listen(sock, 5) < 0) { ++ close(sock); ++ return -1; ++ } ++ ++ return sock; ++} ++ ++ ++int ++ConnectToTcpAddr(host, port) ++ char *host; ++ int port; ++{ ++ struct hostent *hp; ++ int sock, n; ++ struct sockaddr_in addr; ++ int tries = 5; ++ ++ memset(&addr, 0, sizeof(addr)); ++ addr.sin_family = AF_INET; ++ addr.sin_port = htons(port); ++ ++ if ((addr.sin_addr.s_addr = inet_addr(host)) == -1) ++ { ++ if (!(hp = gethostbyname(host))) { ++ errno = EINVAL; ++ return -1; ++ } ++ addr.sin_addr.s_addr = *(unsigned long *)hp->h_addr; ++ } ++ ++ if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { ++ return -1; ++ } ++ ++ do { ++ sock = socket(AF_INET, SOCK_STREAM, 0); ++ tries--; ++ ++ /* We really need to retry if we get EINTR, so spin */ ++ /* If after 5 attempts we're still broke, abort.... */ ++ ++ } while ((sock < 0 && errno == EINTR) && tries > 0); ++ ++ if (sock < 0) { ++ return -1; ++ } ++ ++ tries = 5; ++ ++ do { ++ n = connect(sock, (struct sockaddr *)&addr, (sizeof(addr))); ++ tries--; ++ ++ /* We really need to retry if we get EINTR, so spin */ ++ /* If after 5 attempts we're still broke, abort.... */ ++ ++ } while ((n < 0 && errno == EINTR) && tries > 0); ++ ++ if (n < 0) { ++ close(sock); ++ return -1; ++ } ++ ++ return sock; ++} ++ ++ ++int ++ListenOnUDPPort(ScreenPtr pScreen, int port) ++{ ++ VNCSCREENPTR(pScreen); ++ struct sockaddr_in addr; ++ int sock; ++ int one = 1; ++ ++ memset(&addr, 0, sizeof(addr)); ++ addr.sin_family = AF_INET; ++ addr.sin_port = htons(port); ++ addr.sin_addr.s_addr = pVNC->interface.s_addr; ++ ++ if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { ++ return -1; ++ } ++ if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, ++ (char *)&one, sizeof(one)) < 0) { ++ return -1; ++ } ++ if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { ++ return -1; ++ } ++ ++ return sock; ++} ++ ++#if 0 ++/* ++ * rdpInitSockets sets up the TCP for RDP ++ * connections. It does nothing if called again. ++ */ ++ ++Bool ++rdpInitSockets(ScreenPtr pScreen) ++{ ++ VNCSCREENPTR(pScreen); ++ ++ if ((pVNC->rdpListenSock = ListenOnTCPPort(pScreen, pVNC->rdpPort)) < 0) { ++ rfbLogPerror("ListenOnTCPPort"); ++ pVNC->rdpPort = 0; ++ return FALSE; ++ } ++ ++ rfbLog("Listening for RDP connections on TCP port %d\n", pVNC->rdpPort); ++ ++ AddEnabledDevice(pVNC->rdpListenSock); ++ ++ return TRUE; ++} ++#endif +diff -pNur xorg-server-1.4.orig/hw/vnc/sprite.c xorg-server-1.4/hw/vnc/sprite.c +--- xorg-server-1.4.orig/hw/vnc/sprite.c 1969-12-31 16:00:00.000000000 -0800 ++++ xorg-server-1.4/hw/vnc/sprite.c 2007-09-06 16:09:45.000000000 -0700 +@@ -0,0 +1,2452 @@ ++/* ++ * sprite.c ++ * ++ * software sprite routines - based on misprite ++ * ++ * Modified for XFree86 4.x by Alan Hourihane ++ */ ++ ++/* ++ * 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. ++ */ ++ ++/* $XConsortium: misprite.c,v 5.47 94/04/17 20:27:53 dpw Exp $ */ ++ ++/* ++ ++Copyright (c) 1989 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. ++*/ ++#ifdef HAVE_DIX_CONFIG_H ++#include ++#endif ++ ++ ++#include "rfb.h" ++# include ++# include ++# include ++# include ++# include "misc.h" ++# include "pixmapstr.h" ++# include "input.h" ++# include "mi.h" ++# include "cursorstr.h" ++# include "scrnintstr.h" ++# include "colormapst.h" ++# include "windowstr.h" ++# include "gcstruct.h" ++# include "mipointer.h" ++# include "spritest.h" ++# include "dixfontstr.h" ++#ifdef RENDER ++# include "mipict.h" ++#endif ++ ++/* ++ * screen wrappers ++ */ ++ ++static int rfbSpriteScreenIndex; ++static unsigned long rfbSpriteGeneration = 0; ++ ++static Bool rfbSpriteCloseScreen(int i, ScreenPtr pScreen); ++static void rfbSpriteGetImage(DrawablePtr pDrawable, int sx, int sy, ++ int w, int h, unsigned int format, ++ unsigned long planemask, char *pdstLine); ++static void rfbSpriteGetSpans(DrawablePtr pDrawable, int wMax, ++ DDXPointPtr ppt, int *pwidth, int nspans, ++ char *pdstStart); ++static void rfbSpriteSourceValidate(DrawablePtr pDrawable, int x, int y, ++ int width, int height); ++static Bool rfbSpriteCreateGC(GCPtr pGC); ++static void rfbSpriteBlockHandler(int i, pointer blockData, ++ pointer pTimeout, ++ pointer pReadMask); ++static void rfbSpriteInstallColormap(ColormapPtr pMap); ++static void rfbSpriteStoreColors(ColormapPtr pMap, int ndef, ++ xColorItem *pdef); ++ ++static void rfbSpritePaintWindowBackground(WindowPtr pWin, ++ RegionPtr pRegion, int what); ++static void rfbSpritePaintWindowBorder(WindowPtr pWin, ++ RegionPtr pRegion, int what); ++static void rfbSpriteCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, ++ RegionPtr pRegion); ++static void rfbSpriteClearToBackground(WindowPtr pWin, int x, int y, ++ int w, int h, ++ Bool generateExposures); ++ ++#ifdef RENDER ++static void rfbSpriteComposite(CARD8 op, ++ PicturePtr pSrc, ++ PicturePtr pMask, ++ PicturePtr pDst, ++ INT16 xSrc, ++ INT16 ySrc, ++ INT16 xMask, ++ INT16 yMask, ++ INT16 xDst, ++ INT16 yDst, ++ CARD16 width, ++ CARD16 height); ++ ++static void rfbSpriteGlyphs(CARD8 op, ++ PicturePtr pSrc, ++ PicturePtr pDst, ++ PictFormatPtr maskFormat, ++ INT16 xSrc, ++ INT16 ySrc, ++ int nlist, ++ GlyphListPtr list, ++ GlyphPtr *glyphs); ++#endif ++ ++static void rfbSpriteSaveDoomedAreas(WindowPtr pWin, ++ RegionPtr pObscured, int dx, ++ int dy); ++static RegionPtr rfbSpriteRestoreAreas(WindowPtr pWin, RegionPtr pRgnExposed); ++static void rfbSpriteComputeSaved(ScreenPtr pScreen); ++ ++#define SCREEN_PROLOGUE(pScreen, field)\ ++ ((pScreen)->field = \ ++ ((rfbSpriteScreenPtr) (pScreen)->devPrivates[rfbSpriteScreenIndex].ptr)->field) ++ ++#define SCREEN_EPILOGUE(pScreen, field, wrapper)\ ++ ((pScreen)->field = wrapper) ++ ++/* ++ * GC func wrappers ++ */ ++ ++static int rfbSpriteGCIndex; ++ ++static void rfbSpriteValidateGC(GCPtr pGC, unsigned long stateChanges, ++ DrawablePtr pDrawable); ++static void rfbSpriteCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst); ++static void rfbSpriteDestroyGC(GCPtr pGC); ++static void rfbSpriteChangeGC(GCPtr pGC, unsigned long mask); ++static void rfbSpriteChangeClip(GCPtr pGC, int type, pointer pvalue, int nrects); ++static void rfbSpriteDestroyClip(GCPtr pGC); ++static void rfbSpriteCopyClip(GCPtr pgcDst, GCPtr pgcSrc); ++ ++static GCFuncs rfbSpriteGCFuncs = { ++ rfbSpriteValidateGC, ++ rfbSpriteChangeGC, ++ rfbSpriteCopyGC, ++ rfbSpriteDestroyGC, ++ rfbSpriteChangeClip, ++ rfbSpriteDestroyClip, ++ rfbSpriteCopyClip, ++}; ++ ++#define GC_FUNC_PROLOGUE(pGC) \ ++ rfbSpriteGCPtr pGCPriv = \ ++ (rfbSpriteGCPtr) (pGC)->devPrivates[rfbSpriteGCIndex].ptr;\ ++ (pGC)->funcs = pGCPriv->wrapFuncs; \ ++ if (pGCPriv->wrapOps) \ ++ (pGC)->ops = pGCPriv->wrapOps; ++ ++#define GC_FUNC_EPILOGUE(pGC) \ ++ pGCPriv->wrapFuncs = (pGC)->funcs; \ ++ (pGC)->funcs = &rfbSpriteGCFuncs; \ ++ if (pGCPriv->wrapOps) \ ++ { \ ++ pGCPriv->wrapOps = (pGC)->ops; \ ++ (pGC)->ops = &rfbSpriteGCOps; \ ++ } ++ ++/* ++ * GC op wrappers ++ */ ++ ++static void rfbSpriteFillSpans(DrawablePtr pDrawable, GCPtr pGC, ++ int nInit, DDXPointPtr pptInit, ++ int *pwidthInit, int fSorted); ++static void rfbSpriteSetSpans(DrawablePtr pDrawable, GCPtr pGC, ++ char *psrc, DDXPointPtr ppt, int *pwidth, ++ int nspans, int fSorted); ++static void rfbSpritePutImage(DrawablePtr pDrawable, GCPtr pGC, ++ int depth, int x, int y, int w, int h, ++ int leftPad, int format, char *pBits); ++static RegionPtr rfbSpriteCopyArea(DrawablePtr pSrc, DrawablePtr pDst, ++ GCPtr pGC, int srcx, int srcy, int w, ++ int h, int dstx, int dsty); ++static RegionPtr rfbSpriteCopyPlane(DrawablePtr pSrc, DrawablePtr pDst, ++ GCPtr pGC, int srcx, int srcy, int w, ++ int h, int dstx, int dsty, ++ unsigned long plane); ++static void rfbSpritePolyPoint(DrawablePtr pDrawable, GCPtr pGC, ++ int mode, int npt, xPoint *pptInit); ++static void rfbSpritePolylines(DrawablePtr pDrawable, GCPtr pGC, ++ int mode, int npt, DDXPointPtr pptInit); ++static void rfbSpritePolySegment(DrawablePtr pDrawable, GCPtr pGC, ++ int nseg, xSegment *pSegs); ++static void rfbSpritePolyRectangle(DrawablePtr pDrawable, GCPtr pGC, ++ int nrects, xRectangle *pRects); ++static void rfbSpritePolyArc(DrawablePtr pDrawable, GCPtr pGC, ++ int narcs, xArc *parcs); ++static void rfbSpriteFillPolygon(DrawablePtr pDrawable, GCPtr pGC, ++ int shape, int mode, int count, ++ DDXPointPtr pPts); ++static void rfbSpritePolyFillRect(DrawablePtr pDrawable, GCPtr pGC, ++ int nrectFill, xRectangle *prectInit); ++static void rfbSpritePolyFillArc(DrawablePtr pDrawable, GCPtr pGC, ++ int narcs, xArc *parcs); ++static int rfbSpritePolyText8(DrawablePtr pDrawable, GCPtr pGC, ++ int x, int y, int count, char *chars); ++static int rfbSpritePolyText16(DrawablePtr pDrawable, GCPtr pGC, ++ int x, int y, int count, ++ unsigned short *chars); ++static void rfbSpriteImageText8(DrawablePtr pDrawable, GCPtr pGC, ++ int x, int y, int count, char *chars); ++static void rfbSpriteImageText16(DrawablePtr pDrawable, GCPtr pGC, ++ int x, int y, int count, ++ unsigned short *chars); ++static void rfbSpriteImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, ++ int x, int y, unsigned int nglyph, ++ CharInfoPtr *ppci, ++ pointer pglyphBase); ++static void rfbSpritePolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, ++ int x, int y, unsigned int nglyph, ++ CharInfoPtr *ppci, ++ pointer pglyphBase); ++static void rfbSpritePushPixels(GCPtr pGC, PixmapPtr pBitMap, ++ DrawablePtr pDst, int w, int h, ++ int x, int y); ++#ifdef NEED_LINEHELPER ++static void rfbSpriteLineHelper(); ++#endif ++ ++static GCOps rfbSpriteGCOps = { ++ rfbSpriteFillSpans, rfbSpriteSetSpans, rfbSpritePutImage, ++ rfbSpriteCopyArea, rfbSpriteCopyPlane, rfbSpritePolyPoint, ++ rfbSpritePolylines, rfbSpritePolySegment, rfbSpritePolyRectangle, ++ rfbSpritePolyArc, rfbSpriteFillPolygon, rfbSpritePolyFillRect, ++ rfbSpritePolyFillArc, rfbSpritePolyText8, rfbSpritePolyText16, ++ rfbSpriteImageText8, rfbSpriteImageText16, rfbSpriteImageGlyphBlt, ++ rfbSpritePolyGlyphBlt, rfbSpritePushPixels ++#ifdef NEED_LINEHELPER ++ , rfbSpriteLineHelper ++#endif ++}; ++ ++/* ++ * testing only -- remove cursor for every draw. Eventually, ++ * each draw operation will perform a bounding box check against ++ * the saved cursor area ++ */ ++ ++#define GC_SETUP_CHEAP(pDrawable) \ ++ rfbSpriteScreenPtr pScreenPriv = (rfbSpriteScreenPtr) \ ++ (pDrawable)->pScreen->devPrivates[rfbSpriteScreenIndex].ptr; \ ++ ++#define GC_SETUP(pDrawable, pGC) \ ++ GC_SETUP_CHEAP(pDrawable) \ ++ rfbSpriteGCPtr pGCPrivate = (rfbSpriteGCPtr) \ ++ (pGC)->devPrivates[rfbSpriteGCIndex].ptr; \ ++ GCFuncs *oldFuncs = pGC->funcs; ++ ++#define GC_SETUP_AND_CHECK(pDrawable, pGC) \ ++ GC_SETUP(pDrawable, pGC); \ ++ if (GC_CHECK((WindowPtr)pDrawable)) \ ++ rfbSpriteRemoveCursor (pDrawable->pScreen); ++ ++#define GC_CHECK(pWin) \ ++ (pVNC->cursorIsDrawn && \ ++ (pScreenPriv->pCacheWin == pWin ? \ ++ pScreenPriv->isInCacheWin : ( \ ++ (pScreenPriv->pCacheWin = (pWin)) , \ ++ (pScreenPriv->isInCacheWin = \ ++ (pWin)->drawable.x < pScreenPriv->saved.x2 && \ ++ pScreenPriv->saved.x1 < (pWin)->drawable.x + \ ++ (int) (pWin)->drawable.width && \ ++ (pWin)->drawable.y < pScreenPriv->saved.y2 && \ ++ pScreenPriv->saved.y1 < (pWin)->drawable.y + \ ++ (int) (pWin)->drawable.height &&\ ++ RECT_IN_REGION((pWin)->drawable.pScreen, &(pWin)->borderClip, \ ++ &pScreenPriv->saved) != rgnOUT)))) ++ ++#define GC_OP_PROLOGUE(pGC) { \ ++ (pGC)->funcs = pGCPrivate->wrapFuncs; \ ++ (pGC)->ops = pGCPrivate->wrapOps; \ ++ } ++ ++#define GC_OP_EPILOGUE(pGC) { \ ++ pGCPrivate->wrapOps = (pGC)->ops; \ ++ (pGC)->funcs = oldFuncs; \ ++ (pGC)->ops = &rfbSpriteGCOps; \ ++ } ++ ++/* ++ * pointer-sprite method table ++ */ ++ ++static Bool rfbSpriteRealizeCursor (ScreenPtr pScreen, CursorPtr pCursor); ++static Bool rfbSpriteUnrealizeCursor (ScreenPtr pScreen, CursorPtr pCursor); ++static void rfbSpriteSetCursor (ScreenPtr pScreen, CursorPtr pCursor, int x, int y); ++static void rfbSpriteMoveCursor (ScreenPtr pScreen, int x, int y); ++ ++miPointerSpriteFuncRec rfbSpritePointerFuncs = { ++ rfbSpriteRealizeCursor, ++ rfbSpriteUnrealizeCursor, ++ rfbSpriteSetCursor, ++ rfbSpriteMoveCursor, ++}; ++ ++/* ++ * other misc functions ++ */ ++ ++static Bool rfbDisplayCursor (ScreenPtr pScreen, CursorPtr pCursor); ++ ++ ++/* ++ * rfbSpriteInitialize -- called from device-dependent screen ++ * initialization proc after all of the function pointers have ++ * been stored in the screen structure. ++ */ ++ ++Bool ++rfbSpriteInitialize (pScreen, cursorFuncs, screenFuncs) ++ ScreenPtr pScreen; ++ rfbSpriteCursorFuncPtr cursorFuncs; ++ miPointerScreenFuncPtr screenFuncs; ++{ ++ rfbSpriteScreenPtr pPriv; ++ VisualPtr pVisual; ++#ifdef RENDER ++ PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); ++#endif ++ ++ if (rfbSpriteGeneration != serverGeneration) ++ { ++ rfbSpriteScreenIndex = AllocateScreenPrivateIndex (); ++ if (rfbSpriteScreenIndex < 0) ++ return FALSE; ++ rfbSpriteGeneration = serverGeneration; ++ rfbSpriteGCIndex = AllocateGCPrivateIndex (); ++ } ++ if (!AllocateGCPrivate(pScreen, rfbSpriteGCIndex, sizeof(rfbSpriteGCRec))) ++ return FALSE; ++ pPriv = (rfbSpriteScreenPtr) xalloc (sizeof (rfbSpriteScreenRec)); ++ if (!pPriv) ++ return FALSE; ++ if (!miPointerInitialize (pScreen, &rfbSpritePointerFuncs, screenFuncs,TRUE)) ++ { ++ xfree ((pointer) pPriv); ++ return FALSE; ++ } ++ for (pVisual = pScreen->visuals; ++ pVisual->vid != pScreen->rootVisual; ++ pVisual++) ++ ; ++ pPriv->pVisual = pVisual; ++ pPriv->CloseScreen = pScreen->CloseScreen; ++ pPriv->GetImage = pScreen->GetImage; ++ pPriv->GetSpans = pScreen->GetSpans; ++ pPriv->SourceValidate = pScreen->SourceValidate; ++ pPriv->CreateGC = pScreen->CreateGC; ++#if 0 ++ pPriv->BlockHandler = pScreen->BlockHandler; ++#endif ++ pPriv->InstallColormap = pScreen->InstallColormap; ++ pPriv->StoreColors = pScreen->StoreColors; ++ pPriv->DisplayCursor = pScreen->DisplayCursor; ++ ++ pPriv->PaintWindowBackground = pScreen->PaintWindowBackground; ++ pPriv->PaintWindowBorder = pScreen->PaintWindowBorder; ++ pPriv->CopyWindow = pScreen->CopyWindow; ++ pPriv->ClearToBackground = pScreen->ClearToBackground; ++ ++ pPriv->SaveDoomedAreas = pScreen->SaveDoomedAreas; ++ pPriv->RestoreAreas = pScreen->RestoreAreas; ++#ifdef RENDER ++ if (ps) ++ { ++ pPriv->Composite = ps->Composite; ++ pPriv->Glyphs = ps->Glyphs; ++ } ++#endif ++ ++ pPriv->pCursor = NULL; ++ pPriv->x = 0; ++ pPriv->y = 0; ++ pPriv->shouldBeUp = FALSE; ++ pPriv->pCacheWin = NullWindow; ++ pPriv->isInCacheWin = FALSE; ++ pPriv->checkPixels = TRUE; ++ pPriv->pInstalledMap = NULL; ++ pPriv->pColormap = NULL; ++ pPriv->funcs = cursorFuncs; ++ pPriv->colors[SOURCE_COLOR].red = 0; ++ pPriv->colors[SOURCE_COLOR].green = 0; ++ pPriv->colors[SOURCE_COLOR].blue = 0; ++ pPriv->colors[MASK_COLOR].red = 0; ++ pPriv->colors[MASK_COLOR].green = 0; ++ pPriv->colors[MASK_COLOR].blue = 0; ++ pScreen->devPrivates[rfbSpriteScreenIndex].ptr = (pointer) pPriv; ++ pScreen->CloseScreen = rfbSpriteCloseScreen; ++ pScreen->GetImage = rfbSpriteGetImage; ++ pScreen->GetSpans = rfbSpriteGetSpans; ++ pScreen->SourceValidate = rfbSpriteSourceValidate; ++ pScreen->CreateGC = rfbSpriteCreateGC; ++#if 0 ++ pScreen->BlockHandler = rfbSpriteBlockHandler; ++#endif ++ pScreen->InstallColormap = rfbSpriteInstallColormap; ++ pScreen->StoreColors = rfbSpriteStoreColors; ++ ++ pScreen->PaintWindowBackground = rfbSpritePaintWindowBackground; ++ pScreen->PaintWindowBorder = rfbSpritePaintWindowBorder; ++ pScreen->CopyWindow = rfbSpriteCopyWindow; ++ pScreen->ClearToBackground = rfbSpriteClearToBackground; ++ ++ pScreen->SaveDoomedAreas = rfbSpriteSaveDoomedAreas; ++ pScreen->RestoreAreas = rfbSpriteRestoreAreas; ++ ++ pScreen->DisplayCursor = rfbDisplayCursor; ++#ifdef RENDER ++ if (ps) ++ { ++ ps->Composite = rfbSpriteComposite; ++ ps->Glyphs = rfbSpriteGlyphs; ++ } ++#endif ++ ++ return TRUE; ++} ++ ++/* ++ * Screen wrappers ++ */ ++ ++/* ++ * CloseScreen wrapper -- unwrap everything, free the private data ++ * and call the wrapped function ++ */ ++ ++static Bool ++rfbSpriteCloseScreen (i, pScreen) ++ ScreenPtr pScreen; ++{ ++ rfbSpriteScreenPtr pScreenPriv; ++#ifdef RENDER ++ PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); ++#endif ++ ++ pScreenPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr; ++ ++ pScreen->CloseScreen = pScreenPriv->CloseScreen; ++ pScreen->GetImage = pScreenPriv->GetImage; ++ pScreen->GetSpans = pScreenPriv->GetSpans; ++ pScreen->SourceValidate = pScreenPriv->SourceValidate; ++ pScreen->CreateGC = pScreenPriv->CreateGC; ++#if 0 ++ pScreen->BlockHandler = pScreenPriv->BlockHandler; ++#endif ++ pScreen->InstallColormap = pScreenPriv->InstallColormap; ++ pScreen->StoreColors = pScreenPriv->StoreColors; ++ ++ pScreen->PaintWindowBackground = pScreenPriv->PaintWindowBackground; ++ pScreen->PaintWindowBorder = pScreenPriv->PaintWindowBorder; ++ pScreen->CopyWindow = pScreenPriv->CopyWindow; ++ pScreen->ClearToBackground = pScreenPriv->ClearToBackground; ++ ++ pScreen->SaveDoomedAreas = pScreenPriv->SaveDoomedAreas; ++ pScreen->RestoreAreas = pScreenPriv->RestoreAreas; ++#ifdef RENDER ++ if (ps) ++ { ++ ps->Composite = pScreenPriv->Composite; ++ ps->Glyphs = pScreenPriv->Glyphs; ++ } ++#endif ++ ++ xfree ((pointer) pScreenPriv); ++ ++ return (*pScreen->CloseScreen) (i, pScreen); ++} ++ ++static void ++rfbSpriteGetImage (pDrawable, sx, sy, w, h, format, planemask, pdstLine) ++ DrawablePtr pDrawable; ++ int sx, sy, w, h; ++ unsigned int format; ++ unsigned long planemask; ++ char *pdstLine; ++{ ++ ScreenPtr pScreen = pDrawable->pScreen; ++ rfbSpriteScreenPtr pScreenPriv; ++ VNCSCREENPTR(pScreen); ++ ++ SCREEN_PROLOGUE (pScreen, GetImage); ++ ++ pScreenPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr; ++ ++ if (pDrawable->type == DRAWABLE_WINDOW && ++ pVNC->cursorIsDrawn && ++ ORG_OVERLAP(&pScreenPriv->saved,pDrawable->x,pDrawable->y, sx, sy, w, h)) ++ { ++ rfbSpriteRemoveCursor (pScreen); ++ } ++ ++ (*pScreen->GetImage) (pDrawable, sx, sy, w, h, ++ format, planemask, pdstLine); ++ ++ SCREEN_EPILOGUE (pScreen, GetImage, rfbSpriteGetImage); ++} ++ ++static void ++rfbSpriteGetSpans (pDrawable, wMax, ppt, pwidth, nspans, pdstStart) ++ DrawablePtr pDrawable; ++ int wMax; ++ DDXPointPtr ppt; ++ int *pwidth; ++ int nspans; ++ char *pdstStart; ++{ ++ ScreenPtr pScreen = pDrawable->pScreen; ++ rfbSpriteScreenPtr pScreenPriv; ++ VNCSCREENPTR(pScreen); ++ ++ SCREEN_PROLOGUE (pScreen, GetSpans); ++ ++ pScreenPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr; ++ ++ if (pDrawable->type == DRAWABLE_WINDOW && pVNC->cursorIsDrawn) ++ { ++ register DDXPointPtr pts; ++ register int *widths; ++ register int nPts; ++ register int xorg, ++ yorg; ++ ++ xorg = pDrawable->x; ++ yorg = pDrawable->y; ++ ++ for (pts = ppt, widths = pwidth, nPts = nspans; ++ nPts--; ++ pts++, widths++) ++ { ++ if (SPN_OVERLAP(&pScreenPriv->saved,pts->y+yorg, ++ pts->x+xorg,*widths)) ++ { ++ rfbSpriteRemoveCursor (pScreen); ++ break; ++ } ++ } ++ } ++ ++ (*pScreen->GetSpans) (pDrawable, wMax, ppt, pwidth, nspans, pdstStart); ++ ++ SCREEN_EPILOGUE (pScreen, GetSpans, rfbSpriteGetSpans); ++} ++ ++static void ++rfbSpriteSourceValidate (pDrawable, x, y, width, height) ++ DrawablePtr pDrawable; ++ int x, y, width, height; ++{ ++ ScreenPtr pScreen = pDrawable->pScreen; ++ rfbSpriteScreenPtr pScreenPriv; ++ VNCSCREENPTR(pScreen); ++ ++ SCREEN_PROLOGUE (pScreen, SourceValidate); ++ ++ pScreenPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr; ++ ++ if (pDrawable->type == DRAWABLE_WINDOW && pVNC->cursorIsDrawn && ++ ORG_OVERLAP(&pScreenPriv->saved, pDrawable->x, pDrawable->y, ++ x, y, width, height)) ++ { ++ rfbSpriteRemoveCursor (pScreen); ++ } ++ ++ if (pScreen->SourceValidate) ++ (*pScreen->SourceValidate) (pDrawable, x, y, width, height); ++ ++ SCREEN_EPILOGUE (pScreen, SourceValidate, rfbSpriteSourceValidate); ++} ++ ++static Bool ++rfbSpriteCreateGC (pGC) ++ GCPtr pGC; ++{ ++ ScreenPtr pScreen = pGC->pScreen; ++ Bool ret; ++ rfbSpriteGCPtr pPriv; ++ ++ SCREEN_PROLOGUE (pScreen, CreateGC); ++ ++ pPriv = (rfbSpriteGCPtr)pGC->devPrivates[rfbSpriteGCIndex].ptr; ++ ++ ret = (*pScreen->CreateGC) (pGC); ++ ++ pPriv->wrapOps = NULL; ++ pPriv->wrapFuncs = pGC->funcs; ++ pGC->funcs = &rfbSpriteGCFuncs; ++ ++ SCREEN_EPILOGUE (pScreen, CreateGC, rfbSpriteCreateGC); ++ ++ return ret; ++} ++ ++static void ++rfbSpriteBlockHandler (i, blockData, pTimeout, pReadmask) ++ int i; ++ pointer blockData; ++ pointer pTimeout; ++ pointer pReadmask; ++{ ++ ScreenPtr pScreen = screenInfo.screens[i]; ++ rfbSpriteScreenPtr pPriv; ++ VNCSCREENPTR(pScreen); ++ ++ pPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr; ++ ++ SCREEN_PROLOGUE(pScreen, BlockHandler); ++ ++ (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask); ++ ++ SCREEN_EPILOGUE(pScreen, BlockHandler, rfbSpriteBlockHandler); ++ ++ if (!pVNC->cursorIsDrawn && pPriv->shouldBeUp) ++ rfbSpriteRestoreCursor (pScreen); ++} ++ ++static void ++rfbSpriteInstallColormap (pMap) ++ ColormapPtr pMap; ++{ ++ ScreenPtr pScreen = pMap->pScreen; ++ rfbSpriteScreenPtr pPriv; ++ VNCSCREENPTR(pScreen); ++ ++ pPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr; ++ ++ SCREEN_PROLOGUE(pScreen, InstallColormap); ++ ++ (*pScreen->InstallColormap) (pMap); ++ ++ SCREEN_EPILOGUE(pScreen, InstallColormap, rfbSpriteInstallColormap); ++ ++ pPriv->pInstalledMap = pMap; ++ if (pPriv->pColormap != pMap) ++ { ++ pPriv->checkPixels = TRUE; ++ if (pVNC->cursorIsDrawn) ++ rfbSpriteRemoveCursor (pScreen); ++ } ++} ++ ++static void ++rfbSpriteStoreColors (pMap, ndef, pdef) ++ ColormapPtr pMap; ++ int ndef; ++ xColorItem *pdef; ++{ ++ ScreenPtr pScreen = pMap->pScreen; ++ rfbSpriteScreenPtr pPriv; ++ int i; ++ int updated; ++ VisualPtr pVisual; ++ VNCSCREENPTR(pScreen); ++ ++ pPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr; ++ ++ SCREEN_PROLOGUE(pScreen, StoreColors); ++ ++ (*pScreen->StoreColors) (pMap, ndef, pdef); ++ ++ SCREEN_EPILOGUE(pScreen, StoreColors, rfbSpriteStoreColors); ++ ++ if (pPriv->pColormap == pMap) ++ { ++ updated = 0; ++ pVisual = pMap->pVisual; ++ if (pVisual->class == DirectColor) ++ { ++ /* Direct color - match on any of the subfields */ ++ ++#define MaskMatch(a,b,mask) ((a) & ((pVisual->mask) == (b)) & (pVisual->mask)) ++ ++#define UpdateDAC(plane,dac,mask) {\ ++ if (MaskMatch (pPriv->colors[plane].pixel,pdef[i].pixel,mask)) {\ ++ pPriv->colors[plane].dac = pdef[i].dac; \ ++ updated = 1; \ ++ } \ ++} ++ ++#define CheckDirect(plane) \ ++ UpdateDAC(plane,red,redMask) \ ++ UpdateDAC(plane,green,greenMask) \ ++ UpdateDAC(plane,blue,blueMask) ++ ++ for (i = 0; i < ndef; i++) ++ { ++ CheckDirect (SOURCE_COLOR) ++ CheckDirect (MASK_COLOR) ++ } ++ } ++ else ++ { ++ /* PseudoColor/GrayScale - match on exact pixel */ ++ for (i = 0; i < ndef; i++) ++ { ++ if (pdef[i].pixel == pPriv->colors[SOURCE_COLOR].pixel) ++ { ++ pPriv->colors[SOURCE_COLOR] = pdef[i]; ++ if (++updated == 2) ++ break; ++ } ++ if (pdef[i].pixel == pPriv->colors[MASK_COLOR].pixel) ++ { ++ pPriv->colors[MASK_COLOR] = pdef[i]; ++ if (++updated == 2) ++ break; ++ } ++ } ++ } ++ if (updated) ++ { ++ pPriv->checkPixels = TRUE; ++ if (pVNC->cursorIsDrawn) ++ rfbSpriteRemoveCursor (pScreen); ++ } ++ } ++} ++ ++static void ++rfbSpriteFindColors (ScreenPtr pScreen) ++{ ++ rfbSpriteScreenPtr pScreenPriv = (rfbSpriteScreenPtr) ++ pScreen->devPrivates[rfbSpriteScreenIndex].ptr; ++ CursorPtr pCursor; ++ xColorItem *sourceColor, *maskColor; ++ ++ pCursor = pScreenPriv->pCursor; ++ sourceColor = &pScreenPriv->colors[SOURCE_COLOR]; ++ maskColor = &pScreenPriv->colors[MASK_COLOR]; ++ if (pScreenPriv->pColormap != pScreenPriv->pInstalledMap || ++ !(pCursor->foreRed == sourceColor->red && ++ pCursor->foreGreen == sourceColor->green && ++ pCursor->foreBlue == sourceColor->blue && ++ pCursor->backRed == maskColor->red && ++ pCursor->backGreen == maskColor->green && ++ pCursor->backBlue == maskColor->blue)) ++ { ++ pScreenPriv->pColormap = pScreenPriv->pInstalledMap; ++ sourceColor->red = pCursor->foreRed; ++ sourceColor->green = pCursor->foreGreen; ++ sourceColor->blue = pCursor->foreBlue; ++ FakeAllocColor (pScreenPriv->pColormap, sourceColor); ++ maskColor->red = pCursor->backRed; ++ maskColor->green = pCursor->backGreen; ++ maskColor->blue = pCursor->backBlue; ++ FakeAllocColor (pScreenPriv->pColormap, maskColor); ++ /* "free" the pixels right away, don't let this confuse you */ ++ FakeFreeColor(pScreenPriv->pColormap, sourceColor->pixel); ++ FakeFreeColor(pScreenPriv->pColormap, maskColor->pixel); ++ } ++ pScreenPriv->checkPixels = FALSE; ++} ++ ++/* ++ * BackingStore wrappers ++ */ ++ ++static void ++rfbSpriteSaveDoomedAreas (pWin, pObscured, dx, dy) ++ WindowPtr pWin; ++ RegionPtr pObscured; ++ int dx, dy; ++{ ++ ScreenPtr pScreen = pWin->drawable.pScreen; ++ rfbSpriteScreenPtr pScreenPriv; ++ BoxRec cursorBox; ++ VNCSCREENPTR(pScreen); ++ ++ SCREEN_PROLOGUE (pScreen, SaveDoomedAreas); ++ ++ pScreenPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr; ++ if (pVNC->cursorIsDrawn) ++ { ++ cursorBox = pScreenPriv->saved; ++ ++ if (dx || dy) ++ { ++ cursorBox.x1 += dx; ++ cursorBox.y1 += dy; ++ cursorBox.x2 += dx; ++ cursorBox.y2 += dy; ++ } ++ if (RECT_IN_REGION( pScreen, pObscured, &cursorBox) != rgnOUT) ++ rfbSpriteRemoveCursor (pScreen); ++ } ++ ++ (*pScreen->SaveDoomedAreas) (pWin, pObscured, dx, dy); ++ ++ SCREEN_EPILOGUE (pScreen, SaveDoomedAreas, rfbSpriteSaveDoomedAreas); ++} ++ ++static RegionPtr ++rfbSpriteRestoreAreas (pWin, prgnExposed) ++ WindowPtr pWin; ++ RegionPtr prgnExposed; ++{ ++ ScreenPtr pScreen = pWin->drawable.pScreen; ++ rfbSpriteScreenPtr pScreenPriv; ++ RegionPtr result; ++ VNCSCREENPTR(pScreen); ++ ++ SCREEN_PROLOGUE (pScreen, RestoreAreas); ++ ++ pScreenPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr; ++ if (pVNC->cursorIsDrawn) ++ { ++ if (RECT_IN_REGION( pScreen, prgnExposed, &pScreenPriv->saved) != rgnOUT) ++ rfbSpriteRemoveCursor (pScreen); ++ } ++ ++ result = (*pScreen->RestoreAreas) (pWin, prgnExposed); ++ ++ SCREEN_EPILOGUE (pScreen, RestoreAreas, rfbSpriteRestoreAreas); ++ ++ return result; ++} ++ ++/* ++ * Window wrappers ++ */ ++ ++static void ++rfbSpritePaintWindowBackground (pWin, pRegion, what) ++ WindowPtr pWin; ++ RegionPtr pRegion; ++ int what; ++{ ++ ScreenPtr pScreen = pWin->drawable.pScreen; ++ rfbSpriteScreenPtr pScreenPriv; ++ VNCSCREENPTR(pScreen); ++ ++ SCREEN_PROLOGUE (pScreen, PaintWindowBackground); ++ ++ pScreenPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr; ++ if (pVNC->cursorIsDrawn) ++ { ++ /* ++ * If the cursor is on the same screen as the window, check the ++ * region to paint for the cursor and remove it as necessary ++ */ ++ if (RECT_IN_REGION( pScreen, pRegion, &pScreenPriv->saved) != rgnOUT) ++ rfbSpriteRemoveCursor (pScreen); ++ } ++ ++ (*pScreen->PaintWindowBackground) (pWin, pRegion, what); ++ ++ SCREEN_EPILOGUE (pScreen, PaintWindowBackground, rfbSpritePaintWindowBackground); ++} ++ ++static void ++rfbSpritePaintWindowBorder (pWin, pRegion, what) ++ WindowPtr pWin; ++ RegionPtr pRegion; ++ int what; ++{ ++ ScreenPtr pScreen = pWin->drawable.pScreen; ++ rfbSpriteScreenPtr pScreenPriv; ++ VNCSCREENPTR(pScreen); ++ ++ SCREEN_PROLOGUE (pScreen, PaintWindowBorder); ++ ++ pScreenPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr; ++ if (pVNC->cursorIsDrawn) ++ { ++ /* ++ * If the cursor is on the same screen as the window, check the ++ * region to paint for the cursor and remove it as necessary ++ */ ++ if (RECT_IN_REGION( pScreen, pRegion, &pScreenPriv->saved) != rgnOUT) ++ rfbSpriteRemoveCursor (pScreen); ++ } ++ ++ (*pScreen->PaintWindowBorder) (pWin, pRegion, what); ++ ++ SCREEN_EPILOGUE (pScreen, PaintWindowBorder, rfbSpritePaintWindowBorder); ++} ++ ++static void ++rfbSpriteCopyWindow (pWin, ptOldOrg, pRegion) ++ WindowPtr pWin; ++ DDXPointRec ptOldOrg; ++ RegionPtr pRegion; ++{ ++ ScreenPtr pScreen = pWin->drawable.pScreen; ++ rfbSpriteScreenPtr pScreenPriv; ++ BoxRec cursorBox; ++ int dx, dy; ++ VNCSCREENPTR(pScreen); ++ ++ SCREEN_PROLOGUE (pScreen, CopyWindow); ++ ++ pScreenPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr; ++ if (pVNC->cursorIsDrawn) ++ { ++ /* ++ * check both the source and the destination areas. The given ++ * region is source relative, so offset the cursor box by ++ * the delta position ++ */ ++ cursorBox = pScreenPriv->saved; ++ dx = pWin->drawable.x - ptOldOrg.x; ++ dy = pWin->drawable.y - ptOldOrg.y; ++ cursorBox.x1 -= dx; ++ cursorBox.x2 -= dx; ++ cursorBox.y1 -= dy; ++ cursorBox.y2 -= dy; ++ if (RECT_IN_REGION( pScreen, pRegion, &pScreenPriv->saved) != rgnOUT || ++ RECT_IN_REGION( pScreen, pRegion, &cursorBox) != rgnOUT) ++ rfbSpriteRemoveCursor (pScreen); ++ } ++ ++ (*pScreen->CopyWindow) (pWin, ptOldOrg, pRegion); ++ ++ SCREEN_EPILOGUE (pScreen, CopyWindow, rfbSpriteCopyWindow); ++} ++ ++static void ++rfbSpriteClearToBackground (pWin, x, y, w, h, generateExposures) ++ WindowPtr pWin; ++ short x,y; ++ unsigned short w,h; ++ Bool generateExposures; ++{ ++ ScreenPtr pScreen = pWin->drawable.pScreen; ++ rfbSpriteScreenPtr pScreenPriv; ++ int realw, realh; ++ VNCSCREENPTR(pScreen); ++ ++ SCREEN_PROLOGUE (pScreen, ClearToBackground); ++ ++ pScreenPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr; ++ if (GC_CHECK(pWin)) ++ { ++ if (!(realw = w)) ++ realw = (int) pWin->drawable.width - x; ++ if (!(realh = h)) ++ realh = (int) pWin->drawable.height - y; ++ if (ORG_OVERLAP(&pScreenPriv->saved, pWin->drawable.x, pWin->drawable.y, ++ x, y, realw, realh)) ++ { ++ rfbSpriteRemoveCursor (pScreen); ++ } ++ } ++ ++ (*pScreen->ClearToBackground) (pWin, x, y, w, h, generateExposures); ++ ++ SCREEN_EPILOGUE (pScreen, ClearToBackground, rfbSpriteClearToBackground); ++} ++ ++/* ++ * GC Func wrappers ++ */ ++ ++static void ++rfbSpriteValidateGC (pGC, changes, pDrawable) ++ GCPtr pGC; ++ unsigned long changes; ++ DrawablePtr pDrawable; ++{ ++ GC_FUNC_PROLOGUE (pGC); ++ ++ (*pGC->funcs->ValidateGC) (pGC, changes, pDrawable); ++ ++ pGCPriv->wrapOps = NULL; ++ if (pDrawable->type == DRAWABLE_WINDOW && ((WindowPtr) pDrawable)->viewable) ++ { ++ WindowPtr pWin; ++ RegionPtr pRegion; ++ ++ pWin = (WindowPtr) pDrawable; ++ pRegion = &pWin->clipList; ++ if (pGC->subWindowMode == IncludeInferiors) ++ pRegion = &pWin->borderClip; ++ if (REGION_NOTEMPTY(pDrawable->pScreen, pRegion)) ++ pGCPriv->wrapOps = pGC->ops; ++ } ++ ++ GC_FUNC_EPILOGUE (pGC); ++} ++ ++static void ++rfbSpriteChangeGC (pGC, mask) ++ GCPtr pGC; ++ unsigned long mask; ++{ ++ GC_FUNC_PROLOGUE (pGC); ++ ++ (*pGC->funcs->ChangeGC) (pGC, mask); ++ ++ GC_FUNC_EPILOGUE (pGC); ++} ++ ++static void ++rfbSpriteCopyGC (pGCSrc, mask, pGCDst) ++ GCPtr pGCSrc, pGCDst; ++ unsigned long mask; ++{ ++ GC_FUNC_PROLOGUE (pGCDst); ++ ++ (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst); ++ ++ GC_FUNC_EPILOGUE (pGCDst); ++} ++ ++static void ++rfbSpriteDestroyGC (pGC) ++ GCPtr pGC; ++{ ++ GC_FUNC_PROLOGUE (pGC); ++ ++ (*pGC->funcs->DestroyGC) (pGC); ++ ++ GC_FUNC_EPILOGUE (pGC); ++} ++ ++static void ++rfbSpriteChangeClip (pGC, type, pvalue, nrects) ++ GCPtr pGC; ++ int type; ++ pointer pvalue; ++ int nrects; ++{ ++ GC_FUNC_PROLOGUE (pGC); ++ ++ (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects); ++ ++ GC_FUNC_EPILOGUE (pGC); ++} ++ ++static void ++rfbSpriteCopyClip(pgcDst, pgcSrc) ++ GCPtr pgcDst, pgcSrc; ++{ ++ GC_FUNC_PROLOGUE (pgcDst); ++ ++ (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc); ++ ++ GC_FUNC_EPILOGUE (pgcDst); ++} ++ ++static void ++rfbSpriteDestroyClip(pGC) ++ GCPtr pGC; ++{ ++ GC_FUNC_PROLOGUE (pGC); ++ ++ (* pGC->funcs->DestroyClip)(pGC); ++ ++ GC_FUNC_EPILOGUE (pGC); ++} ++ ++/* ++ * GC Op wrappers ++ */ ++ ++static void ++rfbSpriteFillSpans(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted) ++ DrawablePtr pDrawable; ++ GCPtr pGC; ++ int nInit; /* number of spans to fill */ ++ DDXPointPtr pptInit; /* pointer to list of start points */ ++ int *pwidthInit; /* pointer to list of n widths */ ++ int fSorted; ++{ ++ VNCSCREENPTR(pDrawable->pScreen); ++ ++ GC_SETUP(pDrawable, pGC); ++ ++ if (GC_CHECK((WindowPtr) pDrawable)) ++ { ++ register DDXPointPtr pts; ++ register int *widths; ++ register int nPts; ++ ++ for (pts = pptInit, widths = pwidthInit, nPts = nInit; ++ nPts--; ++ pts++, widths++) ++ { ++ if (SPN_OVERLAP(&pScreenPriv->saved,pts->y,pts->x,*widths)) ++ { ++ rfbSpriteRemoveCursor (pDrawable->pScreen); ++ break; ++ } ++ } ++ } ++ ++ GC_OP_PROLOGUE (pGC); ++ ++ (*pGC->ops->FillSpans) (pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted); ++ ++ GC_OP_EPILOGUE (pGC); ++} ++ ++static void ++rfbSpriteSetSpans(pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted) ++ DrawablePtr pDrawable; ++ GCPtr pGC; ++ char *psrc; ++ register DDXPointPtr ppt; ++ int *pwidth; ++ int nspans; ++ int fSorted; ++{ ++ VNCSCREENPTR(pDrawable->pScreen); ++ ++ GC_SETUP(pDrawable, pGC); ++ ++ if (GC_CHECK((WindowPtr) pDrawable)) ++ { ++ register DDXPointPtr pts; ++ register int *widths; ++ register int nPts; ++ ++ for (pts = ppt, widths = pwidth, nPts = nspans; ++ nPts--; ++ pts++, widths++) ++ { ++ if (SPN_OVERLAP(&pScreenPriv->saved,pts->y,pts->x,*widths)) ++ { ++ rfbSpriteRemoveCursor(pDrawable->pScreen); ++ break; ++ } ++ } ++ } ++ ++ GC_OP_PROLOGUE (pGC); ++ ++ (*pGC->ops->SetSpans) (pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted); ++ ++ GC_OP_EPILOGUE (pGC); ++} ++ ++static void ++rfbSpritePutImage(pDrawable, pGC, depth, x, y, w, h, leftPad, format, pBits) ++ DrawablePtr pDrawable; ++ GCPtr pGC; ++ int depth; ++ int x; ++ int y; ++ int w; ++ int h; ++ int format; ++ char *pBits; ++{ ++ VNCSCREENPTR(pDrawable->pScreen); ++ ++ GC_SETUP(pDrawable, pGC); ++ ++ if (GC_CHECK((WindowPtr) pDrawable)) ++ { ++ if (ORG_OVERLAP(&pScreenPriv->saved,pDrawable->x,pDrawable->y, ++ x,y,w,h)) ++ { ++ rfbSpriteRemoveCursor (pDrawable->pScreen); ++ } ++ } ++ ++ GC_OP_PROLOGUE (pGC); ++ ++ (*pGC->ops->PutImage) (pDrawable, pGC, depth, x, y, w, h, leftPad, format, pBits); ++ ++ GC_OP_EPILOGUE (pGC); ++} ++ ++static RegionPtr ++rfbSpriteCopyArea (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty) ++ DrawablePtr pSrc; ++ DrawablePtr pDst; ++ GCPtr pGC; ++ int srcx; ++ int srcy; ++ int w; ++ int h; ++ int dstx; ++ int dsty; ++{ ++ RegionPtr rgn; ++ VNCSCREENPTR(pGC->pScreen); ++ ++ GC_SETUP(pDst, pGC); ++ ++ /* check destination/source overlap. */ ++ if (GC_CHECK((WindowPtr) pDst) && ++ (ORG_OVERLAP(&pScreenPriv->saved,pDst->x,pDst->y,dstx,dsty,w,h) || ++ ((pDst == pSrc) && ++ ORG_OVERLAP(&pScreenPriv->saved,pSrc->x,pSrc->y,srcx,srcy,w,h)))) ++ { ++ rfbSpriteRemoveCursor (pDst->pScreen); ++ } ++ ++ GC_OP_PROLOGUE (pGC); ++ ++ rgn = (*pGC->ops->CopyArea) (pSrc, pDst, pGC, srcx, srcy, w, h, ++ dstx, dsty); ++ ++ GC_OP_EPILOGUE (pGC); ++ ++ return rgn; ++} ++ ++static RegionPtr ++rfbSpriteCopyPlane (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty, plane) ++ DrawablePtr pSrc; ++ DrawablePtr pDst; ++ register GCPtr pGC; ++ int srcx, ++ srcy; ++ int w, ++ h; ++ int dstx, ++ dsty; ++ unsigned long plane; ++{ ++ RegionPtr rgn; ++ VNCSCREENPTR(pGC->pScreen); ++ ++ GC_SETUP(pDst, pGC); ++ ++ /* ++ * check destination/source for overlap. ++ */ ++ if (GC_CHECK((WindowPtr) pDst) && ++ (ORG_OVERLAP(&pScreenPriv->saved,pDst->x,pDst->y,dstx,dsty,w,h) || ++ ((pDst == pSrc) && ++ ORG_OVERLAP(&pScreenPriv->saved,pSrc->x,pSrc->y,srcx,srcy,w,h)))) ++ { ++ rfbSpriteRemoveCursor (pDst->pScreen); ++ } ++ ++ GC_OP_PROLOGUE (pGC); ++ ++ rgn = (*pGC->ops->CopyPlane) (pSrc, pDst, pGC, srcx, srcy, w, h, ++ dstx, dsty, plane); ++ ++ GC_OP_EPILOGUE (pGC); ++ ++ return rgn; ++} ++ ++static void ++rfbSpritePolyPoint (pDrawable, pGC, mode, npt, pptInit) ++ DrawablePtr pDrawable; ++ GCPtr pGC; ++ int mode; /* Origin or Previous */ ++ int npt; ++ xPoint *pptInit; ++{ ++ xPoint t; ++ int n; ++ BoxRec cursor; ++ register xPoint *pts; ++ VNCSCREENPTR(pDrawable->pScreen); ++ ++ GC_SETUP (pDrawable, pGC); ++ ++ if (npt && GC_CHECK((WindowPtr) pDrawable)) ++ { ++ cursor.x1 = pScreenPriv->saved.x1 - pDrawable->x; ++ cursor.y1 = pScreenPriv->saved.y1 - pDrawable->y; ++ cursor.x2 = pScreenPriv->saved.x2 - pDrawable->x; ++ cursor.y2 = pScreenPriv->saved.y2 - pDrawable->y; ++ ++ if (mode == CoordModePrevious) ++ { ++ t.x = 0; ++ t.y = 0; ++ for (pts = pptInit, n = npt; n--; pts++) ++ { ++ t.x += pts->x; ++ t.y += pts->y; ++ if (cursor.x1 <= t.x && t.x <= cursor.x2 && ++ cursor.y1 <= t.y && t.y <= cursor.y2) ++ { ++ rfbSpriteRemoveCursor (pDrawable->pScreen); ++ break; ++ } ++ } ++ } ++ else ++ { ++ for (pts = pptInit, n = npt; n--; pts++) ++ { ++ if (cursor.x1 <= pts->x && pts->x <= cursor.x2 && ++ cursor.y1 <= pts->y && pts->y <= cursor.y2) ++ { ++ rfbSpriteRemoveCursor (pDrawable->pScreen); ++ break; ++ } ++ } ++ } ++ } ++ ++ GC_OP_PROLOGUE (pGC); ++ ++ (*pGC->ops->PolyPoint) (pDrawable, pGC, mode, npt, pptInit); ++ ++ GC_OP_EPILOGUE (pGC); ++} ++ ++static void ++rfbSpritePolylines (pDrawable, pGC, mode, npt, pptInit) ++ DrawablePtr pDrawable; ++ GCPtr pGC; ++ int mode; ++ int npt; ++ DDXPointPtr pptInit; ++{ ++ BoxPtr cursor; ++ register DDXPointPtr pts; ++ int n; ++ int x, y, x1, y1, x2, y2; ++ int lw; ++ int extra; ++ VNCSCREENPTR(pDrawable->pScreen); ++ ++ GC_SETUP (pDrawable, pGC); ++ ++ if (npt && GC_CHECK((WindowPtr) pDrawable)) ++ { ++ cursor = &pScreenPriv->saved; ++ lw = pGC->lineWidth; ++ x = pptInit->x + pDrawable->x; ++ y = pptInit->y + pDrawable->y; ++ ++ if (npt == 1) ++ { ++ extra = lw >> 1; ++ if (LINE_OVERLAP(cursor, x, y, x, y, extra)) ++ rfbSpriteRemoveCursor (pDrawable->pScreen); ++ } ++ else ++ { ++ extra = lw >> 1; ++ /* ++ * mitered joins can project quite a way from ++ * the line end; the 11 degree miter limit limits ++ * this extension to 10.43 * lw / 2, rounded up ++ * and converted to int yields 6 * lw ++ */ ++ if (pGC->joinStyle == JoinMiter) ++ extra = 6 * lw; ++ else if (pGC->capStyle == CapProjecting) ++ extra = lw; ++ for (pts = pptInit + 1, n = npt - 1; n--; pts++) ++ { ++ x1 = x; ++ y1 = y; ++ if (mode == CoordModeOrigin) ++ { ++ x2 = pDrawable->x + pts->x; ++ y2 = pDrawable->y + pts->y; ++ } ++ else ++ { ++ x2 = x + pts->x; ++ y2 = y + pts->y; ++ } ++ x = x2; ++ y = y2; ++ LINE_SORT(x1, y1, x2, y2); ++ if (LINE_OVERLAP(cursor, x1, y1, x2, y2, extra)) ++ { ++ rfbSpriteRemoveCursor (pDrawable->pScreen); ++ break; ++ } ++ } ++ } ++ } ++ GC_OP_PROLOGUE (pGC); ++ ++ (*pGC->ops->Polylines) (pDrawable, pGC, mode, npt, pptInit); ++ ++ GC_OP_EPILOGUE (pGC); ++} ++ ++static void ++rfbSpritePolySegment(pDrawable, pGC, nseg, pSegs) ++ DrawablePtr pDrawable; ++ GCPtr pGC; ++ int nseg; ++ xSegment *pSegs; ++{ ++ int n; ++ register xSegment *segs; ++ BoxPtr cursor; ++ int x1, y1, x2, y2; ++ int extra; ++ VNCSCREENPTR(pDrawable->pScreen); ++ ++ GC_SETUP(pDrawable, pGC); ++ ++ if (nseg && GC_CHECK((WindowPtr) pDrawable)) ++ { ++ cursor = &pScreenPriv->saved; ++ extra = pGC->lineWidth >> 1; ++ if (pGC->capStyle == CapProjecting) ++ extra = pGC->lineWidth; ++ for (segs = pSegs, n = nseg; n--; segs++) ++ { ++ x1 = segs->x1 + pDrawable->x; ++ y1 = segs->y1 + pDrawable->y; ++ x2 = segs->x2 + pDrawable->x; ++ y2 = segs->y2 + pDrawable->y; ++ LINE_SORT(x1, y1, x2, y2); ++ if (LINE_OVERLAP(cursor, x1, y1, x2, y2, extra)) ++ { ++ rfbSpriteRemoveCursor (pDrawable->pScreen); ++ break; ++ } ++ } ++ } ++ ++ GC_OP_PROLOGUE (pGC); ++ ++ (*pGC->ops->PolySegment) (pDrawable, pGC, nseg, pSegs); ++ ++ GC_OP_EPILOGUE (pGC); ++} ++ ++static void ++rfbSpritePolyRectangle(pDrawable, pGC, nrects, pRects) ++ DrawablePtr pDrawable; ++ GCPtr pGC; ++ int nrects; ++ xRectangle *pRects; ++{ ++ register xRectangle *rects; ++ BoxPtr cursor; ++ int lw; ++ int n; ++ int x1, y1, x2, y2; ++ VNCSCREENPTR(pDrawable->pScreen); ++ ++ GC_SETUP (pDrawable, pGC); ++ ++ if (GC_CHECK((WindowPtr) pDrawable)) ++ { ++ lw = pGC->lineWidth >> 1; ++ cursor = &pScreenPriv->saved; ++ for (rects = pRects, n = nrects; n--; rects++) ++ { ++ x1 = rects->x + pDrawable->x; ++ y1 = rects->y + pDrawable->y; ++ x2 = x1 + (int)rects->width; ++ y2 = y1 + (int)rects->height; ++ if (LINE_OVERLAP(cursor, x1, y1, x2, y1, lw) || ++ LINE_OVERLAP(cursor, x2, y1, x2, y2, lw) || ++ LINE_OVERLAP(cursor, x1, y2, x2, y2, lw) || ++ LINE_OVERLAP(cursor, x1, y1, x1, y2, lw)) ++ { ++ rfbSpriteRemoveCursor (pDrawable->pScreen); ++ break; ++ } ++ } ++ } ++ ++ GC_OP_PROLOGUE (pGC); ++ ++ (*pGC->ops->PolyRectangle) (pDrawable, pGC, nrects, pRects); ++ ++ GC_OP_EPILOGUE (pGC); ++} ++ ++static void ++rfbSpritePolyArc(pDrawable, pGC, narcs, parcs) ++ DrawablePtr pDrawable; ++ register GCPtr pGC; ++ int narcs; ++ xArc *parcs; ++{ ++ BoxPtr cursor; ++ int lw; ++ int n; ++ register xArc *arcs; ++ VNCSCREENPTR(pDrawable->pScreen); ++ ++ GC_SETUP (pDrawable, pGC); ++ ++ if (GC_CHECK((WindowPtr) pDrawable)) ++ { ++ lw = pGC->lineWidth >> 1; ++ cursor = &pScreenPriv->saved; ++ for (arcs = parcs, n = narcs; n--; arcs++) ++ { ++ if (ORG_OVERLAP (cursor, pDrawable->x, pDrawable->y, ++ arcs->x - lw, arcs->y - lw, ++ (int) arcs->width + pGC->lineWidth, ++ (int) arcs->height + pGC->lineWidth)) ++ { ++ rfbSpriteRemoveCursor (pDrawable->pScreen); ++ break; ++ } ++ } ++ } ++ ++ GC_OP_PROLOGUE (pGC); ++ ++ (*pGC->ops->PolyArc) (pDrawable, pGC, narcs, parcs); ++ ++ GC_OP_EPILOGUE (pGC); ++} ++ ++static void ++rfbSpriteFillPolygon(pDrawable, pGC, shape, mode, count, pPts) ++ register DrawablePtr pDrawable; ++ register GCPtr pGC; ++ int shape, mode; ++ int count; ++ DDXPointPtr pPts; ++{ ++ int x, y, minx, miny, maxx, maxy; ++ register DDXPointPtr pts; ++ int n; ++ VNCSCREENPTR(pDrawable->pScreen); ++ ++ GC_SETUP (pDrawable, pGC); ++ ++ if (count && GC_CHECK((WindowPtr) pDrawable)) ++ { ++ x = pDrawable->x; ++ y = pDrawable->y; ++ pts = pPts; ++ minx = maxx = pts->x; ++ miny = maxy = pts->y; ++ pts++; ++ n = count - 1; ++ ++ if (mode == CoordModeOrigin) ++ { ++ for (; n--; pts++) ++ { ++ if (pts->x < minx) ++ minx = pts->x; ++ else if (pts->x > maxx) ++ maxx = pts->x; ++ if (pts->y < miny) ++ miny = pts->y; ++ else if (pts->y > maxy) ++ maxy = pts->y; ++ } ++ minx += x; ++ miny += y; ++ maxx += x; ++ maxy += y; ++ } ++ else ++ { ++ x += minx; ++ y += miny; ++ minx = maxx = x; ++ miny = maxy = y; ++ for (; n--; pts++) ++ { ++ x += pts->x; ++ y += pts->y; ++ if (x < minx) ++ minx = x; ++ else if (x > maxx) ++ maxx = x; ++ if (y < miny) ++ miny = y; ++ else if (y > maxy) ++ maxy = y; ++ } ++ } ++ if (BOX_OVERLAP(&pScreenPriv->saved,minx,miny,maxx,maxy)) ++ rfbSpriteRemoveCursor (pDrawable->pScreen); ++ } ++ ++ GC_OP_PROLOGUE (pGC); ++ ++ (*pGC->ops->FillPolygon) (pDrawable, pGC, shape, mode, count, pPts); ++ ++ GC_OP_EPILOGUE (pGC); ++} ++ ++static void ++rfbSpritePolyFillRect(pDrawable, pGC, nrectFill, prectInit) ++ DrawablePtr pDrawable; ++ GCPtr pGC; ++ int nrectFill; /* number of rectangles to fill */ ++ xRectangle *prectInit; /* Pointer to first rectangle to fill */ ++{ ++ VNCSCREENPTR(pDrawable->pScreen); ++ ++ GC_SETUP(pDrawable, pGC); ++ ++ if (GC_CHECK((WindowPtr) pDrawable)) ++ { ++ register int nRect; ++ register xRectangle *pRect; ++ register int xorg, yorg; ++ ++ xorg = pDrawable->x; ++ yorg = pDrawable->y; ++ ++ for (nRect = nrectFill, pRect = prectInit; nRect--; pRect++) { ++ if (ORGRECT_OVERLAP(&pScreenPriv->saved,xorg,yorg,pRect)){ ++ rfbSpriteRemoveCursor(pDrawable->pScreen); ++ break; ++ } ++ } ++ } ++ ++ GC_OP_PROLOGUE (pGC); ++ ++ (*pGC->ops->PolyFillRect) (pDrawable, pGC, nrectFill, prectInit); ++ ++ GC_OP_EPILOGUE (pGC); ++} ++ ++static void ++rfbSpritePolyFillArc(pDrawable, pGC, narcs, parcs) ++ DrawablePtr pDrawable; ++ GCPtr pGC; ++ int narcs; ++ xArc *parcs; ++{ ++ VNCSCREENPTR(pDrawable->pScreen); ++ ++ GC_SETUP(pDrawable, pGC); ++ ++ if (GC_CHECK((WindowPtr) pDrawable)) ++ { ++ register int n; ++ BoxPtr cursor; ++ register xArc *arcs; ++ ++ cursor = &pScreenPriv->saved; ++ ++ for (arcs = parcs, n = narcs; n--; arcs++) ++ { ++ if (ORG_OVERLAP(cursor, pDrawable->x, pDrawable->y, ++ arcs->x, arcs->y, ++ (int) arcs->width, (int) arcs->height)) ++ { ++ rfbSpriteRemoveCursor (pDrawable->pScreen); ++ break; ++ } ++ } ++ } ++ ++ GC_OP_PROLOGUE (pGC); ++ ++ (*pGC->ops->PolyFillArc) (pDrawable, pGC, narcs, parcs); ++ ++ GC_OP_EPILOGUE (pGC); ++} ++ ++/* ++ * general Poly/Image text function. Extract glyph information, ++ * compute bounding box and remove cursor if it is overlapped. ++ */ ++ ++static Bool ++rfbSpriteTextOverlap (DrawablePtr pDraw, FontPtr font, int x, int y, unsigned int n, CharInfoPtr *charinfo, Bool imageblt, unsigned int w, BoxPtr cursorBox) ++{ ++ ExtentInfoRec extents; ++ ++ x += pDraw->x; ++ y += pDraw->y; ++ ++ if (FONTMINBOUNDS(font,characterWidth) >= 0) ++ { ++ /* compute an approximate (but covering) bounding box */ ++ if (!imageblt || (charinfo[0]->metrics.leftSideBearing < 0)) ++ extents.overallLeft = charinfo[0]->metrics.leftSideBearing; ++ else ++ extents.overallLeft = 0; ++ if (w) ++ extents.overallRight = w - charinfo[n-1]->metrics.characterWidth; ++ else ++ extents.overallRight = FONTMAXBOUNDS(font,characterWidth) ++ * (n - 1); ++ if (imageblt && (charinfo[n-1]->metrics.characterWidth > ++ charinfo[n-1]->metrics.rightSideBearing)) ++ extents.overallRight += charinfo[n-1]->metrics.characterWidth; ++ else ++ extents.overallRight += charinfo[n-1]->metrics.rightSideBearing; ++ if (imageblt && FONTASCENT(font) > FONTMAXBOUNDS(font,ascent)) ++ extents.overallAscent = FONTASCENT(font); ++ else ++ extents.overallAscent = FONTMAXBOUNDS(font, ascent); ++ if (imageblt && FONTDESCENT(font) > FONTMAXBOUNDS(font,descent)) ++ extents.overallDescent = FONTDESCENT(font); ++ else ++ extents.overallDescent = FONTMAXBOUNDS(font,descent); ++ if (!BOX_OVERLAP(cursorBox, ++ x + extents.overallLeft, ++ y - extents.overallAscent, ++ x + extents.overallRight, ++ y + extents.overallDescent)) ++ return FALSE; ++ else if (imageblt && w) ++ return TRUE; ++ /* if it does overlap, fall through and compute exactly, because ++ * taking down the cursor is expensive enough to make this worth it ++ */ ++ } ++ QueryGlyphExtents(font, charinfo, n, &extents); ++ if (imageblt) ++ { ++ if (extents.overallWidth > extents.overallRight) ++ extents.overallRight = extents.overallWidth; ++ if (extents.overallWidth < extents.overallLeft) ++ extents.overallLeft = extents.overallWidth; ++ if (extents.overallLeft > 0) ++ extents.overallLeft = 0; ++ if (extents.fontAscent > extents.overallAscent) ++ extents.overallAscent = extents.fontAscent; ++ if (extents.fontDescent > extents.overallDescent) ++ extents.overallDescent = extents.fontDescent; ++ } ++ return (BOX_OVERLAP(cursorBox, ++ x + extents.overallLeft, ++ y - extents.overallAscent, ++ x + extents.overallRight, ++ y + extents.overallDescent)); ++} ++ ++/* ++ * values for textType: ++ */ ++#define TT_POLY8 0 ++#define TT_IMAGE8 1 ++#define TT_POLY16 2 ++#define TT_IMAGE16 3 ++ ++static int ++rfbSpriteText (DrawablePtr pDraw, GCPtr pGC, int x, int y, unsigned long count, char *chars, FontEncoding fontEncoding, Bool textType, BoxPtr cursorBox) ++{ ++ CharInfoPtr *charinfo; ++ register CharInfoPtr *info; ++ unsigned long i; ++ unsigned int n; ++ int w; ++ void (*drawFunc)() = NULL; ++ ++ Bool imageblt; ++ ++ imageblt = (textType == TT_IMAGE8) || (textType == TT_IMAGE16); ++ ++ charinfo = (CharInfoPtr *) ALLOCATE_LOCAL(count * sizeof(CharInfoPtr)); ++ if (!charinfo) ++ return x; ++ ++ GetGlyphs(pGC->font, count, (unsigned char *)chars, ++ fontEncoding, &i, charinfo); ++ n = (unsigned int)i; ++ w = 0; ++ if (!imageblt) ++ for (info = charinfo; i--; info++) ++ w += (*info)->metrics.characterWidth; ++ ++ if (n != 0) { ++ if (rfbSpriteTextOverlap(pDraw, pGC->font, x, y, n, charinfo, imageblt, w, cursorBox)) ++ rfbSpriteRemoveCursor(pDraw->pScreen); ++ ++#ifdef AVOID_GLYPHBLT ++ /* ++ * On displays like Apollos, which do not optimize the GlyphBlt functions because they ++ * convert fonts to their internal form in RealizeFont and optimize text directly, we ++ * want to invoke the text functions here, not the GlyphBlt functions. ++ */ ++ switch (textType) ++ { ++ case TT_POLY8: ++ drawFunc = (void (*)())pGC->ops->PolyText8; ++ break; ++ case TT_IMAGE8: ++ drawFunc = pGC->ops->ImageText8; ++ break; ++ case TT_POLY16: ++ drawFunc = (void (*)())pGC->ops->PolyText16; ++ break; ++ case TT_IMAGE16: ++ drawFunc = pGC->ops->ImageText16; ++ break; ++ } ++ (*drawFunc) (pDraw, pGC, x, y, (int) count, chars); ++#else /* don't AVOID_GLYPHBLT */ ++ /* ++ * On the other hand, if the device does use GlyphBlt ultimately to do text, we ++ * don't want to slow it down by invoking the text functions and having them call ++ * GetGlyphs all over again, so we go directly to the GlyphBlt functions here. ++ */ ++ drawFunc = imageblt ? pGC->ops->ImageGlyphBlt : pGC->ops->PolyGlyphBlt; ++ (*drawFunc) (pDraw, pGC, x, y, n, charinfo, FONTGLYPHS(pGC->font)); ++#endif /* AVOID_GLYPHBLT */ ++ } ++ DEALLOCATE_LOCAL(charinfo); ++ return x + w; ++} ++ ++static int ++rfbSpritePolyText8(DrawablePtr pDrawable, GCPtr pGC, int x, int y, int count, char *chars) ++{ ++ int ret; ++ VNCSCREENPTR(pDrawable->pScreen); ++ ++ GC_SETUP (pDrawable, pGC); ++ ++ GC_OP_PROLOGUE (pGC); ++ ++ if (GC_CHECK((WindowPtr) pDrawable)) ++ ret = rfbSpriteText (pDrawable, pGC, x, y, (unsigned long)count, chars, ++ Linear8Bit, TT_POLY8, &pScreenPriv->saved); ++ else ++ ret = (*pGC->ops->PolyText8) (pDrawable, pGC, x, y, count, chars); ++ ++ GC_OP_EPILOGUE (pGC); ++ return ret; ++} ++ ++static int ++rfbSpritePolyText16(DrawablePtr pDrawable, GCPtr pGC, int x, int y, int count, unsigned short *chars) ++{ ++ int ret; ++ VNCSCREENPTR(pDrawable->pScreen); ++ ++ GC_SETUP(pDrawable, pGC); ++ ++ GC_OP_PROLOGUE (pGC); ++ ++ if (GC_CHECK((WindowPtr) pDrawable)) ++ ret = rfbSpriteText (pDrawable, pGC, x, y, (unsigned long)count, ++ (char *)chars, ++ FONTLASTROW(pGC->font) == 0 ? ++ Linear16Bit : TwoD16Bit, TT_POLY16, &pScreenPriv->saved); ++ else ++ ret = (*pGC->ops->PolyText16) (pDrawable, pGC, x, y, count, chars); ++ ++ GC_OP_EPILOGUE (pGC); ++ return ret; ++} ++ ++static void ++rfbSpriteImageText8(pDrawable, pGC, x, y, count, chars) ++ DrawablePtr pDrawable; ++ GCPtr pGC; ++ int x, y; ++ int count; ++ char *chars; ++{ ++ VNCSCREENPTR(pDrawable->pScreen); ++ ++ GC_SETUP(pDrawable, pGC); ++ ++ GC_OP_PROLOGUE (pGC); ++ ++ if (GC_CHECK((WindowPtr) pDrawable)) ++ (void) rfbSpriteText (pDrawable, pGC, x, y, (unsigned long)count, ++ chars, Linear8Bit, TT_IMAGE8, &pScreenPriv->saved); ++ else ++ (*pGC->ops->ImageText8) (pDrawable, pGC, x, y, count, chars); ++ ++ GC_OP_EPILOGUE (pGC); ++} ++ ++static void ++rfbSpriteImageText16(pDrawable, pGC, x, y, count, chars) ++ DrawablePtr pDrawable; ++ GCPtr pGC; ++ int x, y; ++ int count; ++ unsigned short *chars; ++{ ++ VNCSCREENPTR(pDrawable->pScreen); ++ ++ GC_SETUP(pDrawable, pGC); ++ ++ GC_OP_PROLOGUE (pGC); ++ ++ if (GC_CHECK((WindowPtr) pDrawable)) ++ (void) rfbSpriteText (pDrawable, pGC, x, y, (unsigned long)count, ++ (char *)chars, ++ FONTLASTROW(pGC->font) == 0 ? ++ Linear16Bit : TwoD16Bit, TT_IMAGE16, &pScreenPriv->saved); ++ else ++ (*pGC->ops->ImageText16) (pDrawable, pGC, x, y, count, chars); ++ ++ GC_OP_EPILOGUE (pGC); ++} ++ ++static void ++rfbSpriteImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase) ++ DrawablePtr pDrawable; ++ GCPtr pGC; ++ int x, y; ++ unsigned int nglyph; ++ CharInfoPtr *ppci; /* array of character info */ ++ pointer pglyphBase; /* start of array of glyphs */ ++{ ++ VNCSCREENPTR(pDrawable->pScreen); ++ ++ GC_SETUP(pDrawable, pGC); ++ ++ GC_OP_PROLOGUE (pGC); ++ ++ if (GC_CHECK((WindowPtr) pDrawable) && ++ rfbSpriteTextOverlap (pDrawable, pGC->font, x, y, nglyph, ppci, TRUE, 0, &pScreenPriv->saved)) ++ { ++ rfbSpriteRemoveCursor(pDrawable->pScreen); ++ } ++ (*pGC->ops->ImageGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); ++ ++ GC_OP_EPILOGUE (pGC); ++} ++ ++static void ++rfbSpritePolyGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase) ++ DrawablePtr pDrawable; ++ GCPtr pGC; ++ int x, y; ++ unsigned int nglyph; ++ CharInfoPtr *ppci; /* array of character info */ ++ pointer pglyphBase; /* start of array of glyphs */ ++{ ++ VNCSCREENPTR(pDrawable->pScreen); ++ ++ GC_SETUP (pDrawable, pGC); ++ ++ GC_OP_PROLOGUE (pGC); ++ ++ if (GC_CHECK((WindowPtr) pDrawable) && ++ rfbSpriteTextOverlap (pDrawable, pGC->font, x, y, nglyph, ppci, FALSE, 0, &pScreenPriv->saved)) ++ { ++ rfbSpriteRemoveCursor(pDrawable->pScreen); ++ } ++ (*pGC->ops->PolyGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); ++ ++ GC_OP_EPILOGUE (pGC); ++} ++ ++static void ++rfbSpritePushPixels(pGC, pBitMap, pDrawable, w, h, x, y) ++ GCPtr pGC; ++ PixmapPtr pBitMap; ++ DrawablePtr pDrawable; ++ int w, h, x, y; ++{ ++ VNCSCREENPTR(pDrawable->pScreen); ++ GC_SETUP(pDrawable, pGC); ++ ++ if (GC_CHECK((WindowPtr) pDrawable) && ++ ORG_OVERLAP(&pScreenPriv->saved,pDrawable->x,pDrawable->y,x,y,w,h)) ++ { ++ rfbSpriteRemoveCursor (pDrawable->pScreen); ++ } ++ ++ GC_OP_PROLOGUE (pGC); ++ ++ (*pGC->ops->PushPixels) (pGC, pBitMap, pDrawable, w, h, x, y); ++ ++ GC_OP_EPILOGUE (pGC); ++} ++ ++#ifdef NEED_LINEHELPER ++/* ++ * I don't expect this routine will ever be called, as the GC ++ * will have been unwrapped for the line drawing ++ */ ++ ++static void ++rfbSpriteLineHelper() ++{ ++ FatalError("rfbSpriteLineHelper called\n"); ++} ++#endif ++ ++#ifdef RENDER ++ ++# define mod(a,b) ((b) == 1 ? 0 : (a) >= 0 ? (a) % (b) : (b) - (-a) % (b)) ++ ++static void ++rfbSpritePictureOverlap (PicturePtr pPict, ++ INT16 x, ++ INT16 y, ++ CARD16 w, ++ CARD16 h) ++{ ++ VNCSCREENPTR(pPict->pDrawable->pScreen); ++ ++ if (pPict->pDrawable->type == DRAWABLE_WINDOW) ++ { ++ WindowPtr pWin = (WindowPtr) (pPict->pDrawable); ++ rfbSpriteScreenPtr pScreenPriv = (rfbSpriteScreenPtr) ++ pPict->pDrawable->pScreen->devPrivates[rfbSpriteScreenIndex].ptr; ++ if (GC_CHECK(pWin)) ++ { ++ if (pPict->repeat) ++ { ++ x = mod(x,pWin->drawable.width); ++ y = mod(y,pWin->drawable.height); ++ } ++ if (ORG_OVERLAP (&pScreenPriv->saved, pWin->drawable.x, pWin->drawable.y, ++ x, y, w, h)) ++ rfbSpriteRemoveCursor (pWin->drawable.pScreen); ++ } ++ } ++} ++ ++#define PICTURE_PROLOGUE(ps, pScreenPriv, field) \ ++ ps->field = pScreenPriv->field ++ ++#define PICTURE_EPILOGUE(ps, field, wrap) \ ++ ps->field = wrap ++ ++static void ++rfbSpriteComposite(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; ++ PictureScreenPtr ps = GetPictureScreen(pScreen); ++ rfbSpriteScreenPtr pScreenPriv; ++ ++ pScreenPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr; ++ PICTURE_PROLOGUE(ps, pScreenPriv, Composite); ++ rfbSpritePictureOverlap (pSrc, xSrc, ySrc, width, height); ++ if (pMask) ++ rfbSpritePictureOverlap (pMask, xMask, yMask, width, height); ++ rfbSpritePictureOverlap (pDst, xDst, yDst, width, height); ++ ++ (*ps->Composite) (op, ++ pSrc, ++ pMask, ++ pDst, ++ xSrc, ++ ySrc, ++ xMask, ++ yMask, ++ xDst, ++ yDst, ++ width, ++ height); ++ ++ PICTURE_EPILOGUE(ps, Composite, rfbSpriteComposite); ++} ++ ++static void ++rfbSpriteGlyphs(CARD8 op, ++ PicturePtr pSrc, ++ PicturePtr pDst, ++ PictFormatPtr maskFormat, ++ INT16 xSrc, ++ INT16 ySrc, ++ int nlist, ++ GlyphListPtr list, ++ GlyphPtr *glyphs) ++{ ++ ScreenPtr pScreen = pDst->pDrawable->pScreen; ++ VNCSCREENPTR(pScreen); ++ PictureScreenPtr ps = GetPictureScreen(pScreen); ++ rfbSpriteScreenPtr pScreenPriv; ++ ++ pScreenPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr; ++ PICTURE_PROLOGUE(ps, pScreenPriv, Glyphs); ++ if (pSrc->pDrawable->type == DRAWABLE_WINDOW) ++ { ++ WindowPtr pSrcWin = (WindowPtr) (pSrc->pDrawable); ++ ++ if (GC_CHECK(pSrcWin)) ++ rfbSpriteRemoveCursor (pScreen); ++ } ++ if (pDst->pDrawable->type == DRAWABLE_WINDOW) ++ { ++ WindowPtr pDstWin = (WindowPtr) (pDst->pDrawable); ++ ++ if (GC_CHECK(pDstWin)) ++ { ++ BoxRec extents; ++ ++ miGlyphExtents (nlist, list, glyphs, &extents); ++ if (BOX_OVERLAP(&pScreenPriv->saved, ++ extents.x1 + pDstWin->drawable.x, ++ extents.y1 + pDstWin->drawable.y, ++ extents.x2 + pDstWin->drawable.x, ++ extents.y2 + pDstWin->drawable.y)) ++ { ++ rfbSpriteRemoveCursor (pScreen); ++ } ++ } ++ } ++ ++ (*ps->Glyphs) (op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs); ++ ++ PICTURE_EPILOGUE (ps, Glyphs, rfbSpriteGlyphs); ++} ++#endif ++ ++/* ++ * miPointer interface routines ++ */ ++ ++#define SPRITE_PAD 8 ++ ++static Bool ++rfbSpriteRealizeCursor (ScreenPtr pScreen, CursorPtr pCursor) ++{ ++ rfbSpriteScreenPtr pScreenPriv; ++ ++ pScreenPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr; ++ if (pCursor == pScreenPriv->pCursor) ++ pScreenPriv->checkPixels = TRUE; ++ return (*pScreenPriv->funcs->RealizeCursor) (pScreen, pCursor); ++} ++ ++static Bool ++rfbSpriteUnrealizeCursor (ScreenPtr pScreen, CursorPtr pCursor) ++{ ++ rfbSpriteScreenPtr pScreenPriv; ++ ++ pScreenPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr; ++ return (*pScreenPriv->funcs->UnrealizeCursor) (pScreen, pCursor); ++} ++ ++static void ++rfbSpriteSetCursor (ScreenPtr pScreen, CursorPtr pCursor, int x, int y) ++{ ++ rfbSpriteScreenPtr pScreenPriv; ++ rfbClientPtr cl, nextCl; ++ VNCSCREENPTR(pScreen); ++ ++ pScreenPriv ++ = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr; ++ if (!pCursor) ++ { ++ pScreenPriv->shouldBeUp = FALSE; ++ if (pVNC->cursorIsDrawn) ++ rfbSpriteRemoveCursor (pScreen); ++ pScreenPriv->pCursor = 0; ++ return; ++ } ++ pScreenPriv->shouldBeUp = TRUE; ++ if (pScreenPriv->x == x && ++ pScreenPriv->y == y && ++ pScreenPriv->pCursor == pCursor && ++ !pScreenPriv->checkPixels) ++ { ++ return; ++ } ++ pScreenPriv->x = x; ++ pScreenPriv->y = y; ++ pScreenPriv->pCacheWin = NullWindow; ++ if (pScreenPriv->checkPixels || pScreenPriv->pCursor != pCursor) ++ { ++ pScreenPriv->pCursor = pCursor; ++ rfbSpriteFindColors (pScreen); ++ } ++ if (pVNC->cursorIsDrawn) { ++ int sx, sy; ++ /* ++ * check to see if the old saved region ++ * encloses the new sprite, in which case we use ++ * the flicker-free MoveCursor primitive. ++ */ ++ sx = pScreenPriv->x - (int)pCursor->bits->xhot; ++ sy = pScreenPriv->y - (int)pCursor->bits->yhot; ++ if (sx + (int) pCursor->bits->width >= pScreenPriv->saved.x1 && ++ sx < pScreenPriv->saved.x2 && ++ sy + (int) pCursor->bits->height >= pScreenPriv->saved.y1 && ++ sy < pScreenPriv->saved.y2 && ++ (int) pCursor->bits->width + (2 * SPRITE_PAD) == ++ pScreenPriv->saved.x2 - pScreenPriv->saved.x1 && ++ (int) pCursor->bits->height + (2 * SPRITE_PAD) == ++ pScreenPriv->saved.y2 - pScreenPriv->saved.y1 ++ ) ++ { ++ pVNC->cursorIsDrawn = FALSE; ++ if (!(sx >= pScreenPriv->saved.x1 && ++ sx + (int)pCursor->bits->width < pScreenPriv->saved.x2 && ++ sy >= pScreenPriv->saved.y1 && ++ sy + (int)pCursor->bits->height < pScreenPriv->saved.y2)) ++ { ++ int oldx1, oldy1, dx, dy; ++ ++ oldx1 = pScreenPriv->saved.x1; ++ oldy1 = pScreenPriv->saved.y1; ++ dx = oldx1 - (sx - SPRITE_PAD); ++ dy = oldy1 - (sy - SPRITE_PAD); ++ pScreenPriv->saved.x1 -= dx; ++ pScreenPriv->saved.y1 -= dy; ++ pScreenPriv->saved.x2 -= dx; ++ pScreenPriv->saved.y2 -= dy; ++ (void) (*pScreenPriv->funcs->ChangeSave) (pScreen, ++ pScreenPriv->saved.x1, ++ pScreenPriv->saved.y1, ++ pScreenPriv->saved.x2 - pScreenPriv->saved.x1, ++ pScreenPriv->saved.y2 - pScreenPriv->saved.y1, ++ dx, dy); ++ } ++ (void) (*pScreenPriv->funcs->MoveCursor) (pScreen, pCursor, ++ pScreenPriv->saved.x1, ++ pScreenPriv->saved.y1, ++ pScreenPriv->saved.x2 - pScreenPriv->saved.x1, ++ pScreenPriv->saved.y2 - pScreenPriv->saved.y1, ++ sx - pScreenPriv->saved.x1, ++ sy - pScreenPriv->saved.y1, ++ pScreenPriv->colors[SOURCE_COLOR].pixel, ++ pScreenPriv->colors[MASK_COLOR].pixel); ++ pVNC->cursorIsDrawn = TRUE; ++ } ++ else ++ { ++ rfbSpriteRemoveCursor (pScreen); ++ } ++ } ++#if 0 ++ if (!pVNC->cursorIsDrawn && pScreenPriv->pCursor) ++ rfbSpriteRestoreCursor (pScreen); ++#endif ++ if (pVNC->cursorIsDrawn) ++ rfbSpriteRemoveCursor (pScreen); ++ ++ for (cl = rfbClientHead; cl; cl = nextCl) { ++ nextCl = cl->next; ++ if (cl->enableCursorPosUpdates) { ++ if (x == cl->cursorX && y == cl->cursorY) { ++ cl->cursorWasMoved = FALSE; ++ continue; ++ } ++ cl->cursorWasMoved = TRUE; ++ } ++ if (REGION_NOTEMPTY(pScreen,&cl->requestedRegion)) { ++ /* cursorIsDrawn is guaranteed to be FALSE here, so we definitely ++ want to send a screen update to the client, even if that's only ++ putting up the cursor */ ++ rfbSendFramebufferUpdate(pScreen, cl); ++ } ++ } ++} ++ ++static void ++rfbSpriteMoveCursor (ScreenPtr pScreen, int x, int y) ++{ ++ rfbSpriteScreenPtr pScreenPriv; ++ ++ pScreenPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr; ++ rfbSpriteSetCursor (pScreen, pScreenPriv->pCursor, x, y); ++} ++ ++/* ++ * undraw/draw cursor ++ */ ++ ++void ++rfbSpriteRemoveCursor (pScreen) ++ ScreenPtr pScreen; ++{ ++ rfbSpriteScreenPtr pScreenPriv; ++ VNCSCREENPTR(pScreen); ++ ++ if (!pVNC->cursorIsDrawn) ++ return; ++ ++ pScreenPriv ++ = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr; ++ ++ pVNC->dontSendFramebufferUpdate = TRUE; ++ pVNC->cursorIsDrawn = FALSE; ++ pScreenPriv->pCacheWin = NullWindow; ++ if (!(*pScreenPriv->funcs->RestoreUnderCursor) (pScreen, ++ pScreenPriv->saved.x1, ++ pScreenPriv->saved.y1, ++ pScreenPriv->saved.x2 - pScreenPriv->saved.x1, ++ pScreenPriv->saved.y2 - pScreenPriv->saved.y1)) ++ { ++ pVNC->cursorIsDrawn = TRUE; ++ } ++ pVNC->dontSendFramebufferUpdate = FALSE; ++} ++ ++ ++void ++rfbSpriteRestoreCursor (pScreen) ++ ScreenPtr pScreen; ++{ ++ rfbSpriteScreenPtr pScreenPriv; ++ int x, y; ++ CursorPtr pCursor; ++ VNCSCREENPTR(pScreen); ++ ++ pScreenPriv ++ = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr; ++ pCursor = pScreenPriv->pCursor; ++ ++ if (pVNC->cursorIsDrawn || !pCursor) ++ return; ++ ++ pVNC->dontSendFramebufferUpdate = TRUE; ++ ++ rfbSpriteComputeSaved (pScreen); ++ ++ x = pScreenPriv->x - (int)pCursor->bits->xhot; ++ y = pScreenPriv->y - (int)pCursor->bits->yhot; ++ if ((*pScreenPriv->funcs->SaveUnderCursor) (pScreen, ++ pScreenPriv->saved.x1, ++ pScreenPriv->saved.y1, ++ pScreenPriv->saved.x2 - pScreenPriv->saved.x1, ++ pScreenPriv->saved.y2 - pScreenPriv->saved.y1)) ++ { ++ if (pScreenPriv->checkPixels) ++ rfbSpriteFindColors (pScreen); ++ if ((*pScreenPriv->funcs->PutUpCursor) (pScreen, pCursor, x, y, ++ pScreenPriv->colors[SOURCE_COLOR].pixel, ++ pScreenPriv->colors[MASK_COLOR].pixel)) ++ pVNC->cursorIsDrawn = TRUE; ++ } ++ ++ pVNC->dontSendFramebufferUpdate = FALSE; ++} ++ ++/* ++ * compute the desired area of the screen to save ++ */ ++ ++static void ++rfbSpriteComputeSaved (pScreen) ++ ScreenPtr pScreen; ++{ ++ rfbSpriteScreenPtr pScreenPriv; ++ int x, y, w, h; ++ int wpad, hpad; ++ CursorPtr pCursor; ++ ++ pScreenPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr; ++ pCursor = pScreenPriv->pCursor; ++ x = pScreenPriv->x - (int)pCursor->bits->xhot; ++ y = pScreenPriv->y - (int)pCursor->bits->yhot; ++ w = pCursor->bits->width; ++ h = pCursor->bits->height; ++ wpad = SPRITE_PAD; ++ hpad = SPRITE_PAD; ++ pScreenPriv->saved.x1 = x - wpad; ++ pScreenPriv->saved.y1 = y - hpad; ++ pScreenPriv->saved.x2 = pScreenPriv->saved.x1 + w + wpad * 2; ++ pScreenPriv->saved.y2 = pScreenPriv->saved.y1 + h + hpad * 2; ++} ++ ++ ++/* ++ * this function is called when the cursor shape is being changed ++ */ ++ ++static Bool ++rfbDisplayCursor(pScreen, pCursor) ++ ScreenPtr pScreen; ++ CursorPtr pCursor; ++{ ++ rfbClientPtr cl; ++ rfbSpriteScreenPtr pPriv; ++ Bool status; ++ ++ for (cl = rfbClientHead; cl ; cl = cl->next) { ++ if (cl->enableCursorShapeUpdates) ++ cl->cursorWasChanged = TRUE; ++ } ++ ++ pPriv = (rfbSpriteScreenPtr)pScreen->devPrivates[rfbSpriteScreenIndex].ptr; ++ status = (*pPriv->DisplayCursor)(pScreen, pCursor); ++ ++ /* send new cursor shape to interested viewers */ ++ for (cl = rfbClientHead; cl ; cl = cl->next) { ++ if (cl->cursorWasChanged) { ++ rfbSendFramebufferUpdate(pScreen, cl); ++ } ++ } ++ ++ return status; ++} ++ ++ ++/* ++ * obtain current cursor pointer ++ */ ++ ++CursorPtr ++rfbSpriteGetCursorPtr (pScreen) ++ ScreenPtr pScreen; ++{ ++ rfbSpriteScreenPtr pScreenPriv; ++ ++ pScreenPriv = (rfbSpriteScreenPtr) ++ pScreen->devPrivates[rfbSpriteScreenIndex].ptr; ++ ++ return pScreenPriv->pCursor; ++} ++ ++/* ++ * obtain current cursor position ++ */ ++ ++void ++rfbSpriteGetCursorPos (pScreen, px, py) ++ ScreenPtr pScreen; ++ int *px, *py; ++{ ++ rfbSpriteScreenPtr pScreenPriv; ++ ++ pScreenPriv = (rfbSpriteScreenPtr) ++ pScreen->devPrivates[rfbSpriteScreenIndex].ptr; ++ ++ *px = pScreenPriv->x; ++ *py = pScreenPriv->y; ++} ++ +diff -pNur xorg-server-1.4.orig/hw/vnc/sprite.h xorg-server-1.4/hw/vnc/sprite.h +--- xorg-server-1.4.orig/hw/vnc/sprite.h 1969-12-31 16:00:00.000000000 -0800 ++++ xorg-server-1.4/hw/vnc/sprite.h 2007-09-06 16:09:45.000000000 -0700 +@@ -0,0 +1,141 @@ ++/* ++ * sprite.h ++ * ++ * software-sprite/sprite drawing - based on misprite ++ * ++ * Modified for XFree86 4.x by Alan Hourihane ++ */ ++ ++/* ++ * 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) 1989 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. ++*/ ++ ++typedef struct { ++ Bool (*RealizeCursor)( ++ ScreenPtr /*pScreen*/, ++ CursorPtr /*pCursor*/ ++); ++ Bool (*UnrealizeCursor)( ++ ScreenPtr /*pScreen*/, ++ CursorPtr /*pCursor*/ ++); ++ Bool (*PutUpCursor)( ++ ScreenPtr /*pScreen*/, ++ CursorPtr /*pCursor*/, ++ int /*x*/, ++ int /*y*/, ++ unsigned long /*source*/, ++ unsigned long /*mask*/ ++); ++ Bool (*SaveUnderCursor)( ++ ScreenPtr /*pScreen*/, ++ int /*x*/, ++ int /*y*/, ++ int /*w*/, ++ int /*h*/ ++); ++ Bool (*RestoreUnderCursor)( ++ ScreenPtr /*pScreen*/, ++ int /*x*/, ++ int /*y*/, ++ int /*w*/, ++ int /*h*/ ++); ++ Bool (*MoveCursor)( ++ ScreenPtr /*pScreen*/, ++ CursorPtr /*pCursor*/, ++ int /*x*/, ++ int /*y*/, ++ int /*w*/, ++ int /*h*/, ++ int /*dx*/, ++ int /*dy*/, ++ unsigned long /*source*/, ++ unsigned long /*mask*/ ++); ++ Bool (*ChangeSave)( ++ ScreenPtr /*pScreen*/, ++ int /*x*/, ++ int /*y*/, ++ int /*w*/, ++ int /*h*/, ++ int /*dx*/, ++ int /*dy*/ ++); ++ ++} rfbSpriteCursorFuncRec, *rfbSpriteCursorFuncPtr; ++ ++extern Bool rfbSpriteInitialize( ++#if NeedFunctionPrototypes ++ ScreenPtr /*pScreen*/, ++ rfbSpriteCursorFuncPtr /*cursorFuncs*/, ++ miPointerScreenFuncPtr /*screenFuncs*/ ++#endif ++); ++ ++extern void rfbSpriteRestoreCursor( ++#if NeedFunctionPrototypes ++ ScreenPtr /*pScreen*/ ++#endif ++); ++ ++extern void rfbSpriteRemoveCursor( ++#if NeedFunctionPrototypes ++ ScreenPtr /*pScreen*/ ++#endif ++); ++ ++extern CursorPtr rfbSpriteGetCursorPtr( ++#if NeedFunctionPrototypes ++ ScreenPtr /*pScreen*/ ++#endif ++); ++ ++extern void rfbSpriteGetCursorPos( ++#if NeedFunctionPrototypes ++ ScreenPtr /*pScreen*/, ++ int * /*px*/, ++ int * /*py*/ ++#endif ++); +diff -pNur xorg-server-1.4.orig/hw/vnc/spritest.h xorg-server-1.4/hw/vnc/spritest.h +--- xorg-server-1.4.orig/hw/vnc/spritest.h 1969-12-31 16:00:00.000000000 -0800 ++++ xorg-server-1.4/hw/vnc/spritest.h 2007-09-06 16:09:45.000000000 -0700 +@@ -0,0 +1,138 @@ ++/* ++ * spritest.h ++ * ++ * sprite structures - based on misprite ++ * ++ * Modified for XFree86 4.x by Alan Hourihane ++ */ ++ ++/* ++ * 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) 1989 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 "sprite.h" ++ ++#ifdef RENDER ++# include "picturestr.h" ++#endif ++ ++/* ++ * per screen information ++ */ ++ ++typedef struct { ++ CloseScreenProcPtr CloseScreen; ++ GetImageProcPtr GetImage; ++ GetSpansProcPtr GetSpans; ++ SourceValidateProcPtr SourceValidate; ++ CreateGCProcPtr CreateGC; ++ ScreenBlockHandlerProcPtr BlockHandler; ++ InstallColormapProcPtr InstallColormap; ++ StoreColorsProcPtr StoreColors; ++ PaintWindowBackgroundProcPtr PaintWindowBackground; ++ PaintWindowBorderProcPtr PaintWindowBorder; ++ CopyWindowProcPtr CopyWindow; ++ ClearToBackgroundProcPtr ClearToBackground; ++ SaveDoomedAreasProcPtr SaveDoomedAreas; ++ RestoreAreasProcPtr RestoreAreas; ++ DisplayCursorProcPtr DisplayCursor; ++#ifdef RENDER ++ CompositeProcPtr Composite; ++ GlyphsProcPtr Glyphs; ++#endif ++ ++ CursorPtr pCursor; ++ int x; ++ int y; ++ Bool shouldBeUp; ++ BoxRec saved; ++ WindowPtr pCacheWin; ++ Bool isInCacheWin; ++ Bool checkPixels; ++ xColorItem colors[2]; ++ ColormapPtr pInstalledMap; ++ ColormapPtr pColormap; ++ VisualPtr pVisual; ++ rfbSpriteCursorFuncPtr funcs; ++} rfbSpriteScreenRec, *rfbSpriteScreenPtr; ++ ++#define SOURCE_COLOR 0 ++#define MASK_COLOR 1 ++ ++typedef struct { ++ GCFuncs *wrapFuncs; ++ GCOps *wrapOps; ++} rfbSpriteGCRec, *rfbSpriteGCPtr; ++ ++/* ++ * Overlap BoxPtr and Box elements ++ */ ++#define BOX_OVERLAP(pCbox,X1,Y1,X2,Y2) \ ++ (((pCbox)->x1 <= (X2)) && ((X1) <= (pCbox)->x2) && \ ++ ((pCbox)->y1 <= (Y2)) && ((Y1) <= (pCbox)->y2)) ++ ++/* ++ * Overlap BoxPtr, origins, and rectangle ++ */ ++#define ORG_OVERLAP(pCbox,xorg,yorg,x,y,w,h) \ ++ BOX_OVERLAP((pCbox),(x)+(xorg),(y)+(yorg),(x)+(xorg)+(w),(y)+(yorg)+(h)) ++ ++/* ++ * Overlap BoxPtr, origins and RectPtr ++ */ ++#define ORGRECT_OVERLAP(pCbox,xorg,yorg,pRect) \ ++ ORG_OVERLAP((pCbox),(xorg),(yorg),(pRect)->x,(pRect)->y, \ ++ (int)((pRect)->width), (int)((pRect)->height)) ++/* ++ * Overlap BoxPtr and horizontal span ++ */ ++#define SPN_OVERLAP(pCbox,y,x,w) BOX_OVERLAP((pCbox),(x),(y),(x)+(w),(y)) ++ ++#define LINE_SORT(x1,y1,x2,y2) \ ++{ int _t; \ ++ if (x1 > x2) { _t = x1; x1 = x2; x2 = _t; } \ ++ if (y1 > y2) { _t = y1; y1 = y2; y2 = _t; } } ++ ++#define LINE_OVERLAP(pCbox,x1,y1,x2,y2,lw2) \ ++ BOX_OVERLAP((pCbox), (x1)-(lw2), (y1)-(lw2), (x2)+(lw2), (y2)+(lw2)) +diff -pNur xorg-server-1.4.orig/hw/vnc/stats.c xorg-server-1.4/hw/vnc/stats.c +--- xorg-server-1.4.orig/hw/vnc/stats.c 1969-12-31 16:00:00.000000000 -0800 ++++ xorg-server-1.4/hw/vnc/stats.c 2007-09-06 16:09:45.000000000 -0700 +@@ -0,0 +1,117 @@ ++/* ++ * stats.c ++ * ++ * Modified for XFree86 4.x by Alan Hourihane ++ */ ++ ++/* ++ * Copyright (C) 2002 Constantin Kaplinsky. All Rights Reserved. ++ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. ++ * ++ * This is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This software is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this software; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, ++ * USA. ++ */ ++#ifdef HAVE_DIX_CONFIG_H ++#include ++#endif ++ ++ ++#include ++#include ++#include "rfb.h" ++ ++static char* encNames[] = { ++ "raw", "copyRect", "RRE", "[encoding 3]", "CoRRE", "hextile", ++ "zlib", "tight", "[encoding 8]", "[encoding 9]" ++}; ++ ++ ++void ++rfbResetStats(rfbClientPtr cl) ++{ ++ int i; ++ for (i = 0; i < MAX_ENCODINGS; i++) { ++ cl->rfbBytesSent[i] = 0; ++ cl->rfbRectanglesSent[i] = 0; ++ } ++ cl->rfbLastRectMarkersSent = 0; ++ cl->rfbLastRectBytesSent = 0; ++ cl->rfbCursorShapeBytesSent = 0; ++ cl->rfbCursorShapeUpdatesSent = 0; ++ cl->rfbCursorPosBytesSent = 0; ++ cl->rfbCursorPosUpdatesSent = 0; ++ cl->rfbFramebufferUpdateMessagesSent = 0; ++ cl->rfbRawBytesEquivalent = 0; ++ cl->rfbKeyEventsRcvd = 0; ++ cl->rfbPointerEventsRcvd = 0; ++} ++ ++void ++rfbPrintStats(rfbClientPtr cl) ++{ ++ int i; ++ int totalRectanglesSent = 0; ++ int totalBytesSent = 0; ++ ++ rfbLog("Statistics:\n"); ++ ++ if ((cl->rfbKeyEventsRcvd != 0) || (cl->rfbPointerEventsRcvd != 0)) ++ rfbLog(" key events received %d, pointer events %d\n", ++ cl->rfbKeyEventsRcvd, cl->rfbPointerEventsRcvd); ++ ++ for (i = 0; i < MAX_ENCODINGS; i++) { ++ totalRectanglesSent += cl->rfbRectanglesSent[i]; ++ totalBytesSent += cl->rfbBytesSent[i]; ++ } ++ totalRectanglesSent += (cl->rfbCursorShapeUpdatesSent + ++ cl->rfbCursorPosUpdatesSent + ++ cl->rfbLastRectMarkersSent); ++ totalBytesSent += (cl->rfbCursorShapeBytesSent + ++ cl->rfbCursorPosBytesSent + ++ cl->rfbLastRectBytesSent); ++ ++ rfbLog(" framebuffer updates %d, rectangles %d, bytes %d\n", ++ cl->rfbFramebufferUpdateMessagesSent, totalRectanglesSent, ++ totalBytesSent); ++ ++ if (cl->rfbLastRectMarkersSent != 0) ++ rfbLog(" LastRect markers %d, bytes %d\n", ++ cl->rfbLastRectMarkersSent, cl->rfbLastRectBytesSent); ++ ++ if (cl->rfbCursorShapeUpdatesSent != 0) ++ rfbLog(" cursor shape updates %d, bytes %d\n", ++ cl->rfbCursorShapeUpdatesSent, cl->rfbCursorShapeBytesSent); ++ ++ if (cl->rfbCursorPosUpdatesSent != 0) ++ rfbLog(" cursor position updates %d, bytes %d\n", ++ cl->rfbCursorPosUpdatesSent, cl->rfbCursorPosBytesSent); ++ ++ for (i = 0; i < MAX_ENCODINGS; i++) { ++ if (cl->rfbRectanglesSent[i] != 0) ++ rfbLog(" %s rectangles %d, bytes %d\n", ++ encNames[i], cl->rfbRectanglesSent[i], cl->rfbBytesSent[i]); ++ } ++ ++ if ((totalBytesSent - cl->rfbBytesSent[rfbEncodingCopyRect]) != 0) { ++ rfbLog(" raw bytes equivalent %d, compression ratio %f\n", ++ cl->rfbRawBytesEquivalent, ++ (double)cl->rfbRawBytesEquivalent ++ / (double)(totalBytesSent - ++ cl->rfbBytesSent[rfbEncodingCopyRect] - ++ cl->rfbCursorShapeBytesSent - ++ cl->rfbCursorPosBytesSent - ++ cl->rfbLastRectBytesSent)); ++ } ++} +diff -pNur xorg-server-1.4.orig/hw/vnc/symlink-vnc.sh xorg-server-1.4/hw/vnc/symlink-vnc.sh +--- xorg-server-1.4.orig/hw/vnc/symlink-vnc.sh 1969-12-31 16:00:00.000000000 -0800 ++++ xorg-server-1.4/hw/vnc/symlink-vnc.sh 2007-09-06 16:09:45.000000000 -0700 +@@ -0,0 +1,198 @@ ++#!/bin/sh ++ ++# ++# A script that symlinks source files from vnc to modular ++# ++# Author: Soren Sandmann (sandmann@redhat.com) (original) ++# adapted for vnc by Alan Hourihane ++ ++# ++# Things we would like to do ++# ++# - Check that all the relevant files exist ++# - AUTHORS, autogen.sh, configure.ac, ... ++# - Check that we have actually linked everything ++# - if a file doesn't need to be linked, then it needs ++# to be listed as "not-linked" ++# - Compute diffs between all the files (shouldn't be necessary) ++# - possibly check that files are listet in Makefile.am's ++# - Clean target directory of irrelevant files ++# ++ ++check_destinations () { ++ # don't do anything - we are relying on the side ++ # effect of dst_dir ++ true ++} ++ ++check_exist() { ++ # Check whether $1 exists ++ ++ if [ ! -e $1 ] ; then ++ error "$1 not found" ++ fi ++} ++ ++delete_existing() { ++ # Delete $2 ++ ++ rm -f $2 ++} ++ ++link_files() { ++ # Link $1 to $2 ++ ++ if [ ! -e $2 ] ; then ++ ln -s $1 $2 ++ fi ++} ++ ++main() { ++ check_args $1 $2 ++ ++ run check_destinations "Creating destination directories" ++ run check_exist "Checking that the source files exist" ++ run delete_existing "Deleting existing files" ++ run link_files "Linking files" ++} ++ ++## actual symlinking ++ ++symlink_vnc() { ++ src_dir . ++ dst_dir . ++ action d3des.c ++ action d3des.h ++ action auth.c ++ action cmap.c ++ action corre.c ++ action cursor.c ++ action cutpaste.c ++ action dispcur.c ++ action draw.c ++ action hextile.c ++ action httpd.c ++ action kbdptr.c ++ action keyboard.h ++ action loginauth.c ++ action rdp.c ++ action rfb.h ++ action rfbkeyb.c ++ action rfbmouse.c ++ action rfbproto.h ++ action rfbserver.c ++ action rre.c ++ action sockets.c ++ action sprite.c ++ action sprite.h ++ action spritest.h ++ action stats.c ++ action tableinitcmtemplate.c ++ action tableinittctemplate.c ++ action tabletranstemplate.c ++ action tight.c ++ action translate.c ++ action vncauth.c ++ action vncauth.h ++ action vncext.c ++ action xistubs.c ++ action zlib.c ++} ++ ++######### ++# ++# Helper functions ++# ++######### ++ ++error() { ++ echo ++ echo \ \ \ error:\ \ \ $1 ++ exit 1 ++} ++ ++# printing out what's going on ++run_module() { ++ # $1 module ++ # $2 explanation ++ echo -n $EXPLANATION for $1 module ...\ ++ symlink_$1 ++ echo DONE ++} ++ ++run() { ++ # $1 what to do ++ # $2 explanation ++ ++ ACTION=$1 EXPLANATION=$2 run_module vnc ++} ++ ++src_dir() { ++ REAL_SRC_DIR=$SRC_DIR/$1 ++ if [ ! -d $REAL_SRC_DIR ] ; then ++ error "Source directory $REAL_SRC_DIR does not exist" ++ fi ++} ++ ++dst_dir() { ++ REAL_DST_DIR=$DST_DIR/$1 ++ if [ ! -d $REAL_DST_DIR ] ; then ++ mkdir -p $REAL_DST_DIR ++ fi ++} ++ ++action() { ++ if [ -z $2 ] ; then ++ $ACTION $REAL_SRC_DIR/$1 $REAL_DST_DIR/$1 ++ else ++ $ACTION $REAL_SRC_DIR/$1 $REAL_DST_DIR/$2 ++ fi ++} ++ ++usage() { ++ echo symlink.sh src-dir dst-dir ++ echo src-dir: the xc directory of the monolithic source tree ++ echo dst-dir: the modular source tree containing proto, app, lib, ... ++} ++ ++# Check commandline args ++check_args() { ++ if [ -z $1 ] ; then ++ echo Missing source dir ++ usage ++ exit 1 ++ fi ++ ++ if [ -z $2 ] ; then ++ echo Missing destination dir ++ usage ++ exit 1 ++ fi ++ ++ if [ ! -d $1 ] ; then ++ echo $1 is not a dir ++ usage ++ exit 1 ++ fi ++ ++ if [ ! -d $2 ] ; then ++ echo $2 is not a dir ++ usage ++ exit 1 ++ fi ++ ++ if [ $1 = $2 ] ; then ++ echo source and destination can\'t be the same ++ usage ++ exit 1 ++ fi ++ ++ D=`dirname "$relpath"` ++ B=`basename "$relpath"` ++ abspath="`cd \"$D\" 2>/dev/null && pwd || echo \"$D\"`/$B" ++ ++ SRC_DIR=`( cd $1 ; pwd )` ++ DST_DIR=`(cd $2 ; pwd )` ++} ++ ++main $1 $2 +diff -pNur xorg-server-1.4.orig/hw/vnc/tableinitcmtemplate.c xorg-server-1.4/hw/vnc/tableinitcmtemplate.c +--- xorg-server-1.4.orig/hw/vnc/tableinitcmtemplate.c 1969-12-31 16:00:00.000000000 -0800 ++++ xorg-server-1.4/hw/vnc/tableinitcmtemplate.c 2007-09-06 16:09:45.000000000 -0700 +@@ -0,0 +1,93 @@ ++/* ++ * tableinitcmtemplate.c - template for initialising lookup tables for ++ * translation from a colour map to true colour. ++ * ++ * This file shouldn't be compiled. It is included multiple times by ++ * translate.c, each time with a different definition of the macro OUT. ++ * For each value of OUT, this file defines a function which allocates an ++ * appropriately sized lookup table and initialises it. ++ * ++ * I know this code isn't nice to read because of all the macros, but ++ * efficiency is important here. ++ * ++ * Modified for XFree86 4.x by Alan Hourihane ++ */ ++ ++/* ++ * 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. ++ */ ++#ifdef HAVE_DIX_CONFIG_H ++#include ++#endif ++ ++ ++#if !defined(OUT) ++#error "This file shouldn't be compiled." ++#error "It is included as part of translate.c" ++#endif ++ ++#define OUT_T CONCAT2E(CARD,OUT) ++#define SwapOUT(x) CONCAT2E(Swap,OUT(x)) ++#define rfbInitColourMapSingleTableOUT \ ++ CONCAT2E(rfbInitColourMapSingleTable,OUT) ++ ++static void ++rfbInitColourMapSingleTableOUT (ScreenPtr pScreen, char **table, rfbPixelFormat *in, ++ rfbPixelFormat *out) ++{ ++ VNCSCREENPTR(pScreen); ++ int i, r, g, b; ++ OUT_T *t; ++ EntryPtr pent; ++ int nEntries = 1 << in->bitsPerPixel; ++ ++ if (*table) free(*table); ++ *table = (char *)malloc(nEntries * sizeof(OUT_T)); ++ t = (OUT_T *)*table; ++ ++#if XFREE86VNC ++ pent = (EntryPtr)&miInstalledMaps[pScreen->myNum]->red[0]; ++#else ++ pent = (EntryPtr)&pVNC->rfbInstalledColormap->red[0]; ++#endif ++ ++ for (i = 0; i < nEntries; i++) { ++ 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; ++ } ++ t[i] = ((((r * out->redMax + 32767) / 65535) << out->redShift) | ++ (((g * out->greenMax + 32767) / 65535) << out->greenShift) | ++ (((b * out->blueMax + 32767) / 65535) << out->blueShift)); ++#if (OUT != 8) ++ if (out->bigEndian != in->bigEndian) { ++ t[i] = SwapOUT(t[i]); ++ } ++#endif ++ pent++; ++ } ++} ++ ++#undef OUT_T ++#undef SwapOUT ++#undef rfbInitColourMapSingleTableOUT +diff -pNur xorg-server-1.4.orig/hw/vnc/tableinittctemplate.c xorg-server-1.4/hw/vnc/tableinittctemplate.c +--- xorg-server-1.4.orig/hw/vnc/tableinittctemplate.c 1969-12-31 16:00:00.000000000 -0800 ++++ xorg-server-1.4/hw/vnc/tableinittctemplate.c 2007-09-06 16:09:45.000000000 -0700 +@@ -0,0 +1,146 @@ ++/* ++ * tableinittctemplate.c - template for initialising lookup tables for ++ * truecolour to truecolour translation. ++ * ++ * This file shouldn't be compiled. It is included multiple times by ++ * translate.c, each time with a different definition of the macro OUT. ++ * For each value of OUT, this file defines two functions for initialising ++ * lookup tables. One is for truecolour translation using a single lookup ++ * table, the other is for truecolour translation using three separate ++ * lookup tables for the red, green and blue values. ++ * ++ * I know this code isn't nice to read because of all the macros, but ++ * efficiency is important here. ++ * ++ * Modified for XFree86 4.x by Alan Hourihane ++ */ ++ ++/* ++ * 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. ++ */ ++#ifdef HAVE_DIX_CONFIG_H ++#include ++#endif ++ ++ ++#if !defined(OUT) ++#error "This file shouldn't be compiled." ++#error "It is included as part of translate.c" ++#endif ++ ++#define OUT_T CONCAT2E(CARD,OUT) ++#define SwapOUT(x) CONCAT2E(Swap,OUT(x)) ++#define rfbInitTrueColourSingleTableOUT \ ++ CONCAT2E(rfbInitTrueColourSingleTable,OUT) ++#define rfbInitTrueColourRGBTablesOUT CONCAT2E(rfbInitTrueColourRGBTables,OUT) ++#define rfbInitOneRGBTableOUT CONCAT2E(rfbInitOneRGBTable,OUT) ++ ++static void ++rfbInitOneRGBTableOUT (OUT_T *table, int inMax, int outMax, int outShift, ++ int swap); ++ ++ ++/* ++ * rfbInitTrueColourSingleTable sets up a single lookup table for truecolour ++ * translation. ++ */ ++ ++static void ++rfbInitTrueColourSingleTableOUT (ScreenPtr pScreen, char **table, rfbPixelFormat *in, ++ rfbPixelFormat *out) ++{ ++ int i; ++ int inRed, inGreen, inBlue, outRed, outGreen, outBlue; ++ OUT_T *t; ++ int nEntries = 1 << in->bitsPerPixel; ++ ++ if (*table) free(*table); ++ *table = (char *)malloc(nEntries * sizeof(OUT_T)); ++ t = (OUT_T *)*table; ++ ++ for (i = 0; i < nEntries; i++) { ++ inRed = (i >> in->redShift) & in->redMax; ++ inGreen = (i >> in->greenShift) & in->greenMax; ++ inBlue = (i >> in->blueShift) & in->blueMax; ++ ++ outRed = (inRed * out->redMax + in->redMax / 2) / in->redMax; ++ outGreen = (inGreen * out->greenMax + in->greenMax / 2) / in->greenMax; ++ outBlue = (inBlue * out->blueMax + in->blueMax / 2) / in->blueMax; ++ ++ t[i] = ((outRed << out->redShift) | ++ (outGreen << out->greenShift) | ++ (outBlue << out->blueShift)); ++#if (OUT != 8) ++ if (out->bigEndian != in->bigEndian) { ++ t[i] = SwapOUT(t[i]); ++ } ++#endif ++ } ++} ++ ++ ++/* ++ * rfbInitTrueColourRGBTables sets up three separate lookup tables for the ++ * red, green and blue values. ++ */ ++ ++static void ++rfbInitTrueColourRGBTablesOUT (ScreenPtr pScreen, char **table, rfbPixelFormat *in, ++ rfbPixelFormat *out) ++{ ++ OUT_T *redTable; ++ OUT_T *greenTable; ++ OUT_T *blueTable; ++ ++ if (*table) free(*table); ++ *table = (char *)malloc((in->redMax + in->greenMax + in->blueMax + 3) ++ * sizeof(OUT_T)); ++ redTable = (OUT_T *)*table; ++ greenTable = redTable + in->redMax + 1; ++ blueTable = greenTable + in->greenMax + 1; ++ ++ rfbInitOneRGBTableOUT (redTable, in->redMax, out->redMax, ++ out->redShift, (out->bigEndian != in->bigEndian)); ++ rfbInitOneRGBTableOUT (greenTable, in->greenMax, out->greenMax, ++ out->greenShift, (out->bigEndian != in->bigEndian)); ++ rfbInitOneRGBTableOUT (blueTable, in->blueMax, out->blueMax, ++ out->blueShift, (out->bigEndian != in->bigEndian)); ++} ++ ++static void ++rfbInitOneRGBTableOUT (OUT_T *table, int inMax, int outMax, int outShift, ++ int swap) ++{ ++ int i; ++ int nEntries = inMax + 1; ++ ++ for (i = 0; i < nEntries; i++) { ++ table[i] = ((i * outMax + inMax / 2) / inMax) << outShift; ++#if (OUT != 8) ++ if (swap) { ++ table[i] = SwapOUT(table[i]); ++ } ++#endif ++ } ++} ++ ++#undef OUT_T ++#undef SwapOUT ++#undef rfbInitTrueColourSingleTableOUT ++#undef rfbInitTrueColourRGBTablesOUT ++#undef rfbInitOneRGBTableOUT +diff -pNur xorg-server-1.4.orig/hw/vnc/tabletranstemplate.c xorg-server-1.4/hw/vnc/tabletranstemplate.c +--- xorg-server-1.4.orig/hw/vnc/tabletranstemplate.c 1969-12-31 16:00:00.000000000 -0800 ++++ xorg-server-1.4/hw/vnc/tabletranstemplate.c 2007-09-06 16:09:45.000000000 -0700 +@@ -0,0 +1,135 @@ ++/* ++ * tabletranstemplate.c - template for translation using lookup tables. ++ * ++ * This file shouldn't be compiled. It is included multiple times by ++ * translate.c, each time with different definitions of the macros IN and OUT. ++ * ++ * For each pair of values IN and OUT, this file defines two functions for ++ * translating a given rectangle of pixel data. One uses a single lookup ++ * table, and the other uses three separate lookup tables for the red, green ++ * and blue values. ++ * ++ * I know this code isn't nice to read because of all the macros, but ++ * efficiency is important here. ++ * ++ * Modified for XFree86 4.x by Alan Hourihane ++ */ ++ ++/* ++ * 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. ++ */ ++#ifdef HAVE_DIX_CONFIG_H ++#include ++#endif ++ ++ ++#if !defined(IN) || !defined(OUT) ++#error "This file shouldn't be compiled." ++#error "It is included as part of translate.c" ++#endif ++ ++#define IN_T CONCAT2E(CARD,IN) ++#define OUT_T CONCAT2E(CARD,OUT) ++#define rfbTranslateWithSingleTableINtoOUT \ ++ CONCAT4E(rfbTranslateWithSingleTable,IN,to,OUT) ++#define rfbTranslateWithRGBTablesINtoOUT \ ++ CONCAT4E(rfbTranslateWithRGBTables,IN,to,OUT) ++ ++/* ++ * rfbTranslateWithSingleTableINtoOUT translates a rectangle of pixel data ++ * using a single lookup table. ++ */ ++ ++static void ++rfbTranslateWithSingleTableINtoOUT (ScreenPtr pScreen, char *table, rfbPixelFormat *in, ++ rfbPixelFormat *out, ++ unsigned char *optr, ++ int bytesBetweenInputLines, ++ int width, int height, ++ int x, int y) ++{ ++ IN_T *ip; ++ OUT_T *op = (OUT_T *)optr; ++ OUT_T *opLineEnd; ++ OUT_T *t = (OUT_T *)table; ++ DrawablePtr pDraw = (DrawablePtr)WindowTable[pScreen->myNum]; ++ int truewidth = PixmapBytePad(width, in->bitsPerPixel); ++ unsigned char *iptr = malloc(truewidth * height * in->bitsPerPixel / 8); ++ int ipextra = truewidth - width; ++ (*pScreen->GetImage)(pDraw, x, y, truewidth, height, ZPixmap, ~0, (char*)iptr); ++ ip = (IN_T *)iptr; ++ ++ while (height > 0) { ++ opLineEnd = op + width; ++ ++ while (op < opLineEnd) { ++ *(op++) = t[*(ip++)]; ++ } ++ ++ ip += ipextra; ++ height--; ++ } ++ free(iptr); ++} ++ ++ ++/* ++ * rfbTranslateWithRGBTablesINtoOUT translates a rectangle of pixel data ++ * using three separate lookup tables for the red, green and blue values. ++ */ ++ ++static void ++rfbTranslateWithRGBTablesINtoOUT (ScreenPtr pScreen, char *table, rfbPixelFormat *in, ++ rfbPixelFormat *out, ++ unsigned char *optr, ++ int bytesBetweenInputLines, ++ int width, int height, ++ int x, int y) ++{ ++ IN_T *ip; ++ OUT_T *op = (OUT_T *)optr; ++ OUT_T *opLineEnd; ++ OUT_T *redTable = (OUT_T *)table; ++ OUT_T *greenTable = redTable + in->redMax + 1; ++ OUT_T *blueTable = greenTable + in->greenMax + 1; ++ DrawablePtr pDraw = (DrawablePtr)WindowTable[pScreen->myNum]; ++ int truewidth = PixmapBytePad(width, in->bitsPerPixel); ++ unsigned char *iptr = malloc(truewidth * height * in->bitsPerPixel / 8); ++ int ipextra = truewidth - width; ++ (*pScreen->GetImage)(pDraw, x, y, truewidth, height, ZPixmap, ~0, (char*)iptr); ++ ip = (IN_T *)iptr; ++ ++ while (height > 0) { ++ opLineEnd = op + width; ++ ++ while (op < opLineEnd) { ++ *(op++) = (redTable[(*ip >> in->redShift) & in->redMax] | ++ greenTable[(*ip >> in->greenShift) & in->greenMax] | ++ blueTable[(*ip >> in->blueShift) & in->blueMax]); ++ ip++; ++ } ++ ip += ipextra; ++ height--; ++ } ++ free(iptr); ++} ++ ++#undef IN_T ++#undef OUT_T ++#undef rfbTranslateWithSingleTableINtoOUT ++#undef rfbTranslateWithRGBTablesINtoOUT +diff -pNur xorg-server-1.4.orig/hw/vnc/tight.c xorg-server-1.4/hw/vnc/tight.c +--- xorg-server-1.4.orig/hw/vnc/tight.c 1969-12-31 16:00:00.000000000 -0800 ++++ xorg-server-1.4/hw/vnc/tight.c 2007-09-06 16:09:45.000000000 -0700 +@@ -0,0 +1,1827 @@ ++/* ++ * tight.c ++ * ++ * Routines to implement Tight Encoding ++ * ++ * Modified for XFree86 4.x by Alan Hourihane ++ */ ++ ++/* ++ * Copyright (C) 2000, 2001 Const Kaplinsky. All Rights Reserved. ++ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. ++ * ++ * This is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This software is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this software; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, ++ * USA. ++ */ ++#ifdef HAVE_DIX_CONFIG_H ++#include ++#endif ++ ++ ++#include ++#include "rfb.h" ++#include ++ ++ ++/* Note: The following constant should not be changed. */ ++#define TIGHT_MIN_TO_COMPRESS 12 ++ ++/* The parameters below may be adjusted. */ ++#define MIN_SPLIT_RECT_SIZE 4096 ++#define MIN_SOLID_SUBRECT_SIZE 2048 ++#define MAX_SPLIT_TILE_SIZE 16 ++ ++/* May be set to TRUE with "-lazytight" Xvnc option. */ ++Bool rfbTightDisableGradient = FALSE; ++ ++/* This variable is set on every rfbSendRectEncodingTight() call. */ ++static Bool usePixelFormat24; ++ ++ ++/* Compression level stuff. The following array contains various ++ encoder parameters for each of 10 compression levels (0..9). ++ Last three parameters correspond to JPEG quality levels (0..9). */ ++ ++typedef struct TIGHT_CONF_s { ++ int maxRectSize, maxRectWidth; ++ int monoMinRectSize, gradientMinRectSize; ++ int idxZlibLevel, monoZlibLevel, rawZlibLevel, gradientZlibLevel; ++ int gradientThreshold, gradientThreshold24; ++ int idxMaxColorsDivisor; ++ int jpegQuality, jpegThreshold, jpegThreshold24; ++} TIGHT_CONF; ++ ++static TIGHT_CONF tightConf[10] = { ++ { 512, 32, 6, 65536, 0, 0, 0, 0, 0, 0, 4, 5, 10000, 23000 }, ++ { 2048, 128, 6, 65536, 1, 1, 1, 0, 0, 0, 8, 10, 8000, 18000 }, ++ { 6144, 256, 8, 65536, 3, 3, 2, 0, 0, 0, 24, 15, 6500, 15000 }, ++ { 10240, 1024, 12, 65536, 5, 5, 3, 0, 0, 0, 32, 25, 5000, 12000 }, ++ { 16384, 2048, 12, 65536, 6, 6, 4, 0, 0, 0, 32, 37, 4000, 10000 }, ++ { 32768, 2048, 12, 4096, 7, 7, 5, 4, 150, 380, 32, 50, 3000, 8000 }, ++ { 65536, 2048, 16, 4096, 7, 7, 6, 4, 170, 420, 48, 60, 2000, 5000 }, ++ { 65536, 2048, 16, 4096, 8, 8, 7, 5, 180, 450, 64, 70, 1000, 2500 }, ++ { 65536, 2048, 32, 8192, 9, 9, 8, 6, 190, 475, 64, 75, 500, 1200 }, ++ { 65536, 2048, 32, 8192, 9, 9, 9, 6, 200, 500, 96, 80, 200, 500 } ++}; ++ ++/* Stuff dealing with palettes. */ ++ ++typedef struct COLOR_LIST_s { ++ struct COLOR_LIST_s *next; ++ int idx; ++ CARD32 rgb; ++} COLOR_LIST; ++ ++typedef struct PALETTE_ENTRY_s { ++ COLOR_LIST *listNode; ++ int numPixels; ++} PALETTE_ENTRY; ++ ++typedef struct PALETTE_s { ++ PALETTE_ENTRY entry[256]; ++ COLOR_LIST *hash[256]; ++ COLOR_LIST list[256]; ++} PALETTE; ++ ++static int paletteNumColors, paletteMaxColors; ++static CARD32 monoBackground, monoForeground; ++static PALETTE palette; ++ ++/* Pointers to dynamically-allocated buffers. */ ++ ++static int tightBeforeBufSize = 0; ++static unsigned char *tightBeforeBuf = NULL; ++ ++static int tightAfterBufSize = 0; ++static unsigned char *tightAfterBuf = NULL; ++ ++static int *prevRowBuf = NULL; ++ ++ ++/* Prototypes for static functions. */ ++ ++static void FindBestSolidArea (ScreenPtr pScreen, int x, int y, int w, int h, ++ CARD32 colorValue, int *w_ptr, int *h_ptr); ++static void ExtendSolidArea (ScreenPtr pScreen, int x, int y, int w, int h, ++ CARD32 colorValue, ++ int *x_ptr, int *y_ptr, int *w_ptr, int *h_ptr); ++static Bool CheckSolidTile (ScreenPtr pScreen, int x, int y, int w, int h, ++ CARD32 *colorPtr, Bool needSameColor); ++static Bool CheckSolidTile8 (ScreenPtr pScreen, int x, int y, int w, int h, ++ CARD32 *colorPtr, Bool needSameColor); ++static Bool CheckSolidTile16 (ScreenPtr pScreen, int x, int y, int w, int h, ++ CARD32 *colorPtr, Bool needSameColor); ++static Bool CheckSolidTile32 (ScreenPtr pScreen, int x, int y, int w, int h, ++ CARD32 *colorPtr, Bool needSameColor); ++ ++static Bool SendRectSimple (rfbClientPtr cl, int x, int y, int w, int h); ++static Bool SendSubrect (rfbClientPtr cl, int x, int y, int w, int h); ++static Bool SendTightHeader (rfbClientPtr cl, int x, int y, int w, int h); ++ ++static Bool SendSolidRect (rfbClientPtr cl); ++static Bool SendMonoRect (rfbClientPtr cl, int w, int h); ++static Bool SendIndexedRect (rfbClientPtr cl, int w, int h); ++static Bool SendFullColorRect (rfbClientPtr cl, int w, int h); ++static Bool SendGradientRect (rfbClientPtr cl, int w, int h); ++ ++static Bool CompressData(rfbClientPtr cl, int streamId, int dataLen, ++ int zlibLevel, int zlibStrategy); ++static Bool SendCompressedData(rfbClientPtr cl, int compressedLen); ++ ++static void FillPalette8(int count); ++static void FillPalette16(int count); ++static void FillPalette32(int count); ++ ++static void PaletteReset(void); ++static int PaletteInsert(CARD32 rgb, int numPixels, int bpp); ++ ++static void Pack24(ScreenPtr pScreen, unsigned char *buf, rfbPixelFormat *fmt, int count); ++ ++static void EncodeIndexedRect16(CARD8 *buf, int count); ++static void EncodeIndexedRect32(CARD8 *buf, int count); ++ ++static void EncodeMonoRect8(CARD8 *buf, int w, int h); ++static void EncodeMonoRect16(CARD8 *buf, int w, int h); ++static void EncodeMonoRect32(CARD8 *buf, int w, int h); ++ ++static void FilterGradient24(ScreenPtr pScreen, unsigned char *buf, rfbPixelFormat *fmt, int w, int h); ++static void FilterGradient16(ScreenPtr pScreen, CARD16 *buf, rfbPixelFormat *fmt, int w, int h); ++static void FilterGradient32(ScreenPtr pScreen, CARD32 *buf, rfbPixelFormat *fmt, int w, int h); ++ ++static int DetectSmoothImage(rfbClientPtr cl, rfbPixelFormat *fmt, int w, int h); ++static unsigned long DetectSmoothImage24(rfbClientPtr cl, rfbPixelFormat *fmt, int w, int h); ++static unsigned long DetectSmoothImage16(rfbClientPtr cl, rfbPixelFormat *fmt, int w, int h); ++static unsigned long DetectSmoothImage32(rfbClientPtr cl, rfbPixelFormat *fmt, int w, int h); ++ ++static Bool SendJpegRect(rfbClientPtr cl, const CARD8 *buffer, int w, int h, int quality); ++static void PrepareRowForJpeg(ScreenPtr pScreen, CARD8 *dst, const CARD8 *buffer, int row, int width); ++static void PrepareRowForJpeg24(ScreenPtr pScreen, CARD8 *dst, const CARD8 *buffer, int row, int width); ++static void PrepareRowForJpeg16(ScreenPtr pScreen, CARD8 *dst, const CARD8 *buffer, int row, int width); ++static void PrepareRowForJpeg32(ScreenPtr pScreen, CARD8 *dst, const CARD8 *buffer, int row, int width); ++ ++static void JpegInitDestination(j_compress_ptr cinfo); ++static boolean JpegEmptyOutputBuffer(j_compress_ptr cinfo); ++static void JpegTermDestination(j_compress_ptr cinfo); ++static void JpegSetDstManager(j_compress_ptr cinfo); ++ ++ ++/* ++ * Tight encoding implementation. ++ */ ++ ++int ++rfbNumCodedRectsTight(cl, x, y, w, h) ++ rfbClientPtr cl; ++ int x, y, w, h; ++{ ++ int maxRectSize, maxRectWidth; ++ int subrectMaxWidth, subrectMaxHeight; ++ ++ /* No matter how many rectangles we will send if LastRect markers ++ are used to terminate rectangle stream. */ ++ if (cl->enableLastRectEncoding && w * h >= MIN_SPLIT_RECT_SIZE) ++ return 0; ++ ++ maxRectSize = tightConf[cl->tightCompressLevel].maxRectSize; ++ maxRectWidth = tightConf[cl->tightCompressLevel].maxRectWidth; ++ ++ if (w > maxRectWidth || w * h > maxRectSize) { ++ subrectMaxWidth = (w > maxRectWidth) ? maxRectWidth : w; ++ subrectMaxHeight = maxRectSize / subrectMaxWidth; ++ return (((w - 1) / maxRectWidth + 1) * ++ ((h - 1) / subrectMaxHeight + 1)); ++ } else { ++ return 1; ++ } ++} ++ ++Bool ++rfbSendRectEncodingTight(cl, x, y, w, h) ++ rfbClientPtr cl; ++ int x, y, w, h; ++{ ++ VNCSCREENPTR(cl->pScreen); ++ int nMaxRows; ++ CARD32 colorValue; ++ int dx, dy, dw, dh; ++ int x_best, y_best, w_best, h_best; ++ ++ if ( cl->format.depth == 24 && cl->format.redMax == 0xFF && ++ cl->format.greenMax == 0xFF && cl->format.blueMax == 0xFF ) { ++ usePixelFormat24 = TRUE; ++ } else { ++ usePixelFormat24 = FALSE; ++ } ++ ++ if (!cl->enableLastRectEncoding || w * h < MIN_SPLIT_RECT_SIZE) ++ return SendRectSimple(cl, x, y, w, h); ++ ++ /* Make sure we can write at least one pixel into tightBeforeBuf. */ ++ ++ if (tightBeforeBufSize < 4) { ++ tightBeforeBufSize = 4; ++ if (tightBeforeBuf == NULL) ++ tightBeforeBuf = (unsigned char *)xalloc(tightBeforeBufSize); ++ else ++ tightBeforeBuf = (unsigned char *)xrealloc(tightBeforeBuf, ++ tightBeforeBufSize); ++ } ++ ++ /* Calculate maximum number of rows in one non-solid rectangle. */ ++ ++ { ++ int maxRectSize, maxRectWidth, nMaxWidth; ++ ++ maxRectSize = tightConf[cl->tightCompressLevel].maxRectSize; ++ maxRectWidth = tightConf[cl->tightCompressLevel].maxRectWidth; ++ nMaxWidth = (w > maxRectWidth) ? maxRectWidth : w; ++ nMaxRows = maxRectSize / nMaxWidth; ++ } ++ ++ /* Try to find large solid-color areas and send them separately. */ ++ ++ for (dy = y; dy < y + h; dy += MAX_SPLIT_TILE_SIZE) { ++ ++ /* If a rectangle becomes too large, send its upper part now. */ ++ ++ if (dy - y >= nMaxRows) { ++ if (!SendRectSimple(cl, x, y, w, nMaxRows)) ++ return 0; ++ y += nMaxRows; ++ h -= nMaxRows; ++ } ++ ++ dh = (dy + MAX_SPLIT_TILE_SIZE <= y + h) ? ++ MAX_SPLIT_TILE_SIZE : (y + h - dy); ++ ++ for (dx = x; dx < x + w; dx += MAX_SPLIT_TILE_SIZE) { ++ ++ dw = (dx + MAX_SPLIT_TILE_SIZE <= x + w) ? ++ MAX_SPLIT_TILE_SIZE : (x + w - dx); ++ ++ if (CheckSolidTile(cl->pScreen, dx, dy, dw, dh, &colorValue, FALSE)) { ++ ++ /* Get dimensions of solid-color area. */ ++ ++ FindBestSolidArea(cl->pScreen, dx, dy, w - (dx - x), h - (dy - y), ++ colorValue, &w_best, &h_best); ++ ++ /* Make sure a solid rectangle is large enough ++ (or the whole rectangle is of the same color). */ ++ ++ if ( w_best * h_best != w * h && ++ w_best * h_best < MIN_SOLID_SUBRECT_SIZE ) ++ continue; ++ ++ /* Try to extend solid rectangle to maximum size. */ ++ ++ x_best = dx; y_best = dy; ++ ExtendSolidArea(cl->pScreen, x, y, w, h, colorValue, ++ &x_best, &y_best, &w_best, &h_best); ++ ++ /* Send rectangles at top and left to solid-color area. */ ++ ++ if ( y_best != y && ++ !SendRectSimple(cl, x, y, w, y_best-y) ) ++ return FALSE; ++ if ( x_best != x && ++ !rfbSendRectEncodingTight(cl, x, y_best, ++ x_best-x, h_best) ) ++ return FALSE; ++ ++ /* Send solid-color rectangle. */ ++ ++ if (!SendTightHeader(cl, x_best, y_best, w_best, h_best)) ++ return FALSE; ++ ++ (*cl->translateFn)(cl->pScreen, cl->translateLookupTable, ++ &pVNC->rfbServerFormat, ++ &cl->format, tightBeforeBuf, ++ pVNC->paddedWidthInBytes, 1, 1, ++ x_best, y_best); ++ ++ if (!SendSolidRect(cl)) ++ return FALSE; ++ ++ /* Send remaining rectangles (at right and bottom). */ ++ ++ if ( x_best + w_best != x + w && ++ !rfbSendRectEncodingTight(cl, x_best+w_best, y_best, ++ w-(x_best-x)-w_best, h_best) ) ++ return FALSE; ++ if ( y_best + h_best != y + h && ++ !rfbSendRectEncodingTight(cl, x, y_best+h_best, ++ w, h-(y_best-y)-h_best) ) ++ return FALSE; ++ ++ /* Return after all recursive calls are done. */ ++ ++ return TRUE; ++ } ++ ++ } ++ ++ } ++ ++ /* No suitable solid-color rectangles found. */ ++ ++ return SendRectSimple(cl, x, y, w, h); ++} ++ ++static void ++FindBestSolidArea(pScreen, x, y, w, h, colorValue, w_ptr, h_ptr) ++ ScreenPtr pScreen; ++ int x, y, w, h; ++ CARD32 colorValue; ++ int *w_ptr, *h_ptr; ++{ ++ int dx, dy, dw, dh; ++ int w_prev; ++ int w_best = 0, h_best = 0; ++ ++ w_prev = w; ++ ++ for (dy = y; dy < y + h; dy += MAX_SPLIT_TILE_SIZE) { ++ ++ dh = (dy + MAX_SPLIT_TILE_SIZE <= y + h) ? ++ MAX_SPLIT_TILE_SIZE : (y + h - dy); ++ dw = (w_prev > MAX_SPLIT_TILE_SIZE) ? ++ MAX_SPLIT_TILE_SIZE : w_prev; ++ ++ if (!CheckSolidTile(pScreen, x, dy, dw, dh, &colorValue, TRUE)) ++ break; ++ ++ for (dx = x + dw; dx < x + w_prev;) { ++ dw = (dx + MAX_SPLIT_TILE_SIZE <= x + w_prev) ? ++ MAX_SPLIT_TILE_SIZE : (x + w_prev - dx); ++ if (!CheckSolidTile(pScreen, dx, dy, dw, dh, &colorValue, TRUE)) ++ break; ++ dx += dw; ++ } ++ ++ w_prev = dx - x; ++ if (w_prev * (dy + dh - y) > w_best * h_best) { ++ w_best = w_prev; ++ h_best = dy + dh - y; ++ } ++ } ++ ++ *w_ptr = w_best; ++ *h_ptr = h_best; ++} ++ ++static void ++ExtendSolidArea(pScreen, x, y, w, h, colorValue, x_ptr, y_ptr, w_ptr, h_ptr) ++ ScreenPtr pScreen; ++ int x, y, w, h; ++ CARD32 colorValue; ++ int *x_ptr, *y_ptr, *w_ptr, *h_ptr; ++{ ++ int cx, cy; ++ ++ /* Try to extend the area upwards. */ ++ for ( cy = *y_ptr - 1; ++ cy >= y && CheckSolidTile(pScreen, *x_ptr, cy, *w_ptr, 1, &colorValue, TRUE); ++ cy-- ); ++ *h_ptr += *y_ptr - (cy + 1); ++ *y_ptr = cy + 1; ++ ++ /* ... downwards. */ ++ for ( cy = *y_ptr + *h_ptr; ++ cy < y + h && ++ CheckSolidTile(pScreen, *x_ptr, cy, *w_ptr, 1, &colorValue, TRUE); ++ cy++ ); ++ *h_ptr += cy - (*y_ptr + *h_ptr); ++ ++ /* ... to the left. */ ++ for ( cx = *x_ptr - 1; ++ cx >= x && CheckSolidTile(pScreen, cx, *y_ptr, 1, *h_ptr, &colorValue, TRUE); ++ cx-- ); ++ *w_ptr += *x_ptr - (cx + 1); ++ *x_ptr = cx + 1; ++ ++ /* ... to the right. */ ++ for ( cx = *x_ptr + *w_ptr; ++ cx < x + w && ++ CheckSolidTile(pScreen, cx, *y_ptr, 1, *h_ptr, &colorValue, TRUE); ++ cx++ ); ++ *w_ptr += cx - (*x_ptr + *w_ptr); ++} ++ ++/* ++ * Check if a rectangle is all of the same color. If needSameColor is ++ * set to non-zero, then also check that its color equals to the ++ * *colorPtr value. The result is 1 if the test is successfull, and in ++ * that case new color will be stored in *colorPtr. ++ */ ++ ++static Bool ++CheckSolidTile(pScreen, x, y, w, h, colorPtr, needSameColor) ++ ScreenPtr pScreen; ++ int x, y, w, h; ++ CARD32 *colorPtr; ++ Bool needSameColor; ++{ ++ VNCSCREENPTR(pScreen); ++ switch(pVNC->rfbServerFormat.bitsPerPixel) { ++ case 32: ++ return CheckSolidTile32(pScreen, x, y, w, h, colorPtr, needSameColor); ++ case 16: ++ return CheckSolidTile16(pScreen, x, y, w, h, colorPtr, needSameColor); ++ default: ++ return CheckSolidTile8(pScreen, x, y, w, h, colorPtr, needSameColor); ++ } ++} ++ ++#define DEFINE_CHECK_SOLID_FUNCTION(bpp) \ ++ \ ++static Bool \ ++CheckSolidTile##bpp(pScreen, x, y, w, h, colorPtr, needSameColor) \ ++ ScreenPtr pScreen; \ ++ int x, y; \ ++ CARD32 *colorPtr; \ ++ Bool needSameColor; \ ++{ \ ++ VNCSCREENPTR(pScreen); \ ++ CARD##bpp *fbptr; \ ++ CARD##bpp colorValue; \ ++ int dx, dy; \ ++ \ ++ fbptr = (CARD##bpp *) \ ++ &pVNC->pfbMemory[y * pVNC->paddedWidthInBytes + x * (bpp/8)]; \ ++ \ ++ colorValue = *fbptr; \ ++ if (needSameColor && (CARD32)colorValue != *colorPtr) \ ++ return FALSE; \ ++ \ ++ for (dy = 0; dy < h; dy++) { \ ++ for (dx = 0; dx < w; dx++) { \ ++ if (colorValue != fbptr[dx]) \ ++ return FALSE; \ ++ } \ ++ fbptr = (CARD##bpp *)((CARD8 *)fbptr + pVNC->paddedWidthInBytes); \ ++ } \ ++ \ ++ *colorPtr = (CARD32)colorValue; \ ++ return TRUE; \ ++} ++ ++DEFINE_CHECK_SOLID_FUNCTION(8) ++DEFINE_CHECK_SOLID_FUNCTION(16) ++DEFINE_CHECK_SOLID_FUNCTION(32) ++ ++static Bool ++SendRectSimple(cl, x, y, w, h) ++ rfbClientPtr cl; ++ int x, y, w, h; ++{ ++ int maxBeforeSize, maxAfterSize; ++ int maxRectSize, maxRectWidth; ++ int subrectMaxWidth, subrectMaxHeight; ++ int dx, dy; ++ int rw, rh; ++ ++ maxRectSize = tightConf[cl->tightCompressLevel].maxRectSize; ++ maxRectWidth = tightConf[cl->tightCompressLevel].maxRectWidth; ++ ++ maxBeforeSize = maxRectSize * (cl->format.bitsPerPixel / 8); ++ maxAfterSize = maxBeforeSize + (maxBeforeSize + 99) / 100 + 12; ++ ++ if (tightBeforeBufSize < maxBeforeSize) { ++ tightBeforeBufSize = maxBeforeSize; ++ if (tightBeforeBuf == NULL) ++ tightBeforeBuf = (unsigned char *)xalloc(tightBeforeBufSize); ++ else ++ tightBeforeBuf = (unsigned char *)xrealloc(tightBeforeBuf, ++ tightBeforeBufSize); ++ } ++ ++ if (tightAfterBufSize < maxAfterSize) { ++ tightAfterBufSize = maxAfterSize; ++ if (tightAfterBuf == NULL) ++ tightAfterBuf = (unsigned char *)xalloc(tightAfterBufSize); ++ else ++ tightAfterBuf = (unsigned char *)xrealloc(tightAfterBuf, ++ tightAfterBufSize); ++ } ++ ++ if (w > maxRectWidth || w * h > maxRectSize) { ++ subrectMaxWidth = (w > maxRectWidth) ? maxRectWidth : w; ++ subrectMaxHeight = maxRectSize / subrectMaxWidth; ++ ++ for (dy = 0; dy < h; dy += subrectMaxHeight) { ++ for (dx = 0; dx < w; dx += maxRectWidth) { ++ rw = (dx + maxRectWidth < w) ? maxRectWidth : w - dx; ++ rh = (dy + subrectMaxHeight < h) ? subrectMaxHeight : h - dy; ++ if (!SendSubrect(cl, x+dx, y+dy, rw, rh)) ++ return FALSE; ++ } ++ } ++ } else { ++ if (!SendSubrect(cl, x, y, w, h)) ++ return FALSE; ++ } ++ ++ return TRUE; ++} ++ ++static Bool ++SendSubrect(cl, x, y, w, h) ++ rfbClientPtr cl; ++ int x, y, w, h; ++{ ++ VNCSCREENPTR(cl->pScreen); ++ Bool success = FALSE; ++ ++ /* Send pending data if there is more than 128 bytes. */ ++ if (pVNC->ublen > 128) { ++ if (!rfbSendUpdateBuf(cl)) ++ return FALSE; ++ } ++ ++ if (!SendTightHeader(cl, x, y, w, h)) ++ return FALSE; ++ ++ (*cl->translateFn)(cl->pScreen, cl->translateLookupTable, &pVNC->rfbServerFormat, ++ &cl->format, tightBeforeBuf, ++ pVNC->paddedWidthInBytes, w, h, x, y); ++ ++ paletteMaxColors = w * h / tightConf[cl->tightCompressLevel].idxMaxColorsDivisor; ++ if ( paletteMaxColors < 2 && ++ w * h >= tightConf[cl->tightCompressLevel].monoMinRectSize ) { ++ paletteMaxColors = 2; ++ } ++ switch (cl->format.bitsPerPixel) { ++ case 8: ++ FillPalette8(w * h); ++ break; ++ case 16: ++ FillPalette16(w * h); ++ break; ++ default: ++ FillPalette32(w * h); ++ } ++ ++ switch (paletteNumColors) { ++ case 0: ++ /* Truecolor image */ ++ if (DetectSmoothImage(cl, &cl->format, w, h)) { ++ if (cl->tightQualityLevel != -1) { ++ success = SendJpegRect(cl, tightBeforeBuf, w, h, ++ tightConf[cl->tightQualityLevel].jpegQuality); ++ } else { ++ success = SendGradientRect(cl, w, h); ++ } ++ } else { ++ success = SendFullColorRect(cl, w, h); ++ } ++ break; ++ case 1: ++ /* Solid rectangle */ ++ success = SendSolidRect(cl); ++ break; ++ case 2: ++ /* Two-color rectangle */ ++ success = SendMonoRect(cl, w, h); ++ break; ++ default: ++ /* Up to 256 different colors */ ++ if ( paletteNumColors > 96 && ++ cl->tightQualityLevel != -1 && cl->tightQualityLevel <= 3 && ++ DetectSmoothImage(cl, &cl->format, w, h) ) { ++ success = SendJpegRect(cl, tightBeforeBuf, w, h, ++ tightConf[cl->tightQualityLevel].jpegQuality); ++ } else { ++ success = SendIndexedRect(cl, w, h); ++ } ++ } ++ return success; ++} ++ ++static Bool ++SendTightHeader(cl, x, y, w, h) ++ rfbClientPtr cl; ++ int x, y, w, h; ++{ ++ VNCSCREENPTR(cl->pScreen); ++ rfbFramebufferUpdateRectHeader rect; ++ ++ if (pVNC->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) { ++ if (!rfbSendUpdateBuf(cl)) ++ return FALSE; ++ } ++ ++ rect.r.x = Swap16IfLE(x); ++ rect.r.y = Swap16IfLE(y); ++ rect.r.w = Swap16IfLE(w); ++ rect.r.h = Swap16IfLE(h); ++ rect.encoding = Swap32IfLE(rfbEncodingTight); ++ ++ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&rect, ++ sz_rfbFramebufferUpdateRectHeader); ++ pVNC->ublen += sz_rfbFramebufferUpdateRectHeader; ++ ++ cl->rfbRectanglesSent[rfbEncodingTight]++; ++ cl->rfbBytesSent[rfbEncodingTight] += sz_rfbFramebufferUpdateRectHeader; ++ ++ return TRUE; ++} ++ ++/* ++ * Subencoding implementations. ++ */ ++ ++static Bool ++SendSolidRect(cl) ++ rfbClientPtr cl; ++{ ++ VNCSCREENPTR(cl->pScreen); ++ int len; ++ ++ if (usePixelFormat24) { ++ Pack24(cl->pScreen, tightBeforeBuf, &cl->format, 1); ++ len = 3; ++ } else ++ len = cl->format.bitsPerPixel / 8; ++ ++ if (pVNC->ublen + 1 + len > UPDATE_BUF_SIZE) { ++ if (!rfbSendUpdateBuf(cl)) ++ return FALSE; ++ } ++ ++ pVNC->updateBuf[pVNC->ublen++] = (char)(rfbTightFill << 4); ++ memcpy (&pVNC->updateBuf[pVNC->ublen], tightBeforeBuf, len); ++ pVNC->ublen += len; ++ ++ cl->rfbBytesSent[rfbEncodingTight] += len + 1; ++ ++ return TRUE; ++} ++ ++static Bool ++SendMonoRect(cl, w, h) ++ rfbClientPtr cl; ++ int w, h; ++{ ++ VNCSCREENPTR(cl->pScreen); ++ int streamId = 1; ++ int paletteLen, dataLen; ++ ++ if ( (pVNC->ublen + TIGHT_MIN_TO_COMPRESS + 6 + ++ 2 * cl->format.bitsPerPixel / 8) > UPDATE_BUF_SIZE ) { ++ if (!rfbSendUpdateBuf(cl)) ++ return FALSE; ++ } ++ ++ /* Prepare tight encoding header. */ ++ dataLen = (w + 7) / 8; ++ dataLen *= h; ++ ++ pVNC->updateBuf[pVNC->ublen++] = (streamId | rfbTightExplicitFilter) << 4; ++ pVNC->updateBuf[pVNC->ublen++] = rfbTightFilterPalette; ++ pVNC->updateBuf[pVNC->ublen++] = 1; ++ ++ /* Prepare palette, convert image. */ ++ switch (cl->format.bitsPerPixel) { ++ ++ case 32: ++ EncodeMonoRect32((CARD8 *)tightBeforeBuf, w, h); ++ ++ ((CARD32 *)tightAfterBuf)[0] = monoBackground; ++ ((CARD32 *)tightAfterBuf)[1] = monoForeground; ++ if (usePixelFormat24) { ++ Pack24(cl->pScreen, tightAfterBuf, &cl->format, 2); ++ paletteLen = 6; ++ } else ++ paletteLen = 8; ++ ++ memcpy(&pVNC->updateBuf[pVNC->ublen], tightAfterBuf, paletteLen); ++ pVNC->ublen += paletteLen; ++ cl->rfbBytesSent[rfbEncodingTight] += 3 + paletteLen; ++ break; ++ ++ case 16: ++ EncodeMonoRect16((CARD8 *)tightBeforeBuf, w, h); ++ ++ ((CARD16 *)tightAfterBuf)[0] = (CARD16)monoBackground; ++ ((CARD16 *)tightAfterBuf)[1] = (CARD16)monoForeground; ++ ++ memcpy(&pVNC->updateBuf[pVNC->ublen], tightAfterBuf, 4); ++ pVNC->ublen += 4; ++ cl->rfbBytesSent[rfbEncodingTight] += 7; ++ break; ++ ++ default: ++ EncodeMonoRect8((CARD8 *)tightBeforeBuf, w, h); ++ ++ pVNC->updateBuf[pVNC->ublen++] = (char)monoBackground; ++ pVNC->updateBuf[pVNC->ublen++] = (char)monoForeground; ++ cl->rfbBytesSent[rfbEncodingTight] += 5; ++ } ++ ++ return CompressData(cl, streamId, dataLen, ++ tightConf[cl->tightCompressLevel].monoZlibLevel, ++ Z_DEFAULT_STRATEGY); ++} ++ ++static Bool ++SendIndexedRect(cl, w, h) ++ rfbClientPtr cl; ++ int w, h; ++{ ++ VNCSCREENPTR(cl->pScreen); ++ int streamId = 2; ++ int i, entryLen; ++ ++ if ( (pVNC->ublen + TIGHT_MIN_TO_COMPRESS + 6 + ++ paletteNumColors * cl->format.bitsPerPixel / 8) > UPDATE_BUF_SIZE ) { ++ if (!rfbSendUpdateBuf(cl)) ++ return FALSE; ++ } ++ ++ /* Prepare tight encoding header. */ ++ pVNC->updateBuf[pVNC->ublen++] = (streamId | rfbTightExplicitFilter) << 4; ++ pVNC->updateBuf[pVNC->ublen++] = rfbTightFilterPalette; ++ pVNC->updateBuf[pVNC->ublen++] = (char)(paletteNumColors - 1); ++ ++ /* Prepare palette, convert image. */ ++ switch (cl->format.bitsPerPixel) { ++ ++ case 32: ++ EncodeIndexedRect32((CARD8 *)tightBeforeBuf, w * h); ++ ++ for (i = 0; i < paletteNumColors; i++) { ++ ((CARD32 *)tightAfterBuf)[i] = ++ palette.entry[i].listNode->rgb; ++ } ++ if (usePixelFormat24) { ++ Pack24(cl->pScreen, tightAfterBuf, &cl->format, paletteNumColors); ++ entryLen = 3; ++ } else ++ entryLen = 4; ++ ++ memcpy(&pVNC->updateBuf[pVNC->ublen], tightAfterBuf, paletteNumColors * entryLen); ++ pVNC->ublen += paletteNumColors * entryLen; ++ cl->rfbBytesSent[rfbEncodingTight] += 3 + paletteNumColors * entryLen; ++ break; ++ ++ case 16: ++ EncodeIndexedRect16((CARD8 *)tightBeforeBuf, w * h); ++ ++ for (i = 0; i < paletteNumColors; i++) { ++ ((CARD16 *)tightAfterBuf)[i] = ++ (CARD16)palette.entry[i].listNode->rgb; ++ } ++ ++ memcpy(&pVNC->updateBuf[pVNC->ublen], tightAfterBuf, paletteNumColors * 2); ++ pVNC->ublen += paletteNumColors * 2; ++ cl->rfbBytesSent[rfbEncodingTight] += 3 + paletteNumColors * 2; ++ break; ++ ++ default: ++ return FALSE; /* Should never happen. */ ++ } ++ ++ return CompressData(cl, streamId, w * h, ++ tightConf[cl->tightCompressLevel].idxZlibLevel, ++ Z_DEFAULT_STRATEGY); ++} ++ ++static Bool ++SendFullColorRect(cl, w, h) ++ rfbClientPtr cl; ++ int w, h; ++{ ++ VNCSCREENPTR(cl->pScreen); ++ int streamId = 0; ++ int len; ++ ++ if (pVNC->ublen + TIGHT_MIN_TO_COMPRESS + 1 > UPDATE_BUF_SIZE) { ++ if (!rfbSendUpdateBuf(cl)) ++ return FALSE; ++ } ++ ++ pVNC->updateBuf[pVNC->ublen++] = 0x00; /* stream id = 0, no flushing, no filter */ ++ cl->rfbBytesSent[rfbEncodingTight]++; ++ ++ if (usePixelFormat24) { ++ Pack24(cl->pScreen, tightBeforeBuf, &cl->format, w * h); ++ len = 3; ++ } else ++ len = cl->format.bitsPerPixel / 8; ++ ++ return CompressData(cl, streamId, w * h * len, ++ tightConf[cl->tightCompressLevel].rawZlibLevel, ++ Z_DEFAULT_STRATEGY); ++} ++ ++static Bool ++SendGradientRect(cl, w, h) ++ rfbClientPtr cl; ++ int w, h; ++{ ++ VNCSCREENPTR(cl->pScreen); ++ int streamId = 3; ++ int len; ++ ++ if (cl->format.bitsPerPixel == 8) ++ return SendFullColorRect(cl, w, h); ++ ++ if (pVNC->ublen + TIGHT_MIN_TO_COMPRESS + 2 > UPDATE_BUF_SIZE) { ++ if (!rfbSendUpdateBuf(cl)) ++ return FALSE; ++ } ++ ++ if (prevRowBuf == NULL) ++ prevRowBuf = (int *)xalloc(2048 * 3 * sizeof(int)); ++ ++ pVNC->updateBuf[pVNC->ublen++] = (streamId | rfbTightExplicitFilter) << 4; ++ pVNC->updateBuf[pVNC->ublen++] = rfbTightFilterGradient; ++ cl->rfbBytesSent[rfbEncodingTight] += 2; ++ ++ if (usePixelFormat24) { ++ FilterGradient24(cl->pScreen, tightBeforeBuf, &cl->format, w, h); ++ len = 3; ++ } else if (cl->format.bitsPerPixel == 32) { ++ FilterGradient32(cl->pScreen, (CARD32 *)tightBeforeBuf, &cl->format, w, h); ++ len = 4; ++ } else { ++ FilterGradient16(cl->pScreen, (CARD16 *)tightBeforeBuf, &cl->format, w, h); ++ len = 2; ++ } ++ ++ return CompressData(cl, streamId, w * h * len, ++ tightConf[cl->tightCompressLevel].gradientZlibLevel, ++ Z_FILTERED); ++} ++ ++/** ++ * Compress the data in the tightBeforeBuf buffer. ++ * \param dataLen - amount of data in tightBeforeBuf to compress, in bytes ++ */ ++static Bool ++CompressData(cl, streamId, dataLen, zlibLevel, zlibStrategy) ++ rfbClientPtr cl; ++ int streamId, dataLen, zlibLevel, zlibStrategy; ++{ ++ VNCSCREENPTR(cl->pScreen); ++ z_streamp pz; ++ int err; ++ ++ if (dataLen < TIGHT_MIN_TO_COMPRESS) { ++ memcpy(&pVNC->updateBuf[pVNC->ublen], tightBeforeBuf, dataLen); ++ pVNC->ublen += dataLen; ++ cl->rfbBytesSent[rfbEncodingTight] += dataLen; ++ return TRUE; ++ } ++ ++ pz = &cl->zsStruct[streamId]; ++ ++ /* Initialize compression stream if needed. */ ++ if (!cl->zsActive[streamId]) { ++ pz->zalloc = Z_NULL; ++ pz->zfree = Z_NULL; ++ pz->opaque = Z_NULL; ++ ++ err = deflateInit2 (pz, zlibLevel, Z_DEFLATED, MAX_WBITS, ++ MAX_MEM_LEVEL, zlibStrategy); ++ if (err != Z_OK) ++ return FALSE; ++ ++ cl->zsActive[streamId] = TRUE; ++ cl->zsLevel[streamId] = zlibLevel; ++ } ++ ++ /* Prepare buffer pointers. */ ++ pz->next_in = (Bytef *)tightBeforeBuf; ++ pz->avail_in = dataLen; ++ pz->next_out = (Bytef *)tightAfterBuf; ++ pz->avail_out = tightAfterBufSize; ++ ++ /* Change compression parameters if needed. */ ++ if (zlibLevel != cl->zsLevel[streamId]) { ++ if (deflateParams (pz, zlibLevel, zlibStrategy) != Z_OK) { ++ return FALSE; ++ } ++ cl->zsLevel[streamId] = zlibLevel; ++ } ++ ++ /* Actual compression. */ ++ if ( deflate (pz, Z_SYNC_FLUSH) != Z_OK || ++ pz->avail_in != 0 || pz->avail_out == 0 ) { ++ return FALSE; ++ } ++ ++ return SendCompressedData(cl, tightAfterBufSize - pz->avail_out); ++} ++ ++static Bool SendCompressedData(cl, compressedLen) ++ rfbClientPtr cl; ++ int compressedLen; ++{ ++ VNCSCREENPTR(cl->pScreen); ++ int i, portionLen; ++ ++ pVNC->updateBuf[pVNC->ublen++] = compressedLen & 0x7F; ++ cl->rfbBytesSent[rfbEncodingTight]++; ++ if (compressedLen > 0x7F) { ++ pVNC->updateBuf[pVNC->ublen-1] |= 0x80; ++ pVNC->updateBuf[pVNC->ublen++] = compressedLen >> 7 & 0x7F; ++ cl->rfbBytesSent[rfbEncodingTight]++; ++ if (compressedLen > 0x3FFF) { ++ pVNC->updateBuf[pVNC->ublen-1] |= 0x80; ++ pVNC->updateBuf[pVNC->ublen++] = compressedLen >> 14 & 0xFF; ++ cl->rfbBytesSent[rfbEncodingTight]++; ++ } ++ } ++ ++ portionLen = UPDATE_BUF_SIZE; ++ for (i = 0; i < compressedLen; i += portionLen) { ++ if (i + portionLen > compressedLen) { ++ portionLen = compressedLen - i; ++ } ++ if (pVNC->ublen + portionLen > UPDATE_BUF_SIZE) { ++ if (!rfbSendUpdateBuf(cl)) ++ return FALSE; ++ } ++ memcpy(&pVNC->updateBuf[pVNC->ublen], &tightAfterBuf[i], portionLen); ++ pVNC->ublen += portionLen; ++ } ++ cl->rfbBytesSent[rfbEncodingTight] += compressedLen; ++ return TRUE; ++} ++ ++/* ++ * Code to determine how many different colors used in rectangle. ++ */ ++ ++static void ++FillPalette8(count) ++ int count; ++{ ++ CARD8 *data = (CARD8 *)tightBeforeBuf; ++ CARD8 c0, c1; ++ int i, n0, n1; ++ ++ paletteNumColors = 0; ++ ++ c0 = data[0]; ++ for (i = 1; i < count && data[i] == c0; i++); ++ if (i == count) { ++ paletteNumColors = 1; ++ return; /* Solid rectangle */ ++ } ++ ++ if (paletteMaxColors < 2) ++ return; ++ ++ n0 = i; ++ c1 = data[i]; ++ n1 = 0; ++ for (i++; i < count; i++) { ++ if (data[i] == c0) { ++ n0++; ++ } else if (data[i] == c1) { ++ n1++; ++ } else ++ break; ++ } ++ if (i == count) { ++ if (n0 > n1) { ++ monoBackground = (CARD32)c0; ++ monoForeground = (CARD32)c1; ++ } else { ++ monoBackground = (CARD32)c1; ++ monoForeground = (CARD32)c0; ++ } ++ paletteNumColors = 2; /* Two colors */ ++ } ++} ++ ++#define DEFINE_FILL_PALETTE_FUNCTION(bpp) \ ++ \ ++static void \ ++FillPalette##bpp(count) \ ++ int count; \ ++{ \ ++ CARD##bpp *data = (CARD##bpp *)tightBeforeBuf; \ ++ CARD##bpp c0, c1, ci = 0; \ ++ int i, n0, n1, ni; \ ++ \ ++ c0 = data[0]; \ ++ for (i = 1; i < count && data[i] == c0; i++); \ ++ if (i >= count) { \ ++ paletteNumColors = 1; /* Solid rectangle */ \ ++ return; \ ++ } \ ++ \ ++ if (paletteMaxColors < 2) { \ ++ paletteNumColors = 0; /* Full-color encoding preferred */ \ ++ return; \ ++ } \ ++ \ ++ n0 = i; \ ++ c1 = data[i]; \ ++ n1 = 0; \ ++ for (i++; i < count; i++) { \ ++ ci = data[i]; \ ++ if (ci == c0) { \ ++ n0++; \ ++ } else if (ci == c1) { \ ++ n1++; \ ++ } else \ ++ break; \ ++ } \ ++ if (i >= count) { \ ++ if (n0 > n1) { \ ++ monoBackground = (CARD32)c0; \ ++ monoForeground = (CARD32)c1; \ ++ } else { \ ++ monoBackground = (CARD32)c1; \ ++ monoForeground = (CARD32)c0; \ ++ } \ ++ paletteNumColors = 2; /* Two colors */ \ ++ return; \ ++ } \ ++ \ ++ PaletteReset(); \ ++ PaletteInsert (c0, (CARD32)n0, bpp); \ ++ PaletteInsert (c1, (CARD32)n1, bpp); \ ++ \ ++ ni = 1; \ ++ for (i++; i < count; i++) { \ ++ if (data[i] == ci) { \ ++ ni++; \ ++ } else { \ ++ if (!PaletteInsert (ci, (CARD32)ni, bpp)) \ ++ return; \ ++ ci = data[i]; \ ++ ni = 1; \ ++ } \ ++ } \ ++ PaletteInsert (ci, (CARD32)ni, bpp); \ ++} ++ ++DEFINE_FILL_PALETTE_FUNCTION(16) ++DEFINE_FILL_PALETTE_FUNCTION(32) ++ ++ ++/* ++ * Functions to operate with palette structures. ++ */ ++ ++#define HASH_FUNC16(rgb) ((int)((((rgb) >> 8) + (rgb)) & 0xFF)) ++#define HASH_FUNC32(rgb) ((int)((((rgb) >> 16) + ((rgb) >> 8)) & 0xFF)) ++ ++static void ++PaletteReset(void) ++{ ++ paletteNumColors = 0; ++ memset(palette.hash, 0, 256 * sizeof(COLOR_LIST *)); ++} ++ ++static int ++PaletteInsert(CARD32 rgb, int numPixels, int bpp) ++{ ++ COLOR_LIST *pnode; ++ COLOR_LIST *prev_pnode = NULL; ++ int hash_key, idx, new_idx, count; ++ ++ hash_key = (bpp == 16) ? HASH_FUNC16(rgb) : HASH_FUNC32(rgb); ++ ++ pnode = palette.hash[hash_key]; ++ ++ while (pnode != NULL) { ++ if (pnode->rgb == rgb) { ++ /* Such palette entry already exists. */ ++ new_idx = idx = pnode->idx; ++ count = palette.entry[idx].numPixels + numPixels; ++ if (new_idx && palette.entry[new_idx-1].numPixels < count) { ++ do { ++ palette.entry[new_idx] = palette.entry[new_idx-1]; ++ palette.entry[new_idx].listNode->idx = new_idx; ++ new_idx--; ++ } ++ while (new_idx && palette.entry[new_idx-1].numPixels < count); ++ palette.entry[new_idx].listNode = pnode; ++ pnode->idx = new_idx; ++ } ++ palette.entry[new_idx].numPixels = count; ++ return paletteNumColors; ++ } ++ prev_pnode = pnode; ++ pnode = pnode->next; ++ } ++ ++ /* Check if palette is full. */ ++ if (paletteNumColors == 256 || paletteNumColors == paletteMaxColors) { ++ paletteNumColors = 0; ++ return 0; ++ } ++ ++ /* Move palette entries with lesser pixel counts. */ ++ for ( idx = paletteNumColors; ++ idx > 0 && palette.entry[idx-1].numPixels < numPixels; ++ idx-- ) { ++ palette.entry[idx] = palette.entry[idx-1]; ++ palette.entry[idx].listNode->idx = idx; ++ } ++ ++ /* Add new palette entry into the freed slot. */ ++ pnode = &palette.list[paletteNumColors]; ++ if (prev_pnode != NULL) { ++ prev_pnode->next = pnode; ++ } else { ++ palette.hash[hash_key] = pnode; ++ } ++ pnode->next = NULL; ++ pnode->idx = idx; ++ pnode->rgb = rgb; ++ palette.entry[idx].listNode = pnode; ++ palette.entry[idx].numPixels = numPixels; ++ ++ return (++paletteNumColors); ++} ++ ++ ++/* ++ * Converting 32-bit color samples into 24-bit colors. ++ * Should be called only when redMax, greenMax and blueMax are 255. ++ * Color components assumed to be byte-aligned. ++ */ ++ ++static void Pack24(pScreen, buf, fmt, count) ++ ScreenPtr pScreen; ++ unsigned char *buf; ++ rfbPixelFormat *fmt; ++ int count; ++{ ++ VNCSCREENPTR(pScreen); ++ CARD32 *buf32; ++ CARD32 pix; ++ int r_shift, g_shift, b_shift; ++ ++ buf32 = (CARD32 *)buf; ++ ++ if (!pVNC->rfbServerFormat.bigEndian == !fmt->bigEndian) { ++ r_shift = fmt->redShift; ++ g_shift = fmt->greenShift; ++ b_shift = fmt->blueShift; ++ } else { ++ r_shift = 24 - fmt->redShift; ++ g_shift = 24 - fmt->greenShift; ++ b_shift = 24 - fmt->blueShift; ++ } ++ ++ while (count--) { ++ pix = *buf32++; ++ *buf++ = (char)(pix >> r_shift); ++ *buf++ = (char)(pix >> g_shift); ++ *buf++ = (char)(pix >> b_shift); ++ } ++} ++ ++ ++/* ++ * Converting truecolor samples into palette indices. ++ */ ++ ++#define DEFINE_IDX_ENCODE_FUNCTION(bpp) \ ++ \ ++static void \ ++EncodeIndexedRect##bpp(buf, count) \ ++ CARD8 *buf; \ ++ int count; \ ++{ \ ++ COLOR_LIST *pnode; \ ++ CARD##bpp *src; \ ++ CARD##bpp rgb; \ ++ int rep = 0; \ ++ \ ++ src = (CARD##bpp *) buf; \ ++ \ ++ while (count--) { \ ++ rgb = *src++; \ ++ while (count && *src == rgb) { \ ++ rep++, src++, count--; \ ++ } \ ++ pnode = palette.hash[HASH_FUNC##bpp(rgb)]; \ ++ while (pnode != NULL) { \ ++ if ((CARD##bpp)pnode->rgb == rgb) { \ ++ *buf++ = (CARD8)pnode->idx; \ ++ while (rep) { \ ++ *buf++ = (CARD8)pnode->idx; \ ++ rep--; \ ++ } \ ++ break; \ ++ } \ ++ pnode = pnode->next; \ ++ } \ ++ } \ ++} ++ ++DEFINE_IDX_ENCODE_FUNCTION(16) ++DEFINE_IDX_ENCODE_FUNCTION(32) ++ ++#define DEFINE_MONO_ENCODE_FUNCTION(bpp) \ ++ \ ++static void \ ++EncodeMonoRect##bpp(buf, w, h) \ ++ CARD8 *buf; \ ++ int w, h; \ ++{ \ ++ CARD##bpp *ptr; \ ++ CARD##bpp bg; \ ++ unsigned int value, mask; \ ++ int aligned_width; \ ++ int x, y, bg_bits; \ ++ \ ++ ptr = (CARD##bpp *) buf; \ ++ bg = (CARD##bpp) monoBackground; \ ++ aligned_width = w - w % 8; \ ++ \ ++ for (y = 0; y < h; y++) { \ ++ for (x = 0; x < aligned_width; x += 8) { \ ++ for (bg_bits = 0; bg_bits < 8; bg_bits++) { \ ++ if (*ptr++ != bg) \ ++ break; \ ++ } \ ++ if (bg_bits == 8) { \ ++ *buf++ = 0; \ ++ continue; \ ++ } \ ++ mask = 0x80 >> bg_bits; \ ++ value = mask; \ ++ for (bg_bits++; bg_bits < 8; bg_bits++) { \ ++ mask >>= 1; \ ++ if (*ptr++ != bg) { \ ++ value |= mask; \ ++ } \ ++ } \ ++ *buf++ = (CARD8)value; \ ++ } \ ++ \ ++ mask = 0x80; \ ++ value = 0; \ ++ if (x >= w) \ ++ continue; \ ++ \ ++ for (; x < w; x++) { \ ++ if (*ptr++ != bg) { \ ++ value |= mask; \ ++ } \ ++ mask >>= 1; \ ++ } \ ++ *buf++ = (CARD8)value; \ ++ } \ ++} ++ ++DEFINE_MONO_ENCODE_FUNCTION(8) ++DEFINE_MONO_ENCODE_FUNCTION(16) ++DEFINE_MONO_ENCODE_FUNCTION(32) ++ ++ ++/* ++ * ``Gradient'' filter for 24-bit color samples. ++ * Should be called only when redMax, greenMax and blueMax are 255. ++ * Color components assumed to be byte-aligned. ++ */ ++ ++static void ++FilterGradient24(pScreen, buf, fmt, w, h) ++ ScreenPtr pScreen; ++ unsigned char *buf; ++ rfbPixelFormat *fmt; ++ int w, h; ++{ ++ VNCSCREENPTR(pScreen); ++ CARD32 *buf32; ++ CARD32 pix32; ++ int *prevRowPtr; ++ int shiftBits[3]; ++ int pixHere[3], pixUpper[3], pixLeft[3], pixUpperLeft[3]; ++ int prediction; ++ int x, y, c; ++ ++ buf32 = (CARD32 *)buf; ++ memset (prevRowBuf, 0, w * 3 * sizeof(int)); ++ ++ if (!pVNC->rfbServerFormat.bigEndian == !fmt->bigEndian) { ++ shiftBits[0] = fmt->redShift; ++ shiftBits[1] = fmt->greenShift; ++ shiftBits[2] = fmt->blueShift; ++ } else { ++ shiftBits[0] = 24 - fmt->redShift; ++ shiftBits[1] = 24 - fmt->greenShift; ++ shiftBits[2] = 24 - fmt->blueShift; ++ } ++ ++ for (y = 0; y < h; y++) { ++ for (c = 0; c < 3; c++) { ++ pixUpper[c] = 0; ++ pixHere[c] = 0; ++ } ++ prevRowPtr = prevRowBuf; ++ for (x = 0; x < w; x++) { ++ pix32 = *buf32++; ++ for (c = 0; c < 3; c++) { ++ pixUpperLeft[c] = pixUpper[c]; ++ pixLeft[c] = pixHere[c]; ++ pixUpper[c] = *prevRowPtr; ++ pixHere[c] = (int)(pix32 >> shiftBits[c] & 0xFF); ++ *prevRowPtr++ = pixHere[c]; ++ ++ prediction = pixLeft[c] + pixUpper[c] - pixUpperLeft[c]; ++ if (prediction < 0) { ++ prediction = 0; ++ } else if (prediction > 0xFF) { ++ prediction = 0xFF; ++ } ++ *buf++ = (char)(pixHere[c] - prediction); ++ } ++ } ++ } ++} ++ ++ ++/* ++ * ``Gradient'' filter for other color depths. ++ */ ++ ++#define DEFINE_GRADIENT_FILTER_FUNCTION(bpp) \ ++ \ ++static void \ ++FilterGradient##bpp(pScreen, buf, fmt, w, h) \ ++ ScreenPtr pScreen; \ ++ CARD##bpp *buf; \ ++ rfbPixelFormat *fmt; \ ++ int w, h; \ ++{ \ ++ VNCSCREENPTR(pScreen); \ ++ CARD##bpp pix, diff; \ ++ Bool endianMismatch; \ ++ int *prevRowPtr; \ ++ int maxColor[3], shiftBits[3]; \ ++ int pixHere[3], pixUpper[3], pixLeft[3], pixUpperLeft[3]; \ ++ int prediction; \ ++ int x, y, c; \ ++ \ ++ memset (prevRowBuf, 0, w * 3 * sizeof(int)); \ ++ \ ++ endianMismatch = (!pVNC->rfbServerFormat.bigEndian != !fmt->bigEndian); \ ++ \ ++ maxColor[0] = fmt->redMax; \ ++ maxColor[1] = fmt->greenMax; \ ++ maxColor[2] = fmt->blueMax; \ ++ shiftBits[0] = fmt->redShift; \ ++ shiftBits[1] = fmt->greenShift; \ ++ shiftBits[2] = fmt->blueShift; \ ++ \ ++ for (y = 0; y < h; y++) { \ ++ for (c = 0; c < 3; c++) { \ ++ pixUpper[c] = 0; \ ++ pixHere[c] = 0; \ ++ } \ ++ prevRowPtr = prevRowBuf; \ ++ for (x = 0; x < w; x++) { \ ++ pix = *buf; \ ++ if (endianMismatch) { \ ++ pix = Swap##bpp(pix); \ ++ } \ ++ diff = 0; \ ++ for (c = 0; c < 3; c++) { \ ++ pixUpperLeft[c] = pixUpper[c]; \ ++ pixLeft[c] = pixHere[c]; \ ++ pixUpper[c] = *prevRowPtr; \ ++ pixHere[c] = (int)(pix >> shiftBits[c] & maxColor[c]); \ ++ *prevRowPtr++ = pixHere[c]; \ ++ \ ++ prediction = pixLeft[c] + pixUpper[c] - pixUpperLeft[c]; \ ++ if (prediction < 0) { \ ++ prediction = 0; \ ++ } else if (prediction > maxColor[c]) { \ ++ prediction = maxColor[c]; \ ++ } \ ++ diff |= ((pixHere[c] - prediction) & maxColor[c]) \ ++ << shiftBits[c]; \ ++ } \ ++ if (endianMismatch) { \ ++ diff = Swap##bpp(diff); \ ++ } \ ++ *buf++ = diff; \ ++ } \ ++ } \ ++} ++ ++DEFINE_GRADIENT_FILTER_FUNCTION(16) ++DEFINE_GRADIENT_FILTER_FUNCTION(32) ++ ++ ++/* ++ * Code to guess if given rectangle is suitable for smooth image ++ * compression (by applying "gradient" filter or JPEG coder). ++ */ ++ ++#define JPEG_MIN_RECT_SIZE 4096 ++ ++#define DETECT_SUBROW_WIDTH 7 ++#define DETECT_MIN_WIDTH 8 ++#define DETECT_MIN_HEIGHT 8 ++ ++static int ++DetectSmoothImage (cl, fmt, w, h) ++ rfbClientPtr cl; ++ rfbPixelFormat *fmt; ++ int w, h; ++{ ++ VNCSCREENPTR(cl->pScreen); ++ unsigned long avgError; ++ ++ if ( pVNC->rfbServerFormat.bitsPerPixel == 8 || fmt->bitsPerPixel == 8 || ++ w < DETECT_MIN_WIDTH || h < DETECT_MIN_HEIGHT ) { ++ return 0; ++ } ++ ++ if (cl->tightQualityLevel != -1) { ++ if (w * h < JPEG_MIN_RECT_SIZE) { ++ return 0; ++ } ++ } else { ++ if ( rfbTightDisableGradient || ++ w * h < tightConf[cl->tightCompressLevel].gradientMinRectSize ) { ++ return 0; ++ } ++ } ++ ++ if (fmt->bitsPerPixel == 32) { ++ if (usePixelFormat24) { ++ avgError = DetectSmoothImage24(cl, fmt, w, h); ++ if (cl->tightQualityLevel != -1) { ++ return (avgError < tightConf[cl->tightQualityLevel].jpegThreshold24); ++ } ++ return (avgError < tightConf[cl->tightCompressLevel].gradientThreshold24); ++ } else { ++ avgError = DetectSmoothImage32(cl, fmt, w, h); ++ } ++ } else { ++ avgError = DetectSmoothImage16(cl, fmt, w, h); ++ } ++ if (cl->tightQualityLevel != -1) { ++ return (avgError < tightConf[cl->tightQualityLevel].jpegThreshold); ++ } ++ return (avgError < tightConf[cl->tightCompressLevel].gradientThreshold); ++} ++ ++static unsigned long ++DetectSmoothImage24 (cl, fmt, w, h) ++ rfbClientPtr cl; ++ rfbPixelFormat *fmt; ++ int w, h; ++{ ++ int off; ++ int x, y, d, dx, c; ++ int diffStat[256]; ++ int pixelCount = 0; ++ int pix, left[3]; ++ unsigned long avgError; ++ ++ /* If client is big-endian, color samples begin from the second ++ byte (offset 1) of a 32-bit pixel value. */ ++ off = (fmt->bigEndian != 0); ++ ++ memset(diffStat, 0, 256*sizeof(int)); ++ ++ y = 0, x = 0; ++ while (y < h && x < w) { ++ for (d = 0; d < h - y && d < w - x - DETECT_SUBROW_WIDTH; d++) { ++ for (c = 0; c < 3; c++) { ++ left[c] = (int)tightBeforeBuf[((y+d)*w+x+d)*4+off+c] & 0xFF; ++ } ++ for (dx = 1; dx <= DETECT_SUBROW_WIDTH; dx++) { ++ for (c = 0; c < 3; c++) { ++ pix = (int)tightBeforeBuf[((y+d)*w+x+d+dx)*4+off+c] & 0xFF; ++ diffStat[abs(pix - left[c])]++; ++ left[c] = pix; ++ } ++ pixelCount++; ++ } ++ } ++ if (w > h) { ++ x += h; ++ y = 0; ++ } else { ++ x = 0; ++ y += w; ++ } ++ } ++ ++ if (diffStat[0] * 33 / pixelCount >= 95) ++ return 0; ++ ++ avgError = 0; ++ for (c = 1; c < 8; c++) { ++ avgError += (unsigned long)diffStat[c] * (unsigned long)(c * c); ++ if (diffStat[c] == 0 || diffStat[c] > diffStat[c-1] * 2) ++ return 0; ++ } ++ for (; c < 256; c++) { ++ avgError += (unsigned long)diffStat[c] * (unsigned long)(c * c); ++ } ++ avgError /= (pixelCount * 3 - diffStat[0]); ++ ++ return avgError; ++} ++ ++#define DEFINE_DETECT_FUNCTION(bpp) \ ++ \ ++static unsigned long \ ++DetectSmoothImage##bpp (cl, fmt, w, h) \ ++ rfbClientPtr cl; \ ++ rfbPixelFormat *fmt; \ ++ int w, h; \ ++{ \ ++ VNCSCREENPTR(cl->pScreen); \ ++ Bool endianMismatch; \ ++ CARD##bpp pix; \ ++ int maxColor[3], shiftBits[3]; \ ++ int x, y, d, dx, c; \ ++ int diffStat[256]; \ ++ int pixelCount = 0; \ ++ int sample, sum, left[3]; \ ++ unsigned long avgError; \ ++ \ ++ endianMismatch = (!pVNC->rfbServerFormat.bigEndian != !fmt->bigEndian); \ ++ \ ++ maxColor[0] = fmt->redMax; \ ++ maxColor[1] = fmt->greenMax; \ ++ maxColor[2] = fmt->blueMax; \ ++ shiftBits[0] = fmt->redShift; \ ++ shiftBits[1] = fmt->greenShift; \ ++ shiftBits[2] = fmt->blueShift; \ ++ \ ++ memset(diffStat, 0, 256*sizeof(int)); \ ++ \ ++ y = 0, x = 0; \ ++ while (y < h && x < w) { \ ++ for (d = 0; d < h - y && d < w - x - DETECT_SUBROW_WIDTH; d++) { \ ++ pix = ((CARD##bpp *)tightBeforeBuf)[(y+d)*w+x+d]; \ ++ if (endianMismatch) { \ ++ pix = Swap##bpp(pix); \ ++ } \ ++ for (c = 0; c < 3; c++) { \ ++ left[c] = (int)(pix >> shiftBits[c] & maxColor[c]); \ ++ } \ ++ for (dx = 1; dx <= DETECT_SUBROW_WIDTH; dx++) { \ ++ pix = ((CARD##bpp *)tightBeforeBuf)[(y+d)*w+x+d+dx]; \ ++ if (endianMismatch) { \ ++ pix = Swap##bpp(pix); \ ++ } \ ++ sum = 0; \ ++ for (c = 0; c < 3; c++) { \ ++ sample = (int)(pix >> shiftBits[c] & maxColor[c]); \ ++ sum += abs(sample - left[c]); \ ++ left[c] = sample; \ ++ } \ ++ if (sum > 255) \ ++ sum = 255; \ ++ diffStat[sum]++; \ ++ pixelCount++; \ ++ } \ ++ } \ ++ if (w > h) { \ ++ x += h; \ ++ y = 0; \ ++ } else { \ ++ x = 0; \ ++ y += w; \ ++ } \ ++ } \ ++ \ ++ if ((diffStat[0] + diffStat[1]) * 100 / pixelCount >= 90) \ ++ return 0; \ ++ \ ++ avgError = 0; \ ++ for (c = 1; c < 8; c++) { \ ++ avgError += (unsigned long)diffStat[c] * (unsigned long)(c * c); \ ++ if (diffStat[c] == 0 || diffStat[c] > diffStat[c-1] * 2) \ ++ return 0; \ ++ } \ ++ for (; c < 256; c++) { \ ++ avgError += (unsigned long)diffStat[c] * (unsigned long)(c * c); \ ++ } \ ++ avgError /= (pixelCount - diffStat[0]); \ ++ \ ++ return avgError; \ ++} ++ ++DEFINE_DETECT_FUNCTION(16) ++DEFINE_DETECT_FUNCTION(32) ++ ++ ++/* ++ * JPEG compression stuff. ++ */ ++ ++static struct jpeg_destination_mgr jpegDstManager; ++static Bool jpegError; ++static int jpegDstDataLen; ++ ++/** ++ * Send the given image rect with jpeg compression. ++ * \param buffer the source image buffer ++ * \param w width of source image in pixels ++ * \param h height of source image in pixels ++ * \param quality jpeg enoding quality ++ */ ++static Bool ++SendJpegRect(rfbClientPtr cl, const CARD8 *buffer, int w, int h, ++ int quality) ++{ ++ VNCSCREENPTR(cl->pScreen); ++ struct jpeg_compress_struct cinfo; ++ struct jpeg_error_mgr jerr; ++ CARD8 *srcBuf; ++ JSAMPROW rowPointer[1]; ++ int i; ++ ++ if (pVNC->rfbServerFormat.bitsPerPixel == 8) ++ return SendFullColorRect(cl, w, h); ++ ++ srcBuf = (CARD8 *)xalloc(w * 3); ++ if (srcBuf == NULL) { ++ return SendFullColorRect(cl, w, h); ++ } ++ rowPointer[0] = srcBuf; ++ ++ cinfo.err = jpeg_std_error(&jerr); ++ jpeg_create_compress(&cinfo); ++ ++ cinfo.image_width = w; ++ cinfo.image_height = h; ++ cinfo.input_components = 3; ++ cinfo.in_color_space = JCS_RGB; ++ ++ jpeg_set_defaults(&cinfo); ++ jpeg_set_quality(&cinfo, quality, TRUE); ++ ++ JpegSetDstManager (&cinfo); ++ ++ jpeg_start_compress(&cinfo, TRUE); ++ ++ for (i = 0; i < h; i++) { ++ PrepareRowForJpeg(cl->pScreen, srcBuf, buffer, i, w); ++ jpeg_write_scanlines(&cinfo, rowPointer, 1); ++ if (jpegError) ++ break; ++ } ++ ++ if (!jpegError) ++ jpeg_finish_compress(&cinfo); ++ ++ jpeg_destroy_compress(&cinfo); ++ xfree((char *)srcBuf); ++ ++ if (jpegError) ++ return SendFullColorRect(cl, w, h); ++ ++ if (pVNC->ublen + TIGHT_MIN_TO_COMPRESS + 1 > UPDATE_BUF_SIZE) { ++ if (!rfbSendUpdateBuf(cl)) ++ return FALSE; ++ } ++ ++ pVNC->updateBuf[pVNC->ublen++] = (char)(rfbTightJpeg << 4); ++ cl->rfbBytesSent[rfbEncodingTight]++; ++ ++ return SendCompressedData(cl, jpegDstDataLen); ++} ++ ++/** ++ * Convert pixel data to format needed for jpeg library. ++ * \dst destination buffer (24bpp) ++ * \buffer source buffer (16 or 32bpp) ++ * \row which image row to prepare/convert ++ * \width width of source buffer, in pixels ++ */ ++static void ++PrepareRowForJpeg(ScreenPtr pScreen, CARD8 *dst, const CARD8 *buffer, ++ int row, int width) ++{ ++ VNCSCREENPTR(pScreen); ++ if (pVNC->rfbServerFormat.bitsPerPixel == 32) { ++ if ( pVNC->rfbServerFormat.redMax == 0xFF && ++ pVNC->rfbServerFormat.greenMax == 0xFF && ++ pVNC->rfbServerFormat.blueMax == 0xFF ) { ++ PrepareRowForJpeg24(pScreen, dst, buffer, row, width); ++ } else { ++ PrepareRowForJpeg32(pScreen, dst, buffer, row, width); ++ } ++ } else { ++ /* 16 bpp assumed. */ ++ PrepareRowForJpeg16(pScreen, dst, buffer, row, width); ++ } ++} ++ ++/** ++ * Src buffer is 32bpp, dst buffer is 24bpp (optimized case). ++ */ ++static void ++PrepareRowForJpeg24(ScreenPtr pScreen, CARD8 *dst, const CARD8 *buffer, ++ int row, int width) ++{ ++ VNCSCREENPTR(pScreen); ++ const CARD32 *src = ((const CARD32 *) buffer) + row * width; ++ while (width--) { ++ CARD32 pix = *src++; ++ *dst++ = (CARD8)(pix >> pVNC->rfbServerFormat.redShift); ++ *dst++ = (CARD8)(pix >> pVNC->rfbServerFormat.greenShift); ++ *dst++ = (CARD8)(pix >> pVNC->rfbServerFormat.blueShift); ++ } ++} ++ ++/** ++ * PrepareRowForJpeg16/32: convert 16bpp or 32bpp pixels to 24bpp ++ */ ++#define DEFINE_JPEG_GET_ROW_FUNCTION(bpp) \ ++ \ ++static void \ ++PrepareRowForJpeg##bpp(ScreenPtr pScreen, CARD8 *dst, const CARD8 *buffer, \ ++ int row, int width) \ ++{ \ ++ VNCSCREENPTR(pScreen); \ ++ CARD##bpp *fbptr; \ ++ CARD##bpp pix; \ ++ int inRed, inGreen, inBlue; \ ++ \ ++ fbptr = ((CARD##bpp *) buffer) + row * width; \ ++ \ ++ while (width--) { \ ++ pix = *fbptr++; \ ++ \ ++ inRed = (int) \ ++ (pix >> pVNC->rfbServerFormat.redShift & pVNC->rfbServerFormat.redMax); \ ++ inGreen = (int) \ ++ (pix >> pVNC->rfbServerFormat.greenShift & pVNC->rfbServerFormat.greenMax); \ ++ inBlue = (int) \ ++ (pix >> pVNC->rfbServerFormat.blueShift & pVNC->rfbServerFormat.blueMax); \ ++ \ ++ *dst++ = (CARD8)((inRed * 255 + pVNC->rfbServerFormat.redMax / 2) / \ ++ pVNC->rfbServerFormat.redMax); \ ++ *dst++ = (CARD8)((inGreen * 255 + pVNC->rfbServerFormat.greenMax / 2) / \ ++ pVNC->rfbServerFormat.greenMax); \ ++ *dst++ = (CARD8)((inBlue * 255 + pVNC->rfbServerFormat.blueMax / 2) / \ ++ pVNC->rfbServerFormat.blueMax); \ ++ } \ ++} ++ ++DEFINE_JPEG_GET_ROW_FUNCTION(16) ++DEFINE_JPEG_GET_ROW_FUNCTION(32) ++ ++/* ++ * Destination manager implementation for JPEG library. ++ */ ++ ++static void ++JpegInitDestination(j_compress_ptr cinfo) ++{ ++ jpegError = FALSE; ++ jpegDstManager.next_output_byte = (JOCTET *)tightAfterBuf; ++ jpegDstManager.free_in_buffer = (size_t)tightAfterBufSize; ++} ++ ++static boolean ++JpegEmptyOutputBuffer(j_compress_ptr cinfo) ++{ ++ jpegError = TRUE; ++ jpegDstManager.next_output_byte = (JOCTET *)tightAfterBuf; ++ jpegDstManager.free_in_buffer = (size_t)tightAfterBufSize; ++ ++ return TRUE; ++} ++ ++static void ++JpegTermDestination(j_compress_ptr cinfo) ++{ ++ jpegDstDataLen = tightAfterBufSize - jpegDstManager.free_in_buffer; ++} ++ ++static void ++JpegSetDstManager(j_compress_ptr cinfo) ++{ ++ jpegDstManager.init_destination = JpegInitDestination; ++ jpegDstManager.empty_output_buffer = JpegEmptyOutputBuffer; ++ jpegDstManager.term_destination = JpegTermDestination; ++ cinfo->dest = &jpegDstManager; ++} ++ +diff -pNur xorg-server-1.4.orig/hw/vnc/translate.c xorg-server-1.4/hw/vnc/translate.c +--- xorg-server-1.4.orig/hw/vnc/translate.c 1969-12-31 16:00:00.000000000 -0800 ++++ xorg-server-1.4/hw/vnc/translate.c 2007-09-06 16:09:45.000000000 -0700 +@@ -0,0 +1,502 @@ ++/* ++ * translate.c - translate between different pixel formats ++ * ++ * Modified for XFree86 4.x by Alan Hourihane ++ */ ++ ++/* ++ * 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. ++ */ ++#ifdef HAVE_DIX_CONFIG_H ++#include ++#endif ++ ++ ++#include ++#include "rfb.h" ++#if XFREE86VNC ++#include ++#endif ++ ++static void PrintPixelFormat(rfbPixelFormat *pf); ++static Bool rfbSetClientColourMapBGR233(rfbClientPtr cl); ++ ++Bool rfbEconomicTranslate = FALSE; ++ ++/* ++ * Some standard pixel formats. ++ */ ++ ++static const rfbPixelFormat BGR233Format = { ++ 8, 8, 0, 1, 7, 7, 3, 0, 3, 6 ++}; ++ ++ ++/* ++ * Macro to compare pixel formats. ++ */ ++ ++#define PF_EQ(x,y) \ ++ ((x.bitsPerPixel == y.bitsPerPixel) && \ ++ (x.depth == y.depth) && \ ++ ((x.bigEndian == y.bigEndian) || (x.bitsPerPixel == 8)) && \ ++ (x.trueColour == y.trueColour) && \ ++ (!x.trueColour || ((x.redMax == y.redMax) && \ ++ (x.greenMax == y.greenMax) && \ ++ (x.blueMax == y.blueMax) && \ ++ (x.redShift == y.redShift) && \ ++ (x.greenShift == y.greenShift) && \ ++ (x.blueShift == y.blueShift)))) ++ ++#define CONCAT2(a,b) a##b ++#define CONCAT2E(a,b) CONCAT2(a,b) ++#define CONCAT4(a,b,c,d) a##b##c##d ++#define CONCAT4E(a,b,c,d) CONCAT4(a,b,c,d) ++ ++#define OUT 8 ++#include "tableinittctemplate.c" ++#include "tableinitcmtemplate.c" ++#define IN 8 ++#include "tabletranstemplate.c" ++#undef IN ++#define IN 16 ++#include "tabletranstemplate.c" ++#undef IN ++#define IN 32 ++#include "tabletranstemplate.c" ++#undef IN ++#undef OUT ++ ++#define OUT 16 ++#include "tableinittctemplate.c" ++#include "tableinitcmtemplate.c" ++#define IN 8 ++#include "tabletranstemplate.c" ++#undef IN ++#define IN 16 ++#include "tabletranstemplate.c" ++#undef IN ++#define IN 32 ++#include "tabletranstemplate.c" ++#undef IN ++#undef OUT ++ ++#define OUT 32 ++#include "tableinittctemplate.c" ++#include "tableinitcmtemplate.c" ++#define IN 8 ++#include "tabletranstemplate.c" ++#undef IN ++#define IN 16 ++#include "tabletranstemplate.c" ++#undef IN ++#define IN 32 ++#include "tabletranstemplate.c" ++#undef IN ++#undef OUT ++ ++typedef void (*rfbInitTableFnType)(ScreenPtr pScreen, char **table, rfbPixelFormat *in, ++ rfbPixelFormat *out); ++ ++rfbInitTableFnType rfbInitTrueColourSingleTableFns[3] = { ++ rfbInitTrueColourSingleTable8, ++ rfbInitTrueColourSingleTable16, ++ rfbInitTrueColourSingleTable32 ++}; ++ ++rfbInitTableFnType rfbInitColourMapSingleTableFns[3] = { ++ rfbInitColourMapSingleTable8, ++ rfbInitColourMapSingleTable16, ++ rfbInitColourMapSingleTable32 ++}; ++ ++rfbInitTableFnType rfbInitTrueColourRGBTablesFns[3] = { ++ rfbInitTrueColourRGBTables8, ++ rfbInitTrueColourRGBTables16, ++ rfbInitTrueColourRGBTables32 ++}; ++ ++rfbTranslateFnType rfbTranslateWithSingleTableFns[3][3] = { ++ { rfbTranslateWithSingleTable8to8, ++ rfbTranslateWithSingleTable8to16, ++ rfbTranslateWithSingleTable8to32 }, ++ { rfbTranslateWithSingleTable16to8, ++ rfbTranslateWithSingleTable16to16, ++ rfbTranslateWithSingleTable16to32 }, ++ { rfbTranslateWithSingleTable32to8, ++ rfbTranslateWithSingleTable32to16, ++ rfbTranslateWithSingleTable32to32 } ++}; ++ ++rfbTranslateFnType rfbTranslateWithRGBTablesFns[3][3] = { ++ { rfbTranslateWithRGBTables8to8, ++ rfbTranslateWithRGBTables8to16, ++ rfbTranslateWithRGBTables8to32 }, ++ { rfbTranslateWithRGBTables16to8, ++ rfbTranslateWithRGBTables16to16, ++ rfbTranslateWithRGBTables16to32 }, ++ { rfbTranslateWithRGBTables32to8, ++ rfbTranslateWithRGBTables32to16, ++ rfbTranslateWithRGBTables32to32 } ++}; ++ ++ ++ ++/* ++ * rfbTranslateNone is used when no translation is required. ++ */ ++ ++void ++rfbTranslateNone(ScreenPtr pScreen, char *table, rfbPixelFormat *in, rfbPixelFormat *out, ++ unsigned char *optr, int bytesBetweenInputLines, ++ int width, int height, int x, int y) ++{ ++ VNCSCREENPTR(pScreen); ++ DrawablePtr pDraw = (DrawablePtr)WindowTable[pScreen->myNum]; ++ int truewidth = PixmapBytePad(width, in->bitsPerPixel) / 4; ++ ++ if ((x + truewidth > pVNC->width) || truewidth != width) { ++ unsigned char *buffer = malloc(truewidth * height * in->bitsPerPixel / 8); ++ unsigned char *buf = buffer; ++ ++ (*pScreen->GetImage)(pDraw, x, y, truewidth, height, ZPixmap, ~0, (char*)buf); ++ while (height--) { ++ memcpy(optr, buf, width * in->bitsPerPixel / 8); ++ optr += width * in->bitsPerPixel / 8; ++ buf += truewidth * in->bitsPerPixel / 8; ++ } ++ free(buffer); ++ return; ++ } ++ ++ (*pScreen->GetImage)(pDraw, x, y, width, height, ZPixmap, ~0, (char*)optr); ++} ++ ++ ++/* ++ * rfbSetTranslateFunction sets the translation function. ++ */ ++ ++Bool ++rfbSetTranslateFunction(cl) ++ rfbClientPtr cl; ++{ ++ VNCSCREENPTR(cl->pScreen); ++ rfbLog("Pixel format for client %s:\n",cl->host); ++ PrintPixelFormat(&cl->format); ++ ++ /* ++ * Check that bits per pixel values are valid ++ */ ++ ++ if ((pVNC->rfbServerFormat.bitsPerPixel != 8) && ++ (pVNC->rfbServerFormat.bitsPerPixel != 16) && ++ (pVNC->rfbServerFormat.bitsPerPixel != 32)) ++ { ++ rfbLog("%s: server bits per pixel not 8, 16 or 32\n", ++ "rfbSetTranslateFunction"); ++ rfbCloseSock(cl->pScreen, cl->sock); ++ return FALSE; ++ } ++ ++ if ((cl->format.bitsPerPixel != 8) && ++ (cl->format.bitsPerPixel != 16) && ++ (cl->format.bitsPerPixel != 32)) ++ { ++ rfbLog("%s: client bits per pixel not 8, 16 or 32\n", ++ "rfbSetTranslateFunction"); ++ rfbCloseSock(cl->pScreen, cl->sock); ++ return FALSE; ++ } ++ ++ if (!pVNC->rfbServerFormat.trueColour && ++ (pVNC->rfbServerFormat.bitsPerPixel != 8) && ++#if XFREE86VNC ++ (miInstalledMaps[cl->pScreen->myNum]->class == PseudoColor)) { ++#else ++ (pVNC->rfbInstalledColormap->class == PseudoColor)) { ++#endif ++ rfbLog("rfbSetTranslateFunction: server has colour map " ++ "but %d-bit - can only cope with 8-bit colour maps\n", ++ pVNC->rfbServerFormat.bitsPerPixel); ++ rfbCloseSock(cl->pScreen, cl->sock); ++ return FALSE; ++ } ++ ++ if (!cl->format.trueColour && ++ (cl->format.bitsPerPixel != 8) && ++#if XFREE86VNC ++ (miInstalledMaps[cl->pScreen->myNum]->class == PseudoColor)) { ++#else ++ (pVNC->rfbInstalledColormap->class == PseudoColor) ) { ++#endif ++ rfbLog("rfbSetTranslateFunction: client has colour map " ++ "but %d-bit - can only cope with 8-bit colour maps\n", ++ cl->format.bitsPerPixel); ++ rfbCloseSock(cl->pScreen, cl->sock); ++ return FALSE; ++ } ++ ++ /* ++ * bpp is valid, now work out how to translate ++ */ ++ ++ if (!cl->format.trueColour) { ++ ++ /* ? -> colour map */ ++ ++ if (!pVNC->rfbServerFormat.trueColour) { ++ ++ /* colour map -> colour map */ ++ ++#if XFREE86VNC ++ if (miInstalledMaps[cl->pScreen->myNum]->class == DirectColor) { ++#else ++ if (pVNC->rfbInstalledColormap->class == DirectColor) { ++#endif ++ rfbLog("rfbSetTranslateFunction: client is %d-bit DirectColor," ++ " client has colour map\n",cl->format.bitsPerPixel); ++ ++ cl->translateFn = rfbTranslateWithRGBTablesFns ++ [pVNC->rfbServerFormat.bitsPerPixel / 16] ++ [cl->format.bitsPerPixel / 16]; ++ ++ (*rfbInitTrueColourRGBTablesFns [cl->format.bitsPerPixel / 16]) ++ (cl->pScreen, &cl->translateLookupTable, ++ &pVNC->rfbServerFormat, &cl->format); ++ ++ return rfbSetClientColourMap(cl, 0, 0); ++ ++ /* PseudoColor colormap */ ++ ++ } else { ++ rfbLog("rfbSetTranslateFunction: both 8-bit colour map: " ++ "no translation needed\n"); ++ cl->translateFn = rfbTranslateNone; ++ return rfbSetClientColourMap(cl, 0, 0); ++ } ++ } ++ ++ /* ++ * truecolour -> colour map ++ * ++ * Set client's colour map to BGR233, then effectively it's ++ * truecolour as well ++ */ ++ ++ if (!rfbSetClientColourMapBGR233(cl)) ++ return FALSE; ++ ++ cl->format = BGR233Format; ++ } ++ ++ /* ? -> truecolour */ ++ ++ if (!pVNC->rfbServerFormat.trueColour) { ++ ++ /* colour map -> truecolour */ ++ ++ rfbLog("rfbSetTranslateFunction: client is %d-bit trueColour," ++ " server has colour map\n",cl->format.bitsPerPixel); ++ ++ cl->translateFn = rfbTranslateWithSingleTableFns ++ [pVNC->rfbServerFormat.bitsPerPixel / 16] ++ [cl->format.bitsPerPixel / 16]; ++ ++ return rfbSetClientColourMap(cl, 0, 0); ++ } ++ ++ /* truecolour -> truecolour */ ++ ++ if (PF_EQ(cl->format,pVNC->rfbServerFormat)) { ++ ++ /* client & server the same */ ++ ++ rfbLog(" no translation needed\n"); ++ cl->translateFn = rfbTranslateNone; ++ return TRUE; ++ } ++ ++ if ((pVNC->rfbServerFormat.bitsPerPixel < 16) || ++ (!rfbEconomicTranslate && (pVNC->rfbServerFormat.bitsPerPixel == 16))) { ++ ++ /* we can use a single lookup table for <= 16 bpp */ ++ ++ cl->translateFn = rfbTranslateWithSingleTableFns ++ [pVNC->rfbServerFormat.bitsPerPixel / 16] ++ [cl->format.bitsPerPixel / 16]; ++ ++ (*rfbInitTrueColourSingleTableFns ++ [cl->format.bitsPerPixel / 16]) (cl->pScreen, ++ &cl->translateLookupTable, ++ &pVNC->rfbServerFormat, &cl->format); ++ ++ } else { ++ ++ /* otherwise we use three separate tables for red, green and blue */ ++ ++ cl->translateFn = rfbTranslateWithRGBTablesFns ++ [pVNC->rfbServerFormat.bitsPerPixel / 16] ++ [cl->format.bitsPerPixel / 16]; ++ ++ (*rfbInitTrueColourRGBTablesFns ++ [cl->format.bitsPerPixel / 16]) (cl->pScreen, ++ &cl->translateLookupTable, ++ &pVNC->rfbServerFormat, &cl->format); ++ } ++ ++ return TRUE; ++} ++ ++ ++ ++/* ++ * rfbSetClientColourMapBGR233 sets the client's colour map so that it's ++ * just like an 8-bit BGR233 true colour client. ++ */ ++ ++static Bool ++rfbSetClientColourMapBGR233(rfbClientPtr cl) ++{ ++ char buf[sz_rfbSetColourMapEntriesMsg + 256 * 3 * 2]; ++ rfbSetColourMapEntriesMsg *scme = (rfbSetColourMapEntriesMsg *)buf; ++ CARD16 *rgb = (CARD16 *)(&buf[sz_rfbSetColourMapEntriesMsg]); ++ int i, len; ++ int r, g, b; ++ ++ if (cl->format.bitsPerPixel != 8) { ++ rfbLog("%s: client not 8 bits per pixel\n", ++ "rfbSetClientColourMapBGR233"); ++ rfbCloseSock(cl->pScreen, cl->sock); ++ return FALSE; ++ } ++ ++ scme->type = rfbSetColourMapEntries; ++ ++ scme->firstColour = Swap16IfLE(0); ++ scme->nColours = Swap16IfLE(256); ++ ++ len = sz_rfbSetColourMapEntriesMsg; ++ ++ i = 0; ++ ++ for (b = 0; b < 4; b++) { ++ for (g = 0; g < 8; g++) { ++ for (r = 0; r < 8; r++) { ++ rgb[i++] = Swap16IfLE(r * 65535 / 7); ++ rgb[i++] = Swap16IfLE(g * 65535 / 7); ++ rgb[i++] = Swap16IfLE(b * 65535 / 3); ++ } ++ } ++ } ++ ++ len += 256 * 3 * 2; ++ ++ if (WriteExact(cl->sock, buf, len) < 0) { ++ rfbLogPerror("rfbSetClientColourMapBGR233: write"); ++ rfbCloseSock(cl->pScreen, cl->sock); ++ return FALSE; ++ } ++ return TRUE; ++} ++ ++ ++/* ++ * rfbSetClientColourMap is called to set the client's colour map. If the ++ * client is a true colour client, we simply update our own translation table ++ * and mark the whole screen as having been modified. ++ */ ++ ++Bool ++rfbSetClientColourMap(cl, firstColour, nColours) ++ rfbClientPtr cl; ++ int firstColour; ++ int nColours; ++{ ++ VNCSCREENPTR(cl->pScreen); ++ BoxRec box; ++ ++ if (nColours == 0) { ++#if XFREE86VNC ++ nColours = miInstalledMaps[cl->pScreen->myNum]->pVisual->ColormapEntries; ++#else ++ nColours = pVNC->rfbInstalledColormap->pVisual->ColormapEntries; ++#endif ++ } ++ ++ if (pVNC->rfbServerFormat.trueColour || !cl->readyForSetColourMapEntries) { ++ return TRUE; ++ } ++ ++ if (cl->format.trueColour) { ++ (*rfbInitColourMapSingleTableFns ++ [cl->format.bitsPerPixel / 16]) (cl->pScreen, ++ &cl->translateLookupTable, ++ &pVNC->rfbServerFormat, &cl->format); ++ ++ REGION_UNINIT(cl->pScreen,&cl->modifiedRegion); ++ box.x1 = box.y1 = 0; ++ box.x2 = pVNC->width; ++ box.y2 = pVNC->height; ++ REGION_INIT(cl->pScreen,&cl->modifiedRegion,&box,0); ++ ++ return TRUE; ++ } ++ ++ return rfbSendSetColourMapEntries(cl, firstColour, nColours); ++} ++ ++ ++/* ++ * rfbSetClientColourMaps sets the colour map for each RFB client. ++ */ ++ ++void ++rfbSetClientColourMaps(firstColour, nColours) ++ int firstColour; ++ int nColours; ++{ ++ rfbClientPtr cl, nextCl; ++ ++ for (cl = rfbClientHead; cl; cl = nextCl) { ++ nextCl = cl->next; ++ rfbSetClientColourMap(cl, firstColour, nColours); ++ } ++} ++ ++ ++static void ++PrintPixelFormat(pf) ++ rfbPixelFormat *pf; ++{ ++ if (pf->bitsPerPixel == 1) { ++ rfbLog(" 1 bpp, %s sig bit in each byte is leftmost on the screen.\n", ++ (pf->bigEndian ? "most" : "least")); ++ } else { ++ rfbLog(" %d bpp, depth %d%s\n",pf->bitsPerPixel,pf->depth, ++ ((pf->bitsPerPixel == 8) ? "" ++ : (pf->bigEndian ? ", big endian" : ", little endian"))); ++ if (pf->trueColour) { ++ rfbLog(" true colour: max r %d g %d b %d, shift r %d g %d b %d\n", ++ pf->redMax, pf->greenMax, pf->blueMax, ++ pf->redShift, pf->greenShift, pf->blueShift); ++ } else { ++ rfbLog(" uses a colour map (not true colour).\n"); ++ } ++ } ++} +diff -pNur xorg-server-1.4.orig/hw/vnc/vncauth.c xorg-server-1.4/hw/vnc/vncauth.c +--- xorg-server-1.4.orig/hw/vnc/vncauth.c 1969-12-31 16:00:00.000000000 -0800 ++++ xorg-server-1.4/hw/vnc/vncauth.c 2007-09-06 16:09:45.000000000 -0700 +@@ -0,0 +1,252 @@ ++/* ++ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. ++ * ++ * This is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This software is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, ++ * USA. ++ */ ++ ++/* ++ * vncauth.c - Functions for VNC password management and authentication. ++ */ ++#ifdef HAVE_DIX_CONFIG_H ++#include ++#endif ++ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++ ++/* ++ * Make sure we call srandom() only once. ++ */ ++ ++static int s_srandom_called = 0; ++ ++/* ++ * We use a fixed key to store passwords, since we assume that our local ++ * file system is secure but nonetheless don't want to store passwords ++ * as plaintext. ++ */ ++ ++static unsigned char s_fixedkey[8] = {23,82,107,6,35,78,88,7}; ++ ++ ++/* ++ * Encrypt a password and store it in a file. Returns 0 if successful, ++ * 1 if the file could not be written. ++ * ++ * NOTE: This function is preserved only for compatibility with the original ++ * AT&T VNC software. Use vncEncryptAndStorePasswd2() instead. ++ */ ++ ++int ++vncEncryptAndStorePasswd(char *passwd, char *fname) ++{ ++ return (vncEncryptAndStorePasswd2(passwd, NULL, fname) == 0); ++} ++ ++/* ++ * Encrypt one or two passwords and store them in a file. Returns 1 if ++ * successful, 0 if the file could not be written (note that the original ++ * vncEncryptAndStorePasswd() function returns inverse values). The ++ * passwdViewOnly pointer may be NULL. ++ * ++ * NOTE: The file name of "-" denotes stdout. ++ */ ++ ++int ++vncEncryptAndStorePasswd2(char *passwd, char *passwdViewOnly, char *fname) ++{ ++ FILE *fp; ++ int bytesToWrite, bytesWrote; ++ unsigned char encryptedPasswd[16] = { ++ 0,0,0,0,0,0,0,0, ++ 0,0,0,0,0,0,0,0 ++ }; ++ ++ if (strcmp(fname, "-") != 0) { ++ fp = fopen(fname, "w"); ++ if (fp == NULL) { ++ return 0; ++ } ++ chmod(fname, S_IRUSR|S_IWUSR); ++ } else { ++ fp = stdout; ++ } ++ ++ strncpy((char*)encryptedPasswd, passwd, 8); ++ if (passwdViewOnly != NULL) ++ strncpy((char*)encryptedPasswd + 8, passwdViewOnly, 8); ++ ++ /* Do encryption in-place - this way we overwrite our copies of ++ plaintext passwords. */ ++ ++ deskey(s_fixedkey, EN0); ++ des(encryptedPasswd, encryptedPasswd); ++ if (passwdViewOnly != NULL) ++ des(encryptedPasswd + 8, encryptedPasswd + 8); ++ ++ bytesToWrite = (passwdViewOnly == NULL) ? 8 : 16; ++ bytesWrote = fwrite(encryptedPasswd, 1, bytesToWrite, fp); ++ ++ if (fp != stdout) { ++ fclose(fp); ++ } ++ return (bytesWrote == bytesToWrite); ++} ++ ++ ++/* ++ * Decrypt a password from a file. Returns a pointer to a newly allocated ++ * string containing the password or a null pointer if the password could ++ * not be retrieved for some reason. ++ * ++ * NOTE: This function is preserved only for compatibility with the original ++ * AT&T VNC software. Use vncDecryptPasswdFromFile2() instead. ++ */ ++ ++char * ++vncDecryptPasswdFromFile(char *fname) ++{ ++ char *passwd; ++ ++ passwd = malloc(9); ++ ++ if (passwd != NULL) { ++ if (vncDecryptPasswdFromFile2(fname, passwd, NULL) == 0) { ++ free(passwd); ++ passwd = NULL; ++ } ++ } ++ ++ return passwd; ++} ++ ++/* ++ * Decrypt one or two passwords from a file. Returns the number of ++ * passwords read (1, 2, or 0 on error). On success, the passwords are ++ * written into buffers passwdFullControl[] and passwdViewOnly[] if ++ * they are not NULL. If the pointers to buffers are not NULL, then ++ * the buffers should be at least of 9 bytes length. ++ */ ++ ++int ++vncDecryptPasswdFromFile2(char *fname, ++ char *passwdFullControl, char *passwdViewOnly) ++{ ++ FILE *fp; ++ int i, ch; ++ unsigned char passwd[16]; ++ ++ if (strcmp(fname, "-") != 0) { ++ if ((fp = fopen(fname,"r")) == NULL) ++ return 0; /* Could not open the file */ ++ } else { ++ fp = stdin; ++ } ++ ++ for (i = 0; i < 16; i++) { ++ ch = getc(fp); ++ if (ch == EOF) ++ break; ++ passwd[i] = ch; ++ } ++ ++ if (fp != stdin) ++ fclose(fp); ++ ++ if (i < 8) ++ return 0; /* Could not read eight bytes */ ++ ++ deskey(s_fixedkey, DE1); ++ ++ /* Decoding first (full-control) password */ ++ if (passwdFullControl != NULL) { ++ des(passwd, passwd); ++ memcpy(passwdFullControl, passwd, 8); ++ passwdFullControl[8] = '\0'; ++ } ++ ++ /* Decoding second (view-only) password if available */ ++ if (i == 16 && passwdViewOnly != NULL) { ++ des(&passwd[8], &passwd[8]); ++ memcpy(passwdViewOnly, &passwd[8], 8); ++ passwdViewOnly[8] = '\0'; ++ } ++ ++ /* Destroying our copy of clear-text passwords */ ++ memset(passwd, 0, 16); ++ ++ return (i < 16) ? 1 : 2; ++} ++ ++ ++/* ++ * Generate CHALLENGESIZE random bytes for use in challenge-response ++ * authentication. ++ */ ++ ++void ++vncRandomBytes(unsigned char *bytes) ++{ ++ int i; ++ unsigned int seed; ++ ++ if (!s_srandom_called) { ++ seed = (unsigned int)time(0) ^ (unsigned int)getpid(); ++ srandom(seed); ++ s_srandom_called = 1; ++ } ++ ++ for (i = 0; i < CHALLENGESIZE; i++) { ++ bytes[i] = (unsigned char)(random() & 255); ++ } ++} ++ ++ ++/* ++ * Encrypt CHALLENGESIZE bytes in memory using a password. ++ */ ++ ++void ++vncEncryptBytes(unsigned char *bytes, char *passwd) ++{ ++ unsigned char key[8]; ++ int i; ++ ++ /* key is simply password padded with nulls */ ++ ++ for (i = 0; i < 8; i++) { ++ if (i < strlen(passwd)) { ++ key[i] = passwd[i]; ++ } else { ++ key[i] = 0; ++ } ++ } ++ ++ deskey(key, EN0); ++ ++ for (i = 0; i < CHALLENGESIZE; i += 8) { ++ des(bytes+i, bytes+i); ++ } ++} +diff -pNur xorg-server-1.4.orig/hw/vnc/vncauth.h xorg-server-1.4/hw/vnc/vncauth.h +--- xorg-server-1.4.orig/hw/vnc/vncauth.h 1969-12-31 16:00:00.000000000 -0800 ++++ xorg-server-1.4/hw/vnc/vncauth.h 2007-09-06 16:09:45.000000000 -0700 +@@ -0,0 +1,33 @@ ++/* ++ * 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. ++ */ ++ ++/* ++ * vncauth.h - describes the functions provided by the vncauth library. ++ */ ++ ++#define MAXPWLEN 8 ++#define CHALLENGESIZE 16 ++ ++extern int vncEncryptAndStorePasswd(char *passwd, char *fname); ++extern char *vncDecryptPasswdFromFile(char *fname); ++extern void vncRandomBytes(unsigned char *bytes); ++extern void vncEncryptBytes(unsigned char *bytes, char *passwd); ++extern int vncEncryptAndStorePasswd2(char *passwd, char *passwdViewOnly, char *fname); ++extern int vncDecryptPasswdFromFile2(char *fname, char *passwdFullControl, char *passwdViewOnly); ++ +diff -pNur xorg-server-1.4.orig/hw/vnc/vncext.c xorg-server-1.4/hw/vnc/vncext.c +--- xorg-server-1.4.orig/hw/vnc/vncext.c 1969-12-31 16:00:00.000000000 -0800 ++++ xorg-server-1.4/hw/vnc/vncext.c 2007-09-06 16:09:45.000000000 -0700 +@@ -0,0 +1,798 @@ ++/* ++ * Copyright (C) 2002 Alan Hourihane. 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. ++ * ++ * Author: Alan Hourihane ++ */ ++#ifdef HAVE_DIX_CONFIG_H ++#include ++#endif ++ ++ ++#include "rfb.h" ++#include "extnsionst.h" ++#define _VNC_SERVER ++#include ++#ifdef XFree86LOADER ++#include "xf86Module.h" ++#endif ++ ++#include ++#include ++#include ++#include ++ ++int VncSelectNotify(ClientPtr client, BOOL onoff); ++void VncExtensionInit(void); ++ ++static int VncErrorBase; /* first vnc error number */ ++static int VncEventBase; /* first vnc event number */ ++ ++#define USE_ORIG_RES_CODE 0 ++ ++#if USE_ORIG_RES_CODE ++unsigned long VncResourceGeneration = 0; ++ ++static RESTYPE VncNotifyList; ++ ++static XID faked; ++ ++typedef struct _VncNotifyListRec { ++ struct _VncNotifyListRec *next; ++ ClientPtr client; ++} VncNotifyListRec, *VncNotifyListPtr; ++#endif ++ ++ ++/** ++ * Each X client that uses libVnc to talk to this extension will ++ * get recorded by one of these records. ++ */ ++typedef struct _VncClientRec { ++ ClientPtr client; ++ struct _VncClientRec *next; ++ XID fakeID; ++ RESTYPE res; ++} VncClientRec, *VncClientRecPtr; ++ ++static VncClientRecPtr ClientsList = NULL; ++ ++ ++/** ++ * Remove client record from list ++ */ ++static void ++VncRemoveClientRecord(ClientPtr client) ++{ ++ /* XXX need 'deleteresource' flag? */ ++ VncClientRecPtr p = ClientsList, prev = NULL; ++ rfbLog("%s client %p\n", __func__, (void *) client); ++ while (p) { ++ if (p->client == client) { ++ /* remove this one */ ++ if (prev) ++ prev->next = p->next; ++ else ++ ClientsList = p->next; ++ xfree(p); ++ return; ++ } ++ prev = p; ++ p = p->next; ++ } ++} ++ ++ ++/** ++ * This callback will be called by X's resource manager to delete the ++ * given resource. We create one resource for each client. When X ++ * deletes the resource, we know the client is going away. ++ */ ++static int ++VncDestroyClientResourceCallback(pointer pn, XID id) ++{ ++ VncClientRecPtr rec = (VncClientRecPtr) pn; ++ VncRemoveClientRecord(rec->client); ++ return Success; ++} ++ ++ ++/** ++ * Add a client record to the list of clients (unless already in list). ++ * We'll create a new, unique resource for this client. This is used ++ * to detect when an X client goes away. ++ */ ++static void ++VncSaveClientRecord(ClientPtr client) ++{ ++ VncClientRecPtr rec = ClientsList; ++ ++ rfbLog("%s saving client %p\n", __func__, (void *) client); ++ ++ /* look if already in list */ ++ while (rec) { ++ if (rec->client == client) { ++ return; /* already in list */ ++ } ++ rec = rec->next; ++ } ++ ++ /* allocate new client record */ ++ rec = (VncClientRecPtr) xalloc(sizeof(VncClientRec)); ++ if (rec) { ++ rec->client = client; ++ rec->fakeID = FakeClientID(client->index); ++ rec->res = CreateNewResourceType(VncDestroyClientResourceCallback); ++ if (!AddResource(rec->fakeID, rec->res, rec)) { ++ xfree(rec); ++ } ++ ++ /* insert at head of list */ ++ rec->next = ClientsList; ++ ClientsList = rec; ++ } ++} ++ ++ ++ ++static int ++ProcVncQueryVersion(ClientPtr client) ++{ ++ xVncQueryVersionReply rep; ++ ++ REQUEST_SIZE_MATCH(xVncQueryVersionReq); ++ rep.type = X_Reply; ++ rep.sequenceNumber = client->sequence; ++ rep.length = 0; ++ rep.majorVersion = VNC_MAJOR_VERSION; ++ rep.minorVersion = VNC_MINOR_VERSION; ++ if(client->swapped) ++ { ++ register char n; ++ swaps(&rep.sequenceNumber, n); ++ swaps(&rep.majorVersion, n); ++ swaps(&rep.minorVersion, n); ++ } ++ (void)WriteToClient(client, SIZEOF(xVncQueryVersionReply), ++ (char *)&rep); ++ return (client->noClientException); ++} /* ProcVncQueryVersion */ ++ ++static int ++ProcVncConnection(ClientPtr client) ++{ ++ REQUEST(xVncConnectionReq); ++ xVncConnectionReply rep; ++ ++ rfbUserAllow( stuff->sock, stuff->accept ); ++ ++ REQUEST_SIZE_MATCH(xVncConnectionReq); ++ rep.type = X_Reply; ++ rep.sequenceNumber = client->sequence; ++ rep.length = 0; ++ rep.sock = 0; ++ rep.accept = 0; ++ if(client->swapped) ++ { ++ register char n; ++ swaps(&rep.sequenceNumber, n); ++ swaps(&rep.sock, n); ++ swaps(&rep.accept, n); ++ } ++ (void)WriteToClient(client, SIZEOF(xVncConnectionReply), ++ (char *)&rep); ++ return (client->noClientException); ++} /* ProcVncConnection */ ++ ++static int ++ProcVncSelectNotify(ClientPtr client) ++{ ++ REQUEST(xVncSelectNotifyReq); ++ xVncSelectNotifyReply rep; ++ ++ VncSelectNotify(client, stuff->onoff); ++ ++ REQUEST_SIZE_MATCH(xVncSelectNotifyReq); ++ rep.type = X_Reply; ++ rep.sequenceNumber = client->sequence; ++ rep.length = 0; ++ if(client->swapped) ++ { ++ register char n; ++ swaps(&rep.sequenceNumber, n); ++ } ++ (void)WriteToClient(client, SIZEOF(xVncSelectNotifyReply), ++ (char *)&rep); ++ return (client->noClientException); ++ ++} ++ ++static int ++ProcVncListConnections(ClientPtr client) ++{ ++ xVncListConnectionsReply rep; ++ rfbClientPtr cl; ++ int count = 0; ++ struct in_addr ipaddress; ++ xVncConnectionListInfo Info; ++ ++ /* count connections */ ++ for (cl = rfbClientHead; cl; cl = cl->next) ++#ifdef CHROMIUM ++ /* ++ * Fix this, as it should be generic, but we're only using it ++ * for Chromium at the moment, so we only list the connections ++ * that have a valid chromium encoding. We should be able to list ++ * any type requested. FIXME! XXXX ++ * See furthur down this function too!!! ++ */ ++ if (cl->enableChromiumEncoding) ++#endif ++ count++; ++ ++ REQUEST_SIZE_MATCH(xVncListConnectionsReq); ++ rep.type = X_Reply; ++ rep.sequenceNumber = client->sequence; ++ rep.count = count; ++ rep.length = count * sizeof(xVncConnectionListInfo) >> 2; ++ if(client->swapped) ++ { ++ register char n; ++ swaps(&rep.sequenceNumber, n); ++ swaps(&rep.count, n); ++ } ++ (void)WriteToClient(client, SIZEOF(xVncListConnectionsReply), ++ (char *)&rep); ++ ++ for (cl = rfbClientHead; cl; cl = cl->next) { ++#ifdef CHROMIUM ++ /* ++ * Fix this, as it should be generic, but we're only using it ++ * for Chromium at the moment, so we only list the connections ++ * that have a valid chromium encoding. We should be able to list ++ * any type requested. FIXME! XXXX ++ */ ++ if (!cl->enableChromiumEncoding) ++ continue; ++#endif ++ inet_aton(cl->host, &ipaddress); ++ memcpy(&Info, &ipaddress, sizeof(struct in_addr)); ++ WriteToClient(client, SIZEOF(xVncConnectionListInfo), (char*)&Info); ++ } ++ ++ return (client->noClientException); ++} /* ProcVncListConnections */ ++ ++#ifdef CHROMIUM ++static int ++ProcVncChromiumStart(ClientPtr client) ++{ ++ REQUEST(xVncChromiumStartReq); ++ xVncChromiumStartReply rep; ++ ++ rfbSendChromiumStart(stuff->ipaddress, stuff->crServerPort, stuff->mothershipPort); ++ ++ REQUEST_SIZE_MATCH(xVncChromiumStartReq); ++ rep.type = X_Reply; ++ rep.sequenceNumber = client->sequence; ++ rep.length = 0; ++ if(client->swapped) ++ { ++ register char n; ++ swaps(&rep.sequenceNumber, n); ++ } ++ (void)WriteToClient(client, SIZEOF(xVncChromiumStartReply), ++ (char *)&rep); ++ return (client->noClientException); ++} /* ProcVncChromiumStart */ ++ ++static int ++ProcVncChromiumMonitor(ClientPtr client) ++{ ++ REQUEST(xVncChromiumMonitorReq); ++ xVncChromiumMonitorReply rep; ++ ++ rfbChromiumMonitorWindowID(stuff->cr_windowid, stuff->windowid); ++ ++ REQUEST_SIZE_MATCH(xVncChromiumMonitorReq); ++ rep.type = X_Reply; ++ rep.sequenceNumber = client->sequence; ++ rep.length = 0; ++ if(client->swapped) ++ { ++ register char n; ++ swaps(&rep.sequenceNumber, n); ++ } ++ (void)WriteToClient(client, SIZEOF(xVncChromiumMonitorReply), ++ (char *)&rep); ++ return (client->noClientException); ++} /* ProcVncChromiumMonitor */ ++#endif /* CHROMIUM */ ++ ++static int ++ProcVncDispatch(ClientPtr client) ++{ ++ REQUEST(xReq); ++ ++ switch (stuff->data) ++ { ++ case X_VncQueryVersion: ++ return ProcVncQueryVersion(client); ++ case X_VncSelectNotify: ++ return ProcVncSelectNotify(client); ++ case X_VncConnection: ++ return ProcVncConnection(client); ++ case X_VncListConnections: ++ return ProcVncListConnections(client); ++#ifdef CHROMIUM ++ case X_VncChromiumStart: ++ return ProcVncChromiumStart(client); ++ case X_VncChromiumMonitor: ++ return ProcVncChromiumMonitor(client); ++#endif ++ default: ++ return BadRequest; ++ } ++} /* ProcVncDispatch */ ++ ++static int ++SProcVncQueryVersion(ClientPtr client) ++{ ++ REQUEST(xVncQueryVersionReq); ++ register char n; ++ ++ swaps(&stuff->length, n); ++ REQUEST_SIZE_MATCH(xVncQueryVersionReq); ++ swaps(&stuff->majorVersion, n); ++ swaps(&stuff->minorVersion,n); ++ return ProcVncQueryVersion(client); ++} /* SProcVncQueryVersion */ ++ ++static int ++SProcVncSelectNotify(ClientPtr client) ++{ ++ REQUEST(xVncSelectNotifyReq); ++ register char n; ++ ++ swaps(&stuff->length, n); ++ REQUEST_SIZE_MATCH(xVncSelectNotifyReq); ++ return ProcVncSelectNotify(client); ++} /* SProcVncSelectNotify */ ++ ++static int ++SProcVncListConnections(ClientPtr client) ++{ ++ REQUEST(xVncListConnectionsReq); ++ register char n; ++ ++ swaps(&stuff->length, n); ++ REQUEST_SIZE_MATCH(xVncListConnectionsReq); ++ return ProcVncListConnections(client); ++} /* SProcVncListConnections */ ++ ++#ifdef CHROMIUM ++static int ++SProcVncChromiumStart(ClientPtr client) ++{ ++ REQUEST(xVncChromiumStartReq); ++ register char n; ++ ++ swaps(&stuff->ipaddress, n); ++ swaps(&stuff->crServerPort, n); ++ swaps(&stuff->mothershipPort, n); ++ swaps(&stuff->length, n); ++ REQUEST_SIZE_MATCH(xVncChromiumStartReq); ++ return ProcVncChromiumStart(client); ++} /* SProcVncChromiumStart */ ++ ++static int ++SProcVncChromiumMonitor(ClientPtr client) ++{ ++ REQUEST(xVncChromiumMonitorReq); ++ register char n; ++ ++ swaps(&stuff->length, n); ++ swaps(&stuff->windowid, n); ++ swaps(&stuff->cr_windowid, n); ++ REQUEST_SIZE_MATCH(xVncChromiumMonitorReq); ++ return ProcVncChromiumMonitor(client); ++} /* SProcVncChromiumMonitor */ ++#endif /* CHROMIUM */ ++ ++static int ++SProcVncConnection(ClientPtr client) ++{ ++ REQUEST(xVncConnectionReq); ++ register char n; ++ ++ ++ swaps(&stuff->length, n); ++ REQUEST_SIZE_MATCH(xVncConnectionReq); ++ swaps(&stuff->sock, n); ++ swaps(&stuff->accept,n); ++ return ProcVncConnection(client); ++} /* SProcVncConnection */ ++ ++static int ++SProcVncDispatch(ClientPtr client) ++{ ++ REQUEST(xReq); ++ ++ switch (stuff->data) ++ { ++ case X_VncQueryVersion: ++ return SProcVncQueryVersion(client); ++ case X_VncSelectNotify: ++ return SProcVncSelectNotify(client); ++ case X_VncConnection: ++ return SProcVncConnection(client); ++ case X_VncListConnections: ++ return SProcVncListConnections(client); ++#ifdef CHROMIUM ++ case X_VncChromiumStart: ++ return SProcVncChromiumStart(client); ++ case X_VncChromiumMonitor: ++ return SProcVncChromiumMonitor(client); ++#endif ++ default: ++ return BadRequest; ++ } ++} /* SProcVncDispatch */ ++ ++static void ++SwapVncConnectedEvent(xVncConnectedEvent *from, xVncConnectedEvent *to) ++{ ++ to->type = from->type; ++ to->detail = from->detail; ++ cpswaps(from->sequenceNumber, to->sequenceNumber); ++ cpswapl(from->connected, to->connected); ++} ++ ++#ifdef CHROMIUM ++static void ++SwapVncChromiumConnectedEvent(xVncConnectedEvent *from, xVncConnectedEvent *to) ++{ ++ to->type = from->type; ++ to->detail = from->detail; ++ cpswaps(from->sequenceNumber, to->sequenceNumber); ++ cpswapl(from->connected, to->connected); ++} ++#endif ++ ++static void ++SwapVncDisconnectedEvent(xVncConnectedEvent *from, xVncConnectedEvent *to) ++{ ++ to->type = from->type; ++ to->detail = from->detail; ++ cpswaps(from->sequenceNumber, to->sequenceNumber); ++ cpswapl(from->connected, to->connected); ++} ++ ++int ++GenerateVncConnectedEvent(int sock) ++{ ++#if USE_ORIG_RES_CODE ++ VncNotifyListPtr pn; ++ ++ pn = (VncNotifyListPtr)LookupIDByType(faked, VncNotifyList); ++#else ++ VncClientRecPtr pn = ClientsList; ++#endif ++ ++ while (pn) ++ { ++ if (pn->client) ++ { ++ xVncConnectedEvent conn; ++ SOCKLEN_T peer_len; ++ struct sockaddr_in peer; ++ ++ conn.type = VncEventBase + XVncConnected; ++ conn.sequenceNumber = pn->client->sequence; ++ conn.connected = sock; ++ ++ peer_len = sizeof(peer); ++ if (getpeername(sock, (struct sockaddr *) &peer, &peer_len) == -1) ++ conn.ipaddress = 0; ++ else ++ conn.ipaddress = (CARD32)peer.sin_addr.s_addr; ++ ++ (void) TryClientEvents(pn->client, (xEventPtr)&conn, 1, NoEventMask, ++ NoEventMask, NullGrab); ++ } ++ pn = pn->next; ++ } ++ ++ return 1; ++} ++ ++ ++ ++#ifdef CHROMIUM ++int ++GenerateVncChromiumConnectedEvent(int sock) ++{ ++#if USE_ORIG_RES_CODE ++ VncNotifyListPtr pn; ++ pn = (VncNotifyListPtr)LookupIDByType(faked, VncNotifyList); ++#else ++ VncClientRecPtr pn = ClientsList; ++#endif ++ rfbLog("Enter GenerateVncChromiumConnectedEvent\n"); ++ while (pn) ++ { ++ if (pn->client) ++ { ++ xVncConnectedEvent conn; ++ SOCKLEN_T peer_len; ++ struct sockaddr_in peer; ++ ++ rfbLog("Sending XVncChromiumConnected to client %p\n", ++ (void *) pn->client); ++ ++ conn.type = VncEventBase + XVncChromiumConnected; ++ conn.sequenceNumber = pn->client->sequence; ++ conn.connected = sock; ++ ++ peer_len = sizeof(peer); ++ if (getpeername(sock, (struct sockaddr *)&peer, &peer_len) == -1) ++ conn.ipaddress = 0; ++ else ++ conn.ipaddress = (CARD32)peer.sin_addr.s_addr; ++ ++ (void) TryClientEvents(pn->client, (xEventPtr)&conn, 1, NoEventMask, ++ NoEventMask, NullGrab); ++ } ++ pn = pn->next; ++ } ++ return 1; ++} ++#endif /* CHROMIUM */ ++ ++ ++int ++GenerateVncDisconnectedEvent(int sock) ++{ ++#if USE_ORIG_RES_CODE ++ VncNotifyListPtr pn; ++ ++ pn = (VncNotifyListPtr)LookupIDByType(faked, VncNotifyList); ++#else ++ VncClientRecPtr pn = ClientsList; ++#endif ++ rfbLog("GenerateVncDisconnectedEvent\n"); ++ while (pn) ++ { ++ if (pn->client) ++ { ++ xVncDisconnectedEvent conn; ++ conn.type = VncEventBase + XVncDisconnected; ++ conn.sequenceNumber = pn->client->sequence; ++ conn.connected = sock; ++ (void) TryClientEvents(pn->client, (xEventPtr)&conn, 1, NoEventMask, ++ NoEventMask, NullGrab); ++ } ++ pn = pn->next; ++ } ++ ++ return 1; ++} ++ ++static void ++VncResetProc(ExtensionEntry *extEntry) ++{ ++} /* VncResetProc */ ++ ++ ++ ++/** ++ * When the app calls libVnc's XVncSelectNotify() we wind up here. ++ * Either add or remove 'client' from the VncNotifyList depending on 'onoff'. ++ */ ++int ++VncSelectNotify(ClientPtr client, BOOL onoff) ++{ ++#if USE_ORIG_RES_CODE ++ VncNotifyListPtr head, newRec, tmp, freeRec = NULL; ++ ++ rfbLog("%s client %p onoff=%d\n", __func__, (void *) client, (int) onoff); ++ if (!faked) ++ faked = FakeClientID(client->index); ++#else ++ /* ignore onoff param */ ++ VncSaveClientRecord(client); ++#endif ++ ++#if USE_ORIG_RES_CODE ++ /* Get the first VncNotifyListPtr */ ++ head = (VncNotifyListPtr) LookupIDByType(faked, VncNotifyList); ++ ++ /* search list for this client */ ++ tmp = head; ++ while (tmp) { ++ if (tmp->client == client) { ++ /* found client! */ ++ if (!onoff) ++ tmp->client = NULL; ++ return Success; ++ } ++ if (!tmp->client) ++ freeRec = tmp; /* save ptr to free record */ ++ tmp = tmp->next; ++ } ++ ++ /* if we get here, we didn't find client in the list */ ++ ++ if (!onoff) { ++ /* if turning off non-existing client, just return */ ++ return Success; ++ } ++ ++ /* OK, add new client to list now */ ++ ++ if (freeRec) { ++ /* re-using a free spot */ ++ freeRec->client = client; ++ return Success; ++ } ++ ++ /* need to allocate new node */ ++ if (!(newRec = (VncNotifyListPtr)xalloc(sizeof(VncNotifyListRec)))) ++ return BadAlloc; ++ /* insert at head, just as AddResource() does!!! */ ++ newRec->next = head; ++ newRec->client = client; ++ if (!AddResource(faked, VncNotifyList, newRec)) { ++ xfree(newRec); ++ return BadAlloc; ++ } ++#endif ++ return Success; ++} ++ ++ ++#if USE_ORIG_RES_CODE ++static int ++VncDestroyNotifyList(pointer pn, XID id) ++{ ++ VncNotifyListPtr cpn = (VncNotifyListPtr) pn; ++ rfbLog("%s client %p\n", __func__, (void *) cpn->client); ++ cpn->client = NULL; ++ return Success; ++} ++#endif ++ ++static Bool ++CreateResourceTypes(void) ++{ ++#if USE_ORIG_RES_CODE ++ if (VncResourceGeneration == serverGeneration) ++ return TRUE; ++ ++ VncResourceGeneration = serverGeneration; ++ ++ if (!(VncNotifyList = CreateNewResourceType(VncDestroyNotifyList))) { ++ ErrorF("CreateResourceTypes: failed to allocate vnc notify list resource.\n"); ++ return FALSE; ++ } ++#endif ++ return TRUE; ++} ++ ++ ++ ++#if XFREE86VNC ++static unsigned long vncCreateScreenResourcesIndex; ++static unsigned long vncExtGeneration = 0; ++extern Bool VNCInit(ScreenPtr pScreen, unsigned char *FBStart); ++ ++/* copied from miscrinit.c */ ++typedef struct ++{ ++ pointer pbits; /* pointer to framebuffer */ ++ int width; /* delta to add to a framebuffer addr to move one row down */ ++} miScreenInitParmsRec, *miScreenInitParmsPtr; ++ ++ ++static Bool ++vncCreateScreenResources(ScreenPtr pScreen) ++{ ++ int ret = TRUE; ++ CreateScreenResourcesProcPtr CreateScreenResources = ++ (CreateScreenResourcesProcPtr) ++ pScreen->devPrivates[vncCreateScreenResourcesIndex].ptr; ++ miScreenInitParmsPtr pScrInitParms; ++ ++ pScrInitParms = (miScreenInitParmsPtr)pScreen->devPrivate; ++ ++ if ( pScreen->CreateScreenResources != vncCreateScreenResources ) { ++ /* Can't find hook we are hung on */ ++ xf86DrvMsg(pScreen->myNum, X_WARNING /* X_ERROR */, ++ "vncCreateScreenResources %p called when not in " ++ "pScreen->CreateScreenResources %p n", ++ (void *) vncCreateScreenResources, ++ (void *) pScreen->CreateScreenResources ); ++ } ++ ++ /* Now do our stuff */ ++ VNCInit(pScreen, pScrInitParms->pbits); ++ ++ /* Unhook this function ... */ ++ pScreen->CreateScreenResources = CreateScreenResources; ++ pScreen->devPrivates[vncCreateScreenResourcesIndex].ptr = NULL; ++ ++ /* ... and call the previous CreateScreenResources fuction, if any */ ++ if (pScreen->CreateScreenResources) { ++ ret = (*pScreen->CreateScreenResources)(pScreen); ++ } ++ ++#ifdef DEBUG ++ ErrorF("vncCreateScreenResources() returns %d\n", ret); ++#endif ++ return ret; ++} ++#endif ++ ++ ++ ++void ++VncExtensionInit(void) ++{ ++ ExtensionEntry *extEntry; ++ ++#if XFREE86VNC ++ if (vncExtGeneration != serverGeneration) { ++ unsigned int i; ++ ++ vncExtGeneration = serverGeneration; ++ ++ if ( ((vncCreateScreenResourcesIndex = AllocateScreenPrivateIndex()) < 0) || ++ ((vncScreenPrivateIndex = AllocateScreenPrivateIndex()) < 0) || ++ ((rfbGCIndex = AllocateGCPrivateIndex()) < 0) ) ++ return; ++ ++ for (i = 0 ; i < screenInfo.numScreens; i++) ++ { ++ screenInfo.screens[i]->devPrivates[vncCreateScreenResourcesIndex].ptr ++ = (void*)(xf86Screens[i]->pScreen->CreateScreenResources); ++ xf86Screens[i]->pScreen->CreateScreenResources = vncCreateScreenResources; ++ } ++ ++ gethostname(rfbThisHost, 255); ++ } ++#endif ++ ++ if (!CreateResourceTypes()) ++ return; ++ ++ extEntry = AddExtension(VNC_EXTENSION_NAME, ++ XVncNumberEvents, XVncNumberErrors, ++ ProcVncDispatch, SProcVncDispatch, ++ VncResetProc, StandardMinorOpcode); ++ ++ VncErrorBase = extEntry->errorBase; ++ VncEventBase = extEntry->eventBase; ++ ++ EventSwapVector[VncEventBase + XVncConnected] = ++ (EventSwapPtr)SwapVncConnectedEvent; ++ EventSwapVector[VncEventBase + XVncDisconnected] = ++ (EventSwapPtr)SwapVncDisconnectedEvent; ++#ifdef CHROMIUM ++ EventSwapVector[VncEventBase + XVncChromiumConnected] = ++ (EventSwapPtr)SwapVncChromiumConnectedEvent; ++#endif ++} /* VncExtensionInit */ +diff -pNur xorg-server-1.4.orig/hw/vnc/xistubs.c xorg-server-1.4/hw/vnc/xistubs.c +--- xorg-server-1.4.orig/hw/vnc/xistubs.c 1969-12-31 16:00:00.000000000 -0800 ++++ xorg-server-1.4/hw/vnc/xistubs.c 2007-09-06 16:09:45.000000000 -0700 +@@ -0,0 +1,323 @@ ++/* $Xorg: stubs.c,v 1.4 2001/02/09 02:04:35 xorgcvs Exp $ */ ++ ++/************************************************************ ++ ++Copyright 1989, 1998 The Open Group ++ ++Permission to use, copy, modify, distribute, and sell this software and its ++documentation for any purpose is hereby granted without fee, provided that ++the above copyright notice appear in all copies and that both that ++copyright notice and this permission notice appear in supporting ++documentation. ++ ++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 ++OPEN GROUP 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 Open Group 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 Open Group. ++ ++Copyright 1989 by Hewlett-Packard Company, Palo Alto, California. ++ ++ All Rights Reserved ++ ++Permission to use, copy, modify, and distribute this software and its ++documentation for any purpose and without fee is hereby granted, ++provided that the above copyright notice appear in all copies and that ++both that copyright notice and this permission notice appear in ++supporting documentation, and that the name of Hewlett-Packard not be ++used in advertising or publicity pertaining to distribution of the ++software without specific, written prior permission. ++ ++HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ++ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL ++HEWLETT-PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ++ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, ++WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ++ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS ++SOFTWARE. ++ ++********************************************************/ ++/* $XFree86: xc/programs/Xserver/Xi/stubs.c,v 3.3 2001/01/17 22:13:26 dawes Exp $ */ ++ ++/* ++ * stubs.c -- stub routines for the X server side of the XINPUT ++ * extension. This file is mainly to be used only as documentation. ++ * There is not much code here, and you can't get a working XINPUT ++ * server just using this. ++ * The Xvfb server uses this file so it will compile with the same ++ * object files as the real X server for a platform that has XINPUT. ++ * Xnest could do the same thing. ++ */ ++#ifdef HAVE_DIX_CONFIG_H ++#include ++#endif ++ ++ ++#define NEED_EVENTS ++#include ++#include ++#include ++#include ++#include "inputstr.h" ++#include "XIstubs.h" ++ ++/*********************************************************************** ++ * ++ * Caller: ProcXChangeKeyboardDevice ++ * ++ * This procedure does the implementation-dependent portion of the work ++ * needed to change the keyboard device. ++ * ++ * The X keyboard device has a FocusRec. If the device that has been ++ * made into the new X keyboard did not have a FocusRec, ++ * ProcXChangeKeyboardDevice will allocate one for it. ++ * ++ * If you do not want clients to be able to focus the old X keyboard ++ * device, call DeleteFocusClassDeviceStruct to free the FocusRec. ++ * ++ * If you support input devices with keys that you do not want to be ++ * used as the X keyboard, you need to check for them here and return ++ * a BadDevice error. ++ * ++ * The default implementation is to do nothing (assume you do want ++ * clients to be able to focus the old X keyboard). The commented-out ++ * sample code shows what you might do if you don't want the default. ++ * ++ */ ++ ++int ++ChangeKeyboardDevice (old_dev, new_dev) ++ DeviceIntPtr old_dev; ++ DeviceIntPtr new_dev; ++ { ++ /*********************************************************************** ++ DeleteFocusClassDeviceStruct(old_dev); * defined in xchgptr.c * ++ **********************************************************************/ ++ return BadMatch; ++ } ++ ++ ++/*********************************************************************** ++ * ++ * Caller: ProcXChangePointerDevice ++ * ++ * This procedure does the implementation-dependent portion of the work ++ * needed to change the pointer device. ++ * ++ * The X pointer device does not have a FocusRec. If the device that ++ * has been made into the new X pointer had a FocusRec, ++ * ProcXChangePointerDevice will free it. ++ * ++ * If you want clients to be able to focus the old pointer device that ++ * has now become accessible through the input extension, you need to ++ * add a FocusRec to it here. ++ * ++ * The XChangePointerDevice protocol request also allows the client ++ * to choose which axes of the new pointer device are used to move ++ * the X cursor in the X- and Y- directions. If the axes are different ++ * than the default ones, you need to keep track of that here. ++ * ++ * If you support input devices with valuators that you do not want to be ++ * used as the X pointer, you need to check for them here and return a ++ * BadDevice error. ++ * ++ * The default implementation is to do nothing (assume you don't want ++ * clients to be able to focus the old X pointer). The commented-out ++ * sample code shows what you might do if you don't want the default. ++ * ++ */ ++ ++int ++#if NeedFunctionPrototypes ++ChangePointerDevice ( ++ DeviceIntPtr old_dev, ++ DeviceIntPtr new_dev, ++ unsigned char x, ++ unsigned char y) ++#else ++ChangePointerDevice (old_dev, new_dev, x, y) ++ DeviceIntPtr old_dev, new_dev; ++ unsigned char x, y; ++#endif ++ { ++ /*********************************************************************** ++ InitFocusClassDeviceStruct(old_dev); * allow focusing old ptr* ++ ++ x_axis = x; * keep track of new x-axis* ++ y_axis = y; * keep track of new y-axis* ++ if (x_axis != 0 || y_axis != 1) ++ axes_changed = TRUE; * remember axes have changed* ++ else ++ axes_changed = FALSE; ++ *************************************************************************/ ++ return BadMatch; ++ } ++ ++/*********************************************************************** ++ * ++ * Caller: ProcXCloseDevice ++ * ++ * Take care of implementation-dependent details of closing a device. ++ * Some implementations may actually close the device, others may just ++ * remove this clients interest in that device. ++ * ++ * The default implementation is to do nothing (assume all input devices ++ * are initialized during X server initialization and kept open). ++ * ++ */ ++ ++void ++CloseInputDevice (d, client) ++ DeviceIntPtr d; ++ ClientPtr client; ++ { ++ } ++ ++/*********************************************************************** ++ * ++ * Caller: ProcXListInputDevices ++ * ++ * This is the implementation-dependent routine to initialize an input ++ * device to the point that information about it can be listed. ++ * Some implementations open all input devices when the server is first ++ * initialized, and never close them. Other implementations open only ++ * the X pointer and keyboard devices during server initialization, ++ * and only open other input devices when some client makes an ++ * XOpenDevice request. If some other process has the device open, the ++ * server may not be able to get information about the device to list it. ++ * ++ * This procedure should be used by implementations that do not initialize ++ * all input devices at server startup. It should do device-dependent ++ * initialization for any devices not previously initialized, and call ++ * AddInputDevice for each of those devices so that a DeviceIntRec will be ++ * created for them. ++ * ++ * The default implementation is to do nothing (assume all input devices ++ * are initialized during X server initialization and kept open). ++ * The commented-out sample code shows what you might do if you don't want ++ * the default. ++ * ++ */ ++ ++void ++AddOtherInputDevices () ++ { ++ /********************************************************************** ++ for each uninitialized device, do something like: ++ ++ DeviceIntPtr dev; ++ DeviceProc deviceProc; ++ pointer private; ++ ++ dev = (DeviceIntPtr) AddInputDevice(deviceProc, TRUE); ++ dev->public.devicePrivate = private; ++ RegisterOtherDevice(dev); ++ dev->inited = ((*dev->deviceProc)(dev, DEVICE_INIT) == Success); ++ ************************************************************************/ ++ ++ } ++ ++/*********************************************************************** ++ * ++ * Caller: ProcXOpenDevice ++ * ++ * This is the implementation-dependent routine to open an input device. ++ * Some implementations open all input devices when the server is first ++ * initialized, and never close them. Other implementations open only ++ * the X pointer and keyboard devices during server initialization, ++ * and only open other input devices when some client makes an ++ * XOpenDevice request. This entry point is for the latter type of ++ * implementation. ++ * ++ * If the physical device is not already open, do it here. In this case, ++ * you need to keep track of the fact that one or more clients has the ++ * device open, and physically close it when the last client that has ++ * it open does an XCloseDevice. ++ * ++ * The default implementation is to do nothing (assume all input devices ++ * are opened during X server initialization and kept open). ++ * ++ */ ++ ++void ++OpenInputDevice (dev, client, status) ++ DeviceIntPtr dev; ++ ClientPtr client; ++ int *status; ++ { ++ } ++ ++/**************************************************************************** ++ * ++ * Caller: ProcXSetDeviceMode ++ * ++ * Change the mode of an extension device. ++ * This function is used to change the mode of a device from reporting ++ * relative motion to reporting absolute positional information, and ++ * vice versa. ++ * The default implementation below is that no such devices are supported. ++ * ++ */ ++ ++int ++SetDeviceMode (client, dev, mode) ++ register ClientPtr client; ++ DeviceIntPtr dev; ++ int mode; ++ { ++ return BadMatch; ++ } ++ ++/**************************************************************************** ++ * ++ * Caller: ProcXSetDeviceValuators ++ * ++ * Set the value of valuators on an extension input device. ++ * This function is used to set the initial value of valuators on ++ * those input devices that are capable of reporting either relative ++ * motion or an absolute position, and allow an initial position to be set. ++ * The default implementation below is that no such devices are supported. ++ * ++ */ ++ ++int ++SetDeviceValuators (client, dev, valuators, first_valuator, num_valuators) ++ register ClientPtr client; ++ DeviceIntPtr dev; ++ int *valuators; ++ int first_valuator; ++ int num_valuators; ++ { ++ return BadMatch; ++ } ++ ++/**************************************************************************** ++ * ++ * Caller: ProcXChangeDeviceControl ++ * ++ * Change the specified device controls on an extension input device. ++ * ++ */ ++ ++int ++ChangeDeviceControl (client, dev, control) ++ register ClientPtr client; ++ DeviceIntPtr dev; ++ xDeviceCtl *control; ++ { ++ switch (control->control) ++ { ++ case DEVICE_RESOLUTION: ++ return (BadMatch); ++ default: ++ return (BadMatch); ++ } ++ } +diff -pNur xorg-server-1.4.orig/hw/vnc/zlib.c xorg-server-1.4/hw/vnc/zlib.c +--- xorg-server-1.4.orig/hw/vnc/zlib.c 1969-12-31 16:00:00.000000000 -0800 ++++ xorg-server-1.4/hw/vnc/zlib.c 2007-09-06 16:09:45.000000000 -0700 +@@ -0,0 +1,310 @@ ++/* ++ * zlib.c ++ * ++ * Routines to implement zlib based encoding (deflate). ++ * ++ * Modified for XFree86 4.x by Alan Hourihane ++ */ ++ ++/* ++ * Copyright (C) 2000 Tridia Corporation. All Rights Reserved. ++ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. ++ * ++ * This is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This software is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this software; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, ++ * USA. ++ * ++ * For the latest source code, please check: ++ * ++ * http://www.developVNC.org/ ++ * ++ * or send email to feedback@developvnc.org. ++ */ ++#ifdef HAVE_DIX_CONFIG_H ++#include ++#endif ++ ++ ++#include ++#include "rfb.h" ++ ++/* ++ * zlibBeforeBuf contains pixel data in the client's format. ++ * zlibAfterBuf contains the zlib (deflated) encoding version. ++ * If the zlib compressed/encoded version is ++ * larger than the raw data or if it exceeds zlibAfterBufSize then ++ * raw encoding is used instead. ++ */ ++ ++static int zlibBeforeBufSize = 0; ++static unsigned char *zlibBeforeBuf = NULL; ++ ++static int zlibAfterBufSize = 0; ++static unsigned char *zlibAfterBuf = NULL; ++static int zlibAfterBufLen; ++ ++/* ++ * rfbSendOneRectEncodingZlib - send a given rectangle using one Zlib ++ * rectangle encoding. ++ */ ++ ++Bool ++rfbSendOneRectEncodingZlib(cl, x, y, w, h) ++ rfbClientPtr cl; ++ int x, y, w, h; ++{ ++ VNCSCREENPTR(cl->pScreen); ++ rfbFramebufferUpdateRectHeader rect; ++ rfbZlibHeader hdr; ++ int deflateResult; ++ int previousOut; ++ int i; ++ int maxRawSize; ++ int maxCompSize; ++ ++ maxRawSize = (pVNC->width * pVNC->height ++ * (cl->format.bitsPerPixel / 8)); ++ ++ if (zlibBeforeBufSize < maxRawSize) { ++ zlibBeforeBufSize = maxRawSize; ++ if (zlibBeforeBuf == NULL) ++ zlibBeforeBuf = (unsigned char *)xalloc(zlibBeforeBufSize); ++ else ++ zlibBeforeBuf = (unsigned char *)xrealloc(zlibBeforeBuf, zlibBeforeBufSize); ++ } ++ ++ /* zlib compression is not useful for very small data sets. ++ * So, we just send these raw without any compression. ++ */ ++ if (( w * h * (pVNC->bitsPerPixel / 8)) < ++ VNC_ENCODE_ZLIB_MIN_COMP_SIZE ) { ++ ++ int result; ++ ++ /* The translation function (used also by the in raw encoding) ++ * requires 4/2/1 byte alignment in the output buffer (which is ++ * pVNC->updateBuf for the raw encoding) based on the bitsPerPixel of ++ * the viewer/client. This prevents SIGBUS errors on some ++ * architectures like SPARC, PARISC... ++ */ ++ if (( cl->format.bitsPerPixel > 8 ) && ++ ( pVNC->ublen % ( cl->format.bitsPerPixel / 8 )) != 0 ) { ++ if (!rfbSendUpdateBuf(cl)) ++ return FALSE; ++ } ++ ++ result = rfbSendRectEncodingRaw(cl, x, y, w, h); ++ ++ return result; ++ ++ } ++ ++ /* ++ * zlib requires output buffer to be slightly larger than the input ++ * buffer, in the worst case. ++ */ ++ maxCompSize = maxRawSize + (( maxRawSize + 99 ) / 100 ) + 12; ++ ++ if (zlibAfterBufSize < maxCompSize) { ++ zlibAfterBufSize = maxCompSize; ++ if (zlibAfterBuf == NULL) ++ zlibAfterBuf = (unsigned char *)xalloc(zlibAfterBufSize); ++ else ++ zlibAfterBuf = (unsigned char *)xrealloc(zlibAfterBuf, zlibAfterBufSize); ++ } ++ ++ /* ++ * Convert pixel data to client format. ++ */ ++ (*cl->translateFn)(cl->pScreen, cl->translateLookupTable, ++ &pVNC->rfbServerFormat, ++ &cl->format, zlibBeforeBuf, ++ pVNC->paddedWidthInBytes, w, h, x, y); ++ ++ cl->compStream.next_in = ( Bytef * )zlibBeforeBuf; ++ cl->compStream.avail_in = w * h * (cl->format.bitsPerPixel / 8); ++ cl->compStream.next_out = ( Bytef * )zlibAfterBuf; ++ cl->compStream.avail_out = maxCompSize; ++ cl->compStream.data_type = Z_BINARY; ++ ++ /* Initialize the deflation state. */ ++ if ( cl->compStreamInited == FALSE ) { ++ ++ cl->compStream.total_in = 0; ++ cl->compStream.total_out = 0; ++ cl->compStream.zalloc = Z_NULL; ++ cl->compStream.zfree = Z_NULL; ++ cl->compStream.opaque = Z_NULL; ++ ++ deflateInit2( &(cl->compStream), ++ cl->zlibCompressLevel, ++ Z_DEFLATED, ++ MAX_WBITS, ++ MAX_MEM_LEVEL, ++ Z_DEFAULT_STRATEGY ); ++ /* deflateInit( &(cl->compStream), Z_BEST_COMPRESSION ); */ ++ /* deflateInit( &(cl->compStream), Z_BEST_SPEED ); */ ++ cl->compStreamInited = TRUE; ++ ++ } ++ ++ previousOut = cl->compStream.total_out; ++ ++ /* Perform the compression here. */ ++ deflateResult = deflate( &(cl->compStream), Z_SYNC_FLUSH ); ++ ++ /* Find the total size of the resulting compressed data. */ ++ zlibAfterBufLen = cl->compStream.total_out - previousOut; ++ ++ if ( deflateResult != Z_OK ) { ++ rfbLog("zlib deflation error: %s\n", cl->compStream.msg); ++ return FALSE; ++ } ++ ++ /* Note that it is not possible to switch zlib parameters based on ++ * the results of the compression pass. The reason is ++ * that we rely on the compressor and decompressor states being ++ * in sync. Compressing and then discarding the results would ++ * cause lose of synchronization. ++ */ ++ ++ /* Update statics */ ++ cl->rfbRectanglesSent[rfbEncodingZlib]++; ++ cl->rfbBytesSent[rfbEncodingZlib] += (sz_rfbFramebufferUpdateRectHeader ++ + sz_rfbZlibHeader + zlibAfterBufLen); ++ ++ if (pVNC->ublen + sz_rfbFramebufferUpdateRectHeader + sz_rfbZlibHeader ++ > UPDATE_BUF_SIZE) ++ { ++ if (!rfbSendUpdateBuf(cl)) ++ return FALSE; ++ } ++ ++ rect.r.x = Swap16IfLE(x); ++ rect.r.y = Swap16IfLE(y); ++ rect.r.w = Swap16IfLE(w); ++ rect.r.h = Swap16IfLE(h); ++ rect.encoding = Swap32IfLE(rfbEncodingZlib); ++ ++ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&rect, ++ sz_rfbFramebufferUpdateRectHeader); ++ pVNC->ublen += sz_rfbFramebufferUpdateRectHeader; ++ ++ hdr.nBytes = Swap32IfLE(zlibAfterBufLen); ++ ++ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&hdr, sz_rfbZlibHeader); ++ pVNC->ublen += sz_rfbZlibHeader; ++ ++ for (i = 0; i < zlibAfterBufLen;) { ++ ++ int bytesToCopy = UPDATE_BUF_SIZE - pVNC->ublen; ++ ++ if (i + bytesToCopy > zlibAfterBufLen) { ++ bytesToCopy = zlibAfterBufLen - i; ++ } ++ ++ memcpy(&pVNC->updateBuf[pVNC->ublen], &zlibAfterBuf[i], bytesToCopy); ++ ++ pVNC->ublen += bytesToCopy; ++ i += bytesToCopy; ++ ++ if (pVNC->ublen == UPDATE_BUF_SIZE) { ++ if (!rfbSendUpdateBuf(cl)) ++ return FALSE; ++ } ++ } ++ ++ return TRUE; ++ ++} ++ ++ ++/* ++ * rfbSendRectEncodingZlib - send a given rectangle using one or more ++ * Zlib encoding rectangles. ++ */ ++ ++Bool ++rfbSendRectEncodingZlib(cl, x, y, w, h) ++ rfbClientPtr cl; ++ int x, y, w, h; ++{ ++ VNCSCREENPTR(cl->pScreen); ++ int maxLines; ++ int linesRemaining; ++ rfbRectangle partialRect; ++ ++ partialRect.x = x; ++ partialRect.y = y; ++ partialRect.w = w; ++ partialRect.h = h; ++ ++ /* Determine maximum pixel/scan lines allowed per rectangle. */ ++ maxLines = ( ZLIB_MAX_SIZE(w) / w ); ++ ++ /* Initialize number of scan lines left to do. */ ++ linesRemaining = h; ++ ++ /* Loop until all work is done. */ ++ while ( linesRemaining > 0 ) { ++ ++ int linesToComp; ++ ++ if ( maxLines < linesRemaining ) ++ linesToComp = maxLines; ++ else ++ linesToComp = linesRemaining; ++ ++ partialRect.h = linesToComp; ++ ++ /* Encode (compress) and send the next rectangle. */ ++ if ( ! rfbSendOneRectEncodingZlib( cl, ++ partialRect.x, ++ partialRect.y, ++ partialRect.w, ++ partialRect.h )) { ++ ++ return FALSE; ++ } ++ ++ /* Technically, flushing the buffer here is not extrememly ++ * efficient. However, this improves the overall throughput ++ * of the system over very slow networks. By flushing ++ * the buffer with every maximum size zlib rectangle, we ++ * improve the pipelining usage of the server CPU, network, ++ * and viewer CPU components. Insuring that these components ++ * are working in parallel actually improves the performance ++ * seen by the user. ++ * Since, zlib is most useful for slow networks, this flush ++ * is appropriate for the desired behavior of the zlib encoding. ++ */ ++ if (( pVNC->ublen > 0 ) && ++ ( linesToComp == maxLines )) { ++ if (!rfbSendUpdateBuf(cl)) { ++ ++ return FALSE; ++ } ++ } ++ ++ /* Update remaining and incremental rectangle location. */ ++ linesRemaining -= linesToComp; ++ partialRect.y += linesToComp; ++ ++ } ++ ++ return TRUE; ++ ++} ++ ++ +diff -pNur xorg-server-1.4.orig/hw/xfree86/dixmods/Makefile.am xorg-server-1.4/hw/xfree86/dixmods/Makefile.am +--- xorg-server-1.4.orig/hw/xfree86/dixmods/Makefile.am 2007-08-23 12:05:48.000000000 -0700 ++++ xorg-server-1.4/hw/xfree86/dixmods/Makefile.am 2007-09-06 16:09:46.000000000 -0700 +@@ -14,6 +14,10 @@ if DBE + DBEMOD = libdbe.la + endif + ++if XCLIPLIST ++XCLIPLISTMOD = libxcliplist.la ++endif ++ + if AFB + AFBMOD = libafb.la + endif +@@ -36,6 +40,7 @@ module_LTLIBRARIES = $(AFBMOD) \ + extsmoduledir = $(moduledir)/extensions + extsmodule_LTLIBRARIES = librecord.la \ + $(DBEMOD) \ ++ $(XCLIPLISTMOD) \ + $(GLXMODS) \ + $(XTRAPMOD) + +@@ -46,6 +51,7 @@ fontsmodule_LTLIBRARIES = libfreetype.la + AM_CFLAGS = @XORG_CFLAGS@ @DIX_CFLAGS@ + INCLUDES = @XORG_INCS@ \ + -I$(top_srcdir)/dbe \ ++ -I$(top_srcdir)/xcliplist \ + -I$(top_srcdir)/hw/xfree86/loader \ + -I$(top_srcdir)/miext/shadow \ + -I$(top_srcdir)/GL/glx +@@ -70,6 +76,10 @@ libdbe_la_LDFLAGS = -avoid-version + libdbe_la_LIBADD = $(top_builddir)/dbe/libdbe.la + libdbe_la_SOURCES = dbemodule.c + ++libxcliplist_la_LDFLAGS = -avoid-version ++libxcliplist_la_LIBADD = $(top_builddir)/xcliplist/libxcliplist.la ++libxcliplist_la_SOURCES = $(top_srcdir)/xcliplist/cliplistmod.c ++ + libfb_la_LDFLAGS = -avoid-version + libfb_la_LIBADD = $(top_builddir)/fb/libfb.la + libfb_la_SOURCES = $(top_builddir)/fb/fbcmap_mi.c fbmodule.c +diff -pNur xorg-server-1.4.orig/hw/xfree86/Makefile.am xorg-server-1.4/hw/xfree86/Makefile.am +--- xorg-server-1.4.orig/hw/xfree86/Makefile.am 2007-08-23 12:04:53.000000000 -0700 ++++ xorg-server-1.4/hw/xfree86/Makefile.am 2007-09-06 16:09:46.000000000 -0700 +@@ -4,6 +4,10 @@ if DRI + DRI_SUBDIR = dri + endif + ++if VNC ++VNC_SUBDIR = vnc ++endif ++ + if XF86UTILS + XF86UTILS_SUBDIR = utils + endif +@@ -21,12 +25,12 @@ DOC_SUBDIR = doc + SUBDIRS = common ddc dummylib i2c x86emu int10 fbdevhw os-support parser rac \ + ramdac shadowfb vbe vgahw xaa $(MFB_SUBDIR) $(CFB_SUBDIR) \ + loader scanpci dixmods exa modes \ +- $(DRI_SUBDIR) $(XF86UTILS_SUBDIR) $(DOC_SUBDIR) ++ $(DRI_SUBDIR) $(XF86UTILS_SUBDIR) $(DOC_SUBDIR) $(VNC_SUBDIR) + + DIST_SUBDIRS = common ddc dummylib i2c x86emu int10 fbdevhw os-support \ + parser rac ramdac shadowfb vbe vgahw xaa xf1bpp xf4bpp \ + xf8_16bpp xf8_32bpp loader scanpci dixmods dri exa modes \ +- utils doc ++ utils doc vnc + + bin_PROGRAMS = Xorg + +diff -pNur xorg-server-1.4.orig/hw/xfree86/vnc/Makefile.am xorg-server-1.4/hw/xfree86/vnc/Makefile.am +--- xorg-server-1.4.orig/hw/xfree86/vnc/Makefile.am 1969-12-31 16:00:00.000000000 -0800 ++++ xorg-server-1.4/hw/xfree86/vnc/Makefile.am 2007-09-06 16:09:51.000000000 -0700 +@@ -0,0 +1,53 @@ ++libvnc_la_LTLIBRARIES = libvnc.la ++libvnc_la_CFLAGS = -I$(top_srcdir)/hw/xfree86/common \ ++ -I$(top_srcdir)/hw/xfree86/os-support \ ++ -I$(top_srcdir)/hw/xfree86/os-support/bus \ ++ -I$(top_srcdir)/mi \ ++ -I$(top_srcdir)/render \ ++ -I$(top_srcdir)/GL/glx \ ++ -I$(top_srcdir)/GL/include \ ++ -I$(top_builddir)/GL/include \ ++ -I@MESA_SOURCE@/include \ ++ -DHAVE_XORG_CONFIG_H \ ++ -DXFree86LOADER \ ++ -DXFREE86VNC=1 \ ++ -DCHROMIUM=1 \ ++ @LIBDRM_CFLAGS@ \ ++ @GL_CFLAGS@ \ ++ @PIXMAN_CFLAGS@ ++ ++# @MODULE_DEFINES@ ++# @LOADER_DEFINES@ ++ ++libvnc_la_LIBADD = -ljpeg -lcrypt ++libvnc_la_LDFLAGS = -module -avoid-version ++libvnc_ladir = $(moduledir)/extensions ++libvnc_la_SOURCES = \ ++ auth.c \ ++ cmap.c \ ++ corre.c \ ++ cursor.c \ ++ cutpaste.c \ ++ d3des.c \ ++ dispcur.c \ ++ draw.c \ ++ hextile.c \ ++ httpd.c \ ++ kbdptr.c \ ++ loginauth.c \ ++ rdp.c \ ++ rfbkeyb.c \ ++ rfbmouse.c \ ++ rfbserver.c \ ++ rre.c \ ++ sockets.c \ ++ sprite.c \ ++ stats.c \ ++ tight.c \ ++ translate.c \ ++ vncInit.c \ ++ vncauth.c \ ++ vncext.c \ ++ zlib.c ++ ++#sdk_HEADERS = vncint.h +diff -pNur xorg-server-1.4.orig/hw/xfree86/vnc/README xorg-server-1.4/hw/xfree86/vnc/README +--- xorg-server-1.4.orig/hw/xfree86/vnc/README 1969-12-31 16:00:00.000000000 -0800 ++++ xorg-server-1.4/hw/xfree86/vnc/README 2007-09-06 16:09:46.000000000 -0700 +@@ -0,0 +1 @@ ++This directory contains the sources for building the vnc.so server extension module. +diff -pNur xorg-server-1.4.orig/hw/xfree86/vnc/vncInit.c xorg-server-1.4/hw/xfree86/vnc/vncInit.c +--- xorg-server-1.4.orig/hw/xfree86/vnc/vncInit.c 1969-12-31 16:00:00.000000000 -0800 ++++ xorg-server-1.4/hw/xfree86/vnc/vncInit.c 2007-09-06 16:09:46.000000000 -0700 +@@ -0,0 +1,638 @@ ++/* ++ * Copyright (C) 2002 Alan Hourihane. 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. ++ * ++ * Author: Alan Hourihane ++ */ ++#ifdef HAVE_DIX_CONFIG_H ++#include ++#endif ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "../ramdac/xf86CursorPriv.h" ++#include "rfb.h" ++#include "vncint.h" ++ ++#include "xf86.h" ++#include "xf86_OSproc.h" ++#include "xf86Resources.h" ++#include "xf86Version.h" ++ ++int vncScreenPrivateIndex = -1; ++int rfbGCIndex = -1; ++int inetdSock = -1; ++Atom VNC_LAST_CLIENT_ID = 0; ++Atom VNC_CONNECT = 0; ++char *desktopName = "x11"; ++char rfbThisHost[256]; ++ ++extern void VncExtensionInit(void); ++ ++Bool VNCInit(ScreenPtr pScreen, unsigned char *FBStart); ++ ++#ifndef XFree86LOADER ++static unsigned long VNCGeneration = 0; ++#endif ++static const OptionInfoRec *VNCAvailableOptions(void *unused); ++static void rfbWakeupHandler (int i, pointer blockData, unsigned long err, pointer pReadmask); ++ ++static Bool vncCursorRealizeCursor(ScreenPtr, CursorPtr); ++static Bool vncCursorUnrealizeCursor(ScreenPtr, CursorPtr); ++static void vncCursorSetCursor(ScreenPtr, CursorPtr, int, int); ++static void vncCursorMoveCursor(ScreenPtr, int, int); ++static Bool vncDisplayCursor(ScreenPtr, CursorPtr); ++ ++static miPointerSpriteFuncRec vncCursorSpriteFuncs = { ++ vncCursorRealizeCursor, ++ vncCursorUnrealizeCursor, ++ vncCursorSetCursor, ++ vncCursorMoveCursor ++}; ++ ++/* ++ * VNC Config options ++ */ ++ ++typedef enum { ++ OPTION_USEVNC, ++ OPTION_RFBPORT, ++ OPTION_HTTPPORT, ++ OPTION_ALWAYS_SHARED, ++ OPTION_NEVER_SHARED, ++ OPTION_DONT_DISCONNECT, ++ OPTION_HTTPDIR, ++ OPTION_PASSWD_FILE, ++ OPTION_USER_ACCEPT, ++ OPTION_LOCALHOST, ++ OPTION_INTERFACE, ++ OPTION_VIEWONLY, ++ OPTION_LOGIN_AUTH, ++} VNCOpts; ++ ++static const OptionInfoRec VNCOptions[] = { ++ {OPTION_USEVNC, "usevnc", OPTV_BOOLEAN, {0}, FALSE }, ++ {OPTION_RFBPORT, "rfbport", OPTV_INTEGER, {0}, FALSE }, ++ {OPTION_HTTPPORT, "httpport", OPTV_INTEGER, {0}, FALSE }, ++ {OPTION_ALWAYS_SHARED, "alwaysshared", OPTV_BOOLEAN, {0}, FALSE }, ++ {OPTION_NEVER_SHARED, "nevershared", OPTV_BOOLEAN, {0}, FALSE }, ++ {OPTION_DONT_DISCONNECT, "dontdisconnect", OPTV_BOOLEAN, {0}, FALSE }, ++ {OPTION_HTTPDIR, "httpdir", OPTV_STRING, {0}, FALSE }, ++ {OPTION_PASSWD_FILE, "rfbauth", OPTV_STRING, {0}, FALSE }, ++ {OPTION_USER_ACCEPT, "useraccept", OPTV_BOOLEAN, {0}, FALSE }, ++ {OPTION_LOCALHOST, "localhost", OPTV_BOOLEAN, {0}, FALSE }, ++ {OPTION_INTERFACE, "interface", OPTV_STRING, {0}, FALSE }, ++ {OPTION_VIEWONLY, "viewonly", OPTV_BOOLEAN, {0}, FALSE }, ++ {OPTION_LOGIN_AUTH, "loginauth", OPTV_BOOLEAN, {0}, FALSE }, ++ { -1, NULL, OPTV_NONE, {0}, FALSE } ++}; ++ ++/*ARGSUSED*/ ++static const OptionInfoRec * ++VNCAvailableOptions(void *unused) ++{ ++ return (VNCOptions); ++} ++ ++/* ++ * rfbLog prints a time-stamped message to the log file (stderr). ++ */ ++ ++void rfbLog(char *format, ...) ++{ ++ va_list ap; ++ char buf[256]; ++ time_t clock; ++ ++ time(&clock); ++ strftime(buf, 255, "%d/%m/%Y %H:%M:%S ", localtime(&clock)); ++ xf86DrvMsgVerb(-1, X_INFO, 1, buf); ++ ++ va_start(ap, format); ++ xf86VDrvMsgVerb(-1, X_NONE, 1, format, ap); ++ va_end(ap); ++} ++ ++void rfbLogPerror(char *str) ++{ ++ rfbLog(""); ++ perror(str); ++} ++ ++/* ++ * Called by vncCreateScreenResources() ++ */ ++Bool ++VNCInit(ScreenPtr pScreen, unsigned char *FBStart) ++{ ++ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; ++ VisualPtr visual; ++ vncScreenPtr pScreenPriv; ++ OptionInfoPtr options; ++ char *interface_str = NULL; ++ miPointerScreenPtr PointPriv; ++ xf86CursorScreenPtr xf86CursorPriv; ++#ifdef RENDER ++ PictureScreenPtr ps; ++#endif ++ ++ if (!FBStart) ++ return FALSE; ++ ++#ifndef XFree86LOADER ++ if (VNCGeneration != serverGeneration) { ++ VncExtensionInit(); ++ VNCGeneration = serverGeneration; ++ } ++#endif ++ ++ if (!AllocateGCPrivate(pScreen, rfbGCIndex, sizeof(rfbGCRec))) ++ return FALSE; ++ ++ if (!(pScreenPriv = xalloc(sizeof(vncScreenRec)))) ++ return FALSE; ++ ++ pScreen->devPrivates[vncScreenPrivateIndex].ptr = (pointer)pScreenPriv; ++ ++ options = xnfalloc(sizeof(VNCOptions)); ++ (void)memcpy(options, VNCOptions, sizeof(VNCOptions)); ++ xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options); ++ ++ if (xf86ReturnOptValBool(options, OPTION_USEVNC, FALSE)) { ++ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "VNC enabled\n"); ++ } else { ++ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VNC disabled\n"); ++ xfree(options); ++ return FALSE; ++ } ++ ++ pScreenPriv->rfbAuthTries = 0; ++ pScreenPriv->rfbAuthTooManyTries = FALSE; ++ pScreenPriv->timer = NULL; ++ pScreenPriv->udpPort = 0; ++ pScreenPriv->rfbListenSock = -1; ++ pScreenPriv->udpSock = -1; ++ pScreenPriv->udpSockConnected = FALSE; ++ pScreenPriv->httpListenSock = -1; ++ pScreenPriv->httpSock = -1; ++ pScreenPriv->maxFd = 0; ++ pScreenPriv->rfbAuthPasswdFile = NULL; ++ pScreenPriv->httpDir = NULL; ++ pScreenPriv->rfbInstalledColormap = NULL; ++ pScreenPriv->interface.s_addr = htonl (INADDR_ANY); ++ ++ pScreenPriv->rfbPort = 0; ++ xf86GetOptValInteger(options, OPTION_RFBPORT, &pScreenPriv->rfbPort); ++ pScreenPriv->httpPort = 0; ++ xf86GetOptValInteger(options, OPTION_HTTPPORT, &pScreenPriv->httpPort); ++ pScreenPriv->rfbAuthPasswdFile = ++ xf86GetOptValString(options, OPTION_PASSWD_FILE); ++ pScreenPriv->httpDir = ++ xf86GetOptValString(options, OPTION_HTTPDIR); ++ pScreenPriv->rfbAlwaysShared = FALSE; ++ xf86GetOptValBool(options, OPTION_ALWAYS_SHARED, ++ &pScreenPriv->rfbAlwaysShared); ++ pScreenPriv->rfbNeverShared = FALSE; ++ xf86GetOptValBool(options, OPTION_NEVER_SHARED, ++ &pScreenPriv->rfbNeverShared); ++ pScreenPriv->rfbUserAccept = FALSE; ++ xf86GetOptValBool(options, OPTION_USER_ACCEPT, ++ &pScreenPriv->rfbUserAccept); ++ pScreenPriv->rfbViewOnly = FALSE; ++ xf86GetOptValBool(options, OPTION_VIEWONLY, ++ &pScreenPriv->rfbViewOnly); ++ pScreenPriv->rfbDontDisconnect = FALSE; ++ xf86GetOptValBool(options, OPTION_DONT_DISCONNECT, ++ &pScreenPriv->rfbDontDisconnect); ++ pScreenPriv->loginAuthEnabled = FALSE; ++ xf86GetOptValBool(options, OPTION_LOGIN_AUTH, ++ &pScreenPriv->loginAuthEnabled); ++ ++ if (xf86ReturnOptValBool(options, OPTION_LOCALHOST, FALSE)) ++ pScreenPriv->interface.s_addr = htonl (INADDR_LOOPBACK); ++ ++ interface_str = xf86GetOptValString(options, OPTION_INTERFACE); ++ ++ if (interface_str && pScreenPriv->interface.s_addr == htonl(INADDR_ANY)) { ++ Bool failed = FALSE; ++ struct in_addr got; ++ unsigned long octet; ++ char *p = interface_str, *end; ++ int q; ++ ++ for (q = 0; q < 4; q++) { ++ octet = strtoul (p, &end, 10); ++ ++ if (p == end || octet > 255) ++ failed = TRUE; ++ ++ if ((q < 3 && *end != '.') || ++ (q == 3 && *end != '\0')) ++ failed = TRUE; ++ ++ got.s_addr = (got.s_addr << 8) | octet; ++ p = end + 1; ++ } ++ ++ if (!failed) ++ pScreenPriv->interface.s_addr = htonl (got.s_addr); ++ else ++ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VNC interface option malformed, not using.\n"); ++ } ++ ++ xfree(options); ++ ++ if (!VNC_LAST_CLIENT_ID) ++ VNC_LAST_CLIENT_ID = MakeAtom("VNC_LAST_CLIENT_ID", ++ strlen("VNC_LAST_CLIENT_ID"), TRUE); ++ if (!VNC_CONNECT) ++ VNC_CONNECT = MakeAtom("VNC_CONNECT", strlen("VNC_CONNECT"), TRUE); ++ ++ rfbInitSockets(pScreen); ++ if (inetdSock == -1) ++ httpInitSockets(pScreen); ++ ++#ifdef CORBA ++ initialiseCORBA(argc, argv, desktopName); ++#endif ++ ++ pScreenPriv->width = pScrn->virtualX; ++ pScreenPriv->height = pScrn->virtualY; ++ pScreenPriv->depth = pScrn->depth; ++ pScreenPriv->paddedWidthInBytes = PixmapBytePad(pScrn->displayWidth, pScrn->depth); ++ pScreenPriv->bitsPerPixel = rfbBitsPerPixel(pScrn->depth); ++ pScreenPriv->pfbMemory = FBStart; ++ pScreenPriv->oldpfbMemory = FBStart; ++ ++ pScreenPriv->cursorIsDrawn = TRUE; ++ pScreenPriv->dontSendFramebufferUpdate = FALSE; ++ ++ pScreenPriv->CloseScreen = pScreen->CloseScreen; ++ pScreenPriv->CreateGC = pScreen->CreateGC; ++ pScreenPriv->PaintWindowBackground = pScreen->PaintWindowBackground; ++ pScreenPriv->PaintWindowBorder = pScreen->PaintWindowBorder; ++ pScreenPriv->CopyWindow = pScreen->CopyWindow; ++ pScreenPriv->ClearToBackground = pScreen->ClearToBackground; ++ pScreenPriv->RestoreAreas = pScreen->RestoreAreas; ++ pScreenPriv->WakeupHandler = pScreen->WakeupHandler; ++ pScreenPriv->EnableDisableFBAccess = pScrn->EnableDisableFBAccess; ++ pScreenPriv->InstallColormap = pScreen->InstallColormap; ++ pScreenPriv->UninstallColormap = pScreen->UninstallColormap; ++ pScreenPriv->ListInstalledColormaps = pScreen->ListInstalledColormaps; ++ pScreenPriv->StoreColors = pScreen->StoreColors; ++ pScreenPriv->DisplayCursor = pScreen->DisplayCursor; ++#ifdef CHROMIUM ++ pScreenPriv->RealizeWindow = pScreen->RealizeWindow; ++ pScreenPriv->UnrealizeWindow = pScreen->UnrealizeWindow; ++ pScreenPriv->DestroyWindow = pScreen->DestroyWindow; ++ pScreenPriv->PositionWindow = pScreen->PositionWindow; ++ pScreenPriv->ResizeWindow = pScreen->ResizeWindow; ++ pScreenPriv->ClipNotify = pScreen->ClipNotify; ++#endif ++#ifdef RENDER ++ ps = GetPictureScreenIfSet(pScreen); ++ if (ps) ++ pScreenPriv->Composite = ps->Composite; ++#endif ++ pScreen->CloseScreen = rfbCloseScreen; ++ pScreen->CreateGC = rfbCreateGC; ++ pScreen->PaintWindowBackground = rfbPaintWindowBackground; ++ pScreen->PaintWindowBorder = rfbPaintWindowBorder; ++ pScreen->CopyWindow = rfbCopyWindow; ++ pScreen->ClearToBackground = rfbClearToBackground; ++ pScreen->RestoreAreas = rfbRestoreAreas; ++ pScreen->WakeupHandler = rfbWakeupHandler; ++ pScrn->EnableDisableFBAccess = rfbEnableDisableFBAccess; ++ pScreen->InstallColormap = rfbInstallColormap; ++ pScreen->UninstallColormap = rfbUninstallColormap; ++ pScreen->ListInstalledColormaps = rfbListInstalledColormaps; ++ pScreen->StoreColors = rfbStoreColors; ++ pScreen->DisplayCursor = vncDisplayCursor; /* it's defined in here */ ++ ++#ifdef CHROMIUM ++ pScreen->RealizeWindow = rfbRealizeWindow; ++ pScreen->UnrealizeWindow = rfbUnrealizeWindow; ++ pScreen->DestroyWindow = rfbDestroyWindow; ++ pScreen->PositionWindow = rfbPositionWindow; ++ pScreen->ResizeWindow = rfbResizeWindow; ++ pScreen->ClipNotify = rfbClipNotify; ++#endif ++#ifdef RENDER ++ if (ps) ++ ps->Composite = rfbComposite; ++#endif ++ ++ for (visual = pScreen->visuals; visual->vid != pScreen->rootVisual; visual++) ++ ; ++ ++ if (!visual) { ++ ErrorF("rfbScreenInit: couldn't find root visual\n"); ++ return FALSE; ++ } ++ ++ pScreenPriv->rfbServerFormat.bitsPerPixel = pScrn->bitsPerPixel; ++ pScreenPriv->rfbServerFormat.depth = pScrn->depth; ++ pScreenPriv->rfbServerFormat.bigEndian = !(*(char *)&rfbEndianTest); ++ pScreenPriv->rfbServerFormat.trueColour = (visual->class == TrueColor); ++ if (pScreenPriv->rfbServerFormat.trueColour) { ++ pScreenPriv->rfbServerFormat.redMax = visual->redMask >> visual->offsetRed; ++ pScreenPriv->rfbServerFormat.greenMax = visual->greenMask >> visual->offsetGreen; ++ pScreenPriv->rfbServerFormat.blueMax = visual->blueMask >> visual->offsetBlue; ++ pScreenPriv->rfbServerFormat.redShift = visual->offsetRed; ++ pScreenPriv->rfbServerFormat.greenShift = visual->offsetGreen; ++ pScreenPriv->rfbServerFormat.blueShift = visual->offsetBlue; ++ } else { ++ pScreenPriv->rfbServerFormat.redMax ++ = pScreenPriv->rfbServerFormat.greenMax ++ = pScreenPriv->rfbServerFormat.blueMax = 0; ++ pScreenPriv->rfbServerFormat.redShift ++ = pScreenPriv->rfbServerFormat.greenShift ++ = pScreenPriv->rfbServerFormat.blueShift = 0; ++ } ++ ++ PointPriv = pScreen->devPrivates[miPointerScreenIndex].ptr; ++ ++ pScreenPriv->spriteFuncs = PointPriv->spriteFuncs; ++ PointPriv->spriteFuncs = &vncCursorSpriteFuncs; ++ ++ if (xf86LoaderCheckSymbol("xf86CursorScreenIndex")) { ++ int *si; ++ ++ si = LoaderSymbol("xf86CursorScreenIndex"); ++ ++ if (*si != -1) { ++ xf86CursorPriv = pScreen->devPrivates[*si].ptr; ++ ++ if (xf86CursorPriv) { ++ pScreenPriv->UseHWCursor = xf86CursorPriv->CursorInfoPtr->UseHWCursor; ++ xf86CursorPriv->CursorInfoPtr->UseHWCursor = vncUseHWCursor; ++#ifdef ARGB_CURSOR ++ pScreenPriv->UseHWCursorARGB = xf86CursorPriv->CursorInfoPtr->UseHWCursorARGB; ++ xf86CursorPriv->CursorInfoPtr->UseHWCursorARGB = vncUseHWCursorARGB; ++#endif ++ pScreenPriv->SWCursor = &xf86CursorPriv->SWCursor; ++ } ++ } ++ } ++ ++ return TRUE; ++} ++ ++/****** miPointerSpriteFunctions *******/ ++ ++static Bool ++vncCursorRealizeCursor(ScreenPtr pScreen, CursorPtr pCurs) ++{ ++ vncScreenPtr pScreenPriv = VNCPTR(pScreen); ++ ++ return (*pScreenPriv->spriteFuncs->RealizeCursor)(pScreen, pCurs); ++} ++ ++static Bool ++vncCursorUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCurs) ++{ ++ vncScreenPtr pScreenPriv = VNCPTR(pScreen); ++ ++ return (*pScreenPriv->spriteFuncs->UnrealizeCursor)(pScreen, pCurs); ++} ++ ++static void ++vncCursorSetCursor(ScreenPtr pScreen, CursorPtr pCurs, int x, int y) ++{ ++ vncScreenPtr pScreenPriv = VNCPTR(pScreen); ++ ++ pScreenPriv->pCurs = pCurs; ++ ++ /* Without this call, cursor changes only appear in the viewer when ++ * some other drawing has occured. Added by BrianP. ++ */ ++ rfbScheduleUpdate(pScreen); ++ ++#if 0 ++ if (pCurs == NullCursor) { /* means we're supposed to remove the cursor */ ++ if (pScreenPriv->cursorIsDrawn) ++ pScreenPriv->cursorIsDrawn = FALSE; ++ return; ++ } ++ ++ pScreenPriv->cursorIsDrawn = TRUE; ++#endif ++ ++ (*pScreenPriv->spriteFuncs->SetCursor)(pScreen, pCurs, x, y); ++} ++ ++static void ++vncCursorMoveCursor(ScreenPtr pScreen, int x, int y) ++{ ++ vncScreenPtr pScreenPriv = VNCPTR(pScreen); ++ rfbClientPtr cl; ++ ++ for (cl = rfbClientHead; cl ; cl = cl->next) { ++ if (cl->enableCursorPosUpdates) ++ cl->cursorWasMoved = TRUE; ++ } ++ ++ (*pScreenPriv->spriteFuncs->MoveCursor)(pScreen, x, y); ++} ++ ++Bool ++vncUseHWCursor(pScreen, pCursor) ++ ScreenPtr pScreen; ++ CursorPtr pCursor; ++{ ++ vncScreenPtr pScreenPriv = VNCPTR(pScreen); ++ rfbClientPtr cl; ++ ++ if (!*pScreenPriv->UseHWCursor) { ++ /* If the driver doesn't have a UseHWCursor function we're ++ * basically saying we can have the HWCursor on all the time ++ */ ++ pScreenPriv->SWCursor = (Bool *)FALSE; ++ return TRUE; ++ } ++ ++ pScreenPriv->SWCursor = (Bool *)FALSE; ++ ++ /* If someone's connected, we revert to software cursor */ ++ for (cl = rfbClientHead; cl ; cl = cl->next) { ++ if (!cl->enableCursorShapeUpdates) ++ pScreenPriv->SWCursor = (Bool *)TRUE; ++ } ++ ++ if (pScreenPriv->SWCursor == (Bool *)TRUE) ++ return FALSE; ++ ++ return (*pScreenPriv->UseHWCursor)(pScreen, pCursor); ++} ++ ++#ifdef ARGB_CURSOR ++#include "cursorstr.h" ++ ++Bool ++vncUseHWCursorARGB(pScreen, pCursor) ++ ScreenPtr pScreen; ++ CursorPtr pCursor; ++{ ++ vncScreenPtr pScreenPriv = VNCPTR(pScreen); ++ rfbClientPtr cl; ++ ++ if (!*pScreenPriv->UseHWCursorARGB) { ++ pScreenPriv->SWCursor = (Bool *)TRUE; ++ return FALSE; ++ } ++ ++ pScreenPriv->SWCursor = (Bool *)FALSE; ++ ++ /* If someone's connected, we revert to software cursor */ ++ for (cl = rfbClientHead; cl ; cl = cl->next) { ++ if (!cl->enableCursorShapeUpdates) ++ pScreenPriv->SWCursor = (Bool *)TRUE; ++ } ++ ++ if (pScreenPriv->SWCursor == (Bool *)TRUE) ++ return FALSE; ++ ++ return (*pScreenPriv->UseHWCursorARGB)(pScreen, pCursor); ++} ++#endif ++ ++static Bool ++vncDisplayCursor(pScreen, pCursor) ++ ScreenPtr pScreen; ++ CursorPtr pCursor; ++{ ++ vncScreenPtr pScreenPriv = VNCPTR(pScreen); ++ rfbClientPtr cl; ++ Bool ret; ++ ++ pScreen->DisplayCursor = pScreenPriv->DisplayCursor; ++ ++ for (cl = rfbClientHead; cl ; cl = cl->next) { ++ if (cl->enableCursorShapeUpdates) ++ cl->cursorWasChanged = TRUE; ++ } ++ ++ ret = (*pScreen->DisplayCursor)(pScreen, pCursor); ++ ++ pScreen->DisplayCursor = vncDisplayCursor; ++ ++ return ret; ++} ++ ++static void ++rfbWakeupHandler ( ++ int i, ++ pointer blockData, ++ unsigned long err, ++ pointer pReadmask ++){ ++ ScreenPtr pScreen = screenInfo.screens[i]; ++ vncScreenPtr pScreenPriv = VNCPTR(pScreen); ++ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; ++ int sigstate = xf86BlockSIGIO(); ++ ++ rfbRootPropertyChange(pScreen); /* Check clipboard */ ++ ++ if (pScrn->vtSema) { ++ rfbCheckFds(pScreen); ++ httpCheckFds(pScreen); ++#ifdef CORBA ++ corbaCheckFds(); ++#endif ++ } else { ++ rfbCheckFds(pScreen); ++ } ++ ++ xf86UnblockSIGIO(sigstate); ++ ++ pScreen->WakeupHandler = pScreenPriv->WakeupHandler; ++ (*pScreen->WakeupHandler) (i, blockData, err, pReadmask); ++ pScreen->WakeupHandler = rfbWakeupHandler; ++} ++ ++#ifdef XFree86LOADER ++static MODULESETUPPROTO(vncSetup); ++ ++static XF86ModuleVersionInfo vncVersRec = ++{ ++ "vnc", ++ "xf4vnc Project, see http://xf4vnc.sf.net (based on modular X.org)", ++ MODINFOSTRING1, ++ MODINFOSTRING2, ++ XORG_VERSION_CURRENT, ++ 1, 1, 0, ++ ABI_CLASS_EXTENSION, ++#if 0 ++ ABI_EXTENSION_VERSION, ++#else ++ /* Hack to allow module to work with more servers (vs. 0.3 above) */ ++ SET_ABI_VERSION(0, 2), ++#endif ++ MOD_CLASS_EXTENSION, ++ {0,0,0,0} ++}; ++ ++XF86ModuleData vncModuleData = { ++ &vncVersRec, /* vers */ ++ vncSetup, /* ModuleSetupProc */ ++ NULL /* ModuleTearDownProc */ ++}; ++ ++ModuleInfoRec VNC = { ++ 1, /* moduleVersion */ ++ "VNC", /* moduleName */ ++ NULL, /* module pointer */ ++ 0, /* refCount */ ++ VNCAvailableOptions, /* function returning array of OptionsInfoRec */ ++}; ++ ++ExtensionModule vncExtensionModule = { ++ VncExtensionInit, /* initFunc */ ++ "VNC", /* name */ ++ NULL, /* disablePtr */ ++ NULL, /* setupFunc */ ++ NULL /* initDependencies */ ++}; ++ ++ ++/*ARGSUSED*/ ++static pointer ++vncSetup(pointer Module, pointer Options, int *ErrorMajor, int *ErrorMinor) ++{ ++ static Bool Initialised = FALSE; ++ ++ if (!Initialised) { ++ Initialised = TRUE; ++#ifndef REMOVE_LOADER_CHECK_MODULE_INFO ++ if (xf86LoaderCheckSymbol("xf86AddModuleInfo")) ++#endif ++ xf86AddModuleInfo(&VNC, Module); ++ } ++ ++ LoadExtension(&vncExtensionModule, FALSE); ++ /* add mouse/kbd input drivers */ ++ vncInitMouse(); ++ vncInitKeyb(); ++ xf86Msg(X_INFO, "Ignore errors regarding the loading of the rfbmouse & rfbkeyb drivers\n"); ++ ++ return (pointer)TRUE; ++} ++#endif +diff -pNur xorg-server-1.4.orig/hw/xfree86/vnc/vncint.h xorg-server-1.4/hw/xfree86/vnc/vncint.h +--- xorg-server-1.4.orig/hw/xfree86/vnc/vncint.h 1969-12-31 16:00:00.000000000 -0800 ++++ xorg-server-1.4/hw/xfree86/vnc/vncint.h 2007-09-06 16:09:46.000000000 -0700 +@@ -0,0 +1,154 @@ ++/* ++ * Copyright (C) 2002 Alan Hourihane. 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. ++ * ++ * Author: Alan Hourihane ++ */ ++ ++#ifndef _VNC_H_ ++#define _VNC_H_ ++ ++#include ++/*#include */ ++ ++extern int vncScreenPrivateIndex; ++ ++#define VNCPTR(pScreen)\ ++ (vncScreenPtr)((pScreen)->devPrivates[vncScreenPrivateIndex].ptr) ++ ++typedef struct { ++ int rfbPort; ++ int rdpPort; ++ int udpPort; ++ int rfbListenSock; ++ int rdpListenSock; ++ int udpSock; ++ int httpPort; ++ int httpListenSock; ++ int httpSock; ++ char * httpDir; ++ char buf[HTTP_BUF_SIZE]; ++ Bool udpSockConnected; ++ char * rfbAuthPasswdFile; ++ size_t buf_filled; ++ int maxFd; ++ fd_set allFds; ++ unsigned char * oldpfbMemory; ++ Bool rfbAlwaysShared; ++ Bool rfbNeverShared; ++ Bool rfbDontDisconnect; ++ Bool rfbUserAccept; ++ Bool rfbViewOnly; ++ unsigned char * pfbMemory; ++ int paddedWidthInBytes; ++ ColormapPtr rfbInstalledColormap; ++ ColormapPtr savedColormap; ++ rfbPixelFormat rfbServerFormat; ++ Bool rfbAuthTooManyTries; ++ int rfbAuthTries; ++ Bool loginAuthEnabled; ++ struct in_addr interface; ++ OsTimerPtr timer; ++ unsigned char updateBuf[UPDATE_BUF_SIZE]; ++ int ublen; ++ int width; ++ int height; ++ int depth; ++ int bitsPerPixel; ++ ++ /* The following two members are used to minimise the amount of unnecessary ++ drawing caused by cursor movement. Whenever any drawing affects the ++ part of the screen where the cursor is, the cursor is removed first and ++ then the drawing is done (this is what the sprite routines test for). ++ Afterwards, however, we do not replace the cursor, even when the cursor ++ is logically being moved across the screen. We only draw the cursor ++ again just as we are about to send the client a framebuffer update. ++ ++ We need to be careful when removing and drawing the cursor because of ++ their relationship with the normal drawing routines. The drawing ++ routines can invoke the cursor routines, but also the cursor routines ++ themselves end up invoking drawing routines. ++ ++ Removing the cursor (rfbSpriteRemoveCursor) is eventually achieved by ++ doing a CopyArea from a pixmap to the screen, where the pixmap contains ++ the saved contents of the screen under the cursor. Before doing this, ++ however, we set cursorIsDrawn to FALSE. Then, when CopyArea is called, ++ it sees that cursorIsDrawn is FALSE and so doesn't feel the need to ++ (recursively!) remove the cursor before doing it. ++ ++ Putting up the cursor (rfbSpriteRestoreCursor) involves a call to ++ PushPixels. While this is happening, cursorIsDrawn must be FALSE so ++ that PushPixels doesn't think it has to remove the cursor first. ++ Obviously cursorIsDrawn is set to TRUE afterwards. ++ ++ Another problem we face is that drawing routines sometimes cause a ++ framebuffer update to be sent to the RFB client. When the RFB client is ++ already waiting for a framebuffer update and some drawing to the ++ framebuffer then happens, the drawing routine sees that the client is ++ ready, so it calls rfbSendFramebufferUpdate. If the cursor is not drawn ++ at this stage, it must be put up, and so rfbSpriteRestoreCursor is ++ called. However, if the original drawing routine was actually called ++ from within rfbSpriteRestoreCursor or rfbSpriteRemoveCursor we don't ++ want this to happen. So both the cursor routines set ++ dontSendFramebufferUpdate to TRUE, and all the drawing routines check ++ this before calling rfbSendFramebufferUpdate. */ ++ ++ Bool cursorIsDrawn; /* TRUE if the cursor is currently drawn */ ++ Bool dontSendFramebufferUpdate; /* TRUE while removing or drawing the ++ cursor */ ++ ++ /* wrapped screen functions */ ++ ++ CloseScreenProcPtr CloseScreen; ++ CreateGCProcPtr CreateGC; ++ PaintWindowBackgroundProcPtr PaintWindowBackground; ++ PaintWindowBorderProcPtr PaintWindowBorder; ++ CopyWindowProcPtr CopyWindow; ++ ClearToBackgroundProcPtr ClearToBackground; ++ RestoreAreasProcPtr RestoreAreas; ++ ScreenWakeupHandlerProcPtr WakeupHandler; ++ InstallColormapProcPtr InstallColormap; ++ UninstallColormapProcPtr UninstallColormap; ++ ListInstalledColormapsProcPtr ListInstalledColormaps; ++ StoreColorsProcPtr StoreColors; ++ xf86EnableDisableFBAccessProc *EnableDisableFBAccess; ++ miPointerSpriteFuncPtr spriteFuncs; ++ DisplayCursorProcPtr DisplayCursor; ++ CursorPtr pCurs; ++ Bool (*UseHWCursor)(ScreenPtr, CursorPtr); ++ Bool (*UseHWCursorARGB)(ScreenPtr, CursorPtr); ++ Bool *SWCursor; ++#ifdef CHROMIUM ++ RealizeWindowProcPtr RealizeWindow; ++ UnrealizeWindowProcPtr UnrealizeWindow; ++ DestroyWindowProcPtr DestroyWindow; ++ ResizeWindowProcPtr ResizeWindow; ++ PositionWindowProcPtr PositionWindow; ++ ClipNotifyProcPtr ClipNotify; ++#endif ++#ifdef RENDER ++ CompositeProcPtr Composite; ++#endif ++ ++} vncScreenRec, *vncScreenPtr; ++ ++extern Bool vncUseHWCursor(ScreenPtr pScreen, CursorPtr pCurs); ++extern Bool vncUseHWCursorARGB(ScreenPtr pScreen, CursorPtr pCurs); ++extern void rfbEnableDisableFBAccess (int index, Bool enable); ++ ++#endif /* _VNC_H_ */ ++ +diff -pNur xorg-server-1.4.orig/Makefile.am xorg-server-1.4/Makefile.am +--- xorg-server-1.4.orig/Makefile.am 2007-08-23 12:04:52.000000000 -0700 ++++ xorg-server-1.4/Makefile.am 2007-09-06 16:09:46.000000000 -0700 +@@ -30,6 +30,10 @@ if DBE + DBE_DIR=dbe + endif + ++if XCLIPLIST ++XCLIPLIST_DIR=xcliplist ++endif ++ + SUBDIRS = \ + doc \ + include \ +@@ -54,6 +58,7 @@ SUBDIRS = \ + $(XTRAP_DIR) \ + $(COMPOSITE_DIR) \ + $(GLX_DIR) \ ++ $(XCLIPLIST_DIR) \ + exa \ + config \ + hw +diff -pNur xorg-server-1.4.orig/mi/miinitext.c xorg-server-1.4/mi/miinitext.c +--- xorg-server-1.4.orig/mi/miinitext.c 2007-08-23 12:04:54.000000000 -0700 ++++ xorg-server-1.4/mi/miinitext.c 2007-09-06 16:09:46.000000000 -0700 +@@ -79,6 +79,18 @@ SOFTWARE. + #undef XF86VIDMODE + #endif + ++#ifdef VNCSERVER ++#undef COMPOSITE ++#undef DAMAGE ++#undef DBE ++#undef RANDR ++#undef XF86MISC ++#undef XFreeXDGA ++#undef XF86DRI ++#undef XF86VIDMODE ++#undef XFIXES ++#endif ++ + #include "misc.h" + #include "extension.h" + #include "micmap.h" +diff -pNur xorg-server-1.4.orig/xcliplist/cliplist.c xorg-server-1.4/xcliplist/cliplist.c +--- xorg-server-1.4.orig/xcliplist/cliplist.c 1969-12-31 16:00:00.000000000 -0800 ++++ xorg-server-1.4/xcliplist/cliplist.c 2007-09-06 16:09:46.000000000 -0700 +@@ -0,0 +1,128 @@ ++/* ++ * Server-side code for the Xcliplist extension ++ */ ++ ++#if HAVE_DIX_CONFIG_H ++#include "dix-config.h" ++#endif ++ ++#include ++#include ++ ++#include "dixstruct.h" ++#include "extnsionst.h" ++#include "windowstr.h" ++ ++#define _XCLIPLIST_SERVER_ ++#include ++ ++ ++static int XClipListErrorBase; ++static unsigned char XClipListReqCode = 0; ++ ++static void ++XClipListResetProc(ExtensionEntry* extEntry) ++{ ++ (void)extEntry; ++} ++ ++static int ++ProcXClipListQueryVersion(ClientPtr client) ++{ ++ xXClipListQueryVersionReply rep; ++ ++ REQUEST_SIZE_MATCH(xXClipListQueryVersionReq); ++ rep.type = X_Reply; ++ rep.length = 0; ++ rep.sequenceNumber = client->sequence; ++ rep.majorVersion = XCLIPLIST_MAJOR_VERSION; ++ rep.minorVersion = XCLIPLIST_MINOR_VERSION; ++ rep.patchVersion = XCLIPLIST_PATCH_VERSION; ++ ++ WriteToClient(client, sizeof(xXClipListQueryVersionReply), (char *)&rep); ++ return (client->noClientException); ++} ++ ++static int ++ProcXGetClipList(ClientPtr client) ++{ ++ xXGetClipListReply rep; ++ WindowPtr pWin; ++ int i; ++ BoxPtr pClipRects = NULL; ++ short xorig, yorig; ++ REQUEST(xXGetClipListReq); ++ REQUEST_SIZE_MATCH(xXGetClipListReq); ++ ++ rep.type = X_Reply; ++ rep.length = 0; ++ rep.sequenceNumber = client->sequence; ++ ++ if(!(pWin = (WindowPtr)LOOKUP_DRAWABLE(stuff->windowid, client) )) ++ { ++ client->errorValue = stuff->windowid; ++ return (BadWindow); ++ } ++ ++ rep.num_entries = REGION_NUM_RECTS(&pWin->clipList); ++ ++ WriteToClient(client, sizeof(xXGetClipListReply), (char *)&rep); ++ ++ pClipRects = REGION_RECTS(&pWin->clipList); ++ ++ xorig = pWin->drawable.x; ++ yorig = pWin->drawable.y; ++ ++ for (i = 0; i < rep.num_entries; i++) { ++ BoxRec box; ++ /* translate clip rect from screen coords to window coords */ ++ box.x1 = pClipRects[i].x1 - xorig; ++ box.y1 = pClipRects[i].y1 - yorig; ++ box.x2 = pClipRects[i].x2 - xorig; ++ box.y2 = pClipRects[i].y2 - yorig; ++ /*memcpy(&box, &pClipRects[i], sizeof(BoxRec));*/ ++ WriteToClient(client, sizeof(BoxRec), (char *)&box); ++ } ++ ++ return (client->noClientException); ++} ++ ++static int ++ProcXClipListDispatch (ClientPtr client) ++{ ++ REQUEST(xReq); ++ ++ switch (stuff->data) { ++ case X_XClipListQueryVersion: ++ return ProcXClipListQueryVersion(client); ++ case X_XGetClipList: ++ return ProcXGetClipList(client); ++ default: ++ return BadRequest; ++ } ++} ++ ++static int ++SProcXClipListDispatch (ClientPtr client) ++{ ++ REQUEST(xReq); ++ (void)stuff; ++ return XClipListErrorBase + XClipListClientNotLocal; ++} ++ ++void ++XClipListExtensionInit(void) ++{ ++ ExtensionEntry* extEntry; ++ ++ if ((extEntry = AddExtension(XCLIPLISTNAME, ++ XClipListNumberEvents, ++ XClipListNumberErrors, ++ ProcXClipListDispatch, ++ SProcXClipListDispatch, ++ XClipListResetProc, ++ StandardMinorOpcode))) { ++ XClipListReqCode = (unsigned char)extEntry->base; ++ XClipListErrorBase = extEntry->errorBase; ++ } ++} +diff -pNur xorg-server-1.4.orig/xcliplist/cliplistmod.c xorg-server-1.4/xcliplist/cliplistmod.c +--- xorg-server-1.4.orig/xcliplist/cliplistmod.c 1969-12-31 16:00:00.000000000 -0800 ++++ xorg-server-1.4/xcliplist/cliplistmod.c 2007-09-06 16:09:46.000000000 -0700 +@@ -0,0 +1,46 @@ ++ ++#include "xorg/xf86Module.h" ++ ++extern Bool noTestExtensions; ++ ++static MODULESETUPPROTO(xcliplistSetup); ++ ++extern void XClipListExtensionInit(INITARGS); ++ ++ExtensionModule xcliplistExt = { ++ XClipListExtensionInit, ++ "XClipList", ++ &noTestExtensions, ++ NULL, ++ NULL ++}; ++ ++static XF86ModuleVersionInfo VersRec = { ++ "XClipList", ++ MODULEVENDORSTRING, ++ MODINFOSTRING1, ++ MODINFOSTRING2, ++ XF86_VERSION_CURRENT, /* XXX fix? */ ++ 1, 13, 0, ++ ABI_CLASS_EXTENSION, ++#if 0 ++ ABI_EXTENSION_VERSION, ++#else ++ /* Hack to allow module to work with more servers (vs. 0.3 above) */ ++ SET_ABI_VERSION(0, 2), ++#endif ++ MOD_CLASS_EXTENSION, ++ {0,0,0,0} ++}; ++ ++XF86ModuleData xcliplistModuleData = { &VersRec, xcliplistSetup, NULL }; ++ ++static pointer ++xcliplistSetup(pointer module, pointer opts, int *errmaj, int *errmin) ++{ ++ LoadExtension(&xcliplistExt, FALSE); ++ ++ /* Need a non-NULL return value to indicate success */ ++ return (pointer)1; ++} ++ +diff -pNur xorg-server-1.4.orig/xcliplist/Makefile.am xorg-server-1.4/xcliplist/Makefile.am +--- xorg-server-1.4.orig/xcliplist/Makefile.am 1969-12-31 16:00:00.000000000 -0800 ++++ xorg-server-1.4/xcliplist/Makefile.am 2007-09-06 16:09:46.000000000 -0700 +@@ -0,0 +1,18 @@ ++#noinst_LTLIBRARIES = libxcliplist.la ++libxcliplist_la_LTLIBRARIES = libxcliplist.la ++ ++#AM_CFLAGS = $(DIX_CFLAGS) @SERVER_DEFINES@ @LOADER_DEFINES@ ++AM_CFLAGS = $(DIX_CFLAGS) ++ ++libxcliplist_la_LDFLAGS = -module -avoid-version ++libxcliplist_ladir = $(moduledir)/extensions ++ ++libxcliplist_la_SOURCES = \ ++ cliplist.c \ ++ cliplistmod.c ++ ++## cliplistmod.c ++ ++if XORG ++sdk_HEADERS = ++endif diff --git a/xorg-x11-server.changes b/xorg-x11-server.changes index 7b770a2..fcc023e 100644 --- a/xorg-x11-server.changes +++ b/xorg-x11-server.changes @@ -1,3 +1,8 @@ +------------------------------------------------------------------- +Fri Oct 19 04:03:57 CEST 2007 - sndirsch@suse.de + +- updated xf4vnc patch; still disabled due to problematic vnc module + ------------------------------------------------------------------- Tue Oct 9 19:07:57 CEST 2007 - sndirsch@suse.de diff --git a/xorg-x11-server.spec b/xorg-x11-server.spec index 3071a36..e1b4365 100644 --- a/xorg-x11-server.spec +++ b/xorg-x11-server.spec @@ -21,7 +21,7 @@ BuildRequires: libjpeg-devel Url: http://xorg.freedesktop.org/ %define EXPERIMENTAL 0 Version: 7.3 -Release: 7 +Release: 12 License: X11/MIT BuildRoot: %{_tmppath}/%{name}-%{version}-build Group: System/X11/Servers/XF86_4 @@ -41,9 +41,6 @@ Source4: xorgcfg.tar.bz2 %if %suse_version > 1010 Source5: modprobe.nvidia %endif -%if %vnc -Source6: 0018-vnc-support.txt.mbox -%endif Source7: xorg-docs-1.4.tar.bz2 Source8: xorg.conf.man-070818.tar Source9: ia64Pci.h @@ -74,8 +71,8 @@ Patch32: acpi_events.diff Patch34: p_pci-off-by-one.diff.ia64 Patch36: libdrm.diff %if %vnc -Patch39: 0018-vnc-support.txt -Patch40: 0018-vnc-support.txt.diff +Patch39: xorg-server-1.4-vnc.patch +Patch40: xorg-server-1.4-vnc-fix.patch %endif Patch41: loadmod-bug197195.diff Patch42: bug227111-ddc_screensize.diff @@ -183,7 +180,8 @@ popd %patch36 -p0 %if %vnc %patch39 -p1 -%patch40 -p0 +%patch40 -p1 +chmod 755 hw/vnc/symlink-vnc.sh %endif %patch41 -p1 %patch42 -p0 @@ -219,11 +217,9 @@ autoreconf -fi %endif %if %vnc %ifnarch s390 s390x - --enable-xorg-vnc \ --enable-xcliplist \ %endif - --enable-xdmx-vnc \ - --enable-xvnc \ + --enable-vnc \ %endif --prefix=/usr \ --sysconfdir=/etc \ @@ -314,11 +310,11 @@ rm -f $RPM_BUILD_ROOT/usr/share/aclocal/*.m4 mkdir -p $RPM_BUILD_ROOT/etc/modprobe.d install -m 644 $RPM_SOURCE_DIR/modprobe.nvidia $RPM_BUILD_ROOT/etc/modprobe.d/nvidia %endif -%if %vnc -%ifarch s390 s390x -rm $RPM_BUILD_ROOT/mfb.h -%endif -%endif +#%if %vnc +#%ifarch s390 s390x +#rm $RPM_BUILD_ROOT/mfb.h +#%endif +#%endif %clean rm -rf "$RPM_BUILD_ROOT" @@ -497,11 +493,11 @@ exit 0 /usr/%{_lib}/X11/* /usr/%{_lib}/xorg/modules/ %{_mandir}/man4/* -%{_mandir}/man5/* %endif /usr/%{_lib}/pkgconfig/*.pc /usr/%{_lib}/xserver/ %{_mandir}/man1/* +%{_mandir}/man5/* %{_mandir}/man7/* %ifnarch s390 s390x /var/X11R6/bin/X @@ -529,6 +525,8 @@ exit 0 /usr/bin/Xvnc %endif %changelog +* Fri Oct 19 2007 - sndirsch@suse.de +- updated xf4vnc patch; still disabled due to problematic vnc module * Tue Oct 09 2007 - sndirsch@suse.de - preferred_mode-fix.diff * more reasonable patch (Bug #329724)