From 47ed8d321c32c6b741cff1f4ff686165c4f269f4 Mon Sep 17 00:00:00 2001 From: Constantin Kaplinsky Date: Fri, 8 Oct 2004 09:43:57 +0000 Subject: [PATCH] Initial revision git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@2 3789f03b-4d11-0410-bbf8-ca57d06f2519 --- LICENCE.TXT | 340 +++ Makefile.in | 5 + README | 284 +++ README.hpux | 39 + README.txt | 126 ++ README_BINARY.txt | 120 ++ Xregion/Makefile.in | 15 + Xregion/Region.c | 1687 +++++++++++++++ Xregion/Xregion.dsp | 132 ++ Xregion/Xregion.h | 220 ++ Xregion/region.h | 190 ++ boilerplate.mk | 35 + configure | 2299 +++++++++++++++++++++ configure.in | 99 + depend.mk | 76 + hpux.patch | 255 +++ java/index.vnc | 13 + java/logo150x150.gif | Bin 0 -> 3584 bytes java/vncviewer.jar | Bin 0 -> 81356 bytes logmessages/logmessages.dsp | 202 ++ logmessages/messages.h | 47 + logmessages/messages.mc | 7 + logmessages/messages.rc | 2 + network/Makefile.in | 17 + network/Socket.h | 129 ++ network/TcpSocket.cxx | 458 ++++ network/TcpSocket.h | 100 + network/msvcwarning.h | 18 + network/network.dsp | 129 ++ rdr/Exception.cxx | 64 + rdr/Exception.h | 59 + rdr/FdInStream.cxx | 281 +++ rdr/FdInStream.h | 77 + rdr/FdOutStream.cxx | 174 ++ rdr/FdOutStream.h | 56 + rdr/FixedMemOutStream.h | 52 + rdr/HexInStream.cxx | 117 ++ rdr/HexInStream.h | 50 + rdr/HexOutStream.cxx | 110 + rdr/HexOutStream.h | 51 + rdr/InStream.cxx | 35 + rdr/InStream.h | 153 ++ rdr/Makefile.in | 19 + rdr/MemInStream.h | 63 + rdr/MemOutStream.h | 82 + rdr/NullOutStream.cxx | 60 + rdr/NullOutStream.h | 42 + rdr/OutStream.h | 152 ++ rdr/RandomStream.cxx | 118 ++ rdr/RandomStream.h | 63 + rdr/SubstitutingInStream.h | 102 + rdr/ZlibInStream.cxx | 125 ++ rdr/ZlibInStream.h | 59 + rdr/ZlibOutStream.cxx | 140 ++ rdr/ZlibOutStream.h | 57 + rdr/msvcwarning.h | 18 + rdr/rdr.dsp | 231 +++ rdr/types.h | 56 + rfb/Blacklist.cxx | 86 + rfb/Blacklist.h | 91 + rfb/CConnection.cxx | 291 +++ rfb/CConnection.h | 178 ++ rfb/CMsgHandler.cxx | 99 + rfb/CMsgHandler.h | 62 + rfb/CMsgReader.cxx | 167 ++ rfb/CMsgReader.h | 75 + rfb/CMsgReaderV3.cxx | 97 + rfb/CMsgReaderV3.h | 35 + rfb/CMsgWriter.cxx | 130 ++ rfb/CMsgWriter.h | 64 + rfb/CMsgWriterV3.cxx | 49 + rfb/CMsgWriterV3.h | 35 + rfb/CSecurity.h | 48 + rfb/CSecurityNone.h | 38 + rfb/CSecurityVncAuth.cxx | 63 + rfb/CSecurityVncAuth.h | 40 + rfb/ColourCube.h | 96 + rfb/ColourMap.h | 34 + rfb/ComparingUpdateTracker.cxx | 151 ++ rfb/ComparingUpdateTracker.h | 47 + rfb/Configuration.cxx | 410 ++++ rfb/Configuration.h | 167 ++ rfb/ConnParams.cxx | 104 + rfb/ConnParams.h | 86 + rfb/Cursor.cxx | 178 ++ rfb/Cursor.h | 56 + rfb/Decoder.cxx | 68 + rfb/Decoder.h | 52 + rfb/Encoder.cxx | 75 + rfb/Encoder.h | 57 + rfb/Exception.h | 37 + rfb/HTTPServer.cxx | 386 ++++ rfb/HTTPServer.h | 112 + rfb/HextileDecoder.cxx | 59 + rfb/HextileDecoder.h | 35 + rfb/HextileEncoder.cxx | 61 + rfb/HextileEncoder.h | 35 + rfb/Hostname.h | 53 + rfb/ImageGetter.h | 30 + rfb/LogWriter.cxx | 137 ++ rfb/LogWriter.h | 106 + rfb/Logger.cxx | 107 + rfb/Logger.h | 70 + rfb/Logger_file.cxx | 123 ++ rfb/Logger_file.h | 51 + rfb/Logger_stdio.cxx | 32 + rfb/Logger_stdio.h | 39 + rfb/Makefile.in | 66 + rfb/Pixel.h | 26 + rfb/PixelBuffer.cxx | 309 +++ rfb/PixelBuffer.h | 172 ++ rfb/PixelFormat.cxx | 238 +++ rfb/PixelFormat.h | 58 + rfb/RREDecoder.cxx | 58 + rfb/RREDecoder.h | 35 + rfb/RREEncoder.cxx | 75 + rfb/RREEncoder.h | 37 + rfb/RawDecoder.cxx | 55 + rfb/RawDecoder.h | 35 + rfb/RawEncoder.cxx | 59 + rfb/RawEncoder.h | 35 + rfb/Rect.h | 112 + rfb/Region.cxx | 248 +++ rfb/Region.h | 84 + rfb/SConnection.cxx | 330 +++ rfb/SConnection.h | 207 ++ rfb/SDesktop.h | 123 ++ rfb/SMsgHandler.cxx | 64 + rfb/SMsgHandler.h | 62 + rfb/SMsgReader.cxx | 105 + rfb/SMsgReader.h | 57 + rfb/SMsgReaderV3.cxx | 57 + rfb/SMsgReaderV3.h | 32 + rfb/SMsgWriter.cxx | 180 ++ rfb/SMsgWriter.h | 156 ++ rfb/SMsgWriterV3.cxx | 173 ++ rfb/SMsgWriterV3.h | 56 + rfb/SSecurity.h | 77 + rfb/SSecurityFactoryStandard.cxx | 101 + rfb/SSecurityFactoryStandard.h | 75 + rfb/SSecurityNone.h | 38 + rfb/SSecurityVncAuth.cxx | 83 + rfb/SSecurityVncAuth.h | 54 + rfb/ServerCore.cxx | 95 + rfb/ServerCore.h | 56 + rfb/Threading.h | 31 + rfb/TransImageGetter.cxx | 278 +++ rfb/TransImageGetter.h | 104 + rfb/TrueColourMap.h | 42 + rfb/UpdateTracker.cxx | 172 ++ rfb/UpdateTracker.h | 107 + rfb/UserPasswdGetter.h | 31 + rfb/VNCSConnectionST.cxx | 629 ++++++ rfb/VNCSConnectionST.h | 168 ++ rfb/VNCServer.h | 86 + rfb/VNCServerST.cxx | 430 ++++ rfb/VNCServerST.h | 233 +++ rfb/ZRLEDecoder.cxx | 91 + rfb/ZRLEDecoder.h | 37 + rfb/ZRLEEncoder.cxx | 122 ++ rfb/ZRLEEncoder.h | 53 + rfb/d3des.c | 434 ++++ rfb/d3des.h | 51 + rfb/encodings.cxx | 46 + rfb/encodings.h | 38 + rfb/hextileConstants.h | 27 + rfb/hextileDecode.h | 126 ++ rfb/hextileEncode.h | 247 +++ rfb/keysymdef.h | 1595 ++++++++++++++ rfb/msgTypes.h | 39 + rfb/msvcwarning.h | 20 + rfb/rfb.dsp | 625 ++++++ rfb/rreDecode.h | 64 + rfb/rreEncode.h | 164 ++ rfb/secTypes.cxx | 64 + rfb/secTypes.h | 51 + rfb/transInitTempl.h | 254 +++ rfb/transTempl.h | 151 ++ rfb/util.cxx | 78 + rfb/util.h | 90 + rfb/vncAuth.cxx | 61 + rfb/vncAuth.h | 31 + rfb/win32/Threading_win32.cxx | 155 ++ rfb/win32/Threading_win32.h | 149 ++ rfb/win32/msvcwarning.h | 19 + rfb/win32/util_win32.h | 111 + rfb/zrleDecode.h | 251 +++ rfb/zrleEncode.h | 328 +++ rfb_win32/AboutDialog.cxx | 49 + rfb_win32/AboutDialog.h | 55 + rfb_win32/CKeyboard.cxx | 259 +++ rfb_win32/CKeyboard.h | 53 + rfb_win32/CPointer.cxx | 188 ++ rfb_win32/CPointer.h | 76 + rfb_win32/CleanDesktop.cxx | 255 +++ rfb_win32/CleanDesktop.h | 57 + rfb_win32/Clipboard.cxx | 199 ++ rfb_win32/Clipboard.h | 66 + rfb_win32/CurrentUser.cxx | 93 + rfb_win32/CurrentUser.h | 78 + rfb_win32/DIBSectionBuffer.cxx | 221 ++ rfb_win32/DIBSectionBuffer.h | 87 + rfb_win32/DeviceFrameBuffer.cxx | 298 +++ rfb_win32/DeviceFrameBuffer.h | 121 ++ rfb_win32/Dialog.cxx | 353 ++++ rfb_win32/Dialog.h | 159 ++ rfb_win32/IntervalTimer.h | 70 + rfb_win32/LaunchProcess.cxx | 92 + rfb_win32/LaunchProcess.h | 59 + rfb_win32/MsgWindow.cxx | 116 ++ rfb_win32/MsgWindow.h | 55 + rfb_win32/OSVersion.cxx | 47 + rfb_win32/OSVersion.h | 54 + rfb_win32/RegConfig.cxx | 151 ++ rfb_win32/RegConfig.h | 56 + rfb_win32/Registry.cxx | 272 +++ rfb_win32/Registry.h | 111 + rfb_win32/SDisplay.cxx | 612 ++++++ rfb_win32/SDisplay.h | 149 ++ rfb_win32/SInput.cxx | 459 ++++ rfb_win32/SInput.h | 70 + rfb_win32/Security.h | 198 ++ rfb_win32/Service.cxx | 638 ++++++ rfb_win32/Service.h | 123 ++ rfb_win32/SocketManager.cxx | 246 +++ rfb_win32/SocketManager.h | 107 + rfb_win32/TCharArray.cxx | 85 + rfb_win32/TCharArray.h | 119 ++ rfb_win32/TrayIcon.h | 90 + rfb_win32/WMCursor.cxx | 98 + rfb_win32/WMCursor.h | 65 + rfb_win32/WMHooks.cxx | 324 +++ rfb_win32/WMHooks.h | 85 + rfb_win32/WMNotifier.cxx | 57 + rfb_win32/WMNotifier.h | 68 + rfb_win32/WMPoller.cxx | 101 + rfb_win32/WMPoller.h | 67 + rfb_win32/WMShatter.cxx | 57 + rfb_win32/WMShatter.h | 53 + rfb_win32/WMWindowCopyRect.cxx | 83 + rfb_win32/WMWindowCopyRect.h | 56 + rfb_win32/Win32Util.cxx | 447 ++++ rfb_win32/Win32Util.h | 217 ++ rfb_win32/keymap.h | 149 ++ rfb_win32/msvcwarning.h | 20 + rfb_win32/rfb_win32.dsp | 341 +++ tx/Makefile.in | 18 + tx/TXButton.h | 124 ++ tx/TXCheckbox.h | 142 ++ tx/TXDialog.h | 90 + tx/TXEntry.h | 188 ++ tx/TXImage.cxx | 340 +++ tx/TXImage.h | 89 + tx/TXLabel.h | 126 ++ tx/TXMenu.cxx | 186 ++ tx/TXMenu.h | 67 + tx/TXMsgBox.h | 111 + tx/TXScrollbar.cxx | 119 ++ tx/TXScrollbar.h | 82 + tx/TXViewport.cxx | 157 ++ tx/TXViewport.h | 77 + tx/TXWindow.cxx | 486 +++++ tx/TXWindow.h | 210 ++ tx/Timer.cxx | 105 + tx/Timer.h | 51 + vnc.dsw | 206 ++ vncconfig/Authentication.h | 137 ++ vncconfig/Connections.h | 278 +++ vncconfig/Desktop.h | 93 + vncconfig/Hooking.h | 65 + vncconfig/Inputs.h | 84 + vncconfig/Legacy.cxx | 248 +++ vncconfig/Legacy.h | 86 + vncconfig/Sharing.h | 59 + vncconfig/resource.h | 86 + vncconfig/vncconfig.cxx | 193 ++ vncconfig/vncconfig.dsp | 188 ++ vncconfig/vncconfig.exe.manifest | 22 + vncconfig/vncconfig.ico | Bin 0 -> 1078 bytes vncconfig/vncconfig.rc | 479 +++++ vncconfig_unix/Makefile.in | 23 + vncconfig_unix/buildtime.c | 18 + vncconfig_unix/vncExt.c | 316 +++ vncconfig_unix/vncExt.h | 279 +++ vncconfig_unix/vncconfig.cxx | 313 +++ vncconfig_unix/vncconfig.man | 115 ++ vncinstall | 98 + vncmkdepend/Makefile | 4 + vncmkdepend/README | 39 + vncmkdepend/cppsetup.c | 242 +++ vncmkdepend/def.h | 140 ++ vncmkdepend/ifparser.c | 445 ++++ vncmkdepend/ifparser.h | 76 + vncmkdepend/include.c | 312 +++ vncmkdepend/main.c | 593 ++++++ vncmkdepend/parse.c | 568 +++++ vncmkdepend/pr.c | 130 ++ vncpasswd/Makefile.in | 18 + vncpasswd/vncpasswd.cxx | 119 ++ vncpasswd/vncpasswd.man | 42 + vncserver | 570 +++++ vncserver.man | 120 ++ vncviewer/CViewManager.cxx | 252 +++ vncviewer/CViewManager.h | 64 + vncviewer/CViewOptions.cxx | 364 ++++ vncviewer/CViewOptions.h | 87 + vncviewer/ConnectingDialog.h | 95 + vncviewer/ConnectionDialog.cxx | 70 + vncviewer/ConnectionDialog.h | 52 + vncviewer/InfoDialog.cxx | 65 + vncviewer/InfoDialog.h | 48 + vncviewer/MRU.h | 140 ++ vncviewer/OptionsDialog.cxx | 309 +++ vncviewer/OptionsDialog.h | 49 + vncviewer/UserPasswdDialog.cxx | 84 + vncviewer/UserPasswdDialog.h | 54 + vncviewer/buildTime.cxx | 1 + vncviewer/cursor1.cur | Bin 0 -> 326 bytes vncviewer/cview.cxx | 1468 +++++++++++++ vncviewer/cview.h | 296 +++ vncviewer/msvcwarning.h | 19 + vncviewer/resource.h | 80 + vncviewer/vncviewer.cxx | 370 ++++ vncviewer/vncviewer.dsp | 229 ++ vncviewer/vncviewer.exe.manifest | 22 + vncviewer/vncviewer.ico | Bin 0 -> 8478 bytes vncviewer/vncviewer.rc | 500 +++++ vncviewer_unix/AboutDialog.h | 37 + vncviewer_unix/CConn.cxx | 669 ++++++ vncviewer_unix/CConn.h | 129 ++ vncviewer_unix/DesktopWindow.cxx | 573 +++++ vncviewer_unix/DesktopWindow.h | 128 ++ vncviewer_unix/InfoDialog.h | 60 + vncviewer_unix/Makefile.in | 23 + vncviewer_unix/OptionsDialog.h | 168 ++ vncviewer_unix/PasswdDialog.h | 72 + vncviewer_unix/ServerDialog.h | 91 + vncviewer_unix/buildtime.c | 18 + vncviewer_unix/parameters.h | 44 + vncviewer_unix/vncviewer.cxx | 244 +++ vncviewer_unix/vncviewer.man | 189 ++ winvnc/AddNewClientDialog.h | 56 + winvnc/JavaViewer.cxx | 95 + winvnc/JavaViewer.h | 54 + winvnc/QueryConnectDialog.cxx | 100 + winvnc/QueryConnectDialog.h | 60 + winvnc/STrayIcon.cxx | 234 +++ winvnc/STrayIcon.h | 58 + winvnc/VNCServerService.cxx | 52 + winvnc/VNCServerService.h | 44 + winvnc/VNCServerWin32.cxx | 341 +++ winvnc/VNCServerWin32.h | 99 + winvnc/buildTime.cxx | 1 + winvnc/connected.ico | Bin 0 -> 1078 bytes winvnc/java/index.vnc | 13 + winvnc/java/logo150x150.gif | Bin 0 -> 3584 bytes winvnc/java/vncviewer.jar | Bin 0 -> 81356 bytes winvnc/msvcwarning.h | 19 + winvnc/resource.h | 37 + winvnc/winvnc.cxx | 249 +++ winvnc/winvnc.dsp | 228 ++ winvnc/winvnc.ico | Bin 0 -> 3310 bytes winvnc/winvnc.rc | 254 +++ winvnc/winvnc4.exe.manifest | 22 + wm_hooks/msvcwarning.h | 19 + wm_hooks/resource.h | 15 + wm_hooks/wm_hooks.cxx | 462 +++++ wm_hooks/wm_hooks.def | 5 + wm_hooks/wm_hooks.dsp | 149 ++ wm_hooks/wm_hooks.h | 103 + wm_hooks/wm_hooks.rc | 109 + x0vncserver/Image.cxx | 149 ++ x0vncserver/Image.h | 48 + x0vncserver/Makefile.in | 22 + x0vncserver/buildtime.c | 18 + x0vncserver/x0vncserver.cxx | 277 +++ x0vncserver/x0vncserver.man | 32 + xc.patch | 191 ++ xc/config/cf/host.def | 1 + xc/config/cf/vnc.def | 32 + xc/programs/Xserver/Xvnc.man | 258 +++ xc/programs/Xserver/vnc/Imakefile | 44 + xc/programs/Xserver/vnc/RegionHelper.h | 77 + xc/programs/Xserver/vnc/XserverDesktop.cc | 1079 ++++++++++ xc/programs/Xserver/vnc/XserverDesktop.h | 102 + xc/programs/Xserver/vnc/Xvnc/Imakefile | 74 + xc/programs/Xserver/vnc/Xvnc/buildtime.c | 18 + xc/programs/Xserver/vnc/Xvnc/xvnc.cc | 1221 +++++++++++ xc/programs/Xserver/vnc/module/Imakefile | 54 + xc/programs/Xserver/vnc/vncExtInit.cc | 714 +++++++ xc/programs/Xserver/vnc/vncExtInit.h | 30 + xc/programs/Xserver/vnc/vncHooks.cc | 1475 +++++++++++++ xc/programs/Xserver/vnc/vncHooks.h | 26 + xc/programs/Xserver/vnc/xf86vncModule.cc | 96 + zlib/ChangeLog | 481 +++++ zlib/FAQ | 100 + zlib/INDEX | 86 + zlib/Make_vms.com | 115 ++ zlib/Makefile.in | 175 ++ zlib/Makefile.riscos | 151 ++ zlib/README | 147 ++ zlib/adler32.c | 48 + zlib/algorithm.txt | 213 ++ zlib/compress.c | 68 + zlib/configure | 212 ++ zlib/crc32.c | 162 ++ zlib/deflate.c | 1350 ++++++++++++ zlib/deflate.h | 318 +++ zlib/descrip.mms | 48 + zlib/example.c | 556 +++++ zlib/gzio.c | 875 ++++++++ zlib/infblock.c | 403 ++++ zlib/infblock.h | 39 + zlib/infcodes.c | 251 +++ zlib/infcodes.h | 27 + zlib/inffast.c | 183 ++ zlib/inffast.h | 17 + zlib/inffixed.h | 151 ++ zlib/inflate.c | 366 ++++ zlib/inftrees.c | 454 ++++ zlib/inftrees.h | 58 + zlib/infutil.c | 87 + zlib/infutil.h | 98 + zlib/maketree.c | 85 + zlib/minigzip.c | 320 +++ zlib/trees.c | 1214 +++++++++++ zlib/trees.h | 128 ++ zlib/uncompr.c | 58 + zlib/zconf.h | 279 +++ zlib/zlib.3 | 107 + zlib/zlib.dsp | 217 ++ zlib/zlib.h | 893 ++++++++ zlib/zlib.html | 971 +++++++++ zlib/zutil.c | 225 ++ zlib/zutil.h | 220 ++ 435 files changed, 72719 insertions(+) create mode 100644 LICENCE.TXT create mode 100644 Makefile.in create mode 100644 README create mode 100644 README.hpux create mode 100644 README.txt create mode 100644 README_BINARY.txt create mode 100644 Xregion/Makefile.in create mode 100644 Xregion/Region.c create mode 100644 Xregion/Xregion.dsp create mode 100644 Xregion/Xregion.h create mode 100644 Xregion/region.h create mode 100644 boilerplate.mk create mode 100755 configure create mode 100644 configure.in create mode 100644 depend.mk create mode 100644 hpux.patch create mode 100644 java/index.vnc create mode 100644 java/logo150x150.gif create mode 100644 java/vncviewer.jar create mode 100644 logmessages/logmessages.dsp create mode 100644 logmessages/messages.h create mode 100644 logmessages/messages.mc create mode 100644 logmessages/messages.rc create mode 100644 network/Makefile.in create mode 100644 network/Socket.h create mode 100644 network/TcpSocket.cxx create mode 100644 network/TcpSocket.h create mode 100644 network/msvcwarning.h create mode 100644 network/network.dsp create mode 100644 rdr/Exception.cxx create mode 100644 rdr/Exception.h create mode 100644 rdr/FdInStream.cxx create mode 100644 rdr/FdInStream.h create mode 100644 rdr/FdOutStream.cxx create mode 100644 rdr/FdOutStream.h create mode 100644 rdr/FixedMemOutStream.h create mode 100644 rdr/HexInStream.cxx create mode 100644 rdr/HexInStream.h create mode 100644 rdr/HexOutStream.cxx create mode 100644 rdr/HexOutStream.h create mode 100644 rdr/InStream.cxx create mode 100644 rdr/InStream.h create mode 100644 rdr/Makefile.in create mode 100644 rdr/MemInStream.h create mode 100644 rdr/MemOutStream.h create mode 100644 rdr/NullOutStream.cxx create mode 100644 rdr/NullOutStream.h create mode 100644 rdr/OutStream.h create mode 100644 rdr/RandomStream.cxx create mode 100644 rdr/RandomStream.h create mode 100644 rdr/SubstitutingInStream.h create mode 100644 rdr/ZlibInStream.cxx create mode 100644 rdr/ZlibInStream.h create mode 100644 rdr/ZlibOutStream.cxx create mode 100644 rdr/ZlibOutStream.h create mode 100644 rdr/msvcwarning.h create mode 100644 rdr/rdr.dsp create mode 100644 rdr/types.h create mode 100644 rfb/Blacklist.cxx create mode 100644 rfb/Blacklist.h create mode 100644 rfb/CConnection.cxx create mode 100644 rfb/CConnection.h create mode 100644 rfb/CMsgHandler.cxx create mode 100644 rfb/CMsgHandler.h create mode 100644 rfb/CMsgReader.cxx create mode 100644 rfb/CMsgReader.h create mode 100644 rfb/CMsgReaderV3.cxx create mode 100644 rfb/CMsgReaderV3.h create mode 100644 rfb/CMsgWriter.cxx create mode 100644 rfb/CMsgWriter.h create mode 100644 rfb/CMsgWriterV3.cxx create mode 100644 rfb/CMsgWriterV3.h create mode 100644 rfb/CSecurity.h create mode 100644 rfb/CSecurityNone.h create mode 100644 rfb/CSecurityVncAuth.cxx create mode 100644 rfb/CSecurityVncAuth.h create mode 100644 rfb/ColourCube.h create mode 100644 rfb/ColourMap.h create mode 100644 rfb/ComparingUpdateTracker.cxx create mode 100644 rfb/ComparingUpdateTracker.h create mode 100644 rfb/Configuration.cxx create mode 100644 rfb/Configuration.h create mode 100644 rfb/ConnParams.cxx create mode 100644 rfb/ConnParams.h create mode 100644 rfb/Cursor.cxx create mode 100644 rfb/Cursor.h create mode 100644 rfb/Decoder.cxx create mode 100644 rfb/Decoder.h create mode 100644 rfb/Encoder.cxx create mode 100644 rfb/Encoder.h create mode 100644 rfb/Exception.h create mode 100644 rfb/HTTPServer.cxx create mode 100644 rfb/HTTPServer.h create mode 100644 rfb/HextileDecoder.cxx create mode 100644 rfb/HextileDecoder.h create mode 100644 rfb/HextileEncoder.cxx create mode 100644 rfb/HextileEncoder.h create mode 100644 rfb/Hostname.h create mode 100644 rfb/ImageGetter.h create mode 100644 rfb/LogWriter.cxx create mode 100644 rfb/LogWriter.h create mode 100644 rfb/Logger.cxx create mode 100644 rfb/Logger.h create mode 100644 rfb/Logger_file.cxx create mode 100644 rfb/Logger_file.h create mode 100644 rfb/Logger_stdio.cxx create mode 100644 rfb/Logger_stdio.h create mode 100644 rfb/Makefile.in create mode 100644 rfb/Pixel.h create mode 100644 rfb/PixelBuffer.cxx create mode 100644 rfb/PixelBuffer.h create mode 100644 rfb/PixelFormat.cxx create mode 100644 rfb/PixelFormat.h create mode 100644 rfb/RREDecoder.cxx create mode 100644 rfb/RREDecoder.h create mode 100644 rfb/RREEncoder.cxx create mode 100644 rfb/RREEncoder.h create mode 100644 rfb/RawDecoder.cxx create mode 100644 rfb/RawDecoder.h create mode 100644 rfb/RawEncoder.cxx create mode 100644 rfb/RawEncoder.h create mode 100644 rfb/Rect.h create mode 100644 rfb/Region.cxx create mode 100644 rfb/Region.h create mode 100644 rfb/SConnection.cxx create mode 100644 rfb/SConnection.h create mode 100644 rfb/SDesktop.h create mode 100644 rfb/SMsgHandler.cxx create mode 100644 rfb/SMsgHandler.h create mode 100644 rfb/SMsgReader.cxx create mode 100644 rfb/SMsgReader.h create mode 100644 rfb/SMsgReaderV3.cxx create mode 100644 rfb/SMsgReaderV3.h create mode 100644 rfb/SMsgWriter.cxx create mode 100644 rfb/SMsgWriter.h create mode 100644 rfb/SMsgWriterV3.cxx create mode 100644 rfb/SMsgWriterV3.h create mode 100644 rfb/SSecurity.h create mode 100644 rfb/SSecurityFactoryStandard.cxx create mode 100644 rfb/SSecurityFactoryStandard.h create mode 100644 rfb/SSecurityNone.h create mode 100644 rfb/SSecurityVncAuth.cxx create mode 100644 rfb/SSecurityVncAuth.h create mode 100644 rfb/ServerCore.cxx create mode 100644 rfb/ServerCore.h create mode 100644 rfb/Threading.h create mode 100644 rfb/TransImageGetter.cxx create mode 100644 rfb/TransImageGetter.h create mode 100644 rfb/TrueColourMap.h create mode 100644 rfb/UpdateTracker.cxx create mode 100644 rfb/UpdateTracker.h create mode 100644 rfb/UserPasswdGetter.h create mode 100644 rfb/VNCSConnectionST.cxx create mode 100644 rfb/VNCSConnectionST.h create mode 100644 rfb/VNCServer.h create mode 100644 rfb/VNCServerST.cxx create mode 100644 rfb/VNCServerST.h create mode 100644 rfb/ZRLEDecoder.cxx create mode 100644 rfb/ZRLEDecoder.h create mode 100644 rfb/ZRLEEncoder.cxx create mode 100644 rfb/ZRLEEncoder.h create mode 100644 rfb/d3des.c create mode 100644 rfb/d3des.h create mode 100644 rfb/encodings.cxx create mode 100644 rfb/encodings.h create mode 100644 rfb/hextileConstants.h create mode 100644 rfb/hextileDecode.h create mode 100644 rfb/hextileEncode.h create mode 100644 rfb/keysymdef.h create mode 100644 rfb/msgTypes.h create mode 100644 rfb/msvcwarning.h create mode 100644 rfb/rfb.dsp create mode 100644 rfb/rreDecode.h create mode 100644 rfb/rreEncode.h create mode 100644 rfb/secTypes.cxx create mode 100644 rfb/secTypes.h create mode 100644 rfb/transInitTempl.h create mode 100644 rfb/transTempl.h create mode 100644 rfb/util.cxx create mode 100644 rfb/util.h create mode 100644 rfb/vncAuth.cxx create mode 100644 rfb/vncAuth.h create mode 100644 rfb/win32/Threading_win32.cxx create mode 100644 rfb/win32/Threading_win32.h create mode 100644 rfb/win32/msvcwarning.h create mode 100644 rfb/win32/util_win32.h create mode 100644 rfb/zrleDecode.h create mode 100644 rfb/zrleEncode.h create mode 100644 rfb_win32/AboutDialog.cxx create mode 100644 rfb_win32/AboutDialog.h create mode 100644 rfb_win32/CKeyboard.cxx create mode 100644 rfb_win32/CKeyboard.h create mode 100644 rfb_win32/CPointer.cxx create mode 100644 rfb_win32/CPointer.h create mode 100644 rfb_win32/CleanDesktop.cxx create mode 100644 rfb_win32/CleanDesktop.h create mode 100644 rfb_win32/Clipboard.cxx create mode 100644 rfb_win32/Clipboard.h create mode 100644 rfb_win32/CurrentUser.cxx create mode 100644 rfb_win32/CurrentUser.h create mode 100644 rfb_win32/DIBSectionBuffer.cxx create mode 100644 rfb_win32/DIBSectionBuffer.h create mode 100644 rfb_win32/DeviceFrameBuffer.cxx create mode 100644 rfb_win32/DeviceFrameBuffer.h create mode 100644 rfb_win32/Dialog.cxx create mode 100644 rfb_win32/Dialog.h create mode 100644 rfb_win32/IntervalTimer.h create mode 100644 rfb_win32/LaunchProcess.cxx create mode 100644 rfb_win32/LaunchProcess.h create mode 100644 rfb_win32/MsgWindow.cxx create mode 100644 rfb_win32/MsgWindow.h create mode 100644 rfb_win32/OSVersion.cxx create mode 100644 rfb_win32/OSVersion.h create mode 100644 rfb_win32/RegConfig.cxx create mode 100644 rfb_win32/RegConfig.h create mode 100644 rfb_win32/Registry.cxx create mode 100644 rfb_win32/Registry.h create mode 100644 rfb_win32/SDisplay.cxx create mode 100644 rfb_win32/SDisplay.h create mode 100644 rfb_win32/SInput.cxx create mode 100644 rfb_win32/SInput.h create mode 100644 rfb_win32/Security.h create mode 100644 rfb_win32/Service.cxx create mode 100644 rfb_win32/Service.h create mode 100644 rfb_win32/SocketManager.cxx create mode 100644 rfb_win32/SocketManager.h create mode 100644 rfb_win32/TCharArray.cxx create mode 100644 rfb_win32/TCharArray.h create mode 100644 rfb_win32/TrayIcon.h create mode 100644 rfb_win32/WMCursor.cxx create mode 100644 rfb_win32/WMCursor.h create mode 100644 rfb_win32/WMHooks.cxx create mode 100644 rfb_win32/WMHooks.h create mode 100644 rfb_win32/WMNotifier.cxx create mode 100644 rfb_win32/WMNotifier.h create mode 100644 rfb_win32/WMPoller.cxx create mode 100644 rfb_win32/WMPoller.h create mode 100644 rfb_win32/WMShatter.cxx create mode 100644 rfb_win32/WMShatter.h create mode 100644 rfb_win32/WMWindowCopyRect.cxx create mode 100644 rfb_win32/WMWindowCopyRect.h create mode 100644 rfb_win32/Win32Util.cxx create mode 100644 rfb_win32/Win32Util.h create mode 100644 rfb_win32/keymap.h create mode 100644 rfb_win32/msvcwarning.h create mode 100644 rfb_win32/rfb_win32.dsp create mode 100644 tx/Makefile.in create mode 100644 tx/TXButton.h create mode 100644 tx/TXCheckbox.h create mode 100644 tx/TXDialog.h create mode 100644 tx/TXEntry.h create mode 100644 tx/TXImage.cxx create mode 100644 tx/TXImage.h create mode 100644 tx/TXLabel.h create mode 100644 tx/TXMenu.cxx create mode 100644 tx/TXMenu.h create mode 100644 tx/TXMsgBox.h create mode 100644 tx/TXScrollbar.cxx create mode 100644 tx/TXScrollbar.h create mode 100644 tx/TXViewport.cxx create mode 100644 tx/TXViewport.h create mode 100644 tx/TXWindow.cxx create mode 100644 tx/TXWindow.h create mode 100644 tx/Timer.cxx create mode 100644 tx/Timer.h create mode 100644 vnc.dsw create mode 100644 vncconfig/Authentication.h create mode 100644 vncconfig/Connections.h create mode 100644 vncconfig/Desktop.h create mode 100644 vncconfig/Hooking.h create mode 100644 vncconfig/Inputs.h create mode 100644 vncconfig/Legacy.cxx create mode 100644 vncconfig/Legacy.h create mode 100644 vncconfig/Sharing.h create mode 100644 vncconfig/resource.h create mode 100644 vncconfig/vncconfig.cxx create mode 100644 vncconfig/vncconfig.dsp create mode 100644 vncconfig/vncconfig.exe.manifest create mode 100644 vncconfig/vncconfig.ico create mode 100644 vncconfig/vncconfig.rc create mode 100644 vncconfig_unix/Makefile.in create mode 100644 vncconfig_unix/buildtime.c create mode 100644 vncconfig_unix/vncExt.c create mode 100644 vncconfig_unix/vncExt.h create mode 100644 vncconfig_unix/vncconfig.cxx create mode 100644 vncconfig_unix/vncconfig.man create mode 100755 vncinstall create mode 100644 vncmkdepend/Makefile create mode 100644 vncmkdepend/README create mode 100644 vncmkdepend/cppsetup.c create mode 100644 vncmkdepend/def.h create mode 100644 vncmkdepend/ifparser.c create mode 100644 vncmkdepend/ifparser.h create mode 100644 vncmkdepend/include.c create mode 100644 vncmkdepend/main.c create mode 100644 vncmkdepend/parse.c create mode 100644 vncmkdepend/pr.c create mode 100644 vncpasswd/Makefile.in create mode 100644 vncpasswd/vncpasswd.cxx create mode 100644 vncpasswd/vncpasswd.man create mode 100755 vncserver create mode 100644 vncserver.man create mode 100644 vncviewer/CViewManager.cxx create mode 100644 vncviewer/CViewManager.h create mode 100644 vncviewer/CViewOptions.cxx create mode 100644 vncviewer/CViewOptions.h create mode 100644 vncviewer/ConnectingDialog.h create mode 100644 vncviewer/ConnectionDialog.cxx create mode 100644 vncviewer/ConnectionDialog.h create mode 100644 vncviewer/InfoDialog.cxx create mode 100644 vncviewer/InfoDialog.h create mode 100644 vncviewer/MRU.h create mode 100644 vncviewer/OptionsDialog.cxx create mode 100644 vncviewer/OptionsDialog.h create mode 100644 vncviewer/UserPasswdDialog.cxx create mode 100644 vncviewer/UserPasswdDialog.h create mode 100644 vncviewer/buildTime.cxx create mode 100644 vncviewer/cursor1.cur create mode 100644 vncviewer/cview.cxx create mode 100644 vncviewer/cview.h create mode 100644 vncviewer/msvcwarning.h create mode 100644 vncviewer/resource.h create mode 100644 vncviewer/vncviewer.cxx create mode 100644 vncviewer/vncviewer.dsp create mode 100644 vncviewer/vncviewer.exe.manifest create mode 100644 vncviewer/vncviewer.ico create mode 100644 vncviewer/vncviewer.rc create mode 100644 vncviewer_unix/AboutDialog.h create mode 100644 vncviewer_unix/CConn.cxx create mode 100644 vncviewer_unix/CConn.h create mode 100644 vncviewer_unix/DesktopWindow.cxx create mode 100644 vncviewer_unix/DesktopWindow.h create mode 100644 vncviewer_unix/InfoDialog.h create mode 100644 vncviewer_unix/Makefile.in create mode 100644 vncviewer_unix/OptionsDialog.h create mode 100644 vncviewer_unix/PasswdDialog.h create mode 100644 vncviewer_unix/ServerDialog.h create mode 100644 vncviewer_unix/buildtime.c create mode 100644 vncviewer_unix/parameters.h create mode 100644 vncviewer_unix/vncviewer.cxx create mode 100644 vncviewer_unix/vncviewer.man create mode 100644 winvnc/AddNewClientDialog.h create mode 100644 winvnc/JavaViewer.cxx create mode 100644 winvnc/JavaViewer.h create mode 100644 winvnc/QueryConnectDialog.cxx create mode 100644 winvnc/QueryConnectDialog.h create mode 100644 winvnc/STrayIcon.cxx create mode 100644 winvnc/STrayIcon.h create mode 100644 winvnc/VNCServerService.cxx create mode 100644 winvnc/VNCServerService.h create mode 100644 winvnc/VNCServerWin32.cxx create mode 100644 winvnc/VNCServerWin32.h create mode 100644 winvnc/buildTime.cxx create mode 100644 winvnc/connected.ico create mode 100644 winvnc/java/index.vnc create mode 100644 winvnc/java/logo150x150.gif create mode 100644 winvnc/java/vncviewer.jar create mode 100644 winvnc/msvcwarning.h create mode 100644 winvnc/resource.h create mode 100644 winvnc/winvnc.cxx create mode 100644 winvnc/winvnc.dsp create mode 100644 winvnc/winvnc.ico create mode 100644 winvnc/winvnc.rc create mode 100644 winvnc/winvnc4.exe.manifest create mode 100644 wm_hooks/msvcwarning.h create mode 100644 wm_hooks/resource.h create mode 100644 wm_hooks/wm_hooks.cxx create mode 100644 wm_hooks/wm_hooks.def create mode 100644 wm_hooks/wm_hooks.dsp create mode 100644 wm_hooks/wm_hooks.h create mode 100644 wm_hooks/wm_hooks.rc create mode 100644 x0vncserver/Image.cxx create mode 100644 x0vncserver/Image.h create mode 100644 x0vncserver/Makefile.in create mode 100644 x0vncserver/buildtime.c create mode 100644 x0vncserver/x0vncserver.cxx create mode 100644 x0vncserver/x0vncserver.man create mode 100644 xc.patch create mode 100644 xc/config/cf/host.def create mode 100644 xc/config/cf/vnc.def create mode 100644 xc/programs/Xserver/Xvnc.man create mode 100644 xc/programs/Xserver/vnc/Imakefile create mode 100644 xc/programs/Xserver/vnc/RegionHelper.h create mode 100644 xc/programs/Xserver/vnc/XserverDesktop.cc create mode 100644 xc/programs/Xserver/vnc/XserverDesktop.h create mode 100644 xc/programs/Xserver/vnc/Xvnc/Imakefile create mode 100644 xc/programs/Xserver/vnc/Xvnc/buildtime.c create mode 100644 xc/programs/Xserver/vnc/Xvnc/xvnc.cc create mode 100644 xc/programs/Xserver/vnc/module/Imakefile create mode 100644 xc/programs/Xserver/vnc/vncExtInit.cc create mode 100644 xc/programs/Xserver/vnc/vncExtInit.h create mode 100644 xc/programs/Xserver/vnc/vncHooks.cc create mode 100644 xc/programs/Xserver/vnc/vncHooks.h create mode 100644 xc/programs/Xserver/vnc/xf86vncModule.cc create mode 100644 zlib/ChangeLog create mode 100644 zlib/FAQ create mode 100644 zlib/INDEX create mode 100644 zlib/Make_vms.com create mode 100644 zlib/Makefile.in create mode 100644 zlib/Makefile.riscos create mode 100644 zlib/README create mode 100644 zlib/adler32.c create mode 100644 zlib/algorithm.txt create mode 100644 zlib/compress.c create mode 100755 zlib/configure create mode 100644 zlib/crc32.c create mode 100644 zlib/deflate.c create mode 100644 zlib/deflate.h create mode 100644 zlib/descrip.mms create mode 100644 zlib/example.c create mode 100644 zlib/gzio.c create mode 100644 zlib/infblock.c create mode 100644 zlib/infblock.h create mode 100644 zlib/infcodes.c create mode 100644 zlib/infcodes.h create mode 100644 zlib/inffast.c create mode 100644 zlib/inffast.h create mode 100644 zlib/inffixed.h create mode 100644 zlib/inflate.c create mode 100644 zlib/inftrees.c create mode 100644 zlib/inftrees.h create mode 100644 zlib/infutil.c create mode 100644 zlib/infutil.h create mode 100644 zlib/maketree.c create mode 100644 zlib/minigzip.c create mode 100644 zlib/trees.c create mode 100644 zlib/trees.h create mode 100644 zlib/uncompr.c create mode 100644 zlib/zconf.h create mode 100644 zlib/zlib.3 create mode 100644 zlib/zlib.dsp create mode 100644 zlib/zlib.h create mode 100644 zlib/zlib.html create mode 100644 zlib/zutil.c create mode 100644 zlib/zutil.h diff --git a/LICENCE.TXT b/LICENCE.TXT new file mode 100644 index 00000000..ae3b5319 --- /dev/null +++ b/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/Makefile.in b/Makefile.in new file mode 100644 index 00000000..9341f4ad --- /dev/null +++ b/Makefile.in @@ -0,0 +1,5 @@ + +SUBDIRS = @ZLIB_DIR@ rdr network Xregion rfb tx x0vncserver vncviewer \ + vncconfig vncpasswd + +# followed by boilerplate.mk diff --git a/README b/README new file mode 100644 index 00000000..4c0e5fb1 --- /dev/null +++ b/README @@ -0,0 +1,284 @@ + +VNC 4.0 Source Distribution for Unix platforms +============================================== + +Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. + +This software is distributed under the GNU General Public Licence as published +by the Free Software Foundation. See the file LICENCE.TXT for the conditions +under which this software is made available. VNC also contains code from other +sources. See the Acknowledgements section below, and the individual files for +details of the conditions under which they are made available. + + +There are six programs here: + + vncviewer - this is the VNC viewer, or client, program for X. + + Xvnc - this is the X VNC server - it is both a VNC server and an X server + with a "virtual" framebuffer. You normally use the vncserver script + to start Xvnc. + + vncserver - this is a wrapper script which makes starting an X VNC server + (i.e. desktop) more convenient. It is written in Perl, so to use + the script you need that. + + vncpasswd - this program allows you to change the password used to access + your X VNC desktops. The vncserver script uses this program when + you first start a VNC server. + + vncconfig - this program is used to configure and control a running instance + of Xvnc. + + x0vncserver - this is an inefficient VNC server which continuously polls any + X display, allowing it to be controlled via VNC. It is + intended mainly as a demonstration of a simple VNC server. + +In addition to these standalone programs, this distribution can also be used to +turn the native X server for a platform into a VNC server. For XFree86 version +4 servers, this is done using a module loaded at run-time. For other X servers +it requires replacing the native X server binary. + +To build this distribution you need a C++ compiler as well as a C compiler. +You also need a reasonably recent version of the X window system installed. +This comes as standard with most unix machines. If you don't have it +installed, see http://www.xfree86.org or http://www.x.org + +To build everything but Xvnc, do: + + % ./configure + % make + +This should build first some libraries - zlib, rdr, network, Xregion, rfb and +tx - then vncviewer, vncconfig and vncpasswd. If you already have zlib +installed on your system you can run "./configure --with-installed-zlib" if you +prefer (this is strongly advised on FreeBSD, since we've been told there are +problems otherwise). + +Building Xvnc +============= + +Building Xvnc and the VNC support for native X servers is much more complex. +If you don't need to build it, skip to the section below on installing. + +Xvnc differs from the other programs in that it is built inside the X source +tree. Unlike previous versions of Xvnc, we do not provide an X source tree +with this distribution. We have designed the distribution to be as independent +as possible of the X tree used. + +We have successfully used XFree86 version 4.3.0, 4.2.0 and 3.3.6 (available +from http://www.xfree86.org). You could also try the original X.org tree +available from http://www.x.org but this does not build as easily because of +lack of support for C++, no support for building server only, and other issues. +Note that the X tree is enormous and notoriously difficult to deal with - +building it is not for the faint-hearted! + +Once you have a copy of the X source tree, make sure it is unpacked at the top +level of this distribution, so that the xc directory of the X source tree +matches the xc of this distribution, for example: + + % tar xzf X420src-1.tgz + +Then you must apply a patch to some files in the X source tree: + + % patch -Np0 and Jef Poskanzer . This is: + + Copyright (c) 1996 Widget Workshop, Inc. All Rights Reserved. + + Permission to use, copy, modify, and distribute this software and its + documentation for NON-COMMERCIAL or COMMERCIAL purposes and without fee + is hereby granted, provided that this copyright notice is kept intact. + + WIDGET WORKSHOP MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE + SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT + NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + PARTICULAR PURPOSE, OR NON-INFRINGEMENT. WIDGET WORKSHOP SHALL NOT BE + LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, + MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. + + THIS SOFTWARE IS NOT DESIGNED OR INTENDED FOR USE OR RESALE AS ON-LINE + CONTROL EQUIPMENT IN HAZARDOUS ENVIRONMENTS REQUIRING FAIL-SAFE + PERFORMANCE, SUCH AS IN THE OPERATION OF NUCLEAR FACILITIES, AIRCRAFT + NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL, DIRECT LIFE + SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH THE FAILURE OF THE + SOFTWARE COULD LEAD DIRECTLY TO DEATH, PERSONAL INJURY, OR SEVERE + PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH RISK ACTIVITIES"). WIDGET + WORKSHOP SPECIFICALLY DISCLAIMS ANY EXPRESS OR IMPLIED WARRANTY OF + FITNESS FOR HIGH RISK ACTIVITIES. + + Copyright (C) 1996 by Jef Poskanzer . All rights + reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + Visit the ACME Labs Java page for up-to-date versions of this and other + fine Java utilities: http://www.acme.com/java/ diff --git a/README.hpux b/README.hpux new file mode 100644 index 00000000..ecbe9667 --- /dev/null +++ b/README.hpux @@ -0,0 +1,39 @@ +I have managed to build Xvnc on HPUX but only with some ugly hacking of +the X tree. The X tree I used as the basis for the build is the XFree86 4.2.0 +tree. The XFree86 4.3.0 tree is unsuitable as it seems to have had some HPUX +stuff removed from it. I built using the aCC C++ compiler. + +Set the following environment variables: + + % CXX=/opt/aCC/bin/aCC + % CFLAGS="+DAportable" + % CXXFLAGS="+DAportable -AA +W749 +W740" + % BOOTSTRAPCFLAGS=-Dhpux + % export CXX CFLAGS CXXFLAGS BOOTSTRAPCFLAGS + +Build the main part of the VNC distribution as normal: + + % ./configure + % make + +Unpack the X tree and apply the patches in xc.patch: + + % gunzip -c X420src-1.tgz | tar xf - + % patch -Np0 and Jef Poskanzer . This is: + + Copyright (c) 1996 Widget Workshop, Inc. All Rights Reserved. + + Permission to use, copy, modify, and distribute this software and its + documentation for NON-COMMERCIAL or COMMERCIAL purposes and without fee + is hereby granted, provided that this copyright notice is kept intact. + + WIDGET WORKSHOP MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE + SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT + NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + PARTICULAR PURPOSE, OR NON-INFRINGEMENT. WIDGET WORKSHOP SHALL NOT BE + LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, + MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. + + THIS SOFTWARE IS NOT DESIGNED OR INTENDED FOR USE OR RESALE AS ON-LINE + CONTROL EQUIPMENT IN HAZARDOUS ENVIRONMENTS REQUIRING FAIL-SAFE + PERFORMANCE, SUCH AS IN THE OPERATION OF NUCLEAR FACILITIES, AIRCRAFT + NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL, DIRECT LIFE + SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH THE FAILURE OF THE + SOFTWARE COULD LEAD DIRECTLY TO DEATH, PERSONAL INJURY, OR SEVERE + PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH RISK ACTIVITIES"). WIDGET + WORKSHOP SPECIFICALLY DISCLAIMS ANY EXPRESS OR IMPLIED WARRANTY OF + FITNESS FOR HIGH RISK ACTIVITIES. + + Copyright (C) 1996 by Jef Poskanzer . All rights + reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + Visit the ACME Labs Java page for up-to-date versions of this and other + fine Java utilities: http://www.acme.com/java/ diff --git a/README_BINARY.txt b/README_BINARY.txt new file mode 100644 index 00000000..8f89fe93 --- /dev/null +++ b/README_BINARY.txt @@ -0,0 +1,120 @@ + +VNC 4 Binary Distribution for Windows platforms +============================================= + +VNC 4 is Copyright RealVNC Ltd. 2002-2004. This software is +distributed under the GNU General Public Licence as published by the +Free Software Foundation. VNC also contains code from other sources, +as outlined in the Acknowledgements section below. + +The installer package contains two VNC components: + + VNC Viewer - this is the VNC Viewer, or client, program for + Win32. + [Win9x, WinME, NT4, Win2000, WinXP, + Windows 2003 Server] + + VNC Server - this is the VNC Server for Win32. It allows a + Windows desktop to be accessed remotely using a + VNC Viewer. + [Win9x, WinME, NT4, Win2000, WinXP(*), + Windows 2003 Server] + +(*) May not work if the in-built Fast User Switching or Remote + Administration features are in use. + +Both components were built using Microsoft Visual C++ 6.0, and are +designed to operate upon the Win32 platforms listed above. + +ACKNOWLEDGEMENTS +================ + +This distribution contains zlib software by Jean-loup Gailly and Mark Adler. +This is: + + Copyright (C) 1995-2002 Jean-loup Gailly and Mark Adler. + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files ftp://ds.internic.net/rfc/rfc1950.txt + (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). + + +This distribution contains public domain DES software by Richard Outerbridge. +This is: + + Copyright (c) 1988,1989,1990,1991,1992 by Richard Outerbridge. + (GEnie : OUTER; CIS : [71755,204]) Graven Imagery, 1992. + + +This distribution contains Java DES software by Dave Zimmerman + and Jef Poskanzer . This is: + + Copyright (c) 1996 Widget Workshop, Inc. All Rights Reserved. + + Permission to use, copy, modify, and distribute this software and its + documentation for NON-COMMERCIAL or COMMERCIAL purposes and without fee + is hereby granted, provided that this copyright notice is kept intact. + + WIDGET WORKSHOP MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE + SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT + NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + PARTICULAR PURPOSE, OR NON-INFRINGEMENT. WIDGET WORKSHOP SHALL NOT BE + LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, + MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. + + THIS SOFTWARE IS NOT DESIGNED OR INTENDED FOR USE OR RESALE AS ON-LINE + CONTROL EQUIPMENT IN HAZARDOUS ENVIRONMENTS REQUIRING FAIL-SAFE + PERFORMANCE, SUCH AS IN THE OPERATION OF NUCLEAR FACILITIES, AIRCRAFT + NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL, DIRECT LIFE + SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH THE FAILURE OF THE + SOFTWARE COULD LEAD DIRECTLY TO DEATH, PERSONAL INJURY, OR SEVERE + PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH RISK ACTIVITIES"). WIDGET + WORKSHOP SPECIFICALLY DISCLAIMS ANY EXPRESS OR IMPLIED WARRANTY OF + FITNESS FOR HIGH RISK ACTIVITIES. + + Copyright (C) 1996 by Jef Poskanzer . All rights + reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + Visit the ACME Labs Java page for up-to-date versions of this and other + fine Java utilities: http://www.acme.com/java/ diff --git a/Xregion/Makefile.in b/Xregion/Makefile.in new file mode 100644 index 00000000..878a29b6 --- /dev/null +++ b/Xregion/Makefile.in @@ -0,0 +1,15 @@ + +SRCS = Region.c + +OBJS = $(SRCS:.c=.o) + +library = libXregion.a + +all:: $(library) + +$(library): $(OBJS) + rm -f $(library) + $(AR) $(library) $(OBJS) + $(RANLIB) $(library) + +# followed by boilerplate.mk diff --git a/Xregion/Region.c b/Xregion/Region.c new file mode 100644 index 00000000..bf2d123b --- /dev/null +++ b/Xregion/Region.c @@ -0,0 +1,1687 @@ +/* $Xorg: Region.c,v 1.6 2001/02/09 02:03:35 xorgcvs Exp $ */ +/************************************************************************ + +Copyright 1987, 1988, 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 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +************************************************************************/ +/* $XFree86: xc/lib/X11/Region.c,v 1.8 2001/12/14 19:54:05 dawes Exp $ */ +/* + * The functions in this file implement the Region abstraction, similar to one + * used in the X11 sample server. A Region is simply an area, as the name + * implies, and is implemented as a "y-x-banded" array of rectangles. To + * explain: Each Region is made up of a certain number of rectangles sorted + * by y coordinate first, and then by x coordinate. + * + * Furthermore, the rectangles are banded such that every rectangle with a + * given upper-left y coordinate (y1) will have the same lower-right y + * coordinate (y2) and vice versa. If a rectangle has scanlines in a band, it + * will span the entire vertical distance of the band. This means that some + * areas that could be merged into a taller rectangle will be represented as + * several shorter rectangles to account for shorter rectangles to its left + * or right but within its "vertical scope". + * + * An added constraint on the rectangles is that they must cover as much + * horizontal area as possible. E.g. no two rectangles in a band are allowed + * to touch. + * + * Whenever possible, bands will be merged together to cover a greater vertical + * distance (and thus reduce the number of rectangles). Two bands can be merged + * only if the bottom of one touches the top of the other and they have + * rectangles in the same places (of the same width, of course). This maintains + * the y-x-banding that's so nice to have... + */ + +#include "Xregion.h" +//#include "Xlibint.h" +//#include "Xutil.h" +#include "region.h" +//#include "poly.h" + +#ifdef DEBUG +#include +#define assert(expr) {if (!(expr)) fprintf(stderr,\ +"Assertion failed file %s, line %d: expr\n", __FILE__, __LINE__); } +#else +#define assert(expr) +#endif + +typedef void (*voidProcp)(); + +static void miRegionOp(); +/* Create a new empty region */ +Region +XCreateRegion() +{ + Region temp; + + if (! (temp = ( Region )Xmalloc( (unsigned) sizeof( REGION )))) + return (Region) NULL; + if (! (temp->rects = ( BOX * )Xmalloc( (unsigned) sizeof( BOX )))) { + Xfree((char *) temp); + return (Region) NULL; + } + temp->numRects = 0; + temp->extents.x1 = 0; + temp->extents.y1 = 0; + temp->extents.x2 = 0; + temp->extents.y2 = 0; + temp->size = 1; + return( temp ); +} + +int +XClipBox( r, rect ) + Region r; + XRectangle *rect; +{ + rect->x = r->extents.x1; + rect->y = r->extents.y1; + rect->width = r->extents.x2 - r->extents.x1; + rect->height = r->extents.y2 - r->extents.y1; + return 1; +} + +int +XUnionRectWithRegion(rect, source, dest) + register XRectangle *rect; + Region source, dest; +{ + REGION region; + + if (!rect->width || !rect->height) + return 0; + region.rects = ®ion.extents; + region.numRects = 1; + region.extents.x1 = rect->x; + region.extents.y1 = rect->y; + region.extents.x2 = rect->x + rect->width; + region.extents.y2 = rect->y + rect->height; + region.size = 1; + + return XUnionRegion(®ion, source, dest); +} + +/*- + *----------------------------------------------------------------------- + * miSetExtents -- + * Reset the extents of a region to what they should be. Called by + * miSubtract and miIntersect b/c they can't figure it out along the + * way or do so easily, as miUnion can. + * + * Results: + * None. + * + * Side Effects: + * The region's 'extents' structure is overwritten. + * + *----------------------------------------------------------------------- + */ +static void +miSetExtents (pReg) + Region pReg; +{ + register BoxPtr pBox, + pBoxEnd, + pExtents; + + if (pReg->numRects == 0) + { + pReg->extents.x1 = 0; + pReg->extents.y1 = 0; + pReg->extents.x2 = 0; + pReg->extents.y2 = 0; + return; + } + + pExtents = &pReg->extents; + pBox = pReg->rects; + pBoxEnd = &pBox[pReg->numRects - 1]; + + /* + * Since pBox is the first rectangle in the region, it must have the + * smallest y1 and since pBoxEnd is the last rectangle in the region, + * it must have the largest y2, because of banding. Initialize x1 and + * x2 from pBox and pBoxEnd, resp., as good things to initialize them + * to... + */ + pExtents->x1 = pBox->x1; + pExtents->y1 = pBox->y1; + pExtents->x2 = pBoxEnd->x2; + pExtents->y2 = pBoxEnd->y2; + + assert(pExtents->y1 < pExtents->y2); + while (pBox <= pBoxEnd) + { + if (pBox->x1 < pExtents->x1) + { + pExtents->x1 = pBox->x1; + } + if (pBox->x2 > pExtents->x2) + { + pExtents->x2 = pBox->x2; + } + pBox++; + } + assert(pExtents->x1 < pExtents->x2); +} + +extern void _XSetClipRectangles(); + +#if 0 +int +XSetRegion( dpy, gc, r ) + Display *dpy; + GC gc; + register Region r; +{ + register int i; + register XRectangle *xr, *pr; + register BOX *pb; + unsigned long total; + + LockDisplay (dpy); + total = r->numRects * sizeof (XRectangle); + if ((xr = (XRectangle *) _XAllocTemp(dpy, total))) { + for (pr = xr, pb = r->rects, i = r->numRects; --i >= 0; pr++, pb++) { + pr->x = pb->x1; + pr->y = pb->y1; + pr->width = pb->x2 - pb->x1; + pr->height = pb->y2 - pb->y1; + } + } + if (xr || !r->numRects) + _XSetClipRectangles(dpy, gc, 0, 0, xr, r->numRects, YXBanded); + if (xr) + _XFreeTemp(dpy, (char *)xr, total); + UnlockDisplay(dpy); + SyncHandle(); + return 1; +} +#endif + +int +XDestroyRegion( r ) + Region r; +{ + Xfree( (char *) r->rects ); + Xfree( (char *) r ); + return 1; +} + + +/* TranslateRegion(pRegion, x, y) + translates in place + added by raymond +*/ + +int +XOffsetRegion(pRegion, x, y) + register Region pRegion; + register int x; + register int y; +{ + register int nbox; + register BOX *pbox; + + pbox = pRegion->rects; + nbox = pRegion->numRects; + + while(nbox--) + { + pbox->x1 += x; + pbox->x2 += x; + pbox->y1 += y; + pbox->y2 += y; + pbox++; + } + pRegion->extents.x1 += x; + pRegion->extents.x2 += x; + pRegion->extents.y1 += y; + pRegion->extents.y2 += y; + return 1; +} + +/* + Utility procedure Compress: + Replace r by the region r', where + p in r' iff (Quantifer m <= dx) (p + m in r), and + Quantifier is Exists if grow is TRUE, For all if grow is FALSE, and + (x,y) + m = (x+m,y) if xdir is TRUE; (x,y+m) if xdir is FALSE. + + Thus, if xdir is TRUE and grow is FALSE, r is replaced by the region + of all points p such that p and the next dx points on the same + horizontal scan line are all in r. We do this using by noting + that p is the head of a run of length 2^i + k iff p is the head + of a run of length 2^i and p+2^i is the head of a run of length + k. Thus, the loop invariant: s contains the region corresponding + to the runs of length shift. r contains the region corresponding + to the runs of length 1 + dxo & (shift-1), where dxo is the original + value of dx. dx = dxo & ~(shift-1). As parameters, s and t are + scratch regions, so that we don't have to allocate them on every + call. +*/ + +#define ZOpRegion(a,b,c) if (grow) XUnionRegion(a,b,c); \ + else XIntersectRegion(a,b,c) +#define ZShiftRegion(a,b) if (xdir) XOffsetRegion(a,b,0); \ + else XOffsetRegion(a,0,b) +#define ZCopyRegion(a,b) XUnionRegion(a,a,b) + +static void +Compress(r, s, t, dx, xdir, grow) + Region r, s, t; + register unsigned dx; + register int xdir, grow; +{ + register unsigned shift = 1; + + ZCopyRegion(r, s); + while (dx) { + if (dx & shift) { + ZShiftRegion(r, -(int)shift); + ZOpRegion(r, s, r); + dx -= shift; + if (!dx) break; + } + ZCopyRegion(s, t); + ZShiftRegion(s, -(int)shift); + ZOpRegion(s, t, s); + shift <<= 1; + } +} + +#undef ZOpRegion +#undef ZShiftRegion +#undef ZCopyRegion + +int +XShrinkRegion(r, dx, dy) + Region r; + int dx, dy; +{ + Region s, t; + int grow; + + if (!dx && !dy) return 0; + if ((! (s = XCreateRegion())) || (! (t = XCreateRegion()))) return 0; + if ((grow = (dx < 0))) dx = -dx; + if (dx) Compress(r, s, t, (unsigned) 2*dx, TRUE, grow); + if ((grow = (dy < 0))) dy = -dy; + if (dy) Compress(r, s, t, (unsigned) 2*dy, FALSE, grow); + XOffsetRegion(r, dx, dy); + XDestroyRegion(s); + XDestroyRegion(t); + return 0; +} + +#ifdef notdef +/*********************************************************** + * Bop down the array of rects until we have passed + * scanline y. numRects is the size of the array. + ***********************************************************/ + +static BOX +*IndexRects(rects, numRects, y) + register BOX *rects; + register int numRects; + register int y; +{ + while ((numRects--) && (rects->y2 <= y)) + rects++; + return(rects); +} +#endif + +/*====================================================================== + * Region Intersection + *====================================================================*/ +/*- + *----------------------------------------------------------------------- + * miIntersectO -- + * Handle an overlapping band for miIntersect. + * + * Results: + * None. + * + * Side Effects: + * Rectangles may be added to the region. + * + *----------------------------------------------------------------------- + */ +/* static void*/ +static int +miIntersectO (pReg, r1, r1End, r2, r2End, y1, y2) + register Region pReg; + register BoxPtr r1; + BoxPtr r1End; + register BoxPtr r2; + BoxPtr r2End; + short y1; + short y2; +{ + register short x1; + register short x2; + register BoxPtr pNextRect; + + pNextRect = &pReg->rects[pReg->numRects]; + + while ((r1 != r1End) && (r2 != r2End)) + { + x1 = max(r1->x1,r2->x1); + x2 = min(r1->x2,r2->x2); + + /* + * If there's any overlap between the two rectangles, add that + * overlap to the new region. + * There's no need to check for subsumption because the only way + * such a need could arise is if some region has two rectangles + * right next to each other. Since that should never happen... + */ + if (x1 < x2) + { + assert(y1rects); + pNextRect->x1 = x1; + pNextRect->y1 = y1; + pNextRect->x2 = x2; + pNextRect->y2 = y2; + pReg->numRects += 1; + pNextRect++; + assert(pReg->numRects <= pReg->size); + } + + /* + * Need to advance the pointers. Shift the one that extends + * to the right the least, since the other still has a chance to + * overlap with that region's next rectangle, if you see what I mean. + */ + if (r1->x2 < r2->x2) + { + r1++; + } + else if (r2->x2 < r1->x2) + { + r2++; + } + else + { + r1++; + r2++; + } + } + return 0; /* lint */ +} + +int +XIntersectRegion(reg1, reg2, newReg) + Region reg1; + Region reg2; /* source regions */ + register Region newReg; /* destination Region */ +{ + /* check for trivial reject */ + if ( (!(reg1->numRects)) || (!(reg2->numRects)) || + (!EXTENTCHECK(®1->extents, ®2->extents))) + newReg->numRects = 0; + else + miRegionOp (newReg, reg1, reg2, + (voidProcp) miIntersectO, (voidProcp) NULL, (voidProcp) NULL); + + /* + * Can't alter newReg's extents before we call miRegionOp because + * it might be one of the source regions and miRegionOp depends + * on the extents of those regions being the same. Besides, this + * way there's no checking against rectangles that will be nuked + * due to coalescing, so we have to examine fewer rectangles. + */ + miSetExtents(newReg); + return 1; +} + +static void +miRegionCopy(dstrgn, rgn) + register Region dstrgn; + register Region rgn; + +{ + if (dstrgn != rgn) /* don't want to copy to itself */ + { + if (dstrgn->size < rgn->numRects) + { + if (dstrgn->rects) + { + BOX *prevRects = dstrgn->rects; + + if (! (dstrgn->rects = (BOX *) + Xrealloc((char *) dstrgn->rects, + (unsigned) rgn->numRects * (sizeof(BOX))))) { + Xfree(prevRects); + return; + } + } + dstrgn->size = rgn->numRects; + } + dstrgn->numRects = rgn->numRects; + dstrgn->extents.x1 = rgn->extents.x1; + dstrgn->extents.y1 = rgn->extents.y1; + dstrgn->extents.x2 = rgn->extents.x2; + dstrgn->extents.y2 = rgn->extents.y2; + + memcpy((char *) dstrgn->rects, (char *) rgn->rects, + (int) (rgn->numRects * sizeof(BOX))); + } +} + +#ifdef notdef + +/* + * combinRegs(newReg, reg1, reg2) + * if one region is above or below the other. +*/ + +static void +combineRegs(newReg, reg1, reg2) + register Region newReg; + Region reg1; + Region reg2; +{ + register Region tempReg; + register BOX *rects; + register BOX *rects1; + register BOX *rects2; + register int total; + + rects1 = reg1->rects; + rects2 = reg2->rects; + + total = reg1->numRects + reg2->numRects; + if (! (tempReg = XCreateRegion())) + return; + tempReg->size = total; + /* region 1 is below region 2 */ + if (reg1->extents.y1 > reg2->extents.y1) + { + miRegionCopy(tempReg, reg2); + rects = &tempReg->rects[tempReg->numRects]; + total -= tempReg->numRects; + while (total--) + *rects++ = *rects1++; + } + else + { + miRegionCopy(tempReg, reg1); + rects = &tempReg->rects[tempReg->numRects]; + total -= tempReg->numRects; + while (total--) + *rects++ = *rects2++; + } + tempReg->extents = reg1->extents; + tempReg->numRects = reg1->numRects + reg2->numRects; + EXTENTS(®2->extents, tempReg); + miRegionCopy(newReg, tempReg); + Xfree((char *)tempReg); +} + +/* + * QuickCheck checks to see if it does not have to go through all the + * the ugly code for the region call. It returns 1 if it did all + * the work for Union, otherwise 0 - still work to be done. +*/ + +static int +QuickCheck(newReg, reg1, reg2) + Region newReg, reg1, reg2; +{ + + /* if unioning with itself or no rects to union with */ + if ( (reg1 == reg2) || (!(reg1->numRects)) ) + { + miRegionCopy(newReg, reg2); + return TRUE; + } + + /* if nothing to union */ + if (!(reg2->numRects)) + { + miRegionCopy(newReg, reg1); + return TRUE; + } + + /* could put an extent check to see if add above or below */ + + if ((reg1->extents.y1 >= reg2->extents.y2) || + (reg2->extents.y1 >= reg1->extents.y2) ) + { + combineRegs(newReg, reg1, reg2); + return TRUE; + } + return FALSE; +} + +/* TopRects(rects, reg1, reg2) + * N.B. We now assume that reg1 and reg2 intersect. Therefore we are + * NOT checking in the two while loops for stepping off the end of the + * region. + */ + +static int +TopRects(newReg, rects, reg1, reg2, FirstRect) + register Region newReg; + register BOX *rects; + register Region reg1; + register Region reg2; + BOX *FirstRect; +{ + register BOX *tempRects; + + /* need to add some rects from region 1 */ + if (reg1->extents.y1 < reg2->extents.y1) + { + tempRects = reg1->rects; + while(tempRects->y1 < reg2->extents.y1) + { + MEMCHECK(newReg, rects, FirstRect); + ADDRECTNOX(newReg,rects, tempRects->x1, tempRects->y1, + tempRects->x2, MIN(tempRects->y2, reg2->extents.y1)); + tempRects++; + } + } + /* need to add some rects from region 2 */ + if (reg2->extents.y1 < reg1->extents.y1) + { + tempRects = reg2->rects; + while (tempRects->y1 < reg1->extents.y1) + { + MEMCHECK(newReg, rects, FirstRect); + ADDRECTNOX(newReg, rects, tempRects->x1,tempRects->y1, + tempRects->x2, MIN(tempRects->y2, reg1->extents.y1)); + tempRects++; + } + } + return 1; +} +#endif + +/*====================================================================== + * Generic Region Operator + *====================================================================*/ + +/*- + *----------------------------------------------------------------------- + * miCoalesce -- + * Attempt to merge the boxes in the current band with those in the + * previous one. Used only by miRegionOp. + * + * Results: + * The new index for the previous band. + * + * Side Effects: + * If coalescing takes place: + * - rectangles in the previous band will have their y2 fields + * altered. + * - pReg->numRects will be decreased. + * + *----------------------------------------------------------------------- + */ +/* static int*/ +static int +miCoalesce (pReg, prevStart, curStart) + register Region pReg; /* Region to coalesce */ + int prevStart; /* Index of start of previous band */ + int curStart; /* Index of start of current band */ +{ + register BoxPtr pPrevBox; /* Current box in previous band */ + register BoxPtr pCurBox; /* Current box in current band */ + register BoxPtr pRegEnd; /* End of region */ + int curNumRects; /* Number of rectangles in current + * band */ + int prevNumRects; /* Number of rectangles in previous + * band */ + int bandY1; /* Y1 coordinate for current band */ + + pRegEnd = &pReg->rects[pReg->numRects]; + + pPrevBox = &pReg->rects[prevStart]; + prevNumRects = curStart - prevStart; + + /* + * Figure out how many rectangles are in the current band. Have to do + * this because multiple bands could have been added in miRegionOp + * at the end when one region has been exhausted. + */ + pCurBox = &pReg->rects[curStart]; + bandY1 = pCurBox->y1; + for (curNumRects = 0; + (pCurBox != pRegEnd) && (pCurBox->y1 == bandY1); + curNumRects++) + { + pCurBox++; + } + + if (pCurBox != pRegEnd) + { + /* + * If more than one band was added, we have to find the start + * of the last band added so the next coalescing job can start + * at the right place... (given when multiple bands are added, + * this may be pointless -- see above). + */ + pRegEnd--; + while (pRegEnd[-1].y1 == pRegEnd->y1) + { + pRegEnd--; + } + curStart = pRegEnd - pReg->rects; + pRegEnd = pReg->rects + pReg->numRects; + } + + if ((curNumRects == prevNumRects) && (curNumRects != 0)) { + pCurBox -= curNumRects; + /* + * The bands may only be coalesced if the bottom of the previous + * matches the top scanline of the current. + */ + if (pPrevBox->y2 == pCurBox->y1) + { + /* + * Make sure the bands have boxes in the same places. This + * assumes that boxes have been added in such a way that they + * cover the most area possible. I.e. two boxes in a band must + * have some horizontal space between them. + */ + do + { + if ((pPrevBox->x1 != pCurBox->x1) || + (pPrevBox->x2 != pCurBox->x2)) + { + /* + * The bands don't line up so they can't be coalesced. + */ + return (curStart); + } + pPrevBox++; + pCurBox++; + prevNumRects -= 1; + } while (prevNumRects != 0); + + pReg->numRects -= curNumRects; + pCurBox -= curNumRects; + pPrevBox -= curNumRects; + + /* + * The bands may be merged, so set the bottom y of each box + * in the previous band to that of the corresponding box in + * the current band. + */ + do + { + pPrevBox->y2 = pCurBox->y2; + pPrevBox++; + pCurBox++; + curNumRects -= 1; + } while (curNumRects != 0); + + /* + * If only one band was added to the region, we have to backup + * curStart to the start of the previous band. + * + * If more than one band was added to the region, copy the + * other bands down. The assumption here is that the other bands + * came from the same region as the current one and no further + * coalescing can be done on them since it's all been done + * already... curStart is already in the right place. + */ + if (pCurBox == pRegEnd) + { + curStart = prevStart; + } + else + { + do + { + *pPrevBox++ = *pCurBox++; + } while (pCurBox != pRegEnd); + } + + } + } + return (curStart); +} + +/*- + *----------------------------------------------------------------------- + * miRegionOp -- + * Apply an operation to two regions. Called by miUnion, miInverse, + * miSubtract, miIntersect... + * + * Results: + * None. + * + * Side Effects: + * The new region is overwritten. + * + * Notes: + * The idea behind this function is to view the two regions as sets. + * Together they cover a rectangle of area that this function divides + * into horizontal bands where points are covered only by one region + * or by both. For the first case, the nonOverlapFunc is called with + * each the band and the band's upper and lower extents. For the + * second, the overlapFunc is called to process the entire band. It + * is responsible for clipping the rectangles in the band, though + * this function provides the boundaries. + * At the end of each band, the new region is coalesced, if possible, + * to reduce the number of rectangles in the region. + * + *----------------------------------------------------------------------- + */ +/* static void*/ +static void +miRegionOp(newReg, reg1, reg2, overlapFunc, nonOverlap1Func, nonOverlap2Func) + register Region newReg; /* Place to store result */ + Region reg1; /* First region in operation */ + Region reg2; /* 2d region in operation */ + void (*overlapFunc)(); /* Function to call for over- + * lapping bands */ + void (*nonOverlap1Func)(); /* Function to call for non- + * overlapping bands in region + * 1 */ + void (*nonOverlap2Func)(); /* Function to call for non- + * overlapping bands in region + * 2 */ +{ + register BoxPtr r1; /* Pointer into first region */ + register BoxPtr r2; /* Pointer into 2d region */ + BoxPtr r1End; /* End of 1st region */ + BoxPtr r2End; /* End of 2d region */ + register short ybot; /* Bottom of intersection */ + register short ytop; /* Top of intersection */ + BoxPtr oldRects; /* Old rects for newReg */ + int prevBand; /* Index of start of + * previous band in newReg */ + int curBand; /* Index of start of current + * band in newReg */ + register BoxPtr r1BandEnd; /* End of current band in r1 */ + register BoxPtr r2BandEnd; /* End of current band in r2 */ + short top; /* Top of non-overlapping + * band */ + short bot; /* Bottom of non-overlapping + * band */ + + /* + * Initialization: + * set r1, r2, r1End and r2End appropriately, preserve the important + * parts of the destination region until the end in case it's one of + * the two source regions, then mark the "new" region empty, allocating + * another array of rectangles for it to use. + */ + r1 = reg1->rects; + r2 = reg2->rects; + r1End = r1 + reg1->numRects; + r2End = r2 + reg2->numRects; + + oldRects = newReg->rects; + + EMPTY_REGION(newReg); + + /* + * Allocate a reasonable number of rectangles for the new region. The idea + * is to allocate enough so the individual functions don't need to + * reallocate and copy the array, which is time consuming, yet we don't + * have to worry about using too much memory. I hope to be able to + * nuke the Xrealloc() at the end of this function eventually. + */ + newReg->size = max(reg1->numRects,reg2->numRects) * 2; + + if (! (newReg->rects = (BoxPtr) + Xmalloc ((unsigned) (sizeof(BoxRec) * newReg->size)))) { + newReg->size = 0; + return; + } + + /* + * Initialize ybot and ytop. + * In the upcoming loop, ybot and ytop serve different functions depending + * on whether the band being handled is an overlapping or non-overlapping + * band. + * In the case of a non-overlapping band (only one of the regions + * has points in the band), ybot is the bottom of the most recent + * intersection and thus clips the top of the rectangles in that band. + * ytop is the top of the next intersection between the two regions and + * serves to clip the bottom of the rectangles in the current band. + * For an overlapping band (where the two regions intersect), ytop clips + * the top of the rectangles of both regions and ybot clips the bottoms. + */ + if (reg1->extents.y1 < reg2->extents.y1) + ybot = reg1->extents.y1; + else + ybot = reg2->extents.y1; + + /* + * prevBand serves to mark the start of the previous band so rectangles + * can be coalesced into larger rectangles. qv. miCoalesce, above. + * In the beginning, there is no previous band, so prevBand == curBand + * (curBand is set later on, of course, but the first band will always + * start at index 0). prevBand and curBand must be indices because of + * the possible expansion, and resultant moving, of the new region's + * array of rectangles. + */ + prevBand = 0; + + do + { + curBand = newReg->numRects; + + /* + * This algorithm proceeds one source-band (as opposed to a + * destination band, which is determined by where the two regions + * intersect) at a time. r1BandEnd and r2BandEnd serve to mark the + * rectangle after the last one in the current band for their + * respective regions. + */ + r1BandEnd = r1; + while ((r1BandEnd != r1End) && (r1BandEnd->y1 == r1->y1)) + { + r1BandEnd++; + } + + r2BandEnd = r2; + while ((r2BandEnd != r2End) && (r2BandEnd->y1 == r2->y1)) + { + r2BandEnd++; + } + + /* + * First handle the band that doesn't intersect, if any. + * + * Note that attention is restricted to one band in the + * non-intersecting region at once, so if a region has n + * bands between the current position and the next place it overlaps + * the other, this entire loop will be passed through n times. + */ + if (r1->y1 < r2->y1) + { + top = max(r1->y1,ybot); + bot = min(r1->y2,r2->y1); + + if ((top != bot) && (nonOverlap1Func != (void (*)())NULL)) + { + (* nonOverlap1Func) (newReg, r1, r1BandEnd, top, bot); + } + + ytop = r2->y1; + } + else if (r2->y1 < r1->y1) + { + top = max(r2->y1,ybot); + bot = min(r2->y2,r1->y1); + + if ((top != bot) && (nonOverlap2Func != (void (*)())NULL)) + { + (* nonOverlap2Func) (newReg, r2, r2BandEnd, top, bot); + } + + ytop = r1->y1; + } + else + { + ytop = r1->y1; + } + + /* + * If any rectangles got added to the region, try and coalesce them + * with rectangles from the previous band. Note we could just do + * this test in miCoalesce, but some machines incur a not + * inconsiderable cost for function calls, so... + */ + if (newReg->numRects != curBand) + { + prevBand = miCoalesce (newReg, prevBand, curBand); + } + + /* + * Now see if we've hit an intersecting band. The two bands only + * intersect if ybot > ytop + */ + ybot = min(r1->y2, r2->y2); + curBand = newReg->numRects; + if (ybot > ytop) + { + (* overlapFunc) (newReg, r1, r1BandEnd, r2, r2BandEnd, ytop, ybot); + + } + + if (newReg->numRects != curBand) + { + prevBand = miCoalesce (newReg, prevBand, curBand); + } + + /* + * If we've finished with a band (y2 == ybot) we skip forward + * in the region to the next band. + */ + if (r1->y2 == ybot) + { + r1 = r1BandEnd; + } + if (r2->y2 == ybot) + { + r2 = r2BandEnd; + } + } while ((r1 != r1End) && (r2 != r2End)); + + /* + * Deal with whichever region still has rectangles left. + */ + curBand = newReg->numRects; + if (r1 != r1End) + { + if (nonOverlap1Func != (void (*)())NULL) + { + do + { + r1BandEnd = r1; + while ((r1BandEnd < r1End) && (r1BandEnd->y1 == r1->y1)) + { + r1BandEnd++; + } + (* nonOverlap1Func) (newReg, r1, r1BandEnd, + max(r1->y1,ybot), r1->y2); + r1 = r1BandEnd; + } while (r1 != r1End); + } + } + else if ((r2 != r2End) && (nonOverlap2Func != (void (*)())NULL)) + { + do + { + r2BandEnd = r2; + while ((r2BandEnd < r2End) && (r2BandEnd->y1 == r2->y1)) + { + r2BandEnd++; + } + (* nonOverlap2Func) (newReg, r2, r2BandEnd, + max(r2->y1,ybot), r2->y2); + r2 = r2BandEnd; + } while (r2 != r2End); + } + + if (newReg->numRects != curBand) + { + (void) miCoalesce (newReg, prevBand, curBand); + } + + /* + * A bit of cleanup. To keep regions from growing without bound, + * we shrink the array of rectangles to match the new number of + * rectangles in the region. This never goes to 0, however... + * + * Only do this stuff if the number of rectangles allocated is more than + * twice the number of rectangles in the region (a simple optimization...). + */ + if (newReg->numRects < (newReg->size >> 1)) + { + if (REGION_NOT_EMPTY(newReg)) + { + BoxPtr prev_rects = newReg->rects; + newReg->size = newReg->numRects; + newReg->rects = (BoxPtr) Xrealloc ((char *) newReg->rects, + (unsigned) (sizeof(BoxRec) * newReg->size)); + if (! newReg->rects) + newReg->rects = prev_rects; + } + else + { + /* + * No point in doing the extra work involved in an Xrealloc if + * the region is empty + */ + newReg->size = 1; + Xfree((char *) newReg->rects); + newReg->rects = (BoxPtr) Xmalloc(sizeof(BoxRec)); + } + } + Xfree ((char *) oldRects); + return; +} + + +/*====================================================================== + * Region Union + *====================================================================*/ + +/*- + *----------------------------------------------------------------------- + * miUnionNonO -- + * Handle a non-overlapping band for the union operation. Just + * Adds the rectangles into the region. Doesn't have to check for + * subsumption or anything. + * + * Results: + * None. + * + * Side Effects: + * pReg->numRects is incremented and the final rectangles overwritten + * with the rectangles we're passed. + * + *----------------------------------------------------------------------- + */ +/* static void*/ +static int +miUnionNonO (pReg, r, rEnd, y1, y2) + register Region pReg; + register BoxPtr r; + BoxPtr rEnd; + register short y1; + register short y2; +{ + register BoxPtr pNextRect; + + pNextRect = &pReg->rects[pReg->numRects]; + + assert(y1 < y2); + + while (r != rEnd) + { + assert(r->x1 < r->x2); + MEMCHECK(pReg, pNextRect, pReg->rects); + pNextRect->x1 = r->x1; + pNextRect->y1 = y1; + pNextRect->x2 = r->x2; + pNextRect->y2 = y2; + pReg->numRects += 1; + pNextRect++; + + assert(pReg->numRects<=pReg->size); + r++; + } + return 0; /* lint */ +} + + +/*- + *----------------------------------------------------------------------- + * miUnionO -- + * Handle an overlapping band for the union operation. Picks the + * left-most rectangle each time and merges it into the region. + * + * Results: + * None. + * + * Side Effects: + * Rectangles are overwritten in pReg->rects and pReg->numRects will + * be changed. + * + *----------------------------------------------------------------------- + */ + +/* static void*/ +static int +miUnionO (pReg, r1, r1End, r2, r2End, y1, y2) + register Region pReg; + register BoxPtr r1; + BoxPtr r1End; + register BoxPtr r2; + BoxPtr r2End; + register short y1; + register short y2; +{ + register BoxPtr pNextRect; + + pNextRect = &pReg->rects[pReg->numRects]; + +#define MERGERECT(r) \ + if ((pReg->numRects != 0) && \ + (pNextRect[-1].y1 == y1) && \ + (pNextRect[-1].y2 == y2) && \ + (pNextRect[-1].x2 >= r->x1)) \ + { \ + if (pNextRect[-1].x2 < r->x2) \ + { \ + pNextRect[-1].x2 = r->x2; \ + assert(pNextRect[-1].x1rects); \ + pNextRect->y1 = y1; \ + pNextRect->y2 = y2; \ + pNextRect->x1 = r->x1; \ + pNextRect->x2 = r->x2; \ + pReg->numRects += 1; \ + pNextRect += 1; \ + } \ + assert(pReg->numRects<=pReg->size);\ + r++; + + assert (y1x1 < r2->x1) + { + MERGERECT(r1); + } + else + { + MERGERECT(r2); + } + } + + if (r1 != r1End) + { + do + { + MERGERECT(r1); + } while (r1 != r1End); + } + else while (r2 != r2End) + { + MERGERECT(r2); + } + return 0; /* lint */ +} + +int +XUnionRegion(reg1, reg2, newReg) + Region reg1; + Region reg2; /* source regions */ + Region newReg; /* destination Region */ +{ + /* checks all the simple cases */ + + /* + * Region 1 and 2 are the same or region 1 is empty + */ + if ( (reg1 == reg2) || (!(reg1->numRects)) ) + { + if (newReg != reg2) + miRegionCopy(newReg, reg2); + return 1; + } + + /* + * if nothing to union (region 2 empty) + */ + if (!(reg2->numRects)) + { + if (newReg != reg1) + miRegionCopy(newReg, reg1); + return 1; + } + + /* + * Region 1 completely subsumes region 2 + */ + if ((reg1->numRects == 1) && + (reg1->extents.x1 <= reg2->extents.x1) && + (reg1->extents.y1 <= reg2->extents.y1) && + (reg1->extents.x2 >= reg2->extents.x2) && + (reg1->extents.y2 >= reg2->extents.y2)) + { + if (newReg != reg1) + miRegionCopy(newReg, reg1); + return 1; + } + + /* + * Region 2 completely subsumes region 1 + */ + if ((reg2->numRects == 1) && + (reg2->extents.x1 <= reg1->extents.x1) && + (reg2->extents.y1 <= reg1->extents.y1) && + (reg2->extents.x2 >= reg1->extents.x2) && + (reg2->extents.y2 >= reg1->extents.y2)) + { + if (newReg != reg2) + miRegionCopy(newReg, reg2); + return 1; + } + + miRegionOp (newReg, reg1, reg2, (voidProcp) miUnionO, + (voidProcp) miUnionNonO, (voidProcp) miUnionNonO); + + newReg->extents.x1 = min(reg1->extents.x1, reg2->extents.x1); + newReg->extents.y1 = min(reg1->extents.y1, reg2->extents.y1); + newReg->extents.x2 = max(reg1->extents.x2, reg2->extents.x2); + newReg->extents.y2 = max(reg1->extents.y2, reg2->extents.y2); + + return 1; +} + + +/*====================================================================== + * Region Subtraction + *====================================================================*/ + +/*- + *----------------------------------------------------------------------- + * miSubtractNonO -- + * Deal with non-overlapping band for subtraction. Any parts from + * region 2 we discard. Anything from region 1 we add to the region. + * + * Results: + * None. + * + * Side Effects: + * pReg may be affected. + * + *----------------------------------------------------------------------- + */ +/* static void*/ +static int +miSubtractNonO1 (pReg, r, rEnd, y1, y2) + register Region pReg; + register BoxPtr r; + BoxPtr rEnd; + register short y1; + register short y2; +{ + register BoxPtr pNextRect; + + pNextRect = &pReg->rects[pReg->numRects]; + + assert(y1x1x2); + MEMCHECK(pReg, pNextRect, pReg->rects); + pNextRect->x1 = r->x1; + pNextRect->y1 = y1; + pNextRect->x2 = r->x2; + pNextRect->y2 = y2; + pReg->numRects += 1; + pNextRect++; + + assert(pReg->numRects <= pReg->size); + + r++; + } + return 0; /* lint */ +} + +/*- + *----------------------------------------------------------------------- + * miSubtractO -- + * Overlapping band subtraction. x1 is the left-most point not yet + * checked. + * + * Results: + * None. + * + * Side Effects: + * pReg may have rectangles added to it. + * + *----------------------------------------------------------------------- + */ +/* static void*/ +static int +miSubtractO (pReg, r1, r1End, r2, r2End, y1, y2) + register Region pReg; + register BoxPtr r1; + BoxPtr r1End; + register BoxPtr r2; + BoxPtr r2End; + register short y1; + register short y2; +{ + register BoxPtr pNextRect; + register int x1; + + x1 = r1->x1; + + assert(y1rects[pReg->numRects]; + + while ((r1 != r1End) && (r2 != r2End)) + { + if (r2->x2 <= x1) + { + /* + * Subtrahend missed the boat: go to next subtrahend. + */ + r2++; + } + else if (r2->x1 <= x1) + { + /* + * Subtrahend preceeds minuend: nuke left edge of minuend. + */ + x1 = r2->x2; + if (x1 >= r1->x2) + { + /* + * Minuend completely covered: advance to next minuend and + * reset left fence to edge of new minuend. + */ + r1++; + if (r1 != r1End) + x1 = r1->x1; + } + else + { + /* + * Subtrahend now used up since it doesn't extend beyond + * minuend + */ + r2++; + } + } + else if (r2->x1 < r1->x2) + { + /* + * Left part of subtrahend covers part of minuend: add uncovered + * part of minuend to region and skip to next subtrahend. + */ + assert(x1x1); + MEMCHECK(pReg, pNextRect, pReg->rects); + pNextRect->x1 = x1; + pNextRect->y1 = y1; + pNextRect->x2 = r2->x1; + pNextRect->y2 = y2; + pReg->numRects += 1; + pNextRect++; + + assert(pReg->numRects<=pReg->size); + + x1 = r2->x2; + if (x1 >= r1->x2) + { + /* + * Minuend used up: advance to new... + */ + r1++; + if (r1 != r1End) + x1 = r1->x1; + } + else + { + /* + * Subtrahend used up + */ + r2++; + } + } + else + { + /* + * Minuend used up: add any remaining piece before advancing. + */ + if (r1->x2 > x1) + { + MEMCHECK(pReg, pNextRect, pReg->rects); + pNextRect->x1 = x1; + pNextRect->y1 = y1; + pNextRect->x2 = r1->x2; + pNextRect->y2 = y2; + pReg->numRects += 1; + pNextRect++; + assert(pReg->numRects<=pReg->size); + } + r1++; + if (r1 != r1End) + x1 = r1->x1; + } + } + + /* + * Add remaining minuend rectangles to region. + */ + while (r1 != r1End) + { + assert(x1x2); + MEMCHECK(pReg, pNextRect, pReg->rects); + pNextRect->x1 = x1; + pNextRect->y1 = y1; + pNextRect->x2 = r1->x2; + pNextRect->y2 = y2; + pReg->numRects += 1; + pNextRect++; + + assert(pReg->numRects<=pReg->size); + + r1++; + if (r1 != r1End) + { + x1 = r1->x1; + } + } + return 0; /* lint */ +} + +/*- + *----------------------------------------------------------------------- + * miSubtract -- + * Subtract regS from regM and leave the result in regD. + * S stands for subtrahend, M for minuend and D for difference. + * + * Results: + * TRUE. + * + * Side Effects: + * regD is overwritten. + * + *----------------------------------------------------------------------- + */ + +int +XSubtractRegion(regM, regS, regD) + Region regM; + Region regS; + register Region regD; +{ + /* check for trivial reject */ + if ( (!(regM->numRects)) || (!(regS->numRects)) || + (!EXTENTCHECK(®M->extents, ®S->extents)) ) + { + miRegionCopy(regD, regM); + return 1; + } + + miRegionOp (regD, regM, regS, (voidProcp) miSubtractO, + (voidProcp) miSubtractNonO1, (voidProcp) NULL); + + /* + * Can't alter newReg's extents before we call miRegionOp because + * it might be one of the source regions and miRegionOp depends + * on the extents of those regions being the unaltered. Besides, this + * way there's no checking against rectangles that will be nuked + * due to coalescing, so we have to examine fewer rectangles. + */ + miSetExtents (regD); + return 1; +} + +int +XXorRegion( sra, srb, dr ) + Region sra, srb, dr; +{ + Region tra, trb; + + if ((! (tra = XCreateRegion())) || (! (trb = XCreateRegion()))) + return 0; + (void) XSubtractRegion(sra,srb,tra); + (void) XSubtractRegion(srb,sra,trb); + (void) XUnionRegion(tra,trb,dr); + XDestroyRegion(tra); + XDestroyRegion(trb); + return 0; +} + +/* + * Check to see if the region is empty. Assumes a region is passed + * as a parameter + */ +int +XEmptyRegion( r ) + Region r; +{ + if( r->numRects == 0 ) return TRUE; + else return FALSE; +} + +/* + * Check to see if two regions are equal + */ +int +XEqualRegion( r1, r2 ) + Region r1, r2; +{ + int i; + + if( r1->numRects != r2->numRects ) return FALSE; + else if( r1->numRects == 0 ) return TRUE; + else if ( r1->extents.x1 != r2->extents.x1 ) return FALSE; + else if ( r1->extents.x2 != r2->extents.x2 ) return FALSE; + else if ( r1->extents.y1 != r2->extents.y1 ) return FALSE; + else if ( r1->extents.y2 != r2->extents.y2 ) return FALSE; + else for( i=0; i < r1->numRects; i++ ) { + if ( r1->rects[i].x1 != r2->rects[i].x1 ) return FALSE; + else if ( r1->rects[i].x2 != r2->rects[i].x2 ) return FALSE; + else if ( r1->rects[i].y1 != r2->rects[i].y1 ) return FALSE; + else if ( r1->rects[i].y2 != r2->rects[i].y2 ) return FALSE; + } + return TRUE; +} + +int +XPointInRegion( pRegion, x, y ) + Region pRegion; + int x, y; +{ + int i; + + if (pRegion->numRects == 0) + return FALSE; + if (!INBOX(pRegion->extents, x, y)) + return FALSE; + for (i=0; inumRects; i++) + { + if (INBOX (pRegion->rects[i], x, y)) + return TRUE; + } + return FALSE; +} + +int +XRectInRegion(region, rx, ry, rwidth, rheight) + register Region region; + int rx, ry; + unsigned int rwidth, rheight; +{ + register BoxPtr pbox; + register BoxPtr pboxEnd; + Box rect; + register BoxPtr prect = ▭ + int partIn, partOut; + + prect->x1 = rx; + prect->y1 = ry; + prect->x2 = rwidth + rx; + prect->y2 = rheight + ry; + + /* this is (just) a useful optimization */ + if ((region->numRects == 0) || !EXTENTCHECK(®ion->extents, prect)) + return(RectangleOut); + + partOut = FALSE; + partIn = FALSE; + + /* can stop when both partOut and partIn are TRUE, or we reach prect->y2 */ + for (pbox = region->rects, pboxEnd = pbox + region->numRects; + pbox < pboxEnd; + pbox++) + { + + if (pbox->y2 <= ry) + continue; /* getting up to speed or skipping remainder of band */ + + if (pbox->y1 > ry) + { + partOut = TRUE; /* missed part of rectangle above */ + if (partIn || (pbox->y1 >= prect->y2)) + break; + ry = pbox->y1; /* x guaranteed to be == prect->x1 */ + } + + if (pbox->x2 <= rx) + continue; /* not far enough over yet */ + + if (pbox->x1 > rx) + { + partOut = TRUE; /* missed part of rectangle to left */ + if (partIn) + break; + } + + if (pbox->x1 < prect->x2) + { + partIn = TRUE; /* definitely overlap */ + if (partOut) + break; + } + + if (pbox->x2 >= prect->x2) + { + ry = pbox->y2; /* finished with this band */ + if (ry >= prect->y2) + break; + rx = prect->x1; /* reset x out to left again */ + } else + { + /* + * Because boxes in a band are maximal width, if the first box + * to overlap the rectangle doesn't completely cover it in that + * band, the rectangle must be partially out, since some of it + * will be uncovered in that band. partIn will have been set true + * by now... + */ + break; + } + + } + + return(partIn ? ((ry < prect->y2) ? RectanglePart : RectangleIn) : + RectangleOut); +} diff --git a/Xregion/Xregion.dsp b/Xregion/Xregion.dsp new file mode 100644 index 00000000..87d04bff --- /dev/null +++ b/Xregion/Xregion.dsp @@ -0,0 +1,132 @@ +# Microsoft Developer Studio Project File - Name="Xregion" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=Xregion - Win32 Debug Unicode +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "Xregion.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "Xregion.mak" CFG="Xregion - Win32 Debug Unicode" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "Xregion - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "Xregion - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE "Xregion - Win32 Debug Unicode" (based on "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "Xregion - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I ".." /D "NDEBUG" /D "_LIB" /D "WIN32" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x809 /d "NDEBUG" +# ADD RSC /l 0x809 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ELSEIF "$(CFG)" == "Xregion - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I ".." /D "_DEBUG" /D "_LIB" /D "WIN32" /D "_MBCS" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE RSC /l 0x809 /d "_DEBUG" +# ADD RSC /l 0x809 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ELSEIF "$(CFG)" == "Xregion - Win32 Debug Unicode" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Xregion___Win32_Debug_Unicode" +# PROP BASE Intermediate_Dir "Xregion___Win32_Debug_Unicode" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug_Unicode" +# PROP Intermediate_Dir "Debug_Unicode" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I ".." /D "_DEBUG" /D "_LIB" /D "WIN32" /D "_MBCS" /FD /GZ /c +# SUBTRACT BASE CPP /YX +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I ".." /D "_LIB" /D "_DEBUG" /D "WIN32" /D "_UNICODE" /D "UNICODE" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE RSC /l 0x809 /d "_DEBUG" +# ADD RSC /l 0x809 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ENDIF + +# Begin Target + +# Name "Xregion - Win32 Release" +# Name "Xregion - Win32 Debug" +# Name "Xregion - Win32 Debug Unicode" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\Region.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\region.h +# End Source File +# Begin Source File + +SOURCE=.\Xregion.h +# End Source File +# End Group +# End Target +# End Project diff --git a/Xregion/Xregion.h b/Xregion/Xregion.h new file mode 100644 index 00000000..7fa44d96 --- /dev/null +++ b/Xregion/Xregion.h @@ -0,0 +1,220 @@ +/* $Xorg: Xutil.h,v 1.8 2001/02/09 02:03:39 xorgcvs Exp $ */ + +/*********************************************************** + +Copyright 1987, 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 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ +/* $XFree86: xc/lib/X11/Xutil.h,v 3.4 2001/12/14 19:54:10 dawes Exp $ */ + +#ifndef _XREGION_H_ +#define _XREGION_H_ + +// - Faked defines to fool the X11 region code + +#include +#include + +#define Bool int +#define Xmalloc malloc +#define Xfree free +#define Xrealloc realloc + +#ifndef max +#define max(a,b) (((a) > (b)) ? (a) : (b)) +#endif + +#ifndef min +#define min(a,b) (((a) < (b)) ? (a) : (b)) +#endif + +#define NeedFunctionPrototypes 1 + +// - Cribbed from Xlib.h + +typedef struct { + short x, y; +} XPoint; + +typedef struct { + short x, y; + unsigned short width, height; +} XRectangle; + +/* + * opaque reference to Region data type + */ +typedef struct _XRegion *Region; + +/* Return values from XRectInRegion() */ + +#define RectangleOut 0 +#define RectangleIn 1 +#define RectanglePart 2 + +#ifdef __cplusplus +extern "C" { +#endif + +extern int XClipBox( +#if NeedFunctionPrototypes + Region /* r */, + XRectangle* /* rect_return */ +#endif +); + +extern Region XCreateRegion( +#if NeedFunctionPrototypes + void +#endif +); + +extern const char *XDefaultString (void); + +extern int XDestroyRegion( +#if NeedFunctionPrototypes + Region /* r */ +#endif +); + +extern int XEmptyRegion( +#if NeedFunctionPrototypes + Region /* r */ +#endif +); + +extern int XEqualRegion( +#if NeedFunctionPrototypes + Region /* r1 */, + Region /* r2 */ +#endif +); + +extern int XIntersectRegion( +#if NeedFunctionPrototypes + Region /* sra */, + Region /* srb */, + Region /* dr_return */ +#endif +); + +extern int XOffsetRegion( +#if NeedFunctionPrototypes + Region /* r */, + int /* dx */, + int /* dy */ +#endif +); + +extern Bool XPointInRegion( +#if NeedFunctionPrototypes + Region /* r */, + int /* x */, + int /* y */ +#endif +); + +extern Region XPolygonRegion( +#if NeedFunctionPrototypes + XPoint* /* points */, + int /* n */, + int /* fill_rule */ +#endif +); + +extern int XRectInRegion( +#if NeedFunctionPrototypes + Region /* r */, + int /* x */, + int /* y */, + unsigned int /* width */, + unsigned int /* height */ +#endif +); + +extern int XShrinkRegion( +#if NeedFunctionPrototypes + Region /* r */, + int /* dx */, + int /* dy */ +#endif +); + +extern int XSubtractRegion( +#if NeedFunctionPrototypes + Region /* sra */, + Region /* srb */, + Region /* dr_return */ +#endif +); + +extern int XUnionRectWithRegion( +#if NeedFunctionPrototypes + XRectangle* /* rectangle */, + Region /* src_region */, + Region /* dest_region_return */ +#endif +); + +extern int XUnionRegion( +#if NeedFunctionPrototypes + Region /* sra */, + Region /* srb */, + Region /* dr_return */ +#endif +); + +extern int XXorRegion( +#if NeedFunctionPrototypes + Region /* sra */, + Region /* srb */, + Region /* dr_return */ +#endif +); + +#ifdef __cplusplus +}; +#endif + +#endif /* _XUTIL_H_ */ diff --git a/Xregion/region.h b/Xregion/region.h new file mode 100644 index 00000000..2ddf12ca --- /dev/null +++ b/Xregion/region.h @@ -0,0 +1,190 @@ +/* $Xorg: region.h,v 1.4 2001/02/09 02:03:40 xorgcvs Exp $ */ +/************************************************************************ + +Copyright 1987, 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 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +************************************************************************/ + +#ifndef _XREGION_H +#define _XREGION_H + +typedef struct { + short x1, x2, y1, y2; +} Box, BOX, BoxRec, *BoxPtr; + +typedef struct { + short x, y, width, height; +}RECTANGLE, RectangleRec, *RectanglePtr; + +#define TRUE 1 +#define FALSE 0 +#define MAXSHORT 32767 +#define MINSHORT -MAXSHORT +#ifndef MAX +#define MAX(a,b) (((a) > (b)) ? (a) : (b)) +#endif +#ifndef MIN +#define MIN(a,b) (((a) < (b)) ? (a) : (b)) +#endif + + +/* + * clip region + */ + +typedef struct _XRegion { + long size; + long numRects; + BOX *rects; + BOX extents; +} REGION; + +/* Xutil.h contains the declaration: + * typedef struct _XRegion *Region; + */ + +/* 1 if two BOXs overlap. + * 0 if two BOXs do not overlap. + * Remember, x2 and y2 are not in the region + */ +#define EXTENTCHECK(r1, r2) \ + ((r1)->x2 > (r2)->x1 && \ + (r1)->x1 < (r2)->x2 && \ + (r1)->y2 > (r2)->y1 && \ + (r1)->y1 < (r2)->y2) + +/* + * update region extents + */ +#define EXTENTS(r,idRect){\ + if((r)->x1 < (idRect)->extents.x1)\ + (idRect)->extents.x1 = (r)->x1;\ + if((r)->y1 < (idRect)->extents.y1)\ + (idRect)->extents.y1 = (r)->y1;\ + if((r)->x2 > (idRect)->extents.x2)\ + (idRect)->extents.x2 = (r)->x2;\ + if((r)->y2 > (idRect)->extents.y2)\ + (idRect)->extents.y2 = (r)->y2;\ + } + +/* + * Check to see if there is enough memory in the present region. + */ +#define MEMCHECK(reg, rect, firstrect){\ + if ((reg)->numRects >= ((reg)->size - 1)){\ + (firstrect) = (BOX *) Xrealloc \ + ((char *)(firstrect), (unsigned) (2 * (sizeof(BOX)) * ((reg)->size)));\ + if ((firstrect) == 0)\ + return(0);\ + (reg)->size *= 2;\ + (rect) = &(firstrect)[(reg)->numRects];\ + }\ + } + +/* this routine checks to see if the previous rectangle is the same + * or subsumes the new rectangle to add. + */ + +#define CHECK_PREVIOUS(Reg, R, Rx1, Ry1, Rx2, Ry2)\ + (!(((Reg)->numRects > 0)&&\ + ((R-1)->y1 == (Ry1)) &&\ + ((R-1)->y2 == (Ry2)) &&\ + ((R-1)->x1 <= (Rx1)) &&\ + ((R-1)->x2 >= (Rx2)))) + +/* add a rectangle to the given Region */ +#define ADDRECT(reg, r, rx1, ry1, rx2, ry2){\ + if (((rx1) < (rx2)) && ((ry1) < (ry2)) &&\ + CHECK_PREVIOUS((reg), (r), (rx1), (ry1), (rx2), (ry2))){\ + (r)->x1 = (rx1);\ + (r)->y1 = (ry1);\ + (r)->x2 = (rx2);\ + (r)->y2 = (ry2);\ + EXTENTS((r), (reg));\ + (reg)->numRects++;\ + (r)++;\ + }\ + } + + + +/* add a rectangle to the given Region */ +#define ADDRECTNOX(reg, r, rx1, ry1, rx2, ry2){\ + if ((rx1 < rx2) && (ry1 < ry2) &&\ + CHECK_PREVIOUS((reg), (r), (rx1), (ry1), (rx2), (ry2))){\ + (r)->x1 = (rx1);\ + (r)->y1 = (ry1);\ + (r)->x2 = (rx2);\ + (r)->y2 = (ry2);\ + (reg)->numRects++;\ + (r)++;\ + }\ + } + +#define EMPTY_REGION(pReg) pReg->numRects = 0 + +#define REGION_NOT_EMPTY(pReg) pReg->numRects + +#define INBOX(r, x, y) \ + ( ( ((r).x2 > x)) && \ + ( ((r).x1 <= x)) && \ + ( ((r).y2 > y)) && \ + ( ((r).y1 <= y)) ) + +/* + * number of points to buffer before sending them off + * to scanlines() : Must be an even number + */ +#define NUMPTSTOBUFFER 200 + +/* + * used to allocate buffers for points and link + * the buffers together + */ +typedef struct _POINTBLOCK { + XPoint pts[NUMPTSTOBUFFER]; + struct _POINTBLOCK *next; +} POINTBLOCK; + +#endif diff --git a/boilerplate.mk b/boilerplate.mk new file mode 100644 index 00000000..979731c5 --- /dev/null +++ b/boilerplate.mk @@ -0,0 +1,35 @@ + +all:: + @subdirs="$(SUBDIRS)"; for d in $$subdirs; do (cd $$d; $(MAKE) $@) || exit 1; done + +clean:: + @subdirs="$(SUBDIRS)"; for d in $$subdirs; do (cd $$d; $(MAKE) $@) || exit 1; done + +clean:: + rm -f $(program) $(library) *.o + +SHELL = @SHELL@ +top_srcdir = @top_srcdir@ +@SET_MAKE@ +CC = @CC@ +CFLAGS = @CFLAGS@ $(DIR_CFLAGS) +CCLD = $(CC) +CXX = @CXX@ +CXXFLAGS = @CXXFLAGS@ +CXXLD = $(CXX) +CPPFLAGS = @CPPFLAGS@ +DEFS = @DEFS@ +ALL_CPPFLAGS = $(CPPFLAGS) $(DEFS) $(DIR_CPPFLAGS) +LIBS = @LIBS@ +LDFLAGS = @LDFLAGS@ +RANLIB = @RANLIB@ +AR = ar cq + +.SUFFIXES: +.SUFFIXES: .cxx .c .o + +.c.o: + $(CC) $(ALL_CPPFLAGS) $(CFLAGS) -c $< + +.cxx.o: + $(CXX) $(ALL_CPPFLAGS) $(CXXFLAGS) -c $< diff --git a/configure b/configure new file mode 100755 index 00000000..40951d21 --- /dev/null +++ b/configure @@ -0,0 +1,2299 @@ +#! /bin/sh + +# Guess values for system-dependent variables and create Makefiles. +# Generated automatically using autoconf version 2.13 +# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc. +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. + +# Defaults: +ac_help= +ac_default_prefix=/usr/local +# Any additions from configure.in: +ac_help="$ac_help + --with-x use the X Window System" +ac_help="$ac_help + --with-installed-zlib use the version of zlib which is installed on the + system instead of the one distributed with VNC" + +# Initialize some variables set by options. +# The variables have the same names as the options, with +# dashes changed to underlines. +build=NONE +cache_file=./config.cache +exec_prefix=NONE +host=NONE +no_create= +nonopt=NONE +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +target=NONE +verbose= +x_includes=NONE +x_libraries=NONE +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +# Initialize some other variables. +subdirs= +MFLAGS= MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} +# Maximum number of lines to put in a shell here document. +ac_max_here_lines=12 + +ac_prev= +for ac_option +do + + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi + + case "$ac_option" in + -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) ac_optarg= ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case "$ac_option" in + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir="$ac_optarg" ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build="$ac_optarg" ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file="$ac_optarg" ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir="$ac_optarg" ;; + + -disable-* | --disable-*) + ac_feature=`echo $ac_option|sed -e 's/-*disable-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + eval "enable_${ac_feature}=no" ;; + + -enable-* | --enable-*) + ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "enable_${ac_feature}='$ac_optarg'" ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix="$ac_optarg" ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he) + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat << EOF +Usage: configure [options] [host] +Options: [defaults in brackets after descriptions] +Configuration: + --cache-file=FILE cache test results in FILE + --help print this message + --no-create do not create output files + --quiet, --silent do not print \`checking...' messages + --version print the version of autoconf that created configure +Directory and file names: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [same as prefix] + --bindir=DIR user executables in DIR [EPREFIX/bin] + --sbindir=DIR system admin executables in DIR [EPREFIX/sbin] + --libexecdir=DIR program executables in DIR [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data in DIR + [PREFIX/share] + --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data in DIR + [PREFIX/com] + --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var] + --libdir=DIR object code libraries in DIR [EPREFIX/lib] + --includedir=DIR C header files in DIR [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include] + --infodir=DIR info documentation in DIR [PREFIX/info] + --mandir=DIR man documentation in DIR [PREFIX/man] + --srcdir=DIR find the sources in DIR [configure dir or ..] + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM + run sed PROGRAM on installed program names +EOF + cat << EOF +Host type: + --build=BUILD configure for building on BUILD [BUILD=HOST] + --host=HOST configure for HOST [guessed] + --target=TARGET configure for TARGET [TARGET=HOST] +Features and packages: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --x-includes=DIR X include files are in DIR + --x-libraries=DIR X library files are in DIR +EOF + if test -n "$ac_help"; then + echo "--enable and --with options recognized:$ac_help" + fi + exit 0 ;; + + -host | --host | --hos | --ho) + ac_prev=host ;; + -host=* | --host=* | --hos=* | --ho=*) + host="$ac_optarg" ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir="$ac_optarg" ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir="$ac_optarg" ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir="$ac_optarg" ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir="$ac_optarg" ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir="$ac_optarg" ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir="$ac_optarg" ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir="$ac_optarg" ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix="$ac_optarg" ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix="$ac_optarg" ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix="$ac_optarg" ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name="$ac_optarg" ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir="$ac_optarg" ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir="$ac_optarg" ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site="$ac_optarg" ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir="$ac_optarg" ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir="$ac_optarg" ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target="$ac_optarg" ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers) + echo "configure generated by autoconf version 2.13" + exit 0 ;; + + -with-* | --with-*) + ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "with_${ac_package}='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`echo $ac_option|sed -e 's/-*without-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + eval "with_${ac_package}=no" ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes="$ac_optarg" ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries="$ac_optarg" ;; + + -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; } + ;; + + *) + if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then + echo "configure: warning: $ac_option: invalid host type" 1>&2 + fi + if test "x$nonopt" != xNONE; then + { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } + fi + nonopt="$ac_option" + ;; + + esac +done + +if test -n "$ac_prev"; then + { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; } +fi + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +# File descriptor usage: +# 0 standard input +# 1 file creation +# 2 errors and warnings +# 3 some systems may open it to /dev/tty +# 4 used on the Kubota Titan +# 6 checking for... messages and results +# 5 compiler messages saved in config.log +if test "$silent" = yes; then + exec 6>/dev/null +else + exec 6>&1 +fi +exec 5>./config.log + +echo "\ +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. +" 1>&5 + +# Strip out --no-create and --no-recursion so they do not pile up. +# Also quote any args containing shell metacharacters. +ac_configure_args= +for ac_arg +do + case "$ac_arg" in + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) ;; + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) + ac_configure_args="$ac_configure_args '$ac_arg'" ;; + *) ac_configure_args="$ac_configure_args $ac_arg" ;; + esac +done + +# NLS nuisances. +# Only set these to C if already set. These must not be set unconditionally +# because not all systems understand e.g. LANG=C (notably SCO). +# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'! +# Non-C LC_CTYPE values break the ctype check. +if test "${LANG+set}" = set; then LANG=C; export LANG; fi +if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi +if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi +if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo > confdefs.h + +# A filename unique to this package, relative to the directory that +# configure is in, which we can look for to find out if srcdir is correct. +ac_unique_file=rdr/InStream.h + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then its parent. + ac_prog=$0 + ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'` + test "x$ac_confdir" = "x$ac_prog" && ac_confdir=. + srcdir=$ac_confdir + if test ! -r $srcdir/$ac_unique_file; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r $srcdir/$ac_unique_file; then + if test "$ac_srcdir_defaulted" = yes; then + { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; } + else + { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; } + fi +fi +srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'` + +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + echo "loading site script $ac_site_file" + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + echo "loading cache $cache_file" + . $cache_file +else + echo "creating cache $cache_file" + > $cache_file +fi + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +ac_exeext= +ac_objext=o +if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then + # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. + if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then + ac_n= ac_c=' +' ac_t=' ' + else + ac_n=-n ac_c= ac_t= + fi +else + ac_n= ac_c='\c' ac_t= +fi + + + +ac_cv_prog_cc_g=no +ac_cv_prog_cxx_g=no + +# Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:537: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="gcc" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:567: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_prog_rejected=no + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + break + fi + done + IFS="$ac_save_ifs" +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# -gt 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + set dummy "$ac_dir/$ac_word" "$@" + shift + ac_cv_prog_CC="$@" + fi +fi +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + if test -z "$CC"; then + case "`uname -s`" in + *win32* | *WIN32*) + # Extract the first word of "cl", so it can be a program name with args. +set dummy cl; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:618: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="cl" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + ;; + esac + fi + test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; } +fi + +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 +echo "configure:650: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +cat > conftest.$ac_ext << EOF + +#line 661 "configure" +#include "confdefs.h" + +main(){return(0);} +EOF +if { (eval echo configure:666: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + ac_cv_prog_cc_works=yes + # If we can't run a trivial program, we are probably using a cross compiler. + if (./conftest; exit) 2>/dev/null; then + ac_cv_prog_cc_cross=no + else + ac_cv_prog_cc_cross=yes + fi +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + ac_cv_prog_cc_works=no +fi +rm -fr conftest* +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +echo "$ac_t""$ac_cv_prog_cc_works" 1>&6 +if test $ac_cv_prog_cc_works = no; then + { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } +fi +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 +echo "configure:692: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 +cross_compiling=$ac_cv_prog_cc_cross + +echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 +echo "configure:697: checking whether we are using GNU C" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.c <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then + ac_cv_prog_gcc=yes +else + ac_cv_prog_gcc=no +fi +fi + +echo "$ac_t""$ac_cv_prog_gcc" 1>&6 + +if test $ac_cv_prog_gcc = yes; then + GCC=yes +else + GCC= +fi + +ac_test_CFLAGS="${CFLAGS+set}" +ac_save_CFLAGS="$CFLAGS" +CFLAGS= +echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 +echo "configure:725: checking whether ${CC-cc} accepts -g" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + echo 'void f(){}' > conftest.c +if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then + ac_cv_prog_cc_g=yes +else + ac_cv_prog_cc_g=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_prog_cc_g" 1>&6 +if test "$ac_test_CFLAGS" = set; then + CFLAGS="$ac_save_CFLAGS" +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi + +for ac_prog in $CCC c++ g++ gcc CC cxx cc++ cl +do +# Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:761: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CXX'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CXX"; then + ac_cv_prog_CXX="$CXX" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CXX="$ac_prog" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CXX="$ac_cv_prog_CXX" +if test -n "$CXX"; then + echo "$ac_t""$CXX" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +test -n "$CXX" && break +done +test -n "$CXX" || CXX="gcc" + + +echo $ac_n "checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works""... $ac_c" 1>&6 +echo "configure:793: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works" >&5 + +ac_ext=C +# CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cxx_cross + +cat > conftest.$ac_ext << EOF + +#line 804 "configure" +#include "confdefs.h" + +int main(){return(0);} +EOF +if { (eval echo configure:809: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + ac_cv_prog_cxx_works=yes + # If we can't run a trivial program, we are probably using a cross compiler. + if (./conftest; exit) 2>/dev/null; then + ac_cv_prog_cxx_cross=no + else + ac_cv_prog_cxx_cross=yes + fi +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + ac_cv_prog_cxx_works=no +fi +rm -fr conftest* +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +echo "$ac_t""$ac_cv_prog_cxx_works" 1>&6 +if test $ac_cv_prog_cxx_works = no; then + { echo "configure: error: installation or configuration problem: C++ compiler cannot create executables." 1>&2; exit 1; } +fi +echo $ac_n "checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 +echo "configure:835: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "$ac_t""$ac_cv_prog_cxx_cross" 1>&6 +cross_compiling=$ac_cv_prog_cxx_cross + +echo $ac_n "checking whether we are using GNU C++""... $ac_c" 1>&6 +echo "configure:840: checking whether we are using GNU C++" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_gxx'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.C <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then + ac_cv_prog_gxx=yes +else + ac_cv_prog_gxx=no +fi +fi + +echo "$ac_t""$ac_cv_prog_gxx" 1>&6 + +if test $ac_cv_prog_gxx = yes; then + GXX=yes +else + GXX= +fi + +ac_test_CXXFLAGS="${CXXFLAGS+set}" +ac_save_CXXFLAGS="$CXXFLAGS" +CXXFLAGS= +echo $ac_n "checking whether ${CXX-g++} accepts -g""... $ac_c" 1>&6 +echo "configure:868: checking whether ${CXX-g++} accepts -g" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_cxx_g'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + echo 'void f(){}' > conftest.cc +if test -z "`${CXX-g++} -g -c conftest.cc 2>&1`"; then + ac_cv_prog_cxx_g=yes +else + ac_cv_prog_cxx_g=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_prog_cxx_g" 1>&6 +if test "$ac_test_CXXFLAGS" = set; then + CXXFLAGS="$ac_save_CXXFLAGS" +elif test $ac_cv_prog_cxx_g = yes; then + if test "$GXX" = yes; then + CXXFLAGS="-g -O2" + else + CXXFLAGS="-g" + fi +else + if test "$GXX" = yes; then + CXXFLAGS="-O2" + else + CXXFLAGS= + fi +fi + +# Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:902: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_RANLIB="ranlib" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":" +fi +fi +RANLIB="$ac_cv_prog_RANLIB" +if test -n "$RANLIB"; then + echo "$ac_t""$RANLIB" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6 +echo "configure:930: checking whether ${MAKE-make} sets \${MAKE}" >&5 +set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftestmake <<\EOF +all: + @echo 'ac_maketemp="${MAKE}"' +EOF +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=` +if test -n "$ac_maketemp"; then + eval ac_cv_prog_make_${ac_make}_set=yes +else + eval ac_cv_prog_make_${ac_make}_set=no +fi +rm -f conftestmake +fi +if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then + echo "$ac_t""yes" 1>&6 + SET_MAKE= +else + echo "$ac_t""no" 1>&6 + SET_MAKE="MAKE=${MAKE-make}" +fi + +ac_ext=C +# CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cxx_cross + + +case "`(uname -sr) 2>/dev/null`" in +"SunOS 5"*) + SOLARIS=yes + USE_MITSHM=yes + ;; +"Linux"*) + LINUX=yes + USE_MITSHM=yes + ;; +esac + +if test "$USE_MITSHM" = yes; then + MITSHM_CPPFLAGS="-DMITSHM" +fi + + +if test "$GCC" = yes; then + CFLAGS="$CFLAGS -Wall" + if test "$SOLARIS" = yes; then + CFLAGS="$CFLAGS -Wno-unknown-pragmas -Wno-implicit-int" + fi +fi +if test "$GXX" = yes; then + CXXFLAGS="$CXXFLAGS -Wall" + if test "$SOLARIS" = yes; then + CXXFLAGS="$CXXFLAGS -Wno-unknown-pragmas -Wno-implicit-int -fpermissive" + fi +fi + +echo $ac_n "checking how to run the C++ preprocessor""... $ac_c" 1>&6 +echo "configure:994: checking how to run the C++ preprocessor" >&5 +if test -z "$CXXCPP"; then +if eval "test \"`echo '$''{'ac_cv_prog_CXXCPP'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_ext=C +# CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cxx_cross + CXXCPP="${CXX-g++} -E" + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1012: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CXXCPP=/lib/cpp +fi +rm -f conftest* + ac_cv_prog_CXXCPP="$CXXCPP" +ac_ext=C +# CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cxx_cross +fi +fi +CXXCPP="$ac_cv_prog_CXXCPP" +echo "$ac_t""$CXXCPP" 1>&6 + +# If we find X, set shell vars x_includes and x_libraries to the +# paths, otherwise set no_x=yes. +# Uses ac_ vars as temps to allow command line to override cache and checks. +# --without-x overrides everything else, but does not touch the cache. +echo $ac_n "checking for X""... $ac_c" 1>&6 +echo "configure:1041: checking for X" >&5 + +# Check whether --with-x or --without-x was given. +if test "${with_x+set}" = set; then + withval="$with_x" + : +fi + +# $have_x is `yes', `no', `disabled', or empty when we do not yet know. +if test "x$with_x" = xno; then + # The user explicitly disabled X. + have_x=disabled +else + if test "x$x_includes" != xNONE && test "x$x_libraries" != xNONE; then + # Both variables are already set. + have_x=yes + else +if eval "test \"`echo '$''{'ac_cv_have_x'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + # One or both of the vars are not set, and there is no cached value. +ac_x_includes=NO ac_x_libraries=NO +rm -fr conftestdir +if mkdir conftestdir; then + cd conftestdir + # Make sure to not put "make" in the Imakefile rules, since we grep it out. + cat > Imakefile <<'EOF' +acfindx: + @echo 'ac_im_incroot="${INCROOT}"; ac_im_usrlibdir="${USRLIBDIR}"; ac_im_libdir="${LIBDIR}"' +EOF + if (xmkmf) >/dev/null 2>/dev/null && test -f Makefile; then + # GNU make sometimes prints "make[1]: Entering...", which would confuse us. + eval `${MAKE-make} acfindx 2>/dev/null | grep -v make` + # Open Windows xmkmf reportedly sets LIBDIR instead of USRLIBDIR. + for ac_extension in a so sl; do + if test ! -f $ac_im_usrlibdir/libX11.$ac_extension && + test -f $ac_im_libdir/libX11.$ac_extension; then + ac_im_usrlibdir=$ac_im_libdir; break + fi + done + # Screen out bogus values from the imake configuration. They are + # bogus both because they are the default anyway, and because + # using them would break gcc on systems where it needs fixed includes. + case "$ac_im_incroot" in + /usr/include) ;; + *) test -f "$ac_im_incroot/X11/Xos.h" && ac_x_includes="$ac_im_incroot" ;; + esac + case "$ac_im_usrlibdir" in + /usr/lib | /lib) ;; + *) test -d "$ac_im_usrlibdir" && ac_x_libraries="$ac_im_usrlibdir" ;; + esac + fi + cd .. + rm -fr conftestdir +fi + +if test "$ac_x_includes" = NO; then + # Guess where to find include files, by looking for this one X11 .h file. + test -z "$x_direct_test_include" && x_direct_test_include=X11/Intrinsic.h + + # First, try using that file with no special directory specified. +cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1108: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + # We can compile using X headers with no special include directory. +ac_x_includes= +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + # Look for the header file in a standard set of common directories. +# Check X11 before X11Rn because it is often a symlink to the current release. + for ac_dir in \ + /usr/X11/include \ + /usr/X11R6/include \ + /usr/X11R5/include \ + /usr/X11R4/include \ + \ + /usr/include/X11 \ + /usr/include/X11R6 \ + /usr/include/X11R5 \ + /usr/include/X11R4 \ + \ + /usr/local/X11/include \ + /usr/local/X11R6/include \ + /usr/local/X11R5/include \ + /usr/local/X11R4/include \ + \ + /usr/local/include/X11 \ + /usr/local/include/X11R6 \ + /usr/local/include/X11R5 \ + /usr/local/include/X11R4 \ + \ + /usr/X386/include \ + /usr/x386/include \ + /usr/XFree86/include/X11 \ + \ + /usr/include \ + /usr/local/include \ + /usr/unsupported/include \ + /usr/athena/include \ + /usr/local/x11r5/include \ + /usr/lpp/Xamples/include \ + \ + /usr/openwin/include \ + /usr/openwin/share/include \ + ; \ + do + if test -r "$ac_dir/$x_direct_test_include"; then + ac_x_includes=$ac_dir + break + fi + done +fi +rm -f conftest* +fi # $ac_x_includes = NO + +if test "$ac_x_libraries" = NO; then + # Check for the libraries. + + test -z "$x_direct_test_library" && x_direct_test_library=Xt + test -z "$x_direct_test_function" && x_direct_test_function=XtMalloc + + # See if we find them without any special options. + # Don't add to $LIBS permanently. + ac_save_LIBS="$LIBS" + LIBS="-l$x_direct_test_library $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + LIBS="$ac_save_LIBS" +# We can link X programs with no special library path. +ac_x_libraries= +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + LIBS="$ac_save_LIBS" +# First see if replacing the include by lib works. +# Check X11 before X11Rn because it is often a symlink to the current release. +for ac_dir in `echo "$ac_x_includes" | sed s/include/lib/` \ + /usr/X11/lib \ + /usr/X11R6/lib \ + /usr/X11R5/lib \ + /usr/X11R4/lib \ + \ + /usr/lib/X11 \ + /usr/lib/X11R6 \ + /usr/lib/X11R5 \ + /usr/lib/X11R4 \ + \ + /usr/local/X11/lib \ + /usr/local/X11R6/lib \ + /usr/local/X11R5/lib \ + /usr/local/X11R4/lib \ + \ + /usr/local/lib/X11 \ + /usr/local/lib/X11R6 \ + /usr/local/lib/X11R5 \ + /usr/local/lib/X11R4 \ + \ + /usr/X386/lib \ + /usr/x386/lib \ + /usr/XFree86/lib/X11 \ + \ + /usr/lib \ + /usr/local/lib \ + /usr/unsupported/lib \ + /usr/athena/lib \ + /usr/local/x11r5/lib \ + /usr/lpp/Xamples/lib \ + /lib/usr/lib/X11 \ + \ + /usr/openwin/lib \ + /usr/openwin/share/lib \ + ; \ +do + for ac_extension in a so sl; do + if test -r $ac_dir/lib${x_direct_test_library}.$ac_extension; then + ac_x_libraries=$ac_dir + break 2 + fi + done +done +fi +rm -f conftest* +fi # $ac_x_libraries = NO + +if test "$ac_x_includes" = NO || test "$ac_x_libraries" = NO; then + # Didn't find X anywhere. Cache the known absence of X. + ac_cv_have_x="have_x=no" +else + # Record where we found X for the cache. + ac_cv_have_x="have_x=yes \ + ac_x_includes=$ac_x_includes ac_x_libraries=$ac_x_libraries" +fi +fi + fi + eval "$ac_cv_have_x" +fi # $with_x != no + +if test "$have_x" != yes; then + echo "$ac_t""$have_x" 1>&6 + no_x=yes +else + # If each of the values was on the command line, it overrides each guess. + test "x$x_includes" = xNONE && x_includes=$ac_x_includes + test "x$x_libraries" = xNONE && x_libraries=$ac_x_libraries + # Update the cache value to reflect the command line values. + ac_cv_have_x="have_x=yes \ + ac_x_includes=$x_includes ac_x_libraries=$x_libraries" + echo "$ac_t""libraries $x_libraries, headers $x_includes" 1>&6 +fi + +if test "$no_x" = yes; then + # Not all programs may use this symbol, but it does not hurt to define it. + cat >> confdefs.h <<\EOF +#define X_DISPLAY_MISSING 1 +EOF + + X_CFLAGS= X_PRE_LIBS= X_LIBS= X_EXTRA_LIBS= +else + if test -n "$x_includes"; then + X_CFLAGS="$X_CFLAGS -I$x_includes" + fi + + # It would also be nice to do this for all -L options, not just this one. + if test -n "$x_libraries"; then + X_LIBS="$X_LIBS -L$x_libraries" + # For Solaris; some versions of Sun CC require a space after -R and + # others require no space. Words are not sufficient . . . . + case "`(uname -sr) 2>/dev/null`" in + "SunOS 5"*) + echo $ac_n "checking whether -R must be followed by a space""... $ac_c" 1>&6 +echo "configure:1290: checking whether -R must be followed by a space" >&5 + ac_xsave_LIBS="$LIBS"; LIBS="$LIBS -R$x_libraries" + cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + ac_R_nospace=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_R_nospace=no +fi +rm -f conftest* + if test $ac_R_nospace = yes; then + echo "$ac_t""no" 1>&6 + X_LIBS="$X_LIBS -R$x_libraries" + else + LIBS="$ac_xsave_LIBS -R $x_libraries" + cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + ac_R_space=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_R_space=no +fi +rm -f conftest* + if test $ac_R_space = yes; then + echo "$ac_t""yes" 1>&6 + X_LIBS="$X_LIBS -R $x_libraries" + else + echo "$ac_t""neither works" 1>&6 + fi + fi + LIBS="$ac_xsave_LIBS" + esac + fi + + # Check for system-dependent libraries X programs must link with. + # Do this before checking for the system-independent R6 libraries + # (-lICE), since we may need -lsocket or whatever for X linking. + + if test "$ISC" = yes; then + X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl_s -linet" + else + # Martyn.Johnson@cl.cam.ac.uk says this is needed for Ultrix, if the X + # libraries were built with DECnet support. And karl@cs.umb.edu says + # the Alpha needs dnet_stub (dnet does not exist). + echo $ac_n "checking for dnet_ntoa in -ldnet""... $ac_c" 1>&6 +echo "configure:1355: checking for dnet_ntoa in -ldnet" >&5 +ac_lib_var=`echo dnet'_'dnet_ntoa | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-ldnet $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet" +else + echo "$ac_t""no" 1>&6 +fi + + if test $ac_cv_lib_dnet_dnet_ntoa = no; then + echo $ac_n "checking for dnet_ntoa in -ldnet_stub""... $ac_c" 1>&6 +echo "configure:1399: checking for dnet_ntoa in -ldnet_stub" >&5 +ac_lib_var=`echo dnet_stub'_'dnet_ntoa | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-ldnet_stub $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet_stub" +else + echo "$ac_t""no" 1>&6 +fi + + fi + + # msh@cis.ufl.edu says -lnsl (and -lsocket) are needed for his 386/AT, + # to get the SysV transport functions. + # chad@anasazi.com says the Pyramis MIS-ES running DC/OSx (SVR4) + # needs -lnsl. + # The nsl library prevents programs from opening the X display + # on Irix 5.2, according to dickey@clark.net. + echo $ac_n "checking for gethostbyname""... $ac_c" 1>&6 +echo "configure:1450: checking for gethostbyname" >&5 +if eval "test \"`echo '$''{'ac_cv_func_gethostbyname'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char gethostbyname(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_gethostbyname) || defined (__stub___gethostbyname) +choke me +#else +gethostbyname(); +#endif + +; return 0; } +EOF +if { (eval echo configure:1481: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_gethostbyname=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_gethostbyname=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'gethostbyname`\" = yes"; then + echo "$ac_t""yes" 1>&6 + : +else + echo "$ac_t""no" 1>&6 +fi + + if test $ac_cv_func_gethostbyname = no; then + echo $ac_n "checking for gethostbyname in -lnsl""... $ac_c" 1>&6 +echo "configure:1502: checking for gethostbyname in -lnsl" >&5 +ac_lib_var=`echo nsl'_'gethostbyname | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lnsl $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl" +else + echo "$ac_t""no" 1>&6 +fi + + fi + + # lieder@skyler.mavd.honeywell.com says without -lsocket, + # socket/setsockopt and other routines are undefined under SCO ODT + # 2.0. But -lsocket is broken on IRIX 5.2 (and is not necessary + # on later versions), says simon@lia.di.epfl.ch: it contains + # gethostby* variants that don't use the nameserver (or something). + # -lsocket must be given before -lnsl if both are needed. + # We assume that if connect needs -lnsl, so does gethostbyname. + echo $ac_n "checking for connect""... $ac_c" 1>&6 +echo "configure:1554: checking for connect" >&5 +if eval "test \"`echo '$''{'ac_cv_func_connect'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char connect(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_connect) || defined (__stub___connect) +choke me +#else +connect(); +#endif + +; return 0; } +EOF +if { (eval echo configure:1585: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_connect=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_connect=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'connect`\" = yes"; then + echo "$ac_t""yes" 1>&6 + : +else + echo "$ac_t""no" 1>&6 +fi + + if test $ac_cv_func_connect = no; then + echo $ac_n "checking for connect in -lsocket""... $ac_c" 1>&6 +echo "configure:1606: checking for connect in -lsocket" >&5 +ac_lib_var=`echo socket'_'connect | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lsocket $X_EXTRA_LIBS $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + X_EXTRA_LIBS="-lsocket $X_EXTRA_LIBS" +else + echo "$ac_t""no" 1>&6 +fi + + fi + + # gomez@mi.uni-erlangen.de says -lposix is necessary on A/UX. + echo $ac_n "checking for remove""... $ac_c" 1>&6 +echo "configure:1652: checking for remove" >&5 +if eval "test \"`echo '$''{'ac_cv_func_remove'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char remove(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_remove) || defined (__stub___remove) +choke me +#else +remove(); +#endif + +; return 0; } +EOF +if { (eval echo configure:1683: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_remove=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_remove=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'remove`\" = yes"; then + echo "$ac_t""yes" 1>&6 + : +else + echo "$ac_t""no" 1>&6 +fi + + if test $ac_cv_func_remove = no; then + echo $ac_n "checking for remove in -lposix""... $ac_c" 1>&6 +echo "configure:1704: checking for remove in -lposix" >&5 +ac_lib_var=`echo posix'_'remove | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lposix $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + X_EXTRA_LIBS="$X_EXTRA_LIBS -lposix" +else + echo "$ac_t""no" 1>&6 +fi + + fi + + # BSDI BSD/OS 2.1 needs -lipc for XOpenDisplay. + echo $ac_n "checking for shmat""... $ac_c" 1>&6 +echo "configure:1750: checking for shmat" >&5 +if eval "test \"`echo '$''{'ac_cv_func_shmat'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char shmat(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_shmat) || defined (__stub___shmat) +choke me +#else +shmat(); +#endif + +; return 0; } +EOF +if { (eval echo configure:1781: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_shmat=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_shmat=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'shmat`\" = yes"; then + echo "$ac_t""yes" 1>&6 + : +else + echo "$ac_t""no" 1>&6 +fi + + if test $ac_cv_func_shmat = no; then + echo $ac_n "checking for shmat in -lipc""... $ac_c" 1>&6 +echo "configure:1802: checking for shmat in -lipc" >&5 +ac_lib_var=`echo ipc'_'shmat | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lipc $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + X_EXTRA_LIBS="$X_EXTRA_LIBS -lipc" +else + echo "$ac_t""no" 1>&6 +fi + + fi + fi + + # Check for libraries that X11R6 Xt/Xaw programs need. + ac_save_LDFLAGS="$LDFLAGS" + test -n "$x_libraries" && LDFLAGS="$LDFLAGS -L$x_libraries" + # SM needs ICE to (dynamically) link under SunOS 4.x (so we have to + # check for ICE first), but we must link in the order -lSM -lICE or + # we get undefined symbols. So assume we have SM if we have ICE. + # These have to be linked with before -lX11, unlike the other + # libraries we check for below, so use a different variable. + # --interran@uluru.Stanford.EDU, kb@cs.umb.edu. + echo $ac_n "checking for IceConnectionNumber in -lICE""... $ac_c" 1>&6 +echo "configure:1857: checking for IceConnectionNumber in -lICE" >&5 +ac_lib_var=`echo ICE'_'IceConnectionNumber | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lICE $X_EXTRA_LIBS $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + X_PRE_LIBS="$X_PRE_LIBS -lSM -lICE" +else + echo "$ac_t""no" 1>&6 +fi + + LDFLAGS="$ac_save_LDFLAGS" + +fi + + +# Check whether --with-installed-zlib or --without-installed-zlib was given. +if test "${with_installed_zlib+set}" = set; then + withval="$with_installed_zlib" + : +fi + + +if test "$with_installed_zlib" = yes; then + echo "using installed zlib" + ZLIB_LIB=-lz +else + ZLIB_DIR=zlib + ZLIB_INCLUDE='-I$(top_srcdir)/zlib' + ZLIB_LIB='$(top_srcdir)/zlib/libz.a' + echo "configuring zlib..." + (cd zlib; ./configure) + echo "...done configuring zlib" +fi + + + + + +echo $ac_n "checking for vsnprintf""... $ac_c" 1>&6 +echo "configure:1928: checking for vsnprintf" >&5 +if eval "test \"`echo '$''{'ac_cv_func_vsnprintf'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char vsnprintf(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_vsnprintf) || defined (__stub___vsnprintf) +choke me +#else +vsnprintf(); +#endif + +; return 0; } +EOF +if { (eval echo configure:1959: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_vsnprintf=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_vsnprintf=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'vsnprintf`\" = yes"; then + echo "$ac_t""yes" 1>&6 + VSNPRINTF_DEFINE='-DHAVE_VSNPRINTF' +else + echo "$ac_t""no" 1>&6 +VSNPRINTF_DEFINE= +fi + + + +echo $ac_n "checking for socklen_t""... $ac_c" 1>&6 +echo "configure:1982: checking for socklen_t" >&5 +cat > conftest.$ac_ext < + #include +int main() { +socklen_t x; +accept(0, 0, &x); +; return 0; } +EOF +if { (eval echo configure:1993: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + echo "$ac_t""yes" 1>&6 +SOCKLEN_T_DEFINE='-DVNC_SOCKLEN_T=socklen_t' +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + echo "$ac_t""using int" 1>&6 +SOCKLEN_T_DEFINE='-DVNC_SOCKLEN_T=int' +fi +rm -f conftest* + + +BOILERPLATE=boilerplate.mk + +if (sh -c "make --version" 2>/dev/null | grep GNU 2>&1 >/dev/null); then + if sh -c "vncmkdepend" >/dev/null 2>&1; then + BOILERPLATE="$BOILERPLATE:depend.mk" + fi +fi + +trap '' 1 2 15 +cat > confcache <<\EOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs. It is not useful on other systems. +# If it contains results you don't want to keep, you may remove or edit it. +# +# By default, configure uses ./config.cache as the cache file, +# creating it if it does not exist already. You can give configure +# the --cache-file=FILE option to use a different cache file; that is +# what configure does when it calls configure scripts in +# subdirectories, so they share the cache. +# Giving --cache-file=/dev/null disables caching, for debugging configure. +# config.status only pays attention to the cache file if you give it the +# --recheck option to rerun configure. +# +EOF +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +(set) 2>&1 | + case `(ac_space=' '; set | grep ac_space) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote substitution + # turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + -e "s/'/'\\\\''/g" \ + -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' + ;; + esac >> confcache +if cmp -s $cache_file confcache; then + : +else + if test -w $cache_file; then + echo "updating cache $cache_file" + cat confcache > $cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# Any assignment to VPATH causes Sun make to only execute +# the first set of double-colon rules, so remove it if not needed. +# If there is a colon in the path, we need to keep it. +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d' +fi + +trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15 + +# Transform confdefs.h into DEFS. +# Protect against shell expansion while executing Makefile rules. +# Protect against Makefile macro expansion. +cat > conftest.defs <<\EOF +s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%-D\1=\2%g +s%[ `~#$^&*(){}\\|;'"<>?]%\\&%g +s%\[%\\&%g +s%\]%\\&%g +s%\$%$$%g +EOF +DEFS=`sed -f conftest.defs confdefs.h | tr '\012' ' '` +rm -f conftest.defs + + +# Without the "./", some shells look in PATH for config.status. +: ${CONFIG_STATUS=./config.status} + +echo creating $CONFIG_STATUS +rm -f $CONFIG_STATUS +cat > $CONFIG_STATUS </dev/null | sed 1q`: +# +# $0 $ac_configure_args +# +# Compiler output produced by configure, useful for debugging +# configure, is in ./config.log if it exists. + +ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]" +for ac_option +do + case "\$ac_option" in + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion" + exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;; + -version | --version | --versio | --versi | --vers | --ver | --ve | --v) + echo "$CONFIG_STATUS generated by autoconf version 2.13" + exit 0 ;; + -help | --help | --hel | --he | --h) + echo "\$ac_cs_usage"; exit 0 ;; + *) echo "\$ac_cs_usage"; exit 1 ;; + esac +done + +ac_given_srcdir=$srcdir + +trap 'rm -fr `echo "Makefile:Makefile.in:$BOILERPLATE \ + rdr/Makefile:rdr/Makefile.in:$BOILERPLATE \ + network/Makefile:network/Makefile.in:$BOILERPLATE \ + Xregion/Makefile:Xregion/Makefile.in:$BOILERPLATE \ + rfb/Makefile:rfb/Makefile.in:$BOILERPLATE \ + tx/Makefile:tx/Makefile.in:$BOILERPLATE \ + x0vncserver/Makefile:x0vncserver/Makefile.in:$BOILERPLATE \ + vncviewer/Makefile:vncviewer/Makefile.in:$BOILERPLATE \ + vncconfig/Makefile:vncconfig/Makefile.in:$BOILERPLATE \ + vncpasswd/Makefile:vncpasswd/Makefile.in:$BOILERPLATE \ +" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 +EOF +cat >> $CONFIG_STATUS < conftest.subs <<\\CEOF +$ac_vpsub +$extrasub +s%@SHELL@%$SHELL%g +s%@CFLAGS@%$CFLAGS%g +s%@CPPFLAGS@%$CPPFLAGS%g +s%@CXXFLAGS@%$CXXFLAGS%g +s%@FFLAGS@%$FFLAGS%g +s%@DEFS@%$DEFS%g +s%@LDFLAGS@%$LDFLAGS%g +s%@LIBS@%$LIBS%g +s%@exec_prefix@%$exec_prefix%g +s%@prefix@%$prefix%g +s%@program_transform_name@%$program_transform_name%g +s%@bindir@%$bindir%g +s%@sbindir@%$sbindir%g +s%@libexecdir@%$libexecdir%g +s%@datadir@%$datadir%g +s%@sysconfdir@%$sysconfdir%g +s%@sharedstatedir@%$sharedstatedir%g +s%@localstatedir@%$localstatedir%g +s%@libdir@%$libdir%g +s%@includedir@%$includedir%g +s%@oldincludedir@%$oldincludedir%g +s%@infodir@%$infodir%g +s%@mandir@%$mandir%g +s%@CC@%$CC%g +s%@CXX@%$CXX%g +s%@RANLIB@%$RANLIB%g +s%@SET_MAKE@%$SET_MAKE%g +s%@MITSHM_CPPFLAGS@%$MITSHM_CPPFLAGS%g +s%@CXXCPP@%$CXXCPP%g +s%@X_CFLAGS@%$X_CFLAGS%g +s%@X_PRE_LIBS@%$X_PRE_LIBS%g +s%@X_LIBS@%$X_LIBS%g +s%@X_EXTRA_LIBS@%$X_EXTRA_LIBS%g +s%@ZLIB_DIR@%$ZLIB_DIR%g +s%@ZLIB_INCLUDE@%$ZLIB_INCLUDE%g +s%@ZLIB_LIB@%$ZLIB_LIB%g +s%@VSNPRINTF_DEFINE@%$VSNPRINTF_DEFINE%g +s%@SOCKLEN_T_DEFINE@%$SOCKLEN_T_DEFINE%g + +CEOF +EOF + +cat >> $CONFIG_STATUS <<\EOF + +# Split the substitutions into bite-sized pieces for seds with +# small command number limits, like on Digital OSF/1 and HP-UX. +ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script. +ac_file=1 # Number of current file. +ac_beg=1 # First line for current file. +ac_end=$ac_max_sed_cmds # Line after last line for current file. +ac_more_lines=: +ac_sed_cmds="" +while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file + else + sed "${ac_end}q" conftest.subs > conftest.s$ac_file + fi + if test ! -s conftest.s$ac_file; then + ac_more_lines=false + rm -f conftest.s$ac_file + else + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f conftest.s$ac_file" + else + ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file" + fi + ac_file=`expr $ac_file + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_cmds` + fi +done +if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat +fi +EOF + +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories. + + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`" + # A "../" for each directory in $ac_dir_suffix. + ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'` + else + ac_dir_suffix= ac_dots= + fi + + case "$ac_given_srcdir" in + .) srcdir=. + if test -z "$ac_dots"; then top_srcdir=. + else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;; + /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;; + *) # Relative path. + srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix" + top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + + + echo creating "$ac_file" + rm -f "$ac_file" + configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure." + case "$ac_file" in + *Makefile*) ac_comsub="1i\\ +# $configure_input" ;; + *) ac_comsub= ;; + esac + + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + sed -e "$ac_comsub +s%@configure_input@%$configure_input%g +s%@srcdir@%$srcdir%g +s%@top_srcdir@%$top_srcdir%g +" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file +fi; done +rm -f conftest.s* + +EOF +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF + +exit 0 +EOF +chmod +x $CONFIG_STATUS +rm -fr confdefs* $ac_clean_files +test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1 + diff --git a/configure.in b/configure.in new file mode 100644 index 00000000..bb49f83b --- /dev/null +++ b/configure.in @@ -0,0 +1,99 @@ +dnl Process this file with autoconf to produce a configure script. +AC_INIT(rdr/InStream.h) + +dnl dirty hack to prevent use of -g in CFLAGS and CXXFLAGS +ac_cv_prog_cc_g=no +ac_cv_prog_cxx_g=no + +dnl Checks for programs. +AC_PROG_CC +AC_PROG_CXX +AC_PROG_RANLIB +AC_PROG_MAKE_SET +AC_LANG_CPLUSPLUS + +case "`(uname -sr) 2>/dev/null`" in +"SunOS 5"*) + SOLARIS=yes + USE_MITSHM=yes + ;; +"Linux"*) + LINUX=yes + USE_MITSHM=yes + ;; +esac + +if test "$USE_MITSHM" = yes; then + MITSHM_CPPFLAGS="-DMITSHM" +fi +AC_SUBST(MITSHM_CPPFLAGS) + +if test "$GCC" = yes; then + CFLAGS="$CFLAGS -Wall" + if test "$SOLARIS" = yes; then + CFLAGS="$CFLAGS -Wno-unknown-pragmas -Wno-implicit-int" + fi +fi +if test "$GXX" = yes; then + CXXFLAGS="$CXXFLAGS -Wall" + if test "$SOLARIS" = yes; then + CXXFLAGS="$CXXFLAGS -Wno-unknown-pragmas -Wno-implicit-int -fpermissive" + fi +fi + +AC_PATH_XTRA + +AC_ARG_WITH(installed-zlib, +[ --with-installed-zlib use the version of zlib which is installed on the + system instead of the one distributed with VNC]) + +if test "$with_installed_zlib" = yes; then + echo "using installed zlib" + ZLIB_LIB=-lz +else + ZLIB_DIR=zlib + ZLIB_INCLUDE='-I$(top_srcdir)/zlib' + ZLIB_LIB='$(top_srcdir)/zlib/libz.a' + echo "configuring zlib..." + (cd zlib; ./configure) + echo "...done configuring zlib" +fi + +AC_SUBST(ZLIB_DIR) +AC_SUBST(ZLIB_INCLUDE) +AC_SUBST(ZLIB_LIB) + +AC_CHECK_FUNC(vsnprintf,VSNPRINTF_DEFINE='-DHAVE_VSNPRINTF',VSNPRINTF_DEFINE=) +AC_SUBST(VSNPRINTF_DEFINE) + +AC_MSG_CHECKING(for socklen_t) +AC_TRY_COMPILE( +[#include + #include ], +[socklen_t x; +accept(0, 0, &x);], +AC_MSG_RESULT(yes) +SOCKLEN_T_DEFINE='-DVNC_SOCKLEN_T=socklen_t', +AC_MSG_RESULT(using int) +SOCKLEN_T_DEFINE='-DVNC_SOCKLEN_T=int') +AC_SUBST(SOCKLEN_T_DEFINE) + +BOILERPLATE=boilerplate.mk + +if (sh -c "make --version" 2>/dev/null | grep GNU 2>&1 >/dev/null); then + if sh -c "vncmkdepend" >/dev/null 2>&1; then + BOILERPLATE="$BOILERPLATE:depend.mk" + fi +fi + +AC_OUTPUT(Makefile:Makefile.in:$BOILERPLATE \ + rdr/Makefile:rdr/Makefile.in:$BOILERPLATE \ + network/Makefile:network/Makefile.in:$BOILERPLATE \ + Xregion/Makefile:Xregion/Makefile.in:$BOILERPLATE \ + rfb/Makefile:rfb/Makefile.in:$BOILERPLATE \ + tx/Makefile:tx/Makefile.in:$BOILERPLATE \ + x0vncserver/Makefile:x0vncserver/Makefile.in:$BOILERPLATE \ + vncviewer/Makefile:vncviewer/Makefile.in:$BOILERPLATE \ + vncconfig/Makefile:vncconfig/Makefile.in:$BOILERPLATE \ + vncpasswd/Makefile:vncpasswd/Makefile.in:$BOILERPLATE \ +) diff --git a/depend.mk b/depend.mk new file mode 100644 index 00000000..51d4cd63 --- /dev/null +++ b/depend.mk @@ -0,0 +1,76 @@ +# +# C / C++ header dependency stuff +# +# Needs GNU make and vncmkdepend, a hacked version of makedepend + +.SUFFIXES: .d + +CMAKEDEPEND = vncmkdepend +CXXMAKEDEPEND = vncmkdepend + +# +# The recommended method of doing dependency analysis in the GNU make manual +# turns out to be painfully slow. This method is similar but it's +# substantially faster and retains the desirable property that the user doesn't +# need to manually invoke a "make depend" step. +# +# As with the method described in the manual, we generate a separate dependency +# (.d) file for each source file. The .d file records the header files that +# each C or C++ source file includes. Any source file recorded in SRCS or +# CXXSRCS will cause us to try and include the corresponding .d file and GNU +# make then treats each .d file as a target to be remade. +# +# Unlike the manual's method, the rule we provide for making the .d file is +# actually a fake. All it does is record in a temporary file that the .d file +# needs to be remade. But as well as all the .d files, we also try to include +# a file called "depend.phony". This file never exists, but it causes GNU make +# to try and make the target "depend.phony". The rule for depend.phony then +# looks at the temporary files generated by the .d rules and then invokes the +# "omkdepend" program on all of the source files in one go. +# + +# +# We use simple assignment here to remove any of the depend.tmp files +# at the time make parses this bit. +# + +dummyvariable := $(shell $(RM) cdepend.tmp cxxdepend.tmp) + +# +# Now the "fake" rules for generating .d files. +# + +%.d: %.c + @echo "$<" >> cdepend.tmp + +%.d: %.cxx + @echo "$<" >> cxxdepend.tmp + +# +# The depend.phony rule which actually runs omkdepend. +# + +depend.phony: + @if [ -f cdepend.tmp ]; then \ + echo $(CMAKEDEPEND) $(ALL_CPPFLAGS) `cat cdepend.tmp`; \ + $(CMAKEDEPEND) $(ALL_CPPFLAGS) `cat cdepend.tmp`; \ + rm -f cdepend.tmp; \ + fi; \ + if [ -f cxxdepend.tmp ]; then \ + echo $(CXXMAKEDEPEND) $(ALL_CPPFLAGS) `cat cxxdepend.tmp`; \ + $(CXXMAKEDEPEND) $(ALL_CPPFLAGS) `cat cxxdepend.tmp`; \ + rm -f cxxdepend.tmp; \ + fi + +# +# Now include the .d files and the "depend.phony" file which never exists. +# For some reason GNU make evaluates the targets in reverse order, so we need +# to include depend.phony first. The "-" tells make not to complain that it +# can't find the file. +# + +-include depend.phony + +ifdef SRCS +-include $(patsubst %.c,%.d,$(patsubst %.cxx,%.d,$(SRCS))) +endif diff --git a/hpux.patch b/hpux.patch new file mode 100644 index 00000000..389c6751 --- /dev/null +++ b/hpux.patch @@ -0,0 +1,255 @@ +*** xc.orig/config/cf/X11.tmpl Tue Jan 15 22:55:26 2002 +--- xc/config/cf/X11.tmpl Sun Sep 7 19:52:01 2003 +*************** +*** 3120,3126 **** + $(RM) index.raw file.nPS file.PS file.txt + #endif + +! #ifndef MakeSimpleDoc(file,srcs) + #define MakeSimpleDoc(file,srcs) MakeDepSimpleDoc(file,srcs,srcs) + #endif + +--- 3120,3126 ---- + $(RM) index.raw file.nPS file.PS file.txt + #endif + +! #ifndef MakeSimpleDoc + #define MakeSimpleDoc(file,srcs) MakeDepSimpleDoc(file,srcs,srcs) + #endif + +*** xc.orig/config/cf/hp.cf Wed Jan 17 16:22:31 2001 +--- xc/config/cf/hp.cf Mon Sep 8 19:54:52 2003 +*************** +*** 131,137 **** + #endif + #define HPFastScrolling YES + #ifndef BuildServer +! # define BuildServer __hp9000s700 + #endif + #if OSMajorVersion < 10 + #define NeedBerklib (BuildServer|BuildFontServer) +--- 131,137 ---- + #endif + #define HPFastScrolling YES + #ifndef BuildServer +! # define BuildServer YES + #endif + #if OSMajorVersion < 10 + #define NeedBerklib (BuildServer|BuildFontServer) +*************** +*** 139,145 **** + #define XawI18nDefines -DHAS_WCHAR_H -DHAS_ISW_FUNCS + + #if OSMajorVersion < 6 || (OSMajorVersion == 6 && OSMinorVersion < 2) +! # define ConnectionFlags -DTCPCONN /* no unix sockets */ + #endif + + #if OSMajorVersion > 8 +--- 139,145 ---- + #define XawI18nDefines -DHAS_WCHAR_H -DHAS_ISW_FUNCS + + #if OSMajorVersion < 6 || (OSMajorVersion == 6 && OSMinorVersion < 2) +! /*# define ConnectionFlags -DTCPCONN*/ /* no unix sockets */ + #endif + + #if OSMajorVersion > 8 +*** xc/config/cf/site.def.orig Tue Sep 9 17:42:56 2003 +--- xc/config/cf/site.def Tue Sep 9 17:43:07 2003 +*************** +*** 84,90 **** + #ifdef AfterVendorCF + + #ifndef ProjectRoot +! #define ProjectRoot /usr/X11R6 + #endif + + /* +--- 84,90 ---- + #ifdef AfterVendorCF + + #ifndef ProjectRoot +! /*#define ProjectRoot /usr/X11R6*/ + #endif + + /* +*** xc.orig/config/imake/imake.c Fri Dec 14 19:53:18 2001 +--- xc/config/imake/imake.c Mon Sep 8 19:35:33 2003 +*************** +*** 288,293 **** +--- 288,294 ---- + #define TRUE 1 + #define FALSE 0 + ++ #define FIXUP_CPP_WHITESPACE + #ifdef FIXUP_CPP_WHITESPACE + int InRule = FALSE; + # ifdef INLINE_SYNTAX +*************** +*** 389,394 **** +--- 390,401 ---- + FILE *tmpfd = NULL; + char makeMacro[ BUFSIZ ]; + char makefileMacro[ BUFSIZ ]; ++ ++ #ifdef FIXUP_CPP_WHITESPACE ++ fprintf(stderr,"\nFIXUP_CPP_WHITESPACE is defined!!\n\n"); ++ #else ++ #error "FIXUP_CPP_WHITESPACE is not defined" ++ #endif + + program = argv[0]; + init(); +*** xc.orig/config/imake/imakemdep.h Fri Dec 14 19:53:19 2001 +--- xc/config/imake/imakemdep.h Tue Sep 9 16:38:18 2003 +*************** +*** 48,54 **** + #ifdef hp9000s800 + #define imake_ccflags "-DSYSV" + #else +! #define imake_ccflags "-Wc,-Nd4000,-Ns3000 -DSYSV" + #endif + #endif + +--- 48,54 ---- + #ifdef hp9000s800 + #define imake_ccflags "-DSYSV" + #else +! #define imake_ccflags "-DSYSV" + #endif + #endif + +*************** +*** 211,217 **** + * all colons). One way to tell if you need this is to see whether or not + * your Makefiles have no tabs in them and lots of @@ strings. + */ +! #if defined(sun) || defined(SYSV) || defined(SVR4) || defined(hcx) || defined(WIN32) || defined(sco) || (defined(AMOEBA) && defined(CROSS_COMPILE)) || defined(__QNX__) || defined(__sgi) + #define FIXUP_CPP_WHITESPACE + #endif + #ifdef WIN32 +--- 211,217 ---- + * all colons). One way to tell if you need this is to see whether or not + * your Makefiles have no tabs in them and lots of @@ strings. + */ +! #if defined(sun) || defined(SYSV) || defined(SVR4) || defined(hcx) || defined(WIN32) || defined(sco) || (defined(AMOEBA) && defined(CROSS_COMPILE)) || defined(__QNX__) || defined(__sgi) || defined(hpux) + #define FIXUP_CPP_WHITESPACE + #endif + #ifdef WIN32 +*** xc.orig/include/Xfuncs.h Fri Dec 14 19:53:25 2001 +--- xc/include/Xfuncs.h Sun Sep 7 20:10:35 2003 +*************** +*** 42,48 **** + #else + #if defined(SYSV) + #include +! void bcopy(); + #define bzero(b,len) memset(b, 0, len) + #define bcmp(b1,b2,len) memcmp(b1, b2, len) + #elif defined(__EMX__) +--- 42,48 ---- + #else + #if defined(SYSV) + #include +! /*void bcopy();*/ + #define bzero(b,len) memset(b, 0, len) + #define bcmp(b1,b2,len) memcmp(b1, b2, len) + #elif defined(__EMX__) +*** xc.orig/include/extensions/security.h Fri Dec 14 19:53:29 2001 +--- xc/include/extensions/security.h Fri Aug 1 17:43:44 2003 +*************** +*** 110,115 **** +--- 110,116 ---- + + #include "input.h" /* for DeviceIntPtr */ + #include "property.h" /* for PropertyPtr */ ++ #include "resource.h" + + /* resource type to pass in LookupIDByType for authorizations */ + extern RESTYPE SecurityAuthorizationResType; +*** xc.orig/lib/font/Type1/fontfcn.c Fri Nov 23 19:21:31 2001 +--- xc/lib/font/Type1/fontfcn.c Sun Sep 7 19:29:27 2003 +*************** +*** 47,52 **** +--- 47,53 ---- + */ + /* $XFree86: xc/lib/font/Type1/fontfcn.c,v 1.11 2001/11/23 19:21:31 dawes Exp $ */ + ++ #include + #ifndef FONTMODULE + #include + #include +*** xc.orig/lib/font/Type1/objects.h Mon Aug 27 20:49:52 2001 +--- xc/lib/font/Type1/objects.h Sun Sep 7 19:29:37 2003 +*************** +*** 50,56 **** + #include + #include + #ifndef FONTMODULE +! #include + #endif + /*SHARED*/ + +--- 50,56 ---- + #include + #include + #ifndef FONTMODULE +! /*#include */ + #endif + /*SHARED*/ + +*** xc.orig/lib/xtrans/Xtransutil.c Tue Sep 9 17:40:14 2003 +--- xc/lib/xtrans/Xtransutil.c Tue Sep 9 17:40:20 2003 +*************** +*** 503,514 **** + if (updateOwner && !updatedOwner) { + PRMSG(1, "mkdir: Owner of %s should be set to root\n", + path, 0, 0); +- sleep(5); + } + if (updateMode && !updatedMode) { + PRMSG(1, "mkdir: Mode of %s should be set to %04o\n", + path, mode, 0); +- sleep(5); + } + return 0; + } +--- 503,512 ---- +*** xc.orig/programs/Xserver/vnc/Xvnc/xvnc.cc 12 Aug 2003 11:00:14 -0000 +--- xc/programs/Xserver/vnc/Xvnc/xvnc.cc 9 Sep 2003 16:15:53 -0000 +*************** +*** 1221,1223 **** +--- 1221,1229 ---- + miRegisterPointerDevice(screenInfo.screens[0], p); + (void)mieqInit ((DevicePtr)k, (DevicePtr)p); + } ++ ++ extern "C" { ++ void XTestGenerateEvent() {} ++ void XTestGetPointerPos() {} ++ void XTestJumpPointer() {} ++ } +*** xc.orig/config/cf/vnc.def 7 Jul 2003 09:51:22 +--- xc/config/cf/vnc.def 9 Sep 2003 15:54:23 +*************** +*** 9,14 **** +--- 9,20 ---- + #define XnestServer NO + #define XprtServer NO + ++ #define BuildXKB NO ++ #define HasCplusplus YES ++ #define CplusplusCmd /opt/aCC/bin/aCC ++ #define CplusplusOptions -AA +W749 +W740 ++ #define ProjectRoot /usr ++ + #ifdef SunArchitecture + #define ProjectRoot /usr/openwin + #define HasGcc2 YES +*************** +*** 29,32 **** +--- 34,38 ---- + + #define ServerTarget(server,subdirs,objects,libs,syslibs) @@\ + CCLINK = $(CXXENVSETUP) $(CXX) @@\ ++ CCOPTIONS = -AA @@\ + ServerTargetWithFlags(server,subdirs,objects,libs,syslibs,$(_NOOP_)) diff --git a/java/index.vnc b/java/index.vnc new file mode 100644 index 00000000..aecb6131 --- /dev/null +++ b/java/index.vnc @@ -0,0 +1,13 @@ + + + +VNC viewer for Java + + + + + + + + diff --git a/java/logo150x150.gif b/java/logo150x150.gif new file mode 100644 index 0000000000000000000000000000000000000000..f1699ba5894157998459c8455541206c04091d6c GIT binary patch literal 3584 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 literal 0 HcmV?d00001 diff --git a/java/vncviewer.jar b/java/vncviewer.jar new file mode 100644 index 0000000000000000000000000000000000000000..3c92b5bba44798f3c6c4a14b3b1df752c91cc020 GIT binary patch literal 81356 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 +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=logmessages - Win32 Debug Unicode +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "logmessages.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "logmessages.mak" CFG="logmessages - Win32 Debug Unicode" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "logmessages - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "logmessages - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "logmessages - Win32 Debug Unicode" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "logmessages - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "..\Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LOGMESSAGES_EXPORTS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /D "NDEBUG" /D "_WINDOWS" /D "_USRDLL" /D "LOGMESSAGES_EXPORTS" /D "WIN32" /D "_MBCS" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x809 /d "NDEBUG" +# ADD RSC /l 0x809 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 /nologo /dll /machine:I386 /out:"messages.mc" +# Begin Custom Build +InputPath=.\messages.mc +SOURCE="$(InputPath)" + +BuildCmds= \ + mc messages.mc \ + rc -r -fo messages.res messages.rc \ + link -dll -noentry -out:..\Release\logmessages.dll messages.res \ + + +"messages.res" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"messages.rc" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"messages.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"..\Release\logmessages.dll" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) +# End Custom Build + +!ELSEIF "$(CFG)" == "logmessages - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "../Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 1 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LOGMESSAGES_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "_DEBUG" /D "_WINDOWS" /D "_USRDLL" /D "LOGMESSAGES_EXPORTS" /D "WIN32" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x809 /d "_DEBUG" +# ADD RSC /l 0x809 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 /nologo /dll /debug /machine:I386 /nodefaultlib /out:"messages.mc" /pdbtype:sept +# Begin Custom Build +InputPath=.\messages.mc +SOURCE="$(InputPath)" + +BuildCmds= \ + mc messages.mc \ + rc -r -fo messages.res messages.rc \ + link -dll -noentry -out:..\Debug\logmessages.dll messages.res \ + + +"messages.res" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"messages.rc" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"messages.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"..\Debug\logmessages.dll" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) +# End Custom Build + +!ELSEIF "$(CFG)" == "logmessages - Win32 Debug Unicode" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "logmessages___Win32_Debug_Unicode" +# PROP BASE Intermediate_Dir "logmessages___Win32_Debug_Unicode" +# PROP BASE Ignore_Export_Lib 1 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "..\Debug_Unicode" +# PROP Intermediate_Dir "Debug_Unicode" +# PROP Ignore_Export_Lib 1 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "_DEBUG" /D "_WINDOWS" /D "_USRDLL" /D "LOGMESSAGES_EXPORTS" /D "WIN32" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "_WINDOWS" /D "_USRDLL" /D "LOGMESSAGES_EXPORTS" /D "_DEBUG" /D "WIN32" /D "_UNICODE" /D "UNICODE" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x809 /d "_DEBUG" +# ADD RSC /l 0x809 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 /nologo /dll /debug /machine:I386 /nodefaultlib /out:"messages.mc" /pdbtype:sept +# ADD LINK32 /nologo /dll /debug /machine:I386 /nodefaultlib /out:"messages.mc" /pdbtype:sept +# Begin Custom Build +InputPath=.\messages.mc +SOURCE="$(InputPath)" + +BuildCmds= \ + mc messages.mc \ + rc -r -fo messages.res messages.rc \ + link -dll -noentry -out:..\Debug\logmessages.dll messages.res \ + + +"messages.res" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"messages.rc" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"messages.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"..\Debug\logmessages.dll" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) +# End Custom Build + +!ENDIF + +# Begin Target + +# Name "logmessages - Win32 Release" +# Name "logmessages - Win32 Debug" +# Name "logmessages - Win32 Debug Unicode" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# Begin Source File + +SOURCE=.\messages.mc +# End Source File +# End Target +# End Project diff --git a/logmessages/messages.h b/logmessages/messages.h new file mode 100644 index 00000000..bfb8c56d --- /dev/null +++ b/logmessages/messages.h @@ -0,0 +1,47 @@ +// +// Values are 32 bit values layed out as follows: +// +// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 +// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 +// +---+-+-+-----------------------+-------------------------------+ +// |Sev|C|R| Facility | Code | +// +---+-+-+-----------------------+-------------------------------+ +// +// where +// +// Sev - is the severity code +// +// 00 - Success +// 01 - Informational +// 10 - Warning +// 11 - Error +// +// C - is the Customer code flag +// +// R - is a reserved bit +// +// Facility - is the facility code +// +// Code - is the facility's status code +// +// +// Define the facility codes +// + + +// +// Define the severity codes +// + + +// +// MessageId: VNC4LogMessage +// +// MessageText: +// +// %1: %2 +// +// +// +#define VNC4LogMessage 0x00000001L + diff --git a/logmessages/messages.mc b/logmessages/messages.mc new file mode 100644 index 00000000..0bc8329e --- /dev/null +++ b/logmessages/messages.mc @@ -0,0 +1,7 @@ +MessageId=0x1 +Severity=Success +SymbolicName=VNC4LogMessage +Language=English +%1: %2 + + diff --git a/logmessages/messages.rc b/logmessages/messages.rc new file mode 100644 index 00000000..0885a897 --- /dev/null +++ b/logmessages/messages.rc @@ -0,0 +1,2 @@ +LANGUAGE 0x9,0x1 +1 11 MSG00001.bin diff --git a/network/Makefile.in b/network/Makefile.in new file mode 100644 index 00000000..8aed303a --- /dev/null +++ b/network/Makefile.in @@ -0,0 +1,17 @@ + +SRCS = TcpSocket.cxx + +OBJS = $(SRCS:.cxx=.o) + +DIR_CPPFLAGS = -I$(top_srcdir) @SOCKLEN_T_DEFINE@ + +library = libnetwork.a + +all:: $(library) + +$(library): $(OBJS) + rm -f $(library) + $(AR) $(library) $(OBJS) + $(RANLIB) $(library) + +# followed by boilerplate.mk diff --git a/network/Socket.h b/network/Socket.h new file mode 100644 index 00000000..a08afe53 --- /dev/null +++ b/network/Socket.h @@ -0,0 +1,129 @@ +/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +// -=- Socket.h - abstract base-class for any kind of network stream/socket + +#ifndef __NETWORK_SOCKET_H__ +#define __NETWORK_SOCKET_H__ + +#include +#include +#include + +namespace network { + + class Socket { + public: + Socket(int fd) + : instream(new rdr::FdInStream(fd)), + outstream(new rdr::FdOutStream(fd)), + own_streams(true) {} + virtual ~Socket() { + if (own_streams) { + delete instream; + delete outstream; + } + } + rdr::FdInStream &inStream() {return *instream;} + rdr::FdOutStream &outStream() {return *outstream;} + int getFd() {return outstream->getFd();} + virtual void shutdown() = 0; + + // information about this end of the socket + virtual char* getMyAddress() = 0; // a string e.g. "192.168.0.1" + virtual int getMyPort() = 0; + virtual char* getMyEndpoint() = 0; //
:: + + // information about the remote end of the socket + virtual char* getPeerAddress() = 0; // a string e.g. "192.168.0.1" + virtual int getPeerPort() = 0; + virtual char* getPeerEndpoint() = 0; //
:: + + // Is the remote end on the same machine? + virtual bool sameMachine() = 0; + + protected: + Socket() : instream(0), outstream(0), own_streams(false) {} + Socket(rdr::FdInStream* i, rdr::FdOutStream* o, bool own) + : instream(i), outstream(o), own_streams(own) {} + rdr::FdInStream* instream; + rdr::FdOutStream* outstream; + bool own_streams; + }; + + class ConnectionFilter { + public: + virtual bool verifyConnection(Socket* s) = 0; + virtual bool queryUserAcceptConnection(Socket*) {return false;} + }; + + class SocketListener { + public: + SocketListener() : fd(0), filter(0) {} + virtual ~SocketListener() {} + + // shutdown() stops the socket from accepting further connections + virtual void shutdown() = 0; + + // accept() returns a new Socket object if there is a connection + // attempt in progress AND if the connection passes the filter + // if one is installed. Otherwise, returns 0. + virtual Socket* accept() = 0; + + void setFilter(ConnectionFilter* f) {filter = f;} + int getFd() {return fd;} + protected: + int fd; + ConnectionFilter* filter; + }; + + struct SocketException : public rdr::SystemException { + SocketException(const char* text, int err_) : rdr::SystemException(text, err_) {} + }; + + class SocketServer { + public: + virtual ~SocketServer() {} + + // addClient() tells the server to manage the socket. + // If the server can't manage the socket, it must shutdown() it. + virtual void addClient(network::Socket* sock) = 0; + + // processSocketEvent() tells the server there is a socket read event. + // If there is an error, or the socket has been closed/shutdown then + // the server MUST delete the socket AND return false. + virtual bool processSocketEvent(network::Socket* sock) = 0; + + // checkTimeouts() allows the server to check socket timeouts, etc. The + // return value is the number of milliseconds to wait before + // checkTimeouts() should be called again. If this number is zero then + // there is no timeout and checkTimeouts() should be called the next time + // an event occurs. + virtual int checkTimeouts() = 0; + + // soonestTimeout() is a function to help work out the soonest of several + // timeouts. + static void soonestTimeout(int* timeout, int newTimeout) { + if (newTimeout && (!*timeout || newTimeout < *timeout)) + *timeout = newTimeout; + } + }; + +} + +#endif // __NETWORK_SOCKET_H__ diff --git a/network/TcpSocket.cxx b/network/TcpSocket.cxx new file mode 100644 index 00000000..b536e673 --- /dev/null +++ b/network/TcpSocket.cxx @@ -0,0 +1,458 @@ +/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#ifdef WIN32 +//#include +#include +#define errorNumber WSAGetLastError() +#define snprintf _snprintf +#else +#define errorNumber errno +#define closesocket close +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +#include +#include +#include + +#ifndef VNC_SOCKLEN_T +#define VNC_SOCKLEN_T int +#endif + +#ifndef INADDR_NONE +#define INADDR_NONE ((unsigned long)-1) +#endif + +using namespace network; +using namespace rdr; + +static rfb::LogWriter vlog("TcpSocket"); + + +void +TcpSocket::initTcpSockets() { +#ifdef WIN32 + WORD requiredVersion = MAKEWORD(2,0); + WSADATA initResult; + + if (WSAStartup(requiredVersion, &initResult) != 0) + throw SocketException("unable to initialise Winsock2", errorNumber); +#else + signal(SIGPIPE, SIG_IGN); +#endif +} + +// -=- TcpSocket + +TcpSocket::TcpSocket(int sock, bool close) + : Socket(new FdInStream(sock), new FdOutStream(sock), true), closeFd(close) +{ +} + +TcpSocket::TcpSocket(const char *host, int port) + : closeFd(true) +{ + int sock; + + // - Create a socket + if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) + throw SocketException("unable to create socket", errorNumber); + +#ifndef WIN32 + // - By default, close the socket on exec() + fcntl(sock, F_SETFD, FD_CLOEXEC); +#endif + + // - Connect it to something + + // Try processing the host as an IP address + struct sockaddr_in addr; + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = inet_addr(host); + addr.sin_port = htons(port); + if ((int)addr.sin_addr.s_addr == -1) { + // Host was not an IP address - try resolving as DNS name + struct hostent *hostinfo; + hostinfo = gethostbyname(host); + if (hostinfo && hostinfo->h_addr) { + addr.sin_addr.s_addr = ((struct in_addr *)hostinfo->h_addr)->s_addr; + } else { + int e = errorNumber; + closesocket(sock); + throw SocketException("unable to resolve host by name", e); + } + } + + // Attempt to connect to the remote host + if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) != 0) { + int e = errorNumber; + closesocket(sock); + throw SocketException("unable to connect to host", e); + } + + int one = 1; + if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, + (char *)&one, sizeof(one)) < 0) { + int e = errorNumber; + closesocket(sock); + throw SocketException("unable to setsockopt TCP_NODELAY", e); + } + + // Create the input and output streams + instream = new FdInStream(sock); + outstream = new FdOutStream(sock); + own_streams = true; +} + +TcpSocket::~TcpSocket() { + if (closeFd) + closesocket(getFd()); +} + +char* TcpSocket::getMyAddress() { + struct sockaddr_in info; + struct in_addr addr; + VNC_SOCKLEN_T info_size = sizeof(info); + + getsockname(getFd(), (struct sockaddr *)&info, &info_size); + memcpy(&addr, &info.sin_addr, sizeof(addr)); + + char* name = inet_ntoa(addr); + if (name) { + return rfb::strDup(name); + } else { + return rfb::strDup(""); + } +} + +int TcpSocket::getMyPort() { + return getSockPort(getFd()); +} + +char* TcpSocket::getMyEndpoint() { + rfb::CharArray address; address.buf = getMyAddress(); + int port = getMyPort(); + + int buflen = strlen(address.buf) + 32; + char* buffer = new char[buflen]; + sprintf(buffer, "%s::%d", address.buf, port); + return buffer; +} + +char* TcpSocket::getPeerAddress() { + struct sockaddr_in info; + struct in_addr addr; + VNC_SOCKLEN_T info_size = sizeof(info); + + getpeername(getFd(), (struct sockaddr *)&info, &info_size); + memcpy(&addr, &info.sin_addr, sizeof(addr)); + + char* name = inet_ntoa(addr); + if (name) { + return rfb::strDup(name); + } else { + return rfb::strDup(""); + } +} + +int TcpSocket::getPeerPort() { + struct sockaddr_in info; + VNC_SOCKLEN_T info_size = sizeof(info); + + getpeername(getFd(), (struct sockaddr *)&info, &info_size); + return ntohs(info.sin_port); +} + +char* TcpSocket::getPeerEndpoint() { + rfb::CharArray address; address.buf = getPeerAddress(); + int port = getPeerPort(); + + int buflen = strlen(address.buf) + 32; + char* buffer = new char[buflen]; + sprintf(buffer, "%s::%d", address.buf, port); + return buffer; +} + +bool TcpSocket::sameMachine() { + struct sockaddr_in peeraddr, myaddr; + VNC_SOCKLEN_T addrlen = sizeof(struct sockaddr_in); + + getpeername(getFd(), (struct sockaddr *)&peeraddr, &addrlen); + getsockname(getFd(), (struct sockaddr *)&myaddr, &addrlen); + + return (peeraddr.sin_addr.s_addr == myaddr.sin_addr.s_addr); +} + +void TcpSocket::shutdown() +{ + ::shutdown(getFd(), 2); +} + +bool TcpSocket::isSocket(int sock) +{ + struct sockaddr_in info; + VNC_SOCKLEN_T info_size = sizeof(info); + return getsockname(sock, (struct sockaddr *)&info, &info_size) >= 0; +} + +bool TcpSocket::isConnected(int sock) +{ + struct sockaddr_in info; + VNC_SOCKLEN_T info_size = sizeof(info); + return getpeername(sock, (struct sockaddr *)&info, &info_size) >= 0; +} + +int TcpSocket::getSockPort(int sock) +{ + struct sockaddr_in info; + VNC_SOCKLEN_T info_size = sizeof(info); + if (getsockname(sock, (struct sockaddr *)&info, &info_size) < 0) + return 0; + return ntohs(info.sin_port); +} + + +TcpListener::TcpListener(int port, bool localhostOnly, int sock, bool close_) + : closeFd(close_) +{ + if (sock != -1) { + fd = sock; + return; + } + + if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) + throw SocketException("unable to create listening socket", errorNumber); + +#ifndef WIN32 + // - By default, close the socket on exec() + fcntl(sock, F_SETFD, FD_CLOEXEC); + + int one = 1; + if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, + (const char *)&one, sizeof(one)) < 0) { + int e = errorNumber; + closesocket(fd); + throw SocketException("unable to create listening socket", e); + } +#endif + + // - Bind it to the desired port + struct sockaddr_in addr; + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + if (localhostOnly) + addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + else + addr.sin_addr.s_addr = htonl(INADDR_ANY); + if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { + int e = errorNumber; + closesocket(fd); + throw SocketException("unable to bind listening socket", e); + } + + // - Set it to be a listening socket + if (listen(fd, 5) < 0) { + int e = errorNumber; + closesocket(fd); + throw SocketException("unable to set socket to listening mode", e); + } +} + +TcpListener::~TcpListener() { + if (closeFd) closesocket(fd); +} + +void TcpListener::shutdown() +{ +#ifdef WIN32 + closesocket(getFd()); +#else + ::shutdown(getFd(), 2); +#endif +} + + +Socket* +TcpListener::accept() { + int new_sock = -1; + + // Accept an incoming connection + if ((new_sock = ::accept(fd, 0, 0)) < 0) + throw SocketException("unable to accept new connection", errorNumber); + +#ifndef WIN32 + // - By default, close the socket on exec() + fcntl(new_sock, F_SETFD, FD_CLOEXEC); +#endif + + // Disable Nagle's algorithm + int one = 1; + if (setsockopt(new_sock, IPPROTO_TCP, TCP_NODELAY, + (char *)&one, sizeof(one)) < 0) { + int e = errorNumber; + closesocket(new_sock); + throw SocketException("unable to setsockopt TCP_NODELAY", e); + } + + // Create the socket object & check connection is allowed + TcpSocket* s = new TcpSocket(new_sock); + if (filter && !filter->verifyConnection(s)) { + delete s; + return 0; + } + return s; +} + +void TcpListener::getMyAddresses(std::list* result) { + const hostent* addrs = gethostbyname(0); + if (addrs == 0) + throw rdr::SystemException("gethostbyname", errorNumber); + if (addrs->h_addrtype != AF_INET) + throw rdr::Exception("getMyAddresses: bad family"); + for (int i=0; addrs->h_addr_list[i] != 0; i++) { + const char* addrC = inet_ntoa(*((struct in_addr*)addrs->h_addr_list[i])); + char* addr = new char[strlen(addrC)+1]; + strcpy(addr, addrC); + result->push_back(addr); + } +} + +int TcpListener::getMyPort() { + return TcpSocket::getSockPort(getFd()); +} + + +TcpFilter::TcpFilter(const char* spec) { + rfb::CharArray tmp; + tmp.buf = rfb::strDup(spec); + while (tmp.buf) { + rfb::CharArray first; + rfb::strSplit(tmp.buf, ',', &first.buf, &tmp.buf); + if (strlen(first.buf)) + filter.push_back(parsePattern(first.buf)); + } +} + +TcpFilter::~TcpFilter() { +} + + +static bool +patternMatchIP(const TcpFilter::Pattern& pattern, const char* value) { + unsigned long address = inet_addr(value); + if (address == INADDR_NONE) return false; + return ((pattern.address & pattern.mask) == (address & pattern.mask)); +} + +bool +TcpFilter::verifyConnection(Socket* s) { + rfb::CharArray name; + + name.buf = s->getPeerAddress(); + std::list::iterator i; + for (i=filter.begin(); i!=filter.end(); i++) { + if (patternMatchIP(*i, name.buf)) { + switch ((*i).action) { + case Accept: + vlog.debug("ACCEPT %s", name.buf); + return true; + case Query: + vlog.debug("QUERY %s", name.buf); + return queryUserAcceptConnection(s); + case Reject: + vlog.debug("REJECT %s", name.buf); + return false; + } + } + } + + vlog.debug("[REJECT] %s", name.buf); + return false; +} + + +TcpFilter::Pattern TcpFilter::parsePattern(const char* p) { + TcpFilter::Pattern pattern; + + bool expandMask = false; + rfb::CharArray addr, mask; + + if (rfb::strSplit(&p[1], '/', &addr.buf, &mask.buf)) { + if (rfb::strContains(mask.buf, '.')) { + pattern.mask = inet_addr(mask.buf); + } else { + pattern.mask = atoi(mask.buf); + expandMask = true; + } + } else { + pattern.mask = 32; + expandMask = true; + } + if (expandMask) { + unsigned long expanded = 0; + // *** check endianness! + for (int i=0; i<(int)pattern.mask; i++) + expanded |= 1<<(31-i); + pattern.mask = htonl(expanded); + } + + pattern.address = inet_addr(addr.buf) & pattern.mask; + if ((pattern.address == INADDR_NONE) || + (pattern.address == 0)) pattern.mask = 0; + + switch(p[0]) { + case '+': pattern.action = TcpFilter::Accept; break; + case '-': pattern.action = TcpFilter::Reject; break; + case '?': pattern.action = TcpFilter::Query; break; + }; + + return pattern; +} + +char* TcpFilter::patternToStr(const TcpFilter::Pattern& p) { + in_addr tmp; + rfb::CharArray addr, mask; + tmp.s_addr = p.address; + addr.buf = rfb::strDup(inet_ntoa(tmp)); + tmp.s_addr = p.mask; + mask.buf = rfb::strDup(inet_ntoa(tmp)); + char* result = new char[strlen(addr.buf)+1+strlen(mask.buf)+1+1]; + switch (p.action) { + case Accept: result[0] = '+'; break; + case Reject: result[0] = '-'; break; + case Query: result[0] = '?'; break; + }; + result[1] = 0; + strcat(result, addr.buf); + strcat(result, "/"); + strcat(result, mask.buf); + return result; +} diff --git a/network/TcpSocket.h b/network/TcpSocket.h new file mode 100644 index 00000000..95333402 --- /dev/null +++ b/network/TcpSocket.h @@ -0,0 +1,100 @@ +/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +// -=- TcpSocket.h - base-class for TCP stream sockets. +// This header also defines the TcpListener class, used +// to listen for incoming socket connections over TCP +// +// NB: Any file descriptors created by the TcpSocket or +// TcpListener classes are close-on-exec if the OS supports +// it. TcpSockets initialised with a caller-supplied fd +// are NOT set to close-on-exec. + +#ifndef __NETWORK_TCP_SOCKET_H__ +#define __NETWORK_TCP_SOCKET_H__ + +#include + +#include + +namespace network { + + class TcpSocket : public Socket { + public: + TcpSocket(int sock, bool close=true); + TcpSocket(const char *name, int port); + virtual ~TcpSocket(); + + virtual char* getMyAddress(); + virtual int getMyPort(); + virtual char* getMyEndpoint(); + + virtual char* getPeerAddress(); + virtual int getPeerPort(); + virtual char* getPeerEndpoint(); + virtual bool sameMachine(); + + virtual void shutdown(); + + static void initTcpSockets(); + + static bool isSocket(int sock); + static bool isConnected(int sock); + static int getSockPort(int sock); + private: + bool closeFd; + }; + + class TcpListener : public SocketListener { + public: + TcpListener(int port, bool localhostOnly=false, int sock=-1, + bool close=true); + virtual ~TcpListener(); + + virtual void shutdown(); + virtual Socket* accept(); + + void getMyAddresses(std::list* addrs); + int getMyPort(); + + private: + bool closeFd; + }; + + class TcpFilter : public ConnectionFilter { + public: + TcpFilter(const char* filter); + virtual ~TcpFilter(); + + virtual bool verifyConnection(Socket* s); + + typedef enum {Accept, Reject, Query} Action; + struct Pattern { + Action action; + unsigned long address; + unsigned long mask; + }; + static Pattern parsePattern(const char* s); + static char* patternToStr(const Pattern& p); + protected: + std::list filter; + }; + +} + +#endif // __NETWORK_TCP_SOCKET_H__ diff --git a/network/msvcwarning.h b/network/msvcwarning.h new file mode 100644 index 00000000..e93f2bbc --- /dev/null +++ b/network/msvcwarning.h @@ -0,0 +1,18 @@ +/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ +#pragma warning( disable : 4800 ) // forcing bool 'true' or 'false' diff --git a/network/network.dsp b/network/network.dsp new file mode 100644 index 00000000..4290700c --- /dev/null +++ b/network/network.dsp @@ -0,0 +1,129 @@ +# Microsoft Developer Studio Project File - Name="network" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=network - Win32 Debug Unicode +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "network.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "network.mak" CFG="network - Win32 Debug Unicode" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "network - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "network - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE "network - Win32 Debug Unicode" (based on "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "network - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O1 /I ".." /FI"msvcwarning.h" /D "NDEBUG" /D "_LIB" /D "WIN32" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x809 /d "NDEBUG" +# ADD RSC /l 0x809 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ELSEIF "$(CFG)" == "network - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I ".." /FI"msvcwarning.h" /D "_DEBUG" /D "_LIB" /D "WIN32" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x809 /d "_DEBUG" +# ADD RSC /l 0x809 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ELSEIF "$(CFG)" == "network - Win32 Debug Unicode" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "network___Win32_Debug_Unicode" +# PROP BASE Intermediate_Dir "network___Win32_Debug_Unicode" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug_Unicode" +# PROP Intermediate_Dir "Debug_Unicode" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I ".." /FI"msvcwarning.h" /D "_DEBUG" /D "_LIB" /D "WIN32" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I ".." /FI"msvcwarning.h" /D "_LIB" /D "_DEBUG" /D "WIN32" /D "_UNICODE" /D "UNICODE" /YX /FD /GZ /c +# ADD BASE RSC /l 0x809 /d "_DEBUG" +# ADD RSC /l 0x809 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ENDIF + +# Begin Target + +# Name "network - Win32 Release" +# Name "network - Win32 Debug" +# Name "network - Win32 Debug Unicode" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\TcpSocket.cxx +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\Socket.h +# End Source File +# Begin Source File + +SOURCE=.\TcpSocket.h +# End Source File +# End Group +# End Target +# End Project diff --git a/rdr/Exception.cxx b/rdr/Exception.cxx new file mode 100644 index 00000000..5f7799f1 --- /dev/null +++ b/rdr/Exception.cxx @@ -0,0 +1,64 @@ +/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ +#include +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#include +#endif + +using namespace rdr; + +SystemException::SystemException(const char* s, int err_) + : Exception(s, "rdr::SystemException"), err(err_) +{ + strncat(str_, ": ", len-1-strlen(str_)); +#ifdef _WIN32 + // Windows error messages are crap, so use unix ones for common errors. + const char* msg = 0; + switch (err) { + case WSAECONNREFUSED: msg = "Connection refused"; break; + case WSAETIMEDOUT: msg = "Connection timed out"; break; + case WSAECONNRESET: msg = "Connection reset by peer"; break; + case WSAECONNABORTED: msg = "Connection aborted"; break; + } + if (msg) { + strncat(str_, msg, len-1-strlen(str_)); + } else { +#ifdef UNICODE + WCHAR* tmsg = new WCHAR[len-strlen(str_)]; + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + 0, err, 0, tmsg, len-1-strlen(str_), 0); + WideCharToMultiByte(CP_ACP, 0, tmsg, wcslen(tmsg)+1, + str_+strlen(str_), len-strlen(str_), 0, 0); + delete [] tmsg; +#else + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + 0, err, 0, str_+strlen(str_), len-1-strlen(str_), 0); +#endif + } + +#else + strncat(str_, strerror(err), len-1-strlen(str_)); +#endif + strncat(str_, " (", len-1-strlen(str_)); + char buf[20]; + sprintf(buf,"%d",err); + strncat(str_, buf, len-1-strlen(str_)); + strncat(str_, ")", len-1-strlen(str_)); +} diff --git a/rdr/Exception.h b/rdr/Exception.h new file mode 100644 index 00000000..98b3f0e9 --- /dev/null +++ b/rdr/Exception.h @@ -0,0 +1,59 @@ +/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#ifndef __RDR_EXCEPTION_H__ +#define __RDR_EXCEPTION_H__ + +#include +#include + +namespace rdr { + + struct Exception { + enum { len = 256 }; + char str_[len]; + char type_[len]; + Exception(const char* s=0, const char* e="rdr::Exception") { + str_[0] = 0; + if (s) + strncat(str_, s, len-1); + else + strcat(str_, "Exception"); + type_[0] = 0; + strncat(type_, e, len-1); + } + virtual const char* str() const { return str_; } + virtual const char* type() const { return type_; } + }; + + struct SystemException : public Exception { + int err; + SystemException(const char* s, int err_); + }; + + struct TimedOut : public Exception { + TimedOut(const char* s="Timed out") : Exception(s,"rdr::TimedOut") {} + }; + + struct EndOfStream : public Exception { + EndOfStream(const char* s="End of stream") + : Exception(s,"rdr::EndOfStream") {} + }; +} + +#endif diff --git a/rdr/FdInStream.cxx b/rdr/FdInStream.cxx new file mode 100644 index 00000000..397847a4 --- /dev/null +++ b/rdr/FdInStream.cxx @@ -0,0 +1,281 @@ +/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#include +#include +#ifdef _WIN32 +#include +#ifndef _WIN32_WCE +#include +#endif +#define read(s,b,l) recv(s,(char*)b,l,0) +#define close closesocket +#undef errno +#define errno WSAGetLastError() +#undef EINTR +#define EINTR WSAEINTR +#else +#include +#include +#include +#include +#endif + +// XXX should use autoconf HAVE_SYS_SELECT_H +#ifdef _AIX +#include +#endif + +#include +#include + +using namespace rdr; + +enum { DEFAULT_BUF_SIZE = 8192, + MIN_BULK_SIZE = 1024 }; + +FdInStream::FdInStream(int fd_, int timeoutms_, int bufSize_, + bool closeWhenDone_) + : fd(fd_), closeWhenDone(closeWhenDone_), + timeoutms(timeoutms_), blockCallback(0), + timing(false), timeWaitedIn100us(5), timedKbits(0), + bufSize(bufSize_ ? bufSize_ : DEFAULT_BUF_SIZE), offset(0) +{ + ptr = end = start = new U8[bufSize]; +} + +FdInStream::FdInStream(int fd_, FdInStreamBlockCallback* blockCallback_, + int bufSize_) + : fd(fd_), timeoutms(0), blockCallback(blockCallback_), + timing(false), timeWaitedIn100us(5), timedKbits(0), + bufSize(bufSize_ ? bufSize_ : DEFAULT_BUF_SIZE), offset(0) +{ + ptr = end = start = new U8[bufSize]; +} + +FdInStream::~FdInStream() +{ + delete [] start; + if (closeWhenDone) close(fd); +} + + +void FdInStream::setTimeout(int timeoutms_) { + timeoutms = timeoutms_; +} + +void FdInStream::setBlockCallback(FdInStreamBlockCallback* blockCallback_) +{ + blockCallback = blockCallback_; + timeoutms = 0; +} + +int FdInStream::pos() +{ + return offset + ptr - start; +} + +void FdInStream::readBytes(void* data, int length) +{ + if (length < MIN_BULK_SIZE) { + InStream::readBytes(data, length); + return; + } + + U8* dataPtr = (U8*)data; + + int n = end - ptr; + if (n > length) n = length; + + memcpy(dataPtr, ptr, n); + dataPtr += n; + length -= n; + ptr += n; + + while (length > 0) { + n = readWithTimeoutOrCallback(dataPtr, length); + dataPtr += n; + length -= n; + offset += n; + } +} + + +int FdInStream::overrun(int itemSize, int nItems, bool wait) +{ + if (itemSize > bufSize) + throw Exception("FdInStream overrun: max itemSize exceeded"); + + if (end - ptr != 0) + memmove(start, ptr, end - ptr); + + offset += ptr - start; + end -= ptr - start; + ptr = start; + + while (end < start + itemSize) { + int n = readWithTimeoutOrCallback((U8*)end, start + bufSize - end, wait); + if (n == 0) return 0; + end += n; + } + + if (itemSize * nItems > end - ptr) + nItems = (end - ptr) / itemSize; + + return nItems; +} + +#ifdef _WIN32 +static void gettimeofday(struct timeval* tv, void*) +{ + LARGE_INTEGER counts, countsPerSec; + static double usecPerCount = 0.0; + + if (QueryPerformanceCounter(&counts)) { + if (usecPerCount == 0.0) { + QueryPerformanceFrequency(&countsPerSec); + usecPerCount = 1000000.0 / countsPerSec.QuadPart; + } + + LONGLONG usecs = (LONGLONG)(counts.QuadPart * usecPerCount); + tv->tv_usec = (long)(usecs % 1000000); + tv->tv_sec = (long)(usecs / 1000000); + + } else { +#ifndef _WIN32_WCE + struct timeb tb; + ftime(&tb); + tv->tv_sec = tb.time; + tv->tv_usec = tb.millitm * 1000; +#else + throw SystemException("QueryPerformanceCounter", GetLastError()); +#endif + } +} +#endif + +// +// readWithTimeoutOrCallback() reads up to the given length in bytes from the +// file descriptor into a buffer. If the wait argument is false, then zero is +// returned if no bytes can be read without blocking. Otherwise if a +// blockCallback is set, it will be called (repeatedly) instead of blocking. +// If alternatively there is a timeout set and that timeout expires, it throws +// a TimedOut exception. Otherwise it returns the number of bytes read. It +// never attempts to read() unless select() indicates that the fd is readable - +// this means it can be used on an fd which has been set non-blocking. It also +// has to cope with the annoying possibility of both select() and read() +// returning EINTR. +// + +int FdInStream::readWithTimeoutOrCallback(void* buf, int len, bool wait) +{ + struct timeval before, after; + if (timing) + gettimeofday(&before, 0); + + int n; + while (true) { + do { + fd_set fds; + struct timeval tv; + struct timeval* tvp = &tv; + + if (!wait) { + tv.tv_sec = tv.tv_usec = 0; + } else if (timeoutms != -1) { + tv.tv_sec = timeoutms / 1000; + tv.tv_usec = (timeoutms % 1000) * 1000; + } else { + tvp = 0; + } + + FD_ZERO(&fds); + FD_SET(fd, &fds); + n = select(fd+1, &fds, 0, 0, tvp); + } while (n < 0 && errno == EINTR); + + if (n > 0) break; + if (n < 0) throw SystemException("select",errno); + if (!wait) return 0; + if (!blockCallback) throw TimedOut(); + + blockCallback->blockCallback(); + } + + do { + n = ::read(fd, buf, len); + } while (n < 0 && errno == EINTR); + + if (n < 0) throw SystemException("read",errno); + if (n == 0) throw EndOfStream(); + + if (timing) { + gettimeofday(&after, 0); +// fprintf(stderr,"%d.%06d\n",(after.tv_sec - before.tv_sec), +// (after.tv_usec - before.tv_usec)); + int newTimeWaited = ((after.tv_sec - before.tv_sec) * 10000 + + (after.tv_usec - before.tv_usec) / 100); + int newKbits = n * 8 / 1000; + +// if (newTimeWaited == 0) { +// fprintf(stderr,"new kbps infinite t %d k %d\n", +// newTimeWaited, newKbits); +// } else { +// fprintf(stderr,"new kbps %d t %d k %d\n", +// newKbits * 10000 / newTimeWaited, newTimeWaited, newKbits); +// } + + // limit rate to between 10kbit/s and 40Mbit/s + + if (newTimeWaited > newKbits*1000) newTimeWaited = newKbits*1000; + if (newTimeWaited < newKbits/4) newTimeWaited = newKbits/4; + + timeWaitedIn100us += newTimeWaited; + timedKbits += newKbits; + } + + return n; +} + +void FdInStream::startTiming() +{ + timing = true; + + // Carry over up to 1s worth of previous rate for smoothing. + + if (timeWaitedIn100us > 10000) { + timedKbits = timedKbits * 10000 / timeWaitedIn100us; + timeWaitedIn100us = 10000; + } +} + +void FdInStream::stopTiming() +{ + timing = false; + if (timeWaitedIn100us < timedKbits/2) + timeWaitedIn100us = timedKbits/2; // upper limit 20Mbit/s +} + +unsigned int FdInStream::kbitsPerSecond() +{ + // The following calculation will overflow 32-bit arithmetic if we have + // received more than about 50Mbytes (400Mbits) since we started timing, so + // it should be OK for a single RFB update. + + return timedKbits * 10000 / timeWaitedIn100us; +} diff --git a/rdr/FdInStream.h b/rdr/FdInStream.h new file mode 100644 index 00000000..d038b1b3 --- /dev/null +++ b/rdr/FdInStream.h @@ -0,0 +1,77 @@ +/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +// +// FdInStream streams from a file descriptor. +// + +#ifndef __RDR_FDINSTREAM_H__ +#define __RDR_FDINSTREAM_H__ + +#include + +namespace rdr { + + class FdInStreamBlockCallback { + public: + virtual void blockCallback() = 0; + }; + + class FdInStream : public InStream { + + public: + + FdInStream(int fd, int timeoutms=-1, int bufSize=0, + bool closeWhenDone_=false); + FdInStream(int fd, FdInStreamBlockCallback* blockCallback, int bufSize=0); + virtual ~FdInStream(); + + void setTimeout(int timeoutms); + void setBlockCallback(FdInStreamBlockCallback* blockCallback); + int getFd() { return fd; } + int pos(); + void readBytes(void* data, int length); + + void startTiming(); + void stopTiming(); + unsigned int kbitsPerSecond(); + unsigned int timeWaited() { return timeWaitedIn100us; } + + protected: + int overrun(int itemSize, int nItems, bool wait); + + private: + int readWithTimeoutOrCallback(void* buf, int len, bool wait=true); + + int fd; + bool closeWhenDone; + int timeoutms; + FdInStreamBlockCallback* blockCallback; + + bool timing; + unsigned int timeWaitedIn100us; + unsigned int timedKbits; + + int bufSize; + int offset; + U8* start; + }; + +} // end of namespace rdr + +#endif diff --git a/rdr/FdOutStream.cxx b/rdr/FdOutStream.cxx new file mode 100644 index 00000000..6795fc89 --- /dev/null +++ b/rdr/FdOutStream.cxx @@ -0,0 +1,174 @@ +/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#include +#include +#ifdef _WIN32 +#include +#define write(s,b,l) send(s,(const char*)b,l,0) +#define EWOULDBLOCK WSAEWOULDBLOCK +#undef errno +#define errno WSAGetLastError() +#undef EINTR +#define EINTR WSAEINTR +#else +#include +#include +#include +#include +#endif + +#include +#include + + +using namespace rdr; + +enum { DEFAULT_BUF_SIZE = 16384, + MIN_BULK_SIZE = 1024 }; + +FdOutStream::FdOutStream(int fd_, int timeoutms_, int bufSize_) + : fd(fd_), timeoutms(timeoutms_), + bufSize(bufSize_ ? bufSize_ : DEFAULT_BUF_SIZE), offset(0) +{ + ptr = start = new U8[bufSize]; + end = start + bufSize; +} + +FdOutStream::~FdOutStream() +{ + try { + flush(); + } catch (Exception&) { + } + delete [] start; +} + +void FdOutStream::setTimeout(int timeoutms_) { + timeoutms = timeoutms_; +} + +void FdOutStream::writeBytes(const void* data, int length) +{ + if (length < MIN_BULK_SIZE) { + OutStream::writeBytes(data, length); + return; + } + + const U8* dataPtr = (const U8*)data; + + flush(); + + while (length > 0) { + int n = writeWithTimeout(dataPtr, length); + length -= n; + dataPtr += n; + offset += n; + } +} + +int FdOutStream::length() +{ + return offset + ptr - start; +} + +void FdOutStream::flush() +{ + U8* sentUpTo = start; + while (sentUpTo < ptr) { + int n = writeWithTimeout((const void*) sentUpTo, ptr - sentUpTo); + sentUpTo += n; + offset += n; + } + + ptr = start; +} + + +int FdOutStream::overrun(int itemSize, int nItems) +{ + if (itemSize > bufSize) + throw Exception("FdOutStream overrun: max itemSize exceeded"); + + flush(); + + if (itemSize * nItems > end - ptr) + nItems = (end - ptr) / itemSize; + + return nItems; +} + +// +// writeWithTimeout() writes up to the given length in bytes from the given +// buffer to the file descriptor. If there is a timeout set and that timeout +// expires, it throws a TimedOut exception. Otherwise it returns the number of +// bytes written. It never attempts to write() unless select() indicates that +// the fd is writable - this means it can be used on an fd which has been set +// non-blocking. It also has to cope with the annoying possibility of both +// select() and write() returning EINTR. +// + +int FdOutStream::writeWithTimeout(const void* data, int length) +{ + int n; + + do { + + do { + fd_set fds; + struct timeval tv; + struct timeval* tvp = &tv; + + if (timeoutms != -1) { + tv.tv_sec = timeoutms / 1000; + tv.tv_usec = (timeoutms % 1000) * 1000; + } else { + tvp = 0; + } + + FD_ZERO(&fds); + FD_SET(fd, &fds); +#ifdef _WIN32_WCE + // NB: This fixes a broken Winsock2 select() behaviour. select() + // never returns for non-blocking sockets, unless they're already + // ready to be written to... + u_long zero = 0; ioctlsocket(fd, FIONBIO, &zero); +#endif + n = select(fd+1, 0, &fds, 0, tvp); +#ifdef _WIN32_WCE + u_long one = 0; ioctlsocket(fd, FIONBIO, &one); +#endif + } while (n < 0 && errno == EINTR); + + if (n < 0) throw SystemException("select",errno); + + if (n == 0) throw TimedOut(); + + do { + n = ::write(fd, data, length); + } while (n < 0 && (errno == EINTR)); + + // NB: This outer loop simply fixes a broken Winsock2 EWOULDBLOCK + // condition, found only under Win98 (first edition), with slow + // network connections. Should in fact never ever happen... + } while (n < 0 && (errno == EWOULDBLOCK)); + + if (n < 0) throw SystemException("write",errno); + + return n; +} diff --git a/rdr/FdOutStream.h b/rdr/FdOutStream.h new file mode 100644 index 00000000..9c46db94 --- /dev/null +++ b/rdr/FdOutStream.h @@ -0,0 +1,56 @@ +/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +// +// FdOutStream streams to a file descriptor. +// + +#ifndef __RDR_FDOUTSTREAM_H__ +#define __RDR_FDOUTSTREAM_H__ + +#include + +namespace rdr { + + class FdOutStream : public OutStream { + + public: + + FdOutStream(int fd, int timeoutms=-1, int bufSize=0); + virtual ~FdOutStream(); + + void setTimeout(int timeoutms); + int getFd() { return fd; } + + void flush(); + int length(); + void writeBytes(const void* data, int length); + + private: + int overrun(int itemSize, int nItems); + int writeWithTimeout(const void* data, int length); + int fd; + int timeoutms; + int bufSize; + int offset; + U8* start; + }; + +} + +#endif diff --git a/rdr/FixedMemOutStream.h b/rdr/FixedMemOutStream.h new file mode 100644 index 00000000..f149e600 --- /dev/null +++ b/rdr/FixedMemOutStream.h @@ -0,0 +1,52 @@ +/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +// +// A FixedMemOutStream writes to a buffer of a fixed length. +// + +#ifndef __RDR_FIXEDMEMOUTSTREAM_H__ +#define __RDR_FIXEDMEMOUTSTREAM_H__ + +#include +#include + +namespace rdr { + + class FixedMemOutStream : public OutStream { + + public: + + FixedMemOutStream(void* buf, int len) { + ptr = start = (U8*)buf; + end = start + len; + } + + int length() { return ptr - start; } + void reposition(int pos) { ptr = start + pos; } + const void* data() { return (const void*)start; } + + private: + + int overrun(int itemSize, int nItems) { throw EndOfStream(); } + U8* start; + }; + +} + +#endif diff --git a/rdr/HexInStream.cxx b/rdr/HexInStream.cxx new file mode 100644 index 00000000..a454ca8e --- /dev/null +++ b/rdr/HexInStream.cxx @@ -0,0 +1,117 @@ +/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#include +#include + +#include +#include + +using namespace rdr; + +const int DEFAULT_BUF_LEN = 16384; + +static inline int min(int a, int b) {return a= '0') && (c <= '9')) + *v = (*v << 4) + (c - '0'); + else if ((c >= 'a') && (c <= 'f')) + *v = (*v << 4) + (c - 'a' + 10); + else + return false; + return true; +} + +bool HexInStream::hexStrToBin(const char* s, char** data, int* length) { + int l=strlen(s); + if ((l % 2) == 0) { + delete [] *data; + *data = 0; *length = 0; + if (l == 0) + return true; + *data = new char[l/2]; + *length = l/2; + for(int i=0;i bufSize) + throw Exception("HexInStream overrun: max itemSize exceeded"); + + if (end - ptr != 0) + memmove(start, ptr, end - ptr); + + end -= ptr - start; + offset += ptr - start; + ptr = start; + + while (end < ptr + itemSize) { + int n = in_stream.check(2, 1, wait); + if (n == 0) return 0; + const U8* iptr = in_stream.getptr(); + const U8* eptr = in_stream.getend(); + int length = min((eptr - iptr)/2, start + bufSize - end); + + U8* optr = (U8*) end; + for (int i=0; i end - ptr) + nItems = (end - ptr) / itemSize; + + return nItems; +} diff --git a/rdr/HexInStream.h b/rdr/HexInStream.h new file mode 100644 index 00000000..fbfc2738 --- /dev/null +++ b/rdr/HexInStream.h @@ -0,0 +1,50 @@ +/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#ifndef __RDR_HEX_INSTREAM_H__ +#define __RDR_HEX_INSTREAM_H__ + +#include + +namespace rdr { + + class HexInStream : public InStream { + public: + + HexInStream(InStream& is, int bufSize=0); + virtual ~HexInStream(); + + int pos(); + + static bool readHexAndShift(char c, int* v); + static bool hexStrToBin(const char* s, char** data, int* length); + + protected: + int overrun(int itemSize, int nItems, bool wait); + + private: + int bufSize; + U8* start; + int offset; + + InStream& in_stream; + }; + +} // end of namespace rdr + +#endif diff --git a/rdr/HexOutStream.cxx b/rdr/HexOutStream.cxx new file mode 100644 index 00000000..f82d9f55 --- /dev/null +++ b/rdr/HexOutStream.cxx @@ -0,0 +1,110 @@ +/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#include +#include + +using namespace rdr; + +const int DEFAULT_BUF_LEN = 16384; + +static inline int min(int a, int b) {return a=0) && (i<=9)) + return '0'+i; + else if ((i>=10) && (i<=15)) + return 'a'+(i-10); + else + throw rdr::Exception("intToHex failed"); +} + +char* HexOutStream::binToHexStr(const char* data, int length) { + char* buffer = new char[length*2+1]; + for (int i=0; i> 4) & 15); + buffer[i*2+1] = intToHex((data[i] & 15)); + if (!buffer[i*2] || !buffer[i*2+1]) { + delete [] buffer; + return 0; + } + } + buffer[length*2] = 0; + return buffer; +} + + +void +HexOutStream::writeBuffer() { + U8* pos = start; + while (pos != ptr) { + out_stream.check(2); + U8* optr = out_stream.getptr(); + U8* oend = out_stream.getend(); + int length = min(ptr-pos, (oend-optr)/2); + + for (int i=0; i> 4) & 0xf); + optr[i*2+1] = intToHex(pos[i] & 0xf); + } + + out_stream.setptr(optr + length*2); + pos += length; + } + offset += ptr - start; + ptr = start; +} + +int HexOutStream::length() +{ + return offset + ptr - start; +} + +void +HexOutStream::flush() { + writeBuffer(); + out_stream.flush(); +} + +int +HexOutStream::overrun(int itemSize, int nItems) { + if (itemSize > bufSize) + throw Exception("HexOutStream overrun: max itemSize exceeded"); + + writeBuffer(); + + if (itemSize * nItems > end - ptr) + nItems = (end - ptr) / itemSize; + + return nItems; +} + diff --git a/rdr/HexOutStream.h b/rdr/HexOutStream.h new file mode 100644 index 00000000..691a16bc --- /dev/null +++ b/rdr/HexOutStream.h @@ -0,0 +1,51 @@ +/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#ifndef __RDR_HEX_OUTSTREAM_H__ +#define __RDR_HEX_OUTSTREAM_H__ + +#include + +namespace rdr { + + class HexOutStream : public OutStream { + public: + + HexOutStream(OutStream& os, int buflen=0); + virtual ~HexOutStream(); + + void flush(); + int length(); + + static char intToHex(int i); + static char* binToHexStr(const char* data, int length); + + private: + void writeBuffer(); + int overrun(int itemSize, int nItems); + + OutStream& out_stream; + + U8* start; + int offset; + int bufSize; + }; + +} + +#endif diff --git a/rdr/InStream.cxx b/rdr/InStream.cxx new file mode 100644 index 00000000..13a6fa19 --- /dev/null +++ b/rdr/InStream.cxx @@ -0,0 +1,35 @@ +/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#include +#include + +using namespace rdr; + +U32 InStream::maxStringLength = 65535; + +char* InStream::readString() +{ + U32 len = readU32(); + if (len > maxStringLength) + throw Exception("InStream max string length exceeded"); + char* str = new char[len+1]; + readBytes(str, len); + str[len] = 0; + return str; +} diff --git a/rdr/InStream.h b/rdr/InStream.h new file mode 100644 index 00000000..2048daa6 --- /dev/null +++ b/rdr/InStream.h @@ -0,0 +1,153 @@ +/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +// +// rdr::InStream marshalls data from a buffer stored in RDR (RFB Data +// Representation). +// + +#ifndef __RDR_INSTREAM_H__ +#define __RDR_INSTREAM_H__ + +#include +#include // for memcpy + +namespace rdr { + + class InStream { + + public: + + virtual ~InStream() {} + + // check() ensures there is buffer data for at least one item of size + // itemSize bytes. Returns the number of items in the buffer (up to a + // maximum of nItems). If wait is false, then instead of blocking to wait + // for the bytes, zero is returned if the bytes are not immediately + // available. + + inline int check(int itemSize, int nItems=1, bool wait=true) + { + if (ptr + itemSize * nItems > end) { + if (ptr + itemSize > end) + return overrun(itemSize, nItems, wait); + + nItems = (end - ptr) / itemSize; + } + return nItems; + } + + // checkNoWait() tries to make sure that the given number of bytes can + // be read without blocking. It returns true if this is the case, false + // otherwise. The length must be "small" (less than the buffer size). + + inline bool checkNoWait(int length) { return check(length, 1, false)!=0; } + + // readU/SN() methods read unsigned and signed N-bit integers. + + inline U8 readU8() { check(1); return *ptr++; } + inline U16 readU16() { check(2); int b0 = *ptr++; int b1 = *ptr++; + return b0 << 8 | b1; } + inline U32 readU32() { check(4); int b0 = *ptr++; int b1 = *ptr++; + int b2 = *ptr++; int b3 = *ptr++; + return b0 << 24 | b1 << 16 | b2 << 8 | b3; } + + inline S8 readS8() { return (S8) readU8(); } + inline S16 readS16() { return (S16)readU16(); } + inline S32 readS32() { return (S32)readU32(); } + + // readString() reads a string - a U32 length followed by the data. + // Returns a null-terminated string - the caller should delete[] it + // afterwards. + + char* readString(); + + // maxStringLength protects against allocating a huge buffer. Set it + // higher if you need longer strings. + + static U32 maxStringLength; + + inline void skip(int bytes) { + while (bytes > 0) { + int n = check(1, bytes); + ptr += n; + bytes -= n; + } + } + + // readBytes() reads an exact number of bytes. + + virtual void readBytes(void* data, int length) { + U8* dataPtr = (U8*)data; + U8* dataEnd = dataPtr + length; + while (dataPtr < dataEnd) { + int n = check(1, dataEnd - dataPtr); + memcpy(dataPtr, ptr, n); + ptr += n; + dataPtr += n; + } + } + + // readOpaqueN() reads a quantity without byte-swapping. + + inline U8 readOpaque8() { return readU8(); } + inline U16 readOpaque16() { check(2); U16 r; ((U8*)&r)[0] = *ptr++; + ((U8*)&r)[1] = *ptr++; return r; } + inline U32 readOpaque32() { check(4); U32 r; ((U8*)&r)[0] = *ptr++; + ((U8*)&r)[1] = *ptr++; ((U8*)&r)[2] = *ptr++; + ((U8*)&r)[3] = *ptr++; return r; } + inline U32 readOpaque24A() { check(3); U32 r=0; ((U8*)&r)[0] = *ptr++; + ((U8*)&r)[1] = *ptr++; ((U8*)&r)[2] = *ptr++; + return r; } + inline U32 readOpaque24B() { check(3); U32 r=0; ((U8*)&r)[1] = *ptr++; + ((U8*)&r)[2] = *ptr++; ((U8*)&r)[3] = *ptr++; + return r; } + + // pos() returns the position in the stream. + + virtual int pos() = 0; + + // getptr(), getend() and setptr() are "dirty" methods which allow you to + // manipulate the buffer directly. This is useful for a stream which is a + // wrapper around an underlying stream. + + inline const U8* getptr() const { return ptr; } + inline const U8* getend() const { return end; } + inline void setptr(const U8* p) { ptr = p; } + + private: + + // overrun() is implemented by a derived class to cope with buffer overrun. + // It ensures there are at least itemSize bytes of buffer data. Returns + // the number of items in the buffer (up to a maximum of nItems). itemSize + // is supposed to be "small" (a few bytes). If wait is false, then + // instead of blocking to wait for the bytes, zero is returned if the bytes + // are not immediately available. + + virtual int overrun(int itemSize, int nItems, bool wait=true) = 0; + + protected: + + InStream() {} + const U8* ptr; + const U8* end; + }; + +} + +#endif diff --git a/rdr/Makefile.in b/rdr/Makefile.in new file mode 100644 index 00000000..9edf2842 --- /dev/null +++ b/rdr/Makefile.in @@ -0,0 +1,19 @@ + +SRCS = Exception.cxx FdInStream.cxx FdOutStream.cxx InStream.cxx \ + NullOutStream.cxx RandomStream.cxx ZlibInStream.cxx ZlibOutStream.cxx \ + HexInStream.cxx HexOutStream.cxx + +OBJS = $(SRCS:.cxx=.o) + +DIR_CPPFLAGS = -I$(top_srcdir) @ZLIB_INCLUDE@ + +library = librdr.a + +all:: $(library) + +$(library): $(OBJS) + rm -f $(library) + $(AR) $(library) $(OBJS) + $(RANLIB) $(library) + +# followed by boilerplate.mk diff --git a/rdr/MemInStream.h b/rdr/MemInStream.h new file mode 100644 index 00000000..2b05e3df --- /dev/null +++ b/rdr/MemInStream.h @@ -0,0 +1,63 @@ +/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +// +// rdr::MemInStream is an InStream which streams from a given memory buffer. +// If the deleteWhenDone parameter is true then the buffer will be delete[]d in +// the destructor. Note that it is delete[]d as a U8* - strictly speaking this +// means it ought to be new[]ed as a U8* as well, but on most platforms this +// doesn't matter. +// + +#ifndef __RDR_MEMINSTREAM_H__ +#define __RDR_MEMINSTREAM_H__ + +#include +#include + +namespace rdr { + + class MemInStream : public InStream { + + public: + + MemInStream(const void* data, int len, bool deleteWhenDone_=false) + : start((const U8*)data), deleteWhenDone(deleteWhenDone_) + { + ptr = start; + end = start + len; + } + + virtual ~MemInStream() { + if (deleteWhenDone) + delete [] (U8*)start; + } + + int pos() { return ptr - start; } + void reposition(int pos) { ptr = start + pos; } + + private: + + int overrun(int itemSize, int nItems, bool wait) { throw EndOfStream(); } + const U8* start; + bool deleteWhenDone; + }; + +} + +#endif diff --git a/rdr/MemOutStream.h b/rdr/MemOutStream.h new file mode 100644 index 00000000..3456f5c7 --- /dev/null +++ b/rdr/MemOutStream.h @@ -0,0 +1,82 @@ +/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +// +// A MemOutStream grows as needed when data is written to it. +// + +#ifndef __RDR_MEMOUTSTREAM_H__ +#define __RDR_MEMOUTSTREAM_H__ + +#include + +namespace rdr { + + class MemOutStream : public OutStream { + + public: + + MemOutStream(int len=1024) { + start = ptr = new U8[len]; + end = start + len; + } + + virtual ~MemOutStream() { + delete [] start; + } + + void writeBytes(const void* data, int length) { + check(length); + memcpy(ptr, data, length); + ptr += length; + } + + int length() { return ptr - start; } + void clear() { ptr = start; }; + void reposition(int pos) { ptr = start + pos; } + + // data() returns a pointer to the buffer. + + const void* data() { return (const void*)start; } + + private: + + // overrun() either doubles the buffer or adds enough space for nItems of + // size itemSize bytes. + + int overrun(int itemSize, int nItems) { + int len = ptr - start + itemSize * nItems; + if (len < (end - start) * 2) + len = (end - start) * 2; + + U8* newStart = new U8[len]; + memcpy(newStart, start, ptr - start); + ptr = newStart + (ptr - start); + delete [] start; + start = newStart; + end = newStart + len; + + return nItems; + } + + U8* start; + }; + +} + +#endif diff --git a/rdr/NullOutStream.cxx b/rdr/NullOutStream.cxx new file mode 100644 index 00000000..e940f2af --- /dev/null +++ b/rdr/NullOutStream.cxx @@ -0,0 +1,60 @@ +/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#include +#include + +using namespace rdr; + +static const int bufferSize = 1024; + +NullOutStream::NullOutStream() + : offset(0) +{ + start = ptr = new U8[bufferSize]; + end = start + bufferSize; +} + +NullOutStream::~NullOutStream() +{ + delete [] start; +} + +int NullOutStream::length() +{ + return offset + ptr - start; +} + +void NullOutStream::writeBytes(const void* data, int length) +{ + offset += length; +} + +int NullOutStream::overrun(int itemSize, int nItems) +{ + if (itemSize > bufferSize) + throw Exception("NullOutStream overrun: max itemSize exceeded"); + + offset += ptr - start; + ptr = start; + + if (itemSize * nItems > end - ptr) + nItems = (end - ptr) / itemSize; + + return nItems; +} diff --git a/rdr/NullOutStream.h b/rdr/NullOutStream.h new file mode 100644 index 00000000..84a56e5f --- /dev/null +++ b/rdr/NullOutStream.h @@ -0,0 +1,42 @@ +/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#ifndef __RDR_NULLOUTSTREAM_H__ +#define __RDR_NULLOUTSTREAM_H__ + +#include + +namespace rdr { + + class NullOutStream : public OutStream { + + public: + NullOutStream(); + virtual ~NullOutStream(); + int length(); + void writeBytes(const void* data, int length); + + private: + int overrun(int itemSize, int nItems); + int offset; + U8* start; + }; + +} + +#endif diff --git a/rdr/OutStream.h b/rdr/OutStream.h new file mode 100644 index 00000000..a064bcc9 --- /dev/null +++ b/rdr/OutStream.h @@ -0,0 +1,152 @@ +/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +// +// rdr::OutStream marshalls data into a buffer stored in RDR (RFB Data +// Representation). +// + +#ifndef __RDR_OUTSTREAM_H__ +#define __RDR_OUTSTREAM_H__ + +#include +#include // for memcpy + +namespace rdr { + + class OutStream { + + protected: + + OutStream() {} + + public: + + virtual ~OutStream() {} + + // check() ensures there is buffer space for at least one item of size + // itemSize bytes. Returns the number of items which fit (up to a maximum + // of nItems). + + inline int check(int itemSize, int nItems=1) + { + if (ptr + itemSize * nItems > end) { + if (ptr + itemSize > end) + return overrun(itemSize, nItems); + + nItems = (end - ptr) / itemSize; + } + return nItems; + } + + // writeU/SN() methods write unsigned and signed N-bit integers. + + inline void writeU8( U8 u) { check(1); *ptr++ = u; } + inline void writeU16(U16 u) { check(2); *ptr++ = u >> 8; *ptr++ = (U8)u; } + inline void writeU32(U32 u) { check(4); *ptr++ = u >> 24; *ptr++ = u >> 16; + *ptr++ = u >> 8; *ptr++ = u; } + + inline void writeS8( S8 s) { writeU8((U8)s); } + inline void writeS16(S16 s) { writeU16((U16)s); } + inline void writeS32(S32 s) { writeU32((U32)s); } + + // writeString() writes a string - a U32 length followed by the data. The + // given string should be null-terminated (but the terminating null is not + // written to the stream). + + inline void writeString(const char* str) { + U32 len = strlen(str); + writeU32(len); + writeBytes(str, len); + } + + inline void pad(int bytes) { + while (bytes-- > 0) writeU8(0); + } + + inline void skip(int bytes) { + while (bytes > 0) { + int n = check(1, bytes); + ptr += n; + bytes -= n; + } + } + + // writeBytes() writes an exact number of bytes. + + virtual void writeBytes(const void* data, int length) { + const U8* dataPtr = (const U8*)data; + const U8* dataEnd = dataPtr + length; + while (dataPtr < dataEnd) { + int n = check(1, dataEnd - dataPtr); + memcpy(ptr, dataPtr, n); + ptr += n; + dataPtr += n; + } + } + + // writeOpaqueN() writes a quantity without byte-swapping. + + inline void writeOpaque8( U8 u) { writeU8(u); } + inline void writeOpaque16(U16 u) { check(2); *ptr++ = ((U8*)&u)[0]; + *ptr++ = ((U8*)&u)[1]; } + inline void writeOpaque32(U32 u) { check(4); *ptr++ = ((U8*)&u)[0]; + *ptr++ = ((U8*)&u)[1]; + *ptr++ = ((U8*)&u)[2]; + *ptr++ = ((U8*)&u)[3]; } + inline void writeOpaque24A(U32 u) { check(3); *ptr++ = ((U8*)&u)[0]; + *ptr++ = ((U8*)&u)[1]; + *ptr++ = ((U8*)&u)[2]; } + inline void writeOpaque24B(U32 u) { check(3); *ptr++ = ((U8*)&u)[1]; + *ptr++ = ((U8*)&u)[2]; + *ptr++ = ((U8*)&u)[3]; } + + // length() returns the length of the stream. + + virtual int length() = 0; + + // flush() requests that the stream be flushed. + + virtual void flush() {} + + // getptr(), getend() and setptr() are "dirty" methods which allow you to + // manipulate the buffer directly. This is useful for a stream which is a + // wrapper around an underlying stream. + + inline U8* getptr() { return ptr; } + inline U8* getend() { return end; } + inline void setptr(U8* p) { ptr = p; } + + private: + + // overrun() is implemented by a derived class to cope with buffer overrun. + // It ensures there are at least itemSize bytes of buffer space. Returns + // the number of items which fit (up to a maximum of nItems). itemSize is + // supposed to be "small" (a few bytes). + + virtual int overrun(int itemSize, int nItems) = 0; + + protected: + + U8* ptr; + U8* end; + }; + +} + +#endif diff --git a/rdr/RandomStream.cxx b/rdr/RandomStream.cxx new file mode 100644 index 00000000..7f62e091 --- /dev/null +++ b/rdr/RandomStream.cxx @@ -0,0 +1,118 @@ +/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#include +#include +#include +#include +#ifndef WIN32 +#include +#include +#else +#define getpid() GetCurrentProcessId() +#endif + +using namespace rdr; + +const int DEFAULT_BUF_LEN = 256; + +unsigned int RandomStream::seed; + +RandomStream::RandomStream() + : offset(0) +{ + ptr = end = start = new U8[DEFAULT_BUF_LEN]; + +#ifdef WIN32 + provider = 0; + if (!CryptAcquireContext(&provider, 0, 0, PROV_RSA_FULL, 0)) { + if (GetLastError() == NTE_BAD_KEYSET) { + if (!CryptAcquireContext(&provider, 0, 0, PROV_RSA_FULL, CRYPT_NEWKEYSET)) { + fprintf(stderr, "RandomStream: unable to create keyset\n"); + provider = 0; + } + } else { + fprintf(stderr, "RandomStream: unable to acquire context\n"); + provider = 0; + } + } + if (!provider) { +#else + fp = fopen("/dev/urandom", "r"); + if (!fp) + fp = fopen("/dev/random", "r"); + if (!fp) { +#endif + fprintf(stderr,"RandomStream: warning: no OS supplied random source - using rand()\n"); + seed += (unsigned int) time(0) + getpid() + getpid() * 987654 + rand(); + srand(seed); + } +} + +RandomStream::~RandomStream() { + delete [] start; + +#ifdef WIN32 + if (provider) { + CryptReleaseContext(provider, 0); + } +#else + if (fp) fclose(fp); +#endif +} + +int RandomStream::pos() { + return offset + ptr - start; +} + +int RandomStream::overrun(int itemSize, int nItems, bool wait) { + if (itemSize > DEFAULT_BUF_LEN) + throw Exception("RandomStream overrun: max itemSize exceeded"); + + if (end - ptr != 0) + memmove(start, ptr, end - ptr); + + end -= ptr - start; + offset += ptr - start; + ptr = start; + + int length = start + DEFAULT_BUF_LEN - end; + +#ifdef WIN32 + if (provider) { + if (!CryptGenRandom(provider, length, (U8*)end)) + throw rdr::SystemException("unable to CryptGenRandom", GetLastError()); + end += length; +#else + if (fp) { + int n = fread((U8*)end, length, 1, fp); + if (n != 1) + throw rdr::SystemException("reading /dev/urandom or /dev/random failed", + errno); + end += length; +#endif + } else { + for (int i=0; i end - ptr) + nItems = (end - ptr) / itemSize; + + return nItems; +} diff --git a/rdr/RandomStream.h b/rdr/RandomStream.h new file mode 100644 index 00000000..c4aaaa6a --- /dev/null +++ b/rdr/RandomStream.h @@ -0,0 +1,63 @@ +/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#ifndef __RDR_RANDOMSTREAM_H__ +#define __RDR_RANDOMSTREAM_H__ + +#include +#include + +#ifdef WIN32 +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0400 +#endif +#define WIN32_LEAN_AND_MEAN +#include +#include +#endif + +namespace rdr { + + class RandomStream : public InStream { + + public: + + RandomStream(); + virtual ~RandomStream(); + + int pos(); + + protected: + int overrun(int itemSize, int nItems, bool wait); + + private: + U8* start; + int offset; + + static unsigned int seed; +#ifdef WIN32 + HCRYPTPROV provider; +#else + FILE* fp; +#endif + + }; + +} // end of namespace rdr + +#endif diff --git a/rdr/SubstitutingInStream.h b/rdr/SubstitutingInStream.h new file mode 100644 index 00000000..3a0559b7 --- /dev/null +++ b/rdr/SubstitutingInStream.h @@ -0,0 +1,102 @@ +/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#ifndef __RDR_SUBSTITUTINGINSTREAM_H__ +#define __RDR_SUBSTITUTINGINSTREAM_H__ + +#include +#include + +namespace rdr { + + class Substitutor { + public: + virtual char* substitute(const char* varName) = 0; + }; + + class SubstitutingInStream : public InStream { + public: + SubstitutingInStream(InStream* underlying_, Substitutor* s, + int maxVarNameLen_) + : underlying(underlying_), dollar(0), substitutor(s), subst(0), + maxVarNameLen(maxVarNameLen_) + { + ptr = end = underlying->getptr(); + varName = new char[maxVarNameLen+1]; + } + ~SubstitutingInStream() { + delete underlying; + delete [] varName; + delete [] subst; + } + + int pos() { return underlying->pos(); } + + virtual int overrun(int itemSize, int nItems, bool wait=true) { + if (itemSize != 1) + throw new rdr::Exception("SubstitutingInStream: itemSize must be 1"); + + if (subst) { + delete [] subst; + subst = 0; + } else { + underlying->setptr(ptr); + } + + underlying->check(1); + ptr = underlying->getptr(); + end = underlying->getend(); + dollar = (const U8*)memchr(ptr, '$', end-ptr); + if (dollar) { + if (dollar == ptr) { + try { + int i = 0; + while (i < maxVarNameLen) { + varName[i++] = underlying->readS8(); + varName[i] = 0; + subst = substitutor->substitute(varName); + if (subst) { + ptr = (U8*)subst; + end = (U8*)subst + strlen(subst); + break; + } + } + } catch (EndOfStream&) { + } + + if (!subst) + dollar = (const U8*)memchr(ptr+1, '$', end-ptr-1); + } + if (!subst && dollar) end = dollar; + } + + if (itemSize * nItems > end - ptr) + nItems = (end - ptr) / itemSize; + + return nItems; + } + + InStream* underlying; + const U8* dollar; + Substitutor* substitutor; + char* varName; + char* subst; + int maxVarNameLen; + }; +} +#endif diff --git a/rdr/ZlibInStream.cxx b/rdr/ZlibInStream.cxx new file mode 100644 index 00000000..52e4dd35 --- /dev/null +++ b/rdr/ZlibInStream.cxx @@ -0,0 +1,125 @@ +/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#include +#include +#include + +using namespace rdr; + +enum { DEFAULT_BUF_SIZE = 16384 }; + +ZlibInStream::ZlibInStream(int bufSize_) + : underlying(0), bufSize(bufSize_ ? bufSize_ : DEFAULT_BUF_SIZE), offset(0), + bytesIn(0) +{ + zs = new z_stream; + zs->zalloc = Z_NULL; + zs->zfree = Z_NULL; + zs->opaque = Z_NULL; + zs->next_in = Z_NULL; + zs->avail_in = 0; + if (inflateInit(zs) != Z_OK) { + delete zs; + throw Exception("ZlibInStream: inflateInit failed"); + } + ptr = end = start = new U8[bufSize]; +} + +ZlibInStream::~ZlibInStream() +{ + delete [] start; + inflateEnd(zs); + delete zs; +} + +void ZlibInStream::setUnderlying(InStream* is, int bytesIn_) +{ + underlying = is; + bytesIn = bytesIn_; + ptr = end = start; +} + +int ZlibInStream::pos() +{ + return offset + ptr - start; +} + +void ZlibInStream::reset() +{ + ptr = end = start; + if (!underlying) return; + + while (bytesIn > 0) { + decompress(true); + end = start; // throw away any data + } + underlying = 0; +} + +int ZlibInStream::overrun(int itemSize, int nItems, bool wait) +{ + if (itemSize > bufSize) + throw Exception("ZlibInStream overrun: max itemSize exceeded"); + if (!underlying) + throw Exception("ZlibInStream overrun: no underlying stream"); + + if (end - ptr != 0) + memmove(start, ptr, end - ptr); + + offset += ptr - start; + end -= ptr - start; + ptr = start; + + while (end - ptr < itemSize) { + if (!decompress(wait)) + return 0; + } + + if (itemSize * nItems > end - ptr) + nItems = (end - ptr) / itemSize; + + return nItems; +} + +// decompress() calls the decompressor once. Note that this won't necessarily +// generate any output data - it may just consume some input data. Returns +// false if wait is false and we would block on the underlying stream. + +bool ZlibInStream::decompress(bool wait) +{ + zs->next_out = (U8*)end; + zs->avail_out = start + bufSize - end; + + int n = underlying->check(1, 1, wait); + if (n == 0) return false; + zs->next_in = (U8*)underlying->getptr(); + zs->avail_in = underlying->getend() - underlying->getptr(); + if ((int)zs->avail_in > bytesIn) + zs->avail_in = bytesIn; + + int rc = inflate(zs, Z_SYNC_FLUSH); + if (rc != Z_OK) { + throw Exception("ZlibInStream: inflate failed"); + } + + bytesIn -= zs->next_in - underlying->getptr(); + end = zs->next_out; + underlying->setptr(zs->next_in); + return true; +} diff --git a/rdr/ZlibInStream.h b/rdr/ZlibInStream.h new file mode 100644 index 00000000..81eb161c --- /dev/null +++ b/rdr/ZlibInStream.h @@ -0,0 +1,59 @@ +/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +// +// ZlibInStream streams from a compressed data stream ("underlying"), +// decompressing with zlib on the fly. +// + +#ifndef __RDR_ZLIBINSTREAM_H__ +#define __RDR_ZLIBINSTREAM_H__ + +#include + +struct z_stream_s; + +namespace rdr { + + class ZlibInStream : public InStream { + + public: + + ZlibInStream(int bufSize=0); + virtual ~ZlibInStream(); + + void setUnderlying(InStream* is, int bytesIn); + void reset(); + int pos(); + + private: + + int overrun(int itemSize, int nItems, bool wait); + bool decompress(bool wait); + + InStream* underlying; + int bufSize; + int offset; + z_stream_s* zs; + int bytesIn; + U8* start; + }; + +} // end of namespace rdr + +#endif diff --git a/rdr/ZlibOutStream.cxx b/rdr/ZlibOutStream.cxx new file mode 100644 index 00000000..6aadde13 --- /dev/null +++ b/rdr/ZlibOutStream.cxx @@ -0,0 +1,140 @@ +/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#include +#include +#include + +using namespace rdr; + +enum { DEFAULT_BUF_SIZE = 16384 }; + +ZlibOutStream::ZlibOutStream(OutStream* os, int bufSize_, int compressLevel) + : underlying(os), bufSize(bufSize_ ? bufSize_ : DEFAULT_BUF_SIZE), offset(0) +{ + zs = new z_stream; + zs->zalloc = Z_NULL; + zs->zfree = Z_NULL; + zs->opaque = Z_NULL; + if (deflateInit(zs, compressLevel) != Z_OK) { + delete zs; + throw Exception("ZlibOutStream: deflateInit failed"); + } + ptr = start = new U8[bufSize]; + end = start + bufSize; +} + +ZlibOutStream::~ZlibOutStream() +{ + try { + flush(); + } catch (Exception&) { + } + delete [] start; + deflateEnd(zs); + delete zs; +} + +void ZlibOutStream::setUnderlying(OutStream* os) +{ + underlying = os; +} + +int ZlibOutStream::length() +{ + return offset + ptr - start; +} + +void ZlibOutStream::flush() +{ + zs->next_in = start; + zs->avail_in = ptr - start; + +// fprintf(stderr,"zos flush: avail_in %d\n",zs->avail_in); + + while (zs->avail_in != 0) { + + do { + underlying->check(1); + zs->next_out = underlying->getptr(); + zs->avail_out = underlying->getend() - underlying->getptr(); + +// fprintf(stderr,"zos flush: calling deflate, avail_in %d, avail_out %d\n", +// zs->avail_in,zs->avail_out); + int rc = deflate(zs, Z_SYNC_FLUSH); + if (rc != Z_OK) throw Exception("ZlibOutStream: deflate failed"); + +// fprintf(stderr,"zos flush: after deflate: %d bytes\n", +// zs->next_out-underlying->getptr()); + + underlying->setptr(zs->next_out); + } while (zs->avail_out == 0); + } + + offset += ptr - start; + ptr = start; +} + +int ZlibOutStream::overrun(int itemSize, int nItems) +{ +// fprintf(stderr,"ZlibOutStream overrun\n"); + + if (itemSize > bufSize) + throw Exception("ZlibOutStream overrun: max itemSize exceeded"); + + while (end - ptr < itemSize) { + zs->next_in = start; + zs->avail_in = ptr - start; + + do { + underlying->check(1); + zs->next_out = underlying->getptr(); + zs->avail_out = underlying->getend() - underlying->getptr(); + +// fprintf(stderr,"zos overrun: calling deflate, avail_in %d, avail_out %d\n", +// zs->avail_in,zs->avail_out); + + int rc = deflate(zs, 0); + if (rc != Z_OK) throw Exception("ZlibOutStream: deflate failed"); + +// fprintf(stderr,"zos overrun: after deflate: %d bytes\n", +// zs->next_out-underlying->getptr()); + + underlying->setptr(zs->next_out); + } while (zs->avail_out == 0); + + // output buffer not full + + if (zs->avail_in == 0) { + offset += ptr - start; + ptr = start; + } else { + // but didn't consume all the data? try shifting what's left to the + // start of the buffer. + fprintf(stderr,"z out buf not full, but in data not consumed\n"); + memmove(start, zs->next_in, ptr - zs->next_in); + offset += zs->next_in - start; + ptr -= zs->next_in - start; + } + } + + if (itemSize * nItems > end - ptr) + nItems = (end - ptr) / itemSize; + + return nItems; +} diff --git a/rdr/ZlibOutStream.h b/rdr/ZlibOutStream.h new file mode 100644 index 00000000..e51db73b --- /dev/null +++ b/rdr/ZlibOutStream.h @@ -0,0 +1,57 @@ +/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +// +// ZlibOutStream streams to a compressed data stream (underlying), compressing +// with zlib on the fly. +// + +#ifndef __RDR_ZLIBOUTSTREAM_H__ +#define __RDR_ZLIBOUTSTREAM_H__ + +#include + +struct z_stream_s; + +namespace rdr { + + class ZlibOutStream : public OutStream { + + public: + + ZlibOutStream(OutStream* os=0, int bufSize=0, int compressionLevel=-1); + virtual ~ZlibOutStream(); + + void setUnderlying(OutStream* os); + void flush(); + int length(); + + private: + + int overrun(int itemSize, int nItems); + + OutStream* underlying; + int bufSize; + int offset; + z_stream_s* zs; + U8* start; + }; + +} // end of namespace rdr + +#endif diff --git a/rdr/msvcwarning.h b/rdr/msvcwarning.h new file mode 100644 index 00000000..e93f2bbc --- /dev/null +++ b/rdr/msvcwarning.h @@ -0,0 +1,18 @@ +/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ +#pragma warning( disable : 4800 ) // forcing bool 'true' or 'false' diff --git a/rdr/rdr.dsp b/rdr/rdr.dsp new file mode 100644 index 00000000..260f8f01 --- /dev/null +++ b/rdr/rdr.dsp @@ -0,0 +1,231 @@ +# Microsoft Developer Studio Project File - Name="rdr" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=rdr - Win32 Debug Unicode +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "rdr.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "rdr.mak" CFG="rdr - Win32 Debug Unicode" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "rdr - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "rdr - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE "rdr - Win32 Debug Unicode" (based on "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "rdr - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O1 /I ".." /FI"msvcwarning.h" /D "NDEBUG" /D "_LIB" /D "WIN32" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x809 /d "NDEBUG" +# ADD RSC /l 0x809 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ELSEIF "$(CFG)" == "rdr - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I ".." /FI"msvcwarning.h" /D "_DEBUG" /D "_LIB" /D "WIN32" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x809 /d "_DEBUG" +# ADD RSC /l 0x809 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ELSEIF "$(CFG)" == "rdr - Win32 Debug Unicode" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "rdr___Win32_Debug_Unicode" +# PROP BASE Intermediate_Dir "rdr___Win32_Debug_Unicode" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug_Unicode" +# PROP Intermediate_Dir "Debug_Unicode" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I ".." /FI"msvcwarning.h" /D "_DEBUG" /D "_LIB" /D "WIN32" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I ".." /FI"msvcwarning.h" /D "_LIB" /D "_DEBUG" /D "WIN32" /D "_UNICODE" /D "UNICODE" /YX /FD /GZ /c +# ADD BASE RSC /l 0x809 /d "_DEBUG" +# ADD RSC /l 0x809 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ENDIF + +# Begin Target + +# Name "rdr - Win32 Release" +# Name "rdr - Win32 Debug" +# Name "rdr - Win32 Debug Unicode" +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\Exception.h +# End Source File +# Begin Source File + +SOURCE=.\FdInStream.h +# End Source File +# Begin Source File + +SOURCE=.\FdOutStream.h +# End Source File +# Begin Source File + +SOURCE=.\FixedMemOutStream.h +# End Source File +# Begin Source File + +SOURCE=.\HexInStream.h +# End Source File +# Begin Source File + +SOURCE=.\HexOutStream.h +# End Source File +# Begin Source File + +SOURCE=.\InStream.h +# End Source File +# Begin Source File + +SOURCE=.\MemInStream.h +# End Source File +# Begin Source File + +SOURCE=.\MemOutStream.h +# End Source File +# Begin Source File + +SOURCE=.\msvcwarning.h +# End Source File +# Begin Source File + +SOURCE=.\NullOutStream.h +# End Source File +# Begin Source File + +SOURCE=.\OutStream.h +# End Source File +# Begin Source File + +SOURCE=.\RandomStream.h +# End Source File +# Begin Source File + +SOURCE=.\SubstitutingInStream.h +# End Source File +# Begin Source File + +SOURCE=.\types.h +# End Source File +# Begin Source File + +SOURCE=.\ZlibInStream.h +# End Source File +# Begin Source File + +SOURCE=.\ZlibOutStream.h +# End Source File +# End Group +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\Exception.cxx +# End Source File +# Begin Source File + +SOURCE=.\FdInStream.cxx +# ADD CPP /I "../zlib" +# End Source File +# Begin Source File + +SOURCE=.\FdOutStream.cxx +# ADD CPP /I "../zlib" +# End Source File +# Begin Source File + +SOURCE=.\HexInStream.cxx +# End Source File +# Begin Source File + +SOURCE=.\HexOutStream.cxx +# End Source File +# Begin Source File + +SOURCE=.\InStream.cxx +# ADD CPP /I "../zlib" +# End Source File +# Begin Source File + +SOURCE=.\NullOutStream.cxx +# ADD CPP /I "../zlib" +# End Source File +# Begin Source File + +SOURCE=.\RandomStream.cxx +# End Source File +# Begin Source File + +SOURCE=.\ZlibInStream.cxx +# ADD CPP /I "../zlib" +# End Source File +# Begin Source File + +SOURCE=.\ZlibOutStream.cxx +# ADD CPP /I "../zlib" +# End Source File +# End Group +# End Target +# End Project diff --git a/rdr/types.h b/rdr/types.h new file mode 100644 index 00000000..3798c975 --- /dev/null +++ b/rdr/types.h @@ -0,0 +1,56 @@ +/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#ifndef __RDR_TYPES_H__ +#define __RDR_TYPES_H__ + +namespace rdr { + + typedef unsigned char U8; + typedef unsigned short U16; + typedef unsigned int U32; + typedef signed char S8; + typedef signed short S16; + typedef signed int S32; + + class U8Array { + public: + U8Array() : buf(0) {} + U8Array(U8* a) : buf(a) {} // note: assumes ownership + U8Array(int len) : buf(new U8[len]) {} + ~U8Array() { delete [] buf; } + + // Get the buffer pointer & clear it (i.e. caller takes ownership) + U8* takeBuf() { U8* tmp = buf; buf = 0; return tmp; } + + U8* buf; + }; + + class U16Array { + public: + U16Array() : buf(0) {} + U16Array(U16* a) : buf(a) {} // note: assumes ownership + U16Array(int len) : buf(new U16[len]) {} + ~U16Array() { delete [] buf; } + U16* takeBuf() { U16* tmp = buf; buf = 0; return tmp; } + U16* buf; + }; + +} // end of namespace rdr + +#endif diff --git a/rfb/Blacklist.cxx b/rfb/Blacklist.cxx new file mode 100644 index 00000000..4c4f95b2 --- /dev/null +++ b/rfb/Blacklist.cxx @@ -0,0 +1,86 @@ +/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ +#include +#include + +using namespace rfb; + +IntParameter Blacklist::threshold("BlacklistThreshold", + "The number of unauthenticated connection attempts allowed from any " + "individual host before that host is black-listed", + 5); +IntParameter Blacklist::initialTimeout("BlacklistTimeout", + "The initial timeout applied when a host is first black-listed. " + "The host cannot re-attempt a connection until the timeout expires.", + 10); + + +Blacklist::Blacklist() { +} + +Blacklist::~Blacklist() { + // Free the map keys + BlacklistMap::iterator i; + for (i=blm.begin(); i!=blm.end(); i++) { + strFree((char*)(*i).first); + } +} + +bool Blacklist::isBlackmarked(const char* name) { + BlacklistMap::iterator i = blm.find(name); + if (i == blm.end()) { + // Entry is not already black-marked. + // Create the entry unmarked, unblocked, + // with suitable defaults set. + BlacklistInfo bi; + bi.marks = 1; + bi.blockUntil = 0; + bi.blockTimeout = initialTimeout; + blm[strDup(name)] = bi; + i = blm.find(name); + } + + // Entry exists - has it reached the threshold yet? + if ((*i).second.marks >= threshold) { + // Yes - entry is blocked - has the timeout expired? + time_t now = time(0); + if (now >= (*i).second.blockUntil) { + // Timeout has expired. Reset timeout and allow + // a re-try. + (*i).second.blockUntil = now + (*i).second.blockTimeout; + (*i).second.blockTimeout = (*i).second.blockTimeout * 2; + return false; + } + // Blocked and timeout still in effect - reject! + return true; + } + + // We haven't reached the threshold yet. + // Increment the black-mark counter but allow + // the entry to pass. + (*i).second.marks++; + return false; +} + +void Blacklist::clearBlackmark(const char* name) { + BlacklistMap::iterator i = blm.find(name); + if (i != blm.end()) { + strFree((char*)(*i).first); + blm.erase(i); + } +} diff --git a/rfb/Blacklist.h b/rfb/Blacklist.h new file mode 100644 index 00000000..4df7ec80 --- /dev/null +++ b/rfb/Blacklist.h @@ -0,0 +1,91 @@ +/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +// +// Blacklist.h - Handling of black-listed entities. +// Just keeps a table mapping strings to timing information, including +// how many times the entry has been black-listed and when to next +// put it on probation (e.g. allow a connection in from the host, and +// re-blacklist it if that fails). +// + +#ifndef __RFB_BLACKLIST_H__ +#define __RFB_BLACKLIST_H__ + +#include +#include +#include + +#include +#include + +namespace rfb { + + // + // -=- Blacklist handler + // + // Parameters include a threshold after which to blacklist the named + // host, and a timeout after which to re-consider them. + // + // Threshold means that isBlackmarked can be called that number of times + // before it will return true. + // + // Timeout means that after that many seconds, the next call to isBlackmarked + // will return false. At the same time, the timeout is doubled, so that the + // next calls will fail, until the timeout expires again or clearBlackmark is + // called. + // + // When clearBlackMark is called, the corresponding entry is completely + // removed, causing the next isBlackmarked call to return false. + + // KNOWN BUG: Client can keep making rejected requests, thus increasing + // their timeout. If client does this for 30 years, timeout may wrap round + // to a very small value again. + + // THIS CLASS IS NOT THREAD-SAFE! + + class Blacklist { + public: + Blacklist(); + ~Blacklist(); + + bool isBlackmarked(const char* name); + void clearBlackmark(const char* name); + + static IntParameter threshold; + static IntParameter initialTimeout; + + protected: + struct ltStr { + bool operator()(const char* s1, const char* s2) const { + return strcmp(s1, s2) < 0; + }; + }; + struct BlacklistInfo { + int marks; + time_t blockUntil; + unsigned int blockTimeout; + }; + typedef std::map BlacklistMap; + BlacklistMap blm; + }; + +} + +#endif + diff --git a/rfb/CConnection.cxx b/rfb/CConnection.cxx new file mode 100644 index 00000000..c6a3eed8 --- /dev/null +++ b/rfb/CConnection.cxx @@ -0,0 +1,291 @@ +/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace rfb; + +static LogWriter vlog("CConnection"); + +CConnection::CConnection() + : is(0), os(0), reader_(0), writer_(0), + shared(false), security(0), nSecTypes(0), clientSecTypeOrder(false), + state_(RFBSTATE_UNINITIALISED), useProtocol3_3(false) +{ +} + +CConnection::~CConnection() +{ + if (security) security->destroy(); + deleteReaderAndWriter(); +} + +void CConnection::setServerName(const char* serverName_) { + serverName.buf = strDup(serverName_); +} + +void CConnection::deleteReaderAndWriter() +{ + delete reader_; + reader_ = 0; + delete writer_; + writer_ = 0; +} + +void CConnection::setStreams(rdr::InStream* is_, rdr::OutStream* os_) +{ + is = is_; + os = os_; +} + +void CConnection::addSecType(rdr::U8 secType) +{ + if (nSecTypes == maxSecTypes) + throw Exception("too many security types"); + secTypes[nSecTypes++] = secType; +} + +void CConnection::setClientSecTypeOrder(bool clientOrder) { + clientSecTypeOrder = clientOrder; +} + +void CConnection::initialiseProtocol() +{ + state_ = RFBSTATE_PROTOCOL_VERSION; +} + +void CConnection::processMsg() +{ + switch (state_) { + + case RFBSTATE_PROTOCOL_VERSION: processVersionMsg(); break; + case RFBSTATE_SECURITY_TYPES: processSecurityTypesMsg(); break; + case RFBSTATE_SECURITY: processSecurityMsg(); break; + case RFBSTATE_SECURITY_RESULT: processSecurityResultMsg(); break; + case RFBSTATE_INITIALISATION: processInitMsg(); break; + case RFBSTATE_NORMAL: reader_->readMsg(); break; + case RFBSTATE_UNINITIALISED: + throw Exception("CConnection::processMsg: not initialised yet?"); + default: + throw Exception("CConnection::processMsg: invalid state"); + } +} + +void CConnection::processVersionMsg() +{ + vlog.debug("reading protocol version"); + bool done; + if (!cp.readVersion(is, &done)) { + state_ = RFBSTATE_INVALID; + throw Exception("reading version failed: not an RFB server?"); + } + if (!done) return; + + vlog.info("Server supports RFB protocol version %d.%d", + cp.majorVersion, cp.minorVersion); + + // The only official RFB protocol versions are currently 3.3, 3.7 and 3.8 + if (cp.beforeVersion(3,3)) { + char msg[256]; + sprintf(msg,"Server gave unsupported RFB protocol version %d.%d", + cp.majorVersion, cp.minorVersion); + vlog.error(msg); + state_ = RFBSTATE_INVALID; + throw Exception(msg); + } else if (useProtocol3_3 || cp.beforeVersion(3,7)) { + cp.setVersion(3,3); + } else if (cp.afterVersion(3,8)) { + cp.setVersion(3,8); + } + + cp.writeVersion(os); + state_ = RFBSTATE_SECURITY_TYPES; + + vlog.info("Using RFB protocol version %d.%d", + cp.majorVersion, cp.minorVersion); +} + + +void CConnection::processSecurityTypesMsg() +{ + vlog.debug("processing security types message"); + + int secType = secTypeInvalid; + + if (cp.isVersion(3,3)) { + + // legacy 3.3 server may only offer "vnc authentication" or "none" + + secType = is->readU32(); + if (secType == secTypeInvalid) { + throwConnFailedException(); + + } else if (secType == secTypeNone || secType == secTypeVncAuth) { + int j; + for (j = 0; j < nSecTypes; j++) + if (secTypes[j] == secType) break; + if (j == nSecTypes) + secType = secTypeInvalid; + } else { + vlog.error("Unknown 3.3 security type %d", secType); + throw Exception("Unknown 3.3 security type"); + } + + } else { + + // >=3.7 server will offer us a list + + int nServerSecTypes = is->readU8(); + if (nServerSecTypes == 0) + throwConnFailedException(); + + int secTypePos = nSecTypes; + for (int i = 0; i < nServerSecTypes; i++) { + rdr::U8 serverSecType = is->readU8(); + vlog.debug("Server offers security type %s(%d)", + secTypeName(serverSecType),serverSecType); + + // If we haven't already chosen a secType, try this one + // If we are using the client's preference for types, + // we keep trying types, to find the one that matches and + // which appears first in the client's list of supported types. + if (secType == secTypeInvalid || clientSecTypeOrder) { + for (int j = 0; j < nSecTypes; j++) { + if (secTypes[j] == serverSecType && j < secTypePos) { + secType = secTypes[j]; + secTypePos = j; + break; + } + } + // NB: Continue reading the remaining server secTypes, but ignore them + } + } + + // Inform the server of our decision + if (secType != secTypeInvalid) { + os->writeU8(secType); + os->flush(); + vlog.debug("Choosing security type %s(%d)",secTypeName(secType),secType); + } + } + + if (secType == secTypeInvalid) { + state_ = RFBSTATE_INVALID; + vlog.error("No matching security types"); + throw Exception("No matching security types"); + } + + state_ = RFBSTATE_SECURITY; + security = getCSecurity(secType); + processSecurityMsg(); +} + +void CConnection::processSecurityMsg() +{ + vlog.debug("processing security message"); + bool done; + if (!security->processMsg(this, &done)) + throwAuthFailureException(); + if (done) { + state_ = RFBSTATE_SECURITY_RESULT; + processSecurityResultMsg(); + } +} + +void CConnection::processSecurityResultMsg() +{ + vlog.debug("processing security result message"); + int result; + if (cp.beforeVersion(3,8) && security->getType() == secTypeNone) { + result = secResultOK; + } else { + if (!is->checkNoWait(1)) return; + result = is->readU32(); + } + switch (result) { + case secResultOK: + securityCompleted(); + break; + case secResultFailed: + vlog.debug("auth failed"); + throwAuthFailureException(); + case secResultTooMany: + vlog.debug("auth failed - too many tries"); + throwAuthFailureException(); + default: + vlog.error("unknown security result"); + throwAuthFailureException(); + }; +} + +void CConnection::processInitMsg() +{ + vlog.debug("reading server initialisation"); + reader_->readServerInit(); +} + +void CConnection::throwAuthFailureException() +{ + CharArray reason; + vlog.debug("state=%d, ver=%d.%d", state(), cp.majorVersion, cp.minorVersion); + if (state()==RFBSTATE_SECURITY_RESULT && !cp.beforeVersion(3,8)) { + reason.buf = is->readString(); + } else { + reason.buf = strDup("Authentication failure"); + } + state_ = RFBSTATE_INVALID; + vlog.error(reason.buf); + throw AuthFailureException(reason.buf); +} + +void CConnection::throwConnFailedException() +{ + state_ = RFBSTATE_INVALID; + CharArray reason; + reason.buf = is->readString(); + throw ConnFailedException(reason.buf); +} + +void CConnection::securityCompleted() +{ + state_ = RFBSTATE_INITIALISATION; + reader_ = new CMsgReaderV3(this, is); + writer_ = new CMsgWriterV3(&cp, os); + vlog.debug("Authentication success!"); + authSuccess(); + writer_->writeClientInit(shared); +} + +void CConnection::authSuccess() +{ +} + +void CConnection::serverInit() +{ + state_ = RFBSTATE_NORMAL; + vlog.debug("initialisation done"); +} diff --git a/rfb/CConnection.h b/rfb/CConnection.h new file mode 100644 index 00000000..480fca30 --- /dev/null +++ b/rfb/CConnection.h @@ -0,0 +1,178 @@ +/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ +// +// CConnection - class on the client side representing a connection to a +// server. A derived class should override methods appropriately. +// + +#ifndef __RFB_CCONNECTION_H__ +#define __RFB_CCONNECTION_H__ + +#include +#include +#include +#include + +namespace rfb { + + class CMsgReader; + class CMsgWriter; + class CSecurity; + class IdentityVerifier; + + class CConnection : public CMsgHandler { + public: + + CConnection(); + virtual ~CConnection(); + + // *** + void setServerName(const char* serverName_); + + // Methods to initialise the connection + + // setStreams() sets the streams to be used for the connection. These must + // be set before initialiseProtocol() and processMsg() are called. The + // CSecurity object may call setStreams() again to provide alternative + // streams over which the RFB protocol is sent (i.e. encrypting/decrypting + // streams). Ownership of the streams remains with the caller + // (i.e. SConnection will not delete them). + void setStreams(rdr::InStream* is, rdr::OutStream* os); + + // addSecType() should be called once for each security type which the + // client supports. The order in which they're added is such that the + // first one is most preferred. + void addSecType(rdr::U8 secType); + + // setClientSecTypeOrder() determines whether the client should obey + // the server's security type preference, by picking the first server security + // type that the client supports, or whether it should pick the first type + // that the server supports, from the client-supported list of types. + void setClientSecTypeOrder(bool clientOrder); + + // setShared sets the value of the shared flag which will be sent to the + // server upon initialisation. + void setShared(bool s) { shared = s; } + + // setProtocol3_3 configures whether or not the CConnection should + // only ever support protocol version 3.3 + void setProtocol3_3(bool s) {useProtocol3_3 = s;} + + // initialiseProtocol() should be called once the streams and security + // types are set. Subsequently, processMsg() should be called whenever + // there is data to read on the InStream. + void initialiseProtocol(); + + // processMsg() should be called whenever there is either: + // - data available on the underlying network stream + // In this case, processMsg may return without processing an RFB message, + // if the available data does not result in an RFB message being ready + // to handle. e.g. if data is encrypted. + // NB: This makes it safe to call processMsg() in response to select() + // - data available on the CConnection's current InStream + // In this case, processMsg should always process the available RFB + // message before returning. + // NB: In either case, you must have called initialiseProtocol() first. + void processMsg(); + + + // Methods to be overridden in a derived class + + // getCSecurity() gets the CSecurity object for the given type. The type + // is guaranteed to be one of the secTypes passed in to addSecType(). The + // CSecurity object's destroy() method will be called by the CConnection + // from its destructor. + virtual CSecurity* getCSecurity(int secType)=0; + + // getCurrentCSecurity() gets the CSecurity instance used for this connection. + const CSecurity* getCurrentCSecurity() const {return security;} + + // getIdVerifier() returns the identity verifier associated with the connection. + // Ownership of the IdentityVerifier is retained by the CConnection instance. + virtual IdentityVerifier* getIdentityVerifier() {return 0;} + + // authSuccess() is called when authentication has succeeded. + virtual void authSuccess(); + + // serverInit() is called when the ServerInit message is received. The + // derived class must call on to CConnection::serverInit(). + virtual void serverInit(); + + + // Other methods + + // deleteReaderAndWriter() deletes the reader and writer associated with + // this connection. This may be useful if you want to delete the streams + // before deleting the SConnection to make sure that no attempt by the + // SConnection is made to read or write. + // XXX Do we really need this at all??? + void deleteReaderAndWriter(); + + CMsgReader* reader() { return reader_; } + CMsgWriter* writer() { return writer_; } + + rdr::InStream* getInStream() { return is; } + rdr::OutStream* getOutStream() { return os; } + + char* getServerName() {return strDup(serverName.buf);} + + enum stateEnum { + RFBSTATE_UNINITIALISED, + RFBSTATE_PROTOCOL_VERSION, + RFBSTATE_SECURITY_TYPES, + RFBSTATE_SECURITY, + RFBSTATE_SECURITY_RESULT, + RFBSTATE_INITIALISATION, + RFBSTATE_NORMAL, + RFBSTATE_INVALID + }; + + stateEnum state() { return state_; } + + protected: + void setState(stateEnum s) { state_ = s; } + + private: + void processVersionMsg(); + void processSecurityTypesMsg(); + void processSecurityMsg(); + void processSecurityResultMsg(); + void processInitMsg(); + void throwAuthFailureException(); + void throwConnFailedException(); + void securityCompleted(); + + rdr::InStream* is; + rdr::OutStream* os; + CMsgReader* reader_; + CMsgWriter* writer_; + bool deleteStreamsWhenDone; + bool shared; + CSecurity* security; + enum { maxSecTypes = 8 }; + int nSecTypes; + rdr::U8 secTypes[maxSecTypes]; + bool clientSecTypeOrder; + stateEnum state_; + + CharArray serverName; + + bool useProtocol3_3; + }; +} +#endif diff --git a/rfb/CMsgHandler.cxx b/rfb/CMsgHandler.cxx new file mode 100644 index 00000000..10109169 --- /dev/null +++ b/rfb/CMsgHandler.cxx @@ -0,0 +1,99 @@ +/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ +#include +#include + +using namespace rfb; + +CMsgHandler::CMsgHandler() +{ +} + +CMsgHandler::~CMsgHandler() +{ +} + +void CMsgHandler::setDesktopSize(int width, int height) +{ + cp.width = width; + cp.height = height; +} + +void CMsgHandler::setCursor(const Point& hotspot, const Point& size, void* data, void* mask) +{ +} + +void CMsgHandler::setPixelFormat(const PixelFormat& pf) +{ + cp.setPF(pf); +} + +void CMsgHandler::setName(const char* name) +{ + cp.setName(name); +} + +void CMsgHandler::serverInit() +{ + throw Exception("CMsgHandler::serverInit called"); +} + +void CMsgHandler::framebufferUpdateStart() +{ +} + +void CMsgHandler::framebufferUpdateEnd() +{ +} + +void CMsgHandler::beginRect(const Rect& r, unsigned int encoding) +{ +} + +void CMsgHandler::endRect(const Rect& r, unsigned int encoding) +{ +} + + +void CMsgHandler::setColourMapEntries(int firstColour, int nColours, + rdr::U16* rgbs) +{ + throw Exception("CMsgHandler::setColourMapEntries called"); +} + +void CMsgHandler::bell() +{ +} + +void CMsgHandler::serverCutText(const char* str, int len) +{ +} + +void CMsgHandler::fillRect(const Rect& r, Pixel pix) +{ +} + +void CMsgHandler::imageRect(const Rect& r, void* pixels) +{ +} + +void CMsgHandler::copyRect(const Rect& r, int srcX, int srcY) +{ +} + + diff --git a/rfb/CMsgHandler.h b/rfb/CMsgHandler.h new file mode 100644 index 00000000..7a69f145 --- /dev/null +++ b/rfb/CMsgHandler.h @@ -0,0 +1,62 @@ +/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ +// +// CMsgHandler - class to handle incoming messages on the client side. +// + +#ifndef __RFB_CMSGHANDLER_H__ +#define __RFB_CMSGHANDLER_H__ + +#include +#include +#include +#include + +namespace rdr { class InStream; } + +namespace rfb { + + class CMsgHandler { + public: + CMsgHandler(); + virtual ~CMsgHandler(); + + virtual void setDesktopSize(int w, int h); + virtual void setCursor(const Point& hotspot, const Point& size, void* data, void* mask); + virtual void setPixelFormat(const PixelFormat& pf); + virtual void setName(const char* name); + virtual void serverInit(); + + virtual void framebufferUpdateStart(); + virtual void framebufferUpdateEnd(); + virtual void beginRect(const Rect& r, unsigned int encoding); + virtual void endRect(const Rect& r, unsigned int encoding); + + virtual void setColourMapEntries(int firstColour, int nColours, + rdr::U16* rgbs); + virtual void bell(); + virtual void serverCutText(const char* str, int len); + + virtual void fillRect(const Rect& r, Pixel pix); + virtual void imageRect(const Rect& r, void* pixels); + virtual void copyRect(const Rect& r, int srcX, int srcY); + + ConnParams cp; + }; +} +#endif diff --git a/rfb/CMsgReader.cxx b/rfb/CMsgReader.cxx new file mode 100644 index 00000000..46973eb2 --- /dev/null +++ b/rfb/CMsgReader.cxx @@ -0,0 +1,167 @@ +/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ +#include +#include +#include +#include +#include +#include + +using namespace rfb; + +CMsgReader::CMsgReader(CMsgHandler* handler_, rdr::InStream* is_) + : imageBufIdealSize(0), handler(handler_), is(is_), + imageBuf(0), imageBufSize(0) +{ + for (unsigned int i = 0; i <= encodingMax; i++) { + decoders[i] = 0; + } +} + +CMsgReader::~CMsgReader() +{ + for (unsigned int i = 0; i <= encodingMax; i++) { + delete decoders[i]; + } + delete [] imageBuf; +} + +void CMsgReader::endMsg() +{ +} + +void CMsgReader::readSetColourMapEntries() +{ + is->skip(1); + int firstColour = is->readU16(); + int nColours = is->readU16(); + rdr::U16Array rgbs(nColours * 3); + for (int i = 0; i < nColours * 3; i++) + rgbs.buf[i] = is->readU16(); + endMsg(); + handler->setColourMapEntries(firstColour, nColours, rgbs.buf); +} + +void CMsgReader::readBell() +{ + endMsg(); + handler->bell(); +} + +void CMsgReader::readServerCutText() +{ + is->skip(3); + int len = is->readU32(); + if (len > 256*1024) { + is->skip(len); + fprintf(stderr,"cut text too long (%d bytes) - ignoring\n",len); + return; + } + CharArray ca(len+1); + ca.buf[len] = 0; + is->readBytes(ca.buf, len); + endMsg(); + handler->serverCutText(ca.buf, len); +} + +void CMsgReader::readFramebufferUpdateStart() +{ + endMsg(); + handler->framebufferUpdateStart(); +} + +void CMsgReader::readFramebufferUpdateEnd() +{ + endMsg(); + handler->framebufferUpdateEnd(); +} + +void CMsgReader::readRect(const Rect& r, unsigned int encoding) +{ + if ((r.br.x > handler->cp.width) || (r.br.y > handler->cp.height)) { + fprintf(stderr, "Rect too big: %dx%d at %d,%d exceeds %dx%d\n", + r.width(), r.height(), r.tl.x, r.tl.y, + handler->cp.width, handler->cp.height); + throw Exception("Rect too big"); + } + + if (r.is_empty()) + fprintf(stderr, "Warning: zero size rect\n"); + + handler->beginRect(r, encoding); + + if (encoding == encodingCopyRect) { + readCopyRect(r); + } else { + if (!decoders[encoding]) { + decoders[encoding] = Decoder::createDecoder(encoding, this); + if (!decoders[encoding]) { + fprintf(stderr, "Unknown rect encoding %d\n", encoding); + throw Exception("Unknown rect encoding"); + } + } + decoders[encoding]->readRect(r, handler); + } + + handler->endRect(r, encoding); +} + +void CMsgReader::readCopyRect(const Rect& r) +{ + int srcX = is->readU16(); + int srcY = is->readU16(); + handler->copyRect(r, srcX, srcY); +} + +void CMsgReader::readSetCursor(const Point& hotspot, const Point& size) +{ + int data_len = size.x * size.y * (handler->cp.pf().bpp/8); + int mask_len = ((size.x+7)/8) * size.y; + rdr::U8Array data(data_len); + rdr::U8Array mask(mask_len); + + is->readBytes(data.buf, data_len); + is->readBytes(mask.buf, mask_len); + + handler->setCursor(hotspot, size, data.buf, mask.buf); +} + +rdr::U8* CMsgReader::getImageBuf(int required, int requested, int* nPixels) +{ + int requiredBytes = required * (handler->cp.pf().bpp / 8); + int requestedBytes = requested * (handler->cp.pf().bpp / 8); + int size = requestedBytes; + if (size > imageBufIdealSize) size = imageBufIdealSize; + + if (size < requiredBytes) + size = requiredBytes; + + if (imageBufSize < size) { + imageBufSize = size; + delete [] imageBuf; + imageBuf = new rdr::U8[imageBufSize]; + } + if (nPixels) + *nPixels = imageBufSize / (handler->cp.pf().bpp / 8); + return imageBuf; +} + +int CMsgReader::bpp() +{ + return handler->cp.pf().bpp; +} diff --git a/rfb/CMsgReader.h b/rfb/CMsgReader.h new file mode 100644 index 00000000..8b4638c7 --- /dev/null +++ b/rfb/CMsgReader.h @@ -0,0 +1,75 @@ +/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ +// +// CMsgReader - class for reading RFB messages on the server side +// (i.e. messages from client to server). +// + +#ifndef __RFB_CMSGREADER_H__ +#define __RFB_CMSGREADER_H__ + +#include +#include +#include + +namespace rdr { class InStream; } + +namespace rfb { + class CMsgHandler; + struct Rect; + + class CMsgReader { + public: + virtual ~CMsgReader(); + + virtual void readServerInit()=0; + + // readMsg() reads a message, calling the handler as appropriate. + virtual void readMsg()=0; + + rdr::InStream* getInStream() { return is; } + rdr::U8* getImageBuf(int required, int requested=0, int* nPixels=0); + int bpp(); + + int imageBufIdealSize; + + protected: + virtual void readSetColourMapEntries(); + virtual void readBell(); + virtual void readServerCutText(); + + virtual void endMsg(); + + virtual void readFramebufferUpdateStart(); + virtual void readFramebufferUpdateEnd(); + virtual void readRect(const Rect& r, unsigned int encoding); + + virtual void readCopyRect(const Rect& r); + + virtual void readSetCursor(const Point& hotspot, const Point& size); + + CMsgReader(CMsgHandler* handler, rdr::InStream* is); + + CMsgHandler* handler; + rdr::InStream* is; + Decoder* decoders[encodingMax+1]; + rdr::U8* imageBuf; + int imageBufSize; + }; +} +#endif diff --git a/rfb/CMsgReaderV3.cxx b/rfb/CMsgReaderV3.cxx new file mode 100644 index 00000000..1f974fd5 --- /dev/null +++ b/rfb/CMsgReaderV3.cxx @@ -0,0 +1,97 @@ +/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ +#include +#include +#include +#include +#include +#include + +using namespace rfb; + +CMsgReaderV3::CMsgReaderV3(CMsgHandler* handler, rdr::InStream* is) + : CMsgReader(handler, is), nUpdateRectsLeft(0) +{ +} + +CMsgReaderV3::~CMsgReaderV3() +{ +} + +void CMsgReaderV3::readServerInit() +{ + int width = is->readU16(); + int height = is->readU16(); + handler->setDesktopSize(width, height); + PixelFormat pf; + pf.read(is); + handler->setPixelFormat(pf); + char* name = is->readString(); + handler->setName(name); + delete [] name; + endMsg(); + handler->serverInit(); +} + +void CMsgReaderV3::readMsg() +{ + if (nUpdateRectsLeft == 0) { + + int type = is->readU8(); + switch (type) { + case msgTypeFramebufferUpdate: readFramebufferUpdate(); break; + case msgTypeSetColourMapEntries: readSetColourMapEntries(); break; + case msgTypeBell: readBell(); break; + case msgTypeServerCutText: readServerCutText(); break; + default: + fprintf(stderr, "unknown message type %d\n", type); + throw Exception("unknown message type"); + } + + } else { + + int x = is->readU16(); + int y = is->readU16(); + int w = is->readU16(); + int h = is->readU16(); + unsigned int encoding = is->readU32(); + + switch (encoding) { + case pseudoEncodingDesktopSize: + handler->setDesktopSize(w, h); + break; + case pseudoEncodingCursor: + readSetCursor(Point(x, y), Point(w, h)); + break; + default: + readRect(Rect(x, y, x+w, y+h), encoding); + break; + }; + + nUpdateRectsLeft--; + if (nUpdateRectsLeft == 0) handler->framebufferUpdateEnd(); + } +} + +void CMsgReaderV3::readFramebufferUpdate() +{ + is->skip(1); + nUpdateRectsLeft = is->readU16(); + endMsg(); + handler->framebufferUpdateStart(); +} diff --git a/rfb/CMsgReaderV3.h b/rfb/CMsgReaderV3.h new file mode 100644 index 00000000..93c8c6a5 --- /dev/null +++ b/rfb/CMsgReaderV3.h @@ -0,0 +1,35 @@ +/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ +#ifndef __RFB_CMSGREADERV3_H__ +#define __RFB_CMSGREADERV3_H__ + +#include + +namespace rfb { + class CMsgReaderV3 : public CMsgReader { + public: + CMsgReaderV3(CMsgHandler* handler, rdr::InStream* is); + virtual ~CMsgReaderV3(); + virtual void readServerInit(); + virtual void readMsg(); + private: + void readFramebufferUpdate(); + int nUpdateRectsLeft; + }; +} +#endif diff --git a/rfb/CMsgWriter.cxx b/rfb/CMsgWriter.cxx new file mode 100644 index 00000000..a7e4fb93 --- /dev/null +++ b/rfb/CMsgWriter.cxx @@ -0,0 +1,130 @@ +/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace rfb; + +CMsgWriter::CMsgWriter(ConnParams* cp_, rdr::OutStream* os_) + : cp(cp_), os(os_) +{ +} + +CMsgWriter::~CMsgWriter() +{ +} + +void CMsgWriter::writeSetPixelFormat(const PixelFormat& pf) +{ + startMsg(msgTypeSetPixelFormat); + os->pad(3); + pf.write(os); + endMsg(); +} + +void CMsgWriter::writeSetEncodings(int nEncodings, rdr::U32* encodings) +{ + startMsg(msgTypeSetEncodings); + os->skip(1); + os->writeU16(nEncodings); + for (int i = 0; i < nEncodings; i++) + os->writeU32(encodings[i]); + endMsg(); +} + +// Ask for encodings based on which decoders are supported. Assumes higher +// encoding numbers are more desirable. + +void CMsgWriter::writeSetEncodings(int preferredEncoding, bool useCopyRect) +{ + int nEncodings = 0; + rdr::U32 encodings[encodingMax+2]; + if (cp->supportsLocalCursor) + encodings[nEncodings++] = pseudoEncodingCursor; + if (cp->supportsDesktopResize) + encodings[nEncodings++] = pseudoEncodingDesktopSize; + if (Decoder::supported(preferredEncoding)) { + encodings[nEncodings++] = preferredEncoding; + } + if (useCopyRect) { + encodings[nEncodings++] = encodingCopyRect; + } + for (int i = encodingMax; i >= 0; i--) { + if (i != preferredEncoding && Decoder::supported(i)) { + encodings[nEncodings++] = i; + } + } + writeSetEncodings(nEncodings, encodings); +} + +void CMsgWriter::writeFramebufferUpdateRequest(const Rect& r, bool incremental) +{ + startMsg(msgTypeFramebufferUpdateRequest); + os->writeU8(incremental); + os->writeU16(r.tl.x); + os->writeU16(r.tl.y); + os->writeU16(r.width()); + os->writeU16(r.height()); + endMsg(); +} + + +void CMsgWriter::writeKeyEvent(rdr::U32 key, bool down) +{ + startMsg(msgTypeKeyEvent); + os->writeU8(down); + os->pad(2); + os->writeU32(key); + endMsg(); +} + + +void CMsgWriter::writePointerEvent(int x, int y, int buttonMask) +{ + if (x < 0) x = 0; + if (y < 0) y = 0; + if (x >= cp->width) x = cp->width - 1; + if (y >= cp->height) y = cp->height - 1; + + startMsg(msgTypePointerEvent); + os->writeU8(buttonMask); + os->writeU16(x); + os->writeU16(y); + endMsg(); +} + + +void CMsgWriter::writeClientCutText(const char* str, int len) +{ + startMsg(msgTypeClientCutText); + os->pad(3); + os->writeU32(len); + os->writeBytes(str, len); + endMsg(); +} + +void CMsgWriter::setOutStream(rdr::OutStream* os_) +{ + os = os_; +} diff --git a/rfb/CMsgWriter.h b/rfb/CMsgWriter.h new file mode 100644 index 00000000..8d6e373c --- /dev/null +++ b/rfb/CMsgWriter.h @@ -0,0 +1,64 @@ +/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ +// +// CMsgWriter - class for writing RFB messages on the server side. +// + +#ifndef __RFB_CMSGWRITER_H__ +#define __RFB_CMSGWRITER_H__ + +#include + +namespace rdr { class OutStream; } + +namespace rfb { + + class PixelFormat; + class ConnParams; + struct Rect; + + class CMsgWriter { + public: + virtual ~CMsgWriter(); + + virtual void writeClientInit(bool shared)=0; + + virtual void writeSetPixelFormat(const PixelFormat& pf); + virtual void writeSetEncodings(int nEncodings, rdr::U32* encodings); + virtual void writeSetEncodings(int preferredEncoding, bool useCopyRect); + virtual void writeFramebufferUpdateRequest(const Rect& r,bool incremental); + virtual void writeKeyEvent(rdr::U32 key, bool down); + virtual void writePointerEvent(int x, int y, int buttonMask); + virtual void writeClientCutText(const char* str, int len); + + virtual void startMsg(int type)=0; + virtual void endMsg()=0; + + virtual void setOutStream(rdr::OutStream* os); + + ConnParams* getConnParams() { return cp; } + rdr::OutStream* getOutStream() { return os; } + + protected: + CMsgWriter(ConnParams* cp, rdr::OutStream* os); + + ConnParams* cp; + rdr::OutStream* os; + }; +} +#endif diff --git a/rfb/CMsgWriterV3.cxx b/rfb/CMsgWriterV3.cxx new file mode 100644 index 00000000..a6ad237c --- /dev/null +++ b/rfb/CMsgWriterV3.cxx @@ -0,0 +1,49 @@ +/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ +#include +#include +#include +#include +#include + +using namespace rfb; + +CMsgWriterV3::CMsgWriterV3(ConnParams* cp, rdr::OutStream* os) + : CMsgWriter(cp, os) +{ +} + +CMsgWriterV3::~CMsgWriterV3() +{ +} + +void CMsgWriterV3::writeClientInit(bool shared) +{ + os->writeU8(shared); + endMsg(); +} + +void CMsgWriterV3::startMsg(int type) +{ + os->writeU8(type); +} + +void CMsgWriterV3::endMsg() +{ + os->flush(); +} diff --git a/rfb/CMsgWriterV3.h b/rfb/CMsgWriterV3.h new file mode 100644 index 00000000..0cf6157a --- /dev/null +++ b/rfb/CMsgWriterV3.h @@ -0,0 +1,35 @@ +/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ +#ifndef __RFB_CMSGWRITERV3_H__ +#define __RFB_CMSGWRITERV3_H__ + +#include + +namespace rfb { + class CMsgWriterV3 : public CMsgWriter { + public: + CMsgWriterV3(ConnParams* cp, rdr::OutStream* os); + virtual ~CMsgWriterV3(); + + virtual void writeClientInit(bool shared); + virtual void startMsg(int type); + virtual void endMsg(); + + }; +} +#endif diff --git a/rfb/CSecurity.h b/rfb/CSecurity.h new file mode 100644 index 00000000..639d550e --- /dev/null +++ b/rfb/CSecurity.h @@ -0,0 +1,48 @@ +/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ +// +// CSecurity - class on the client side for handling security handshaking. A +// derived class for a particular security type overrides the processMsg() +// method. processMsg() is called first when the security type has been +// decided on, and will keep being called whenever there is data to read from +// the server until either it returns false, indicating authentication/security +// failure, or it returns with done set to true, to indicate success. +// +// Note that the first time processMsg() is called, there is no guarantee that +// there is any data to read from the CConnection's InStream, but subsequent +// calls guarantee there is at least one byte which can be read without +// blocking. +// +// description is a string describing the level of encryption applied to the +// session, or null if no encryption will be used. + +#ifndef __RFB_CSECURITY_H__ +#define __RFB_CSECURITY_H__ + +namespace rfb { + class CConnection; + class CSecurity { + public: + virtual ~CSecurity() {} + virtual bool processMsg(CConnection* cc, bool* done)=0; + virtual void destroy() { delete this; } + virtual int getType() const = 0; + virtual const char* description() const = 0; + }; +} +#endif diff --git a/rfb/CSecurityNone.h b/rfb/CSecurityNone.h new file mode 100644 index 00000000..23b36cee --- /dev/null +++ b/rfb/CSecurityNone.h @@ -0,0 +1,38 @@ +/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ +// +// CSecurityNone.h +// + +#ifndef __CSECURITYNONE_H__ +#define __CSECURITYNONE_H__ + +#include + +namespace rfb { + + class CSecurityNone : public CSecurity { + public: + virtual bool processMsg(CConnection* cc, bool* done) { + *done = true; return true; + } + virtual int getType() const {return secTypeNone;} + virtual const char* description() const {return "No Encryption";} + }; +} +#endif diff --git a/rfb/CSecurityVncAuth.cxx b/rfb/CSecurityVncAuth.cxx new file mode 100644 index 00000000..3d6c87c5 --- /dev/null +++ b/rfb/CSecurityVncAuth.cxx @@ -0,0 +1,63 @@ +/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ +// +// CSecurityVncAuth +// + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace rfb; + +static LogWriter vlog("VncAuth"); + +CSecurityVncAuth::CSecurityVncAuth(UserPasswdGetter* upg_) + : upg(upg_) +{ +} + +CSecurityVncAuth::~CSecurityVncAuth() +{ +} + +bool CSecurityVncAuth::processMsg(CConnection* cc, bool* done) +{ + *done = false; + rdr::InStream* is = cc->getInStream(); + rdr::OutStream* os = cc->getOutStream(); + + rdr::U8 challenge[vncAuthChallengeSize]; + is->readBytes(challenge, vncAuthChallengeSize); + CharArray passwd; + if (!upg->getUserPasswd(0, &passwd.buf)) { + vlog.error("Getting password failed"); + return false; + } + vncAuthEncryptChallenge(challenge, passwd.buf); + memset(passwd.buf, 0, strlen(passwd.buf)); + os->writeBytes(challenge, vncAuthChallengeSize); + os->flush(); + *done = true; + return true; +} diff --git a/rfb/CSecurityVncAuth.h b/rfb/CSecurityVncAuth.h new file mode 100644 index 00000000..bfa40b3b --- /dev/null +++ b/rfb/CSecurityVncAuth.h @@ -0,0 +1,40 @@ +/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ +#ifndef __RFB_CSECURITYVNCAUTH_H__ +#define __RFB_CSECURITYVNCAUTH_H__ + +#include +#include +#include + +namespace rfb { + + class UserPasswdGetter; + + class CSecurityVncAuth : public CSecurity { + public: + CSecurityVncAuth(UserPasswdGetter* pg); + virtual ~CSecurityVncAuth(); + virtual bool processMsg(CConnection* cc, bool* done); + virtual int getType() const {return secTypeVncAuth;}; + virtual const char* description() const {return "No Encryption";} + private: + UserPasswdGetter* upg; + }; +} +#endif diff --git a/rfb/ColourCube.h b/rfb/ColourCube.h new file mode 100644 index 00000000..904256c4 --- /dev/null +++ b/rfb/ColourCube.h @@ -0,0 +1,96 @@ +/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ +// +// ColourCube - structure to represent a colour cube. The colour cube consists +// of its dimensions (nRed x nGreen x nBlue) and a table mapping an (r,g,b) +// triple to a pixel value. +// +// A colour cube is used in two cases. The first is internally in a viewer +// when it cannot use a trueColour format, nor can it have exclusive access to +// a writable colour map. This is most notably the case for an X viewer +// wishing to use a PseudoColor X server's default colormap. +// +// The second use is on the server side when a client has asked for a colour +// map and the server is trueColour. Instead of setting an uneven trueColour +// format like bgr233, it can set the client's colour map up with a 6x6x6 +// colour cube. For this use the colour cube table has a null mapping, which +// makes it easy to perform the reverse lookup operation from pixel value to +// r,g,b values. + +#ifndef __RFB_COLOURCUBE_H__ +#define __RFB_COLOURCUBE_H__ + +#include +#include + +namespace rfb { + + class ColourCube : public ColourMap { + public: + ColourCube(int nr, int ng, int nb, Pixel* table_=0) + : nRed(nr), nGreen(ng), nBlue(nb), table(table_), deleteTable(false) + { + if (!table) { + table = new Pixel[size()]; + deleteTable = true; + // set a null mapping by default + for (int i = 0; i < size(); i++) + table[i] = i; + } + } + + ColourCube() : deleteTable(false) {} + + virtual ~ColourCube() { + if (deleteTable) delete [] table; + } + + void set(int r, int g, int b, Pixel p) { + table[(r * nGreen + g) * nBlue + b] = p; + } + + Pixel lookup(int r, int g, int b) const { + return table[(r * nGreen + g) * nBlue + b]; + } + + int size() const { return nRed*nGreen*nBlue; } + int redMult() const { return nGreen*nBlue; } + int greenMult() const { return nBlue; } + int blueMult() const { return 1; } + + // ColourMap lookup() method. Note that this only works when the table has + // the default null mapping. + virtual void lookup(int i, int* r, int* g, int* b) { + if (i >= size()) return; + *b = i % nBlue; + i /= nBlue; + *g = i % nGreen; + *r = i / nGreen; + *r = (*r * 65535 + (nRed-1) / 2) / (nRed-1); + *g = (*g * 65535 + (nGreen-1) / 2) / (nGreen-1); + *b = (*b * 65535 + (nBlue-1) / 2) / (nBlue-1); + } + + int nRed; + int nGreen; + int nBlue; + Pixel* table; + bool deleteTable; + }; +} +#endif diff --git a/rfb/ColourMap.h b/rfb/ColourMap.h new file mode 100644 index 00000000..ee7783dc --- /dev/null +++ b/rfb/ColourMap.h @@ -0,0 +1,34 @@ +/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ +#ifndef __RFB_COLOURMAP_H__ +#define __RFB_COLOURMAP_H__ +namespace rfb { + struct Colour { + Colour() : r(0), g(0), b(0) {} + Colour(int r_, int g_, int b_) : r(r_), g(g_), b(b_) {} + int r, g, b; + bool operator==(const Colour& c) const {return c.r == r && c.g == g && c.b == b;} + bool operator!=(const Colour& c) const {return !(c == *this);} + }; + + class ColourMap { + public: + virtual void lookup(int index, int* r, int* g, int* b)=0; + }; +} +#endif diff --git a/rfb/ComparingUpdateTracker.cxx b/rfb/ComparingUpdateTracker.cxx new file mode 100644 index 00000000..0c44d85a --- /dev/null +++ b/rfb/ComparingUpdateTracker.cxx @@ -0,0 +1,151 @@ +/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ +#include +#include +#include +#include +#include + +using namespace rfb; + +ComparingUpdateTracker::ComparingUpdateTracker(PixelBuffer* buffer) + : SimpleUpdateTracker(true), fb(buffer), + oldFb(fb->getPF(), 0, 0), firstCompare(true) +{ + changed.assign_union(fb->getRect()); +} + +ComparingUpdateTracker::~ComparingUpdateTracker() +{ +} + + +void ComparingUpdateTracker::flush_update(UpdateInfo* info, + const Region& cliprgn, int maxArea) +{ + throw rfb::Exception("flush_update(UpdateInfo*) not implemented"); +} + +void ComparingUpdateTracker::flush_update(UpdateTracker &ut, + const Region &cliprgn) +{ + throw rfb::Exception("flush_update(UpdateTracker&) not implemented"); +} + + +#define BLOCK_SIZE 16 + +void ComparingUpdateTracker::compare() +{ + std::vector rects; + std::vector::iterator i; + + if (firstCompare) { + // NB: We leave the change region untouched on this iteration, + // since in effect the entire framebuffer has changed. + oldFb.setSize(fb->width(), fb->height()); + for (int y=0; yheight(); y+=BLOCK_SIZE) { + Rect pos(0, y, fb->width(), min(fb->height(), y+BLOCK_SIZE)); + int srcStride; + const rdr::U8* srcData = fb->getPixelsR(pos, &srcStride); + oldFb.imageRect(pos, srcData, srcStride); + } + firstCompare = false; + } else { + copied.get_rects(&rects, copy_delta.x<=0, copy_delta.y<=0); + for (i = rects.begin(); i != rects.end(); i++) + oldFb.copyRect(*i, copy_delta); + + Region to_check = changed.union_(copied); + to_check.get_rects(&rects); + + Region newChanged; + for (i = rects.begin(); i != rects.end(); i++) + compareRect(*i, &newChanged); + + copied.assign_subtract(newChanged); + changed = newChanged; + } +} + +void ComparingUpdateTracker::compareRect(const Rect& r, Region* newChanged) +{ + if (!r.enclosed_by(fb->getRect())) { + fprintf(stderr,"ComparingUpdateTracker: rect outside fb (%d,%d-%d,%d)\n", r.tl.x, r.tl.y, r.br.x, r.br.y); + return; + } + + int bytesPerPixel = fb->getPF().bpp/8; + int oldStride; + rdr::U8* oldData = oldFb.getPixelsRW(r, &oldStride); + int oldStrideBytes = oldStride * bytesPerPixel; + + std::vector changedBlocks; + + for (int blockTop = r.tl.y; blockTop < r.br.y; blockTop += BLOCK_SIZE) + { + // Get a strip of the source buffer + Rect pos(r.tl.x, blockTop, r.br.x, min(r.br.y, blockTop+BLOCK_SIZE)); + int fbStride; + const rdr::U8* newBlockPtr = fb->getPixelsR(pos, &fbStride); + int newStrideBytes = fbStride * bytesPerPixel; + + rdr::U8* oldBlockPtr = oldData; + int blockBottom = min(blockTop+BLOCK_SIZE, r.br.y); + + for (int blockLeft = r.tl.x; blockLeft < r.br.x; blockLeft += BLOCK_SIZE) + { + const rdr::U8* newPtr = newBlockPtr; + rdr::U8* oldPtr = oldBlockPtr; + + int blockRight = min(blockLeft+BLOCK_SIZE, r.br.x); + int blockWidthInBytes = (blockRight-blockLeft) * bytesPerPixel; + + for (int y = blockTop; y < blockBottom; y++) + { + if (memcmp(oldPtr, newPtr, blockWidthInBytes) != 0) + { + // A block has changed - copy the remainder to the oldFb + changedBlocks.push_back(Rect(blockLeft, blockTop, + blockRight, blockBottom)); + for (int y2 = y; y2 < blockBottom; y2++) + { + memcpy(oldPtr, newPtr, blockWidthInBytes); + newPtr += newStrideBytes; + oldPtr += oldStrideBytes; + } + break; + } + + newPtr += newStrideBytes; + oldPtr += oldStrideBytes; + } + + oldBlockPtr += blockWidthInBytes; + newBlockPtr += blockWidthInBytes; + } + + oldData += oldStrideBytes * BLOCK_SIZE; + } + + if (!changedBlocks.empty()) { + Region temp; + temp.setOrderedRects(changedBlocks); + newChanged->assign_union(temp); + } +} diff --git a/rfb/ComparingUpdateTracker.h b/rfb/ComparingUpdateTracker.h new file mode 100644 index 00000000..bec93d1f --- /dev/null +++ b/rfb/ComparingUpdateTracker.h @@ -0,0 +1,47 @@ +/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#ifndef __RFB_COMPARINGUPDATETRACKER_H__ +#define __RFB_COMPARINGUPDATETRACKER_H__ + +#include + +namespace rfb { + + class ComparingUpdateTracker : public SimpleUpdateTracker { + public: + ComparingUpdateTracker(PixelBuffer* buffer); + ~ComparingUpdateTracker(); + + // compare() does the comparison and reduces its changed and copied regions + // as appropriate. + + virtual void compare(); + + virtual void flush_update(UpdateInfo* info, const Region& cliprgn, + int maxArea); + virtual void flush_update(UpdateTracker &info, const Region &cliprgn); + private: + void compareRect(const Rect& r, Region* newchanged); + PixelBuffer* fb; + ManagedPixelBuffer oldFb; + bool firstCompare; + }; + +} +#endif diff --git a/rfb/Configuration.cxx b/rfb/Configuration.cxx new file mode 100644 index 00000000..048fb77d --- /dev/null +++ b/rfb/Configuration.cxx @@ -0,0 +1,410 @@ +/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +// -=- Configuration.cxx + +#include +#include +#include +#include +#ifdef WIN32 +#define strcasecmp _stricmp +#define strncasecmp _strnicmp +#endif + +#include +#include +#include +#include + +#ifdef WIN32 + +// Under Win32, we use these routines from several threads, +// so we must provide suitable locking. +#include + +static rfb::Mutex configLock; + +#endif + +#include +#include + +using namespace rfb; + +static LogWriter vlog("Config"); + + +// -=- Configuration + +VoidParameter* Configuration::head = 0; + +bool Configuration::setParam(const char* n, const char* v, bool immutable) { + return setParam(n, strlen(n), v, immutable); +} + +bool Configuration::setParam(const char* name, int len, + const char* val, bool immutable) +{ + VoidParameter* current = head; + while (current) { + if ((int)strlen(current->getName()) == len && + strncasecmp(current->getName(), name, len) == 0) + { + bool b = current->setParam(val); + if (b && immutable) + current->setImmutable(); + return b; + } + current = current->_next; + } + return false; +} + +bool Configuration::setParam(const char* config, bool immutable) { + bool hyphen = false; + if (config[0] == '-') { + hyphen = true; + config++; + if (config[0] == '-') config++; // allow gnu-style --