├── NEWS ├── debian ├── compat ├── source │ └── format ├── watch ├── README.Debian ├── autogen.sh ├── control ├── copyright ├── rules └── changelog ├── TODO ├── AUTHORS ├── Makefile.am ├── directvnc-xmapconv.1 ├── src ├── directvnc-xmapconv ├── Makefile.am ├── debug.h ├── vncauth.h ├── tight.h ├── d3des.h ├── jpeg.h ├── keysym.h ├── main.c ├── vncauth.c ├── getopt.h ├── jpeg.c ├── getopt1.c ├── directvnc.h ├── modmap.c ├── sockets.c ├── args.c ├── cursor.c ├── tight.c ├── d3des.c ├── dfb.c └── rfb.c ├── THANKS ├── README ├── configure.in ├── config.h.in ├── directvnc.spec ├── directvnc-kbmapping.7 ├── directvnc.1 ├── changelog ├── INSTALL └── COPYING /NEWS: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /debian/compat: -------------------------------------------------------------------------------- 1 | 7 2 | -------------------------------------------------------------------------------- /debian/source/format: -------------------------------------------------------------------------------- 1 | 3.0 (quilt) 2 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | - look at the three patches received from Till 2 | - look at wishlist items listed in Debian Bugs (http://bugs.debian.org/cgi-bin/pkgreport.cgi?package=directvnc#_0_6_4) 3 | -------------------------------------------------------------------------------- /debian/watch: -------------------------------------------------------------------------------- 1 | version=3 2 | 3 | # direct access is forbidden... 4 | #http://cloud.github.com/downloads/drinkmilk/directvnc/directvnc-(.*)\.tar\.gz 5 | 6 | # ... so we scan the home page instead 7 | http://github.com/drinkmilk/directvnc/downloads \ 8 | /downloads/drinkmilk/directvnc/directvnc-([\d\.]*).tar.gz 9 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Original author: 2 | Till Adam 3 | 4 | Directvnc revival from 2010: 5 | Loris Boillet 6 | 7 | Head chief senior build engineer and release supervisor (up to 2003): 8 | Arnaud Launay 9 | 10 | This contains code from both the original AT&T implementation and the tightvnc 11 | implementation by Constantin Kaplinsky . 12 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | ## Process this file with automake to produce Makefile.in 2 | 3 | AUTOMAKE_OPTIONS = 1.4 foreign 4 | 5 | # A list of all the files in the current directory which can be regenerated 6 | MAINTAINERCLEANFILES = Makefile.in 7 | 8 | man_MANS = directvnc.1 directvnc-xmapconv.1 directvnc-kbmapping.7 9 | 10 | docs_DATA = README AUTHORS changelog 11 | docsdir = $(prefix)/share/doc/@PACKAGE@ 12 | 13 | EXTRA_DIST = \ 14 | $(man_MANS) \ 15 | $(docs_DATA) \ 16 | directvnc.spec 17 | 18 | SUBDIRS = src 19 | -------------------------------------------------------------------------------- /debian/README.Debian: -------------------------------------------------------------------------------- 1 | directvnc for Debian 2 | -------------------- 3 | 4 | To be able to run this software you need access to the /dev/fb0 device 5 | so the user needs to be in the video group. The user will also need 6 | access to /dev/mouse or /dev/psaux to be able to run directvnc. 7 | 8 | Also note that access to /dev/tty0 will be needed if more than one 9 | directFB app is used at the same time. 10 | 11 | Originally by Ola Lundqvist 12 | Modified by Loris Boillet 13 | -------------------------------------------------------------------------------- /directvnc-xmapconv.1: -------------------------------------------------------------------------------- 1 | .TH directvnc-xmapconv 1 "Jul 30, 2011" 2 | .SH NAME 3 | directvnc-xmapconv - produce directvnc's xmodmap keyboard layout files 4 | .SH SYNOPSIS 5 | directvnc-xmodmap 6 | .SH DESCRIPTION 7 | directvnc-xmapconv reads an xmodmap syntax file from standard input, and writes 8 | the directvnc compatible syntax file to standard output. Inside, the script 9 | runs its standard input through the C preprocessor including the keysymdef.h 10 | file and prepending each keysym identifier with XK_. The directvnc keyboard 11 | layout file mentioned earlier was produced exactly this way out of the xmodmap 12 | file for Cyrillic input. 13 | 14 | .SH SEE ALSO 15 | directvnc-kbmapping(7), directvnc(1), xmodmap(1) 16 | 17 | .SH AUTHORS 18 | Dimitry Golubovsky, Loris Boillet 19 | 20 | .br 21 | -------------------------------------------------------------------------------- /src/directvnc-xmapconv: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # A script to convert a xmodmap-style file into one that directvnc understands. 4 | # The file is passed through the C preprocessor to convert character keysyms 5 | # to their numeric equivalents. 6 | 7 | # The script reads the xmodmap file on its stdin and outputs directvnc-compatible 8 | # on its stdout. 9 | 10 | KEYSYMDEF=/usr/include/X11/keysymdef.h 11 | 12 | if [ ! -r $KEYSYMDEF ]; then 13 | echo "$0: $KEYSYMDEF does not exist. You may need to install X11 core wire protocol headers." 14 | exit 1; 15 | fi 16 | 17 | FORCEDEFS=`grep '^#ifdef' $KEYSYMDEF | sed 's/#ifdef */-D/g'` 18 | 19 | grep '^ *keycode' | sed 's/=//g' | awk ' 20 | { 21 | for(i=3;i<=NF;i++) { 22 | $i="XK_" $i; 23 | } 24 | print 25 | }' | cpp -P $FORCEDEFS -imacros $KEYSYMDEF - 26 | -------------------------------------------------------------------------------- /debian/autogen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # autogen.sh glue 4 | # 5 | # Requires: automake 1.9, autoconf 2.57+, libtool 1.5.6+ 6 | # Conflicts: autoconf 2.13 7 | set -e 8 | 9 | # Refresh GNU autotools toolchain. 10 | echo Cleaning autotools files... 11 | find -type d -name autom4te.cache -print0 | xargs -0 rm -rf \; 12 | find -type f \( -name missing -o -name install-sh -o -name mkinstalldirs \ 13 | -o -name depcomp -o -name ltmain.sh -o -name configure \ 14 | -o -name config.sub -o -name config.guess -o -name config.cache \ 15 | -o -name config.log -o -name Makefile.in \) -print0 | xargs -0 rm -f 16 | 17 | echo Running autoreconf... 18 | autoreconf --force --install 19 | 20 | # For the Debian package build 21 | test -d debian && { 22 | # link these in Debian builds 23 | rm -f config.sub config.guess 24 | ln -s /usr/share/misc/config.sub . 25 | ln -s /usr/share/misc/config.guess . 26 | } 27 | exit 0 28 | -------------------------------------------------------------------------------- /src/Makefile.am: -------------------------------------------------------------------------------- 1 | # A list of all the files in the current directory which can be regenerated 2 | MAINTAINERCLEANFILES = Makefile.in 3 | 4 | #DEBUGFLAGS = -DDEBUG -DDEBUG_NEST 5 | 6 | AM_LDFLAGS = @DIRECTFB_LIBS@ 7 | AM_CFLAGS = -Wall @DIRECTFB_CFLAGS@ $(DEBUGFLAGS) 8 | 9 | LIBOBJS = @LIBOBJS@ 10 | 11 | bin_PROGRAMS = directvnc 12 | directvnc_SOURCES = main.c debug.h dfb.c directvnc.h sockets.c args.c \ 13 | rfb.c getopt.c getopt1.c getopt.h \ 14 | d3des.c d3des.h vncauth.c vncauth.h jpeg.c jpeg.h \ 15 | tight.c tight.h rfbproto.h keysym.h \ 16 | cursor.c modmap.c 17 | 18 | bin_SCRIPTS = directvnc-xmapconv 19 | 20 | # setuid root. Is this really necessary? I cant access my framebuffer 21 | # otherwise. 22 | # 23 | # install-exec-hook: 24 | # chown root $(bindir)/directvnc 25 | # chmod u+s $(bindir)/directvnc 26 | # 27 | 28 | -------------------------------------------------------------------------------- /debian/control: -------------------------------------------------------------------------------- 1 | Source: directvnc 2 | Section: misc 3 | Priority: optional 4 | Maintainer: Loris Boillet 5 | Build-Depends: debhelper (>= 7), libdirectfb-dev (>= 0.9.24), zlib1g-dev, libjpeg-dev, pkg-config, x11proto-core-dev, autotools-dev, autoconf, automake, libtool 6 | Standards-Version: 3.9.2 7 | Homepage: http://drinkmilk.github.com/directvnc/ 8 | 9 | Package: directvnc 10 | Architecture: any 11 | Depends: ${shlibs:Depends}, ${misc:Depends} 12 | Recommends: x11proto-core-dev 13 | Description: VNC client using the framebuffer as display 14 | DirectVNC is a client implementing the remote framebuffer protocol (rfb) 15 | which is used by VNC servers. If a VNC server is running on a machine you 16 | can connect to it using this client and have the contents of its display 17 | shown on your screen. Keyboard and mouse events are sent to the server, so 18 | you can basically control a VNC server remotely. 19 | -------------------------------------------------------------------------------- /THANKS: -------------------------------------------------------------------------------- 1 | - the stuff in socket.c is taken from the original AT&T unix vnciewer as are 2 | the files related to vnc-auth (d3des.c d3des.h and vncauth.c) 3 | 4 | - the tight implementation is largely copied form the tight vnc distribution 5 | by Constantin Kaplinsky 6 | 7 | - A big thank you to the creators of the DirectFB library for their help and 8 | patience with my questions and suggestions. Denis Oliver Kropp and Andreas 9 | Hundt in particular. 10 | 11 | - Also thanks to Yasin Taskin for rpm debugging and beta testing 12 | 13 | - Ovidiu Damian did the debian infrastructure. Many thanks for that. 14 | 15 | - Miguel Sofer sent a patch moving endianess adjustment 16 | calculations from runtime to compile time 17 | 18 | - Arnaud Launay cleaned up the build process and helped 19 | with releasing. Many thanks. 20 | 21 | - Thanks to Dimitry Golubovsky for adding Keyboard 22 | Layout Switching and 24bpp support 23 | 24 | The following people provided helpfull suggestions, tips or reported bugs. 25 | Thanks a lot: 26 | 27 | Bitt Faulk 28 | Evan Langlois 29 | 30 | -------------------------------------------------------------------------------- /src/debug.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2001 Till Adam 3 | * Authors: Till Adam 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, a copy can be downloaded from 17 | * http://www.gnu.org/licenses/gpl.html, or obtained by writing to the 18 | * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 | * Boston, MA 02110-1301, USA. 20 | */ 21 | 22 | 23 | #ifndef DEBUG_H 24 | #define DEBUG_H 25 | 26 | #define DEBUG 27 | 28 | #ifdef WITH_DMALLOC 29 | #include 30 | #define emalloc(a) malloc(a) 31 | #define estrdup(a) strdup(a) 32 | #define erealloc(a,b) realloc(a,b) 33 | #else 34 | #define emalloc(a) _emalloc(a) 35 | #define estrdup(a) _estrdup(a) 36 | #define erealloc(a,b) _erealloc(a,b) 37 | #endif 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /src/vncauth.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. 3 | * 4 | * This is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This software is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, a copy can be downloaded from 16 | * http://www.gnu.org/licenses/gpl.html, or obtained by writing to the 17 | * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 18 | * Boston, MA 02110-1301, USA. 19 | */ 20 | 21 | /* 22 | * vncauth.h - describes the functions provided by the vncauth library. 23 | */ 24 | 25 | #define MAXPWLEN 8 26 | #define CHALLENGESIZE 16 27 | 28 | extern int vncEncryptAndStorePasswd(char *passwd, char *fname); 29 | extern char *vncDecryptPasswdFromFile(char *fname); 30 | extern void vncRandomBytes(unsigned char *bytes); 31 | extern void vncEncryptBytes(unsigned char *bytes, char *passwd); 32 | -------------------------------------------------------------------------------- /debian/copyright: -------------------------------------------------------------------------------- 1 | This package was debianized by: 2 | Ola Lundqvist on Sun, 31 Aug 2003 14:41:29 +0200. 3 | Maintained by Loris Boillet since 2010. 4 | 5 | It was downloaded from: 6 | http://github.com/drinkmilk/directvnc 7 | 8 | Upstream Author: 9 | Main author: 10 | Till Adam 11 | 12 | Head chief senior build engineer and release supervisor: 13 | Arnaud Launay 14 | 15 | Maintenance release from 2010: 16 | Loris Boillet 17 | 18 | This contains code from both the original AT&T implementation and the tightvnc 19 | implementation by Constantin Kaplinsky . 20 | 21 | Copyright (C) 2002 Free Software Foundation, Inc. 22 | 23 | This program is free software; you can redistribute it and/or modify 24 | it under the terms of the GNU General Public License as published by 25 | the Free Software Foundation; either version 2, or (at your option) 26 | any later version. 27 | 28 | This program is distributed in the hope that it will be useful, 29 | but WITHOUT ANY WARRANTY; without even the implied warranty of 30 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 31 | GNU General Public License for more details. 32 | 33 | On Debian systems, the complete text of the GNU General Public License 34 | may be found in `/usr/share/common-licenses/GPL-2'. 35 | -------------------------------------------------------------------------------- /src/tight.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2000, 2001 Const Kaplinsky. All Rights Reserved. 3 | * 4 | * This is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This software is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, a copy can be downloaded from 16 | * http://www.gnu.org/licenses/gpl.html, or obtained by writing to the 17 | * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 18 | * Boston, MA 02110-1301, USA. 19 | */ 20 | 21 | /* Type declarations for tight */ 22 | 23 | typedef void (*filterPtr)(int, void *, void *); 24 | 25 | /* Prototypes for tight*/ 26 | 27 | int InitFilterCopy (int rw, int rh); 28 | int InitFilterPalette (int rw, int rh); 29 | int InitFilterGradient (int rw, int rh); 30 | void FilterCopy (int numRows, void* srcBuffer, void *destBuffer); 31 | void FilterPalette (int numRows, void* srcBuffer, void *destBuffer); 32 | void FilterGradient (int numRows, void* srcBuffer, void *destBuffer); 33 | 34 | int _handle_tight_encoded_message(rfbFramebufferUpdateRectHeader rectheader); 35 | int _handle_zlib_encoded_message(rfbFramebufferUpdateRectHeader rectheader); 36 | 37 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | DirectVNC README 2 | ------------ 3 | 4 | DirectVNC is a client implementing the remote framebuffer protocol (rfb) 5 | which is used by VNC servers. If a VNC server is running on a machine you 6 | can connect to it using this client and have the contents of its display 7 | shown on your screen. Keyboard and mouse events are sent to the server, so 8 | you can basically control a VNC server remotely. There are servers (and 9 | other clients) freely available for all operating systems. 10 | 11 | What makes DirectVNC different from other unix vnc clients is that it uses 12 | the linux framebuffer device through the DirectFB library which enables it 13 | to run on anything that has a framebuffer without the need for a running X 14 | server. This includes embedded devices. DirectFB even uses acceleration 15 | features of certain graphics cards. Find out all about DirectFB here: 16 | 17 | www.directfb.org 18 | 19 | DirectVNC basically provides a very thin VNC client for unix framebuffer 20 | systems. 21 | 22 | Usage 23 | ----- 24 | directvnc server[:display#] [options] 25 | 26 | The server can be an IP address or a hostname. For a complete list of 27 | options see the man page or type directvnc -h. 28 | 29 | Quitting 30 | -------- 31 | quits the client 32 | 33 | Requirements 34 | ------------ 35 | - DirectFB library available from convergence integrated media 36 | (www.directfb.org) 37 | - Linux kernel (>= 2.6.x) with working framebuffer device (check /proc/fb). 38 | 39 | See COPYING for license information and INSTALL for generic installation 40 | instructions. 41 | -------------------------------------------------------------------------------- /src/d3des.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This is D3DES (V5.09) by Richard Outerbridge with the double and 3 | * triple-length support removed for use in VNC. 4 | * 5 | * These changes are: 6 | * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. 7 | * 8 | * This software is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 11 | */ 12 | 13 | /* d3des.h - 14 | * 15 | * Headers and defines for d3des.c 16 | * Graven Imagery, 1992. 17 | * 18 | * Copyright (c) 1988,1989,1990,1991,1992 by Richard Outerbridge 19 | * (GEnie : OUTER; CIS : [71755,204]) 20 | */ 21 | 22 | #define EN0 0 /* MODE == encrypt */ 23 | #define DE1 1 /* MODE == decrypt */ 24 | 25 | extern void deskey(unsigned char *, int); 26 | /* hexkey[8] MODE 27 | * Sets the internal key register according to the hexadecimal 28 | * key contained in the 8 bytes of hexkey, according to the DES, 29 | * for encryption or decryption according to MODE. 30 | */ 31 | 32 | extern void usekey(unsigned long *); 33 | /* cookedkey[32] 34 | * Loads the internal key register with the data in cookedkey. 35 | */ 36 | 37 | extern void cpkey(unsigned long *); 38 | /* cookedkey[32] 39 | * Copies the contents of the internal key register into the storage 40 | * located at &cookedkey[0]. 41 | */ 42 | 43 | extern void des(unsigned char *, unsigned char *); 44 | /* from[8] to[8] 45 | * Encrypts/Decrypts (according to the key currently loaded in the 46 | * internal key register) one block of eight bytes at address 'from' 47 | * into the block at address 'to'. They can be the same. 48 | */ 49 | 50 | /* d3des.h V5.09 rwo 9208.04 15:06 Graven Imagery 51 | ********************************************************************/ 52 | -------------------------------------------------------------------------------- /configure.in: -------------------------------------------------------------------------------- 1 | dnl Process this file with autoconf to create configure. 2 | 3 | AC_INIT(src/main.c) 4 | AM_INIT_AUTOMAKE(directvnc, 0.7.7) 5 | AM_CONFIG_HEADER(config.h) 6 | 7 | AC_ISC_POSIX 8 | AC_PROG_CC 9 | AM_PROG_CC_STDC 10 | AC_HEADER_STDC 11 | AC_PROG_INSTALL 12 | AC_PROG_CXX 13 | 14 | AM_ENABLE_SHARED 15 | dnl AM_DISABLE_STATIC 16 | AC_LIBTOOL_DLOPEN 17 | AM_PROG_LIBTOOL 18 | AM_WITH_DMALLOC 19 | 20 | if test "X$enable_shared" = "Xyes"; then 21 | DLLDFLAGS=-export-dynamic 22 | AC_SUBST(DLLDFLAGS) 23 | fi 24 | 25 | 26 | LIBS="$LIBS -lm" 27 | 28 | 29 | dnl check for libjpeg 30 | AC_CHECK_LIB(jpeg, jpeg_destroy_decompress, 31 | [ 32 | AC_CHECK_HEADER(jpeglib.h, 33 | [ 34 | LIBS="$LIBS -ljpeg" 35 | ], 36 | AC_MSG_WARN([***JPEGheader files not found.]) 37 | ) 38 | ], 39 | AC_MSG_WARN([*** JPEG library not found.]) 40 | ) 41 | 42 | dnl Test for libz 43 | AC_CHECK_LIB(z, gzsetparams, 44 | [ 45 | AC_CHECK_HEADER(zlib.h, 46 | [ 47 | LIBS="$LIBS -lz" 48 | ], 49 | AC_MSG_WARN([*** libz header files not found.]) 50 | ) 51 | ], 52 | [ 53 | AC_MSG_WARN([*** libz not found.]) 54 | ] 55 | ) 56 | 57 | # 58 | # Find pkg-config needed for DFB 59 | # 60 | AC_PATH_PROG(PKG_CONFIG, pkg-config) 61 | if test -z "${PKG_CONFIG}"; then 62 | AC_MSG_ERROR([*** pkg-config not found. See http://pkgconfig.sourceforge.net]) 63 | fi 64 | 65 | if ! ${PKG_CONFIG} --atleast-pkgconfig-version 0.5 >/dev/null ; then 66 | AC_MSG_ERROR([*** pkg-config too old; version 0.5 or better required.]) 67 | fi 68 | 69 | 70 | # 71 | # Check for DirectFB 72 | # 73 | PKG_CHECK_MODULES(DIRECTFB, directfb >= 0.9.24) 74 | 75 | AC_CHECK_FUNCS([getopt getopt_long]) 76 | 77 | AC_OUTPUT([ 78 | Makefile 79 | src/Makefile 80 | ]) 81 | -------------------------------------------------------------------------------- /config.h.in: -------------------------------------------------------------------------------- 1 | /* config.h.in. Generated from configure.in by autoheader. */ 2 | 3 | /* Define to 1 if you have the header file. */ 4 | #undef HAVE_DLFCN_H 5 | 6 | /* Define to 1 if you have the `getopt' function. */ 7 | #undef HAVE_GETOPT 8 | 9 | /* Define to 1 if you have the `getopt_long' function. */ 10 | #undef HAVE_GETOPT_LONG 11 | 12 | /* Define to 1 if you have the header file. */ 13 | #undef HAVE_INTTYPES_H 14 | 15 | /* Define to 1 if you have the header file. */ 16 | #undef HAVE_MEMORY_H 17 | 18 | /* Define to 1 if you have the header file. */ 19 | #undef HAVE_STDINT_H 20 | 21 | /* Define to 1 if you have the header file. */ 22 | #undef HAVE_STDLIB_H 23 | 24 | /* Define to 1 if you have the header file. */ 25 | #undef HAVE_STRINGS_H 26 | 27 | /* Define to 1 if you have the header file. */ 28 | #undef HAVE_STRING_H 29 | 30 | /* Define to 1 if you have the header file. */ 31 | #undef HAVE_SYS_STAT_H 32 | 33 | /* Define to 1 if you have the header file. */ 34 | #undef HAVE_SYS_TYPES_H 35 | 36 | /* Define to 1 if you have the header file. */ 37 | #undef HAVE_UNISTD_H 38 | 39 | /* Define to the sub-directory in which libtool stores uninstalled libraries. 40 | */ 41 | #undef LT_OBJDIR 42 | 43 | /* Name of package */ 44 | #undef PACKAGE 45 | 46 | /* Define to the address where bug reports for this package should be sent. */ 47 | #undef PACKAGE_BUGREPORT 48 | 49 | /* Define to the full name of this package. */ 50 | #undef PACKAGE_NAME 51 | 52 | /* Define to the full name and version of this package. */ 53 | #undef PACKAGE_STRING 54 | 55 | /* Define to the one symbol short name of this package. */ 56 | #undef PACKAGE_TARNAME 57 | 58 | /* Define to the home page for this package. */ 59 | #undef PACKAGE_URL 60 | 61 | /* Define to the version of this package. */ 62 | #undef PACKAGE_VERSION 63 | 64 | /* Define to 1 if you have the ANSI C header files. */ 65 | #undef STDC_HEADERS 66 | 67 | /* Version number of package */ 68 | #undef VERSION 69 | 70 | /* Define if using the dmalloc debugging malloc package */ 71 | #undef WITH_DMALLOC 72 | -------------------------------------------------------------------------------- /directvnc.spec: -------------------------------------------------------------------------------- 1 | %define name directvnc 2 | %define version 0.7.7 3 | %define release 1 4 | 5 | Summary: VNC client for the GNU/Linux framebuffer device using the DirectFB library. 6 | Name: %{name} 7 | Version: %{version} 8 | Release: %{release} 9 | Source: http://cloud.github.com/downloads/drinkmilk/directvnc/%{name}-%{version}.tar.gz 10 | Url: http://drinkmilk.github.com/directvnc 11 | License: GPL 12 | Group: Networking/Remote Access 13 | BuildRoot: %{_tmppath}/%{name}-buildroot 14 | Prefix: %{_prefix} 15 | Requires: libdirectfb >= 0.9.24 16 | 17 | %description 18 | DirectVNC is a client implementing the remote framebuffer protocol (rfb) 19 | which is used by VNC servers. If a VNC server is running on a machine you 20 | can connect to it using this client and have the contents of its display 21 | shown on your screen. Keyboard and mouse events are sent to the server, so 22 | you can basically control a VNC server remotely. There are servers (and 23 | other clients) freely available for all operating systems. To find out more 24 | about VNC check out its home on the web at AT&T labs. 25 | 26 | www.uk.research.att.com/vnc/ 27 | 28 | What makes DirectVNC different from other unix vnc clients is that it uses 29 | the linux framebuffer device through the DirectFB library which enables it 30 | to run on anything that has a framebuffer without the need for a running X 31 | server. This includes embedded devices. DirectFB even uses acceleration 32 | features of certain graphics cards. Find out all about DirectFB here: 33 | 34 | www.directfb.org 35 | 36 | DirectVNC basically provides a very thin VNC client for unix framebuffer 37 | systems. 38 | 39 | %prep 40 | rm -rf $RPM_BUILD_ROOT 41 | %setup 42 | 43 | %build 44 | %configure 45 | make 46 | 47 | %install 48 | %makeinstall 49 | 50 | 51 | %clean 52 | rm -rf $RPM_BUILD_ROOT 53 | 54 | %files 55 | %defattr(-,root,root,755) 56 | %doc AUTHORS changelog README 57 | %{_mandir}/man1/directvnc.1* 58 | %{_mandir}/man1/directvnc-xmapconv.1* 59 | %{_mandir}/man1/directvnc-kbmapping.7* 60 | %{_bindir}/directvnc 61 | %{_bindir}/directvnc-xmapconv 62 | 63 | 64 | 65 | %changelog 66 | * Sat Dec 08 2001 Till Adam 67 | - initial spec file 68 | 69 | 70 | # end of file 71 | -------------------------------------------------------------------------------- /src/jpeg.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2000, 2001 Const Kaplinsky. All Rights Reserved. 3 | * Copyright (C) 2000 Tridia Corporation. All Rights Reserved. 4 | * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. 5 | * 6 | * This is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This software is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, a copy can be downloaded from 18 | * http://www.gnu.org/licenses/gpl.html, or obtained by writing to the 19 | * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 20 | * Boston, MA 02110-1301, USA. 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include "directvnc.h" 28 | #include 29 | 30 | void JpegInitSource(j_decompress_ptr cinfo); 31 | int JpegFillInputBuffer(j_decompress_ptr cinfo); 32 | void JpegSkipInputData(j_decompress_ptr cinfo, long num_bytes); 33 | void JpegTermSource(j_decompress_ptr cinfo); 34 | void JpegSetSrcManager(j_decompress_ptr cinfo, CARD8 *compressedData, 35 | int compressedLen); 36 | int DecompressJpegRect(int x, int y, int w, int h); 37 | 38 | long ReadCompactLen (void); 39 | 40 | 41 | #define RGB24_TO_PIXEL(bpp,r,g,b) \ 42 | ((((CARD##bpp)(r) & 0xFF) * opt.client.redmax + 127) / 255 \ 43 | << opt.client.redshift | \ 44 | (((CARD##bpp)(g) & 0xFF) * opt.client.greenmax + 127) / 255 \ 45 | << opt.client.greenshift | \ 46 | (((CARD##bpp)(b) & 0xFF) * opt.client.bluemax + 127) / 255 \ 47 | << opt.client.blueshift) 48 | -------------------------------------------------------------------------------- /src/keysym.h: -------------------------------------------------------------------------------- 1 | /* $Xorg: keysym.h,v 1.3 2000/08/18 04:05:44 coskrey Exp $ */ 2 | 3 | /*********************************************************** 4 | 5 | Copyright 1987, 1998 The Open Group 6 | 7 | All Rights Reserved. 8 | 9 | The above copyright notice and this permission notice shall be included in 10 | all copies or substantial portions of the Software. 11 | 12 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 15 | OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 16 | AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 17 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 18 | 19 | Except as contained in this notice, the name of The Open Group shall not be 20 | used in advertising or otherwise to promote the sale, use or other dealings 21 | in this Software without prior written authorization from The Open Group. 22 | 23 | 24 | Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. 25 | 26 | All Rights Reserved 27 | 28 | Permission to use, copy, modify, and distribute this software and its 29 | documentation for any purpose and without fee is hereby granted, 30 | provided that the above copyright notice appear in all copies and that 31 | both that copyright notice and this permission notice appear in 32 | supporting documentation, and that the name of Digital not be 33 | used in advertising or publicity pertaining to distribution of the 34 | software without specific, written prior permission. 35 | 36 | DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 37 | ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 38 | DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 39 | ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 40 | WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 41 | ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 42 | SOFTWARE. 43 | 44 | ******************************************************************/ 45 | /* $XFree86: xc/include/keysym.h,v 1.2 2000/10/27 18:30:46 dawes Exp $ */ 46 | 47 | /* default keysyms */ 48 | #define XK_MISCELLANY 49 | #define XK_XKB_KEYS 50 | #define XK_LATIN1 51 | #define XK_LATIN2 52 | #define XK_LATIN3 53 | #define XK_LATIN4 54 | #define XK_LATIN8 55 | #define XK_LATIN9 56 | #define XK_CAUCASUS 57 | #define XK_GREEK 58 | #define XK_KATAKANA 59 | #define XK_ARABIC 60 | #define XK_CYRILLIC 61 | #define XK_HEBREW 62 | #define XK_THAI 63 | #define XK_KOREAN 64 | #define XK_ARMENIAN 65 | #define XK_GEORGIAN 66 | #define XK_VIETNAMESE 67 | #define XK_CURRENCY 68 | 69 | #include 70 | 71 | -------------------------------------------------------------------------------- /debian/rules: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make -f 2 | # Sample debian/rules that uses debhelper. 3 | # GNU copyright 1997 to 1999 by Joey Hess. 4 | 5 | # Uncomment this to turn on verbose mode. 6 | #export DH_VERBOSE=1 7 | 8 | 9 | # These are used for cross-compiling and for saving the configure script 10 | # from having to guess our platform (since we know it already) 11 | export DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE) 12 | export DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE) 13 | 14 | # FOR AUTOCONF 2.52 AND NEWER ONLY 15 | ifeq ($(DEB_BUILD_GNU_TYPE), $(DEB_HOST_GNU_TYPE)) 16 | confflags += --build $(DEB_HOST_GNU_TYPE) 17 | else 18 | confflags += --build $(DEB_BUILD_GNU_TYPE) --host $(DEB_HOST_GNU_TYPE) 19 | endif 20 | 21 | CFLAGS = -Wall -g 22 | 23 | ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS))) 24 | CFLAGS += -O0 25 | else 26 | CFLAGS += -O2 27 | endif 28 | ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS))) 29 | INSTALL_PROGRAM += -s 30 | endif 31 | 32 | export CPPFLAGS = -I/usr/X11R6/include 33 | 34 | configure: Makefile.am configure.in 35 | dh_testdir 36 | chmod +x debian/autogen.sh 37 | debian/autogen.sh 38 | 39 | config.status: configure 40 | dh_testdir 41 | 42 | ln -sf /usr/share/misc/config.sub . 43 | ln -sf /usr/share/misc/config.guess . 44 | rm -f config.cache 45 | 46 | ./configure $(confflags) --prefix=/usr --mandir=\$${prefix}/share/man --infodir=\$${prefix}/share/info 47 | 48 | 49 | build: build-arch build-indep 50 | build-arch: build-stamp 51 | build-indep: build-stamp 52 | build-stamp: config.status 53 | dh_testdir 54 | 55 | # Add here commands to compile the package. 56 | $(MAKE) 57 | 58 | touch build-stamp 59 | 60 | clean: 61 | dh_testdir 62 | dh_testroot 63 | rm -f build-stamp 64 | 65 | [ ! -f Makefile ] || $(MAKE) clean 66 | [ ! -f Makefile ] || $(MAKE) distclean 67 | 68 | find \( -name config.sub -o -name config.guess \ 69 | -o -name config.cache -o -name config.log \) -print0 \ 70 | | xargs -0 -r rm -f \; 71 | 72 | dh_clean 73 | 74 | install: build 75 | dh_testdir 76 | dh_testroot 77 | dh_prep 78 | dh_installdirs 79 | 80 | # Add here commands to install the package into debian/directvnc. 81 | $(MAKE) install DESTDIR=$(CURDIR)/debian/directvnc 82 | 83 | # Build architecture-independent files here. 84 | binary-indep: build install 85 | # We have nothing to do by default. 86 | 87 | # Build architecture-dependent files here. 88 | binary-arch: build install 89 | dh_testdir 90 | dh_testroot 91 | dh_installchangelogs 92 | dh_installdocs 93 | dh_installexamples 94 | dh_installman 95 | dh_link 96 | dh_strip 97 | dh_compress 98 | dh_fixperms 99 | dh_installdeb 100 | dh_shlibdeps 101 | dh_gencontrol 102 | dh_md5sums 103 | dh_builddeb 104 | 105 | binary: binary-indep binary-arch 106 | .PHONY: build clean binary-indep binary-arch binary install 107 | -------------------------------------------------------------------------------- /src/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2001 Till Adam 3 | * Authors: Till Adam 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, a copy can be downloaded from 17 | * http://www.gnu.org/licenses/gpl.html, or obtained by writing to the 18 | * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 | * Boston, MA 02110-1301, USA. 20 | */ 21 | 22 | #include 23 | #include "directvnc.h" 24 | #include 25 | #include 26 | 27 | /* little convenience function */ 28 | static inline double get_time(void); 29 | static inline void sig_handler(int foo) { exit(1); } 30 | 31 | int 32 | main (int argc,char **argv) 33 | { 34 | /* parse arguments */ 35 | args_parse(argc, argv); 36 | mousestate.buttonmask = 0; 37 | 38 | /* Read the modifier map if provided */ 39 | 40 | if (modmap_read_file(opt.modmapfile)) { 41 | printf("Couldn't parse the keyboard mapping file %s. Exiting\n",opt.modmapfile); 42 | exit(0); 43 | } 44 | 45 | /* Connect to server */ 46 | if (!rfb_connect_to_server(opt.servername, 5900 + opt.port)) 47 | { 48 | printf("Couldnt establish connection with the VNC server. Exiting\n"); 49 | close(sock); 50 | exit(0); 51 | } 52 | 53 | /* initialize the connection */ 54 | if (!rfb_initialise_connection()) 55 | { 56 | printf("Connection with VNC server couldnt be initialized. Exiting\n"); 57 | close (sock); 58 | exit(0); 59 | } 60 | 61 | /* Tell the VNC server which pixel format and encodings we want to use */ 62 | if (!rfb_set_format_and_encodings()) 63 | { 64 | printf("Error negotiating format and encodings. Exiting.\n"); 65 | close(sock); 66 | exit(0); 67 | } 68 | 69 | /* initialize the framebuffer lib */ 70 | dfb_init(argc, argv); 71 | 72 | /* hook in sighandler, so we can clean up on ctrl-c */ 73 | signal(SIGINT, sig_handler); 74 | 75 | /* calculate horizontal and vertical offset */ 76 | if (opt.client.width > opt.server.width) 77 | opt.h_offset = rint( (opt.client.width - opt.server.width) /2); 78 | if (opt.client.height > opt.server.height) 79 | opt.v_offset = rint( (opt.client.height - opt.server.height) /2); 80 | 81 | mousestate.x = opt.client.width / 2; 82 | mousestate.y = opt.client.height / 2; 83 | 84 | /* FIXME disabled for now 85 | * opt.h_ratio = (double) opt.client.width / (double) opt.server.width; 86 | * opt.v_ratio = (double) opt.client.height / (double) opt.server.height; 87 | */ 88 | 89 | /* Now enter the main loop, processing VNC messages. mouse and keyboard 90 | * events will automatically be processed whenever the VNC connection is 91 | * idle. */ 92 | rfb_send_update_request(0); 93 | while (1) 94 | { 95 | 96 | if (!rfb_handle_server_message()) 97 | break; 98 | 99 | rfb_send_update_request(1); 100 | 101 | /* If we've just been here and there are no events pending, let the 102 | * other kids play for a bit. */ 103 | dfb_wait_for_event_with_timeout(opt.poll_freq); 104 | } 105 | dfb_deinit(); 106 | close(sock); 107 | return (1); 108 | } 109 | 110 | static inline double 111 | get_time(void) 112 | { 113 | struct timeval v; 114 | gettimeofday(&v, NULL); 115 | 116 | return ((double)v.tv_sec + (((double)v.tv_usec) /1000000)); 117 | } 118 | 119 | -------------------------------------------------------------------------------- /src/vncauth.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. 3 | * 4 | * This is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This software is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, a copy can be downloaded from 16 | * http://www.gnu.org/licenses/gpl.html, or obtained by writing to the 17 | * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 18 | * Boston, MA 02110-1301, USA. 19 | */ 20 | 21 | /* 22 | * vncauth.c - Functions for VNC password management and authentication. 23 | */ 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | 35 | /* 36 | * We use a fixed key to store passwords, since we assume that our local 37 | * file system is secure but nonetheless don't want to store passwords 38 | * as plaintext. 39 | */ 40 | 41 | unsigned char fixedkey[8] = {23,82,107,6,35,78,88,7}; 42 | 43 | 44 | /* 45 | * Encrypt a password and store it in a file. Returns 0 if successful, 46 | * 1 if the file could not be written. 47 | */ 48 | 49 | int 50 | vncEncryptAndStorePasswd(char *passwd, char *fname) 51 | { 52 | FILE *fp; 53 | int i; 54 | unsigned char encryptedPasswd[8]; 55 | 56 | if ((fp = fopen(fname,"w")) == NULL) return 1; 57 | 58 | chmod(fname, S_IRUSR|S_IWUSR); 59 | 60 | /* pad password with nulls */ 61 | 62 | for (i = 0; i < 8; i++) { 63 | if (i < strlen(passwd)) { 64 | encryptedPasswd[i] = passwd[i]; 65 | } else { 66 | encryptedPasswd[i] = 0; 67 | } 68 | } 69 | 70 | /* Do encryption in-place - this way we overwrite our copy of the plaintext 71 | password */ 72 | 73 | deskey(fixedkey, EN0); 74 | des(encryptedPasswd, encryptedPasswd); 75 | 76 | for (i = 0; i < 8; i++) { 77 | putc(encryptedPasswd[i], fp); 78 | } 79 | 80 | fclose(fp); 81 | return 0; 82 | } 83 | 84 | 85 | /* 86 | * Decrypt a password from a file. Returns a pointer to a newly allocated 87 | * string containing the password or a null pointer if the password could 88 | * not be retrieved for some reason. 89 | */ 90 | 91 | char * 92 | vncDecryptPasswdFromFile(char *fname) 93 | { 94 | FILE *fp; 95 | int i, ch; 96 | unsigned char *passwd = (unsigned char *)malloc(9); 97 | 98 | if ((fp = fopen(fname,"r")) == NULL) return NULL; 99 | 100 | for (i = 0; i < 8; i++) { 101 | ch = getc(fp); 102 | if (ch == EOF) { 103 | fclose(fp); 104 | return NULL; 105 | } 106 | passwd[i] = ch; 107 | } 108 | 109 | fclose(fp); 110 | 111 | deskey(fixedkey, DE1); 112 | des(passwd, passwd); 113 | 114 | passwd[8] = 0; 115 | 116 | return (char *)passwd; 117 | } 118 | 119 | 120 | /* 121 | * Generate CHALLENGESIZE random bytes for use in challenge-response 122 | * authentication. 123 | */ 124 | 125 | void 126 | vncRandomBytes(unsigned char *bytes) 127 | { 128 | int i; 129 | unsigned int seed = (unsigned int) time(0); 130 | 131 | srandom(seed); 132 | for (i = 0; i < CHALLENGESIZE; i++) { 133 | bytes[i] = (unsigned char)(random() & 255); 134 | } 135 | } 136 | 137 | 138 | /* 139 | * Encrypt CHALLENGESIZE bytes in memory using a password. 140 | */ 141 | 142 | void 143 | vncEncryptBytes(unsigned char *bytes, char *passwd) 144 | { 145 | unsigned char key[8]; 146 | int i; 147 | 148 | /* key is simply password padded with nulls */ 149 | 150 | for (i = 0; i < 8; i++) { 151 | if (i < strlen(passwd)) { 152 | key[i] = passwd[i]; 153 | } else { 154 | key[i] = 0; 155 | } 156 | } 157 | 158 | deskey(key, EN0); 159 | 160 | for (i = 0; i < CHALLENGESIZE; i += 8) { 161 | des(bytes+i, bytes+i); 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /directvnc-kbmapping.7: -------------------------------------------------------------------------------- 1 | .TH directvnc-kbmapping 7 "Jul 30, 2011" 2 | .SH NAME 3 | directvnc-kbmapping - Details of keyboard mapping file syntax for directvnc(1) 4 | .SH Xmodmap Keyboard Layout File Syntax 5 | General syntax of the xmodmap keyboard layout file is described in the 6 | xmodmap(1x) manual page. For the purposes of keyboard switching implementation 7 | in directvnc, the following subset of its syntax is used: 8 | 9 | Comments (lines starting with an exclamation mark) are recognized as such, and 10 | ignored Expressions using keycode are recognized with up to four keysym values, 11 | used as described in the mentioned manual page Other xmodmap expressions will 12 | be ignored. So, the following is a valid syntax of an xmodmap file that can be 13 | converted into a directvnc keyboard layout file: 14 | 15 | .br 16 | Key Base Shift Mode Mode+Shift 17 | .br 18 | 19 | .br 20 | keycode 13 = 4 dollar 4 quotedbl 21 | .br 22 | keycode 14 = 5 percent 5 colon 23 | .br 24 | keycode 15 = 6 asciicircum 6 comma 25 | .br 26 | keycode 16 = 7 ampersand 7 period 27 | .br 28 | keycode 24 = q Q Cyrillic_shorti Cyrillic_SHORTI 29 | .br 30 | keycode 25 = w W Cyrillic_tse Cyrillic_TSE 31 | .br 32 | keycode 26 = e E Cyrillic_u Cyrillic_U 33 | .br 34 | keycode 27 = r R Cyrillic_ka Cyrillic_KA 35 | 36 | An example of a xmodmap file for Cyrillic input can be found ???? 37 | 38 | .SH Directvnc Keyboard Layout File Syntax 39 | 40 | The xmodmap file uses character identifiers to identify keysyms that keycodes 41 | will be translated to. While this works in the original xmodmap program which 42 | acts as a client to the X server it loads keyboard layout into (xmodmap queries 43 | the X server to convert symbolic keysym identifiers into numeric), directvnc is 44 | not supposed to interact with the remote Xvnc server this way. Instead, a 45 | derivative format is used, which contains hexadecimal codes for keysyms: 46 | 47 | keycode 13 0x034 0x024 0x034 0x022 48 | .br 49 | keycode 14 0x035 0x025 0x035 0x03a 50 | .br 51 | keycode 15 0x036 0x05e 0x036 0x02c 52 | .br 53 | keycode 16 0x037 0x026 0x037 0x02e 54 | .br 55 | keycode 24 0x071 0x051 0x6ca 0x6ea 56 | .br 57 | keycode 25 0x077 0x057 0x6c3 0x6e3 58 | .br 59 | keycode 26 0x065 0x045 0x6d5 0x6f5 60 | .br 61 | keycode 27 0x072 0x052 0x6cb 0x6eb 62 | .br 63 | keycode 28 0x074 0x054 0x6c5 0x6e5 64 | .br 65 | keycode 29 0x079 0x059 0x6ce 0x6ee 66 | .br 67 | keycode 30 0x075 0x055 0x6c7 0x6e7 68 | 69 | The keycode keyword does not play any role at the moment, but is preserved for 70 | the future extensions, when other xmodmap expressions may also be recognized. 71 | 72 | .SH Conversion From One to Another 73 | 74 | As noted above, directvnc does not query the remote Xvnc server for keysyms' 75 | numeric values. There is the keysymdef.h include file which contains all the 76 | necessary information. In particular, considering this (a small portion of the 77 | keysymdef.h file): 78 | 79 | #define XK_Q 0x051 80 | .br 81 | #define XK_q 0x071 82 | .br 83 | #define XK_Cyrillic_shorti 0x6ca 84 | .br 85 | #define XK_Cyrillic_SHORTI 0x6ea 86 | 87 | 88 | it becomes clear how to convert 89 | 90 | keycode 24 = q Q Cyrillic_shorti Cyrillic_SHORTI 91 | 92 | into 93 | 94 | keycode 24 0x071 0x051 0x6ca 0x6ea 95 | 96 | The directvnc-xmapconv(1) utility reads an xmodmap syntax file from standard 97 | input, and writes the directvnc compatible syntax file to standard output. 98 | 99 | Inside, the script 100 | runs its standard input through the C preprocessor including the keysymdef.h 101 | file and prepending each keysym identifier with XK_. The directvnc keyboard 102 | layout file mentioned earlier was produced exactly this way out of the xmodmap 103 | file for Cyrillic input. 104 | 105 | .SH Key Modifiers Logic 106 | 107 | The directvnc's keyboard layout switching module holds an internal table where 108 | the contents of the keyboard layout file is read into. The module intercepts 109 | all keyboard input obtained from DirectFB, and uses keyboard scan code plus 8 110 | (also known as the 111 | .B MIN_KEYCODE 112 | constant) as index into that table to determine whether any mapping exists for 113 | a given keycode. 114 | 115 | The directvnc's keyboard layout switching module uses the ScrollLock key as 116 | mode lock: when its LED is on, the third or fourth keysym would be transmitted 117 | (depending on the Shift and CapsLock status); when Scroll lock LED is off, the 118 | first or the second keysym would be transmitted. 119 | 120 | The Alt or AltGr keys are not used to control keyboard mode. 121 | 122 | For letters, Shift and CapsLock are XORed. For numbers, CapsLock does not 123 | apply. 124 | 125 | If Ctrl is pressed, or there was no keyboard layout file specified, or the 126 | keyboard layout file does not contain any mapping for a given keycode, 127 | directvnc performs its default translation of keyboard code into a keysym using 128 | its hardcoded ISO-8859-1 translation table. 129 | 130 | .SH SEE ALSO 131 | directvnc(1), directvnc-xmapconv(1), xmodmap(1) 132 | 133 | .SH AUTHOR 134 | Dimitry Golubovsky, Loris Boillet 135 | .br 136 | -------------------------------------------------------------------------------- /debian/changelog: -------------------------------------------------------------------------------- 1 | directvnc (0.7.7-1) unstable; urgency=low 2 | 3 | * New upstream release. 4 | * Update debian/control: 5 | - Build-Depends on libjpeg-dev, not libjpeg62-dev (Closes: #633728) 6 | - Bump Standards-Version from 3.8.4 to 3.9.2 (no changes needed). 7 | - Recommends x11proto-core-dev (useful to generate keymap files). 8 | * Fix debian/rules missing build-arch and build-indep target. Thanks to 9 | lintian. 10 | * Fix typos in copyright file. 11 | 12 | -- Loris Boillet Sun, 31 Jul 2011 09:15:59 +0100 13 | 14 | directvnc (0.7.6-1) unstable; urgency=low 15 | 16 | * New maintainer. (Closes: #367169) 17 | * New upstream release. (Closes: #490057, #503390, #538110) 18 | - debian/patches/directvnc-manpage-bpp.patch: Merged upstream. 19 | - Fix lintian warnings: ancient libtool and spelling errors in manpage. 20 | * Add a note in README.debian about needed access to /dev/tty0 if more than 21 | one directFB app is used at the same time (Closes: #355754) 22 | * Bump debian/compat to 7. 23 | * Update debian/control: 24 | - Bump Standards-Version from 3.6.2 to 3.8.4 (no changes needed). 25 | - Add Homepage field. Thanks to lintian. 26 | - Add missing ${misc:Depends}. Thanks to lintian. 27 | - Add build-depends to autotools-dev, autoconf, automake and libtool. 28 | * Fix copyright without copyright notice. Thanks to lintian. 29 | * Replacing obsolete dh_clean -k with dh_prep. 30 | * Switch to dpkg-source 3.0 (quilt) format. 31 | * Autotools files now systematically re-generated (adds debian/autogen.sh). 32 | * Cleaned-up debian/rules: removed commented out dh_* commands. 33 | 34 | -- Loris Boillet Sun, 15 Feb 2010 09:13:09 +0100 35 | 36 | directvnc (0.7.5-9) unstable; urgency=low 37 | 38 | * QA upload. 39 | * Replaced build-dependency on x-dev by x11proto-core-dev (Closes: #515360). 40 | * debian/rules: do not ignore error of "make distclean" 41 | 42 | -- Ralf Treinen Fri, 20 Feb 2009 23:21:48 +0100 43 | 44 | directvnc (0.7.5-8) unstable; urgency=low 45 | 46 | [Ola Lundqvist ] 47 | * Orphaned package and set maintainer to QA team. 48 | 49 | [Roberto C. Sanchez ] 50 | * Replace DFBCardCapabilities with DFBGraphicsDeviceDescription, per 51 | http://mail.directfb.org/pipermail/directfb-users/2005-April/000181.html, 52 | closes: #364264 53 | * Bump Build-Depends on libdirectfb-dev to 0.9.24. 54 | 55 | -- Ola Lundqvist Sun, 14 May 2006 10:44:19 +0200 56 | 57 | directvnc (0.7.5-7.1) unstable; urgency=low 58 | 59 | * Non-maintainer upload. 60 | * Fix inclusion of X11R6 headers to workaround FTBFS: export 61 | CPPFLAGS = -I/usr/X11R6/include before configure in debian/rules 62 | * reinvent changes from 0.7.5-6.1, Ola Lundqvist silently ignored 63 | them and uploaded 0.7.5-7. 64 | * rm -f config.log to make build process more silent 65 | 66 | -- Jonas Meurer Wed, 12 Oct 2005 15:30:34 +0200 67 | 68 | directvnc (0.7.5-7) unstable; urgency=low 69 | 70 | * Rebuild against libdirectfb-0.9-22, closes: #314976. 71 | * Updated standards version to 3.6.2. 72 | 73 | -- Ola Lundqvist Sun, 9 Oct 2005 21:46:23 +0200 74 | 75 | directvnc (0.7.5-6.1) unstable; urgency=low 76 | 77 | * Non-maintainer upload. 78 | * rebuild against libdirectfb-0.9-22 for transition (closes: #314976) 79 | * bumped standards-version to 3.6.2 (no changes needed) 80 | * updated fsf address to make lintian happy 81 | * change xlibs-dev Build-Depends to x-dev, after searching docs and source 82 | i believe that only some x headers are needed to build. 83 | 84 | -- Jonas Meurer Mon, 3 Oct 2005 17:22:37 +0200 85 | 86 | directvnc (0.7.5-6) unstable; urgency=low 87 | 88 | * Documented display size restriction, closes: #248009. 89 | * Applied patch from Brian Brunswick that fix a busy 90 | loop problem, closes: #246336. 91 | * Fixed another potential busy loop problem in the same way as 92 | #24336 is fixed. 93 | 94 | -- Ola Lundqvist Sun, 17 Apr 2005 00:11:50 +0200 95 | 96 | directvnc (0.7.5-5) unstable; urgency=low 97 | 98 | * Fixed depends field, closes: #218358. 99 | Thanks to Guillem Jover for notifying me. 100 | * Added patch to fix a manpage issue, closes: #248015. 101 | Thanks to Marco Herrn for the patch. 102 | 103 | -- Ola Lundqvist Thu, 22 Jul 2004 21:55:43 +0200 104 | 105 | directvnc (0.7.5-4) unstable; urgency=low 106 | 107 | * Rebuilt against libdirectfb 0.9.20, closes: #233508. 108 | 109 | -- Ola Lundqvist Fri, 12 Mar 2004 13:54:09 +0100 110 | 111 | directvnc (0.7.5-3) unstable; urgency=low 112 | 113 | * Added even more build dependencies, closes: #210997. 114 | 115 | -- Ola Lundqvist Mon, 27 Oct 2003 22:31:22 +0100 116 | 117 | directvnc (0.7.5-2) unstable; urgency=low 118 | 119 | * Fixed missing build dependency, closes: #210997. 120 | * Added versioned dependency on directfb. 121 | 122 | -- Ola Lundqvist Sat, 4 Oct 2003 12:21:53 +0200 123 | 124 | directvnc (0.7.5-1) unstable; urgency=low 125 | 126 | * Initial release. 127 | 128 | -- Ola Lundqvist Sun, 31 Aug 2003 14:41:29 +0200 129 | 130 | -------------------------------------------------------------------------------- /directvnc.1: -------------------------------------------------------------------------------- 1 | .TH directvnc 1 "Mar 5, 2010" 2 | .SH NAME 3 | directvnc - a vnc client for the linux framebuffer device 4 | .SH SYNOPSIS 5 | directvnc server:display [options] 6 | .SH DESCRIPTION 7 | .B DirectVNC 8 | is a client implementing the remote framebuffer protocol (rfb) which is 9 | used by VNC servers. If a VNC server is running on a machine you can connect 10 | to it using this client and have the contents of its display shown on your 11 | screen. Keyboard and mouse events are sent to the server, so you can basically 12 | control a VNC server remotely. There are servers (and other clients) freely 13 | available for all operating systems. 14 | 15 | What makes DirectVNC different from other unix vnc clients is that it uses the 16 | linux framebuffer device through the DirectFB library which enables it to run 17 | on anything that has a framebuffer without the need for a running X server. 18 | This includes embedded devices. DirectFB even uses acceleration features of 19 | certain graphics cards. Thus a lot of configuration can be done by creating the 20 | library specific configuration file /etc/directfbrc or the program-specific 21 | configuration file /etc/directfbrc.directvnc. See directfbrc(5) or find out all 22 | about DirectFB here: 23 | 24 | www.directfb.org 25 | 26 | DirectVNC basically provides a very thin VNC client for unix framebuffer systems. 27 | 28 | .SH QUITTING 29 | Hitting exits the viewer. 30 | 31 | .SH OPTIONS 32 | .TP 5 33 | .B -h, --help 34 | display help output and exit 35 | .TP 5 36 | .B -v, --version 37 | output version information and exit 38 | .TP 5 39 | .B -p, --password 40 | password string to be passed to the server for authentication. Use this with 41 | care! 42 | .TP 5 43 | .B -b, --bpp 44 | the bits per pixel to be used by the client. Currently only 16 and 24 bpp 45 | are available. 46 | .TP 5 47 | .B -e --encodings 48 | DirectVNC supports several different compression methods to encode 49 | screen updates; this option specifies a set of them to use in order of 50 | preference. Encodings are specified separated with spaces, and must 51 | thus be enclosed in quotes if more than one is specified. Available 52 | encodings, in default order for a remote connection, are "copyrect 53 | tight hextile zlib corre rre raw". For a local connection (to the same 54 | machine), the default order to try is "raw copyrect tight hextile zlib 55 | corre rre". Raw encoding is always assumed as a last option if no 56 | other encoding can be used for some reason. 57 | .TP 5 58 | .B -f --pollfrequency 59 | time in ms to wait between polls for screen updates when no events are to be 60 | processed. This reduces cpu and network load. Default is 50 ms. 61 | .TP 5 62 | .B -s, --shared (default) 63 | Don't disconnect already connected clients. 64 | .TP 5 65 | .B -n, --noshared 66 | Disconnect already connected clients. 67 | .TP 5 68 | .B -n, --nolocalcursor 69 | Disable local cursor tracking By default, and if the server is capable of the 70 | SoftCursor encoding, mouse movements do not generate framebuffer updates and 71 | the cursor state is kept locally. This removes mouse pointer lag and lets the 72 | connection appear faster. 73 | 74 | .TP 5 75 | .B -c --compresslevel level 76 | Use specified compression level (0..9) for "tight" and "zlib" 77 | encodings (only usable with servers capable of those encodings). Level 1 78 | uses minimum of CPU time and achieves weak compression ratios, while level 9 79 | offers best compression but is slow in terms of CPU time consumption on the 80 | server side. Use high levels with very slow network connections, and low 81 | levels when working over high\-speed LANs. It's not recommended to use 82 | compression level 0, reasonable choices start from the level 1. 83 | 84 | .TP 5 85 | .B -q --quality level 86 | Use the specified image quality level (0..9) for "tight" 87 | encoding (only usable with servers capable of those encodings). 88 | Specifying this option allows "tight" encoder to use lossy JPEG compression. 89 | Quality level 0 denotes bad image quality but very impressive compression 90 | ratios, while level 9 offers very good image quality at lower compression 91 | ratios. Note that "tight" encoder uses JPEG to encode only those screen areas 92 | that look suitable for lossy compression, so quality level 0 does not always 93 | mean unacceptable image quality. 94 | 95 | .TP 5 96 | .B -m --modmap PATH 97 | Path to the modmap (subset of X-style) file to load. With this option, it is 98 | possible to set an alternative keyboard layout, with ability to support non-latin 99 | characters such as Cyrillic. A plain text file, containing a subset of xmodmap(1) 100 | syntax (only keycode expressions are recognized with up to four KEYSYMNAMEs) can 101 | be converted into the format that directvnc understands, and can be loaded upon 102 | directvnc startup with this option. See directvnc-kbmapping(7). 103 | 104 | .SH LIMITATIONS 105 | At the moment, it is still necessary to use the \-\-bpp command line option to 106 | set color depth. When negotiating with the remote VNC server side, color depth 107 | supplied by the server will be used. It is therefore necessary to make sure (at 108 | least in the present) that screen color depth (default, or set in the DirectFB 109 | configuration file), color depth supplied at the command line, and remote VNC 110 | server color depth all match. 111 | 112 | .SH SEE ALSO 113 | directfbrc(5), directvnc-kbmapping(7), directvnc-xmapconv(1), xmodmap(1) 114 | 115 | .SH AUTHORS 116 | Till Adam, Dimitry Golubovsky, Malte S. Stretz, Loris Boillet and others, based on 117 | AT&T and tightvnc VNC implementations. 118 | 119 | .br 120 | -------------------------------------------------------------------------------- /src/getopt.h: -------------------------------------------------------------------------------- 1 | /* Declarations for getopt. 2 | Copyright (C) 1989,90,91,92,93,94,96,97 Free Software Foundation, Inc. 3 | This file is part of the GNU C Library. 4 | 5 | The GNU C Library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Library General Public License as 7 | published by the Free Software Foundation; either version 2 of the 8 | License, or (at your option) any later version. 9 | 10 | The GNU C Library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Library General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, a copy can be downloaded from 17 | http://www.gnu.org/licenses/gpl.html, or obtained by writing to the 18 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 | Boston, MA 02110-1301, USA. */ 20 | 21 | #ifndef _GETOPT_H 22 | #define _GETOPT_H 1 23 | 24 | #ifdef __cplusplus 25 | extern "C" 26 | { 27 | #endif 28 | 29 | /* For communication from `getopt' to the caller. 30 | When `getopt' finds an option that takes an argument, 31 | the argument value is returned here. 32 | Also, when `ordering' is RETURN_IN_ORDER, 33 | each non-option ARGV-element is returned here. */ 34 | 35 | extern char *optarg; 36 | 37 | /* Index in ARGV of the next element to be scanned. 38 | This is used for communication to and from the caller 39 | and for communication between successive calls to `getopt'. 40 | 41 | On entry to `getopt', zero means this is the first call; initialize. 42 | 43 | When `getopt' returns -1, this is the index of the first of the 44 | non-option elements that the caller should itself scan. 45 | 46 | Otherwise, `optind' communicates from one call to the next 47 | how much of ARGV has been scanned so far. */ 48 | 49 | extern int optind; 50 | 51 | /* Callers store zero here to inhibit the error message `getopt' prints 52 | for unrecognized options. */ 53 | 54 | extern int opterr; 55 | 56 | /* Set to an option character which was unrecognized. */ 57 | 58 | extern int optopt; 59 | 60 | /* Describe the long-named options requested by the application. 61 | The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector 62 | of `struct option' terminated by an element containing a name which is 63 | zero. 64 | 65 | The field `has_arg' is: 66 | no_argument (or 0) if the option does not take an argument, 67 | required_argument (or 1) if the option requires an argument, 68 | optional_argument (or 2) if the option takes an optional argument. 69 | 70 | If the field `flag' is not NULL, it points to a variable that is set 71 | to the value given in the field `val' when the option is found, but 72 | left unchanged if the option is not found. 73 | 74 | To have a long-named option do something other than set an `int' to 75 | a compiled-in constant, such as set a value from `optarg', set the 76 | option's `flag' field to zero and its `val' field to a nonzero 77 | value (the equivalent single-letter option character, if there is 78 | one). For long options that have a zero `flag' field, `getopt' 79 | returns the contents of the `val' field. */ 80 | 81 | struct option 82 | { 83 | #if defined (__STDC__) && __STDC__ 84 | const char *name; 85 | #else 86 | char *name; 87 | #endif 88 | /* has_arg can't be an enum because some compilers complain about type 89 | mismatches in all the code that assumes it is an int. */ 90 | int has_arg; 91 | int *flag; 92 | int val; 93 | }; 94 | 95 | /* Names for the values of the `has_arg' field of `struct option'. */ 96 | 97 | #define no_argument 0 98 | #define required_argument 1 99 | #define optional_argument 2 100 | 101 | #if defined (__STDC__) && __STDC__ 102 | #ifdef __GNU_LIBRARY__ 103 | /* Many other libraries have conflicting prototypes for getopt, with 104 | differences in the consts, in stdlib.h. To avoid compilation 105 | errors, only prototype getopt for the GNU C library. */ 106 | extern int getopt(int argc, char *const *argv, const char *shortopts); 107 | #else /* not __GNU_LIBRARY__ */ 108 | #ifndef __cplusplus 109 | /* C++ is more pedantic, and demands a full prototype, not this. 110 | Hope that stdlib.h has a prototype for `getopt'. */ 111 | extern int getopt(); 112 | #endif /* __cplusplus */ 113 | #endif /* __GNU_LIBRARY__ */ 114 | extern int getopt_long(int argc, char *const *argv, const char *shortopts, 115 | const struct option *longopts, int *longind); 116 | extern int getopt_long_only(int argc, char *const *argv, 117 | const char *shortopts, 118 | const struct option *longopts, int *longind); 119 | 120 | /* Internal only. Users should not call this directly. */ 121 | extern int _getopt_internal(int argc, char *const *argv, 122 | const char *shortopts, 123 | const struct option *longopts, int *longind, 124 | int long_only); 125 | #else /* not __STDC__ */ 126 | extern int getopt(); 127 | extern int getopt_long(); 128 | extern int getopt_long_only(); 129 | 130 | extern int _getopt_internal(); 131 | #endif /* __STDC__ */ 132 | 133 | #ifdef __cplusplus 134 | } 135 | #endif 136 | 137 | #endif /* getopt.h */ 138 | -------------------------------------------------------------------------------- /src/jpeg.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2000, 2001 Const Kaplinsky. All Rights Reserved. 3 | * Copyright (C) 2000 Tridia Corporation. All Rights Reserved. 4 | * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. 5 | * 6 | * This is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This software is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, a copy can be downloaded from 18 | * http://www.gnu.org/licenses/gpl.html, or obtained by writing to the 19 | * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 20 | * Boston, MA 02110-1301, USA. 21 | */ 22 | 23 | #include "jpeg.h" 24 | /* 25 | * JPEG source manager functions for JPEG decompression in Tight decoder. 26 | */ 27 | static int jpegError; 28 | static struct jpeg_source_mgr jpegSrcManager; 29 | static JOCTET *jpegBufferPtr; 30 | static size_t jpegBufferLen; 31 | 32 | void 33 | JpegInitSource(j_decompress_ptr cinfo) 34 | { 35 | jpegError = 0; 36 | } 37 | 38 | int 39 | JpegFillInputBuffer(j_decompress_ptr cinfo) 40 | { 41 | jpegError = 1; 42 | jpegSrcManager.bytes_in_buffer = (size_t)jpegBufferLen; 43 | jpegSrcManager.next_input_byte = (JOCTET *)jpegBufferPtr; 44 | 45 | return TRUE; 46 | } 47 | 48 | void 49 | JpegSkipInputData(j_decompress_ptr cinfo, long num_bytes) 50 | { 51 | if (num_bytes < 0 || num_bytes > jpegSrcManager.bytes_in_buffer) { 52 | jpegError = 1; 53 | jpegSrcManager.bytes_in_buffer = (size_t)jpegBufferLen; 54 | jpegSrcManager.next_input_byte = (JOCTET *)jpegBufferPtr; 55 | } else { 56 | jpegSrcManager.next_input_byte += (size_t) num_bytes; 57 | jpegSrcManager.bytes_in_buffer -= (size_t) num_bytes; 58 | } 59 | } 60 | 61 | void 62 | JpegTermSource(j_decompress_ptr cinfo) 63 | { 64 | /* No work necessary here. */ 65 | } 66 | 67 | void 68 | JpegSetSrcManager(j_decompress_ptr cinfo, CARD8 *compressedData, 69 | int compressedLen) 70 | { 71 | jpegBufferPtr = (JOCTET *)compressedData; 72 | jpegBufferLen = (size_t)compressedLen; 73 | 74 | jpegSrcManager.init_source = JpegInitSource; 75 | jpegSrcManager.fill_input_buffer = JpegFillInputBuffer; 76 | jpegSrcManager.skip_input_data = JpegSkipInputData; 77 | jpegSrcManager.resync_to_restart = jpeg_resync_to_restart; 78 | jpegSrcManager.term_source = JpegTermSource; 79 | jpegSrcManager.next_input_byte = jpegBufferPtr; 80 | jpegSrcManager.bytes_in_buffer = jpegBufferLen; 81 | 82 | cinfo->src = &jpegSrcManager; 83 | } 84 | 85 | 86 | /*---------------------------------------------------------------------------- 87 | * 88 | * JPEG decompression. 89 | * 90 | */ 91 | 92 | int 93 | DecompressJpegRect(int x, int y, int w, int h) 94 | { 95 | struct jpeg_decompress_struct cinfo; 96 | struct jpeg_error_mgr jerr; 97 | int compressedLen; 98 | CARD8 *compressedData; 99 | CARD16 *pixelPtr; 100 | JSAMPROW rowPointer[1]; 101 | int dx, dy; 102 | 103 | compressedLen = (int)ReadCompactLen(); 104 | if (compressedLen <= 0) { 105 | fprintf(stderr, "Incorrect data received from the server.\n"); 106 | return 0; 107 | } 108 | 109 | compressedData = malloc(compressedLen); 110 | if (compressedData == NULL) { 111 | fprintf(stderr, "Memory allocation error.\n"); 112 | return 0; 113 | } 114 | 115 | if (!read_from_rfb_server(sock, (char*)compressedData, compressedLen)) { 116 | free(compressedData); 117 | return 0; 118 | } 119 | 120 | cinfo.err = jpeg_std_error(&jerr); 121 | jpeg_create_decompress(&cinfo); 122 | 123 | JpegSetSrcManager(&cinfo, compressedData, compressedLen); 124 | 125 | jpeg_read_header(&cinfo, TRUE); 126 | cinfo.out_color_space = JCS_RGB; 127 | 128 | jpeg_start_decompress(&cinfo); 129 | if (cinfo.output_width != w || cinfo.output_height != h || 130 | cinfo.output_components != 3) { 131 | fprintf(stderr, "Tight Encoding: Wrong JPEG data received.\n"); 132 | jpeg_destroy_decompress(&cinfo); 133 | free(compressedData); 134 | return 0; 135 | } 136 | 137 | rowPointer[0] = (JSAMPROW)buffer; 138 | dy = 0; 139 | while (cinfo.output_scanline < cinfo.output_height) { 140 | jpeg_read_scanlines(&cinfo, rowPointer, 1); 141 | if (jpegError) { 142 | break; 143 | } 144 | /* FIXME 16 bpp hardcoded */ 145 | /* Fill the second half of our global buffer with the uncompressed data */ 146 | pixelPtr = (CARD16 *)&buffer[BUFFER_SIZE / 2]; 147 | for (dx = 0; dx < w; dx++) { 148 | *pixelPtr++ = 149 | RGB24_TO_PIXEL(16, buffer[dx*3], buffer[dx*3+1], buffer[dx*3+2]); 150 | } 151 | 152 | /* write scanline to screen */ 153 | dfb_write_data_to_screen(x, y + dy, w, 1, &buffer[BUFFER_SIZE/2]); 154 | dy++; 155 | } 156 | 157 | if (!jpegError) 158 | jpeg_finish_decompress(&cinfo); 159 | 160 | jpeg_destroy_decompress(&cinfo); 161 | free(compressedData); 162 | 163 | return !jpegError; 164 | } 165 | 166 | long 167 | ReadCompactLen (void) 168 | { 169 | long len; 170 | CARD8 b; 171 | 172 | if (!read_from_rfb_server(sock, (char *)&b, 1)) 173 | return -1; 174 | len = (int)b & 0x7F; 175 | if (b & 0x80) { 176 | if (!read_from_rfb_server(sock, (char *)&b, 1)) 177 | return -1; 178 | len |= ((int)b & 0x7F) << 7; 179 | if (b & 0x80) { 180 | if (!read_from_rfb_server(sock, (char *)&b, 1)) 181 | return -1; 182 | len |= ((int)b & 0xFF) << 14; 183 | } 184 | } 185 | return len; 186 | } 187 | 188 | 189 | -------------------------------------------------------------------------------- /src/getopt1.c: -------------------------------------------------------------------------------- 1 | #ifndef HAVE_GETOPT_LONG 2 | #define HAVE_GETOPT_LONG 1 3 | /* getopt_long and getopt_long_only entry points for GNU getopt. 4 | Copyright (C) 1987,88,89,90,91,92,93,94,96,97 Free Software Foundation, Inc. 5 | This file is part of the GNU C Library. 6 | 7 | The GNU C Library is free software; you can redistribute it and/or 8 | modify it under the terms of the GNU Library General Public License as 9 | published by the Free Software Foundation; either version 2 of the 10 | License, or (at your option) any later version. 11 | 12 | The GNU C Library is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | Library General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program; if not, a copy can be downloaded from 19 | http://www.gnu.org/licenses/gpl.html, or obtained by writing to the 20 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 21 | Boston, MA 02110-1301, USA. */ 22 | 23 | #ifdef HAVE_CONFIG_H 24 | #include "config.h" 25 | #endif 26 | 27 | #include "getopt.h" 28 | 29 | #if !defined (__STDC__) || !__STDC__ 30 | /* This is a separate conditional since some stdc systems 31 | reject `defined (const)'. */ 32 | #ifndef const 33 | #define const 34 | #endif 35 | #endif 36 | 37 | #include 38 | 39 | /* Comment out all this code if we are using the GNU C Library, and are not 40 | actually compiling the library itself. This code is part of the GNU C 41 | Library, but also included in many other GNU distributions. Compiling 42 | and linking in this code is a waste when using the GNU C library 43 | (especially if it is a shared library). Rather than having every GNU 44 | program understand `configure --with-gnu-libc' and omit the object files, 45 | it is simpler to just do this in the source for each such file. */ 46 | 47 | #define GETOPT_INTERFACE_VERSION 2 48 | #if !defined (_LIBC) && defined (__GLIBC__) && __GLIBC__ >= 2 49 | #include 50 | #if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION 51 | #define ELIDE_CODE 52 | #endif 53 | #endif 54 | 55 | #ifndef ELIDE_CODE 56 | 57 | 58 | /* This needs to come after some library #include 59 | to get __GNU_LIBRARY__ defined. */ 60 | #ifdef __GNU_LIBRARY__ 61 | #include 62 | #endif 63 | 64 | #ifndef NULL 65 | #define NULL 0 66 | #endif 67 | 68 | int 69 | getopt_long(argc, argv, options, long_options, opt_index) 70 | int argc; 71 | char *const *argv; 72 | const char *options; 73 | const struct option *long_options; 74 | int *opt_index; 75 | { 76 | return _getopt_internal(argc, argv, options, long_options, opt_index, 0); 77 | } 78 | 79 | /* Like getopt_long, but '-' as well as '--' can indicate a long option. 80 | If an option that starts with '-' (not '--') doesn't match a long option, 81 | but does match a short option, it is parsed as a short option 82 | instead. */ 83 | 84 | int 85 | getopt_long_only(argc, argv, options, long_options, opt_index) 86 | int argc; 87 | char *const *argv; 88 | const char *options; 89 | const struct option *long_options; 90 | int *opt_index; 91 | { 92 | return _getopt_internal(argc, argv, options, long_options, opt_index, 1); 93 | } 94 | 95 | 96 | #endif /* Not ELIDE_CODE. */ 97 | 98 | #ifdef TEST 99 | 100 | #include 101 | 102 | int 103 | main(argc, argv) 104 | int argc; 105 | char **argv; 106 | { 107 | int c; 108 | int digit_optind = 0; 109 | 110 | while (1) 111 | { 112 | int this_option_optind = optind ? optind : 1; 113 | int option_index = 0; 114 | static struct option long_options[] = { 115 | {"add", 1, 0, 0}, 116 | {"append", 0, 0, 0}, 117 | {"delete", 1, 0, 0}, 118 | {"verbose", 0, 0, 0}, 119 | {"create", 0, 0, 0}, 120 | {"file", 1, 0, 0}, 121 | {0, 0, 0, 0} 122 | }; 123 | 124 | c = 125 | getopt_long(argc, argv, "abc:d:0123456789", long_options, 126 | &option_index); 127 | if (c == -1) 128 | break; 129 | 130 | switch (c) 131 | { 132 | case 0: 133 | printf("option %s", long_options[option_index].name); 134 | if (optarg) 135 | printf(" with arg %s", optarg); 136 | printf("\n"); 137 | break; 138 | 139 | case '0': 140 | case '1': 141 | case '2': 142 | case '3': 143 | case '4': 144 | case '5': 145 | case '6': 146 | case '7': 147 | case '8': 148 | case '9': 149 | if (digit_optind != 0 && digit_optind != this_option_optind) 150 | printf("digits occur in two different argv-elements.\n"); 151 | digit_optind = this_option_optind; 152 | printf("option %c\n", c); 153 | break; 154 | 155 | case 'a': 156 | printf("option a\n"); 157 | break; 158 | 159 | case 'b': 160 | printf("option b\n"); 161 | break; 162 | 163 | case 'c': 164 | printf("option c with value `%s'\n", optarg); 165 | break; 166 | 167 | case 'd': 168 | printf("option d with value `%s'\n", optarg); 169 | break; 170 | 171 | case '?': 172 | break; 173 | 174 | default: 175 | printf("?? getopt returned character code 0%o ??\n", c); 176 | } 177 | } 178 | 179 | if (optind < argc) 180 | { 181 | printf("non-option ARGV-elements: "); 182 | while (optind < argc) 183 | printf("%s ", argv[optind++]); 184 | printf("\n"); 185 | } 186 | 187 | exit(0); 188 | } 189 | 190 | #endif /* TEST */ 191 | #endif /* HAVE_GETOPT_LONG */ 192 | -------------------------------------------------------------------------------- /src/directvnc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2001 Till Adam 3 | * Authors: Till Adam 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, a copy can be downloaded from 17 | * http://www.gnu.org/licenses/gpl.html, or obtained by writing to the 18 | * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 | * Boston, MA 02110-1301, USA. 20 | */ 21 | 22 | 23 | 24 | #ifndef DIRECTVNC_H 25 | #define DIRECTVNC_H 26 | 27 | /* global include file */ 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include "rfbproto.h" 35 | #include "vncauth.h" 36 | #include 37 | 38 | 39 | /* Note that the CoRRE encoding uses this buffer and assumes it is big enough 40 | to hold 255 * 255 * 32 bits -> 260100 bytes. 640*480 = 307200 bytes. 41 | Hextile also assumes it is big enough to hold 16 * 16 * 32 bits. 42 | Tight encoding assumes BUFFER_SIZE is at least 16384 bytes. */ 43 | 44 | #define BUFFER_SIZE (640*480) 45 | char buffer[BUFFER_SIZE]; 46 | 47 | #define MAX_ENCODINGS 10 48 | 49 | #ifdef WORDS_BIGENDIAN 50 | #define Swap16IfLE(s) (s) 51 | #define Swap32IfLE(l) (l) 52 | #else 53 | #define Swap16IfLE(s) ((((s) & 0xff) << 8) | (((s) >> 8) & 0xff)) 54 | #define Swap32IfLE(l) ((((l) & 0xff000000) >> 24) | \ 55 | (((l) & 0x00ff0000) >> 8) | \ 56 | (((l) & 0x0000ff00) << 8) | \ 57 | (((l) & 0x000000ff) << 24)) 58 | #endif /* WORDS_BIGENDIAN */ 59 | 60 | struct _mousestate 61 | { 62 | int x; 63 | int y; 64 | unsigned int buttonmask; 65 | }; 66 | 67 | struct _mousestate mousestate; 68 | 69 | int sock; 70 | 71 | /* rfb.c */ 72 | int rfb_connect_to_server (char *server, int display); 73 | int rfb_initialise_connection (); 74 | int rfb_set_format_and_encodings (); 75 | int rfb_send_update_request(int incremental); 76 | int rfb_handle_server_message (); 77 | int rfb_update_mouse (); 78 | int rfb_send_key_event(int key, int down_flag); 79 | void rfb_get_rgb_from_data(int *r, int *g, int *b, char *data); 80 | 81 | /* args.c */ 82 | struct serversettings 83 | { 84 | char *name; 85 | int width; 86 | int height; 87 | int bpp; 88 | int depth; 89 | int bigendian; 90 | int truecolour; 91 | int redmax; 92 | int greenmax; 93 | int bluemax; 94 | int redshift; 95 | int greenshift; 96 | int blueshift; 97 | }; 98 | 99 | struct clientsettings 100 | { 101 | int width; 102 | int height; 103 | int bpp; 104 | int depth; 105 | int bigendian; 106 | int truecolour; 107 | int redmax; 108 | int greenmax; 109 | int bluemax; 110 | int redshift; 111 | int greenshift; 112 | int blueshift; 113 | int compresslevel; 114 | int quality; 115 | }; 116 | 117 | 118 | struct __dfb_vnc_options 119 | { 120 | char *servername; 121 | int port; 122 | char *password; 123 | char *passwordfile; 124 | char *encodings; 125 | char *modmapfile; 126 | struct serversettings server; 127 | struct clientsettings client; 128 | int shared; 129 | int stretch; 130 | int localcursor; 131 | int poll_freq; 132 | /* not really options, but hey ;) */ 133 | double h_ratio; 134 | double v_ratio; 135 | int h_offset; 136 | int v_offset; 137 | }; 138 | 139 | 140 | typedef struct __dfb_vnc_options dfb_vnc_options; 141 | extern dfb_vnc_options opt; 142 | int args_parse(int argc, char **argv); 143 | 144 | /* sockets.c */ 145 | int read_from_rfb_server(int sock, char *out, unsigned int n); 146 | int write_exact(int sock, char *buf, unsigned int n); 147 | int set_non_blocking(int sock); 148 | 149 | /* dfb.c */ 150 | void dfb_init(int argc, char *argv[]); 151 | void dfb_deinit(); 152 | void fb_handle_error(DFBResult err); 153 | int dfb_write_data_to_screen(int x, int y, int w, int h, void *data); 154 | int dfb_process_events(void); 155 | int dfb_wait_for_event_with_timeout(int milliseconds); 156 | int dfb_copy_rect(int src_x, int src_y, int dest_x, int dest_y, int w, int h); 157 | int dfb_draw_rect_with_rgb(int x, int y, int w, int h, int r, int g, int b); 158 | IDirectFBSurface *dfb_create_cursor_saved_area(int width, int heigth); 159 | void dfb_save_cursor_rect( IDirectFBSurface *surf, int x, int y, int width, int heigth); 160 | void dfb_restore_cursor_rect( IDirectFBSurface *surf, int x, int y, int width, int heigth); 161 | 162 | /* cursor.c */ 163 | int HandleRichCursor(int x, int y, int w, int h); 164 | void SoftCursorLockArea(int x, int y, int w, int h); 165 | void SoftCursorUnlockScreen(void); 166 | void SoftCursorMove(int x, int y); 167 | 168 | /* modmap.c */ 169 | 170 | int modmap_read_file(char *filename); 171 | int modmap_translate_code(int keycode,DFBInputDeviceLockState lock, int shift); 172 | 173 | /* macro for a safe call to DirectFB functions */ 174 | #define DFBCHECK(x...) \ 175 | { \ 176 | err = x; \ 177 | if (err != DFB_OK) { \ 178 | fprintf( stderr, "%s <%d>:\n\t", __FILE__, __LINE__ ); \ 179 | DirectFBErrorFatal( #x, err ); \ 180 | } \ 181 | } 182 | 183 | #endif 184 | 185 | 186 | -------------------------------------------------------------------------------- /changelog: -------------------------------------------------------------------------------- 1 | Wed Jul 31 21:23:54 2011 Loris Boillet 2 | * New version: 0.7.7 3 | * Adds Keyboard Layout Switching support (thanks Dimitry Golubovsky) 4 | * Adds 24bpp support (thanks Dimitry Golubovsky) 5 | 6 | Wed Jan 13 22:39:24 2010 Loris Boillet 7 | * 7 years later... new version! 0.7.6 (bug fixes only) 8 | * Fix compatibility issue with DirectFB >= 0.9.24 9 | (Patch from "Roberto C. Sanchez" ) 10 | * Ran autoreconf -i to generate and update autoconf files. 11 | Fix autoconf warning 12 | * We now require DirectFB >= 0.9.24 13 | * Fix initialisation error which caused "raw" encoding to be always 14 | used, ignoring any command line option 15 | * Specify in man page that only 16 is available for the -bpp option 16 | (Patch from Marco Herrn ). Also fixed some spelling 17 | errors 18 | * Fix hangs, segfaults, and/or busy-loops (Patch from Brian Brunswick 19 | and Ola Lundqvist ) 20 | * Fix architecture independant files should be in $(prefix)/share 21 | according to FHS (Patch taken from debian) 22 | * Fix GCC warnings 23 | * Fix FSF address in licenses (thanks to licensecheck) 24 | * Updated Homepage and download place 25 | 26 | Fre Jan 24 10:31:03 2003 Till Adam 27 | * make screen update frequency configurable, to reduce cpu load 28 | 29 | Son Dez 01 16:14:36 2002 Till Adam 30 | * fix another problem pointed out by miguel sofer 31 | by clipping to client dimensions on server > client 32 | 33 | Sam Nov 30 19:29:49 2002 Till Adam 34 | * make it compile and work with 0.9.15 35 | * fix local cursor bug for client dimensions > server 36 | dimensions 37 | 38 | Fri Oct 11 12:34:24 2002 Till Adam 39 | * better autogen.sh 40 | * make configure.in work with current autofoo 41 | * add handler for sigint, so ctrl-c exits properly 42 | 43 | Sam Sep 21 23:34:45 2002 Till Adam 44 | * Add timeout between update request to minimize cpu utilization. 45 | * Fix control key remainging pressed between sessions. 46 | * Fix autofoo 47 | 48 | Sat Jul 20 13:08:40 2002 Till Adam 49 | * Release version 0.7 50 | 51 | Wed Jul 10 20:13:40 2002 Till Adam 52 | * add SoftCursorSupport which speeds up things as the cursor is 53 | * tracked locally and does not trigger screen updates 54 | 55 | Fri Jun 28 21:49:36 2002 Till Adam 56 | * fix keyboard handling (what crack have I been smoking?) 57 | * readd the X keysym files, so we dont need X headers 58 | 59 | Thu Jun 13 11:30:22 2002 Till Adam 60 | * bump required DFB version to 0.9.12 61 | * ask for password later, so no password works (reported by 62 | * Bitt Faulk and 63 | * Evan Langlois ) 64 | * misc fixups 65 | 66 | Mon Jun 03 21:08:42 2002 Till Adam 67 | * follow DFB 0.9.11 kay handling API changes 68 | * bump version to 0.7 69 | 70 | Fri May 31 17:13:52 2002 Till Adam 71 | * fix src/Makefile.am (how did this ever work?) 72 | * debian changes by Ovidiu Damian 73 | 74 | Fri Apr 26 18:29:39 2002 Till Adam 75 | * get tight and zlib encoding working 76 | * add command line paramters for jpeg quality and compresslevel 77 | * update man page 78 | 79 | Sun Apr 21 16:30:36 2002 Till Adam 80 | * start support for tight encoding 81 | * add zlib encoding 82 | 83 | Sat Feb 02 12:30:51 2002 Till Adam 84 | 85 | * more API changes to follow. 86 | * Dont use the ascii value sent for the return key, but send 87 | XK_Return, so a LF is added when appropriate. 88 | 89 | Fri Jan 18 22:11:07 2002 Till Adam 90 | 91 | * follow DFB API changes InputBuffer -> EventBuffer etc. 92 | 93 | Sat Jan 05 22:51:44 2002 Till Adam 94 | 95 | * handle non existant host names gracefully 96 | * include vncauth.h and rfbproto.h from vnc sources. They never change 97 | anyway and it removes the dependency 98 | 99 | Die Dez 11 21:09:41 2001 Till Adam 100 | 101 | * removed --stretch again. Doesnt look good at all and the code is 102 | much simpler without it. 103 | * use blit when doing copyrect - doh 104 | 105 | Sam Dez 08 10:31:05 2001 Till Adam 106 | 107 | * middle button is 2, right button is 3 not the other way around 108 | (ahem) 109 | * added spec file. No idea if it is any good, but it produces rpms 110 | somehow. Better than nothing 111 | 112 | Fre Nov 30 09:28:01 2001 Till Adam 113 | 114 | * changed the name from fbvnc to directvnc. There already is an app of 115 | that name. 116 | * move from sourceforge to savannah.gnu.org 117 | 118 | Son Nov 25 21:19:39 2001 Till Adam 119 | 120 | * added option --stretch, -x which causes the server image to be 121 | stretched or shrunk to the client resolution 122 | * added a few other options 123 | * updated man page 124 | * hitting now quits the client 125 | 126 | Don Nov 22 22:10:35 2001 Till Adam 127 | 128 | * fixed Bell messages and hopefully ServerCutText messages 129 | 130 | Sam Nov 17 22:22:39 2001 Till Adam 131 | 132 | * lots of changes 133 | * added option handling via getopt 134 | * huge speed increase through blitting instead of stretchblitting the 135 | whole screen - duh ;) 136 | * various clean ups 137 | 138 | Son Okt 21 15:21:53 2001 Till Adam 139 | 140 | * fixed errorneous (sp?) rgb calculation for rect drawing 141 | * dont flip the whole screen on every redraw 142 | 143 | Fre Aug 31 09:31:54 2001 Till Adam 144 | 145 | * added hextile, RRE and CoRRE encodings 146 | * scale mouse events from client to server resolution properly (until 147 | optional scaling is fixed, that is) 148 | 149 | Mon Aug 27 17:23:03 2001 Till Adam 150 | 151 | * sourceforge project created 152 | * initial import into cvs 153 | * add copy rect encoding 154 | 155 | Sam Aug 18 14:15:50 2001 Till Adam 156 | 157 | * project creation 158 | -------------------------------------------------------------------------------- /src/modmap.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2007 Dmitry Golubovsky 3 | * Authors: Dmitry Golubovsky 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, a copy can be downloaded from 17 | * http://www.gnu.org/licenses/gpl.html, or obtained by writing to the 18 | * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 | * Boston, MA 02110-1301, USA. 20 | */ 21 | 22 | /* 23 | * Part of this module is derived from XFREE86 sources, and has the following notice: 24 | */ 25 | 26 | /* 27 | * 28 | * Copyright 1988, 1998 The Open Group 29 | * 30 | * Permission to use, copy, modify, distribute, and sell this software and its 31 | * documentation for any purpose is hereby granted without fee, provided that 32 | * the above copyright notice appear in all copies and that both that 33 | * copyright notice and this permission notice appear in supporting 34 | * documentation. 35 | * 36 | * The above copyright notice and this permission notice shall be included 37 | * in all copies or substantial portions of the Software. 38 | * 39 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 40 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 41 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 42 | * IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR 43 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 44 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 45 | * OTHER DEALINGS IN THE SOFTWARE. 46 | * 47 | * Except as contained in this notice, the name of The Open Group shall 48 | * not be used in advertising or otherwise to promote the sale, use or 49 | * other dealings in this Software without prior written authorization 50 | * from The Open Group. 51 | */ 52 | 53 | 54 | #include 55 | #include 56 | #include "directvnc.h" 57 | #include "keysym.h" 58 | 59 | /* 60 | * This is an extension to the original directvnc enabling processing of a subset 61 | * of X11-style modmap file to provide better Unicode capabilities. Sources of this file 62 | * are based on original xmodmap sources. 63 | */ 64 | 65 | typedef struct { 66 | char keycode; 67 | int base; 68 | int shift; 69 | int mode; 70 | int modshift; 71 | } MAPENTRY; 72 | 73 | static MAPENTRY kbmap[256]; 74 | 75 | #define MIN_KEYCODE 8 76 | 77 | /* 78 | * Perform translation of the keycode to keysym. If there is no translation 79 | * for the given keycode, return XK_VoidSymbol. ScrollLock is hardcoded 80 | * to switch between modes. CAPS does not apply to all keys: roughly 81 | * approximating, assume that if base is a letter then CAPS applies. 82 | * It additionally applies to [];',./` if Scroll is on (but this may need 83 | * additional configuration for non-cyrillic keyboards). This assumption 84 | * is based on the fact that keysyms for ASCII characters are same as characters. 85 | */ 86 | 87 | int modmap_translate_code(int keycode,DFBInputDeviceLockState lock, int shift) { 88 | int apply_caps = 0; 89 | 90 | if (keycode > 255) 91 | return XK_VoidSymbol; 92 | 93 | keycode += MIN_KEYCODE; 94 | 95 | if (kbmap[keycode].keycode != keycode) 96 | return XK_VoidSymbol; 97 | 98 | if (isalpha(kbmap[keycode].base)) 99 | apply_caps = 1; 100 | 101 | if (lock & DILS_SCROLL && index ("[];',./`", kbmap[keycode].base) != NULL) 102 | apply_caps = 1; 103 | 104 | if (lock & DILS_CAPS && apply_caps) 105 | shift = !shift; 106 | 107 | return (lock & DILS_SCROLL) ? (shift ? kbmap[keycode].modshift : kbmap[keycode].mode) : 108 | (shift ? kbmap[keycode].shift : kbmap[keycode].base); 109 | } 110 | 111 | /* 112 | * Main entry: process a modmap file whose path is stored in options. 113 | */ 114 | 115 | static int process_file (char *); 116 | static void process_line (int, char *); 117 | 118 | int modmap_read_file(char *filename) 119 | { 120 | int i; 121 | 122 | for (i = 0; i < 256; i ++) { 123 | bzero (&kbmap[i],sizeof(MAPENTRY)); 124 | } 125 | 126 | return process_file(filename); 127 | } 128 | 129 | /* 130 | * filename: NULL means use stdin 131 | */ 132 | static int process_file (char *filename) 133 | { 134 | FILE *fp; 135 | char buffer[BUFSIZ]; 136 | int lineno; 137 | 138 | /* open the file, eventually we'll want to pipe through cpp */ 139 | if (!filename) { 140 | return 0; /* use the hardcoded map */ 141 | } else { 142 | fp = fopen (filename, "r"); 143 | if (!fp) { 144 | fprintf (stderr, "unable to open modmap file '%s' for reading\n", 145 | filename); 146 | return -1; 147 | } 148 | } 149 | 150 | for (lineno = 0; ; lineno++) { 151 | buffer[0] = '\0'; 152 | if (fgets (buffer, BUFSIZ, fp) == NULL) 153 | break; 154 | 155 | process_line (lineno, buffer); 156 | } 157 | 158 | (void) fclose (fp); 159 | return 0; 160 | } 161 | 162 | 163 | static void process_line (lineno, buffer) 164 | int lineno; 165 | char *buffer; 166 | { 167 | int len; 168 | int i; 169 | char *cp; 170 | 171 | char kkbuf[10]; 172 | MAPENTRY me; 173 | 174 | len = strlen (buffer); 175 | 176 | for (i = 0; i < len; i++) { /* look for blank lines */ 177 | register char c = buffer[i]; 178 | if (!(isspace(c) || c == '\n')) break; 179 | } 180 | if (i == len) return; 181 | 182 | cp = &buffer[i]; 183 | 184 | if (*cp == '!') return; /* look for comments */ 185 | len -= (cp - buffer); /* adjust len by how much we skipped */ 186 | 187 | /* pipe through cpp */ 188 | 189 | /* strip trailing space */ 190 | for (i = len-1; i >= 0; i--) { 191 | register char c = cp[i]; 192 | if (!(isspace(c) || c == '\n')) break; 193 | } 194 | if (i >= 0) cp[len = (i+1)] = '\0'; /* nul terminate */ 195 | 196 | /* handle input */ 197 | /*handle_line (cp, len);*/ 198 | 199 | me.keycode = 0; 200 | me.base = me.shift = me.mode = me.modshift = XK_VoidSymbol; 201 | 202 | sscanf(cp,"%s %c %x %x %x %x", kkbuf, &me.keycode, &me.base, &me.shift, &me.mode, &me.modshift); 203 | 204 | kbmap[me.keycode&0xFF] = me; 205 | } 206 | 207 | -------------------------------------------------------------------------------- /src/sockets.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. 3 | * 4 | * This is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This software is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, a copy can be downloaded from 16 | * http://www.gnu.org/licenses/gpl.html, or obtained by writing to the 17 | * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 18 | * Boston, MA 02110-1301, USA. 19 | */ 20 | 21 | /* 22 | * sockets.c - functions to deal with sockets. 23 | */ 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include "directvnc.h" 36 | 37 | void PrintInHex(char *buf, int len); 38 | 39 | int errorMessageOnReadFailure = 1; 40 | 41 | #define BUF_SIZE 8192 42 | static char buf[BUF_SIZE]; 43 | static char *bufoutptr = buf; 44 | static int buffered = 0; 45 | 46 | /* 47 | * ReadFromRFBServer is called whenever we want to read some data from the RFB 48 | * server. It is non-trivial for two reasons: 49 | * 50 | * 1. For efficiency it performs some intelligent buffering, avoiding invoking 51 | * the read() system call too often. For small chunks of data, it simply 52 | * copies the data out of an internal buffer. For large amounts of data it 53 | * reads directly into the buffer provided by the caller. 54 | * 55 | * 2. Whenever read() would block, it invokes the Xt event dispatching 56 | * mechanism to process X events. In fact, this is the only place these 57 | * events are processed, as there is no XtAppMainLoop in the program. 58 | */ 59 | 60 | 61 | int 62 | read_from_rfb_server(int sock, char *out, unsigned int n) 63 | { 64 | if (n <= buffered) 65 | { 66 | memcpy(out, bufoutptr, n); 67 | bufoutptr += n; 68 | buffered -= n; 69 | return 1; 70 | } 71 | 72 | memcpy(out, bufoutptr, buffered); 73 | out += buffered; 74 | n -= buffered; 75 | 76 | bufoutptr = buf; 77 | buffered = 0; 78 | 79 | if (n <= BUF_SIZE) 80 | { 81 | 82 | while (buffered < n) 83 | { 84 | int i = read(sock, buf + buffered, BUF_SIZE - buffered); 85 | 86 | if (i <= 0) 87 | { 88 | if (i < 0) 89 | { 90 | if (errno == EWOULDBLOCK || errno == EAGAIN) 91 | { 92 | dfb_process_events(); 93 | usleep(10000); 94 | i = 0; 95 | } 96 | else 97 | { 98 | fprintf(stderr, "DIRECTVNC"); 99 | perror(": read"); 100 | return -1; 101 | } 102 | } 103 | else 104 | { 105 | if (errorMessageOnReadFailure) 106 | { 107 | fprintf(stderr, "%s: VNC server closed connection\n", 108 | "DIRECTVNC"); 109 | } 110 | close(sock); 111 | dfb_deinit(); 112 | exit (-1); 113 | } 114 | } 115 | buffered += i; 116 | } 117 | 118 | memcpy(out, bufoutptr, n); 119 | bufoutptr += n; 120 | buffered -= n; 121 | return 1; 122 | 123 | } 124 | else 125 | { 126 | 127 | while (n > 0) 128 | { 129 | int i = read(sock, out, n); 130 | 131 | if (i <= 0) 132 | { 133 | if (i < 0) 134 | { 135 | if (errno == EWOULDBLOCK || errno == EAGAIN) 136 | { 137 | dfb_process_events(); 138 | usleep(10000); 139 | i = 0; 140 | } 141 | else 142 | { 143 | fprintf(stderr, "DIRECTVNC"); 144 | perror(": read"); 145 | return -1; 146 | } 147 | } 148 | else 149 | { 150 | if (errorMessageOnReadFailure) 151 | { 152 | fprintf(stderr, "%s: VNC server closed connection\n", 153 | "DIRECTVNC"); 154 | } 155 | close(sock); 156 | dfb_deinit(); 157 | exit (-1); 158 | } 159 | } 160 | out += i; 161 | n -= i; 162 | } 163 | 164 | return 1; 165 | } 166 | } 167 | 168 | 169 | /* 170 | * Write an exact number of bytes, and don't return until you've sent them. 171 | */ 172 | 173 | int 174 | write_exact(int sock, char *buf, unsigned int n) 175 | { 176 | fd_set fds; 177 | int i = 0; 178 | int j; 179 | 180 | while (i < n) 181 | { 182 | j = write(sock, buf + i, (n - i)); 183 | if (j <= 0) 184 | { 185 | if (j < 0) 186 | { 187 | if (errno == EWOULDBLOCK || errno == EAGAIN) 188 | { 189 | FD_ZERO(&fds); 190 | FD_SET(sock, &fds); 191 | 192 | if (select(sock + 1, NULL, &fds, NULL, NULL) <= 0) 193 | { 194 | fprintf(stderr, "DIRECTVNC"); 195 | perror(": select"); 196 | return -1; 197 | } 198 | j = 0; 199 | } 200 | else 201 | { 202 | fprintf(stderr, "DIRECTVNC"); 203 | perror(": write"); 204 | return -1; 205 | } 206 | } 207 | else 208 | { 209 | fprintf(stderr, "%s: write failed\n", "DIRECTVNC"); 210 | return -1; 211 | } 212 | } 213 | i += j; 214 | } 215 | return 1; 216 | } 217 | 218 | 219 | /* 220 | * SetNonBlocking sets a socket into non-blocking mode. 221 | */ 222 | 223 | int 224 | set_non_blocking(int sock) 225 | { 226 | if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) 227 | { 228 | fprintf(stderr, "DIRECTVNC Setting socket to non-blocking failed\n."); 229 | return -1; 230 | } 231 | return 1; 232 | } 233 | 234 | 235 | /* 236 | * Print out the contents of a packet for debugging. 237 | */ 238 | 239 | void 240 | PrintInHex(char *buf, int len) 241 | { 242 | int i, j; 243 | char c, str[17]; 244 | 245 | str[16] = 0; 246 | 247 | fprintf(stderr, "ReadExact: "); 248 | 249 | for (i = 0; i < len; i++) 250 | { 251 | if ((i % 16 == 0) && (i != 0)) 252 | { 253 | fprintf(stderr, " "); 254 | } 255 | c = buf[i]; 256 | str[i % 16] = (((c > 31) && (c < 127)) ? c : '.'); 257 | fprintf(stderr, "%02x ", (unsigned char) c); 258 | if ((i % 4) == 3) 259 | fprintf(stderr, " "); 260 | if ((i % 16) == 15) 261 | { 262 | fprintf(stderr, "%s\n", str); 263 | } 264 | } 265 | if ((i % 16) != 0) 266 | { 267 | for (j = i % 16; j < 16; j++) 268 | { 269 | fprintf(stderr, " "); 270 | if ((j % 4) == 3) 271 | fprintf(stderr, " "); 272 | } 273 | str[i % 16] = 0; 274 | fprintf(stderr, "%s\n", str); 275 | } 276 | 277 | fflush(stderr); 278 | } 279 | -------------------------------------------------------------------------------- /src/args.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2001 Till Adam 3 | * Authors: Till Adam 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, a copy can be downloaded from 17 | * http://www.gnu.org/licenses/gpl.html, or obtained by writing to the 18 | * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 | * Boston, MA 02110-1301, USA. 20 | */ 21 | 22 | #include "config.h" 23 | #include "directvnc.h" 24 | #include "getopt.h" 25 | #include 26 | 27 | dfb_vnc_options opt; 28 | static void show_usage_and_exit(); 29 | static void show_version(); 30 | static void _parse_options_array(int argc, char **argv); 31 | 32 | int 33 | args_parse(int argc, char **argv) 34 | { 35 | char *buf; 36 | 37 | if (argc <= 1) 38 | show_usage_and_exit(); 39 | 40 | 41 | /* servername and display like so: 192.168.0.1:1 or so: localhost:2 */ 42 | buf = argv[1]; 43 | 44 | buf = strtok (buf, ":"); 45 | opt.servername = strdup(buf); 46 | if ( (buf = strtok(NULL, "")) ) 47 | opt.port = atoi(buf); 48 | else 49 | printf("You did not specify a display to connect to. I will assume 0.\n"); 50 | 51 | /* set some default values */ 52 | opt.client.width = 1024; 53 | opt.client.height = 768; 54 | 55 | opt.client.bpp = 16; 56 | opt.client.depth = 16; 57 | opt.client.bigendian = 0; 58 | opt.client.truecolour = 1; 59 | opt.client.redmax = 31; 60 | opt.client.greenmax = 63; 61 | opt.client.bluemax = 31; 62 | opt.client.redshift =11; 63 | opt.client.greenshift = 5; 64 | opt.client.blueshift = 0; 65 | opt.client.compresslevel = 99; 66 | opt.client.quality = 99; 67 | 68 | opt.shared = 1; 69 | opt.localcursor = 1; 70 | opt.poll_freq = 50; 71 | 72 | opt.h_ratio = 1; 73 | opt.v_ratio = 1; 74 | opt.h_offset = 0; 75 | opt.v_offset = 0; 76 | 77 | #ifdef DEBUG 78 | fprintf(stderr, "server: %s\n", opt.servername); 79 | fprintf(stderr, "port: %d\n", opt.port); 80 | #endif 81 | 82 | /* now go and parse the command line */ 83 | _parse_options_array(argc, argv); 84 | 85 | return 1; 86 | } 87 | 88 | static void 89 | _parse_options_array(int argc, char **argv) 90 | { 91 | static char sopts[] = { 92 | /* actions */ 93 | 'h', 94 | 'v', 95 | 96 | /* options */ 97 | 'b', ':', 98 | 'c', ':', 99 | 'q', ':', 100 | 'p', ':', 101 | 'P', ':', 102 | 'e', ':', 103 | 's', 104 | 'n', 105 | 'l', 106 | 'f', ':', 107 | 'm', ':', 108 | 109 | 0 110 | }; 111 | 112 | static struct option lopts[] = { 113 | /* actions */ 114 | {"help", 0, NULL, 'h'}, 115 | {"version", 0, NULL, 'v'}, 116 | 117 | /* options */ 118 | {"bpp", 1, NULL, 'b'}, 119 | {"compresslevel", 1, NULL, 'c'}, 120 | {"quality", 1, NULL, 'q'}, 121 | {"password", 1, NULL, 'p'}, 122 | {"passwordfile", 1, NULL, 'P'}, 123 | {"encodings", 1, NULL, 'e'}, 124 | {"shared", 0, NULL, 's'}, 125 | {"noshared", 0, NULL, 'n'}, 126 | {"nolocalcursor", 0, NULL, 'l'}, 127 | {"pollfrequency", 1, NULL, 'f'}, 128 | {"modmap", 1, NULL, 'm'}, 129 | 130 | {0, 0, 0, 0} 131 | }; 132 | int optch = 0, opti = 0; 133 | 134 | /* Now to parse some optionarinos */ 135 | while ((optch = getopt_long_only(argc, argv, sopts, lopts, &opti)) != -1) 136 | { 137 | int intarg = 0; 138 | switch (optch) 139 | { 140 | case 0: 141 | break; 142 | 143 | case 'h': 144 | show_usage_and_exit(); 145 | break; 146 | case 'v': 147 | show_version(); 148 | exit(1); 149 | break; 150 | 151 | case 'b': 152 | intarg = atoi(optarg); 153 | switch (intarg) { 154 | case 24: 155 | opt.client.bpp=32; 156 | opt.client.depth=intarg; 157 | opt.client.redmax=255; 158 | opt.client.bluemax=255; 159 | opt.client.greenmax=255; 160 | opt.client.redshift=16; 161 | opt.client.greenshift=8; 162 | opt.client.blueshift=0; 163 | break; 164 | case 16: 165 | opt.client.bpp = intarg; 166 | break; 167 | case 8: 168 | case 32: 169 | default: 170 | fprintf(stderr, "Depth currently not supported!\n"); 171 | exit(-1); 172 | } 173 | break; 174 | case 'f': 175 | opt.poll_freq = atoi(optarg); 176 | break; 177 | case 'p': 178 | opt.password = strdup(optarg); 179 | break; 180 | case 'P': 181 | opt.passwordfile = strdup(optarg); 182 | break; 183 | case 'e': 184 | opt.encodings = strdup(optarg); 185 | break; 186 | case 'm': 187 | opt.modmapfile = strdup(optarg); 188 | break; 189 | case 's': 190 | opt.shared = 1; 191 | break; 192 | case 'n': 193 | opt.shared = 0; 194 | break; 195 | case 'l': 196 | opt.localcursor = 0; 197 | break; 198 | case 'c': 199 | intarg = atoi(optarg); 200 | if (intarg >= 0 && intarg <= 9) { 201 | opt.client.compresslevel = intarg; 202 | } else { 203 | fprintf(stderr, "Invalid compression level: %s\n", optarg); 204 | exit(-2); 205 | } 206 | break; 207 | case 'q': 208 | intarg = atoi(optarg); 209 | if (intarg >= 0 && intarg <= 9) { 210 | opt.client.quality = intarg; 211 | } else { 212 | fprintf(stderr, "Invalid quality level: %s\n", optarg); 213 | exit(-2); 214 | } 215 | break; 216 | 217 | } 218 | } 219 | } 220 | 221 | static void 222 | show_usage_and_exit() 223 | { 224 | 225 | fprintf(stderr, "\n" 226 | "DirectVNC viewer version %s\n" 227 | "\n" 228 | "Usage: directvnc [:] []\n" 229 | "\n" 230 | "with\n" 231 | " server " "VNC host to connect to.\n" 232 | " display " "Optional display number (default: 0).\n" 233 | "\n" 234 | "and options being:\n" 235 | /*0 1 2 */ /*3 4 5 6 7 */ 236 | /*12345678901234567890123456789*/ /*0123456789012345678901234567890123456789012345678*/ 237 | " -p, --password STRING " "Password for the server.\n" 238 | " -P, --passwordfile FILENAME" "Password file for the server.\n" 239 | " -b, --bpp NUM " "Set the clients bit per pixel to NUM.\n" 240 | " -f, --pollfrequency MS " "Time between checks for events in milliseconds.\n" 241 | " -l, --nolocalcursor " "Disable local cursor handling.\n" 242 | " -s, --shared " "Don't disonnect already connected clients.\n" 243 | " -n, --noshared " "Disconnect already connected clients.\n" 244 | " -e, --encodings \"STRING\" " "List of encodings to be used in order of\n" 245 | " " "preference (e.g. \"hextile copyrect\").\n" 246 | " -c, --compresslevel LEVEL " "Compression level (0..9) to be used by zlib.\n" 247 | " -q, --quality LEVEL " "Quality level (0..9) to be used by jpeg\n" 248 | " " "compression in tight encoding.\n" 249 | " -m, --modmap STRING " "Path to the modmap (subset of X-style) file to load\n" 250 | " -h, --help " "Show this text and exit.\n" 251 | " -v, --version " "Show version information and exit.\n" 252 | "\n" 253 | , VERSION 254 | ); 255 | exit(1); 256 | } 257 | 258 | static void 259 | show_version() 260 | { 261 | fprintf(stderr, "This is version %s of DirectVNC\n", VERSION); 262 | } 263 | -------------------------------------------------------------------------------- /INSTALL: -------------------------------------------------------------------------------- 1 | Basic Installation 2 | ================== 3 | 4 | These are generic installation instructions. 5 | 6 | The `configure' shell script attempts to guess correct values for 7 | various system-dependent variables used during compilation. It uses 8 | those values to create a `Makefile' in each directory of the package. 9 | It may also create one or more `.h' files containing system-dependent 10 | definitions. Finally, it creates a shell script `config.status' that 11 | you can run in the future to recreate the current configuration, a file 12 | `config.cache' that saves the results of its tests to speed up 13 | reconfiguring, and a file `config.log' containing compiler output 14 | (useful mainly for debugging `configure'). 15 | 16 | If you need to do unusual things to compile the package, please try 17 | to figure out how `configure' could check whether to do them, and mail 18 | diffs or instructions to the address given in the `README' so they can 19 | be considered for the next release. If at some point `config.cache' 20 | contains results you don't want to keep, you may remove or edit it. 21 | 22 | The file `configure.in' is used to create `configure' by a program 23 | called `autoconf'. You only need `configure.in' if you want to change 24 | it or regenerate `configure' using a newer version of `autoconf'. 25 | 26 | The simplest way to compile this package is: 27 | 28 | 1. `cd' to the directory containing the package's source code and type 29 | `./configure' to configure the package for your system. If you're 30 | using `csh' on an old version of System V, you might need to type 31 | `sh ./configure' instead to prevent `csh' from trying to execute 32 | `configure' itself. 33 | 34 | Running `configure' takes awhile. While running, it prints some 35 | messages telling which features it is checking for. 36 | 37 | 2. Type `make' to compile the package. 38 | 39 | 3. Optionally, type `make check' to run any self-tests that come with 40 | the package. 41 | 42 | 4. Type `make install' to install the programs and any data files and 43 | documentation. 44 | 45 | 5. You can remove the program binaries and object files from the 46 | source code directory by typing `make clean'. To also remove the 47 | files that `configure' created (so you can compile the package for 48 | a different kind of computer), type `make distclean'. There is 49 | also a `make maintainer-clean' target, but that is intended mainly 50 | for the package's developers. If you use it, you may have to get 51 | all sorts of other programs in order to regenerate files that came 52 | with the distribution. 53 | 54 | Compilers and Options 55 | ===================== 56 | 57 | Some systems require unusual options for compilation or linking that 58 | the `configure' script does not know about. You can give `configure' 59 | initial values for variables by setting them in the environment. Using 60 | a Bourne-compatible shell, you can do that on the command line like 61 | this: 62 | CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure 63 | 64 | Or on systems that have the `env' program, you can do it like this: 65 | env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure 66 | 67 | Compiling For Multiple Architectures 68 | ==================================== 69 | 70 | You can compile the package for more than one kind of computer at the 71 | same time, by placing the object files for each architecture in their 72 | own directory. To do this, you must use a version of `make' that 73 | supports the `VPATH' variable, such as GNU `make'. `cd' to the 74 | directory where you want the object files and executables to go and run 75 | the `configure' script. `configure' automatically checks for the 76 | source code in the directory that `configure' is in and in `..'. 77 | 78 | If you have to use a `make' that does not supports the `VPATH' 79 | variable, you have to compile the package for one architecture at a time 80 | in the source code directory. After you have installed the package for 81 | one architecture, use `make distclean' before reconfiguring for another 82 | architecture. 83 | 84 | Installation Names 85 | ================== 86 | 87 | By default, `make install' will install the package's files in 88 | `/usr/local/bin', `/usr/local/man', etc. You can specify an 89 | installation prefix other than `/usr/local' by giving `configure' the 90 | option `--prefix=PATH'. 91 | 92 | You can specify separate installation prefixes for 93 | architecture-specific files and architecture-independent files. If you 94 | give `configure' the option `--exec-prefix=PATH', the package will use 95 | PATH as the prefix for installing programs and libraries. 96 | Documentation and other data files will still use the regular prefix. 97 | 98 | In addition, if you use an unusual directory layout you can give 99 | options like `--bindir=PATH' to specify different values for particular 100 | kinds of files. Run `configure --help' for a list of the directories 101 | you can set and what kinds of files go in them. 102 | 103 | If the package supports it, you can cause programs to be installed 104 | with an extra prefix or suffix on their names by giving `configure' the 105 | option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. 106 | 107 | Optional Features 108 | ================= 109 | 110 | Some packages pay attention to `--enable-FEATURE' options to 111 | `configure', where FEATURE indicates an optional part of the package. 112 | They may also pay attention to `--with-PACKAGE' options, where PACKAGE 113 | is something like `gnu-as' or `x' (for the X Window System). The 114 | `README' should mention any `--enable-' and `--with-' options that the 115 | package recognizes. 116 | 117 | For packages that use the X Window System, `configure' can usually 118 | find the X include and library files automatically, but if it doesn't, 119 | you can use the `configure' options `--x-includes=DIR' and 120 | `--x-libraries=DIR' to specify their locations. 121 | 122 | Specifying the System Type 123 | ========================== 124 | 125 | There may be some features `configure' can not figure out 126 | automatically, but needs to determine by the type of host the package 127 | will run on. Usually `configure' can figure that out, but if it prints 128 | a message saying it can not guess the host type, give it the 129 | `--host=TYPE' option. TYPE can either be a short name for the system 130 | type, such as `sun4', or a canonical name with three fields: 131 | CPU-COMPANY-SYSTEM 132 | 133 | See the file `config.sub' for the possible values of each field. If 134 | `config.sub' isn't included in this package, then this package doesn't 135 | need to know the host type. 136 | 137 | If you are building compiler tools for cross-compiling, you can also 138 | use the `--target=TYPE' option to select the type of system they will 139 | produce code for and the `--build=TYPE' option to select the type of 140 | system on which you are compiling the package. 141 | 142 | Sharing Defaults 143 | ================ 144 | 145 | If you want to set default values for `configure' scripts to share, 146 | you can create a site shell script called `config.site' that gives 147 | default values for variables like `CC', `cache_file', and `prefix'. 148 | `configure' looks for `PREFIX/share/config.site' if it exists, then 149 | `PREFIX/etc/config.site' if it exists. Or, you can set the 150 | `CONFIG_SITE' environment variable to the location of the site script. 151 | A warning: not all `configure' scripts look for a site script. 152 | 153 | Operation Controls 154 | ================== 155 | 156 | `configure' recognizes the following options to control how it 157 | operates. 158 | 159 | `--cache-file=FILE' 160 | Use and save the results of the tests in FILE instead of 161 | `./config.cache'. Set FILE to `/dev/null' to disable caching, for 162 | debugging `configure'. 163 | 164 | `--help' 165 | Print a summary of the options to `configure', and exit. 166 | 167 | `--quiet' 168 | `--silent' 169 | `-q' 170 | Do not print messages saying which checks are being made. To 171 | suppress all normal output, redirect it to `/dev/null' (any error 172 | messages will still be shown). 173 | 174 | `--srcdir=DIR' 175 | Look for the package's source code in directory DIR. Usually 176 | `configure' can determine that directory automatically. 177 | 178 | `--version' 179 | Print the version of Autoconf used to generate the `configure' 180 | script, and exit. 181 | 182 | `configure' also accepts some other, not widely useful, options. 183 | -------------------------------------------------------------------------------- /src/cursor.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2001 Const Kaplinsky. All Rights Reserved. 3 | * 4 | * This is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This software is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, a copy can be downloaded from 16 | * http://www.gnu.org/licenses/gpl.html, or obtained by writing to the 17 | * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 18 | * Boston, MA 02110-1301, USA. 19 | */ 20 | 21 | /* 22 | * cursor.c - code to support cursor shape updates (XCursor, RichCursor). 23 | */ 24 | 25 | 26 | #include "directvnc.h" 27 | 28 | #define OPER_SAVE 0 29 | #define OPER_RESTORE 1 30 | 31 | #define Bool int 32 | #define True 1 33 | #define False 0 34 | 35 | 36 | /* Data kept for RichCursor encoding support. */ 37 | static Bool prevRichCursorSet = False; 38 | static IDirectFBSurface *rcSavedArea = NULL; 39 | static CARD8 *rcSource, *rcMask; 40 | static int rcHotX, rcHotY, rcWidth, rcHeight; 41 | static int rcCursorX = 0, rcCursorY = 0; 42 | static int rcLockX, rcLockY, rcLockWidth, rcLockHeight; 43 | static Bool rcCursorHidden, rcLockSet; 44 | 45 | static Bool SoftCursorInLockedArea(void); 46 | static void SoftCursorCopyArea(int oper); 47 | static void SoftCursorDraw(void); 48 | static void FreeCursors(Bool setDotCursor); 49 | 50 | 51 | /********************************************************************* 52 | * HandleRichCursor(). RichCursor shape updates support. This 53 | * variation of cursor shape updates cannot be supported directly via 54 | * Xlib cursors so we have to emulate cursor operating on the frame 55 | * buffer (that is why we call it "software cursor"). 56 | ********************************************************************/ 57 | 58 | Bool HandleRichCursor(int xhot, int yhot, int width, int height) 59 | { 60 | size_t bytesPerRow, bytesMaskData; 61 | char *buf; 62 | CARD8 *ptr; 63 | int x, y, b; 64 | 65 | bytesPerRow = (width + 7) / 8; 66 | bytesMaskData = bytesPerRow * height; 67 | 68 | FreeCursors(True); 69 | 70 | if (width * height == 0) 71 | return True; 72 | 73 | /* Read cursor pixel data. */ 74 | 75 | rcSource = malloc(width * height * (opt.client.bpp / 8)); 76 | if (rcSource == NULL) 77 | return False; 78 | 79 | if (!read_from_rfb_server(sock, (char *)rcSource, 80 | width * height * (opt.client.bpp / 8))) { 81 | free(rcSource); 82 | return False; 83 | } 84 | 85 | /* Read and decode mask data. */ 86 | 87 | buf = malloc(bytesMaskData); 88 | if (buf == NULL) { 89 | free(rcSource); 90 | return False; 91 | } 92 | 93 | if (!read_from_rfb_server(sock, buf, bytesMaskData)) { 94 | free(rcSource); 95 | free(buf); 96 | return False; 97 | } 98 | 99 | rcMask = malloc(width * height); 100 | if (rcMask == NULL) { 101 | free(rcSource); 102 | free(buf); 103 | return False; 104 | } 105 | 106 | ptr = rcMask; 107 | for (y = 0; y < height; y++) { 108 | for (x = 0; x < width / 8; x++) { 109 | for (b = 7; b >= 0; b--) { 110 | *ptr++ = buf[y * bytesPerRow + x] >> b & 1; 111 | } 112 | } 113 | for (b = 7; b > 7 - width % 8; b--) { 114 | *ptr++ = buf[y * bytesPerRow + x] >> b & 1; 115 | } 116 | } 117 | 118 | free(buf); 119 | 120 | /* Set remaining data associated with cursor. */ 121 | rcSavedArea = dfb_create_cursor_saved_area(width, height); 122 | if (!rcSavedArea) { 123 | return False; 124 | } 125 | 126 | rcHotX = xhot; 127 | rcHotY = yhot; 128 | rcWidth = width; 129 | rcHeight = height; 130 | 131 | SoftCursorCopyArea(OPER_SAVE); 132 | SoftCursorDraw(); 133 | 134 | rcCursorHidden = False; 135 | rcLockSet = False; 136 | 137 | prevRichCursorSet = True; 138 | return True; 139 | } 140 | 141 | 142 | /********************************************************************* 143 | * SoftCursorLockArea(). This function should be used to prevent 144 | * collisions between simultaneous framebuffer update operations and 145 | * cursor drawing operations caused by movements of pointing device. 146 | * The parameters denote a rectangle where mouse cursor should not be 147 | * drawn. Every next call to this function expands locked area so 148 | * previous locks remain active. 149 | ********************************************************************/ 150 | 151 | void SoftCursorLockArea(int x, int y, int w, int h) 152 | { 153 | int newX, newY; 154 | if (!prevRichCursorSet) 155 | return; 156 | 157 | if (!rcLockSet) { 158 | rcLockX = x; 159 | rcLockY = y; 160 | rcLockWidth = w; 161 | rcLockHeight = h; 162 | rcLockSet = True; 163 | } else { 164 | newX = (x < rcLockX) ? x : rcLockX; 165 | newY = (y < rcLockY) ? y : rcLockY; 166 | rcLockWidth = (x + w > rcLockX + rcLockWidth) ? 167 | (x + w - newX) : (rcLockX + rcLockWidth - newX); 168 | rcLockHeight = (y + h > rcLockY + rcLockHeight) ? 169 | (y + h - newY) : (rcLockY + rcLockHeight - newY); 170 | rcLockX = newX; 171 | rcLockY = newY; 172 | } 173 | 174 | if (!rcCursorHidden && SoftCursorInLockedArea()) { 175 | SoftCursorCopyArea(OPER_RESTORE); 176 | rcCursorHidden = True; 177 | } 178 | } 179 | 180 | /********************************************************************* 181 | * SoftCursorUnlockScreen(). This function discards all locks 182 | * performed since previous SoftCursorUnlockScreen() call. 183 | ********************************************************************/ 184 | 185 | void SoftCursorUnlockScreen(void) 186 | { 187 | if (!prevRichCursorSet) 188 | return; 189 | 190 | if (rcCursorHidden) { 191 | SoftCursorCopyArea(OPER_SAVE); 192 | SoftCursorDraw(); 193 | rcCursorHidden = False; 194 | } 195 | rcLockSet = False; 196 | } 197 | 198 | /********************************************************************* 199 | * SoftCursorMove(). Moves soft cursor in particular location. This 200 | * function respects locking of screen areas so when the cursor is 201 | * moved in the locked area, it becomes invisible until 202 | * SoftCursorUnlock() functions is called. 203 | ********************************************************************/ 204 | 205 | void SoftCursorMove(int x, int y) 206 | { 207 | if (prevRichCursorSet && !rcCursorHidden) { 208 | SoftCursorCopyArea(OPER_RESTORE); 209 | rcCursorHidden = True; 210 | } 211 | 212 | rcCursorX = x; 213 | rcCursorY = y; 214 | 215 | if (prevRichCursorSet && !(rcLockSet && SoftCursorInLockedArea())) { 216 | SoftCursorCopyArea(OPER_SAVE); 217 | SoftCursorDraw(); 218 | rcCursorHidden = False; 219 | } 220 | } 221 | 222 | 223 | /********************************************************************* 224 | * Internal (static) low-level functions. 225 | ********************************************************************/ 226 | 227 | static Bool SoftCursorInLockedArea(void) 228 | { 229 | return (rcLockX < rcCursorX - rcHotX + rcWidth && 230 | rcLockY < rcCursorY - rcHotY + rcHeight && 231 | rcLockX + rcLockWidth > rcCursorX - rcHotX && 232 | rcLockY + rcLockHeight > rcCursorY - rcHotY); 233 | } 234 | 235 | static void SoftCursorCopyArea(int oper) 236 | { 237 | int x, y, w, h; 238 | 239 | x = rcCursorX - rcHotX; 240 | y = rcCursorY - rcHotY; 241 | if (x >= opt.server.width || y >= opt.server.height) 242 | return; 243 | 244 | w = rcWidth; 245 | h = rcHeight; 246 | if (x < 0) { 247 | w += x; 248 | x = 0; 249 | } else if (x + w > opt.server.width) { 250 | w = opt.server.width - x; 251 | } 252 | if (y < 0) { 253 | h += y; 254 | y = 0; 255 | } else if (y + h > opt.server.height) { 256 | h = opt.server.height - y; 257 | } 258 | 259 | if (oper == OPER_SAVE) { 260 | /* Save screen area in memory. */ 261 | dfb_save_cursor_rect(rcSavedArea, x,y,w,h); 262 | } else { 263 | /* Restore screen area. */ 264 | dfb_restore_cursor_rect(rcSavedArea, x,y,w,h); 265 | } 266 | } 267 | 268 | static void SoftCursorDraw(void) 269 | { 270 | int x, y, x0, y0; 271 | int offset, bytesPerPixel; 272 | char *pos; 273 | int r,g,b; 274 | 275 | bytesPerPixel = opt.client.bpp / 8; 276 | 277 | /* FIXME: Speed optimization is possible. */ 278 | for (y = 0; y < rcHeight; y++) { 279 | y0 = rcCursorY - rcHotY + y; 280 | if (y0 >= 0 && y0 < opt.server.height) { 281 | for (x = 0; x < rcWidth; x++) { 282 | x0 = rcCursorX - rcHotX + x; 283 | if (x0 >= 0 && x0 < opt.server.width) { 284 | offset = y * rcWidth + x; 285 | if (rcMask[offset]) { 286 | pos = (char *)&rcSource[offset * bytesPerPixel]; 287 | rfb_get_rgb_from_data(&r, &g, &b, pos); 288 | dfb_draw_rect_with_rgb(x0, y0, 1, 1, r,g,b); 289 | } 290 | } 291 | } 292 | } 293 | } 294 | } 295 | 296 | static void FreeCursors(Bool setDotCursor) 297 | { 298 | 299 | if (prevRichCursorSet) { 300 | SoftCursorCopyArea(OPER_RESTORE); 301 | free(rcSource); 302 | free(rcMask); 303 | prevRichCursorSet = False; 304 | } 305 | } 306 | 307 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc. 5 | 675 Mass Ave, Cambridge, MA 02139, USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Library General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | -------------------------------------------------------------------------------- /src/tight.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2001 Till Adam 3 | * Authors: Till Adam 4 | * 5 | * original implementation by Constantin Kaplinsky 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, a copy can be downloaded from 19 | * http://www.gnu.org/licenses/gpl.html, or obtained by writing to the 20 | * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 21 | * Boston, MA 02110-1301, USA. 22 | */ 23 | 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | #include "directvnc.h" 36 | #include "jpeg.h" 37 | #include "tight.h" 38 | 39 | /* 40 | * Variables for the ``tight'' encoding implementation. 41 | */ 42 | #define RGB_TO_PIXEL(bpp,r,g,b) \ 43 | (((CARD16)(r) & opt.client.redmax) << opt.client.redshift | \ 44 | ((CARD16)(g) & opt.client.greenmax) << opt.client.greenshift | \ 45 | ((CARD16)(b) & opt.client.bluemax) << opt.client.blueshift) 46 | 47 | #define TIGHT_MIN_TO_COMPRESS 12 48 | /* Separate buffer for compressed data. */ 49 | #define ZLIB_BUFFER_SIZE 512 50 | static char zlib_buffer[ZLIB_BUFFER_SIZE]; 51 | 52 | /* Four independent compression streams for zlib library. */ 53 | static z_stream zlibStream[4]; 54 | static int zlibStreamActive[4] = { 55 | 0, 0, 0, 0 56 | }; 57 | 58 | /* Filter stuff. Should be initialized by filter initialization code. */ 59 | static int cutZeros; 60 | static int rectWidth, rectColors; 61 | static char tightPalette[256*4]; 62 | static CARD8 tightPrevRow[2048*3*sizeof(CARD16)]; 63 | 64 | /* zlib stuff */ 65 | static int raw_buffer_size = -1; 66 | static char *raw_buffer; 67 | static z_stream decompStream; 68 | static int decompStreamInited = 0; 69 | 70 | 71 | 72 | int 73 | _handle_tight_encoded_message(rfbFramebufferUpdateRectHeader rectheader) 74 | { 75 | CARD8 comp_ctl; 76 | CARD8 filter_id; 77 | CARD16 fill_colour; 78 | int r=0, g=0, b=0; 79 | filterPtr filterFn; 80 | int err, stream_id, compressedLen, bitsPixel; 81 | int bufferSize, rowSize, numRows, portionLen, rowsProcessed, extraBytes; 82 | void *dst; 83 | z_streamp zs; 84 | 85 | /* read the compression type */ 86 | if (!read_from_rfb_server(sock, (char*)&comp_ctl, 1)) return 0; 87 | 88 | /* The lower 4 bits are apparently used as active flags for the zlib 89 | * streams. Iterate over them and right shift 1, so the encoding ends up in 90 | * the first 4 bits. */ 91 | for (stream_id = 0; stream_id < 4; stream_id++) { 92 | if ((comp_ctl & 1) && zlibStreamActive[stream_id]) { 93 | if (inflateEnd (&zlibStream[stream_id]) != Z_OK && 94 | zlibStream[stream_id].msg != NULL) 95 | fprintf(stderr, "inflateEnd: %s\n", zlibStream[stream_id].msg); 96 | zlibStreamActive[stream_id] = 0; 97 | } 98 | comp_ctl >>= 1; 99 | } 100 | 101 | /* Handle solid rectangles. */ 102 | if (comp_ctl == rfbTightFill) { 103 | 104 | if (!read_from_rfb_server(sock, (char*)&fill_colour, sizeof(fill_colour))) 105 | return 0; 106 | 107 | rfb_get_rgb_from_data(&r, &g, &b, (char*)&fill_colour); 108 | dfb_draw_rect_with_rgb( 109 | rectheader.r.x, 110 | rectheader.r.y, 111 | rectheader.r.w, 112 | rectheader.r.h, 113 | r,g,b 114 | ); 115 | return 1; 116 | } 117 | 118 | /* Handle jpeg compressed rectangle */ 119 | if (comp_ctl == rfbTightJpeg) { 120 | return DecompressJpegRect( 121 | rectheader.r.x, 122 | rectheader.r.y, 123 | rectheader.r.w, 124 | rectheader.r.h); 125 | } 126 | 127 | /* Quit on unsupported subencoding value. */ 128 | if (comp_ctl > rfbTightMaxSubencoding) { 129 | fprintf(stderr, "Tight encoding: bad subencoding value received.\n"); 130 | return 0; 131 | } 132 | 133 | /* 134 | * Here primary compression mode handling begins. 135 | * Data was processed with optional filter + zlib compression. 136 | */ 137 | 138 | /* First, we should identify a filter to use. */ 139 | if ((comp_ctl & rfbTightExplicitFilter) != 0) { 140 | if (!read_from_rfb_server(sock, (char*)&filter_id, 1)) 141 | return 0; 142 | 143 | switch (filter_id) { 144 | case rfbTightFilterCopy: 145 | filterFn = FilterCopy; 146 | bitsPixel = InitFilterCopy(rectheader.r.w, rectheader.r.h); 147 | break; 148 | case rfbTightFilterPalette: 149 | filterFn = FilterPalette; 150 | bitsPixel = InitFilterPalette(rectheader.r.w, rectheader.r.h); 151 | break; 152 | case rfbTightFilterGradient: 153 | filterFn = FilterGradient; 154 | bitsPixel = InitFilterGradient(rectheader.r.w, rectheader.r.h); 155 | break; 156 | default: 157 | fprintf(stderr, "Tight encoding: unknown filter code received.\n"); 158 | return 0; 159 | } 160 | } else { 161 | filterFn = FilterCopy; 162 | bitsPixel = InitFilterCopy(rectheader.r.w, rectheader.r.h); 163 | } 164 | if (bitsPixel == 0) { 165 | fprintf(stderr, "Tight encoding: error receiving palette.\n"); 166 | return 0; 167 | } 168 | 169 | /* Determine if the data should be decompressed or just copied. */ 170 | rowSize = (rectheader.r.w * bitsPixel + 7) / 8; 171 | 172 | /* rect is to small to be compressed reasonably, simply copy */ 173 | if (rectheader.r.h * rowSize < TIGHT_MIN_TO_COMPRESS) { 174 | if (!read_from_rfb_server(sock, (char*)buffer, rectheader.r.h * rowSize)) 175 | return 0; 176 | 177 | dst = (void *) &buffer[TIGHT_MIN_TO_COMPRESS * 4]; 178 | filterFn(rectheader.r.h, buffer, dst); 179 | dfb_write_data_to_screen( 180 | rectheader.r.x, 181 | rectheader.r.y, 182 | rectheader.r.w, 183 | rectheader.r.h, 184 | dst 185 | ); 186 | 187 | return 1; 188 | } 189 | 190 | /* Read the length (1..3 bytes) of compressed data following. */ 191 | compressedLen = (int)ReadCompactLen(); 192 | if (compressedLen <= 0) { 193 | fprintf(stderr, "Incorrect data received from the server.\n"); 194 | return 0; 195 | } 196 | 197 | /* Now let's initialize compression stream if needed. */ 198 | stream_id = comp_ctl & 0x03; 199 | zs = &zlibStream[stream_id]; 200 | if (!zlibStreamActive[stream_id]) { 201 | zs->zalloc = Z_NULL; 202 | zs->zfree = Z_NULL; 203 | zs->opaque = Z_NULL; 204 | err = inflateInit(zs); 205 | if (err != Z_OK) { 206 | if (zs->msg != NULL) 207 | fprintf(stderr, "InflateInit error: %s.\n", zs->msg); 208 | return 0; 209 | } 210 | zlibStreamActive[stream_id] = 1; 211 | } 212 | 213 | /* Read, decode and draw actual pixel data in a loop. */ 214 | bufferSize = 640*480 * bitsPixel / (bitsPixel + opt.client.bpp) & 0xFFFFFFFC; 215 | dst = &buffer[bufferSize]; 216 | if (rowSize > bufferSize) { 217 | /* Should be impossible when BUFFER_SIZE >= 16384 */ 218 | fprintf(stderr, "Internal error: incorrect buffer size.\n"); 219 | return 0; 220 | } 221 | 222 | rowsProcessed = 0; 223 | extraBytes = 0; 224 | 225 | while (compressedLen > 0) { 226 | if (compressedLen > ZLIB_BUFFER_SIZE) 227 | portionLen = ZLIB_BUFFER_SIZE; 228 | else 229 | portionLen = compressedLen; 230 | 231 | if (!read_from_rfb_server(sock, (char*)zlib_buffer, portionLen)) 232 | return 0; 233 | 234 | compressedLen -= portionLen; 235 | 236 | zs->next_in = (Bytef *)zlib_buffer; 237 | zs->avail_in = portionLen; 238 | 239 | do { 240 | zs->next_out = (Bytef *)&buffer[extraBytes]; 241 | zs->avail_out = bufferSize - extraBytes; 242 | 243 | err = inflate(zs, Z_SYNC_FLUSH); 244 | if (err == Z_BUF_ERROR) /* Input exhausted -- no problem. */ 245 | break; 246 | if (err != Z_OK && err != Z_STREAM_END) { 247 | if (zs->msg != NULL) { 248 | fprintf(stderr, "Inflate error: %s.\n", zs->msg); 249 | } else { 250 | fprintf(stderr, "Inflate error: %d.\n", err); 251 | } 252 | return 0; 253 | } 254 | 255 | numRows = (bufferSize - zs->avail_out) / rowSize; 256 | 257 | filterFn(numRows, buffer, dst); 258 | 259 | extraBytes = bufferSize - zs->avail_out - numRows * rowSize; 260 | if (extraBytes > 0) 261 | memcpy(buffer, &buffer[numRows * rowSize], extraBytes); 262 | 263 | dfb_write_data_to_screen( 264 | rectheader.r.x, 265 | rectheader.r.y + rowsProcessed, 266 | rectheader.r.w, 267 | numRows, 268 | dst); 269 | rowsProcessed += numRows; 270 | } 271 | while (zs->avail_out == 0); 272 | } 273 | 274 | if (rowsProcessed != rectheader.r.h) { 275 | fprintf(stderr, "Incorrect number of scan lines after decompression.\n"); 276 | return 0; 277 | } 278 | 279 | return 1; 280 | } 281 | 282 | /*---------------------------------------------------------------------------- 283 | * 284 | * Filter stuff. 285 | * 286 | */ 287 | 288 | 289 | int 290 | InitFilterCopy (int rw, int rh) 291 | { 292 | rectWidth = rw; 293 | return opt.client.bpp; 294 | } 295 | 296 | void 297 | FilterCopy (int numRows, void *src, void *dst) 298 | { 299 | memcpy (dst, src, numRows * rectWidth * (opt.client.bpp / 8)); 300 | } 301 | 302 | int 303 | InitFilterGradient (int rw, int rh) 304 | { 305 | int bits; 306 | 307 | bits = InitFilterCopy(rw, rh); 308 | if (cutZeros) 309 | memset(tightPrevRow, 0, rw * 3); 310 | else 311 | memset(tightPrevRow, 0, rw * 3 * sizeof(CARD16)); 312 | 313 | return bits; 314 | } 315 | 316 | void 317 | FilterGradient (int numRows, void* buffer, void *buffer2) 318 | { 319 | int x, y, c; 320 | CARD16 *src = (CARD16 *)buffer; 321 | CARD16 *dst = (CARD16 *)buffer2; 322 | CARD16 *thatRow = (CARD16 *)tightPrevRow; 323 | CARD16 thisRow[2048*3]; 324 | CARD16 pix[3]; 325 | CARD16 max[3]; 326 | int shift[3]; 327 | int est[3]; 328 | 329 | 330 | max[0] = opt.client.redmax; 331 | max[1] = opt.client.greenmax; 332 | max[2] = opt.client.bluemax; 333 | 334 | shift[0] = opt.client.redshift; 335 | shift[1] = opt.client.greenshift; 336 | shift[2] = opt.client.blueshift; 337 | 338 | for (y = 0; y < numRows; y++) { 339 | 340 | /* First pixel in a row */ 341 | for (c = 0; c < 3; c++) { 342 | pix[c] = (CARD16)(((src[y*rectWidth] >> shift[c]) + thatRow[c]) & max[c]); 343 | thisRow[c] = pix[c]; 344 | } 345 | dst[y*rectWidth] = RGB_TO_PIXEL(opt.client.bpp, pix[0], pix[1], pix[2]); 346 | 347 | /* Remaining pixels of a row */ 348 | for (x = 1; x < rectWidth; x++) { 349 | for (c = 0; c < 3; c++) { 350 | est[c] = (int)thatRow[x*3+c] + (int)pix[c] - (int)thatRow[(x-1)*3+c]; 351 | if (est[c] > (int)max[c]) { 352 | est[c] = (int)max[c]; 353 | } else if (est[c] < 0) { 354 | est[c] = 0; 355 | } 356 | pix[c] = (CARD16)(((src[y*rectWidth+x] >> shift[c]) + est[c]) & max[c]); 357 | thisRow[x*3+c] = pix[c]; 358 | } 359 | dst[y*rectWidth+x] = RGB_TO_PIXEL(opt.client.bpp, pix[0], pix[1], pix[2]); 360 | } 361 | memcpy(thatRow, thisRow, rectWidth * 3 * sizeof(CARD16)); 362 | } 363 | } 364 | 365 | int 366 | InitFilterPalette (int rw, int rh) 367 | { 368 | CARD8 numColors; 369 | rectWidth = rw; 370 | 371 | if (!read_from_rfb_server(sock, (char*)&numColors, 1)) 372 | return 0; 373 | 374 | rectColors = (int)numColors; 375 | if (++rectColors < 2) 376 | return 0; 377 | 378 | if (!read_from_rfb_server(sock, (char*)&tightPalette, rectColors * (opt.client.bpp / 8))) 379 | return 0; 380 | 381 | return (rectColors == 2) ? 1 : 8; 382 | } 383 | 384 | void 385 | FilterPalette (int numRows, void *buffer, void *buffer2) 386 | { 387 | /* FIXME works only in 16 bpp. The dst and palette pointers would need to 388 | * be adjusted in size. Maybe after dinner ;) */ 389 | int x, y, b, w; 390 | CARD8 *src = (CARD8 *)buffer; 391 | CARD16 *dst = (CARD16 *)buffer2; 392 | CARD16 *palette = (CARD16 *)tightPalette; 393 | 394 | if (rectColors == 2) { 395 | w = (rectWidth + 7) / 8; 396 | for (y = 0; y < numRows; y++) { 397 | for (x = 0; x < rectWidth / 8; x++) { 398 | for (b = 7; b >= 0; b--) 399 | dst[y*rectWidth+x*8+7-b] = palette[src[y*w+x] >> b & 1]; 400 | } 401 | for (b = 7; b >= 8 - rectWidth % 8; b--) { 402 | dst[y*rectWidth+x*8+7-b] = palette[src[y*w+x] >> b & 1]; 403 | } 404 | } 405 | } else { 406 | for (y = 0; y < numRows; y++) 407 | for (x = 0; x < rectWidth; x++) 408 | dst[y*rectWidth+x] = palette[(int)src[y*rectWidth+x]]; 409 | } 410 | } 411 | 412 | int 413 | _handle_zlib_encoded_message(rfbFramebufferUpdateRectHeader rectheader) 414 | { 415 | rfbZlibHeader hdr; 416 | int remaining; 417 | int inflateResult; 418 | int toRead; 419 | 420 | /* First make sure we have a large enough raw buffer to hold the 421 | * decompressed data. In practice, with a fixed BPP, fixed frame 422 | * buffer size and the first update containing the entire frame 423 | * buffer, this buffer allocation should only happen once, on the 424 | * first update. 425 | */ 426 | if ( raw_buffer_size < (( rectheader.r.w * rectheader.r.h ) 427 | * ( opt.client.bpp / 8 ))) { 428 | 429 | if ( raw_buffer != NULL ) { 430 | 431 | free( raw_buffer ); 432 | 433 | } 434 | 435 | raw_buffer_size = (( rectheader.r.w * rectheader.r.h ) 436 | * ( opt.client.bpp / 8 )); 437 | raw_buffer = (char*) malloc( raw_buffer_size ); 438 | 439 | } 440 | 441 | if (!read_from_rfb_server(sock, (char *)&hdr, sz_rfbZlibHeader)) 442 | return 0; 443 | 444 | remaining = Swap32IfLE(hdr.nBytes); 445 | 446 | /* Need to initialize the decompressor state. */ 447 | decompStream.next_in = ( Bytef * )buffer; 448 | decompStream.avail_in = 0; 449 | decompStream.next_out = ( Bytef * )raw_buffer; 450 | decompStream.avail_out = raw_buffer_size; 451 | decompStream.data_type = Z_BINARY; 452 | 453 | /* Initialize the decompression stream structures on the first invocation. */ 454 | if ( decompStreamInited == 0 ) { 455 | 456 | inflateResult = inflateInit( &decompStream ); 457 | 458 | if ( inflateResult != Z_OK ) { 459 | fprintf(stderr, 460 | "inflateInit returned error: %d, msg: %s\n", 461 | inflateResult, 462 | decompStream.msg); 463 | return 0; 464 | } 465 | 466 | decompStreamInited = 1; 467 | 468 | } 469 | 470 | inflateResult = Z_OK; 471 | 472 | /* Process buffer full of data until no more to process, or 473 | * some type of inflater error, or Z_STREAM_END. 474 | */ 475 | while (( remaining > 0 ) && 476 | ( inflateResult == Z_OK )) { 477 | 478 | if ( remaining > BUFFER_SIZE ) { 479 | toRead = BUFFER_SIZE; 480 | } 481 | else { 482 | toRead = remaining; 483 | } 484 | 485 | /* Fill the buffer, obtaining data from the server. */ 486 | if (!read_from_rfb_server(sock, buffer,toRead)) 487 | return 0; 488 | 489 | decompStream.next_in = ( Bytef * )buffer; 490 | decompStream.avail_in = toRead; 491 | 492 | /* Need to uncompress buffer full. */ 493 | inflateResult = inflate( &decompStream, Z_SYNC_FLUSH ); 494 | 495 | /* We never supply a dictionary for compression. */ 496 | if ( inflateResult == Z_NEED_DICT ) { 497 | fprintf(stderr,"zlib inflate needs a dictionary!\n"); 498 | return 0; 499 | } 500 | if ( inflateResult < 0 ) { 501 | fprintf(stderr, 502 | "zlib inflate returned error: %d, msg: %s\n", 503 | inflateResult, 504 | decompStream.msg); 505 | return 0; 506 | } 507 | 508 | /* Result buffer allocated to be at least large enough. We should 509 | * never run out of space! 510 | */ 511 | if (( decompStream.avail_in > 0 ) && 512 | ( decompStream.avail_out <= 0 )) { 513 | fprintf(stderr,"zlib inflate ran out of space!\n"); 514 | return 0; 515 | } 516 | 517 | remaining -= toRead; 518 | 519 | } /* while ( remaining > 0 ) */ 520 | 521 | if ( inflateResult == Z_OK ) { 522 | 523 | /* Put the uncompressed contents of the update on the screen. */ 524 | dfb_write_data_to_screen( 525 | rectheader.r.x, 526 | rectheader.r.y, 527 | rectheader.r.w, 528 | rectheader.r.h, 529 | raw_buffer 530 | ); 531 | 532 | 533 | } 534 | else { 535 | 536 | fprintf(stderr, 537 | "zlib inflate returned error: %d, msg: %s\n", 538 | inflateResult, 539 | decompStream.msg); 540 | return 0; 541 | 542 | } 543 | 544 | return 1; 545 | } 546 | -------------------------------------------------------------------------------- /src/d3des.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This is D3DES (V5.09) by Richard Outerbridge with the double and 3 | * triple-length support removed for use in VNC. Also the bytebit[] array 4 | * has been reversed so that the most significant bit in each byte of the 5 | * key is ignored, not the least significant. 6 | * 7 | * These changes are: 8 | * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. 9 | * 10 | * This software is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 13 | */ 14 | 15 | /* D3DES (V5.09) - 16 | * 17 | * A portable, public domain, version of the Data Encryption Standard. 18 | * 19 | * Written with Symantec's THINK (Lightspeed) C by Richard Outerbridge. 20 | * Thanks to: Dan Hoey for his excellent Initial and Inverse permutation 21 | * code; Jim Gillogly & Phil Karn for the DES key schedule code; Dennis 22 | * Ferguson, Eric Young and Dana How for comparing notes; and Ray Lau, 23 | * for humouring me on. 24 | * 25 | * Copyright (c) 1988,1989,1990,1991,1992 by Richard Outerbridge. 26 | * (GEnie : OUTER; CIS : [71755,204]) Graven Imagery, 1992. 27 | */ 28 | 29 | #include "d3des.h" 30 | 31 | static void scrunch(unsigned char *, unsigned long *); 32 | static void unscrun(unsigned long *, unsigned char *); 33 | static void desfunc(unsigned long *, unsigned long *); 34 | static void cookey(unsigned long *); 35 | 36 | static unsigned long KnL[32] = { 0L }; 37 | //static unsigned long KnR[32] = { 0L }; 38 | //static unsigned long Kn3[32] = { 0L }; 39 | /* 40 | * static unsigned char Df_Key[24] = { 41 | * 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef, 42 | * 0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10, 43 | * 0x89,0xab,0xcd,0xef,0x01,0x23,0x45,0x67 }; 44 | */ 45 | 46 | static unsigned short bytebit[8] = { 47 | 01, 02, 04, 010, 020, 040, 0100, 0200 }; 48 | 49 | static unsigned long bigbyte[24] = { 50 | 0x800000L, 0x400000L, 0x200000L, 0x100000L, 51 | 0x80000L, 0x40000L, 0x20000L, 0x10000L, 52 | 0x8000L, 0x4000L, 0x2000L, 0x1000L, 53 | 0x800L, 0x400L, 0x200L, 0x100L, 54 | 0x80L, 0x40L, 0x20L, 0x10L, 55 | 0x8L, 0x4L, 0x2L, 0x1L }; 56 | 57 | /* Use the key schedule specified in the Standard (ANSI X3.92-1981). */ 58 | 59 | static unsigned char pc1[56] = { 60 | 56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17, 61 | 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35, 62 | 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21, 63 | 13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3 }; 64 | 65 | static unsigned char totrot[16] = { 66 | 1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28 }; 67 | 68 | static unsigned char pc2[48] = { 69 | 13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9, 70 | 22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1, 71 | 40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47, 72 | 43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31 }; 73 | 74 | void deskey(key, edf) /* Thanks to James Gillogly & Phil Karn! */ 75 | unsigned char *key; 76 | int edf; 77 | { 78 | register int i, j, l, m, n; 79 | unsigned char pc1m[56], pcr[56]; 80 | unsigned long kn[32]; 81 | 82 | for ( j = 0; j < 56; j++ ) { 83 | l = pc1[j]; 84 | m = l & 07; 85 | pc1m[j] = (key[l >> 3] & bytebit[m]) ? 1 : 0; 86 | } 87 | for( i = 0; i < 16; i++ ) { 88 | if( edf == DE1 ) m = (15 - i) << 1; 89 | else m = i << 1; 90 | n = m + 1; 91 | kn[m] = kn[n] = 0L; 92 | for( j = 0; j < 28; j++ ) { 93 | l = j + totrot[i]; 94 | if( l < 28 ) pcr[j] = pc1m[l]; 95 | else pcr[j] = pc1m[l - 28]; 96 | } 97 | for( j = 28; j < 56; j++ ) { 98 | l = j + totrot[i]; 99 | if( l < 56 ) pcr[j] = pc1m[l]; 100 | else pcr[j] = pc1m[l - 28]; 101 | } 102 | for( j = 0; j < 24; j++ ) { 103 | if( pcr[pc2[j]] ) kn[m] |= bigbyte[j]; 104 | if( pcr[pc2[j+24]] ) kn[n] |= bigbyte[j]; 105 | } 106 | } 107 | cookey(kn); 108 | return; 109 | } 110 | 111 | static void cookey(raw1) 112 | register unsigned long *raw1; 113 | { 114 | register unsigned long *cook, *raw0; 115 | unsigned long dough[32]; 116 | register int i; 117 | 118 | cook = dough; 119 | for( i = 0; i < 16; i++, raw1++ ) { 120 | raw0 = raw1++; 121 | *cook = (*raw0 & 0x00fc0000L) << 6; 122 | *cook |= (*raw0 & 0x00000fc0L) << 10; 123 | *cook |= (*raw1 & 0x00fc0000L) >> 10; 124 | *cook++ |= (*raw1 & 0x00000fc0L) >> 6; 125 | *cook = (*raw0 & 0x0003f000L) << 12; 126 | *cook |= (*raw0 & 0x0000003fL) << 16; 127 | *cook |= (*raw1 & 0x0003f000L) >> 4; 128 | *cook++ |= (*raw1 & 0x0000003fL); 129 | } 130 | usekey(dough); 131 | return; 132 | } 133 | 134 | void cpkey(into) 135 | register unsigned long *into; 136 | { 137 | register unsigned long *from, *endp; 138 | 139 | from = KnL, endp = &KnL[32]; 140 | while( from < endp ) *into++ = *from++; 141 | return; 142 | } 143 | 144 | void usekey(from) 145 | register unsigned long *from; 146 | { 147 | register unsigned long *to, *endp; 148 | 149 | to = KnL, endp = &KnL[32]; 150 | while( to < endp ) *to++ = *from++; 151 | return; 152 | } 153 | 154 | void des(inblock, outblock) 155 | unsigned char *inblock, *outblock; 156 | { 157 | unsigned long work[2]; 158 | 159 | scrunch(inblock, work); 160 | desfunc(work, KnL); 161 | unscrun(work, outblock); 162 | return; 163 | } 164 | 165 | static void scrunch(outof, into) 166 | register unsigned char *outof; 167 | register unsigned long *into; 168 | { 169 | *into = (*outof++ & 0xffL) << 24; 170 | *into |= (*outof++ & 0xffL) << 16; 171 | *into |= (*outof++ & 0xffL) << 8; 172 | *into++ |= (*outof++ & 0xffL); 173 | *into = (*outof++ & 0xffL) << 24; 174 | *into |= (*outof++ & 0xffL) << 16; 175 | *into |= (*outof++ & 0xffL) << 8; 176 | *into |= (*outof & 0xffL); 177 | return; 178 | } 179 | 180 | static void unscrun(outof, into) 181 | register unsigned long *outof; 182 | register unsigned char *into; 183 | { 184 | *into++ = (*outof >> 24) & 0xffL; 185 | *into++ = (*outof >> 16) & 0xffL; 186 | *into++ = (*outof >> 8) & 0xffL; 187 | *into++ = *outof++ & 0xffL; 188 | *into++ = (*outof >> 24) & 0xffL; 189 | *into++ = (*outof >> 16) & 0xffL; 190 | *into++ = (*outof >> 8) & 0xffL; 191 | *into = *outof & 0xffL; 192 | return; 193 | } 194 | 195 | static unsigned long SP1[64] = { 196 | 0x01010400L, 0x00000000L, 0x00010000L, 0x01010404L, 197 | 0x01010004L, 0x00010404L, 0x00000004L, 0x00010000L, 198 | 0x00000400L, 0x01010400L, 0x01010404L, 0x00000400L, 199 | 0x01000404L, 0x01010004L, 0x01000000L, 0x00000004L, 200 | 0x00000404L, 0x01000400L, 0x01000400L, 0x00010400L, 201 | 0x00010400L, 0x01010000L, 0x01010000L, 0x01000404L, 202 | 0x00010004L, 0x01000004L, 0x01000004L, 0x00010004L, 203 | 0x00000000L, 0x00000404L, 0x00010404L, 0x01000000L, 204 | 0x00010000L, 0x01010404L, 0x00000004L, 0x01010000L, 205 | 0x01010400L, 0x01000000L, 0x01000000L, 0x00000400L, 206 | 0x01010004L, 0x00010000L, 0x00010400L, 0x01000004L, 207 | 0x00000400L, 0x00000004L, 0x01000404L, 0x00010404L, 208 | 0x01010404L, 0x00010004L, 0x01010000L, 0x01000404L, 209 | 0x01000004L, 0x00000404L, 0x00010404L, 0x01010400L, 210 | 0x00000404L, 0x01000400L, 0x01000400L, 0x00000000L, 211 | 0x00010004L, 0x00010400L, 0x00000000L, 0x01010004L }; 212 | 213 | static unsigned long SP2[64] = { 214 | 0x80108020L, 0x80008000L, 0x00008000L, 0x00108020L, 215 | 0x00100000L, 0x00000020L, 0x80100020L, 0x80008020L, 216 | 0x80000020L, 0x80108020L, 0x80108000L, 0x80000000L, 217 | 0x80008000L, 0x00100000L, 0x00000020L, 0x80100020L, 218 | 0x00108000L, 0x00100020L, 0x80008020L, 0x00000000L, 219 | 0x80000000L, 0x00008000L, 0x00108020L, 0x80100000L, 220 | 0x00100020L, 0x80000020L, 0x00000000L, 0x00108000L, 221 | 0x00008020L, 0x80108000L, 0x80100000L, 0x00008020L, 222 | 0x00000000L, 0x00108020L, 0x80100020L, 0x00100000L, 223 | 0x80008020L, 0x80100000L, 0x80108000L, 0x00008000L, 224 | 0x80100000L, 0x80008000L, 0x00000020L, 0x80108020L, 225 | 0x00108020L, 0x00000020L, 0x00008000L, 0x80000000L, 226 | 0x00008020L, 0x80108000L, 0x00100000L, 0x80000020L, 227 | 0x00100020L, 0x80008020L, 0x80000020L, 0x00100020L, 228 | 0x00108000L, 0x00000000L, 0x80008000L, 0x00008020L, 229 | 0x80000000L, 0x80100020L, 0x80108020L, 0x00108000L }; 230 | 231 | static unsigned long SP3[64] = { 232 | 0x00000208L, 0x08020200L, 0x00000000L, 0x08020008L, 233 | 0x08000200L, 0x00000000L, 0x00020208L, 0x08000200L, 234 | 0x00020008L, 0x08000008L, 0x08000008L, 0x00020000L, 235 | 0x08020208L, 0x00020008L, 0x08020000L, 0x00000208L, 236 | 0x08000000L, 0x00000008L, 0x08020200L, 0x00000200L, 237 | 0x00020200L, 0x08020000L, 0x08020008L, 0x00020208L, 238 | 0x08000208L, 0x00020200L, 0x00020000L, 0x08000208L, 239 | 0x00000008L, 0x08020208L, 0x00000200L, 0x08000000L, 240 | 0x08020200L, 0x08000000L, 0x00020008L, 0x00000208L, 241 | 0x00020000L, 0x08020200L, 0x08000200L, 0x00000000L, 242 | 0x00000200L, 0x00020008L, 0x08020208L, 0x08000200L, 243 | 0x08000008L, 0x00000200L, 0x00000000L, 0x08020008L, 244 | 0x08000208L, 0x00020000L, 0x08000000L, 0x08020208L, 245 | 0x00000008L, 0x00020208L, 0x00020200L, 0x08000008L, 246 | 0x08020000L, 0x08000208L, 0x00000208L, 0x08020000L, 247 | 0x00020208L, 0x00000008L, 0x08020008L, 0x00020200L }; 248 | 249 | static unsigned long SP4[64] = { 250 | 0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L, 251 | 0x00802080L, 0x00800081L, 0x00800001L, 0x00002001L, 252 | 0x00000000L, 0x00802000L, 0x00802000L, 0x00802081L, 253 | 0x00000081L, 0x00000000L, 0x00800080L, 0x00800001L, 254 | 0x00000001L, 0x00002000L, 0x00800000L, 0x00802001L, 255 | 0x00000080L, 0x00800000L, 0x00002001L, 0x00002080L, 256 | 0x00800081L, 0x00000001L, 0x00002080L, 0x00800080L, 257 | 0x00002000L, 0x00802080L, 0x00802081L, 0x00000081L, 258 | 0x00800080L, 0x00800001L, 0x00802000L, 0x00802081L, 259 | 0x00000081L, 0x00000000L, 0x00000000L, 0x00802000L, 260 | 0x00002080L, 0x00800080L, 0x00800081L, 0x00000001L, 261 | 0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L, 262 | 0x00802081L, 0x00000081L, 0x00000001L, 0x00002000L, 263 | 0x00800001L, 0x00002001L, 0x00802080L, 0x00800081L, 264 | 0x00002001L, 0x00002080L, 0x00800000L, 0x00802001L, 265 | 0x00000080L, 0x00800000L, 0x00002000L, 0x00802080L }; 266 | 267 | static unsigned long SP5[64] = { 268 | 0x00000100L, 0x02080100L, 0x02080000L, 0x42000100L, 269 | 0x00080000L, 0x00000100L, 0x40000000L, 0x02080000L, 270 | 0x40080100L, 0x00080000L, 0x02000100L, 0x40080100L, 271 | 0x42000100L, 0x42080000L, 0x00080100L, 0x40000000L, 272 | 0x02000000L, 0x40080000L, 0x40080000L, 0x00000000L, 273 | 0x40000100L, 0x42080100L, 0x42080100L, 0x02000100L, 274 | 0x42080000L, 0x40000100L, 0x00000000L, 0x42000000L, 275 | 0x02080100L, 0x02000000L, 0x42000000L, 0x00080100L, 276 | 0x00080000L, 0x42000100L, 0x00000100L, 0x02000000L, 277 | 0x40000000L, 0x02080000L, 0x42000100L, 0x40080100L, 278 | 0x02000100L, 0x40000000L, 0x42080000L, 0x02080100L, 279 | 0x40080100L, 0x00000100L, 0x02000000L, 0x42080000L, 280 | 0x42080100L, 0x00080100L, 0x42000000L, 0x42080100L, 281 | 0x02080000L, 0x00000000L, 0x40080000L, 0x42000000L, 282 | 0x00080100L, 0x02000100L, 0x40000100L, 0x00080000L, 283 | 0x00000000L, 0x40080000L, 0x02080100L, 0x40000100L }; 284 | 285 | static unsigned long SP6[64] = { 286 | 0x20000010L, 0x20400000L, 0x00004000L, 0x20404010L, 287 | 0x20400000L, 0x00000010L, 0x20404010L, 0x00400000L, 288 | 0x20004000L, 0x00404010L, 0x00400000L, 0x20000010L, 289 | 0x00400010L, 0x20004000L, 0x20000000L, 0x00004010L, 290 | 0x00000000L, 0x00400010L, 0x20004010L, 0x00004000L, 291 | 0x00404000L, 0x20004010L, 0x00000010L, 0x20400010L, 292 | 0x20400010L, 0x00000000L, 0x00404010L, 0x20404000L, 293 | 0x00004010L, 0x00404000L, 0x20404000L, 0x20000000L, 294 | 0x20004000L, 0x00000010L, 0x20400010L, 0x00404000L, 295 | 0x20404010L, 0x00400000L, 0x00004010L, 0x20000010L, 296 | 0x00400000L, 0x20004000L, 0x20000000L, 0x00004010L, 297 | 0x20000010L, 0x20404010L, 0x00404000L, 0x20400000L, 298 | 0x00404010L, 0x20404000L, 0x00000000L, 0x20400010L, 299 | 0x00000010L, 0x00004000L, 0x20400000L, 0x00404010L, 300 | 0x00004000L, 0x00400010L, 0x20004010L, 0x00000000L, 301 | 0x20404000L, 0x20000000L, 0x00400010L, 0x20004010L }; 302 | 303 | static unsigned long SP7[64] = { 304 | 0x00200000L, 0x04200002L, 0x04000802L, 0x00000000L, 305 | 0x00000800L, 0x04000802L, 0x00200802L, 0x04200800L, 306 | 0x04200802L, 0x00200000L, 0x00000000L, 0x04000002L, 307 | 0x00000002L, 0x04000000L, 0x04200002L, 0x00000802L, 308 | 0x04000800L, 0x00200802L, 0x00200002L, 0x04000800L, 309 | 0x04000002L, 0x04200000L, 0x04200800L, 0x00200002L, 310 | 0x04200000L, 0x00000800L, 0x00000802L, 0x04200802L, 311 | 0x00200800L, 0x00000002L, 0x04000000L, 0x00200800L, 312 | 0x04000000L, 0x00200800L, 0x00200000L, 0x04000802L, 313 | 0x04000802L, 0x04200002L, 0x04200002L, 0x00000002L, 314 | 0x00200002L, 0x04000000L, 0x04000800L, 0x00200000L, 315 | 0x04200800L, 0x00000802L, 0x00200802L, 0x04200800L, 316 | 0x00000802L, 0x04000002L, 0x04200802L, 0x04200000L, 317 | 0x00200800L, 0x00000000L, 0x00000002L, 0x04200802L, 318 | 0x00000000L, 0x00200802L, 0x04200000L, 0x00000800L, 319 | 0x04000002L, 0x04000800L, 0x00000800L, 0x00200002L }; 320 | 321 | static unsigned long SP8[64] = { 322 | 0x10001040L, 0x00001000L, 0x00040000L, 0x10041040L, 323 | 0x10000000L, 0x10001040L, 0x00000040L, 0x10000000L, 324 | 0x00040040L, 0x10040000L, 0x10041040L, 0x00041000L, 325 | 0x10041000L, 0x00041040L, 0x00001000L, 0x00000040L, 326 | 0x10040000L, 0x10000040L, 0x10001000L, 0x00001040L, 327 | 0x00041000L, 0x00040040L, 0x10040040L, 0x10041000L, 328 | 0x00001040L, 0x00000000L, 0x00000000L, 0x10040040L, 329 | 0x10000040L, 0x10001000L, 0x00041040L, 0x00040000L, 330 | 0x00041040L, 0x00040000L, 0x10041000L, 0x00001000L, 331 | 0x00000040L, 0x10040040L, 0x00001000L, 0x00041040L, 332 | 0x10001000L, 0x00000040L, 0x10000040L, 0x10040000L, 333 | 0x10040040L, 0x10000000L, 0x00040000L, 0x10001040L, 334 | 0x00000000L, 0x10041040L, 0x00040040L, 0x10000040L, 335 | 0x10040000L, 0x10001000L, 0x10001040L, 0x00000000L, 336 | 0x10041040L, 0x00041000L, 0x00041000L, 0x00001040L, 337 | 0x00001040L, 0x00040040L, 0x10000000L, 0x10041000L }; 338 | 339 | static void desfunc(block, keys) 340 | register unsigned long *block, *keys; 341 | { 342 | register unsigned long fval, work, right, leftt; 343 | register int round; 344 | 345 | leftt = block[0]; 346 | right = block[1]; 347 | work = ((leftt >> 4) ^ right) & 0x0f0f0f0fL; 348 | right ^= work; 349 | leftt ^= (work << 4); 350 | work = ((leftt >> 16) ^ right) & 0x0000ffffL; 351 | right ^= work; 352 | leftt ^= (work << 16); 353 | work = ((right >> 2) ^ leftt) & 0x33333333L; 354 | leftt ^= work; 355 | right ^= (work << 2); 356 | work = ((right >> 8) ^ leftt) & 0x00ff00ffL; 357 | leftt ^= work; 358 | right ^= (work << 8); 359 | right = ((right << 1) | ((right >> 31) & 1L)) & 0xffffffffL; 360 | work = (leftt ^ right) & 0xaaaaaaaaL; 361 | leftt ^= work; 362 | right ^= work; 363 | leftt = ((leftt << 1) | ((leftt >> 31) & 1L)) & 0xffffffffL; 364 | 365 | for( round = 0; round < 8; round++ ) { 366 | work = (right << 28) | (right >> 4); 367 | work ^= *keys++; 368 | fval = SP7[ work & 0x3fL]; 369 | fval |= SP5[(work >> 8) & 0x3fL]; 370 | fval |= SP3[(work >> 16) & 0x3fL]; 371 | fval |= SP1[(work >> 24) & 0x3fL]; 372 | work = right ^ *keys++; 373 | fval |= SP8[ work & 0x3fL]; 374 | fval |= SP6[(work >> 8) & 0x3fL]; 375 | fval |= SP4[(work >> 16) & 0x3fL]; 376 | fval |= SP2[(work >> 24) & 0x3fL]; 377 | leftt ^= fval; 378 | work = (leftt << 28) | (leftt >> 4); 379 | work ^= *keys++; 380 | fval = SP7[ work & 0x3fL]; 381 | fval |= SP5[(work >> 8) & 0x3fL]; 382 | fval |= SP3[(work >> 16) & 0x3fL]; 383 | fval |= SP1[(work >> 24) & 0x3fL]; 384 | work = leftt ^ *keys++; 385 | fval |= SP8[ work & 0x3fL]; 386 | fval |= SP6[(work >> 8) & 0x3fL]; 387 | fval |= SP4[(work >> 16) & 0x3fL]; 388 | fval |= SP2[(work >> 24) & 0x3fL]; 389 | right ^= fval; 390 | } 391 | 392 | right = (right << 31) | (right >> 1); 393 | work = (leftt ^ right) & 0xaaaaaaaaL; 394 | leftt ^= work; 395 | right ^= work; 396 | leftt = (leftt << 31) | (leftt >> 1); 397 | work = ((leftt >> 8) ^ right) & 0x00ff00ffL; 398 | right ^= work; 399 | leftt ^= (work << 8); 400 | work = ((leftt >> 2) ^ right) & 0x33333333L; 401 | right ^= work; 402 | leftt ^= (work << 2); 403 | work = ((right >> 16) ^ leftt) & 0x0000ffffL; 404 | leftt ^= work; 405 | right ^= (work << 16); 406 | work = ((right >> 4) ^ leftt) & 0x0f0f0f0fL; 407 | leftt ^= work; 408 | right ^= (work << 4); 409 | *block++ = right; 410 | *block = leftt; 411 | return; 412 | } 413 | 414 | /* Validation sets: 415 | * 416 | * Single-length key, single-length plaintext - 417 | * Key : 0123 4567 89ab cdef 418 | * Plain : 0123 4567 89ab cde7 419 | * Cipher : c957 4425 6a5e d31d 420 | * 421 | * Double-length key, single-length plaintext - 422 | * Key : 0123 4567 89ab cdef fedc ba98 7654 3210 423 | * Plain : 0123 4567 89ab cde7 424 | * Cipher : 7f1d 0a77 826b 8aff 425 | * 426 | * Double-length key, double-length plaintext - 427 | * Key : 0123 4567 89ab cdef fedc ba98 7654 3210 428 | * Plain : 0123 4567 89ab cdef 0123 4567 89ab cdff 429 | * Cipher : 27a0 8440 406a df60 278f 47cf 42d6 15d7 430 | * 431 | * Triple-length key, single-length plaintext - 432 | * Key : 0123 4567 89ab cdef fedc ba98 7654 3210 89ab cdef 0123 4567 433 | * Plain : 0123 4567 89ab cde7 434 | * Cipher : de0b 7c06 ae5e 0ed5 435 | * 436 | * Triple-length key, double-length plaintext - 437 | * Key : 0123 4567 89ab cdef fedc ba98 7654 3210 89ab cdef 0123 4567 438 | * Plain : 0123 4567 89ab cdef 0123 4567 89ab cdff 439 | * Cipher : ad0d 1b30 ac17 cf07 0ed1 1c63 81e4 4de5 440 | * 441 | * d3des V5.0a rwo 9208.07 18:44 Graven Imagery 442 | **********************************************************************/ 443 | -------------------------------------------------------------------------------- /src/dfb.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2001 Till Adam 3 | * Authors: Till Adam 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, a copy can be downloaded from 17 | * http://www.gnu.org/licenses/gpl.html, or obtained by writing to the 18 | * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 | * Boston, MA 02110-1301, USA. 20 | */ 21 | #include "directvnc.h" 22 | #include 23 | #include "keysym.h" 24 | #define KeySym int 25 | 26 | /* DirectFB interfaces needed */ 27 | IDirectFB *dfb = NULL; 28 | IDirectFBSurface *primary = NULL; 29 | IDirectFBDisplayLayer *layer = NULL; 30 | IDirectFBInputDevice *keyboard = NULL; 31 | IDirectFBInputDevice *mouse = NULL; 32 | IDirectFBEventBuffer *input_buffer = NULL; 33 | DFBResult err; 34 | DFBSurfaceDescription dsc; 35 | DFBGraphicsDeviceDescription caps; 36 | DFBDisplayLayerConfig layer_config; 37 | DFBRegion rect; 38 | DFBRectangle scratch_rect; 39 | 40 | static KeySym DirectFBTranslateSymbol (DFBInputDeviceKeymapEntry *entry, int index); 41 | 42 | void 43 | dfb_init(int argc, char *argv[]) 44 | { 45 | DFBCHECK(DirectFBInit( &argc, &argv )); 46 | 47 | /* quiet option is no longer supported in DFB 1.2 */ 48 | /* DFBCHECK(DirectFBSetOption ("quiet", "")); */ 49 | 50 | /* create the super interface */ 51 | DFBCHECK(DirectFBCreate( &dfb )); 52 | 53 | dfb->SetCooperativeLevel(dfb, DFSCL_FULLSCREEN); 54 | 55 | DFBCHECK(dfb->GetDisplayLayer( dfb, DLID_PRIMARY, &layer )); 56 | layer->GetConfiguration (layer, &layer_config); 57 | 58 | /* get the primary surface, i.e. the surface of the primary layer we have 59 | exclusive access to */ 60 | memset( &dsc, 0, sizeof(DFBSurfaceDescription) ); 61 | dsc.flags = 62 | DSDESC_CAPS | DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT; 63 | dsc.width = layer_config.width; 64 | dsc.height = layer_config.height; 65 | 66 | dsc.caps = DSCAPS_PRIMARY | DSCAPS_SYSTEMONLY /*| DSCAPS_FLIPPING */; 67 | /* FIXME */ 68 | dsc.pixelformat = DSPF_RGB16; 69 | DFBCHECK(dfb->CreateSurface(dfb, &dsc, &primary )); 70 | primary->GetSize (primary, &opt.client.width, &opt.client.height); 71 | 72 | DFBCHECK(dfb->GetInputDevice( dfb, DIDID_KEYBOARD, &keyboard )); 73 | DFBCHECK(dfb->GetInputDevice( dfb, DIDID_MOUSE, &mouse )); 74 | DFBCHECK (dfb->CreateInputEventBuffer (dfb, DICAPS_ALL, DFB_TRUE, &input_buffer)); 75 | } 76 | 77 | 78 | /* 79 | * deinitializes resources and DirectFB 80 | */ 81 | void 82 | dfb_deinit() 83 | { 84 | if ( primary ) 85 | primary->Release( primary ); 86 | if ( input_buffer ) 87 | input_buffer->Release( input_buffer ); 88 | if ( keyboard ) 89 | keyboard->Release( keyboard ); 90 | if ( mouse ) 91 | mouse->Release( mouse ); 92 | if ( layer ) 93 | layer->Release( layer ); 94 | if ( dfb ) 95 | dfb->Release( dfb ); 96 | } 97 | 98 | void 99 | dfb_flip() 100 | { 101 | primary->Flip(primary, NULL, DSFLIP_WAITFORSYNC); 102 | } 103 | 104 | void 105 | dfb_flip_rect(x, y, w, h) 106 | { 107 | rect.x1 = x+opt.h_offset; 108 | rect.y1 = y+opt.v_offset; 109 | rect.x2 = x+w; 110 | rect.y2 = y+h; 111 | primary->Flip(primary, &rect, DSFLIP_WAITFORSYNC); 112 | } 113 | 114 | int 115 | dfb_write_data_to_screen(int x, int y, int w, int h, void *data) 116 | { 117 | 118 | char *dst; 119 | int pitch; /* number of bytes per row */ 120 | int orig_src_pitch, src_pitch; 121 | 122 | orig_src_pitch = w * opt.client.bpp/8; 123 | /* make sure we dont exceed client dimensions */ 124 | if (x > opt.client.width || y > opt.client.height) 125 | return 1; 126 | if ( x+w > opt.client.width) 127 | w = opt.client.width - x; 128 | if ( y+h > opt.client.height) 129 | h = opt.client.height - y; 130 | 131 | src_pitch = w * opt.client.bpp/8; 132 | 133 | if(primary->Lock(primary, DSLF_WRITE, (void**)(&dst), &pitch) ==DFB_OK) 134 | { 135 | int i; 136 | dst += opt.v_offset * pitch; 137 | dst += (y*pitch + ( (x+opt.h_offset) * opt.client.bpp/8) ); 138 | for (i=0;iUnlock (primary); 145 | } 146 | dfb_flip_rect (x,y,w,h); 147 | return 1; 148 | } 149 | 150 | int 151 | dfb_copy_rect(int src_x, int src_y, int dest_x, int dest_y, int w, int h) 152 | { 153 | /* make sure we dont exceed client dimensions */ 154 | if ( src_x > opt.client.width 155 | || src_y > opt.client.height 156 | || dest_x > opt.client.width 157 | || dest_y > opt.client.height) 158 | return 1; 159 | if ( src_x+w > opt.client.width) 160 | w = opt.client.width - src_x; 161 | if ( src_y+h > opt.client.height) 162 | h = opt.client.height - src_y; 163 | 164 | scratch_rect.x = src_x+opt.h_offset; 165 | scratch_rect.y = src_y+opt.v_offset; 166 | scratch_rect.w = w; 167 | scratch_rect.h = h; 168 | 169 | primary->Blit(primary, primary, &scratch_rect, 170 | dest_x+opt.h_offset, dest_y+opt.v_offset); 171 | dfb_flip_rect (src_x,src_y,w,h); 172 | return 1; 173 | } 174 | 175 | int 176 | dfb_draw_rect_with_rgb(int x, int y, int w, int h, int r, int g, int b) 177 | { 178 | /* make sure we dont exceed client dimensions */ 179 | if (x > opt.client.width || y > opt.client.height) 180 | return 1; 181 | if ( x+w > opt.client.width) 182 | w = opt.client.width - x; 183 | if ( y+h > opt.client.height) 184 | h = opt.client.height - y; 185 | 186 | 187 | primary->SetColor(primary, r,g,b,0xFF); 188 | primary->FillRectangle(primary, x+opt.h_offset,y+opt.v_offset,w,h); 189 | dfb_flip_rect (x,y,w,h); 190 | return 1; 191 | } 192 | 193 | 194 | IDirectFBSurface * 195 | dfb_create_cursor_saved_area(int width, int height) 196 | { 197 | IDirectFBSurface *surf; 198 | memset( &dsc, 0, sizeof(DFBSurfaceDescription) ); 199 | dsc.flags = DSDESC_CAPS | DSDESC_WIDTH; 200 | dsc.width = width; 201 | dsc.height = height; 202 | 203 | DFBCHECK(dfb->CreateSurface(dfb, &dsc, &surf)); 204 | return surf; 205 | } 206 | 207 | void 208 | dfb_restore_cursor_rect( IDirectFBSurface *surf, int x, int y, int w, int h) 209 | { 210 | int surf_w, surf_h; 211 | surf->GetSize(surf, &surf_w, &surf_h); 212 | scratch_rect.x = surf_w-w; 213 | scratch_rect.y = surf_h-h; 214 | scratch_rect.w = w; 215 | scratch_rect.h = h; 216 | primary->Blit(primary, surf, &scratch_rect, x+opt.h_offset, y+opt.v_offset); 217 | } 218 | 219 | void 220 | dfb_save_cursor_rect( IDirectFBSurface *surf, int x, int y, int w, int h) 221 | { 222 | int surf_w, surf_h; 223 | scratch_rect.x = x + opt.h_offset; 224 | scratch_rect.y = y + opt.v_offset; 225 | scratch_rect.w = w; 226 | scratch_rect.h = h; 227 | surf->GetSize(surf, &surf_w, &surf_h); 228 | surf->Blit(surf, primary, &scratch_rect, surf_w-w, surf_h -h); 229 | } 230 | 231 | static KeySym 232 | _translate_with_modmap (DFBInputDeviceKeymapEntry *entry, int index, DFBInputDeviceLockState lkst, int ctrl) { 233 | if (opt.modmapfile != NULL && !ctrl) { 234 | KeySym ks = modmap_translate_code(entry->code, lkst, index & 1); 235 | if (ks != XK_VoidSymbol) return ks; 236 | } 237 | return DirectFBTranslateSymbol(entry, index); 238 | } 239 | 240 | 241 | static void 242 | _dfb_handle_key_event(DFBInputEvent evt, int press_or_release) 243 | { 244 | int keysym; 245 | int level = 0; 246 | int ctrl = 0; 247 | char keytype = 0; /* '',A,N,K */ 248 | DFBInputDeviceLockState lkst = 0; 249 | DFBInputDeviceKeymapEntry entry; 250 | keyboard->GetKeymapEntry(keyboard, evt.key_code, &entry); 251 | /* OK according to the RFB specs we need to modify 252 | any key_codes to thier symbols. This includes 253 | caps lock and numlock, as they are ignored by the 254 | server. 255 | It might be good to back through this code sometime 256 | to make is execute faster. */ 257 | /*What type of key do we have ALPHA,NUMBER,KEYPAD,OTHER */ 258 | if ((evt.key_id >= DIKI_KP_DIV) && (evt.key_id<= DIKI_KP_9)) 259 | keytype='K'; 260 | if ((evt.key_id >= DIKI_A) && (evt.key_id<= DIKI_Z)) 261 | keytype='A'; 262 | if ((evt.key_id >= DIKI_0) && (evt.key_id<= DIKI_9)) 263 | keytype='N'; 264 | 265 | /*CASES: */ 266 | /* SHIFT=shifton for all */ 267 | if (evt.modifiers & DIMM_SHIFT) { 268 | level = 1; /*do the shift*/ 269 | /* SHIFT NUMLOCK CAPSLOCK == ALPHA-Normal, Numbers-Shifted, and KP-Normal */ 270 | if ((evt.locks & DILS_CAPS) && (evt.locks & DILS_NUM) && 271 | ((keytype=='K')||(keytype=='A')) ) { 272 | level = 0; 273 | } else { 274 | /* SHIFT CAPSLOCK == ALPHA-Normal, Numbers-Shifted, and KP-Shifted */ 275 | if ((evt.locks & DILS_CAPS) && (keytype=='A')) level = 0; 276 | /* SHIFT NUMLOCK == ALPHA-Shifted, Numbers-Shifted, and KP-Normal */ 277 | if ((evt.locks & DILS_NUM) && (keytype=='K')) level = 0; 278 | } 279 | 280 | } else { 281 | /* CAPSLOCK == ALPHA-Shifted, Numbers-Normal, and KP-Normal */ 282 | if ((evt.locks & DILS_CAPS) && (keytype=='A')) level = 1; 283 | /* NUMLOCK == ALPHA-Normal, Numbers-Normal, and KP-Shifted */ 284 | if ((evt.locks & DILS_NUM) && (keytype=='K')) level = 1; 285 | } 286 | 287 | if (evt.modifiers & DIMM_ALTGR) 288 | level = level + 2; 289 | if (evt.modifiers & DIMM_CONTROL) 290 | ctrl = 1; 291 | keysym = _translate_with_modmap(&entry, level, lkst, ctrl); 292 | rfb_send_key_event(keysym, press_or_release); 293 | } 294 | 295 | int 296 | dfb_wait_for_event_with_timeout(int milliseconds) 297 | { 298 | return input_buffer->WaitForEventWithTimeout(input_buffer, 0, milliseconds); 299 | } 300 | 301 | int 302 | dfb_wait_for_event() 303 | { 304 | return input_buffer->WaitForEvent(input_buffer); 305 | } 306 | 307 | 308 | int 309 | dfb_process_events() 310 | { 311 | DFBInputEvent evt; 312 | 313 | /* we need to check whether the dfb ressources have been set up because 314 | * this might be called during handshaking when dfb_init has not been 315 | * called yet. This is the disadvantage of processing client events 316 | * whenever the socket would block. The other option would be to initialize 317 | * the dfb ressources (input input_buffer) before everything else, but then the 318 | * screen gets blanked for every unsuccessful connect (wrong password) 319 | * which is not pretty either. I think I prefer checking here for the time 320 | * being. */ 321 | if (!dfb) 322 | return 0; 323 | 324 | while(input_buffer->GetEvent(input_buffer, DFB_EVENT(&evt)) == DFB_OK) 325 | { 326 | switch (evt.type) 327 | { 328 | case DIET_KEYPRESS: 329 | /* quit on ctrl-q FIXME make this configurable*/ 330 | if (evt.key_id == DIKI_Q && evt.modifiers & DIMM_CONTROL) 331 | { 332 | /* Ugh. 333 | * The control key is still pressed when we disconnect, so it 334 | * is still pressed when the next session attaches. Since DFB 335 | * doesnt discern the two control keys, we send release events 336 | * for both. X just ignores releases for unpressed keys, 337 | * luckily */ 338 | rfb_send_key_event(XK_Control_L, 0); 339 | rfb_send_key_event(XK_Control_R, 0); 340 | dfb_deinit(); 341 | exit(1); 342 | } 343 | _dfb_handle_key_event(evt, 1); 344 | break; 345 | case DIET_KEYRELEASE: 346 | _dfb_handle_key_event(evt, 0); 347 | break; 348 | case DIET_AXISMOTION: 349 | if (evt.flags & DIEF_AXISREL) 350 | { 351 | switch (evt.axis) 352 | { 353 | case DIAI_X: 354 | mousestate.x += evt.axisrel; 355 | break; 356 | case DIAI_Y: 357 | mousestate.y += evt.axisrel; 358 | break; 359 | default: 360 | break; 361 | } 362 | rfb_update_mouse(); 363 | } 364 | break; 365 | case DIET_BUTTONPRESS: 366 | switch (evt.button) 367 | { 368 | case DIBI_LEFT: 369 | mousestate.buttonmask |= rfbButton1Mask; 370 | break; 371 | case DIBI_MIDDLE: 372 | mousestate.buttonmask |= rfbButton2Mask; 373 | break; 374 | case DIBI_RIGHT: 375 | mousestate.buttonmask |= rfbButton3Mask; 376 | break; 377 | default: 378 | //fprintf(stdout, "Are we capturing the wheel here? %d\n", evt.button); 379 | break; 380 | } 381 | rfb_update_mouse(); 382 | break; 383 | case DIET_BUTTONRELEASE: 384 | switch (evt.button) 385 | { 386 | case DIBI_LEFT: 387 | mousestate.buttonmask &= ~rfbButton1Mask; 388 | break; 389 | case DIBI_MIDDLE: 390 | mousestate.buttonmask &= ~rfbButton2Mask; 391 | break; 392 | case DIBI_RIGHT: 393 | mousestate.buttonmask &= ~rfbButton3Mask; 394 | break; 395 | default: 396 | break; 397 | } 398 | rfb_update_mouse(); 399 | break; 400 | 401 | case DIET_UNKNOWN: /* fallthrough */ 402 | default: 403 | fprintf(stderr, "Unknown event: %d\n", evt.type); 404 | break; 405 | } 406 | } 407 | return 1; 408 | 409 | } 410 | 411 | 412 | /* 413 | (c) Copyright 2002 Denis Oliver Kropp 414 | All rights reserved. 415 | 416 | =========================================================================== 417 | 418 | An X keyCode must be in the range XkbMinLegalKeyCode (8) to 419 | XkbMaxLegalKeyCode(255). 420 | 421 | The keyCodes we get from the kernel range from 0 to 127, so we need to 422 | offset the range before passing the keyCode to X. 423 | 424 | An X KeySym is an extended ascii code that is device independent. 425 | 426 | The modifier map is accessed by the keyCode, but the normal map is 427 | accessed by keyCode - MIN_KEYCODE. Sigh. 428 | 429 | =========================================================================== 430 | */ 431 | 432 | 433 | /* This table assumes an iso8859_1 encoding for the characters 434 | * > 80, as returned by pccons */ 435 | static KeySym latin1_to_x[256] = { 436 | XK_VoidSymbol, XK_VoidSymbol, XK_VoidSymbol, XK_VoidSymbol, 437 | XK_VoidSymbol, XK_VoidSymbol, XK_VoidSymbol, XK_VoidSymbol, 438 | XK_BackSpace, XK_Tab, XK_Linefeed, XK_VoidSymbol, 439 | XK_VoidSymbol, XK_Return, XK_VoidSymbol, XK_VoidSymbol, 440 | XK_VoidSymbol, XK_VoidSymbol, XK_VoidSymbol, XK_VoidSymbol, 441 | XK_VoidSymbol, XK_VoidSymbol, XK_VoidSymbol, XK_VoidSymbol, 442 | XK_Cancel, XK_VoidSymbol, XK_VoidSymbol, XK_Escape, 443 | XK_VoidSymbol, XK_VoidSymbol, XK_VoidSymbol, XK_VoidSymbol, 444 | XK_space, XK_exclam, XK_quotedbl, XK_numbersign, 445 | XK_dollar, XK_percent, XK_ampersand, XK_apostrophe, 446 | XK_parenleft, XK_parenright, XK_asterisk, XK_plus, 447 | XK_comma, XK_minus, XK_period, XK_slash, 448 | XK_0, XK_1, XK_2, XK_3, 449 | XK_4, XK_5, XK_6, XK_7, 450 | XK_8, XK_9, XK_colon, XK_semicolon, 451 | XK_less, XK_equal, XK_greater, XK_question, 452 | XK_at, XK_A, XK_B, XK_C, 453 | XK_D, XK_E, XK_F, XK_G, 454 | XK_H, XK_I, XK_J, XK_K, 455 | XK_L, XK_M, XK_N, XK_O, 456 | XK_P, XK_Q, XK_R, XK_S, 457 | XK_T, XK_U, XK_V, XK_W, 458 | XK_X, XK_Y, XK_Z, XK_bracketleft, 459 | XK_backslash, XK_bracketright,XK_asciicircum, XK_underscore, 460 | XK_grave, XK_a, XK_b, XK_c, 461 | XK_d, XK_e, XK_f, XK_g, 462 | XK_h, XK_i, XK_j, XK_k, 463 | XK_l, XK_m, XK_n, XK_o, 464 | XK_p, XK_q, XK_r, XK_s, 465 | XK_t, XK_u, XK_v, XK_w, 466 | XK_x, XK_y, XK_z, XK_braceleft, 467 | XK_bar, XK_braceright, XK_asciitilde, XK_Delete, 468 | XK_VoidSymbol, XK_VoidSymbol, XK_VoidSymbol, XK_VoidSymbol, 469 | XK_VoidSymbol, XK_VoidSymbol, XK_VoidSymbol, XK_VoidSymbol, 470 | XK_VoidSymbol, XK_VoidSymbol, XK_VoidSymbol, XK_VoidSymbol, 471 | XK_VoidSymbol, XK_VoidSymbol, XK_VoidSymbol, XK_VoidSymbol, 472 | XK_VoidSymbol, XK_VoidSymbol, XK_VoidSymbol, XK_VoidSymbol, 473 | XK_VoidSymbol, XK_VoidSymbol, XK_VoidSymbol, XK_VoidSymbol, 474 | XK_VoidSymbol, XK_VoidSymbol, XK_VoidSymbol, XK_VoidSymbol, 475 | XK_VoidSymbol, XK_VoidSymbol, XK_VoidSymbol, XK_VoidSymbol, 476 | XK_nobreakspace,XK_exclamdown, XK_cent, XK_sterling, 477 | XK_currency, XK_yen, XK_brokenbar, XK_section, 478 | XK_diaeresis, XK_copyright, XK_ordfeminine, XK_guillemotleft, 479 | XK_notsign, XK_hyphen, XK_registered, XK_macron, 480 | XK_degree, XK_plusminus, XK_twosuperior, XK_threesuperior, 481 | XK_acute, XK_mu, XK_paragraph, XK_periodcentered, 482 | XK_cedilla, XK_onesuperior, XK_masculine, XK_guillemotright, 483 | XK_onequarter, XK_onehalf, XK_threequarters,XK_questiondown, 484 | XK_Agrave, XK_Aacute, XK_Acircumflex, XK_Atilde, 485 | XK_Adiaeresis, XK_Aring, XK_AE, XK_Ccedilla, 486 | XK_Egrave, XK_Eacute, XK_Ecircumflex, XK_Ediaeresis, 487 | XK_Igrave, XK_Iacute, XK_Icircumflex, XK_Idiaeresis, 488 | XK_ETH, XK_Ntilde, XK_Ograve, XK_Oacute, 489 | XK_Ocircumflex, XK_Otilde, XK_Odiaeresis, XK_multiply, 490 | XK_Ooblique, XK_Ugrave, XK_Uacute, XK_Ucircumflex, 491 | XK_Udiaeresis, XK_Yacute, XK_THORN, XK_ssharp, 492 | XK_agrave, XK_aacute, XK_acircumflex, XK_atilde, 493 | XK_adiaeresis, XK_aring, XK_ae, XK_ccedilla, 494 | XK_egrave, XK_eacute, XK_ecircumflex, XK_ediaeresis, 495 | XK_igrave, XK_iacute, XK_icircumflex, XK_idiaeresis, 496 | XK_eth, XK_ntilde, XK_ograve, XK_oacute, 497 | XK_ocircumflex, XK_otilde, XK_odiaeresis, XK_division, 498 | XK_oslash, XK_ugrave, XK_uacute, XK_ucircumflex, 499 | XK_udiaeresis, XK_yacute, XK_thorn, XK_ydiaeresis 500 | }; 501 | 502 | static DFBInputDeviceKeymapSymbolIndex diksi[4] = { 503 | DIKSI_BASE, 504 | DIKSI_BASE_SHIFT, 505 | DIKSI_ALT, 506 | DIKSI_ALT_SHIFT 507 | }; 508 | 509 | static KeySym 510 | DirectFBTranslateSymbol (DFBInputDeviceKeymapEntry *entry, int index) 511 | { 512 | DFBInputDeviceKeySymbol symbol = entry->symbols[diksi[index]]; 513 | DFBInputDeviceKeyIdentifier id = entry->identifier; 514 | 515 | if (id >= DIKI_KP_DIV && id <= DIKI_KP_9) 516 | { 517 | if (symbol >= DIKS_0 && symbol <= DIKS_9) 518 | return XK_KP_0 + symbol - DIKS_0; 519 | 520 | switch (symbol) 521 | { 522 | case DIKS_HOME: 523 | return XK_KP_Home; 524 | 525 | case DIKS_CURSOR_LEFT: 526 | return XK_KP_Left; 527 | 528 | case DIKS_CURSOR_UP: 529 | return XK_KP_Up; 530 | 531 | case DIKS_CURSOR_RIGHT: 532 | return XK_KP_Right; 533 | 534 | case DIKS_CURSOR_DOWN: 535 | return XK_KP_Down; 536 | 537 | case DIKS_PAGE_UP: 538 | return XK_KP_Page_Up; 539 | 540 | case DIKS_PAGE_DOWN: 541 | return XK_KP_Page_Down; 542 | 543 | case DIKS_END: 544 | return XK_KP_End; 545 | 546 | case DIKS_BEGIN: 547 | return XK_KP_Begin; 548 | 549 | case DIKS_INSERT: 550 | return XK_KP_Insert; 551 | 552 | case DIKS_DELETE: 553 | return XK_KP_Delete; 554 | 555 | default: 556 | ; 557 | } 558 | 559 | switch (id) 560 | { 561 | case DIKI_KP_DIV: 562 | return XK_KP_Divide; 563 | 564 | case DIKI_KP_MULT: 565 | return XK_KP_Multiply; 566 | 567 | case DIKI_KP_MINUS: 568 | return XK_KP_Subtract; 569 | 570 | case DIKI_KP_PLUS: 571 | return XK_KP_Add; 572 | 573 | case DIKI_KP_ENTER: 574 | return XK_KP_Enter; 575 | 576 | case DIKI_KP_SPACE: 577 | return XK_KP_Space; 578 | 579 | case DIKI_KP_TAB: 580 | return XK_KP_Tab; 581 | 582 | case DIKI_KP_F1: 583 | return XK_KP_F1; 584 | 585 | case DIKI_KP_F2: 586 | return XK_KP_F2; 587 | 588 | case DIKI_KP_F3: 589 | return XK_KP_F3; 590 | 591 | case DIKI_KP_F4: 592 | return XK_KP_F4; 593 | 594 | case DIKI_KP_EQUAL: 595 | return XK_KP_Equal; 596 | 597 | case DIKI_KP_DECIMAL: 598 | return XK_KP_Decimal; 599 | 600 | case DIKI_KP_SEPARATOR: 601 | return XK_KP_Separator; 602 | 603 | default: 604 | ; 605 | } 606 | } 607 | 608 | if (symbol == DIKS_TAB && (index & 1)) 609 | return XK_ISO_Left_Tab; 610 | 611 | if (symbol > 0 && symbol < 256) 612 | return latin1_to_x[symbol]; 613 | 614 | if (DFB_KEY_TYPE (symbol) == DIKT_FUNCTION && symbol < DFB_FUNCTION_KEY(36)) 615 | return XK_F1 + symbol - DIKS_F1; 616 | 617 | switch (id) 618 | { 619 | case DIKI_SHIFT_L: 620 | return XK_Shift_L; 621 | 622 | case DIKI_SHIFT_R: 623 | return XK_Shift_R; 624 | 625 | case DIKI_CONTROL_L: 626 | return XK_Control_L; 627 | 628 | case DIKI_CONTROL_R: 629 | return XK_Control_R; 630 | 631 | default: 632 | ; 633 | } 634 | 635 | 636 | switch (symbol) 637 | { 638 | case DIKS_CURSOR_LEFT: 639 | return XK_Left; 640 | 641 | case DIKS_CURSOR_RIGHT: 642 | return XK_Right; 643 | 644 | case DIKS_CURSOR_UP: 645 | return XK_Up; 646 | 647 | case DIKS_CURSOR_DOWN: 648 | return XK_Down; 649 | 650 | case DIKS_INSERT: 651 | return XK_Insert; 652 | 653 | case DIKS_HOME: 654 | return XK_Home; 655 | 656 | case DIKS_END: 657 | return XK_End; 658 | 659 | case DIKS_PAGE_UP: 660 | return XK_Page_Up; 661 | 662 | case DIKS_PAGE_DOWN: 663 | return XK_Page_Down; 664 | 665 | case DIKS_PRINT: 666 | return XK_Print; 667 | 668 | case DIKS_PAUSE: 669 | return XK_Pause; 670 | 671 | case DIKS_OK: 672 | return XK_Return; 673 | 674 | case DIKS_SELECT: 675 | return XK_Select; 676 | 677 | case DIKS_CLEAR: 678 | return XK_Clear; 679 | 680 | case DIKS_MENU: 681 | return XK_Menu; 682 | 683 | case DIKS_HELP: 684 | return XK_Help; 685 | 686 | 687 | case DIKS_ALT: 688 | return XK_Alt_L; 689 | 690 | case DIKS_ALTGR: 691 | return XK_Mode_switch; 692 | 693 | case DIKS_META: 694 | return XK_Meta_L; 695 | 696 | case DIKS_SUPER: 697 | return XK_Super_L; 698 | 699 | case DIKS_HYPER: 700 | return XK_Hyper_L; 701 | 702 | 703 | case DIKS_CAPS_LOCK: 704 | return XK_Caps_Lock; 705 | 706 | case DIKS_NUM_LOCK: 707 | return XK_Num_Lock; 708 | 709 | case DIKS_SCROLL_LOCK: 710 | return XK_Scroll_Lock; 711 | 712 | 713 | case DIKS_DEAD_GRAVE: 714 | return XK_dead_grave; 715 | 716 | case DIKS_DEAD_ACUTE: 717 | return XK_dead_acute; 718 | 719 | case DIKS_DEAD_CIRCUMFLEX: 720 | return XK_dead_circumflex; 721 | 722 | case DIKS_DEAD_TILDE: 723 | return XK_dead_tilde; 724 | 725 | case DIKS_DEAD_DIAERESIS: 726 | return XK_dead_diaeresis; 727 | 728 | case DIKS_DEAD_CEDILLA: 729 | return XK_dead_cedilla; 730 | 731 | default: 732 | ; 733 | } 734 | 735 | return 0; 736 | } 737 | -------------------------------------------------------------------------------- /src/rfb.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2001 Till Adam 3 | * Authors: Till Adam 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, a copy can be downloaded from 17 | * http://www.gnu.org/licenses/gpl.html, or obtained by writing to the 18 | * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 | * Boston, MA 02110-1301, USA. 20 | */ 21 | 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #include "directvnc.h" 34 | #include "tight.h" 35 | 36 | int _rfb_negotiate_protocol (); 37 | int _rfb_authenticate (); 38 | int _rfb_initialise_client (); 39 | int _rfb_initialise_server (); 40 | 41 | 42 | static int _handle_raw_encoded_message(rfbFramebufferUpdateRectHeader rectheader); 43 | static int _handle_copyrect_encoded_message(rfbFramebufferUpdateRectHeader rectheader); 44 | static int _handle_rre_encoded_message(rfbFramebufferUpdateRectHeader rectheader); 45 | static int _handle_corre_encoded_message(rfbFramebufferUpdateRectHeader rectheader); 46 | static int _handle_hextile_encoded_message(rfbFramebufferUpdateRectHeader rectheader); 47 | static int _handle_richcursor_message(rfbFramebufferUpdateRectHeader rectheader); 48 | 49 | /* 50 | * ConnectToRFBServer. 51 | */ 52 | 53 | 54 | int 55 | rfb_connect_to_server (char *host, int port) 56 | { 57 | struct hostent *he=NULL; 58 | int one=1; 59 | struct sockaddr_in s; 60 | 61 | 62 | if ( (sock = socket (AF_INET, SOCK_STREAM, 0)) <0) 63 | { 64 | fprintf(stderr, "Error creating communication socket: %d\n", errno); 65 | exit(2); 66 | } 67 | 68 | /* if the server wasnt specified as an ip address, look it up */ 69 | if (!inet_aton(host, &s.sin_addr)) 70 | { 71 | if ( (he = gethostbyname(host)) ) 72 | memcpy (&s.sin_addr.s_addr, he->h_addr, he->h_length); 73 | else 74 | { 75 | fprintf(stderr, "Couldnt resolve host!\n"); 76 | close(sock); 77 | return (0); 78 | } 79 | } 80 | 81 | s.sin_port = htons(port); 82 | s.sin_family = AF_INET; 83 | 84 | if (connect(sock,(struct sockaddr*) &s, sizeof(s)) < 0) 85 | { 86 | fprintf(stderr, "Connect error\n"); 87 | close(sock); 88 | return (0); 89 | } 90 | if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *)&one, sizeof(one)) < 0) 91 | { 92 | fprintf(stderr, "Error setting socket options\n"); 93 | close(sock); 94 | return (0); 95 | } 96 | 97 | if (!set_non_blocking(sock)) return -1; 98 | 99 | return (sock); 100 | } 101 | 102 | int 103 | rfb_initialise_connection () 104 | { 105 | if (!_rfb_negotiate_protocol()) return 0; 106 | if (!_rfb_authenticate()) return 0; 107 | if (!_rfb_initialise_client()) return 0; 108 | if (!_rfb_initialise_server()) return 0; 109 | 110 | return(1); 111 | } 112 | 113 | int 114 | _rfb_negotiate_protocol() 115 | { 116 | rfbProtocolVersionMsg msg; 117 | 118 | /* read the protocol version the server uses */ 119 | if (!read_from_rfb_server(sock, (char*)&msg, sz_rfbProtocolVersionMsg)) 120 | return 0; 121 | /* FIXME actually do something with that information ;) */ 122 | 123 | /* send the protocol version we want to use */ 124 | sprintf(msg, rfbProtocolVersionFormat, 125 | rfbProtocolMajorVersion, 126 | rfbProtocolMinorVersion); 127 | if (!write_exact (sock, msg, sz_rfbProtocolVersionMsg)) 128 | return 0; 129 | 130 | return 1; 131 | } 132 | 133 | 134 | int 135 | _rfb_authenticate() 136 | { 137 | CARD32 authscheme; 138 | 139 | read_from_rfb_server(sock, (char *)&authscheme, 4); 140 | authscheme = Swap32IfLE(authscheme); 141 | switch (authscheme) 142 | { 143 | CARD32 reason_length; 144 | CARD8 *reason_string; 145 | CARD8 challenge_and_response[CHALLENGESIZE]; 146 | CARD32 auth_result; 147 | 148 | case rfbConnFailed: 149 | fprintf(stderr, "DIRECTVNC: Connection to VNC server failed\n"); 150 | read_from_rfb_server(sock, (char *)&reason_length, 4); 151 | reason_length = Swap32IfLE(reason_length); 152 | reason_string = malloc(sizeof(CARD8) * reason_length); 153 | read_from_rfb_server(sock, (char *)reason_string, reason_length); 154 | fprintf(stderr, "Errormessage: %s\n", reason_string); 155 | return (0); 156 | case rfbVncAuth: 157 | 158 | /* we didnt get a password on the command line, so go get one */ 159 | if (!opt.password) 160 | { 161 | if( opt.passwordfile ) 162 | { 163 | opt.password = vncDecryptPasswdFromFile( opt.passwordfile ); 164 | } 165 | else 166 | { 167 | opt.password = getpass("Password: "); 168 | } 169 | } 170 | 171 | if (!read_from_rfb_server(sock, (char *)challenge_and_response, CHALLENGESIZE)) 172 | return 0; 173 | vncEncryptBytes(challenge_and_response, opt.password); 174 | if (!write_exact(sock, (char *)challenge_and_response, CHALLENGESIZE)) 175 | return 0; 176 | if (!read_from_rfb_server(sock, (char*)&auth_result, 4)) 177 | return 0; 178 | auth_result = Swap32IfLE(auth_result); 179 | switch (auth_result) 180 | { 181 | case rfbVncAuthFailed: 182 | fprintf(stderr, "Authentication Failed\n"); 183 | return (0); 184 | case rfbVncAuthTooMany: 185 | fprintf(stderr, "Too many connections\n"); 186 | return (0); 187 | case rfbVncAuthOK: 188 | fprintf(stderr, "Authentication OK\n"); 189 | break; 190 | } 191 | break; 192 | case rfbNoAuth: 193 | break; 194 | } 195 | return 1; 196 | } 197 | 198 | int 199 | _rfb_initialise_client() 200 | { 201 | rfbClientInitMsg cl; 202 | cl.shared = opt.shared; 203 | if (!write_exact (sock, (char *) &cl, sz_rfbClientInitMsg)) 204 | return 0; 205 | 206 | return 1; 207 | } 208 | 209 | int 210 | _rfb_initialise_server() 211 | { 212 | int len; 213 | rfbServerInitMsg si; 214 | 215 | if (!read_from_rfb_server(sock, (char *)&si, sz_rfbServerInitMsg)) 216 | return 0; 217 | opt.server.width = Swap16IfLE(si.framebufferWidth); 218 | opt.server.height = Swap16IfLE(si.framebufferHeight); 219 | opt.server.bpp = si.format.bitsPerPixel; 220 | opt.server.depth = si.format.bigEndian; 221 | opt.server.truecolour = si.format.trueColour; 222 | 223 | opt.server.redmax = Swap16IfLE(si.format.redMax); 224 | opt.server.greenmax = Swap16IfLE(si.format.greenMax); 225 | opt.server.bluemax = Swap16IfLE(si.format.blueMax); 226 | opt.server.redshift = si.format.redShift; 227 | opt.server.greenshift = si.format.greenShift; 228 | opt.server.blueshift = si.format.blueShift; 229 | 230 | len = Swap32IfLE(si.nameLength); 231 | opt.server.name = malloc(sizeof(char) * len+1); 232 | 233 | if (!read_from_rfb_server(sock, opt.server.name, len)) 234 | return 0; 235 | 236 | return 1; 237 | } 238 | 239 | int 240 | rfb_set_format_and_encodings() 241 | { 242 | char *next; 243 | int num_enc =0; 244 | rfbSetPixelFormatMsg pf; 245 | rfbSetEncodingsMsg em; 246 | CARD32 enc[MAX_ENCODINGS]; 247 | 248 | pf.type = 0; 249 | pf.format.bitsPerPixel = opt.client.bpp; 250 | pf.format.depth = opt.client.depth; 251 | pf.format.bigEndian = opt.client.bigendian; 252 | pf.format.trueColour = opt.client.truecolour; 253 | pf.format.redMax = Swap16IfLE(opt.client.redmax); 254 | pf.format.greenMax = Swap16IfLE(opt.client.greenmax); 255 | pf.format.blueMax = Swap16IfLE(opt.client.bluemax); 256 | pf.format.redShift =opt.client.redshift; 257 | pf.format.greenShift = opt.client.greenshift; 258 | pf.format.blueShift = opt.client.blueshift; 259 | 260 | if (!write_exact(sock, (char*)&pf, sz_rfbSetPixelFormatMsg)) return 0; 261 | 262 | em.type = rfbSetEncodings; 263 | em.nEncodings = Swap16IfLE(0); 264 | 265 | /* figure out the encodings string given on the command line */ 266 | next = strtok(opt.encodings, " "); 267 | while (next && em.nEncodings < MAX_ENCODINGS) 268 | { 269 | if (!strcmp(next, "raw")) 270 | { 271 | enc[num_enc++] = Swap32IfLE(rfbEncodingRaw); 272 | } 273 | if (!strcmp(next, "tight")) 274 | { 275 | enc[num_enc++] = Swap32IfLE(rfbEncodingTight); 276 | } 277 | if (!strcmp(next, "hextile")) 278 | { 279 | enc[num_enc++] = Swap32IfLE(rfbEncodingHextile); 280 | } 281 | if (!strcmp(next, "zlib")) 282 | { 283 | enc[num_enc++] = Swap32IfLE(rfbEncodingZlib); 284 | } 285 | else if (!strcmp(next, "copyrect")) 286 | { 287 | enc[num_enc++] = Swap32IfLE(rfbEncodingCopyRect); 288 | } 289 | else if (!strcmp(next, "corre")) 290 | { 291 | enc[num_enc++] = Swap32IfLE(rfbEncodingCoRRE); 292 | } 293 | else if (!strcmp(next, "rre")) 294 | { 295 | enc[num_enc++] = Swap32IfLE(rfbEncodingRRE); 296 | } 297 | next = strtok(NULL, " "); 298 | em.nEncodings = Swap16IfLE(num_enc); 299 | } 300 | if (!em.nEncodings) 301 | { 302 | enc[num_enc++] = Swap32IfLE(rfbEncodingTight); 303 | enc[num_enc++] = Swap32IfLE(rfbEncodingHextile); 304 | enc[num_enc++] = Swap32IfLE(rfbEncodingZlib); 305 | enc[num_enc++] = Swap32IfLE(rfbEncodingCopyRect); 306 | enc[num_enc++] = Swap32IfLE(rfbEncodingRRE); 307 | enc[num_enc++] = Swap32IfLE(rfbEncodingCoRRE); 308 | enc[num_enc++] = Swap32IfLE(rfbEncodingRaw); 309 | } 310 | 311 | /* Track cursor locally */ 312 | if (opt.localcursor) 313 | enc[num_enc++] = Swap32IfLE(rfbEncodingRichCursor); 314 | 315 | if (opt.client.compresslevel <= 9) 316 | enc[num_enc++] = Swap32IfLE(rfbEncodingCompressLevel0 + 317 | opt.client.compresslevel); 318 | if (opt.client.quality <= 9) 319 | enc[num_enc++] = Swap32IfLE(rfbEncodingQualityLevel0 + 320 | opt.client.quality); 321 | 322 | em.nEncodings = Swap16IfLE(num_enc); 323 | 324 | if (!write_exact(sock, (char*)&em, sz_rfbSetEncodingsMsg)) return 0; 325 | if (!write_exact(sock, (char*)&enc, num_enc * 4)) return 0; 326 | 327 | return(1); 328 | } 329 | 330 | 331 | int 332 | rfb_send_update_request(int incremental) 333 | { 334 | rfbFramebufferUpdateRequestMsg urq; 335 | 336 | urq.type = rfbFramebufferUpdateRequest; 337 | urq.incremental = incremental; 338 | urq.x = 0; 339 | urq.y = 0; 340 | urq.w = opt.server.width; 341 | urq.h = opt.server.height; 342 | 343 | urq.x = Swap16IfLE(urq.x); 344 | urq.y = Swap16IfLE(urq.y); 345 | urq.w = Swap16IfLE(urq.w); 346 | urq.h = Swap16IfLE(urq.h); 347 | 348 | if (!write_exact(sock, (char*)&urq, sz_rfbFramebufferUpdateRequestMsg)) 349 | return 0; 350 | 351 | return 1; 352 | } 353 | 354 | 355 | int 356 | rfb_handle_server_message() 357 | { 358 | int size; 359 | char *buf; 360 | rfbServerToClientMsg msg; 361 | rfbFramebufferUpdateRectHeader rectheader; 362 | 363 | if (!read_from_rfb_server(sock, (char*)&msg, 1)) return 0; 364 | switch (msg.type) 365 | { 366 | int i; 367 | case rfbFramebufferUpdate: 368 | read_from_rfb_server(sock, ((char*)&msg.fu)+1, sz_rfbFramebufferUpdateMsg-1); 369 | msg.fu.nRects = Swap16IfLE(msg.fu.nRects); 370 | for (i=0;i< msg.fu.nRects;i++) 371 | { 372 | read_from_rfb_server(sock, (char*)&rectheader, 373 | sz_rfbFramebufferUpdateRectHeader); 374 | rectheader.r.x = Swap16IfLE(rectheader.r.x); 375 | rectheader.r.y = Swap16IfLE(rectheader.r.y); 376 | rectheader.r.w = Swap16IfLE(rectheader.r.w); 377 | rectheader.r.h = Swap16IfLE(rectheader.r.h); 378 | rectheader.encoding = Swap32IfLE(rectheader.encoding); 379 | SoftCursorLockArea(rectheader.r.x, rectheader.r.y, rectheader.r.w, rectheader.r.h); 380 | switch (rectheader.encoding) 381 | { 382 | case rfbEncodingRaw: 383 | _handle_raw_encoded_message(rectheader); 384 | break; 385 | case rfbEncodingCopyRect: 386 | _handle_copyrect_encoded_message(rectheader); 387 | break; 388 | case rfbEncodingRRE: 389 | _handle_rre_encoded_message(rectheader); 390 | break; 391 | case rfbEncodingCoRRE: 392 | _handle_corre_encoded_message(rectheader); 393 | break; 394 | case rfbEncodingHextile: 395 | _handle_hextile_encoded_message(rectheader); 396 | break; 397 | case rfbEncodingTight: 398 | _handle_tight_encoded_message(rectheader); 399 | break; 400 | case rfbEncodingZlib: 401 | _handle_zlib_encoded_message(rectheader); 402 | break; 403 | case rfbEncodingRichCursor: 404 | _handle_richcursor_message(rectheader); 405 | break; 406 | case rfbEncodingLastRect: 407 | printf("LAST\n"); 408 | break; 409 | 410 | default: 411 | printf("Unknown encoding\n"); 412 | return 0; 413 | break; 414 | } 415 | /* Now we may discard "soft cursor locks". */ 416 | SoftCursorUnlockScreen(); 417 | 418 | } 419 | break; 420 | case rfbSetColourMapEntries: 421 | fprintf(stderr, "SetColourMapEntries\n"); 422 | read_from_rfb_server(sock, ((char*)&msg.scme)+1, sz_rfbSetColourMapEntriesMsg-1); 423 | break; 424 | case rfbBell: 425 | fprintf(stderr, "Bell message. Unimplemented.\n"); 426 | break; 427 | case rfbServerCutText: 428 | fprintf(stderr, "ServerCutText. Unimplemented.\n"); 429 | read_from_rfb_server(sock, ((char*)&msg.sct)+1, 430 | sz_rfbServerCutTextMsg-1); 431 | size = Swap32IfLE(msg.sct.length); 432 | buf = malloc(sizeof(char) * size); 433 | read_from_rfb_server(sock, buf, size); 434 | buf[size]=0; 435 | printf("%s\n", buf); 436 | free(buf); 437 | break; 438 | default: 439 | printf("Unknown server message. Type: %i\n", msg.type); 440 | return 0; 441 | break; 442 | } 443 | return(1); 444 | } 445 | 446 | int 447 | rfb_update_mouse() 448 | { 449 | rfbPointerEventMsg msg; 450 | 451 | if (mousestate.x < 0) mousestate.x = 0; 452 | if (mousestate.y < 0) mousestate.y = 0; 453 | 454 | if (mousestate.x > opt.client.width) mousestate.x = opt.client.width; 455 | if (mousestate.y > opt.client.height) mousestate.y = opt.client.height; 456 | 457 | 458 | msg.type = rfbPointerEvent; 459 | msg.buttonMask = mousestate.buttonmask; 460 | 461 | /* scale to server resolution */ 462 | msg.x = rint(mousestate.x * opt.h_ratio); 463 | msg.y = rint(mousestate.y * opt.v_ratio); 464 | 465 | SoftCursorMove(msg.x, msg.y); 466 | 467 | msg.x = Swap16IfLE(msg.x); 468 | msg.y = Swap16IfLE(msg.y); 469 | 470 | return(write_exact(sock, (char*)&msg, sz_rfbPointerEventMsg)); 471 | } 472 | 473 | int 474 | rfb_send_key_event(int key, int down_flag) 475 | { 476 | rfbKeyEventMsg ke; 477 | 478 | ke.type = rfbKeyEvent; 479 | ke.down = down_flag; 480 | ke.key = Swap32IfLE(key); 481 | 482 | return (write_exact(sock, (char*)&ke, sz_rfbKeyEventMsg)); 483 | } 484 | 485 | static int 486 | _handle_raw_encoded_message(rfbFramebufferUpdateRectHeader rectheader) 487 | { 488 | int size; 489 | char *buf; 490 | size = (opt.client.bpp/8 * rectheader.r.w) * rectheader.r.h; 491 | buf = malloc(size); 492 | if (!read_from_rfb_server(sock, buf, size)) return 0; 493 | dfb_write_data_to_screen( 494 | rectheader.r.x, 495 | rectheader.r.y, 496 | rectheader.r.w, 497 | rectheader.r.h, 498 | buf 499 | ); 500 | free (buf); 501 | return 1; 502 | } 503 | 504 | static int 505 | _handle_copyrect_encoded_message(rfbFramebufferUpdateRectHeader rectheader) 506 | { 507 | int src_x, src_y; 508 | 509 | if (!read_from_rfb_server(sock, (char*)&src_x, 2)) return 0; 510 | if (!read_from_rfb_server(sock, (char*)&src_y, 2)) return 0; 511 | 512 | /* If RichCursor encoding is used, we should extend our 513 | "cursor lock area" (previously set to destination 514 | rectangle) to the source rectangle as well. */ 515 | SoftCursorLockArea(src_x, src_y, rectheader.r.w, rectheader.r.h); 516 | dfb_copy_rect( 517 | Swap16IfLE(src_x), 518 | Swap16IfLE(src_y), 519 | rectheader.r.x, 520 | rectheader.r.y, 521 | rectheader.r.w, 522 | rectheader.r.h 523 | ); 524 | return 1; 525 | } 526 | 527 | static int 528 | _handle_rre_encoded_message(rfbFramebufferUpdateRectHeader rectheader) 529 | { 530 | rfbRREHeader header; 531 | char *colour; 532 | CARD16 rect[4]; 533 | int i; 534 | int r=0, g=0, b=0; 535 | 536 | colour = malloc(sizeof(opt.client.bpp/8)); 537 | if (!read_from_rfb_server(sock, (char *)&header, sz_rfbRREHeader)) return 0; 538 | header.nSubrects = Swap32IfLE(header.nSubrects); 539 | 540 | /* draw background rect */ 541 | if (!read_from_rfb_server(sock, colour, opt.client.bpp/8)) return 0; 542 | rfb_get_rgb_from_data(&r, &g, &b, colour); 543 | dfb_draw_rect_with_rgb( 544 | rectheader.r.x, 545 | rectheader.r.y, 546 | rectheader.r.w, 547 | rectheader.r.h, 548 | r,g,b 549 | ); 550 | 551 | /* subrect pixel values */ 552 | for (i=0;i> opt.client.redshift ) & opt.client.redmax) <<3; 721 | *g = (( foo16 >> opt.client.greenshift ) & opt.client.greenmax)<<2; 722 | *b = (( foo16 >> opt.client.blueshift ) & opt.client.bluemax)<<3; 723 | break; 724 | case 24: 725 | case 32: 726 | *r=data[2]&0x00FF; 727 | *g=data[1]&0x00FF; 728 | *b=data[0]&0x00FF; 729 | break; 730 | } 731 | } 732 | --------------------------------------------------------------------------------