summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrunge <runge>2007-02-19 03:11:25 +0000
committerrunge <runge>2007-02-19 03:11:25 +0000
commit23178cd162a5ee7372115c1f76fda6129b912b75 (patch)
treef5e67bade83c8a20d7c527d290fb060ccc289caa
parentd60e8ccfc8c1b173c914ffa26a88203690bf9e3a (diff)
downloadlibtdevnc-23178cd1.tar.gz
libtdevnc-23178cd1.zip
store 1.0.12 snapshot.
-rwxr-xr-xx11vnc/misc/enhanced_tightvnc_viewer/bin/ssvnc11
-rwxr-xr-xx11vnc/misc/enhanced_tightvnc_viewer/bin/ssvnc_cmd9
-rwxr-xr-xx11vnc/misc/enhanced_tightvnc_viewer/bin/util/ss_vncviewer48
-rwxr-xr-xx11vnc/misc/enhanced_tightvnc_viewer/bin/util/ssvnc.tcl552
-rwxr-xr-xx11vnc/misc/enhanced_tightvnc_viewer/build.unix8
-rwxr-xr-xx11vnc/misc/enhanced_tightvnc_viewer/src/patches/_bundle2
-rw-r--r--x11vnc/misc/enhanced_tightvnc_viewer/src/patches/tight-vncviewer-full.patch6997
7 files changed, 7028 insertions, 599 deletions
diff --git a/x11vnc/misc/enhanced_tightvnc_viewer/bin/ssvnc b/x11vnc/misc/enhanced_tightvnc_viewer/bin/ssvnc
index 26d8a3d..35e8c59 100755
--- a/x11vnc/misc/enhanced_tightvnc_viewer/bin/ssvnc
+++ b/x11vnc/misc/enhanced_tightvnc_viewer/bin/ssvnc
@@ -25,10 +25,10 @@ if [ "X$FULLNAME" = "XKarl J. Runge" ]; then
VNCVIEWER_POPUP_FIX=1
export VNCVIEWER_POPUP_FIX
- if uname -smr | grep 'Linux 2\.4.*i686' > /dev/null; then
- UNAME="Linux.i686.older"
- export UNAME
- fi
+ #if uname -smr | grep 'Linux 2\.4.*i686' > /dev/null; then
+ # UNAME="Linux.i686.older"
+ # export UNAME
+ #fi
PATH=`echo "$PATH" | sed -e 's,runge/bin/override,-------------,'`
fi
@@ -108,8 +108,9 @@ if [ ! -d "$dir/$name" -a $nearby = 0 ]; then
fi
echo "Using externel \"vncviewer\" and \"stunnel\" found in PATH."
else
+ STUNNEL=stunnel
STUNNEL_EXTRA_OPTS=${STUNNEL_EXTRA_OPTS:-"maxconn = 1"}
- export STUNNEL_EXTRA_OPTS
+ export STUNNEL STUNNEL_EXTRA_OPTS
SSVNC_VIEWER_INTERNAL=1
export SSVNC_VIEWER_INTERNAL
fi
diff --git a/x11vnc/misc/enhanced_tightvnc_viewer/bin/ssvnc_cmd b/x11vnc/misc/enhanced_tightvnc_viewer/bin/ssvnc_cmd
index 3c7158f..a24e409 100755
--- a/x11vnc/misc/enhanced_tightvnc_viewer/bin/ssvnc_cmd
+++ b/x11vnc/misc/enhanced_tightvnc_viewer/bin/ssvnc_cmd
@@ -169,14 +169,15 @@ if [ ! -d "$dir/$name" -a $nearby = 0 ]; then
echo "Using externel \"vncviewer\" and \"stunnel\" found in PATH."
else
+ STUNNEL=stunnel
STUNNEL_EXTRA_OPTS=${STUNNEL_EXTRA_OPTS:-"maxconn = 1"}
- export STUNNEL_EXTRA_OPTS
+ export STUNNEL STUNNEL_EXTRA_OPTS
SSVNC_VIEWER_INTERNAL=1
export SSVNC_VIEWER_INTERNAL
fi
if [ "X$DARWIN_COTVNC" = "X" -a "X$VNCVIEWERCMD" = "Xvncviewer" ]; then
- hstr=`"$VNCVIEWERCMD" -h 2>&1 | head -5`
+ hstr=`$VNCVIEWERCMD -h 2>&1 | head -5`
if echo "$hstr" | grep '^TightVNC.*version 1\.[23]' > /dev/null; then
# we need to avoid raw encoding
use_ours=1
@@ -206,13 +207,13 @@ fi
#
if [ $use_ours = 1 ]; then
if [ "X$base" = "Xtightvncviewer" ]; then
- "$VNCVIEWERCMD" -encodings 'copyrect tight zrle zlib hextile' "$@"
+ $VNCVIEWERCMD -encodings 'copyrect tight zrle zlib hextile' "$@"
else
ss_vncviewer "$@" -encodings 'copyrect tight zrle zlib hextile'
fi
else
if [ "X$base" = "Xtightvncviewer" ]; then
- "$VNCVIEWERCMD" "$@"
+ $VNCVIEWERCMD "$@"
else
ss_vncviewer "$@"
fi
diff --git a/x11vnc/misc/enhanced_tightvnc_viewer/bin/util/ss_vncviewer b/x11vnc/misc/enhanced_tightvnc_viewer/bin/util/ss_vncviewer
index cf10859..b241c5b 100755
--- a/x11vnc/misc/enhanced_tightvnc_viewer/bin/util/ss_vncviewer
+++ b/x11vnc/misc/enhanced_tightvnc_viewer/bin/util/ss_vncviewer
@@ -38,6 +38,9 @@
# (the first CONNECT is done through host1:port1 to host2:port2
# and then a 2nd CONNECT to the destination VNC server.)
#
+# -showcert Only fetch the certificate using the 'openssl s_client'
+# command (openssl(1) must in installed).
+#
# See http://www.karlrunge.com/x11vnc/#faq-ssl-ca for details on SSL
# certificates with VNC.
#
@@ -133,13 +136,18 @@ if [ "X$SS_VNCVIEWER_SSH_CMD" != "X" ]; then
ssh_cmd="$SS_VNCVIEWER_SSH_CMD"
fi
ssh_args=""
+showcert=""
if [ "X$1" = "X-viewerflavor" ]; then
if echo "$VNCVIEWERCMD" | grep -i chicken.of > /dev/null; then
echo "cotvnc"
exit 0
fi
- str=`"$VNCVIEWERCMD" -h 2>&1 | head -5`
+ if echo "$VNCVIEWERCMD" | grep -i ultra > /dev/null; then
+ echo "ultravnc"
+ exit 0
+ fi
+ str=`$VNCVIEWERCMD -h 2>&1 | head -5`
if echo "$str" | grep -i 'TightVNC.viewer' > /dev/null; then
echo "tightvnc"
elif echo "$str" | grep -i 'RealVNC.Ltd' > /dev/null; then
@@ -173,6 +181,8 @@ do
;;
"-alpha") gotalpha=1
;;
+ "-showcert") showcert=1
+ ;;
"-grab") VNCVIEWER_GRAB_SERVER=1; export VNCVIEWER_GRAB_SERVER
;;
"-h"*) help; exit 0
@@ -370,7 +380,7 @@ if [ "X$use_ssh" = "X1" ]; then
echo "Running viewer:"
echo "$VNCVIEWERCMD" "$@" localhost:$N
echo ""
- "$VNCVIEWERCMD" "$@" localhost:$N
+ $VNCVIEWERCMD "$@" localhost:$N
exit $?
else
@@ -574,11 +584,39 @@ if [ "X$proxy" != "X" ]; then
ptmp="/tmp/ss_vncviewer${RANDOM}.$$.pl"
mytmp "$ptmp"
pcode "$ptmp"
- connect="exec = $ptmp"
+ if [ "X$showcert" != "X1" -a "X$direct_connect" = "X" ]; then
+ if uname | grep Darwin >/dev/null; then
+ nd=`expr $use + 333`
+ SSVNC_LISTEN=$nd
+ export SSVNC_LISTEN
+ $ptmp 2>/dev/null &
+ sleep 3
+ host="localhost"
+ port="$nd"
+ connect="connect = localhost:$nd"
+ else
+ connect="exec = $ptmp"
+ fi
+ else
+ connect="exec = $ptmp"
+ fi
else
connect="connect = $host:$port"
fi
+if [ "X$showcert" = "X1" ]; then
+ if [ "X$proxy" != "X" ]; then
+ SSVNC_LISTEN=$use
+ export SSVNC_LISTEN
+ $ptmp 2>/dev/null &
+ sleep 3
+ host="localhost"
+ port="$use"
+ fi
+ openssl s_client -connect $host:$port 2>&1 < /dev/null
+ exit $?
+fi
+
if [ "X$direct_connect" != "X" ]; then
echo ""
echo "Running viewer for direct connection:"
@@ -605,7 +643,7 @@ if [ "X$direct_connect" != "X" ]; then
fi
echo "$VNCVIEWERCMD" "$@" $host:$disp
echo ""
- "$VNCVIEWERCMD" "$@" $host:$disp
+ $VNCVIEWERCMD "$@" $host:$disp
exit $?
fi
@@ -653,7 +691,7 @@ echo ""
echo "Running viewer:"
echo "$VNCVIEWERCMD" "$@" localhost:$N
echo ""
-"$VNCVIEWERCMD" "$@" localhost:$N
+$VNCVIEWERCMD "$@" localhost:$N
kill $pid
sleep 1
diff --git a/x11vnc/misc/enhanced_tightvnc_viewer/bin/util/ssvnc.tcl b/x11vnc/misc/enhanced_tightvnc_viewer/bin/util/ssvnc.tcl
index ac7c605..d9aebc4 100755
--- a/x11vnc/misc/enhanced_tightvnc_viewer/bin/util/ssvnc.tcl
+++ b/x11vnc/misc/enhanced_tightvnc_viewer/bin/util/ssvnc.tcl
@@ -117,6 +117,14 @@ proc help {} {
after it is established). "x11vnc -ssl ..." does this, and any VNC
server can be made to do this by using, e.g., STUNNEL on the remote side.
+ *IMPORTANT*: If you do not take the steps to verify the VNC Server's
+ SSL Certificate, you are vulnerable to a Man-In-The-Middle attack.
+ (Only passive sniffing attacks are prevented). You can use the "Fetch
+ Cert" button to retrieve the Cert and then after you check it is OK
+ (say, via comparing the MD5 or other info) you can save it and use
+ it to verify connections. See the Certs... Help for information on
+ how to do this.
+
Note that on Windows when the Viewer connection is finished you may
need to terminate STUNNEL manually from the System Tray (right click
on dark green icon) and selecting "Exit".
@@ -205,7 +213,7 @@ proc help {} {
the dialog. Then copy the cert file to the VNC Server and specify the
other one in the "Certs ..." dialog. Alternatively you can use the
"Import Certificate" action to paste in a certificate or read one in
- from a file.
+ from a file or use the "Fetch Cert" button on the main panel.
More Options:
@@ -274,8 +282,9 @@ proc help_certs {} {
set msg {
Description:
- Only with SSL Certificate verification can Man-In-The-Middle attacks be
- prevented. Otherwise, only passive snooping attacks are prevented with SSL.
+ *IMPORTANT*: Only with SSL Certificate verification can Man-In-The-Middle
+ attacks be prevented. Otherwise, only passive snooping attacks are prevented
+ with SSL.
The SSL Certificate files described below can have been created externally
(e.g. by x11vnc), you can import it via "Import Certificate" if you like.
@@ -283,6 +292,14 @@ proc help_certs {} {
Certificate + Private Key pair. In that case you will need to distribute one
of the generated files to the VNC Server.
+ You can also retrieve the remote VNC Server's Cert via the "Fetch Cert" button
+ on the main panel. After you check that it is the correct Cert (e.g. by
+ comparing MD5 hash or other info), you can save it. It will be set as the
+ "ServerCert" to verify against for the connection. To make this verification
+ check permanent, you will need to save the profile via Options -> Save Profile.
+
+ Note: due to a deficiency in openssl "Fetch Cert" is very slow on Windows.
+
Your Certificate + Key:
@@ -313,8 +330,8 @@ proc help_certs {} {
Select which file or directory by clicking on the appropriate "Browse..." button.
- Once selected, if you click the Right Mouse button on the "Browse..." button then
- information about the certificate will be displayed.
+ Once selected, if you click Info or the Right Mouse button on "Browse..."
+ then information about the certificate will be displayed.
Notes:
@@ -335,7 +352,7 @@ proc help_certs {} {
and then copy the Server certificate to the local (viewer-side) machine.
x11vnc prints out to the screen the Server certificate it generates.
You can set "ServerCert" to it directly or use the "Import Certificate"
- action to save it to a file.
+ action to save it to a file. Or use the "Fetch Cert" method.
x11vnc also has command line utilities to create server, client, and CA
(Certificate Authority) certificates. See the above URLs.
@@ -651,6 +668,7 @@ proc set_defaults {} {
global sound_daemon_local_cmd sound_daemon_local_port sound_daemon_local_kill sound_daemon_local_start
global smb_su_mode smb_mount_list
global use_port_knocking port_knocking_list
+ global ycrop_string
global include_list
set defs(use_viewonly) 0
@@ -700,6 +718,7 @@ proc set_defaults {} {
set defs(sound_daemon_local_kill) 0
set defs(use_port_knocking) 0
+ set defs(ycrop_string) ""
set defs(port_knocking_list) ""
set defs(include_list) ""
@@ -1949,6 +1968,271 @@ proc direct_connect_msg {} {
}
}
+proc fetch_cert {} {
+ global vncdisplay is_windows
+ set hp [get_vncdisplay]
+
+ regsub {[ ]*cmd=.*$} $hp "" tt
+ if {[regexp {^[ ]*$} $tt]} {
+ mesg "No host:disp supplied."
+ bell
+ catch {raise .}
+ return
+ }
+ if {[regexp -- {--nohost--} $tt]} {
+ mesg "No host:disp supplied."
+ bell
+ catch {raise .}
+ return
+ }
+ if {! [regexp ":" $hp]} {
+ if {! [regexp {cmd=} $hp]} {
+ append hp ":0"
+ }
+ }
+ set hpnew [get_ssh_hp $hp]
+ set proxy [get_ssh_proxy $hp]
+
+ mesg "Fetching $hpnew Cert..."
+ global cert_text
+ set cert_text ""
+ .f4.getcert configure -state disabled
+ update
+ if {$is_windows} {
+ set cert_text [fetch_cert_windows $hp]
+ } else {
+ catch {set cert_text [fetch_cert_unix $hp]}
+ }
+ .f4.getcert configure -state normal
+ mesg "Fetched $hpnew Cert"
+
+ set n 50
+ set ok 1
+ if {$cert_text == ""} {
+ set cert_text "An Error occurred in fetching SSL Certificate from $hp"
+ set ok 0
+ set n 4
+ } elseif {! [regexp {BEGIN CERTIFICATE} $cert_text]} {
+ set cert_text "An Error occurred in fetching $hp\n\n$cert_text"
+ set ok 0
+ } else {
+ set text ""
+ set on 0
+ foreach line [split $cert_text "\n"] {
+ if [regexp -- {-----BEGIN CERTIFICATE-----} $line] {
+ set on 1
+ }
+ if {! $on} {
+ continue;
+ }
+ append text "$line\n"
+ if [regexp -- {-----END CERTIFICATE-----} $line] {
+ set on 0
+ }
+ }
+ global is_windows
+ set tmp "/tmp/cert.hsh.[pid]"
+ if {$is_windows} {
+ set tmp cert.hsh
+ }
+ set fh ""
+ catch {set fh [open $tmp "w"]}
+ if {$fh != ""} {
+ puts $fh $text
+ close $fh
+ set info ""
+ catch {set info [get_x509_info $tmp]}
+ catch {file delete $tmp}
+ if [regexp -nocase {MD5 Finger[^\n]*} $info mvar] {
+ set cert_text "$mvar\n\n$cert_text"
+ }
+ if [regexp -nocase {SHA. Finger[^\n]*} $info mvar] {
+ set cert_text "$mvar\n\n$cert_text"
+ }
+ }
+ set cert_text "SSL Certificate from $hp\n\n$cert_text"
+ }
+
+ toplev .fetch
+
+ scroll_text_dismiss .fetch.f 90 $n
+
+ if {$ok} {
+ button .fetch.save -text Save -command "destroy .fetch; save_cert $hpnew"
+ pack .fetch.save -side bottom -fill x
+ }
+
+ center_win .fetch
+ wm title .fetch "$hp Certificate"
+
+ .fetch.f.t insert end $cert_text
+ jiggle_text .fetch.f.t
+}
+
+proc fetch_cert_unix {hp} {
+ set hpnew [get_ssh_hp $hp]
+ set proxy [get_ssh_proxy $hp]
+ if {$proxy != ""} {
+ return [exec ss_vncviewer -proxy $proxy -showcert $hpnew 2>/dev/null]
+ } else {
+ return [exec ss_vncviewer -showcert $hpnew]
+ }
+}
+
+proc fetch_cert_windows {hp} {
+ set hpnew [get_ssh_hp $hp]
+ set proxy [get_ssh_proxy $hp]
+
+ set list [split $hpnew ":"]
+
+ set host [lindex $list 0]
+ if {$host == ""} {
+ set host "localhost"
+ }
+
+ if [regexp {^.*@} $host match] {
+ mesg "Trimming \"$match\" from hostname"
+ regsub {^.*@} $host "" host
+ }
+
+ set disp [lindex $list 1]
+ set disp [string trim $disp]
+ regsub { .*$} $disp "" disp
+
+ if {$disp == "" || ! [regexp {^[0-9][0-9]*$} $disp]} {
+ set disp 0
+ }
+ set port [expr "$disp + 5900"]
+
+ if {$proxy != ""} {
+ global env
+
+ set port2 5991
+ set env(SSVNC_PROXY) $proxy
+ set env(SSVNC_LISTEN) $port2
+ set env(SSVNC_DEST) "$host:$port"
+
+ set host localhost
+ set port $port2
+ mesg "Starting TCP helper on port $port2 ..."
+ after 600
+ set proxy_pid [exec "connect_br.exe" &]
+ unset -nocomplain env(SSVNC_PROXY)
+ unset -nocomplain env(SSVNC_LISTEN)
+ unset -nocomplain env(SSVNC_DEST)
+ }
+
+ set ossl [get_openssl]
+ update
+ set tin tmpin.txt
+ set tou tmpout.txt
+ set fh ""
+ catch {set fh [open $tin "w"]}
+ if {$fh != ""} {
+ puts $fh "Q"
+ puts $fh "GET /WOMBAT HTTP/1.1\r\nHost: wombat.com\r\n\r\n\r\n"
+ close $fh
+ }
+ if {1} {
+ set ph ""
+ set ph [open "| $ossl s_client -connect $host:$port < $tin 2>NUL" "r"]
+# set ph [open "| $ossl s_client -connect $host:$port" "r"]
+ set text ""
+ if {$ph != ""} {
+ set pids [pid $ph]
+ set got 0
+ while {[gets $ph line] > -1} {
+ append text "$line\n"
+#mesg "line: $line"; after 10
+ if [regexp {END CERT} $line] {
+ set got 1
+ }
+ if {$got && [regexp {^ *Verify return code} $line]} {
+ break
+ }
+ if [regexp {^RFB } $line] {
+ break
+ }
+ if [regexp {^DONE} $line] {
+ break
+ }
+ }
+ foreach pid $pids {
+ global is_win9x
+ if {$pid == ""} {
+ ;
+ } elseif {$is_win9x} {
+ catch {exec w98/kill.exe /f $pid}
+ } else {
+ catch {exec tskill.exe $pid}
+ }
+ }
+ catch {close $ph}
+ catch {file delete $tin $tou}
+ return $text
+ }
+ } else {
+ set pids ""
+if {1} {
+ set ph2 [open "| $ossl s_client -connect $host:$port > $tou 2>NUL" "w"]
+ set pids [pid $ph2]
+ after 500
+ for {set i 0} {$i < 128} {incr i} {
+ puts $ph2 "Q"
+ }
+ catch {close $ph2}
+
+} else {
+ set pids [exec $ossl s_client -connect $host:$port < $tin >& $tou &]
+}
+ for {set i 0} {$i < 10} {incr i} {
+ after 500
+ set got 0
+ set ph ""
+ catch {set ph [open $tou "r"]}
+#mesg "open: $tou"
+ if {$ph != ""} {
+ while {[gets $ph line] > -1} {
+#mesg "line: $line"; after 10
+ if [regexp {END CERT} $line] {
+ set got 1
+ break
+ }
+ }
+ close $ph
+ }
+#mesg "clse: $tou"
+ if {$got} {
+ break
+#mesg "GOT"; after 200
+ }
+ }
+ global is_win9x
+ foreach pid $pids {
+#mesg "kill -- $pid"
+ if {$pid == ""} {
+ ;
+ } elseif {$is_win9x} {
+ catch {exec w98/kill.exe /f $pid}
+ } else {
+ catch {exec tskill.exe $pid}
+ }
+ }
+ after 500
+ set ph ""
+ catch {set ph [open $tou "r"]}
+ }
+ set text ""
+ if {$ph != ""} {
+ while {[gets $ph line] > -1} {
+ append text "$line\n"
+ }
+ close $ph
+ }
+ catch {file delete $tin $tou}
+ return $text
+}
+
proc launch_unix {hp} {
global smb_redir_0 smb_mounts env
global vncauth_passwd
@@ -2131,8 +2415,36 @@ proc launch_unix {hp} {
set cmd "$cmd $hp"
+ set do_vncspacewrapper 0
if {$change_vncviewer && $change_vncviewer_path != ""} {
- set env(VNCVIEWERCMD) $change_vncviewer_path
+ set path [string trim $change_vncviewer_path]
+ if [regexp {^["'].} $path] { # "
+ set tmp "/tmp/vncspacewrapper."
+ set do_vncspacewrapper 1
+ append tmp [clock clicks -milliseconds]
+ catch {file delete $tmp}
+ if {[file exists $tmp]} {
+ catch {destroy .c}
+ mesg "file still exists: $tmp"
+ bell
+ return
+ }
+ catch {set fh [open $tmp "w"]}
+ catch {exec chmod 700 $tmp}
+ if {! [file exists $tmp]} {
+ catch {destroy .c}
+ mesg "cannot create: $tmp"
+ bell
+ return
+ }
+ puts $fh "#!/bin/sh"
+ puts $fh "echo $tmp; set -xv"
+ puts $fh "$path \"\$@\""
+ puts $fh "sleep 1; rm -f $tmp"
+ close $fh
+ set path $tmp
+ }
+ set env(VNCVIEWERCMD) $path
} else {
if [info exists env(VNCVIEWERCMD_OVERRIDE)] {
set env(VNCVIEWERCMD) $env(VNCVIEWERCMD_OVERRIDE)
@@ -2145,7 +2457,19 @@ proc launch_unix {hp} {
set realvnc3 0
set flavor ""
if {! $darwin_cotvnc} {
- catch {set flavor [exec ss_vncviewer -viewerflavor 2>/dev/null]}
+ set done 0
+ if {$do_vncspacewrapper} {
+ if [regexp -nocase {ultra} $change_vncviewer_path] {
+ set done 1
+ set flavor "ultravnc"
+ } elseif [regexp -nocase {chicken.of} $change_vncviewer_path] {
+ set done 1
+ set flavor "cotvnc"
+ }
+ }
+ if {! $done} {
+ catch {set flavor [exec ss_vncviewer -viewerflavor 2>/dev/null]}
+ }
}
if [regexp {realvnc4} $flavor] {
set realvnc4 1
@@ -2174,6 +2498,8 @@ proc launch_unix {hp} {
if {$use_viewonly} {
if {$darwin_cotvnc} {
set cmd "$cmd --ViewOnly"
+ } elseif {$flavor == "ultravnc"} {
+ set cmd "$cmd /viewonly"
} else {
set cmd "$cmd -viewonly"
}
@@ -2181,6 +2507,8 @@ proc launch_unix {hp} {
if {$use_fullscreen} {
if {$darwin_cotvnc} {
set cmd "$cmd --FullScreen"
+ } elseif {$flavor == "ultravnc"} {
+ set cmd "$cmd /fullscreen"
} else {
set cmd "$cmd -fullscreen"
}
@@ -2188,6 +2516,8 @@ proc launch_unix {hp} {
if {$use_bgr233} {
if {$realvnc4} {
set cmd "$cmd -lowcolourlevel 1"
+ } elseif {$flavor == "ultravnc"} {
+ set cmd "$cmd /8bit"
} else {
set cmd "$cmd -bgr233"
}
@@ -2195,6 +2525,8 @@ proc launch_unix {hp} {
if {$use_nojpeg} {
if {$darwin_cotvnc} {
;
+ } elseif {$flavor == "ultravnc"} {
+ ;
} elseif {! $realvnc4 && ! $realvnc3} {
set cmd "$cmd -nojpeg"
}
@@ -2202,6 +2534,8 @@ proc launch_unix {hp} {
if {! $use_raise_on_beep} {
if {$darwin_cotvnc} {
;
+ } elseif {$flavor == "ultravnc"} {
+ ;
} elseif {! $realvnc4 && ! $realvnc3} {
set cmd "$cmd -noraiseonbeep"
}
@@ -2209,6 +2543,8 @@ proc launch_unix {hp} {
if {$use_compresslevel != "" && $use_compresslevel != "default"} {
if {$realvnc3} {
;
+ } elseif {$flavor == "ultravnc"} {
+ ;
} elseif {$realvnc4} {
set cmd "$cmd -zliblevel '$use_compresslevel'"
} else {
@@ -2218,6 +2554,8 @@ proc launch_unix {hp} {
if {$use_quality != "" && $use_quality != "default"} {
if {$darwin_cotvnc} {
;
+ } elseif {$flavor == "ultravnc"} {
+ ;
} elseif {! $realvnc4 && ! $realvnc3} {
set cmd "$cmd -quality '$use_quality'"
}
@@ -2226,6 +2564,8 @@ proc launch_unix {hp} {
# realvnc4 -preferredencoding zrle
if {$darwin_cotvnc} {
;
+ } elseif {$flavor == "ultravnc"} {
+ ;
} elseif {$realvnc4} {
set cmd "$cmd -preferredencoding zrle"
} else {
@@ -2233,11 +2573,27 @@ proc launch_unix {hp} {
}
}
+ global ycrop_string
+ catch {unset env(VNCVIEWER_SBWIDTH)}
+ catch {unset env(VNCVIEWER_YCROP)}
+ if {[info exists ycrop_string] && $ycrop_string != ""} {
+ set t $ycrop_string
+ if [regexp {,sb=([0-9][0-9]*)} $t m mv1] {
+ set env(VNCVIEWER_SBWIDTH) $mv1
+ }
+ regsub {,sb=([0-9][0-9]*)} $t "" t
+ if {$t != ""} {
+ set env(VNCVIEWER_YCROP) $t
+ }
+ #catch {puts "VNCVIEWER_SBWIDTH $env(VNCVIEWER_SBWIDTH)"}
+ #catch {puts "VNCVIEWER_YCROP $env(VNCVIEWER_YCROP)"}
+ }
+
catch {destroy .o}
catch {destroy .oa}
update
- if {$sound_daemon_local_start && $sound_daemon_local_cmd != ""} {
+ if {$use_sound && $sound_daemon_local_start && $sound_daemon_local_cmd != ""} {
mesg "running: $sound_daemon_local_cmd"
exec sh -c "$sound_daemon_local_cmd" >& /dev/null </dev/null &
update
@@ -2267,18 +2623,18 @@ proc launch_unix {hp} {
set xrm2 "XTerm*VT100*translations:#override Shift<Btn3Down>:print()\\nCtrl<Key>N:print()"
set xrm3 "*mainMenu*print*Label: New SSVNC_GUI"
}
- set m "Done. You Can X-out or Ctrl-C this Terminal if you like."
+ set m "Done. You Can X-out or Ctrl-C this Terminal if you like. Ctrl-\\\\ to pause."
global uname
if {$uname == "Darwin"} {
regsub {X-out or } $m "" m
}
unix_terminal_cmd $geometry "SSL/SSH VNC Viewer $hp" \
- "set -xv; $cmd; set +xv; echo; echo $m; echo; echo sleep 15; echo; sleep 15" 0 $xrm1 $xrm2 $xrm3
+ "set -xv; $cmd; set +xv; ulimit -c 0; trap 'printf \"Paused. Press Enter to exit:\"; read x' QUIT; echo; echo $m; echo; echo sleep 5; echo; sleep 6" 0 $xrm1 $xrm2 $xrm3
set env(SS_VNCVIEWER_SSH_CMD) ""
set env(SS_VNCVIEWER_USE_C) ""
- if {$sound_daemon_local_kill && $sound_daemon_local_cmd != ""} {
+ if {$use_sound && $sound_daemon_local_kill && $sound_daemon_local_cmd != ""} {
set daemon [string trim $sound_daemon_local_cmd]
regsub {^gw[ \t]*} $daemon "" daemon
regsub {[ \t].*$} $daemon "" daemon
@@ -2940,7 +3296,7 @@ proc get_x509_info {crt} {
set ossl [get_openssl]
set info ""
update
- set ph [open "| $ossl x509 -text -in \"$crt\"" "r"]
+ set ph [open "| $ossl x509 -text -fingerprint -in \"$crt\"" "r"]
while {[gets $ph line] > -1} {
append info "$line\n"
}
@@ -3288,7 +3644,7 @@ proc create_cert {} {
(it is also possible to handle many client certs at once in a directory,
see the -sslverify documentation). Then you would use "vnccert.pem"
- as the MyCert entry in the Set SSL Certificates dialog.
+ as the MyCert entry in the SSL Certificates dialog.
For case 2) you would copy "vnccert.pem" to the VNC Server side and
instruct the server to use it. For x11vnc it would be for example:
@@ -3296,7 +3652,7 @@ proc create_cert {} {
x11vnc -ssl /path/to/vnccert.pem
Then you would use "vnccert.crt" as the as the ServerCert entry in the
- "Set SSL Certificates" dialog.
+ "SSL Certificates" dialog.
Creating the Certificate:
@@ -3317,7 +3673,7 @@ proc create_cert {} {
After you have created the certificate files, you must copy and import
either "vnccert.pem" or "vnccert.pem" to the remote VNC Server and
- also select the other file in the "Set SSL Certificates" dialog.
+ also select the other file in the "SSL Certificates" dialog.
See the description above.
For more information see:
@@ -3453,7 +3809,7 @@ proc import_browse {} {
update
}
-proc import_save_browse {} {
+proc import_save_browse {{par ".icrt"}} {
global import_save_file
set idir ""
@@ -3464,14 +3820,14 @@ proc import_save_browse {} {
set idir [get_idir_certs ""]
}
if {$idir != ""} {
- set t [tk_getSaveFile -parent .icrt -defaultextension ".crt" -initialdir $idir]
+ set t [tk_getSaveFile -parent $par -defaultextension ".crt" -initialdir $idir]
} else {
- set t [tk_getSaveFile -parent .icrt -defaultextension ".crt"]
+ set t [tk_getSaveFile -parent $par -defaultextension ".crt"]
}
if {$t != ""} {
set import_save_file $t
}
- catch {raise .icrt}
+ catch {raise $par}
update
}
@@ -3485,7 +3841,10 @@ proc do_save {} {
}
set str ""
- if {$import_mode == "paste"} {
+ if {$import_mode == "save_cert_text"} {
+ global save_cert_text
+ set str $save_cert_text
+ } elseif {$import_mode == "paste"} {
set str [.icrt.paste.t get 1.0 end]
} else {
if {! [file exists $import_file]} {
@@ -3536,8 +3895,17 @@ proc do_save {} {
puts -nonewline $fh $str
close $fh
catch {destroy .icrt}
+ set p .c
+ if {![winfo exists .c]} {
+ getcerts
+ update
+ }
+ if {![winfo exists .c]} {
+ set p .
+ }
catch {raise .c}
- tk_messageBox -parent .c -type ok -icon info \
+ catch {destroy .scrt}
+ tk_messageBox -parent $p -type ok -icon info \
-message "Saved to file: $import_save_file" -title "Save File: $import_save_file"
}
@@ -3664,12 +4032,104 @@ TCQ+tbQ/DOiTXGKx1nlcKoPdkG+QVQVJthlQcpam
center_win .icrt
}
+proc save_cert {hp} {
+
+ toplev .scrt
+ wm title .scrt "Import SSL Certificate"
+
+ global scroll_text_focus
+ set scroll_text_focus 0
+ global uname
+ scroll_text .scrt.f 90 14
+ set scroll_text_focus 1
+
+ set msg {
+ This dialog lets you import a SSL Certificate retrieved from a VNC server.
+
+ Set the "Save to File" name to the file where the imported certificate
+ will be saved.
+
+ Then, click on "Save" to save the imported Certificate.
+
+ After you have imported the Certificate it will be automatically selected
+ as the "ServerCert" for this host: %HOST
+
+ To make the ServerCert setting to the imported cert file permanent,
+ select Options -> Save Profile to save it in a profile.
+}
+
+ regsub {%HOST} $msg "$hp" msg
+ .scrt.f.t insert end $msg
+
+ set w .scrt.mf
+ frame $w
+
+ global import_file
+ set import_file ""
+ entry $w.e -width 40 -textvariable import_file
+
+ scroll_text .scrt.paste 90 26
+
+ button .scrt.cancel -text "Cancel" -command {destroy .scrt; catch {raise .c}}
+ bind .scrt <Escape> {destroy .scrt; catch {raise .c}}
+
+ global import_save_file
+ button .scrt.save -text "Save" -command {do_save; set svcert $import_save_file}
+
+ set w .scrt.sf
+ frame $w
+
+ label $w.l -text "Save to File:" -anchor w
+ set import_save_file "server:$hp.crt"
+ global is_windows
+ if {$is_windows} {
+ regsub -all {:} $import_save_file "_" import_save_file
+ }
+ set import_save_file [get_idir_certs ""]/$import_save_file
+ entry $w.e -width 40 -textvariable import_save_file
+ button $w.b -pady 1 -anchor w -text "Browse..." -command {import_save_browse .scrt}
+
+ pack $w.b -side right
+ pack $w.l -side left
+ pack $w.e -side left -expand 1 -fill x
+
+ pack .scrt.cancel .scrt.save .scrt.sf .scrt.mf -side bottom -fill x
+ pack .scrt.paste -side bottom -fill x
+
+ pack .scrt.f -side top -fill both -expand 1
+
+ global cert_text
+ set text ""
+ set on 0
+ foreach line [split $cert_text "\n"] {
+ if [regexp -- {-----BEGIN CERTIFICATE-----} $line] {
+ set on 1
+ }
+ if {! $on} {
+ continue;
+ }
+ append text "$line\n"
+ if [regexp -- {-----END CERTIFICATE-----} $line] {
+ set on 0
+ }
+ }
+ global save_cert_text
+ set save_cert_text $text
+ .scrt.paste.t insert end "$text"
+ global import_mode
+ set import_mode "save_cert_text"
+
+ focus .scrt.paste.t
+
+ center_win .scrt
+}
+
proc getcerts {} {
global mycert svcert crtdir
global use_ssh use_sshssl
toplev .c
- wm title .c "Set SSL Certificates"
+ wm title .c "SSL Certificates"
frame .c.mycert
frame .c.svcert
frame .c.crtdir
@@ -3690,6 +4150,8 @@ proc getcerts {} {
button .c.mycert.i -text "Info" -command {show_mycert}
button .c.svcert.i -text "Info" -command {show_svcert}
button .c.crtdir.i -text "Info" -command {}
+ bind .c.mycert.b <Enter> "v_mycert"
+ bind .c.svcert.b <Enter> "v_svcert"
.c.mycert.i configure -state disabled
.c.svcert.i configure -state disabled
.c.crtdir.i configure -state disabled
@@ -3718,6 +4180,13 @@ proc getcerts {} {
}
}
+ if {$mycert != ""} {
+ v_mycert
+ }
+ if {$svcert != ""} {
+ v_svcert
+ }
+
pack .c.mycert .c.svcert .c.crtdir .c.create .c.import .c.b -side top -fill x
center_win .c
wm resizable .c 1 0
@@ -5776,6 +6245,15 @@ proc help_advanced_opts {} {
The port can also be closed when the encrypted VNC connection
finishes.
+ Y Crop: this is for x11vnc's -ncache client side caching scheme
+ with our Unix TightVNC viewer. Sets the Y value to "crop" the
+ viewer size at (below the cut is the pixel cache region you do
+ not want to see). If the screen is tall (H > 2*W) ycropping
+ will be autodetected, or you can set to -1 to force autodection.
+ Otherwise, set it to the desired Y value. You can also set
+ the scrollbar width (very thin by default) by appending ",sb=N"
+ (or use ",sb=N" by itself to just set the scrollbar width).
+
Include: Profile template(s) to load before loading a profile
(see Load Profile under "Options"). For example if you Save a
profile called "globals" that has some settings you use often,
@@ -5812,7 +6290,7 @@ proc change_vncviewer_dialog {} {
wm title .chviewer "Change VNC Viewer"
global help_font
- eval text .chviewer.t -width 90 -height 16 $help_font
+ eval text .chviewer.t -width 90 -height 24 $help_font
apply_bg .chviewer.t
set msg {
@@ -5826,10 +6304,17 @@ proc change_vncviewer_dialog {} {
avoid setting any others in this GUI under "Options").
If the path to the program name has any spaces it in, please surround it with
- double quotes, e.g. "C:\Program Files\My Vnc Viewer\VNCVIEWER.EXE"
+ double quotes, e.g.
+
+ "C:\Program Files\My Vnc Viewer\VNCVIEWER.EXE"
+
+ Make sure the very first character is a quote. You should quote the command
+ even if it is only the command line arguments that need extra protection:
+
+ "wine" -- "/home/fred/Program Flies/UltraVNC-1.0.2.exe" /64colors
Since the command line options differ between them greatly, if you know it
- is of the RealVNC 4.x flavor, indicate so on the check box.
+ is of the RealVNC 4.x flavor, indicate on the check box. Otherwise we guess.
}
.chviewer.t insert end $msg
@@ -6558,6 +7043,15 @@ proc set_advanced_options {} {
-command {if {$use_port_knocking} {port_knocking_dialog}}
incr i
+ global ycrop_string
+ frame .oa.b$i
+ label .oa.b$i.l -text "Y Crop: "
+ entry .oa.b$i.e -width 10 -textvariable ycrop_string
+ pack .oa.b$i.l -side left
+ pack .oa.b$i.e -side right -expand 1 -fill x
+
+ incr i
+
global include_list
frame .oa.b$i
label .oa.b$i.l -text "Include:"
@@ -6706,16 +7200,19 @@ proc ssl_ssh_adjust {which} {
set use_ssh 0
set use_sshssl 0
set sshssl_sw "ssl"
+ catch {.f4.getcert configure -state normal}
} elseif {$which == "ssh"} {
set use_ssl 0
set use_ssh 1
set use_sshssl 0
set sshssl_sw "ssh"
+ catch {.f4.getcert configure -state disabled}
} elseif {$which == "sshssl"} {
set use_ssl 0
set use_ssh 0
set use_sshssl 1
set sshssl_sw "sshssl"
+ catch {.f4.getcert configure -state disabled}
}
if [info exists remote_ssh_cmd_list] {
@@ -6955,6 +7452,7 @@ label .f1.l -width $wl -anchor w -text "VNC Password:" -relief ridge
entry .f1.e -width $we -textvariable vncauth_passwd -show *
pack .f1.l -side left
pack .f1.e -side left -expand 1 -fill x
+bind .f1.e <Return> launch
frame .f2
label .f2.l -width $wl -anchor w -text "Proxy/Gateway:" -relief ridge
@@ -6976,7 +7474,9 @@ frame .f4
radiobutton .f4.ssl -anchor w -variable sshssl_sw -value ssl -command {ssl_ssh_adjust ssl} -text "Use SSL"
radiobutton .f4.ssh -anchor w -variable sshssl_sw -value ssh -command {ssl_ssh_adjust ssh} -text "Use SSH"
radiobutton .f4.sshssl -anchor w -variable sshssl_sw -value sshssl -command {ssl_ssh_adjust sshssl} -text "Use SSH and SSL"
+button .f4.getcert -command {fetch_cert} -text "Fetch Cert"
pack .f4.ssl .f4.ssh .f4.sshssl -side left -fill x
+pack .f4.getcert -side right -fill x
ssl_ssh_adjust ssl
diff --git a/x11vnc/misc/enhanced_tightvnc_viewer/build.unix b/x11vnc/misc/enhanced_tightvnc_viewer/build.unix
index 1678478..e18510c 100755
--- a/x11vnc/misc/enhanced_tightvnc_viewer/build.unix
+++ b/x11vnc/misc/enhanced_tightvnc_viewer/build.unix
@@ -166,6 +166,10 @@ do
if [ ! -f "$patch" ]; then
continue
fi
+ if [ "X$PATCH_FAIL" != "X" ]; then
+ failed=1
+ break
+ fi
echo PATCHING WITH: "$patch"
ls -l "$patch"
sleep 1
@@ -254,6 +258,10 @@ do
if [ ! -f "$patch" ]; then
continue
fi
+ if [ "X$PATCH_FAIL" != "X" ]; then
+ failed=1
+ break
+ fi
echo PATCHING WITH: "$patch"
ls -l "$patch"
sleep 1
diff --git a/x11vnc/misc/enhanced_tightvnc_viewer/src/patches/_bundle b/x11vnc/misc/enhanced_tightvnc_viewer/src/patches/_bundle
index 054c8d6..694e132 100755
--- a/x11vnc/misc/enhanced_tightvnc_viewer/src/patches/_bundle
+++ b/x11vnc/misc/enhanced_tightvnc_viewer/src/patches/_bundle
@@ -1,7 +1,7 @@
#!/bin/sh
rm -rf ./src/tmp/* || exit 1
-vers=1.0.11
+vers=1.0.12
cd .. || exit 1
diff --git a/x11vnc/misc/enhanced_tightvnc_viewer/src/patches/tight-vncviewer-full.patch b/x11vnc/misc/enhanced_tightvnc_viewer/src/patches/tight-vncviewer-full.patch
index 4dd2bd0..714d624 100644
--- a/x11vnc/misc/enhanced_tightvnc_viewer/src/patches/tight-vncviewer-full.patch
+++ b/x11vnc/misc/enhanced_tightvnc_viewer/src/patches/tight-vncviewer-full.patch
@@ -1,15 +1,18 @@
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/Vncviewer vnc_unixsrc/vncviewer/Vncviewer
--- vnc_unixsrc.orig/vncviewer/Vncviewer 2003-02-07 05:30:57.000000000 -0500
-+++ vnc_unixsrc/vncviewer/Vncviewer 2007-02-04 18:25:33.000000000 -0500
-@@ -5,7 +5,7 @@
++++ vnc_unixsrc/vncviewer/Vncviewer 2007-02-18 19:52:59.000000000 -0500
+@@ -5,9 +5,9 @@
!
! The title of the main window. "%s" will be replaced by the desktop name.
-!
+!
- Vncviewer.title: TightVNC: %s
+-Vncviewer.title: TightVNC: %s
++Vncviewer.title: SSVNC: %s Press F8 for Menu
+
+ !
@@ -50,6 +50,7 @@
*desktop.baseTranslations:\
@@ -18,126 +21,217 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/Vncviewer vnc_unixsrc/vncview
<ButtonPress>: SendRFBEvent()\n\
<ButtonRelease>: SendRFBEvent()\n\
<Motion>: SendRFBEvent()\n\
-@@ -79,7 +80,7 @@
+@@ -77,9 +78,9 @@
+ ! Popup window appearance
+ !
- *popup.title: TightVNC popup
+-*popup.title: TightVNC popup
++*popup.title: SSVNC popup
*popup*background: grey
-*popup*font: -*-helvetica-bold-r-*-*-16-*-*-*-*-*-*-*
+*popup*font: -*-helvetica-medium-r-*-*-12-*-*-*-*-*-*-*
*popup.buttonForm.Command.borderWidth: 0
*popup.buttonForm.Toggle.borderWidth: 0
-@@ -96,7 +97,7 @@
+@@ -96,43 +97,154 @@
! Popup buttons
!
-*popupButtonCount: 8
-+*popupButtonCount: 22
++*popupButtonCount: 27
*popup*button1.label: Dismiss popup
- *popup*button1.translations: #override\n\
-@@ -136,3 +137,86 @@
+-*popup*button1.translations: #override\n\
+- <Btn1Down>,<Btn1Up>: HidePopup()
++*popup*button1.translations: #override\\n\
++ <Btn1Down>,<Btn1Up>: HidePopup()
+
+ *popup*button2.label: Quit viewer
+-*popup*button2.translations: #override\n\
+- <Btn1Down>,<Btn1Up>: Quit()
++*popup*button2.translations: #override\\n\
++ <Btn1Down>,<Btn1Up>: Quit()
+
+-*popup*button3.label: Full screen
++*popup*button3.label: Full screen (also F9)
+ *popup*button3.type: toggle
+-*popup*button3.translations: #override\n\
+- <Visible>: SetFullScreenState()\n\
+- <Btn1Down>,<Btn1Up>: toggle() HidePopup() ToggleFullScreen()
++*popup*button3.translations: #override\\n\
++ <Visible>: SetFullScreenState()\\n\
++ <Btn1Down>,<Btn1Up>: toggle() ToggleFullScreen() HidePopup()
+
+ *popup*button4.label: Clipboard: local -> remote
+-*popup*button4.translations: #override\n\
+- <Btn1Down>,<Btn1Up>: SelectionToVNC(always) HidePopup()
++*popup*button4.translations: #override\\n\
++ <Btn1Down>,<Btn1Up>: SelectionToVNC(always) HidePopup()
+
+ *popup*button5.label: Clipboard: local <- remote
+-*popup*button5.translations: #override\n\
+- <Btn1Down>,<Btn1Up>: SelectionFromVNC(always) HidePopup()
++*popup*button5.translations: #override\\n\
++ <Btn1Down>,<Btn1Up>: SelectionFromVNC(always) HidePopup()
+
+ *popup*button6.label: Request refresh
+-*popup*button6.translations: #override\n\
+- <Btn1Down>,<Btn1Up>: SendRFBEvent(fbupdate) HidePopup()
++*popup*button6.translations: #override\\n\
++ <Btn1Down>,<Btn1Up>: SendRFBEvent(fbupdate) HidePopup()
+
+ *popup*button7.label: Send ctrl-alt-del
+-*popup*button7.translations: #override\n\
+- <Btn1Down>,<Btn1Up>: SendRFBEvent(keydown,Control_L)\
+- SendRFBEvent(keydown,Alt_L)\
+- SendRFBEvent(key,Delete)\
+- SendRFBEvent(keyup,Alt_L)\
+- SendRFBEvent(keyup,Control_L)\
+- HidePopup()
++*popup*button7.translations: #override\\n\
++ <Btn1Down>,<Btn1Up>: SendRFBEvent(keydown,Control_L)\
++ SendRFBEvent(keydown,Alt_L)\
++ SendRFBEvent(key,Delete)\
++ SendRFBEvent(keyup,Alt_L)\
++ SendRFBEvent(keyup,Control_L)\
++ HidePopup()
+
*popup*button8.label: Send F8
- *popup*button8.translations: #override\n\
- <Btn1Down>,<Btn1Up>: SendRFBEvent(key,F8) HidePopup()
+-*popup*button8.translations: #override\n\
+- <Btn1Down>,<Btn1Up>: SendRFBEvent(key,F8) HidePopup()
++*popup*button8.translations: #override\\n\
++ <Btn1Down>,<Btn1Up>: SendRFBEvent(key,F8) HidePopup()
+
+*popup*button9.label: Send F9
-+*popup*button9.translations: #override\n\
-+ <Btn1Down>,<Btn1Up>: SendRFBEvent(key,F9) HidePopup()
++*popup*button9.translations: #override\\n\
++ <Btn1Down>,<Btn1Up>: SendRFBEvent(key,F9) HidePopup()
+
+*popup*button10.label: ViewOnly
+*popup*button10.type: toggle
-+*popup*button10.translations: #override\n\
-+ <Visible>: SetViewOnlyState()\n\
-+ <Btn1Down>,<Btn1Up>: toggle() ToggleViewOnly() HidePopup()
++*popup*button10.translations: #override\\n\
++ <Visible>: SetViewOnlyState()\\n\
++ <Btn1Down>,<Btn1Up>: toggle() ToggleViewOnly() HidePopup()
+
+*popup*button11.label: Cursor Shape
+*popup*button11.type: toggle
-+*popup*button11.translations: #override\n\
-+ <Visible>: SetCursorShapeState()\n\
-+ <Btn1Down>,<Btn1Up>: toggle() ToggleCursorShape() HidePopup()
++*popup*button11.translations: #override\\n\
++ <Visible>: SetCursorShapeState()\\n\
++ <Btn1Down>,<Btn1Up>: toggle() ToggleCursorShape() HidePopup()
+
+*popup*button12.label: X11 Cursor
+*popup*button12.type: toggle
-+*popup*button12.translations: #override\n\
-+ <Visible>: SetX11CursorState()\n\
-+ <Btn1Down>,<Btn1Up>: toggle() ToggleX11Cursor() HidePopup()
++*popup*button12.translations: #override\\n\
++ <Visible>: SetX11CursorState()\\n\
++ <Btn1Down>,<Btn1Up>: toggle() ToggleX11Cursor() HidePopup()
+
+*popup*button13.label: Cursor Alphablend
+*popup*button13.type: toggle
-+*popup*button13.translations: #override\n\
-+ <Visible>: SetCursorAlphaState()\n\
-+ <Btn1Down>,<Btn1Up>: toggle() ToggleCursorAlpha() HidePopup()
++*popup*button13.translations: #override\\n\
++ <Visible>: SetCursorAlphaState()\\n\
++ <Btn1Down>,<Btn1Up>: toggle() ToggleCursorAlpha() HidePopup()
+
+*popup*button14.label: Toggle Tight/ZRLE
+*popup*button14.type: toggle
-+*popup*button14.translations: #override\n\
-+ <Visible>: SetZRLEState()\n\
-+ <Btn1Down>,<Btn1Up>: toggle() ToggleTightZRLE() HidePopup()
++*popup*button14.translations: #override\\n\
++ <Visible>: SetZRLEState()\\n\
++ <Btn1Down>,<Btn1Up>: toggle() ToggleTightZRLE() HidePopup()
+
+*popup*button15.label: Disable JPEG
+*popup*button15.type: toggle
-+*popup*button15.translations: #override\n\
-+ <Visible>: SetNOJPEGState()\n\
-+ <Btn1Down>,<Btn1Up>: toggle() ToggleJPEG() HidePopup()
++*popup*button15.translations: #override\\n\
++ <Visible>: SetNOJPEGState()\\n\
++ <Btn1Down>,<Btn1Up>: toggle() ToggleJPEG() HidePopup()
+
+*popup*button16.label: Prefer raw for localhost
+*popup*button16.type: toggle
-+*popup*button16.translations: #override\n\
-+ <Visible>: SetRawLocalState()\n\
-+ <Btn1Down>,<Btn1Up>: toggle() ToggleRawLocal() HidePopup()
++*popup*button16.translations: #override\\n\
++ <Visible>: SetRawLocalState()\\n\
++ <Btn1Down>,<Btn1Up>: toggle() ToggleRawLocal() HidePopup()
+
+*popup*button17.label: Full Color
+*popup*button17.type: toggle
-+*popup*button17.translations: #override\n\
-+ <Visible>: SetFullColorState()\n\
-+ <Btn1Down>,<Btn1Up>: toggle() ToggleFullColor() HidePopup()
++*popup*button17.translations: #override\\n\
++ <Visible>: SetFullColorState()\\n\
++ <Btn1Down>,<Btn1Up>: toggle() ToggleFullColor() HidePopup()
+
-+*popup*button18.label: 16 bit color (BGR565)
++*popup*button18.label: Grey Scale (16 & 8-bpp)
+*popup*button18.type: toggle
-+*popup*button18.translations: #override\n\
-+ <Visible>: Set16bppState()\n\
-+ <Btn1Down>,<Btn1Up>: toggle() Toggle16bpp() HidePopup()
++*popup*button18.translations: #override\\n\
++ <Visible>: SetGreyScaleState()\\n\
++ <Btn1Down>,<Btn1Up>: toggle() ToggleGreyScale() HidePopup()
+
-+*popup*button19.label: 8 bit color (BGR233)
++*popup*button19.label: 16 bit color (BGR565)
+*popup*button19.type: toggle
-+*popup*button19.translations: #override\n\
-+ <Visible>: Set8bppState()\n\
-+ <Btn1Down>,<Btn1Up>: toggle() Toggle8bpp() HidePopup()
++*popup*button19.translations: #override\\n\
++ <Visible>: Set16bppState()\\n\
++ <Btn1Down>,<Btn1Up>: toggle() Toggle16bpp() HidePopup()
+
-+*popup*button20.label: - 256 colors
++*popup*button20.label: 8 bit color (BGR233)
+*popup*button20.type: toggle
-+*popup*button20.translations: #override\n\
-+ <Visible>: Set256ColorsState()\n\
-+ <Btn1Down>,<Btn1Up>: toggle() Toggle256Colors() HidePopup()
++*popup*button20.translations: #override\\n\
++ <Visible>: Set8bppState()\\n\
++ <Btn1Down>,<Btn1Up>: toggle() Toggle8bpp() HidePopup()
+
-+*popup*button21.label: - 64 colors
++*popup*button21.label: - 256 colors
+*popup*button21.type: toggle
-+*popup*button21.translations: #override\n\
-+ <Visible>: Set64ColorsState()\n\
-+ <Btn1Down>,<Btn1Up>: toggle() Toggle64Colors() HidePopup()
++*popup*button21.translations: #override\\n\
++ <Visible>: Set256ColorsState()\\n\
++ <Btn1Down>,<Btn1Up>: toggle() Toggle256Colors() HidePopup()
+
-+*popup*button22.label: - 8 colors
++*popup*button22.label: - 64 colors
+*popup*button22.type: toggle
-+*popup*button22.translations: #override\n\
-+ <Visible>: Set8ColorsState()\n\
-+ <Btn1Down>,<Btn1Up>: toggle() Toggle8Colors() HidePopup()
++*popup*button22.translations: #override\\n\
++ <Visible>: Set64ColorsState()\\n\
++ <Btn1Down>,<Btn1Up>: toggle() Toggle64Colors() HidePopup()
++
++*popup*button23.label: - 8 colors
++*popup*button23.type: toggle
++*popup*button23.translations: #override\\n\
++ <Visible>: Set8ColorsState()\\n\
++ <Btn1Down>,<Btn1Up>: toggle() Toggle8Colors() HidePopup()
++
++*popup*button24.label: Disable Remote Input
++*popup*button24.type: toggle
++*popup*button24.translations: #override\\n\
++ <Visible>: SetServerInputState()\\n\
++ <Btn1Down>,<Btn1Up>: toggle() ToggleServerInput() HidePopup()
++
++*popup*button25.label: Single Window
++*popup*button25.type: toggle
++*popup*button25.translations: #override\\n\
++ <Visible>: SetSingleWindowState()\\n\
++ <Btn1Down>,<Btn1Up>: toggle() ToggleSingleWindow() HidePopup()
++
++*popup*button26.label: Set 1/n Server Scale
++*popup*button26.translations: #override\\n\
++ <Btn1Down>,<Btn1Up>: DoServerScale() HidePopup()
++
++*popup*button27.label: Text Chat
++*popup*button27.type: toggle
++*popup*button27.translations: #override\\n\
++ <Visible>: SetTextChatState()\\n\
++ <Btn1Down>,<Btn1Up>: toggle() ToggleTextChat() HidePopup()
+
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/vncviewer/argsresources.c
--- vnc_unixsrc.orig/vncviewer/argsresources.c 2007-02-04 17:10:31.000000000 -0500
-+++ vnc_unixsrc/vncviewer/argsresources.c 2007-02-04 18:25:53.000000000 -0500
-@@ -45,8 +45,18 @@
++++ vnc_unixsrc/vncviewer/argsresources.c 2007-02-18 20:41:40.000000000 -0500
+@@ -31,7 +31,7 @@
+
+ char *fallback_resources[] = {
+
+- "Vncviewer.title: TightVNC: %s",
++ "Vncviewer.title: SSVNC: %s - Press F8 for Menu",
+
+ "Vncviewer.translations:\
+ <Enter>: SelectionToVNC()\\n\
+@@ -45,8 +45,14 @@
"*viewport.useRight: True",
"*viewport*Scrollbar*thumb: None",
-+#if 0
-+ "vncviewer*.desktop.translations: #override Shift <Key>F8: ToggleFullScreen()",
-+ "vncviewer*.desktop.translations: #override <Key>F9: ToggleFullScreen()",
-+#endif
-+ "*viewport.horizontal.height: %SBW",
-+ "*viewport.vertical.width: %SBW",
-+ "vncviewer*viewport.horizontal.height: %SBW",
-+ "vncviewer*viewport.vertical.width: %SBW",
++ "*viewport.horizontal.height: 6 ",
++ "*viewport.vertical.width: 6 ",
++ "vncviewer*viewport.horizontal.height: 6 ",
++ "vncviewer*viewport.vertical.width: 6 ",
+
"*desktop.baseTranslations:\
- <Key>F8: ShowPopup()\\n\
@@ -146,9 +240,12 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v
<ButtonPress>: SendRFBEvent()\\n\
<ButtonRelease>: SendRFBEvent()\\n\
<Motion>: SendRFBEvent()\\n\
-@@ -66,7 +76,8 @@
+@@ -64,9 +70,10 @@
+ "*passwordDialog.dialog.value.translations: #override\\n\
+ <Key>Return: PasswordDialogDone()",
- "*popup.title: TightVNC popup",
+- "*popup.title: TightVNC popup",
++ "*popup.title: SSVNC popup",
"*popup*background: grey",
- "*popup*font: -*-helvetica-bold-r-*-*-16-*-*-*-*-*-*-*",
+ "*popup*font_old: -*-helvetica-bold-r-*-*-16-*-*-*-*-*-*-*",
@@ -156,16 +253,25 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v
"*popup.buttonForm.Command.borderWidth: 0",
"*popup.buttonForm.Toggle.borderWidth: 0",
-@@ -74,7 +85,7 @@
+@@ -74,7 +81,7 @@
"*popup.buttonForm.translations: #override\\n\
<KeyPress>: SendRFBEvent() HidePopup()",
- "*popupButtonCount: 8",
-+ "*popupButtonCount: 22",
++ "*popupButtonCount: 27",
"*popup*button1.label: Dismiss popup",
"*popup*button1.translations: #override\\n\
-@@ -115,6 +126,96 @@
+@@ -84,7 +91,7 @@
+ "*popup*button2.translations: #override\\n\
+ <Btn1Down>,<Btn1Up>: Quit()",
+
+- "*popup*button3.label: Full screen",
++ "*popup*button3.label: Full screen (also F9)",
+ "*popup*button3.type: toggle",
+ "*popup*button3.translations: #override\\n\
+ <Visible>: SetFullScreenState()\\n\
+@@ -115,9 +122,127 @@
"*popup*button8.translations: #override\\n\
<Btn1Down>,<Btn1Up>: SendRFBEvent(key,F8) HidePopup()",
@@ -203,14 +309,6 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v
+ <Visible>: SetZRLEState()\\n\
+ <Btn1Down>,<Btn1Up>: toggle() ToggleTightZRLE() HidePopup()",
+
-+#if 0
-+ "*popup*button14.label: - ZRLE/ZWYRLE",
-+ "*popup*button14.type: toggle",
-+ "*popup*button14.translations: #override\\n\
-+ <Visible>: SetZRLEState()\\n\
-+ <Btn1Down>,<Btn1Up>: toggle() ToggleTightZRLE() HidePopup()",
-+#endif
-+
+ "*popup*button15.label: Disable JPEG",
+ "*popup*button15.type: toggle",
+ "*popup*button15.translations: #override\\n\
@@ -229,40 +327,79 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v
+ <Visible>: SetFullColorState()\\n\
+ <Btn1Down>,<Btn1Up>: toggle() ToggleFullColor() HidePopup()",
+
-+ "*popup*button18.label: 16 bit color (BGR565)",
++ "*popup*button18.label: Grey Scale (16 & 8-bpp)",
+ "*popup*button18.type: toggle",
+ "*popup*button18.translations: #override\\n\
-+ <Visible>: Set16bppState()\\n\
-+ <Btn1Down>,<Btn1Up>: toggle() Toggle16bpp() HidePopup()",
++ <Visible>: SetGreyScaleState()\\n\
++ <Btn1Down>,<Btn1Up>: toggle() ToggleGreyScale() HidePopup()",
+
-+ "*popup*button19.label: 8 bit color (BGR233)",
++ "*popup*button19.label: 16 bit color (BGR565)",
+ "*popup*button19.type: toggle",
+ "*popup*button19.translations: #override\\n\
-+ <Visible>: Set8bppState()\\n\
-+ <Btn1Down>,<Btn1Up>: toggle() Toggle8bpp() HidePopup()",
++ <Visible>: Set16bppState()\\n\
++ <Btn1Down>,<Btn1Up>: toggle() Toggle16bpp() HidePopup()",
+
-+ "*popup*button20.label: - 256 colors",
++ "*popup*button20.label: 8 bit color (BGR233)",
+ "*popup*button20.type: toggle",
+ "*popup*button20.translations: #override\\n\
-+ <Visible>: Set256ColorsState()\\n\
-+ <Btn1Down>,<Btn1Up>: toggle() Toggle256Colors() HidePopup()",
++ <Visible>: Set8bppState()\\n\
++ <Btn1Down>,<Btn1Up>: toggle() Toggle8bpp() HidePopup()",
+
-+ "*popup*button21.label: - 64 colors",
++ "*popup*button21.label: - 256 colors",
+ "*popup*button21.type: toggle",
+ "*popup*button21.translations: #override\\n\
-+ <Visible>: Set64ColorsState()\\n\
-+ <Btn1Down>,<Btn1Up>: toggle() Toggle64Colors() HidePopup()",
++ <Visible>: Set256ColorsState()\\n\
++ <Btn1Down>,<Btn1Up>: toggle() Toggle256Colors() HidePopup()",
+
-+ "*popup*button22.label: - 8 colors",
++ "*popup*button22.label: - 64 colors",
+ "*popup*button22.type: toggle",
+ "*popup*button22.translations: #override\\n\
++ <Visible>: Set64ColorsState()\\n\
++ <Btn1Down>,<Btn1Up>: toggle() Toggle64Colors() HidePopup()",
++
++ "*popup*button23.label: - 8 colors",
++ "*popup*button23.type: toggle",
++ "*popup*button23.translations: #override\\n\
+ <Visible>: Set8ColorsState()\\n\
+ <Btn1Down>,<Btn1Up>: toggle() Toggle8Colors() HidePopup()",
+
++ "*popup*button24.label: Disable Remote Input",
++ "*popup*button24.type: toggle",
++ "*popup*button24.translations: #override\\n\
++ <Visible>: SetServerInputState()\\n\
++ <Btn1Down>,<Btn1Up>: toggle() ToggleServerInput() HidePopup()",
++
++ "*popup*button25.label: Single Window",
++ "*popup*button25.type: toggle",
++ "*popup*button25.translations: #override\\n\
++ <Visible>: SetSingleWindowState()\\n\
++ <Btn1Down>,<Btn1Up>: toggle() ToggleSingleWindow() HidePopup()",
++
++ "*popup*button26.label: Set 1/n Server Scale",
++ "*popup*button26.translations: #override\\n\
++ <Btn1Down>,<Btn1Up>: DoServerScale() HidePopup()",
++
++ "*popup*button27.label: Text Chat",
++ "*popup*button27.type: toggle",
++ "*popup*button27.translations: #override\\n\
++ <Visible>: SetTextChatState()\\n\
++ <Btn1Down>,<Btn1Up>: toggle() ToggleTextChat() HidePopup()",
++
NULL
};
-@@ -135,6 +236,7 @@
++#if 0
++ "*popup*button14.label: - ZRLE/ZWYRLE",
++ "*popup*button14.type: toggle",
++ "*popup*button14.translations: #override\\n\
++ <Visible>: SetZRLEState()\\n\
++ <Btn1Down>,<Btn1Up>: toggle() ToggleTightZRLE() HidePopup()",
++#endif
++
+
+ /*
+ * vncServerHost and vncServerPort are set either from the command line or
+@@ -135,6 +260,7 @@
*/
AppData appData;
@@ -270,7 +407,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v
static XtResource appDataResourceList[] = {
{"shareDesktop", "ShareDesktop", XtRBool, sizeof(Bool),
-@@ -161,8 +263,17 @@
+@@ -161,8 +287,20 @@
{"encodings", "Encodings", XtRString, sizeof(String),
XtOffsetOf(AppData, encodingsString), XtRImmediate, (XtPointer) 0},
@@ -282,6 +419,9 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v
+ {"useBGR565", "UseBGR565", XtRBool, sizeof(Bool),
+ XtOffsetOf(AppData, useBGR565), XtRImmediate, (XtPointer) False},
+
++ {"useGreyScale", "UseGreyScale", XtRBool, sizeof(Bool),
++ XtOffsetOf(AppData, useGreyScale), XtRImmediate, (XtPointer) False},
++
+ {"yCrop", "yCrop", XtRInt, sizeof(int),
+ XtOffsetOf(AppData, yCrop), XtRImmediate, (XtPointer) 0},
+
@@ -290,7 +430,30 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v
{"nColours", "NColours", XtRInt, sizeof(int),
XtOffsetOf(AppData, nColours), XtRImmediate, (XtPointer) 256},
-@@ -218,14 +329,29 @@
+@@ -179,7 +317,7 @@
+ {"requestedDepth", "RequestedDepth", XtRInt, sizeof(int),
+ XtOffsetOf(AppData, requestedDepth), XtRImmediate, (XtPointer) 0},
+
+- {"useSharedMemory", "UseSharedMemory", XtRBool, sizeof(Bool),
++ {"useShm", "UseShm", XtRBool, sizeof(Bool),
+ XtOffsetOf(AppData, useShm), XtRImmediate, (XtPointer) True},
+
+ {"wmDecorationWidth", "WmDecorationWidth", XtRInt, sizeof(int),
+@@ -206,8 +344,13 @@
+ {"bumpScrollPixels", "BumpScrollPixels", XtRInt, sizeof(int),
+ XtOffsetOf(AppData, bumpScrollPixels), XtRImmediate, (XtPointer) 20},
+
++#if 0
+ {"compressLevel", "CompressionLevel", XtRInt, sizeof(int),
+ XtOffsetOf(AppData, compressLevel), XtRImmediate, (XtPointer) -1},
++#endif
++
++ {"compressLevel", "CompressionLevel", XtRInt, sizeof(int),
++ XtOffsetOf(AppData, compressLevel), XtRImmediate, (XtPointer) 7},
+
+ {"qualityLevel", "QualityLevel", XtRInt, sizeof(int),
+ XtOffsetOf(AppData, qualityLevel), XtRImmediate, (XtPointer) 6},
+@@ -218,14 +361,49 @@
{"useRemoteCursor", "UseRemoteCursor", XtRBool, sizeof(Bool),
XtOffsetOf(AppData, useRemoteCursor), XtRImmediate, (XtPointer) True},
@@ -314,15 +477,35 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v
+ {"grabAll", "GrabAll", XtRBool, sizeof(Bool),
+ XtOffsetOf(AppData, grabAll), XtRImmediate, (XtPointer) False},
+
++#if 0
++ {"useBackingstore", "UseBackingstore", XtRBool, sizeof(Bool),
++ XtOffsetOf(AppData, useBackingstore), XtRImmediate, (XtPointer) True},
++#else
++ {"useBackingstore", "UseBackingstore", XtRBool, sizeof(Bool),
++ XtOffsetOf(AppData, useBackingstore), XtRImmediate, (XtPointer) False},
++#endif
++
+ {"overrideRedir", "OverrideRedir", XtRBool, sizeof(Bool),
+ XtOffsetOf(AppData, overrideRedir), XtRImmediate, (XtPointer) True},
+
++ {"serverInput", "ServerInput", XtRBool, sizeof(Bool),
++ XtOffsetOf(AppData, serverInput), XtRImmediate, (XtPointer) True},
++
++ {"singleWindow", "SingleWindow", XtRBool, sizeof(Bool),
++ XtOffsetOf(AppData, singleWindow), XtRImmediate, (XtPointer) False},
++
++ {"serverScale", "ServerScale", XtRInt, sizeof(int),
++ XtOffsetOf(AppData, serverScale), XtRImmediate, (XtPointer) 1},
++
++ {"chatActive", "ChatActive", XtRBool, sizeof(Bool),
++ XtOffsetOf(AppData, chatActive), XtRImmediate, (XtPointer) False},
++
+ {"popupFix", "PopupFix", XtRBool, sizeof(Bool),
+ XtOffsetOf(AppData, popupFix), XtRImmediate, (XtPointer) False}
};
-@@ -243,7 +369,18 @@
+@@ -243,7 +421,20 @@
{"-passwd", "*passwordFile", XrmoptionSepArg, 0},
{"-user", "*userLogin", XrmoptionSepArg, 0},
{"-encodings", "*encodings", XrmoptionSepArg, 0},
@@ -334,6 +517,8 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v
+ {"-bgr111", "*useBGR233", XrmoptionNoArg, "8"},
+ {"-16bpp", "*useBGR565", XrmoptionNoArg, "True"},
+ {"-bgr565", "*useBGR565", XrmoptionNoArg, "True"},
++ {"-grey", "*useGreyScale", XrmoptionNoArg, "True"},
++ {"-gray", "*useGreyScale", XrmoptionNoArg, "True"},
+ {"-sbwidth", "*sbwidth", XrmoptionSepArg, 0},
+ {"-ycrop", "*yCrop", XrmoptionSepArg, 0},
+ {"-sbwidth", "*sbwidth", XrmoptionSepArg, 0},
@@ -342,7 +527,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v
{"-owncmap", "*forceOwnCmap", XrmoptionNoArg, "True"},
{"-truecolor", "*forceTrueColour", XrmoptionNoArg, "True"},
{"-truecolour", "*forceTrueColour", XrmoptionNoArg, "True"},
-@@ -253,7 +390,14 @@
+@@ -253,7 +444,17 @@
{"-nojpeg", "*enableJPEG", XrmoptionNoArg, "False"},
{"-nocursorshape", "*useRemoteCursor", XrmoptionNoArg, "False"},
{"-x11cursor", "*useX11Cursor", XrmoptionNoArg, "True"},
@@ -354,11 +539,14 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v
+ {"-grabkeyboard", "*grabKeyboard", XrmoptionNoArg, "True"},
+ {"-nograbkeyboard","*grabKeyboard", XrmoptionNoArg, "False"},
+ {"-nooverride", "*overrideRedir", XrmoptionNoArg, "False"},
-+ {"-popupfix", "*popupFix", XrmoptionNoArg, "True"}
++ {"-bs", "*useBackingstore", XrmoptionNoArg, "True"},
++ {"-nobs", "*useBackingstore", XrmoptionNoArg, "False"},
++ {"-popupfix", "*popupFix", XrmoptionNoArg, "True"},
++ {"-noshm", "*useShm", XrmoptionNoArg, "False"}
};
-@@ -277,6 +421,32 @@
+@@ -277,6 +478,41 @@
{"Pause", Pause},
{"RunCommand", RunCommand},
{"Quit", Quit},
@@ -368,6 +556,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v
+ {"Toggle256Colors", Toggle256Colors},
+ {"Toggle64Colors", Toggle64Colors},
+ {"Toggle8Colors", Toggle8Colors},
++ {"ToggleGreyScale", ToggleGreyScale},
+ {"ToggleTightZRLE", ToggleTightZRLE},
+ {"ToggleViewOnly", ToggleViewOnly},
+ {"ToggleJPEG", ToggleJPEG},
@@ -375,12 +564,17 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v
+ {"ToggleCursorAlpha", ToggleCursorAlpha},
+ {"ToggleX11Cursor", ToggleX11Cursor},
+ {"ToggleRawLocal", ToggleRawLocal},
++ {"ToggleServerInput", ToggleServerInput},
++ {"ToggleSingleWindow", ToggleSingleWindow},
++ {"ToggleTextChat", ToggleTextChat},
++ {"DoServerScale", DoServerScale},
+ {"Set8bppState", Set8bppState},
+ {"Set16bppState", Set16bppState},
+ {"SetFullColorState", SetFullColorState},
+ {"Set256ColorsState", Set256ColorsState},
+ {"Set64ColorsState", Set64ColorsState},
+ {"Set8ColorsState", Set8ColorsState},
++ {"SetGreyScaleState", SetGreyScaleState},
+ {"SetZRLEState", SetZRLEState},
+ {"SetNOJPEGState", SetNOJPEGState},
+ {"SetViewOnlyState", SetViewOnlyState},
@@ -388,17 +582,32 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v
+ {"SetCursorAlphaState", SetCursorAlphaState},
+ {"SetX11CursorState", SetX11CursorState},
+ {"SetRawLocalState", SetRawLocalState},
++ {"SetServerInputState", SetServerInputState},
++ {"SetSingleWindowState", SetSingleWindowState},
++ {"SetTextChatState", SetTextChatState},
};
-@@ -332,7 +502,56 @@
+@@ -302,8 +538,8 @@
+ void
+ usage(void)
+ {
+- fprintf(stderr,
+- "TightVNC viewer version 1.3dev7\n"
++ fprintf(stdout,
++ "TightVNC viewer version 1.3dev7 (SSVNC)\n"
+ "\n"
+ "Usage: %s [<OPTIONS>] [<HOST>][:<DISPLAY#>]\n"
+ " %s [<OPTIONS>] [<HOST>][::<PORT#>]\n"
+@@ -332,10 +568,110 @@
" -autopass\n"
"\n"
"Option names may be abbreviated, e.g. -bgr instead of -bgr233.\n"
- "See the manual page for more information."
+ "See the manual page for more information.\n"
+ "\n"
-+ "Enhanced TightVNC viewer options:\n"
++ "\n"
++ "Enhanced TightVNC viewer (SSVNC) options:\n"
+ "\n"
+ " URL http://www.karlrunge.com/x11vnc/enhanced_tightvnc_viewer.html\n"
+ "\n"
@@ -418,6 +627,8 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v
+ " pixels to 32bpp locally.\n"
+ " -bgr565 Same as -16bpp.\n"
+ "\n"
++ " -grey Use a grey scale for the 16- and 8-bpp modes.\n"
++ "\n"
+ " -alpha Use alphablending transparency for local cursors\n"
+ " requires: x11vnc server, both client and server\n"
+ " must be 32bpp and same endianness.\n"
@@ -428,8 +639,10 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v
+ " Use a negative value (e.g. -1) for autodetection.\n"
+ " Autodetection will always take place if the remote\n"
+ " fb height is more than 2 times the width.\n"
-+ " -sbwidth n Scrollbar width, default is very narrow: 2 pixels,\n"
-+ " it is narrow to avoid distraction in -ycrop mode.\n"
++ "\n"
++ " -sbwidth n Scrollbar width for x11vnc -ncache mode (-ycrop),\n"
++ " default is very narrow: 2 pixels, it is narrow to\n"
++ " avoid distraction in -ycrop mode.\n"
+ "\n"
+ " -rawlocal Prefer raw encoding for localhost, default is\n"
+ " no, i.e. assumes you have a SSH tunnel instead.\n"
@@ -442,14 +655,63 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v
+ " -grabkbd Grab the X keyboard when in fullscreen mode,\n"
+ " needed by some window managers. Same as -grabkeyboard.\n"
+ " -grabkbd is the default, use -nograbkbd to disable.\n"
-+#if 0
-+ " -nooverride Do not apply OverrideRedirect in fullscreen mode.\n"
-+#endif
++ "\n"
++ " -bs, -nobs Whether or not to use X server Backingstore for the\n"
++ " main viewer window. The default is to not, mainly\n"
++ " because most Linux, etc, systems X servers disable\n"
++ " *all* Backingstore by default. To re-enable it put\n"
++ "\n"
++ " Option \"Backingstore\"\n"
++ "\n"
++ " in the Device section of /etc/X11/xorg.conf.\n"
++ " In -bs mode with no X server backingstore, whenever an\n"
++ " area of the screen is re-exposed it must go out to the\n"
++ " VNC server to retrieve the pixels. This is too slow.\n"
++ "\n"
++ " In -nobs mode, memory is allocated by the viewer to\n"
++ " provide its own backing of the main viewer window. This\n"
++ " actually makes some activities faster (changes in large\n"
++ " regions) but can appear to \"flash\" too much.\n"
++ "\n"
++ " -noshm Disable use of MIT shared memory extension (not recommended)\n"
++ "\n"
++ " New Popup actions:\n"
++ "\n"
++ " Cursor Shape: ~ -nocursorshape\n"
++ " X11 Cursor: ~ -x11cursor\n"
++ " Cursor Alphablend: ~ -alpha\n"
++ " Disable JPEG: ~ -nojpeg\n"
++ " Prefer raw for localhost ~ -rawlocal\n"
++ " Full Color as many colors as local screen allows.\n"
++ " Grey scale (16 & 8-bpp) ~ -grey, for low colors 16/8bpp modes only.\n"
++ " 16 bit color (BGR565) ~ -16bpp / -bgr565\n"
++ " 8 bit color (BGR233) ~ -bgr233\n"
++ " 256 colors ~ -bgr233 default # of colors.\n"
++ " 64 colors ~ -bgr222 / -use64\n"
++ " 8 colors ~ -bgr111 / -use8\n"
++ "\n"
++ " Disable Remote Input Ultravnc ext. Try to prevent input and\n"
++ " viewing of monitor at physical display.\n"
++ " Single Window Ultravnc ext. Grab and view a single window.\n"
++ " (click on the window you want).\n"
++ " Set 1/n Server Scale Ultravnc ext. Scale desktop by 1/n.\n"
++ " prompt is from the terminal.\n"
++ " Text Chat Ultravnc ext. Do Text Chat, currently\n"
++ " input via the terminal (no window).\n"
++ "\n"
++ " Note: the Ultravnc extensions only apply to servers that support\n"
++ " them. x11vnc/libvncserver supports some of them.\n"
+ "\n"
"\n", programName, programName, programName, programName);
exit(1);
}
-@@ -357,6 +576,17 @@
++#if 0
++ " -nooverride Do not apply OverrideRedirect in fullscreen mode.\n"
++#endif
+
+
+ /*
+@@ -357,6 +693,23 @@
XtGetApplicationResources(toplevel, &appData, appDataResourceList,
XtNumber(appDataResourceList), 0, 0);
@@ -462,12 +724,18 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v
+ if (getenv("VNCVIEWER_GRAB_SERVER")) {
+ appData.grabAll = True;
+ }
++ if (getenv("VNCVIEWER_YCROP")) {
++ int n = atoi(getenv("VNCVIEWER_YCROP"));
++ if (n != 0) {
++ appData.yCrop = n;
++ }
++ }
+
+
/* Add our actions to the actions table so they can be used in widget
resource specs */
-@@ -376,6 +606,10 @@
+@@ -376,6 +729,10 @@
return;
}
@@ -480,7 +748,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v
appData.passwordDialog = True;
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/colour.c vnc_unixsrc/vncviewer/colour.c
--- vnc_unixsrc.orig/vncviewer/colour.c 2002-04-30 09:07:31.000000000 -0400
-+++ vnc_unixsrc/vncviewer/colour.c 2007-02-03 19:56:11.000000000 -0500
++++ vnc_unixsrc/vncviewer/colour.c 2007-02-17 23:57:21.000000000 -0500
@@ -31,6 +31,9 @@
#define BGR233_SIZE 256
unsigned long BGR233ToPixel[BGR233_SIZE];
@@ -580,7 +848,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/colour.c vnc_unixsrc/vncviewe
PrintPixelFormat(&myFormat);
SetupBGR233Map();
-@@ -394,16 +444,29 @@
+@@ -394,16 +444,43 @@
for (r = 0; r < 8; r++) {
for (g = 0; g < 8; g++) {
for (b = 0; b < 4; b++) {
@@ -604,17 +872,32 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/colour.c vnc_unixsrc/vncviewe
for (i = 0; i < cmapSize; i++) {
if (exactBGR233[i] || shared[i]) {
- unsigned long distance
+- unsigned long distance
- = (abs(cmapEntry[i].red - r * 65535 / 7)
- + abs(cmapEntry[i].green - g * 65535 / 7)
- + abs(cmapEntry[i].blue - b * 65535 / 3));
-+ = ( abs(cmapEntry[i].red - r * 65535 / rm)
-+ + abs(cmapEntry[i].green - g * 65535 / gm)
-+ + abs(cmapEntry[i].blue - b * 65535 / bm));
++ unsigned long distance;
++ int r1, g1, b1;
++ if (appData.useGreyScale) {
++ int ave;
++ ave = (r + g + 2*b)/3;
++ r1 = ave;
++ g1 = ave;
++ b1 = ave/2;
++ } else {
++ r1 = r;
++ g1 = g;
++ b1 = b;
++ }
++ distance
++ = ( abs(cmapEntry[i].red - r1 * 65535 / rm)
++ + abs(cmapEntry[i].green - g1 * 65535 / gm)
++ + abs(cmapEntry[i].blue - b1 * 65535 / bm));
++
if (distance < minDistance) {
minDistance = distance;
-@@ -412,7 +475,7 @@
+@@ -412,7 +489,7 @@
}
}
@@ -623,7 +906,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/colour.c vnc_unixsrc/vncviewe
if (shared[nearestPixel] && !usedAsNearest[nearestPixel])
nSharedUsed++;
usedAsNearest[nearestPixel] = True;
-@@ -433,6 +496,38 @@
+@@ -433,6 +510,53 @@
}
}
@@ -649,6 +932,21 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/colour.c vnc_unixsrc/vncviewe
+ b2 = (255 * b) / bm;
+
+ pixel = (r2 << 16) | (g2 << 8) | (b2 << 0);
++ if (appData.useGreyScale) {
++ int ave;
++ int r1, g1, b1;
++ ave = (2*r + g + 2*b)/3;
++ r1 = ave/2;
++ g1 = ave;
++ b1 = ave/2;
++
++ r2 = (255 * r1) / rm;
++ g2 = (255 * g1) / gm;
++ b2 = (255 * b1) / bm;
++
++ pixel = (r2 << 16) | (g2 << 8) | (b2 << 0);
++ }
++
+ idx = (b<<bs) | (g<<gs) | (r<<rs);
+ if (0) fprintf(stderr, "cnt: %5d idx: %5d pixel: 0x%08x\n", cnt, idx, pixel);
+ BGR565ToPixel[idx] = pixel;
@@ -662,7 +960,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/colour.c vnc_unixsrc/vncviewe
/*
* AllocateExactBGR233Colours() attempts to allocate each of the colours in the
-@@ -484,8 +579,13 @@
+@@ -484,8 +608,13 @@
ri = rn;
for (gi = 0; gi < gn; gi++) {
for (bi = 0; bi < bn; bi++) {
@@ -678,7 +976,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/colour.c vnc_unixsrc/vncviewe
}
}
rn++;
-@@ -496,8 +596,13 @@
+@@ -496,8 +625,13 @@
gi = gn;
for (ri = 0; ri < rn; ri++) {
for (bi = 0; bi < bn; bi++) {
@@ -694,7 +992,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/colour.c vnc_unixsrc/vncviewe
}
}
gn++;
-@@ -507,8 +612,13 @@
+@@ -507,8 +641,13 @@
bi = bn;
for (ri = 0; ri < rn; ri++) {
for (gi = 0; gi < gn; gi++) {
@@ -710,7 +1008,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/colour.c vnc_unixsrc/vncviewe
}
}
bn++;
-@@ -529,18 +639,29 @@
+@@ -529,18 +668,36 @@
AllocateBGR233Colour(int r, int g, int b)
{
XColor c;
@@ -732,9 +1030,16 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/colour.c vnc_unixsrc/vncviewe
+ bm = 1; gm = 1; rm = 1;
+ }
+
-+ c.red = r * 65535 / rm;
-+ c.green = g * 65535 / gm;
-+ c.blue = b * 65535 / bm;
++ c.red = r * 65535 / rm;
++ c.green = g * 65535 / gm;
++ c.blue = b * 65535 / bm;
++ if (appData.useGreyScale) {
++ int ave;
++ ave = (c.red + c.green + c.blue)/3;
++ c.red = ave;
++ c.green = ave;
++ c.blue = ave;
++ }
if (!XAllocColor(dpy, cmap, &c))
return False;
@@ -746,8 +1051,27 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/colour.c vnc_unixsrc/vncviewe
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/corre.c vnc_unixsrc/vncviewer/corre.c
--- vnc_unixsrc.orig/vncviewer/corre.c 2000-06-11 08:00:53.000000000 -0400
-+++ vnc_unixsrc/vncviewer/corre.c 2007-02-03 20:48:52.000000000 -0500
-@@ -50,8 +50,12 @@
++++ vnc_unixsrc/vncviewer/corre.c 2007-02-17 22:50:15.000000000 -0500
+@@ -29,6 +29,18 @@
+ #define HandleCoRREBPP CONCAT2E(HandleCoRRE,BPP)
+ #define CARDBPP CONCAT2E(CARD,BPP)
+
++#define FillRectangle(x, y, w, h, color) \
++ { \
++ XGCValues _gcv; \
++ _gcv.foreground = color; \
++ if (!appData.useBackingstore) { \
++ FillScreen(x, y, w, h, _gcv.foreground); \
++ } else { \
++ XChangeGC(dpy, gc, GCForeground, &_gcv); \
++ XFillRectangle(dpy, desktopWin, gc, x, y, w, h); \
++ } \
++ }
++
+ static Bool
+ HandleCoRREBPP (int rx, int ry, int rw, int rh)
+ {
+@@ -50,11 +62,19 @@
#if (BPP == 8)
gcv.foreground = (appData.useBGR233 ? BGR233ToPixel[pix] : pix);
#else
@@ -758,9 +1082,16 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/corre.c vnc_unixsrc/vncviewer
#endif
+#endif
++#if 0
XChangeGC(dpy, gc, GCForeground, &gcv);
XFillRectangle(dpy, desktopWin, gc, rx, ry, rw, rh);
-@@ -72,8 +76,12 @@
++#else
++ FillRectangle(rx, ry, rw, rh, gcv.foreground);
++#endif
+
+ if (!ReadFromRFBServer(buffer, hdr.nSubrects * (4 + (BPP / 8))))
+ return False;
+@@ -72,12 +92,22 @@
#if (BPP == 8)
gcv.foreground = (appData.useBGR233 ? BGR233ToPixel[pix] : pix);
#else
@@ -771,11 +1102,21 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/corre.c vnc_unixsrc/vncviewer
#endif
+#endif
++#if 0
XChangeGC(dpy, gc, GCForeground, &gcv);
XFillRectangle(dpy, desktopWin, gc, rx + x, ry + y, w, h);
++#else
++ FillRectangle(rx + x, ry + y, w, h, gcv.foreground);
++#endif
+ }
+
+ return True;
+ }
++
++#undef FillRectangle
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/cursor.c vnc_unixsrc/vncviewer/cursor.c
--- vnc_unixsrc.orig/vncviewer/cursor.c 2003-01-15 04:46:52.000000000 -0500
-+++ vnc_unixsrc/vncviewer/cursor.c 2007-02-03 18:09:18.000000000 -0500
++++ vnc_unixsrc/vncviewer/cursor.c 2007-02-08 18:46:24.000000000 -0500
@@ -39,7 +39,7 @@
static Bool prevSoftCursorSet = False;
@@ -796,31 +1137,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/cursor.c vnc_unixsrc/vncviewe
/* Copied from Xvnc/lib/font/util/utilbitmap.c */
static unsigned char _reverse_byte[0x100] = {
-@@ -103,6 +103,7 @@
- Pixmap source, mask;
- Cursor cursor;
- int i;
-+if (0) fprintf(stderr, "In HandleXCursor\n");
-
- bytesPerRow = (width + 7) / 8;
- bytesData = bytesPerRow * height;
-@@ -149,6 +150,7 @@
- XFreePixmap(dpy, mask);
- free(buf);
-
-+if (0) fprintf(stderr, "HandleXCursor calls XDefineCursor: 0x%x\n", cursor);
- XDefineCursor(dpy, desktopWin, cursor);
- FreeX11Cursor();
- prevXCursor = cursor;
-@@ -175,6 +177,7 @@
- char *buf;
- CARD8 *ptr;
- int x, y, b;
-+if (0) fprintf(stderr, "In HandleCursorShape\n");
-
- bytesPerPixel = myFormat.bitsPerPixel / 8;
- bytesPerRow = (width + 7) / 8;
-@@ -195,12 +198,14 @@
+@@ -195,6 +195,7 @@
buf = malloc(bytesMaskData);
if (buf == NULL) {
free(rcSource);
@@ -828,14 +1145,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/cursor.c vnc_unixsrc/vncviewe
return False;
}
- /* Read and decode cursor pixel data, depending on the encoding type. */
-
- if (enc == rfbEncodingXCursor) {
-+if (0) fprintf(stderr, "HandleCursorShape: rfbEncodingXCursor\n");
- if (appData.useX11Cursor) {
- HandleXCursor(xhot, yhot, width, height);
- return True;
-@@ -209,6 +214,7 @@
+@@ -209,6 +210,7 @@
/* Read and convert background and foreground colors. */
if (!ReadFromRFBServer((char *)&rgb, sz_rfbXCursorColors)) {
free(rcSource);
@@ -843,7 +1153,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/cursor.c vnc_unixsrc/vncviewe
free(buf);
return False;
}
-@@ -218,6 +224,7 @@
+@@ -218,6 +220,7 @@
/* Read 1bpp pixel data into a temporary buffer. */
if (!ReadFromRFBServer(buf, bytesMaskData)) {
free(rcSource);
@@ -851,11 +1161,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/cursor.c vnc_unixsrc/vncviewe
free(buf);
return False;
}
-@@ -254,9 +261,11 @@
- }
-
- } else { /* enc == rfbEncodingRichCursor */
-+if (0) fprintf(stderr, "HandleCursorShape: rfbEncodingRichCursor\n");
+@@ -257,6 +260,7 @@
if (!ReadFromRFBServer((char *)rcSource, width * height * bytesPerPixel)) {
free(rcSource);
@@ -863,7 +1169,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/cursor.c vnc_unixsrc/vncviewe
free(buf);
return False;
}
-@@ -267,6 +276,7 @@
+@@ -267,6 +271,7 @@
if (!ReadFromRFBServer(buf, bytesMaskData)) {
free(rcSource);
@@ -871,7 +1177,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/cursor.c vnc_unixsrc/vncviewe
free(buf);
return False;
}
-@@ -274,6 +284,7 @@
+@@ -274,6 +279,7 @@
rcMask = malloc(width * height);
if (rcMask == NULL) {
free(rcSource);
@@ -879,15 +1185,87 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/cursor.c vnc_unixsrc/vncviewe
free(buf);
return False;
}
-@@ -301,6 +312,7 @@
- rcWidth = width;
- rcHeight = height;
+@@ -429,41 +435,51 @@
+ rcLockY + rcLockHeight > rcCursorY - rcHotY);
+ }
+
++extern XImage *image;
++
+ static void SoftCursorCopyArea(int oper)
+ {
+- int x, y, w, h;
++ int x, y, w, h;
-+if (0) fprintf(stderr, "HandleCursorShape: SoftCursorCopyArea\n");
- SoftCursorCopyArea(OPER_SAVE);
- SoftCursorDraw();
+- x = rcCursorX - rcHotX;
+- y = rcCursorY - rcHotY;
+- if (x >= si.framebufferWidth || y >= si.framebufferHeight)
+- return;
++ x = rcCursorX - rcHotX;
++ y = rcCursorY - rcHotY;
++ if (x >= si.framebufferWidth || y >= si.framebufferHeight) {
++ return;
++ }
-@@ -472,6 +484,139 @@
+- w = rcWidth;
+- h = rcHeight;
+- if (x < 0) {
+- w += x;
+- x = 0;
+- } else if (x + w > si.framebufferWidth) {
+- w = si.framebufferWidth - x;
+- }
+- if (y < 0) {
+- h += y;
+- y = 0;
+- } else if (y + h > si.framebufferHeight) {
+- h = si.framebufferHeight - y;
+- }
++ w = rcWidth;
++ h = rcHeight;
++ if (x < 0) {
++ w += x;
++ x = 0;
++ } else if (x + w > si.framebufferWidth) {
++ w = si.framebufferWidth - x;
++ }
++ if (y < 0) {
++ h += y;
++ y = 0;
++ } else if (y + h > si.framebufferHeight) {
++ h = si.framebufferHeight - y;
++ }
+
+- if (oper == OPER_SAVE) {
+- /* Save screen area in memory. */
++ if (oper == OPER_SAVE) {
++ /* Save screen area in memory. */
++//fprintf(stderr, "OPER_SAVE\n");
+ #ifdef MITSHM
+- if (appData.useShm)
+- XSync(dpy, False);
++ if (appData.useShm) {
++ XSync(dpy, False);
++ } else
+ #endif
+- XCopyArea(dpy, desktopWin, rcSavedArea, gc, x, y, w, h, 0, 0);
+- } else {
+- /* Restore screen area. */
+- XCopyArea(dpy, rcSavedArea, desktopWin, gc, 0, 0, w, h, x, y);
+- }
++ {
++ XSync(dpy, False);
++ }
++ XCopyArea(dpy, desktopWin, rcSavedArea, gc, x, y, w, h, 0, 0);
++ } else {
++//fprintf(stderr, "OPER_RESTORE\n");
++ /* Restore screen area. */
++ XCopyArea(dpy, rcSavedArea, desktopWin, gc, 0, 0, w, h, x, y);
++ XGetSubImage(dpy, rcSavedArea, 0, 0, w, h, AllPlanes, ZPixmap, image, x, y);
++ }
+ }
+
+ static void SoftCursorDraw(void)
+@@ -472,6 +488,139 @@
int offset, bytesPerPixel;
char *pos;
@@ -1027,42 +1405,70 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/cursor.c vnc_unixsrc/vncviewe
bytesPerPixel = myFormat.bitsPerPixel / 8;
/* FIXME: Speed optimization is possible. */
-@@ -492,19 +637,20 @@
+@@ -492,23 +641,23 @@
}
}
-static void FreeSoftCursor(void)
+void FreeSoftCursor(void)
{
- if (prevSoftCursorSet) {
- SoftCursorCopyArea(OPER_RESTORE);
- XFreePixmap(dpy, rcSavedArea);
- free(rcSource);
-+ rcSource = NULL;
- free(rcMask);
- prevSoftCursorSet = False;
- }
+- if (prevSoftCursorSet) {
+- SoftCursorCopyArea(OPER_RESTORE);
+- XFreePixmap(dpy, rcSavedArea);
+- free(rcSource);
+- free(rcMask);
+- prevSoftCursorSet = False;
+- }
++ if (prevSoftCursorSet) {
++ SoftCursorCopyArea(OPER_RESTORE);
++ XFreePixmap(dpy, rcSavedArea);
++ free(rcSource);
++ rcSource = NULL;
++ free(rcMask);
++ prevSoftCursorSet = False;
++ }
}
-static void FreeX11Cursor()
+void FreeX11Cursor()
{
- if (prevXCursorSet) {
- XFreeCursor(dpy, prevXCursor);
+- if (prevXCursorSet) {
+- XFreeCursor(dpy, prevXCursor);
+- prevXCursorSet = False;
+- }
++ if (prevXCursorSet) {
++ XFreeCursor(dpy, prevXCursor);
++ prevXCursorSet = False;
++ }
+ }
+-
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncviewer/desktop.c
--- vnc_unixsrc.orig/vncviewer/desktop.c 2004-05-28 13:29:29.000000000 -0400
-+++ vnc_unixsrc/vncviewer/desktop.c 2007-02-04 18:34:32.000000000 -0500
-@@ -31,7 +31,7 @@
++++ vnc_unixsrc/vncviewer/desktop.c 2007-02-18 17:07:21.000000000 -0500
+@@ -28,21 +28,28 @@
+ #include <X11/extensions/XShm.h>
+ #endif
+
++#include <X11/cursorfont.h>
++
GC gc;
GC srcGC, dstGC; /* used for debugging copyrect */
Window desktopWin;
-Cursor dotCursor;
+Cursor dotCursor = None;
++Cursor bogoCursor = None;
Widget form, viewport, desktop;
static Bool modifierPressed[256];
-@@ -43,6 +43,8 @@
+
+-static XImage *image = NULL;
++XImage *image = NULL;
++XImage *image_ycrop = NULL;
+
+ static Cursor CreateDotCursor();
++static Cursor CreateBogoCursor();
+ static void CopyBGR233ToScreen(CARD8 *buf, int x, int y, int width,int height);
static void HandleBasicDesktopEvent(Widget w, XtPointer ptr, XEvent *ev,
Boolean *cont);
@@ -1071,32 +1477,47 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview
static XtResource desktopBackingStoreResources[] = {
{
XtNbackingStore, XtCBackingStore, XtRBackingStore, sizeof(int), 0,
-@@ -50,6 +52,60 @@
+@@ -50,6 +57,86 @@
},
};
+void create_image() {
-+ image = NULL;
++ image = NULL;
++ image_ycrop = NULL;
++
++//fprintf(stderr, "useShm: %d\n", appData.useShm);
+
+#ifdef MITSHM
-+ if (appData.useShm) {
-+ image = CreateShmImage();
-+ if (!image)
-+ appData.useShm = False;
-+ }
++ if (appData.useShm) {
++ image = CreateShmImage(0);
++ if (!image) {
++ if (appData.yCrop > 0) {
++ image_ycrop = CreateShmImage(1);
++ if (!image_ycrop) {
++ appData.useShm = False;
++ } else {
++ fprintf(stderr, "created smaller image_ycrop "
++ "shm image\n");
++ }
++ } else {
++ appData.useShm = False;
++ }
++ }
++ }
+#endif
+
-+ if (!image) {
-+ image = XCreateImage(dpy, vis, visdepth, ZPixmap, 0, NULL,
-+ si.framebufferWidth, si.framebufferHeight,
-+ BitmapPad(dpy), 0);
++ if (!image) {
++ image = XCreateImage(dpy, vis, visdepth, ZPixmap, 0, NULL,
++ si.framebufferWidth, si.framebufferHeight, BitmapPad(dpy), 0);
+
-+ image->data = malloc(image->bytes_per_line * image->height);
-+ if (!image->data) {
-+ fprintf(stderr,"malloc failed\n");
-+ exit(1);
-+ }
-+ }
++ image->data = malloc(image->bytes_per_line * image->height);
++ if (!image->data) {
++ fprintf(stderr,"malloc failed\n");
++ exit(1);
++ } else {
++ fprintf(stderr, "created non-shm image\n");
++ }
++ }
+}
+
+int old_width = 0;
@@ -1129,14 +1550,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview
+ }
+}
+
-
- /*
- * DesktopInitBeforeRealization creates the "desktop" widget and the viewport
-@@ -79,32 +135,102 @@
- XtAddEventHandler(desktop, LeaveWindowMask|ExposureMask,
- True, HandleBasicDesktopEvent, NULL);
-
-+
++void check_tall(void) {
+ if (! appData.yCrop) {
+ int w = si.framebufferWidth;
+ int h = si.framebufferHeight;
@@ -1146,25 +1560,80 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview
+ appData.yCrop = -1;
+ }
+ }
++}
+
+ /*
+ * DesktopInitBeforeRealization creates the "desktop" widget and the viewport
+@@ -59,53 +146,158 @@
+ void
+ DesktopInitBeforeRealization()
+ {
+- int i;
++ int i;
+
+- form = XtVaCreateManagedWidget("form", formWidgetClass, toplevel,
+- XtNborderWidth, 0,
+- XtNdefaultDistance, 0, NULL);
++ form = XtVaCreateManagedWidget("form", formWidgetClass, toplevel,
++ XtNborderWidth, 0, XtNdefaultDistance, 0, NULL);
+
+- viewport = XtVaCreateManagedWidget("viewport", viewportWidgetClass, form,
+- XtNborderWidth, 0,
+- NULL);
++ viewport = XtVaCreateManagedWidget("viewport", viewportWidgetClass, form,
++ XtNborderWidth, 0, NULL);
+
+- desktop = XtVaCreateManagedWidget("desktop", coreWidgetClass, viewport,
+- XtNborderWidth, 0,
+- NULL);
++ desktop = XtVaCreateManagedWidget("desktop", coreWidgetClass, viewport,
++ XtNborderWidth, 0, NULL);
++
++ XtVaSetValues(desktop, XtNwidth, si.framebufferWidth,
++ XtNheight, si.framebufferHeight, NULL);
++
++ XtAddEventHandler(desktop, LeaveWindowMask|ExposureMask,
++ True, HandleBasicDesktopEvent, NULL);
++
++
++ check_tall();
++
+ if (appData.yCrop) {
++ int wm, hm;
+ if (appData.yCrop < 0) {
+ appData.yCrop = guessCrop();
+ fprintf(stderr, "Set -ycrop to: %d\n", appData.yCrop);
+ }
-+ XtVaSetValues(toplevel, XtNmaxHeight, appData.yCrop, NULL);
-+ XtVaSetValues(form, XtNmaxHeight, appData.yCrop, NULL);
++ hm = appData.yCrop;
++ if (0 && appData.sbWidth <= 6 && appData.sbWidth > 0) {
++ hm += appData.sbWidth;
++ }
++ XtVaSetValues(toplevel, XtNmaxHeight, hm, NULL);
++ XtVaSetValues(form, XtNmaxHeight, hm, NULL);
+ XtVaSetValues(viewport, XtNforceBars, False, NULL);
+ }
+ old_width = si.framebufferWidth;
+ old_height = si.framebufferHeight;
-+
- for (i = 0; i < 256; i++)
- modifierPressed[i] = False;
-- image = NULL;
-+ create_image();
+- XtVaSetValues(desktop, XtNwidth, si.framebufferWidth,
+- XtNheight, si.framebufferHeight, NULL);
++ for (i = 0; i < 256; i++) {
++ modifierPressed[i] = False;
++ }
+
+- XtAddEventHandler(desktop, LeaveWindowMask|ExposureMask,
+- True, HandleBasicDesktopEvent, NULL);
++ create_image();
+}
+- for (i = 0; i < 256; i++)
+- modifierPressed[i] = False;
++static Widget scrollbar_y = NULL;
+
+- image = NULL;
++static int xsst = 2;
++#include <X11/Xaw/Scrollbar.h>
+
-#ifdef MITSHM
- if (appData.useShm) {
- image = CreateShmImage();
@@ -1172,15 +1641,12 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview
- appData.useShm = False;
- }
-#endif
-+static Widget scrollbar_y = NULL;
-
+-
- if (!image) {
- image = XCreateImage(dpy, vis, visdepth, ZPixmap, 0, NULL,
- si.framebufferWidth, si.framebufferHeight,
- BitmapPad(dpy), 0);
-+static int xsst = 2;
-+#include <X11/Xaw/Scrollbar.h>
-
+-
- image->data = malloc(image->bytes_per_line * image->height);
- if (!image->data) {
- fprintf(stderr,"malloc failed\n");
@@ -1201,7 +1667,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview
+ float t = 0.0;
+ XtVaSetValues(w, XtNtopOfThumb, &t, NULL);
+ }
- }
++}
+static XtCallbackProc Jumped(Widget w, XtPointer closure, XtPointer call_data) {
+ float top = *((float *) call_data);
+ Position x, y;
@@ -1219,44 +1685,152 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview
+ XtVaSetValues(w, XtNtopOfThumb, *(XtArgVal*)&t, XtNshown, *(XtArgVal*)&s, NULL);
+ }
+ }
-+}
-+
+ }
+
+
++extern double dnow(void);
+
+void check_things() {
-+ Widget w;
-+ static time_t last = 0;
+ static int installed_callback = 0;
++ static int first = 1;
++ static double last_scrollbar = 0.0;
++ int w = si.framebufferWidth;
++ int h = si.framebufferHeight;
++ double now = dnow();
++ static double last = 0;
++
++ if (first) {
++ first = 0;
++ SendFramebufferUpdateRequest(0, 0, si.framebufferWidth, si.framebufferHeight, False);
++ }
++ if (appData.yCrop > 0 && appData.yCrop < dpyHeight && h > 2*w && now > last_scrollbar + 0.25) {
++ Widget wv, wh, wc;
++ Position x0, y0;
++ Position x1, y1;
++ Dimension w0, h0, b0;
++ Dimension w1, h1, b1;
++ Dimension w2, h2, b2;
++
++ wc = XtNameToWidget(viewport, "clip");
++ wv = XtNameToWidget(viewport, "vertical");
++ wh = XtNameToWidget(viewport, "horizontal");
++ if (wc && wv && wh) {
++ int doit = 1;
++ int sb = appData.sbWidth;
++ XtVaGetValues(wv, XtNwidth, &w0, XtNheight, &h0, XtNborderWidth, &b0, XtNx, &x0, XtNy, &y0, NULL);
++ XtVaGetValues(wh, XtNwidth, &w1, XtNheight, &h1, XtNborderWidth, &b1, XtNx, &x1, XtNy, &y1, NULL);
++ XtVaGetValues(wc, XtNwidth, &w2, XtNheight, &h2, XtNborderWidth, &b2, NULL);
++ if (!sb) {
++ sb = 2;
++ }
++ if (w0 != sb || h1 != sb) {
++ fprintf(stderr, "Very tall (-ncache) fb, setting scrollbar thickness to: %d pixels\n", sb);
++
++ XtUnmanageChild(wv);
++ XtUnmanageChild(wh);
++ XtUnmanageChild(wc);
++
++ XtVaSetValues(wv, XtNwidth, sb, XtNx, x0 + (w0 - sb), NULL);
++ XtVaSetValues(wh, XtNheight, sb, XtNy, y1 + (h1 - sb), NULL);
++ w2 = w2 + (w0 - sb);
++ h2 = h2 + (h1 - sb);
++ if (w2 > 10 && h2 > 10) {
++ XtVaSetValues(wc, XtNwidth, w2, XtNheight, h2, NULL);
++ }
++
++ XtManageChild(wv);
++ XtManageChild(wh);
++ XtManageChild(wc);
++ }
++ }
++ last_scrollbar = dnow();
++ }
+
-+ if (time(NULL) <= last + 1) {
++ if (now <= last + 1.0) {
+ return;
+ }
+
+ dpyWidth = WidthOfScreen(DefaultScreenOfDisplay(dpy));
+ dpyHeight = HeightOfScreen(DefaultScreenOfDisplay(dpy));
-
-+ if (!installed_callback) {
-+ if (appData.yCrop > 0) {
-+#if 0
-+ w = XtNameToWidget(viewport, "vertical");
-+ if (w != NULL) {
-+ fprintf(stderr, "got scrollbar\n");
-+ XtAddCallback(w, XtNjumpProc, Jumped, NULL);
-+ XtAddCallback(w, XtNscrollProc, Scrolled, NULL);
-+ scrollbar_y = w;
-+ installed_callback = 1;
-+ }
-+#endif
-+ }
-+ }
-+ last = time(NULL);
++
++ last = dnow();
+}
-
++
/*
* DesktopInitAfterRealization does things which require the X windows to
-@@ -144,6 +270,24 @@
- XChangeWindowAttributes(dpy, desktopWin, valuemask, &attr);
- }
+ * exist. It creates some GCs and sets the dot cursor.
+@@ -114,34 +306,100 @@
+ void
+ DesktopInitAfterRealization()
+ {
+- XGCValues gcv;
+- XSetWindowAttributes attr;
+- unsigned long valuemask;
+-
+- desktopWin = XtWindow(desktop);
+-
+- gc = XCreateGC(dpy,desktopWin,0,NULL);
+-
+- gcv.function = GXxor;
+- gcv.foreground = 0x0f0f0f0f;
+- srcGC = XCreateGC(dpy,desktopWin,GCFunction|GCForeground,&gcv);
+- gcv.foreground = 0xf0f0f0f0;
+- dstGC = XCreateGC(dpy,desktopWin,GCFunction|GCForeground,&gcv);
+-
+- XtAddConverter(XtRString, XtRBackingStore, XmuCvtStringToBackingStore,
+- NULL, 0);
+-
+- XtVaGetApplicationResources(desktop, (XtPointer)&attr.backing_store,
+- desktopBackingStoreResources, 1, NULL);
+- valuemask = CWBackingStore;
+-
+- if (!appData.useX11Cursor) {
+- dotCursor = CreateDotCursor();
+- attr.cursor = dotCursor;
+- valuemask |= CWCursor;
+- }
++ XGCValues gcv;
++ XSetWindowAttributes attr;
++ XWindowAttributes gattr;
++ unsigned long valuemask = 0;
++
++ desktopWin = XtWindow(desktop);
++
++ gc = XCreateGC(dpy,desktopWin,0,NULL);
++
++ gcv.function = GXxor;
++ gcv.foreground = 0x0f0f0f0f;
++ srcGC = XCreateGC(dpy,desktopWin,GCFunction|GCForeground,&gcv);
++ gcv.foreground = 0xf0f0f0f0;
++ dstGC = XCreateGC(dpy,desktopWin,GCFunction|GCForeground,&gcv);
++
++ XtAddConverter(XtRString, XtRBackingStore, XmuCvtStringToBackingStore,
++ NULL, 0);
++
++ if (appData.useBackingstore) {
++ XtVaGetApplicationResources(desktop, (XtPointer)&attr.backing_store,
++ desktopBackingStoreResources, 1, NULL);
++ valuemask |= CWBackingStore;
++ } else {
++ attr.background_pixel = BlackPixel(dpy, DefaultScreen(dpy));
++ valuemask |= CWBackPixel;
++ }
++
++ if (!appData.useX11Cursor) {
++ dotCursor = CreateDotCursor();
++ attr.cursor = dotCursor;
++ valuemask |= CWCursor;
++ }
++ bogoCursor = XCreateFontCursor(dpy, XC_bogosity);
+- XChangeWindowAttributes(dpy, desktopWin, valuemask, &attr);
++ XChangeWindowAttributes(dpy, desktopWin, valuemask, &attr);
++ if (XGetWindowAttributes(dpy, desktopWin, &gattr)) {
++ fprintf(stderr, "desktopWin backingstore: %d save_under: %d\n", gattr.backing_store, gattr.save_under);
++ }
++ fprintf(stderr, "\n");
++}
++
+extern void FreeX11Cursor(void);
+extern void FreeSoftCursor(void);
+
@@ -1274,111 +1848,469 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview
+ FreeSoftCursor();
+}
+
-+
++void put_image(int src_x, int src_y, int dst_x, int dst_y, int width,
++ int height) {
++
++#ifdef MITSHM
++ if (appData.useShm) {
++ if (image_ycrop == NULL) {
++//fprintf(stderr, "shm not image_ycrop\n");
++ XShmPutImage(dpy, desktopWin, gc, image, src_x, src_y,
++ dst_x, dst_y, width, height, False);
++ } else if ((width < 32 && height < 32) || height > appData.yCrop) {
++//fprintf(stderr, "non-shmB image %d %d %d %d %d %d\n", src_x, src_y, dst_x, dst_y, width, height);
++ XPutImage(dpy, desktopWin, gc, image, src_x, src_y,
++ dst_x, dst_y, width, height);
++ } else {
++ char *src, *dst;
++ int Bpp = image->bits_per_pixel / 8;
++ int Bpl = image->bytes_per_line, h;
++ int Bpl2 = image_ycrop->bytes_per_line;
++ src = image->data + src_y * Bpl + src_x * Bpp;
++ dst = image_ycrop->data;
++ for (h = 0; h < height; h++) {
++ memcpy(dst, src, width * Bpp);
++ src += Bpl;
++ dst += Bpl2;
++ }
++//fprintf(stderr, "shm image_ycrop %d %d %d %d %d %d\n", 0, 0, dst_x, dst_y, width, height);
++ XShmPutImage(dpy, desktopWin, gc, image_ycrop, 0, 0,
++ dst_x, dst_y, width, height, False);
++ }
++ } else
++#endif
++ {
++//fprintf(stderr, "non-shmA image %d %d %d %d %d %d\n", src_x, src_y, dst_x, dst_y, width, height);
++ XPutImage(dpy, desktopWin, gc, image, src_x, src_y,
++ dst_x, dst_y, width, height);
++ }
+ }
- /*
- * HandleBasicDesktopEvent - deal with expose and leave events.
-@@ -185,6 +329,8 @@
- }
- break;
+
+@@ -152,39 +410,53 @@
+ static void
+ HandleBasicDesktopEvent(Widget w, XtPointer ptr, XEvent *ev, Boolean *cont)
+ {
+- int i;
++ int i, x, y, width, height;
+
+- switch (ev->type) {
+
++ switch (ev->type) {
+ case Expose:
+ case GraphicsExpose:
+ /* sometimes due to scrollbars being added/removed we get an expose outside
+ the actual desktop area. Make sure we don't pass it on to the RFB
+ server. */
++ x = ev->xexpose.x;
++ y = ev->xexpose.y;
++ width = ev->xexpose.width;
++ height = ev->xexpose.height;
++
++//fprintf(stderr, "Expose: %dx%d+%d+%d\n", width, height, x, y);
++ if (x + width > si.framebufferWidth) {
++ width = si.framebufferWidth - x;
++ if (width <= 0) {
++ break;
++ }
++ }
+
+- if (ev->xexpose.x + ev->xexpose.width > si.framebufferWidth) {
+- ev->xexpose.width = si.framebufferWidth - ev->xexpose.x;
+- if (ev->xexpose.width <= 0) break;
+- }
+-
+- if (ev->xexpose.y + ev->xexpose.height > si.framebufferHeight) {
+- ev->xexpose.height = si.framebufferHeight - ev->xexpose.y;
+- if (ev->xexpose.height <= 0) break;
+- }
++ if (y + height > si.framebufferHeight) {
++ height = si.framebufferHeight - y;
++ if (height <= 0) {
++ break;
++ }
++ }
+
+- SendFramebufferUpdateRequest(ev->xexpose.x, ev->xexpose.y,
+- ev->xexpose.width, ev->xexpose.height, False);
+- break;
++ if (appData.useBackingstore) {
++ SendFramebufferUpdateRequest(x, y, width, height, False);
++ } else {
++ put_image(x, y, x, y, width, height);
++ XSync(dpy, False);
++ }
++ break;
+
+ case LeaveNotify:
+- for (i = 0; i < 256; i++) {
+- if (modifierPressed[i]) {
+- SendKeyEvent(XKeycodeToKeysym(dpy, i, 0), False);
+- modifierPressed[i] = False;
+- }
+- }
+- break;
++ for (i = 0; i < 256; i++) {
++ if (modifierPressed[i]) {
++ SendKeyEvent(XKeycodeToKeysym(dpy, i, 0), False);
++ modifierPressed[i] = False;
++ }
++ }
++ break;
}
-+
+ check_things();
}
-@@ -330,7 +476,7 @@
+@@ -201,6 +473,9 @@
+ * button2 down, 3 for both, etc).
*/
- static Cursor
--CreateDotCursor()
-+CreateDotCursorOrig()
++extern Bool selectingSingleWindow;
++extern Cursor dotCursor;
++
+ void
+ SendRFBEvent(Widget w, XEvent *ev, String *params, Cardinal *num_params)
{
- Cursor cursor;
- Pixmap src, msk;
-@@ -352,6 +498,29 @@
- }
+@@ -215,6 +490,13 @@
+ if (appData.viewOnly) return;
-+static Cursor
-+CreateDotCursor()
++ if (selectingSingleWindow && ev->type == ButtonPress) {
++ selectingSingleWindow = False;
++ SendSingleWindow(ev->xbutton.x, ev->xbutton.y);
++ XDefineCursor(dpy, desktopWin, dotCursor);
++ return;
++ }
++
+ if (*num_params != 0) {
+ if (strncasecmp(params[0],"key",3) == 0) {
+ if (*num_params != 2) {
+@@ -332,23 +614,99 @@
+ static Cursor
+ CreateDotCursor()
+ {
+- Cursor cursor;
+- Pixmap src, msk;
+- static char srcBits[] = { 0, 14,14,14, 0 };
+- static char mskBits[] = { 14,31,31,31,14 };
+- XColor fg, bg;
+-
+- src = XCreateBitmapFromData(dpy, DefaultRootWindow(dpy), srcBits, 5, 5);
+- msk = XCreateBitmapFromData(dpy, DefaultRootWindow(dpy), mskBits, 5, 5);
+- XAllocNamedColor(dpy, DefaultColormap(dpy,DefaultScreen(dpy)), "black",
+- &fg, &fg);
+- XAllocNamedColor(dpy, DefaultColormap(dpy,DefaultScreen(dpy)), "white",
+- &bg, &bg);
+- cursor = XCreatePixmapCursor(dpy, src, msk, &fg, &bg, 2, 2);
+- XFreePixmap(dpy, src);
+- XFreePixmap(dpy, msk);
++ Cursor cursor;
++ Pixmap src, msk;
++ static char srcBits[] = { 0, 14, 0 };
++ static char mskBits[] = { 14,31,14 };
++ XColor fg, bg;
++
++ src = XCreateBitmapFromData(dpy, DefaultRootWindow(dpy), srcBits, 3, 3);
++ msk = XCreateBitmapFromData(dpy, DefaultRootWindow(dpy), mskBits, 3, 3);
++ XAllocNamedColor(dpy, DefaultColormap(dpy,DefaultScreen(dpy)), "black",
++ &fg, &fg);
++ XAllocNamedColor(dpy, DefaultColormap(dpy,DefaultScreen(dpy)), "white",
++ &bg, &bg);
++ cursor = XCreatePixmapCursor(dpy, src, msk, &fg, &bg, 1, 1);
++ XFreePixmap(dpy, src);
++ XFreePixmap(dpy, msk);
+
+- return cursor;
++ return cursor;
++}
++
++/*
++ * FillImage.
++ */
++
++void
++FillScreen(int x, int y, int width, int height, unsigned long fill)
+{
-+ Cursor cursor;
-+ Pixmap src, msk;
-+ static char srcBits[] = { 0, 14, 0 };
-+ static char mskBits[] = { 14,31,14 };
-+ XColor fg, bg;
++ int bpp = image->bits_per_pixel;
++ int Bpp = image->bits_per_pixel / 8;
++ int Bpl = image->bytes_per_line;
++ int h, widthInBytes = width * Bpp;
++ static char *buf = NULL;
++ static int buflen = 0;
++ unsigned char *ucp;
++ unsigned short *usp;
++ unsigned int *uip;
++ char *scr;
++
++//fprintf(stderr, "FillImage bpp=%d %04dx%04d+%04d+%04d -- 0x%x\n", bpp, width, height, x, y, fill);
++
++ if (widthInBytes > buflen || !buf) {
++ if (buf) {
++ free(buf);
++ }
++ buflen = widthInBytes * 2;
++ buf = (char *)malloc(buflen);
++ }
++ ucp = (unsigned char*) buf;
++ usp = (unsigned short*) buf;
++ uip = (unsigned int*) buf;
++
++ for (h = 0; h < width; h++) {
++ if (bpp == 8) {
++ *(ucp+h) = (unsigned char) fill;
++ } else if (bpp == 16) {
++ *(usp+h) = (unsigned short) fill;
++ } else if (bpp == 32) {
++ *(uip+h) = (unsigned int) fill;
++ }
++ }
+
-+ src = XCreateBitmapFromData(dpy, DefaultRootWindow(dpy), srcBits, 3, 3);
-+ msk = XCreateBitmapFromData(dpy, DefaultRootWindow(dpy), mskBits, 3, 3);
-+ XAllocNamedColor(dpy, DefaultColormap(dpy,DefaultScreen(dpy)), "black",
-+ &fg, &fg);
-+ XAllocNamedColor(dpy, DefaultColormap(dpy,DefaultScreen(dpy)), "white",
-+ &bg, &bg);
-+ cursor = XCreatePixmapCursor(dpy, src, msk, &fg, &bg, 1, 1);
-+ XFreePixmap(dpy, src);
-+ XFreePixmap(dpy, msk);
++ scr = image->data + y * Bpl + x * Bpp;
+
-+ return cursor;
++ for (h = 0; h < height; h++) {
++ memcpy(scr, buf, widthInBytes);
++ scr += Bpl;
++ }
++ put_image(x, y, x, y, width, height);
+}
+
-+
- /*
- * CopyDataToScreen.
- */
-@@ -367,7 +536,11 @@
- usleep(appData.rawDelay * 1000);
- }
++void copy_rect(int x, int y, int width, int height, int src_x, int src_y) {
++ char *src, *dst;
++ int i;
++ int Bpp = image->bits_per_pixel / 8;
++ int Bpl = image->bytes_per_line;
++
++//fprintf(stderr, "copy_rect: %04dx%04d+%04d+%04d -- %04d %04d Bpp=%d Bpl=%d\n", width, height, x, y, src_x, src_y, Bpp, Bpl);
++ if (y < src_y) {
++ src = image->data + src_y * Bpl + src_x * Bpp;
++ dst = image->data + y * Bpl + x * Bpp;
++ for (i = 0; i < height; i++) {
++ memmove(dst, src, Bpp * width);
++ src += Bpl;
++ dst += Bpl;
++ }
++ } else {
++ src = image->data + (src_y + height - 1) * Bpl + src_x * Bpp;
++ dst = image->data + (y + height - 1) * Bpl + x * Bpp;
++ for (i = 0; i < height; i++) {
++ memmove(dst, src, Bpp * width);
++ src -= Bpl;
++ dst -= Bpl;
++ }
++ }
+ }
+
+
+@@ -359,38 +717,37 @@
+ void
+ CopyDataToScreen(char *buf, int x, int y, int width, int height)
+ {
+- if (appData.rawDelay != 0) {
+- XFillRectangle(dpy, desktopWin, gc, x, y, width, height);
+-
+- XSync(dpy,False);
+-
+- usleep(appData.rawDelay * 1000);
+- }
++ if (appData.rawDelay != 0) {
++ XFillRectangle(dpy, desktopWin, gc, x, y, width, height);
++ XSync(dpy,False);
++ usleep(appData.rawDelay * 1000);
++ }
- if (!appData.useBGR233) {
-+ if (appData.useBGR233) {
-+ CopyBGR233ToScreen((CARD8 *)buf, x, y, width, height);
-+ } else if (appData.useBGR565) {
-+ CopyBGR565ToScreen((CARD16 *)buf, x, y, width, height);
-+ } else {
- int h;
- int widthInBytes = width * myFormat.bitsPerPixel / 8;
- int scrWidthInBytes = si.framebufferWidth * myFormat.bitsPerPixel / 8;
-@@ -380,8 +553,6 @@
- buf += widthInBytes;
- scr += scrWidthInBytes;
- }
+- int h;
+- int widthInBytes = width * myFormat.bitsPerPixel / 8;
+- int scrWidthInBytes = si.framebufferWidth * myFormat.bitsPerPixel / 8;
+-
+- char *scr = (image->data + y * scrWidthInBytes
+- + x * myFormat.bitsPerPixel / 8);
+-
+- for (h = 0; h < height; h++) {
+- memcpy(scr, buf, widthInBytes);
+- buf += widthInBytes;
+- scr += scrWidthInBytes;
+- }
- } else {
- CopyBGR233ToScreen((CARD8 *)buf, x, y, width, height);
- }
+- }
++ if (appData.useBGR233) {
++ CopyBGR233ToScreen((CARD8 *)buf, x, y, width, height);
++ } else if (appData.useBGR565) {
++ CopyBGR565ToScreen((CARD16 *)buf, x, y, width, height);
++ } else {
++ int h;
++ int widthInBytes = width * myFormat.bitsPerPixel / 8;
++ int scrWidthInBytes = si.framebufferWidth * myFormat.bitsPerPixel / 8;
++
++ char *scr = (image->data + y * scrWidthInBytes
++ + x * myFormat.bitsPerPixel / 8);
++
++//fprintf(stderr, "CopyDataToScreen %dx%d+%d+%d\n", width, height, x, y);
++
++ for (h = 0; h < height; h++) {
++ memcpy(scr, buf, widthInBytes);
++ buf += widthInBytes;
++ scr += scrWidthInBytes;
++ }
++ }
- #ifdef MITSHM
-@@ -460,3 +631,111 @@
- break;
- }
+-#ifdef MITSHM
+- if (appData.useShm) {
+- XShmPutImage(dpy, desktopWin, gc, image, x, y, x, y, width, height, False);
+- return;
+- }
+-#endif
+- XPutImage(dpy, desktopWin, gc, image, x, y, x, y, width, height);
++ put_image(x, y, x, y, width, height);
++ if (width > 1 && height > 1) {
++ XSync(dpy, False);
++ }
}
+
+
+@@ -401,62 +758,175 @@
+ static void
+ CopyBGR233ToScreen(CARD8 *buf, int x, int y, int width, int height)
+ {
+- int p, q;
+- int xoff = 7 - (x & 7);
+- int xcur;
+- int fbwb = si.framebufferWidth / 8;
+- CARD8 *scr1 = ((CARD8 *)image->data) + y * fbwb + x / 8;
+- CARD8 *scrt;
+- CARD8 *scr8 = ((CARD8 *)image->data) + y * si.framebufferWidth + x;
+- CARD16 *scr16 = ((CARD16 *)image->data) + y * si.framebufferWidth + x;
+- CARD32 *scr32 = ((CARD32 *)image->data) + y * si.framebufferWidth + x;
++ int p, q;
++ int xoff = 7 - (x & 7);
++ int xcur;
++ int fbwb = si.framebufferWidth / 8;
++ CARD8 *scr1 = ((CARD8 *)image->data) + y * fbwb + x / 8;
++ CARD8 *scrt;
++ CARD8 *scr8 = ((CARD8 *)image->data) + y * si.framebufferWidth + x;
++ CARD16 *scr16 = ((CARD16 *)image->data) + y * si.framebufferWidth + x;
++ CARD32 *scr32 = ((CARD32 *)image->data) + y * si.framebufferWidth + x;
+
+- switch (visbpp) {
++ switch (visbpp) {
+
+ /* thanks to Chris Hooper for single bpp support */
+
+- case 1:
+- for (q = 0; q < height; q++) {
+- xcur = xoff;
+- scrt = scr1;
+- for (p = 0; p < width; p++) {
+- *scrt = ((*scrt & ~(1 << xcur))
+- | (BGR233ToPixel[*(buf++)] << xcur));
+-
+- if (xcur-- == 0) {
+- xcur = 7;
+- scrt++;
++ case 1:
++ for (q = 0; q < height; q++) {
++ xcur = xoff;
++ scrt = scr1;
++ for (p = 0; p < width; p++) {
++ *scrt = ((*scrt & ~(1 << xcur))
++ | (BGR233ToPixel[*(buf++)] << xcur));
++
++ if (xcur-- == 0) {
++ xcur = 7;
++ scrt++;
++ }
++ }
++ scr1 += fbwb;
++ }
++ break;
+
++ case 8:
++ for (q = 0; q < height; q++) {
++ for (p = 0; p < width; p++) {
++ *(scr8++) = BGR233ToPixel[*(buf++)];
++ }
++ scr8 += si.framebufferWidth - width;
++ }
++ break;
++
++ case 16:
++ for (q = 0; q < height; q++) {
++ for (p = 0; p < width; p++) {
++ *(scr16++) = BGR233ToPixel[*(buf++)];
++ }
++ scr16 += si.framebufferWidth - width;
++ }
++ break;
++
++ case 32:
++ for (q = 0; q < height; q++) {
++ for (p = 0; p < width; p++) {
++ *(scr32++) = BGR233ToPixel[*(buf++)];
++ }
++ scr32 += si.framebufferWidth - width;
++ }
++ break;
+ }
+- }
+- scr1 += fbwb;
+- }
+- break;
++}
+
+- case 8:
+- for (q = 0; q < height; q++) {
+- for (p = 0; p < width; p++) {
+- *(scr8++) = BGR233ToPixel[*(buf++)];
+- }
+- scr8 += si.framebufferWidth - width;
+- }
+- break;
+static void
+CopyBGR565ToScreen(CARD16 *buf, int x, int y, int width, int height)
+{
-+ int p, q;
-+ CARD32 *scr32 = ((CARD32 *)image->data) + y * si.framebufferWidth + x;
-+
-+ /* case 32: */
-+ for (q = 0; q < height; q++) {
-+ for (p = 0; p < width; p++) {
-+ *(scr32++) = BGR565ToPixel[*(buf++)];
-+ }
-+ scr32 += si.framebufferWidth - width;
-+ }
++ int p, q;
++ CARD32 *scr32 = ((CARD32 *)image->data) + y * si.framebufferWidth + x;
+
+- case 16:
+- for (q = 0; q < height; q++) {
+- for (p = 0; p < width; p++) {
+- *(scr16++) = BGR233ToPixel[*(buf++)];
+- }
+- scr16 += si.framebufferWidth - width;
+- }
+- break;
++ /* case 32: */
++ for (q = 0; q < height; q++) {
++ for (p = 0; p < width; p++) {
++ *(scr32++) = BGR565ToPixel[*(buf++)];
++ }
++ scr32 += si.framebufferWidth - width;
++ }
+}
-+
+
+- case 32:
+- for (q = 0; q < height; q++) {
+- for (p = 0; p < width; p++) {
+- *(scr32++) = BGR233ToPixel[*(buf++)];
+- }
+- scr32 += si.framebufferWidth - width;
+- }
+- break;
+- }
+static void reset_image(void) {
+ if (UsingShm()) {
+ ShmCleanup();
-+ } else {
-+ if (image && image->data) {
-+ free(image->data);
-+ /* see manpage XDestroyImage may also free data, so we skip and have a tiny leak instead */
-+ if (0) XDestroyImage(image);
-+ image = NULL;
-+ }
+ }
++ if (image && image->data) {
++ XDestroyImage(image);
++ }
++ image = NULL;
++ if (image_ycrop && image_ycrop->data) {
++ XDestroyImage(image_ycrop);
++ }
++ image_ycrop = NULL;
+ create_image();
+ XFlush(dpy);
+}
@@ -1386,6 +2318,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview
+void ReDoDesktop(void) {
+ int w, h, x, y, dw, dh;
+
++ check_tall();
+ if (appData.yCrop) {
+ if (appData.yCrop < 0 || old_width <= 0) {
+ appData.yCrop = guessCrop();
@@ -1432,6 +2365,9 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview
+ h = si.framebufferHeight;
+ if (appData.yCrop > 0) {
+ h = appData.yCrop;
++ if (0 && appData.sbWidth <= 6 && appData.sbWidth > 0) {
++ h += appData.sbWidth;
++ }
+ }
+
+ if (w + dw >= dpyWidth) {
@@ -1459,10 +2395,10 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview
+ XtConfigureWidget(toplevel, x + dw, y + dh, w, h, 0);
+
+ reset_image();
-+}
+ }
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/fullscreen.c vnc_unixsrc/vncviewer/fullscreen.c
--- vnc_unixsrc.orig/vncviewer/fullscreen.c 2003-10-09 05:23:49.000000000 -0400
-+++ vnc_unixsrc/vncviewer/fullscreen.c 2007-02-04 14:15:42.000000000 -0500
++++ vnc_unixsrc/vncviewer/fullscreen.c 2007-02-17 16:32:23.000000000 -0500
@@ -85,10 +85,14 @@
Dimension oldViewportWidth, oldViewportHeight, clipWidth, clipHeight;
Position viewportX, viewportY;
@@ -1640,9 +2576,28 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/fullscreen.c vnc_unixsrc/vncv
if (desktopY > si.framebufferHeight - dpyHeight)
desktopY = si.framebufferHeight - dpyHeight;
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/hextile.c vnc_unixsrc/vncviewer/hextile.c
---- vnc_unixsrc.orig/vncviewer/hextile.c 2000-06-11 08:00:53.000000000 -0400
-+++ vnc_unixsrc/vncviewer/hextile.c 2007-02-03 20:41:19.000000000 -0500
-@@ -66,11 +66,18 @@
+--- vnc_unixsrc.orig/vncviewer/hextile.c 2007-02-17 22:33:46.000000000 -0500
++++ vnc_unixsrc/vncviewer/hextile.c 2007-02-17 22:48:39.000000000 -0500
+@@ -30,6 +30,18 @@
+ #define CARDBPP CONCAT2E(CARD,BPP)
+ #define GET_PIXEL CONCAT2E(GET_PIXEL,BPP)
+
++#define FillRectangle(x, y, w, h, color) \
++ { \
++ XGCValues _gcv; \
++ _gcv.foreground = color; \
++ if (!appData.useBackingstore) { \
++ FillScreen(x, y, w, h, _gcv.foreground); \
++ } else { \
++ XChangeGC(dpy, gc, GCForeground, &_gcv); \
++ XFillRectangle(dpy, desktopWin, gc, x, y, w, h); \
++ } \
++ }
++
+ static Bool
+ HandleHextileBPP (int rx, int ry, int rw, int rh)
+ {
+@@ -66,14 +78,25 @@
return False;
#if (BPP == 8)
@@ -1661,9 +2616,18 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/hextile.c vnc_unixsrc/vncview
gcv.foreground = bg;
+ }
- XChangeGC(dpy, gc, GCForeground, &gcv);
- XFillRectangle(dpy, desktopWin, gc, x, y, w, h);
-@@ -101,11 +108,18 @@
+- XChangeGC(dpy, gc, GCForeground, &gcv);
+- XFillRectangle(dpy, desktopWin, gc, x, y, w, h);
++#if 0
++ XChangeGC(dpy, gc, GCForeground, &gcv);
++ XFillRectangle(dpy, desktopWin, gc, x, y, w, h);
++#else
++ FillRectangle(x, y, w, h, gcv.foreground);
++#endif
+
+ if (subencoding & rfbHextileForegroundSpecified)
+ if (!ReadFromRFBServer((char *)&fg, sizeof(fg)))
+@@ -101,14 +124,25 @@
sh = rfbHextileExtractH(*ptr);
ptr++;
#if (BPP == 8)
@@ -1682,9 +2646,18 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/hextile.c vnc_unixsrc/vncview
gcv.foreground = fg;
+ }
- XChangeGC(dpy, gc, GCForeground, &gcv);
- XFillRectangle(dpy, desktopWin, gc, x+sx, y+sy, sw, sh);
-@@ -116,11 +130,18 @@
+- XChangeGC(dpy, gc, GCForeground, &gcv);
+- XFillRectangle(dpy, desktopWin, gc, x+sx, y+sy, sw, sh);
++#if 0
++ XChangeGC(dpy, gc, GCForeground, &gcv);
++ XFillRectangle(dpy, desktopWin, gc, x+sx, y+sy, sw, sh);
++#else
++ FillRectangle(x+sx, y+sy, sw, sh, gcv.foreground);
++#endif
+ }
+
+ } else {
+@@ -116,13 +150,22 @@
return False;
#if (BPP == 8)
@@ -1703,8 +2676,30 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/hextile.c vnc_unixsrc/vncview
gcv.foreground = fg;
+ }
++#if 0
XChangeGC(dpy, gc, GCForeground, &gcv);
++#endif
+ for (i = 0; i < nSubrects; i++) {
+ sx = rfbHextileExtractX(*ptr);
+@@ -131,7 +174,11 @@
+ sw = rfbHextileExtractW(*ptr);
+ sh = rfbHextileExtractH(*ptr);
+ ptr++;
++#if 0
+ XFillRectangle(dpy, desktopWin, gc, x+sx, y+sy, sw, sh);
++#else
++ FillRectangle(x+sx, y+sy, sw, sh, gcv.foreground);
++#endif
+ }
+ }
+ }
+@@ -139,3 +186,5 @@
+
+ return True;
+ }
++
++#undef FillRectangle
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/popup.c vnc_unixsrc/vncviewer/popup.c
--- vnc_unixsrc.orig/vncviewer/popup.c 2000-06-11 08:00:53.000000000 -0400
+++ vnc_unixsrc/vncviewer/popup.c 2007-02-04 11:14:45.000000000 -0500
@@ -1744,10 +2739,33 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/popup.c vnc_unixsrc/vncviewer
XSetWMProtocols(dpy, XtWindow(popup), &wmDeleteWindow, 1);
}
+diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/popup_ad vnc_unixsrc/vncviewer/popup_ad
+--- vnc_unixsrc.orig/vncviewer/popup_ad 1969-12-31 19:00:00.000000000 -0500
++++ vnc_unixsrc/vncviewer/popup_ad 2007-02-18 19:52:31.000000000 -0500
+@@ -0,0 +1,19 @@
++#!/usr/bin/perl
++
++$ok = 0;
++
++open(A, "<argsresources.c") || die;
++
++while (<A>) {
++ if (/popupButtonCount:/) {
++ $on = 1;
++ } elsif (/^\s*NULL/) {
++ $on = 0;
++ }
++ next unless $on;
++ chomp;
++ $_ =~ s/^\s*"//;
++ $_ =~ s/",//;
++ $_ .= "\n" unless $_ =~ /\n/;
++ print;
++}
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncviewer/rfbproto.c
--- vnc_unixsrc.orig/vncviewer/rfbproto.c 2004-03-11 13:14:39.000000000 -0500
-+++ vnc_unixsrc/vncviewer/rfbproto.c 2007-02-04 18:31:34.000000000 -0500
-@@ -57,6 +57,23 @@
++++ vnc_unixsrc/vncviewer/rfbproto.c 2007-02-18 18:46:53.000000000 -0500
+@@ -57,6 +57,25 @@
static Bool HandleTight16(int rx, int ry, int rw, int rh);
static Bool HandleTight32(int rx, int ry, int rw, int rh);
@@ -1763,6 +2781,8 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
+ unsigned long length;
+} rfbZRLEHeader;
+
++long zywrle;
++
+#define sz_rfbZRLEHeader 4
+
+#define rfbZRLETileWidth 64
@@ -1771,7 +2791,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
static void ReadConnFailedReason(void);
static long ReadCompactLen (void);
-@@ -68,6 +85,9 @@
+@@ -68,6 +87,9 @@
int compressedLen);
@@ -1781,7 +2801,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
int rfbsock;
char *desktopName;
rfbPixelFormat myFormat;
-@@ -177,6 +197,9 @@
+@@ -177,6 +199,9 @@
sig_rfbEncodingPointerPos, "Pointer position update");
CapsAdd(encodingCaps, rfbEncodingLastRect, rfbTightVncVendor,
sig_rfbEncodingLastRect, "LastRect protocol extension");
@@ -1791,31 +2811,887 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
}
-@@ -729,6 +752,23 @@
+@@ -187,21 +212,21 @@
+ Bool
+ ConnectToRFBServer(const char *hostname, int port)
+ {
+- unsigned int host;
++ unsigned int host;
+
+- if (!StringToIPAddr(hostname, &host)) {
+- fprintf(stderr,"Couldn't convert '%s' to host address\n", hostname);
+- return False;
+- }
++ if (!StringToIPAddr(hostname, &host)) {
++ fprintf(stderr,"Couldn't convert '%s' to host address\n", hostname);
++ return False;
++ }
+
+- rfbsock = ConnectToTcpAddr(host, port);
++ rfbsock = ConnectToTcpAddr(host, port);
+
+- if (rfbsock < 0) {
+- fprintf(stderr,"Unable to connect to VNC server\n");
+- return False;
+- }
++ if (rfbsock < 0) {
++ fprintf(stderr,"Unable to connect to VNC server\n");
++ return False;
++ }
+
+- return SetNonBlocking(rfbsock);
++ return SetNonBlocking(rfbsock);
+ }
+
+
+@@ -212,117 +237,127 @@
+ Bool
+ InitialiseRFBConnection(void)
+ {
+- rfbProtocolVersionMsg pv;
+- int server_major, server_minor;
+- int viewer_major, viewer_minor;
+- rfbClientInitMsg ci;
+- int secType;
++ rfbProtocolVersionMsg pv;
++ int server_major, server_minor;
++ int viewer_major, viewer_minor;
++ rfbClientInitMsg ci;
++ int secType;
+
+- /* if the connection is immediately closed, don't report anything, so
+- that pmw's monitor can make test connections */
++ /* if the connection is immediately closed, don't report anything, so
++ that pmw's monitor can make test connections */
+
+- if (listenSpecified)
+- errorMessageOnReadFailure = False;
++ if (listenSpecified) {
++ errorMessageOnReadFailure = False;
++ }
+
+- if (!ReadFromRFBServer(pv, sz_rfbProtocolVersionMsg))
+- return False;
++ if (!ReadFromRFBServer(pv, sz_rfbProtocolVersionMsg)) {
++ return False;
++ }
+
+- errorMessageOnReadFailure = True;
++ errorMessageOnReadFailure = True;
+
+- pv[sz_rfbProtocolVersionMsg] = 0;
++ pv[sz_rfbProtocolVersionMsg] = 0;
+
+- if (sscanf(pv, rfbProtocolVersionFormat,
+- &server_major, &server_minor) != 2) {
+- fprintf(stderr,"Not a valid VNC server\n");
+- return False;
+- }
++ if (sscanf(pv, rfbProtocolVersionFormat, &server_major, &server_minor) != 2) {
++ fprintf(stderr,"Not a valid VNC server\n");
++ return False;
++ }
+
+- viewer_major = rfbProtocolMajorVersion;
+- if (server_major == 3 && server_minor >= rfbProtocolMinorVersion) {
+- /* the server supports at least the standard protocol 3.7 */
+- viewer_minor = rfbProtocolMinorVersion;
+- } else {
+- /* any other server version, request the standard 3.3 */
+- viewer_minor = rfbProtocolFallbackMinorVersion;
+- }
++ viewer_major = rfbProtocolMajorVersion;
++ if (server_major == 3 && server_minor >= rfbProtocolMinorVersion) {
++ /* the server supports at least the standard protocol 3.7 */
++ viewer_minor = rfbProtocolMinorVersion;
++ } else {
++ /* any other server version, request the standard 3.3 */
++ viewer_minor = rfbProtocolFallbackMinorVersion;
++ }
+
+- fprintf(stderr, "Connected to RFB server, using protocol version %d.%d\n",
+- viewer_major, viewer_minor);
++ fprintf(stderr, "Connected to RFB server, using protocol version %d.%d\n", viewer_major, viewer_minor);
+
+- sprintf(pv, rfbProtocolVersionFormat, viewer_major, viewer_minor);
++ sprintf(pv, rfbProtocolVersionFormat, viewer_major, viewer_minor);
+
+- if (!WriteExact(rfbsock, pv, sz_rfbProtocolVersionMsg))
+- return False;
++ if (!WriteExact(rfbsock, pv, sz_rfbProtocolVersionMsg)) {
++ return False;
++ }
+
+- /* Read or select the security type. */
+- if (viewer_minor == rfbProtocolMinorVersion) {
+- secType = SelectSecurityType();
+- } else {
+- secType = ReadSecurityType();
+- }
+- if (secType == rfbSecTypeInvalid)
+- return False;
++ /* Read or select the security type. */
++ if (viewer_minor == rfbProtocolMinorVersion) {
++ secType = SelectSecurityType();
++ } else {
++ secType = ReadSecurityType();
++ }
++ if (secType == rfbSecTypeInvalid) {
++ return False;
++ }
+
+- switch (secType) {
+- case rfbSecTypeNone:
+- fprintf(stderr, "No authentication needed\n");
+- break;
+- case rfbSecTypeVncAuth:
+- if (!AuthenticateVNC())
+- return False;
+- break;
+- case rfbSecTypeTight:
+- tightVncProtocol = True;
+- InitCapabilities();
+- if (!SetupTunneling())
+- return False;
+- if (!PerformAuthenticationTight())
+- return False;
+- break;
+- default: /* should never happen */
+- fprintf(stderr, "Internal error: Invalid security type\n");
+- return False;
+- }
++ switch (secType) {
++ case rfbSecTypeNone:
++ fprintf(stderr, "No authentication needed\n");
++ break;
++ case rfbSecTypeVncAuth:
++ if (!AuthenticateVNC()) {
++ return False;
++ }
++ break;
++ case rfbSecTypeTight:
++ tightVncProtocol = True;
++ InitCapabilities();
++ if (!SetupTunneling()) {
++ return False;
++ }
++ if (!PerformAuthenticationTight()) {
++ return False;
++ }
++ break;
++ default: /* should never happen */
++ fprintf(stderr, "Internal error: Invalid security type\n");
++ return False;
++ }
+
+- ci.shared = (appData.shareDesktop ? 1 : 0);
++ ci.shared = (appData.shareDesktop ? 1 : 0);
+
+- if (!WriteExact(rfbsock, (char *)&ci, sz_rfbClientInitMsg))
+- return False;
++ if (!WriteExact(rfbsock, (char *)&ci, sz_rfbClientInitMsg)) {
++ return False;
++ }
+
+- if (!ReadFromRFBServer((char *)&si, sz_rfbServerInitMsg))
+- return False;
++ if (!ReadFromRFBServer((char *)&si, sz_rfbServerInitMsg)) {
++ return False;
++ }
+
+- si.framebufferWidth = Swap16IfLE(si.framebufferWidth);
+- si.framebufferHeight = Swap16IfLE(si.framebufferHeight);
+- si.format.redMax = Swap16IfLE(si.format.redMax);
+- si.format.greenMax = Swap16IfLE(si.format.greenMax);
+- si.format.blueMax = Swap16IfLE(si.format.blueMax);
+- si.nameLength = Swap32IfLE(si.nameLength);
+-
+- /* FIXME: Check arguments to malloc() calls. */
+- desktopName = malloc(si.nameLength + 1);
+- if (!desktopName) {
+- fprintf(stderr, "Error allocating memory for desktop name, %lu bytes\n",
+- (unsigned long)si.nameLength);
+- return False;
+- }
++ si.framebufferWidth = Swap16IfLE(si.framebufferWidth);
++ si.framebufferHeight = Swap16IfLE(si.framebufferHeight);
++ si.format.redMax = Swap16IfLE(si.format.redMax);
++ si.format.greenMax = Swap16IfLE(si.format.greenMax);
++ si.format.blueMax = Swap16IfLE(si.format.blueMax);
++ si.nameLength = Swap32IfLE(si.nameLength);
++
++ /* FIXME: Check arguments to malloc() calls. */
++ desktopName = malloc(si.nameLength + 1);
++ if (!desktopName) {
++ fprintf(stderr, "Error allocating memory for desktop name, %lu bytes\n",
++ (unsigned long)si.nameLength);
++ return False;
++ }
+
+- if (!ReadFromRFBServer(desktopName, si.nameLength)) return False;
++ if (!ReadFromRFBServer(desktopName, si.nameLength)) {
++ return False;
++ }
+
+- desktopName[si.nameLength] = 0;
++ desktopName[si.nameLength] = 0;
+
+- fprintf(stderr,"Desktop name \"%s\"\n",desktopName);
++ fprintf(stderr,"Desktop name \"%s\"\n",desktopName);
+
+- fprintf(stderr,"VNC server default format:\n");
+- PrintPixelFormat(&si.format);
++ fprintf(stderr,"VNC server default format:\n");
++ PrintPixelFormat(&si.format);
+
+- if (tightVncProtocol) {
+- /* Read interaction capabilities (protocol 3.7t) */
+- if (!ReadInteractionCaps())
+- return False;
+- }
++ if (tightVncProtocol) {
++ /* Read interaction capabilities (protocol 3.7t) */
++ if (!ReadInteractionCaps()) {
++ return False;
++ }
++ }
+
+- return True;
++ return True;
+ }
+
+
+@@ -333,26 +368,27 @@
+ static int
+ ReadSecurityType(void)
+ {
+- CARD32 secType;
++ CARD32 secType;
+
+- /* Read the security type */
+- if (!ReadFromRFBServer((char *)&secType, sizeof(secType)))
+- return rfbSecTypeInvalid;
++ /* Read the security type */
++ if (!ReadFromRFBServer((char *)&secType, sizeof(secType))) {
++ return rfbSecTypeInvalid;
++ }
+
+- secType = Swap32IfLE(secType);
++ secType = Swap32IfLE(secType);
+
+- if (secType == rfbSecTypeInvalid) {
+- ReadConnFailedReason();
+- return rfbSecTypeInvalid;
+- }
++ if (secType == rfbSecTypeInvalid) {
++ ReadConnFailedReason();
++ return rfbSecTypeInvalid;
++ }
+
+- if (secType != rfbSecTypeNone && secType != rfbSecTypeVncAuth) {
+- fprintf(stderr, "Unknown security type from RFB server: %d\n",
+- (int)secType);
+- return rfbSecTypeInvalid;
+- }
++ if (secType != rfbSecTypeNone && secType != rfbSecTypeVncAuth) {
++ fprintf(stderr, "Unknown security type from RFB server: %d\n",
++ (int)secType);
++ return rfbSecTypeInvalid;
++ }
+
+- return (int)secType;
++ return (int)secType;
+ }
+
+
+@@ -363,60 +399,66 @@
+ static int
+ SelectSecurityType(void)
+ {
+- CARD8 nSecTypes;
+- char *secTypeNames[] = {"None", "VncAuth"};
+- CARD8 knownSecTypes[] = {rfbSecTypeNone, rfbSecTypeVncAuth};
+- int nKnownSecTypes = sizeof(knownSecTypes);
+- CARD8 *secTypes;
+- CARD8 secType = rfbSecTypeInvalid;
+- int i, j;
+-
+- /* Read the list of secutiry types. */
+- if (!ReadFromRFBServer((char *)&nSecTypes, sizeof(nSecTypes)))
+- return rfbSecTypeInvalid;
+-
+- if (nSecTypes == 0) {
+- ReadConnFailedReason();
+- return rfbSecTypeInvalid;
+- }
++ CARD8 nSecTypes;
++ char *secTypeNames[] = {"None", "VncAuth"};
++ CARD8 knownSecTypes[] = {rfbSecTypeNone, rfbSecTypeVncAuth};
++ int nKnownSecTypes = sizeof(knownSecTypes);
++ CARD8 *secTypes;
++ CARD8 secType = rfbSecTypeInvalid;
++ int i, j;
++
++ /* Read the list of secutiry types. */
++ if (!ReadFromRFBServer((char *)&nSecTypes, sizeof(nSecTypes))) {
++ return rfbSecTypeInvalid;
++ }
+
+- secTypes = malloc(nSecTypes);
+- if (!ReadFromRFBServer((char *)secTypes, nSecTypes))
+- return rfbSecTypeInvalid;
+-
+- /* Find out if the server supports TightVNC protocol extensions */
+- for (j = 0; j < (int)nSecTypes; j++) {
+- if (secTypes[j] == rfbSecTypeTight) {
+- free(secTypes);
+- secType = rfbSecTypeTight;
+- if (!WriteExact(rfbsock, (char *)&secType, sizeof(secType)))
+- return rfbSecTypeInvalid;
+- fprintf(stderr, "Enabling TightVNC protocol extensions\n");
+- return rfbSecTypeTight;
+- }
+- }
++ if (nSecTypes == 0) {
++ ReadConnFailedReason();
++ return rfbSecTypeInvalid;
++ }
+
+- /* Find first supported security type */
+- for (j = 0; j < (int)nSecTypes; j++) {
+- for (i = 0; i < nKnownSecTypes; i++) {
+- if (secTypes[j] == knownSecTypes[i]) {
+- secType = secTypes[j];
+- if (!WriteExact(rfbsock, (char *)&secType, sizeof(secType))) {
+- free(secTypes);
+- return rfbSecTypeInvalid;
+- }
+- break;
+- }
+- }
+- if (secType != rfbSecTypeInvalid) break;
+- }
++ secTypes = malloc(nSecTypes);
++ if (!ReadFromRFBServer((char *)secTypes, nSecTypes)) {
++ return rfbSecTypeInvalid;
++ }
++
++ /* Find out if the server supports TightVNC protocol extensions */
++ for (j = 0; j < (int)nSecTypes; j++) {
++ if (secTypes[j] == rfbSecTypeTight) {
++ free(secTypes);
++ secType = rfbSecTypeTight;
++ if (!WriteExact(rfbsock, (char *)&secType, sizeof(secType))) {
++ return rfbSecTypeInvalid;
++ }
++ fprintf(stderr, "Enabling TightVNC protocol extensions\n");
++ return rfbSecTypeTight;
++ }
++ }
+
+- free(secTypes);
++ /* Find first supported security type */
++ for (j = 0; j < (int)nSecTypes; j++) {
++ for (i = 0; i < nKnownSecTypes; i++) {
++ if (secTypes[j] == knownSecTypes[i]) {
++ secType = secTypes[j];
++ if (!WriteExact(rfbsock, (char *)&secType, sizeof(secType))) {
++ free(secTypes);
++ return rfbSecTypeInvalid;
++ }
++ break;
++ }
++ }
++ if (secType != rfbSecTypeInvalid) {
++ break;
++ }
++ }
++
++ free(secTypes);
+
+- if (secType == rfbSecTypeInvalid)
+- fprintf(stderr, "Server did not offer supported security type\n");
++ if (secType == rfbSecTypeInvalid) {
++ fprintf(stderr, "Server did not offer supported security type\n");
++ }
+
+- return (int)secType;
++ return (int)secType;
+ }
+
+
+@@ -451,6 +493,9 @@
+ return True;
+ }
+
++static char *restart_session_pw = NULL;
++static int restart_session_len = 0;
++
+
+ /*
+ * Negotiate authentication scheme (protocol version 3.7t)
+@@ -459,56 +504,61 @@
+ static Bool
+ PerformAuthenticationTight(void)
+ {
+- rfbAuthenticationCapsMsg caps;
+- CARD32 authScheme;
+- int i;
++ rfbAuthenticationCapsMsg caps;
++ CARD32 authScheme;
++ int i;
+
+- /* In the protocol version 3.7t, the server informs us about supported
+- authentication schemes. Here we read this information. */
++ /* In the protocol version 3.7t, the server informs us about supported
++ authentication schemes. Here we read this information. */
+
+- if (!ReadFromRFBServer((char *)&caps, sz_rfbAuthenticationCapsMsg))
+- return False;
++ if (!ReadFromRFBServer((char *)&caps, sz_rfbAuthenticationCapsMsg)) {
++ return False;
++ }
+
+- caps.nAuthTypes = Swap32IfLE(caps.nAuthTypes);
++ caps.nAuthTypes = Swap32IfLE(caps.nAuthTypes);
+
+- if (!caps.nAuthTypes) {
+- fprintf(stderr, "No authentication needed\n");
+- return True;
+- }
++ if (!caps.nAuthTypes) {
++ fprintf(stderr, "No authentication needed\n");
++ return True;
++ }
+
+- if (!ReadCapabilityList(authCaps, caps.nAuthTypes))
+- return False;
++ if (!ReadCapabilityList(authCaps, caps.nAuthTypes)) {
++ return False;
++ }
+
+- /* Prefer Unix login authentication if a user name was given. */
+- if (appData.userLogin && CapsIsEnabled(authCaps, rfbAuthUnixLogin)) {
+- authScheme = Swap32IfLE(rfbAuthUnixLogin);
+- if (!WriteExact(rfbsock, (char *)&authScheme, sizeof(authScheme)))
+- return False;
+- return AuthenticateUnixLogin();
+- }
++ /* Prefer Unix login authentication if a user name was given. */
++ if (appData.userLogin && CapsIsEnabled(authCaps, rfbAuthUnixLogin)) {
++ authScheme = Swap32IfLE(rfbAuthUnixLogin);
++ if (!WriteExact(rfbsock, (char *)&authScheme, sizeof(authScheme))) {
++ return False;
++ }
++ return AuthenticateUnixLogin();
++ }
+
+- /* Otherwise, try server's preferred authentication scheme. */
+- for (i = 0; i < CapsNumEnabled(authCaps); i++) {
+- authScheme = CapsGetByOrder(authCaps, i);
+- if (authScheme != rfbAuthUnixLogin && authScheme != rfbAuthVNC)
+- continue; /* unknown scheme - cannot use it */
+- authScheme = Swap32IfLE(authScheme);
+- if (!WriteExact(rfbsock, (char *)&authScheme, sizeof(authScheme)))
+- return False;
+- authScheme = Swap32IfLE(authScheme); /* convert it back */
+- if (authScheme == rfbAuthUnixLogin) {
+- return AuthenticateUnixLogin();
+- } else if (authScheme == rfbAuthVNC) {
+- return AuthenticateVNC();
+- } else {
+- /* Should never happen. */
+- fprintf(stderr, "Assertion failed: unknown authentication scheme\n");
+- return False;
+- }
+- }
++ /* Otherwise, try server's preferred authentication scheme. */
++ for (i = 0; i < CapsNumEnabled(authCaps); i++) {
++ authScheme = CapsGetByOrder(authCaps, i);
++ if (authScheme != rfbAuthUnixLogin && authScheme != rfbAuthVNC) {
++ continue; /* unknown scheme - cannot use it */
++ }
++ authScheme = Swap32IfLE(authScheme);
++ if (!WriteExact(rfbsock, (char *)&authScheme, sizeof(authScheme))) {
++ return False;
++ }
++ authScheme = Swap32IfLE(authScheme); /* convert it back */
++ if (authScheme == rfbAuthUnixLogin) {
++ return AuthenticateUnixLogin();
++ } else if (authScheme == rfbAuthVNC) {
++ return AuthenticateVNC();
++ } else {
++ /* Should never happen. */
++ fprintf(stderr, "Assertion failed: unknown authentication scheme\n");
++ return False;
++ }
++ }
+
+- fprintf(stderr, "No suitable authentication schemes offered by server\n");
+- return False;
++ fprintf(stderr, "No suitable authentication schemes offered by server\n");
++ return False;
+ }
+
+
+@@ -519,80 +569,97 @@
+ static Bool
+ AuthenticateVNC(void)
+ {
+- CARD32 authScheme, authResult;
+- CARD8 challenge[CHALLENGESIZE];
+- char *passwd;
+- char buffer[64];
+- char* cstatus;
+- int len;
++ CARD32 authScheme, authResult;
++ CARD8 challenge[CHALLENGESIZE];
++ char *passwd = NULL;
++ char buffer[64];
++ char* cstatus;
++ int len;
++ int restart = 0;
+
+- fprintf(stderr, "Performing standard VNC authentication\n");
++ fprintf(stderr, "Performing standard VNC authentication\n");
+
+- if (!ReadFromRFBServer((char *)challenge, CHALLENGESIZE))
+- return False;
++ if (!ReadFromRFBServer((char *)challenge, CHALLENGESIZE)) {
++ return False;
++ }
+
+- if (appData.passwordFile) {
+- passwd = vncDecryptPasswdFromFile(appData.passwordFile);
+- if (!passwd) {
+- fprintf(stderr, "Cannot read valid password from file \"%s\"\n",
+- appData.passwordFile);
+- return False;
+- }
+- } else if (appData.autoPass) {
+- passwd = buffer;
+- cstatus = fgets(buffer, sizeof buffer, stdin);
+- if (cstatus == NULL)
+- buffer[0] = '\0';
+- else
+- {
+- len = strlen(buffer);
+- if (len > 0 && buffer[len - 1] == '\n')
+- buffer[len - 1] = '\0';
+- }
+- } else if (appData.passwordDialog) {
+- passwd = DoPasswordDialog();
+- } else {
+- passwd = getpass("Password: ");
+- }
++ if (restart_session_pw != NULL) {
++ passwd = restart_session_pw;
++ restart_session_pw = NULL;
++ restart = 1;
++ } else if (appData.passwordFile) {
++ passwd = vncDecryptPasswdFromFile(appData.passwordFile);
++ if (!passwd) {
++ fprintf(stderr, "Cannot read valid password from file \"%s\"\n",
++ appData.passwordFile);
++ return False;
++ }
++ } else if (appData.autoPass) {
++ passwd = buffer;
++ cstatus = fgets(buffer, sizeof buffer, stdin);
++ if (cstatus == NULL) {
++ buffer[0] = '\0';
++ } else {
++ len = strlen(buffer);
++ if (len > 0 && buffer[len - 1] == '\n') {
++ buffer[len - 1] = '\0';
++ }
++ }
++ } else if (appData.passwordDialog) {
++ passwd = DoPasswordDialog();
++ } else {
++ passwd = getpass("Password: ");
++ }
+
+- if (!passwd || strlen(passwd) == 0) {
+- fprintf(stderr, "Reading password failed\n");
+- return False;
+- }
+- if (strlen(passwd) > 8) {
+- passwd[8] = '\0';
+- }
++ if (restart) {
++#define EN0 0
++#define DE1 1
++ unsigned char s_fixedkey[8] = {23,82,107,6,35,78,88,7};
++ deskey(s_fixedkey, DE1);
++ des(passwd, passwd);
++ } else {
++ if (!passwd || strlen(passwd) == 0) {
++ fprintf(stderr, "Reading password failed\n");
++ return False;
++ }
++ if (strlen(passwd) > 8) {
++ passwd[8] = '\0';
++ }
++ }
++ vncEncryptBytes(challenge, passwd);
++
+
+- vncEncryptBytes(challenge, passwd);
+
+- /* Lose the password from memory */
+- memset(passwd, '\0', strlen(passwd));
++// /* Lose the password from memory */
++// memset(passwd, '\0', strlen(passwd));
+
+- if (!WriteExact(rfbsock, (char *)challenge, CHALLENGESIZE))
+- return False;
++ if (!WriteExact(rfbsock, (char *)challenge, CHALLENGESIZE)) {
++ return False;
++ }
+
+- if (!ReadFromRFBServer((char *)&authResult, 4))
+- return False;
++ if (!ReadFromRFBServer((char *)&authResult, 4)) {
++ return False;
++ }
+
+- authResult = Swap32IfLE(authResult);
++ authResult = Swap32IfLE(authResult);
+
+- switch (authResult) {
+- case rfbVncAuthOK:
+- fprintf(stderr, "VNC authentication succeeded\n");
+- break;
+- case rfbVncAuthFailed:
+- fprintf(stderr, "VNC authentication failed\n");
+- return False;
+- case rfbVncAuthTooMany:
+- fprintf(stderr, "VNC authentication failed - too many tries\n");
+- return False;
+- default:
+- fprintf(stderr, "Unknown VNC authentication result: %d\n",
+- (int)authResult);
+- return False;
+- }
++ switch (authResult) {
++ case rfbVncAuthOK:
++ fprintf(stderr, "VNC authentication succeeded\n");
++ break;
++ case rfbVncAuthFailed:
++ fprintf(stderr, "VNC authentication failed\n");
++ return False;
++ case rfbVncAuthTooMany:
++ fprintf(stderr, "VNC authentication failed - too many tries\n");
++ return False;
++ default:
++ fprintf(stderr, "Unknown VNC authentication result: %d\n",
++ (int)authResult);
++ return False;
++ }
+
+- return True;
++ return True;
+ }
+
+ /*
+@@ -602,68 +669,71 @@
+ static Bool
+ AuthenticateUnixLogin(void)
+ {
+- CARD32 loginLen, passwdLen, authResult;
+- char *login;
+- char *passwd;
+- struct passwd *ps;
+-
+- fprintf(stderr, "Performing Unix login-style authentication\n");
+-
+- if (appData.userLogin) {
+- login = appData.userLogin;
+- } else {
+- ps = getpwuid(getuid());
+- login = ps->pw_name;
+- }
++ CARD32 loginLen, passwdLen, authResult;
++ char *login;
++ char *passwd;
++ struct passwd *ps;
++
++ fprintf(stderr, "Performing Unix login-style authentication\n");
++
++ if (appData.userLogin) {
++ login = appData.userLogin;
++ } else {
++ ps = getpwuid(getuid());
++ login = ps->pw_name;
++ }
+
+- fprintf(stderr, "Using user name \"%s\"\n", login);
++ fprintf(stderr, "Using user name \"%s\"\n", login);
+
+- if (appData.passwordDialog) {
+- passwd = DoPasswordDialog();
+- } else {
+- passwd = getpass("Password: ");
+- }
+- if (!passwd || strlen(passwd) == 0) {
+- fprintf(stderr, "Reading password failed\n");
+- return False;
+- }
++ if (appData.passwordDialog) {
++ passwd = DoPasswordDialog();
++ } else {
++ passwd = getpass("Password: ");
++ }
++ if (!passwd || strlen(passwd) == 0) {
++ fprintf(stderr, "Reading password failed\n");
++ return False;
++ }
+
+- loginLen = Swap32IfLE((CARD32)strlen(login));
+- passwdLen = Swap32IfLE((CARD32)strlen(passwd));
++ loginLen = Swap32IfLE((CARD32)strlen(login));
++ passwdLen = Swap32IfLE((CARD32)strlen(passwd));
+
+- if (!WriteExact(rfbsock, (char *)&loginLen, sizeof(loginLen)) ||
+- !WriteExact(rfbsock, (char *)&passwdLen, sizeof(passwdLen)))
+- return False;
++ if (!WriteExact(rfbsock, (char *)&loginLen, sizeof(loginLen)) ||
++ !WriteExact(rfbsock, (char *)&passwdLen, sizeof(passwdLen))) {
++ return False;
++ }
+
+- if (!WriteExact(rfbsock, login, strlen(login)) ||
+- !WriteExact(rfbsock, passwd, strlen(passwd)))
+- return False;
++ if (!WriteExact(rfbsock, login, strlen(login)) ||
++ !WriteExact(rfbsock, passwd, strlen(passwd))) {
++ return False;
++ }
+
+- /* Lose the password from memory */
+- memset(passwd, '\0', strlen(passwd));
++// /* Lose the password from memory */
++// memset(passwd, '\0', strlen(passwd));
+
+- if (!ReadFromRFBServer((char *)&authResult, sizeof(authResult)))
+- return False;
++ if (!ReadFromRFBServer((char *)&authResult, sizeof(authResult))) {
++ return False;
++ }
+
+- authResult = Swap32IfLE(authResult);
++ authResult = Swap32IfLE(authResult);
+
+- switch (authResult) {
+- case rfbVncAuthOK:
+- fprintf(stderr, "Authentication succeeded\n");
+- break;
+- case rfbVncAuthFailed:
+- fprintf(stderr, "Authentication failed\n");
+- return False;
+- case rfbVncAuthTooMany:
+- fprintf(stderr, "Authentication failed - too many tries\n");
+- return False;
+- default:
+- fprintf(stderr, "Unknown authentication result: %d\n",
+- (int)authResult);
+- return False;
+- }
++ switch (authResult) {
++ case rfbVncAuthOK:
++ fprintf(stderr, "Authentication succeeded\n");
++ break;
++ case rfbVncAuthFailed:
++ fprintf(stderr, "Authentication failed\n");
++ return False;
++ case rfbVncAuthTooMany:
++ fprintf(stderr, "Authentication failed - too many tries\n");
++ return False;
++ default:
++ fprintf(stderr, "Unknown authentication result: %d\n",
++ (int)authResult);
++ return False;
++ }
+
+- return True;
++ return True;
+ }
+
+
+@@ -675,19 +745,20 @@
+ static Bool
+ ReadInteractionCaps(void)
+ {
+- rfbInteractionCapsMsg intr_caps;
++ rfbInteractionCapsMsg intr_caps;
+
+- /* Read the counts of list items following */
+- if (!ReadFromRFBServer((char *)&intr_caps, sz_rfbInteractionCapsMsg))
+- return False;
+- intr_caps.nServerMessageTypes = Swap16IfLE(intr_caps.nServerMessageTypes);
+- intr_caps.nClientMessageTypes = Swap16IfLE(intr_caps.nClientMessageTypes);
+- intr_caps.nEncodingTypes = Swap16IfLE(intr_caps.nEncodingTypes);
+-
+- /* Read the lists of server- and client-initiated messages */
+- return (ReadCapabilityList(serverMsgCaps, intr_caps.nServerMessageTypes) &&
+- ReadCapabilityList(clientMsgCaps, intr_caps.nClientMessageTypes) &&
+- ReadCapabilityList(encodingCaps, intr_caps.nEncodingTypes));
++ /* Read the counts of list items following */
++ if (!ReadFromRFBServer((char *)&intr_caps, sz_rfbInteractionCapsMsg)) {
++ return False;
++ }
++ intr_caps.nServerMessageTypes = Swap16IfLE(intr_caps.nServerMessageTypes);
++ intr_caps.nClientMessageTypes = Swap16IfLE(intr_caps.nClientMessageTypes);
++ intr_caps.nEncodingTypes = Swap16IfLE(intr_caps.nEncodingTypes);
++
++ /* Read the lists of server- and client-initiated messages */
++ return (ReadCapabilityList(serverMsgCaps, intr_caps.nServerMessageTypes) &&
++ ReadCapabilityList(clientMsgCaps, intr_caps.nClientMessageTypes) &&
++ ReadCapabilityList(encodingCaps, intr_caps.nEncodingTypes));
+ }
+
+
+@@ -700,17 +771,18 @@
+ static Bool
+ ReadCapabilityList(CapsContainer *caps, int count)
+ {
+- rfbCapabilityInfo msginfo;
+- int i;
++ rfbCapabilityInfo msginfo;
++ int i;
+
+- for (i = 0; i < count; i++) {
+- if (!ReadFromRFBServer((char *)&msginfo, sz_rfbCapabilityInfo))
+- return False;
+- msginfo.code = Swap32IfLE(msginfo.code);
+- CapsEnable(caps, &msginfo);
+- }
++ for (i = 0; i < count; i++) {
++ if (!ReadFromRFBServer((char *)&msginfo, sz_rfbCapabilityInfo)) {
++ return False;
++ }
++ msginfo.code = Swap32IfLE(msginfo.code);
++ CapsEnable(caps, &msginfo);
++ }
+
+- return True;
++ return True;
+ }
+
+
+@@ -729,6 +801,10 @@
Bool requestCompressLevel = False;
Bool requestQualityLevel = False;
Bool requestLastRectEncoding = False;
+ Bool requestNewFBSizeEncoding = True;
++ Bool requestTextChatEncoding = True;
+
-+ fprintf(stderr, "SetFormatAndEncodings: sent_FBU state: %2d\n", sent_FBU);
-+#if 0
-+ if (sent_FBU == 1 || sent_FBU == 2) {
-+ int i;
-+ skip_XtUpdate = 1;
-+ for (i=0; i<10; i++) {
-+ Bool result = HandleRFBServerMessage();
-+ fprintf(stderr, "--------: %2d\n", sent_FBU);
-+ if (sent_FBU == 0) {
-+ break;
-+ }
-+ }
-+ skip_XtUpdate = 0;
-+ }
-+#endif
++// fprintf(stderr, "SetFormatAndEncodings: sent_FBU state: %2d\n", sent_FBU);
spf.type = rfbSetPixelFormat;
spf.format = myFormat;
-@@ -736,6 +776,7 @@
+@@ -736,6 +812,7 @@
spf.format.greenMax = Swap16IfLE(spf.format.greenMax);
spf.format.blueMax = Swap16IfLE(spf.format.blueMax);
@@ -1823,7 +3699,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
if (!WriteExact(rfbsock, (char *)&spf, sz_rfbSetPixelFormatMsg))
return False;
-@@ -754,6 +795,12 @@
+@@ -754,6 +831,12 @@
encStrLen = strlen(encStr);
}
@@ -1836,16 +3712,18 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
if (strncasecmp(encStr,"raw",encStrLen) == 0) {
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingRaw);
} else if (strncasecmp(encStr,"copyrect",encStrLen) == 0) {
-@@ -775,6 +822,8 @@
+@@ -775,6 +858,10 @@
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingCoRRE);
} else if (strncasecmp(encStr,"rre",encStrLen) == 0) {
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingRRE);
+ } else if (strncasecmp(encStr,"zrle",encStrLen) == 0) {
+ encs[se->nEncodings++] = Swap32IfLE(rfbEncodingZRLE);
++ } else if (strncasecmp(encStr,"zywrle",encStrLen) == 0) {
++ encs[se->nEncodings++] = Swap32IfLE(rfbEncodingZYWRLE);
} else {
fprintf(stderr,"Unknown encoding '%.*s'\n",encStrLen,encStr);
}
-@@ -797,7 +846,7 @@
+@@ -797,7 +884,7 @@
if (appData.useRemoteCursor) {
if (se->nEncodings < MAX_ENCODINGS)
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingXCursor);
@@ -1854,7 +3732,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingRichCursor);
if (se->nEncodings < MAX_ENCODINGS)
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingPointerPos);
-@@ -806,10 +855,14 @@
+@@ -806,10 +893,14 @@
if (se->nEncodings < MAX_ENCODINGS && requestLastRectEncoding) {
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingLastRect);
}
@@ -1870,7 +3748,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
fprintf(stderr,"Same machine: preferring raw encoding\n");
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingRaw);
} else {
-@@ -819,6 +872,7 @@
+@@ -819,6 +910,7 @@
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingCopyRect);
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingTight);
@@ -1878,7 +3756,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingHextile);
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingZlib);
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingCoRRE);
-@@ -844,11 +898,14 @@
+@@ -844,11 +936,14 @@
if (appData.useRemoteCursor) {
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingXCursor);
@@ -1894,104 +3772,854 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
}
len = sz_rfbSetEncodingsMsg + se->nEncodings * 4;
-@@ -889,6 +946,12 @@
- fur.w = Swap16IfLE(w);
- fur.h = Swap16IfLE(h);
+@@ -868,8 +963,8 @@
+ Bool
+ SendIncrementalFramebufferUpdateRequest()
+ {
+- return SendFramebufferUpdateRequest(0, 0, si.framebufferWidth,
+- si.framebufferHeight, True);
++ return SendFramebufferUpdateRequest(0, 0, si.framebufferWidth,
++ si.framebufferHeight, True);
+ }
+
+@@ -880,19 +975,26 @@
+ Bool
+ SendFramebufferUpdateRequest(int x, int y, int w, int h, Bool incremental)
+ {
+- rfbFramebufferUpdateRequestMsg fur;
++ rfbFramebufferUpdateRequestMsg fur;
+
+- fur.type = rfbFramebufferUpdateRequest;
+- fur.incremental = incremental ? 1 : 0;
+- fur.x = Swap16IfLE(x);
+- fur.y = Swap16IfLE(y);
+- fur.w = Swap16IfLE(w);
+- fur.h = Swap16IfLE(h);
++ fur.type = rfbFramebufferUpdateRequest;
++ fur.incremental = incremental ? 1 : 0;
++ fur.x = Swap16IfLE(x);
++ fur.y = Swap16IfLE(y);
++ fur.w = Swap16IfLE(w);
++ fur.h = Swap16IfLE(h);
++
+ if (incremental) {
+ sent_FBU = 1;
+ } else {
+ sent_FBU = 2;
+ }
+
+- if (!WriteExact(rfbsock, (char *)&fur, sz_rfbFramebufferUpdateRequestMsg))
+- return False;
++ if (!WriteExact(rfbsock, (char *)&fur, sz_rfbFramebufferUpdateRequestMsg)) {
++ return False;
++ }
+
+- return True;
++ return True;
+ }
+
+
+@@ -903,19 +1005,20 @@
+ Bool
+ SendPointerEvent(int x, int y, int buttonMask)
+ {
+- rfbPointerEventMsg pe;
++ rfbPointerEventMsg pe;
+
+- pe.type = rfbPointerEvent;
+- pe.buttonMask = buttonMask;
+- if (x < 0) x = 0;
+- if (y < 0) y = 0;
+-
+- if (!appData.useX11Cursor)
+- SoftCursorMove(x, y);
+-
+- pe.x = Swap16IfLE(x);
+- pe.y = Swap16IfLE(y);
+- return WriteExact(rfbsock, (char *)&pe, sz_rfbPointerEventMsg);
++ pe.type = rfbPointerEvent;
++ pe.buttonMask = buttonMask;
++ if (x < 0) x = 0;
++ if (y < 0) y = 0;
++
++ if (!appData.useX11Cursor) {
++ SoftCursorMove(x, y);
++ }
+
- if (!WriteExact(rfbsock, (char *)&fur, sz_rfbFramebufferUpdateRequestMsg))
- return False;
++ pe.x = Swap16IfLE(x);
++ pe.y = Swap16IfLE(y);
++ return WriteExact(rfbsock, (char *)&pe, sz_rfbPointerEventMsg);
+ }
+
-@@ -955,6 +1018,10 @@
+@@ -926,12 +1029,12 @@
+ Bool
+ SendKeyEvent(CARD32 key, Bool down)
+ {
+- rfbKeyEventMsg ke;
++ rfbKeyEventMsg ke;
+
+- ke.type = rfbKeyEvent;
+- ke.down = down ? 1 : 0;
+- ke.key = Swap32IfLE(key);
+- return WriteExact(rfbsock, (char *)&ke, sz_rfbKeyEventMsg);
++ ke.type = rfbKeyEvent;
++ ke.down = down ? 1 : 0;
++ ke.key = Swap32IfLE(key);
++ return WriteExact(rfbsock, (char *)&ke, sz_rfbKeyEventMsg);
+ }
+
+
+@@ -942,281 +1045,551 @@
+ Bool
+ SendClientCutText(char *str, int len)
+ {
+- rfbClientCutTextMsg cct;
++ rfbClientCutTextMsg cct;
++
++ if (serverCutText) {
++ free(serverCutText);
++ }
++ serverCutText = NULL;
+
+- if (serverCutText)
+- free(serverCutText);
+- serverCutText = NULL;
+-
+- cct.type = rfbClientCutText;
+- cct.length = Swap32IfLE(len);
+- return (WriteExact(rfbsock, (char *)&cct, sz_rfbClientCutTextMsg) &&
+- WriteExact(rfbsock, str, len));
++ cct.type = rfbClientCutText;
++ cct.length = Swap32IfLE(len);
++ return (WriteExact(rfbsock, (char *)&cct, sz_rfbClientCutTextMsg) &&
++ WriteExact(rfbsock, str, len));
}
++Bool
++SendServerScale(int nfac)
++{
++ rfbSetScaleMsg ssc;
++ if (nfac < 0 || nfac > 100) {
++ return True;
++ }
+
+-/*
+- * HandleRFBServerMessage.
+- */
++ ssc.type = rfbSetScale;
++ ssc.scale = nfac;
++ return WriteExact(rfbsock, (char *)&ssc, sz_rfbSetScaleMsg);
++}
+ Bool
+-HandleRFBServerMessage()
++SendServerInput(Bool enabled)
+ {
+- rfbServerToClientMsg msg;
++ rfbSetServerInputMsg sim;
+
+- if (!ReadFromRFBServer((char *)&msg, 1))
+- return False;
++ sim.type = rfbSetServerInput;
++ sim.status = enabled;
++ return WriteExact(rfbsock, (char *)&sim, sz_rfbSetServerInputMsg);
++}
+
+- switch (msg.type) {
++Bool
++SendSingleWindow(int x, int y)
++{
++ rfbSetSWMsg sw;
+
+- case rfbSetColourMapEntries:
+- {
+- int i;
+- CARD16 rgb[3];
+- XColor xc;
++ if (x == -1 && y == -1) {
++ sw.type = rfbSetSW;
++ sw.x = Swap16IfLE(1);
++ sw.y = Swap16IfLE(1);
++ } else {
++ sw.type = rfbSetSW;
++ sw.x = Swap16IfLE(x);
++ sw.y = Swap16IfLE(y);
++ }
++ sw.status = True;
++ return WriteExact(rfbsock, (char *)&sw, sz_rfbSetSWMsg);
++}
+
+- if (!ReadFromRFBServer(((char *)&msg) + 1,
+- sz_rfbSetColourMapEntriesMsg - 1))
+- return False;
++Bool
++SendTextChat(char *str)
++{
++ rfbTextChatMsg chat;
++ chat.type = rfbTextChat;
++ chat.pad1 = 0;
++ chat.pad2 = 0;
++ chat.length = (unsigned int) strlen(str);
++//fprintf(stderr, "Sending: %d %s\n", chat.length, str);
++ chat.length = Swap32IfLE(chat.length);
++ if (!WriteExact(rfbsock, (char *)&chat, sz_rfbTextChatMsg)) {
++ return False;
++ }
++ return WriteExact(rfbsock, str, strlen(str));
++}
+
+- msg.scme.firstColour = Swap16IfLE(msg.scme.firstColour);
+- msg.scme.nColours = Swap16IfLE(msg.scme.nColours);
++extern void raiseme(void);
+
+- for (i = 0; i < msg.scme.nColours; i++) {
+- if (!ReadFromRFBServer((char *)rgb, 6))
+- return False;
+- xc.pixel = msg.scme.firstColour + i;
+- xc.red = Swap16IfLE(rgb[0]);
+- xc.green = Swap16IfLE(rgb[1]);
+- xc.blue = Swap16IfLE(rgb[2]);
+- xc.flags = DoRed|DoGreen|DoBlue;
+- XStoreColor(dpy, cmap, &xc);
+- }
+-
+- break;
+- }
++Bool
++SendTextChatOpen(void)
++{
++ raiseme();
++ rfbTextChatMsg chat;
++ chat.type = rfbTextChat;
++ chat.pad1 = 0;
++ chat.pad2 = 0;
++ chat.length = Swap32IfLE(rfbTextChatOpen);
++ return WriteExact(rfbsock, (char *)&chat, sz_rfbTextChatMsg);
++}
+
+- case rfbFramebufferUpdate:
+- {
+- rfbFramebufferUpdateRectHeader rect;
+- int linesToRead;
+- int bytesPerLine;
+- int i;
+- int usecs;
++Bool
++SendTextChatClose(void)
++{
++ rfbTextChatMsg chat;
++ chat.type = rfbTextChat;
++ chat.pad1 = 0;
++ chat.pad2 = 0;
++ chat.length = Swap32IfLE(rfbTextChatClose);
++ return WriteExact(rfbsock, (char *)&chat, sz_rfbTextChatMsg);
++}
+
+- if (!ReadFromRFBServer(((char *)&msg.fu) + 1,
+- sz_rfbFramebufferUpdateMsg - 1))
+- return False;
++Bool
++SendTextChatFinished(void)
++{
++ rfbTextChatMsg chat;
++ chat.type = rfbTextChat;
++ chat.pad1 = 0;
++ chat.pad2 = 0;
++ chat.length = Swap32IfLE(rfbTextChatFinished);
++ return WriteExact(rfbsock, (char *)&chat, sz_rfbTextChatMsg);
++}
++
+extern int do_format_change;
+extern int do_cursor_change;
+extern void cutover_format_change(void);
+
- /*
- * HandleRFBServerMessage.
- */
-@@ -1004,6 +1071,9 @@
- int i;
- int usecs;
++double dtime(double *t_old) {
++ /*
++ * usage: call with 0.0 to initialize, subsequent calls give
++ * the time difference since last call.
++ */
++ double t_now, dt;
++ struct timeval now;
++
++ gettimeofday(&now, NULL);
++ t_now = now.tv_sec + ( (double) now.tv_usec/1000000. );
++ if (*t_old == 0.0) {
++ *t_old = t_now;
++ return t_now;
++ }
++ dt = t_now - *t_old;
++ *t_old = t_now;
++ return(dt);
++}
+
+- msg.fu.nRects = Swap16IfLE(msg.fu.nRects);
++/* common dtime() activities: */
++double dtime0(double *t_old) {
++ *t_old = 0.0;
++ return dtime(t_old);
++}
+
+- for (i = 0; i < msg.fu.nRects; i++) {
+- if (!ReadFromRFBServer((char *)&rect, sz_rfbFramebufferUpdateRectHeader))
+- return False;
++double dnow(void) {
++ double t;
++ return dtime0(&t);
++}
+
+- rect.encoding = Swap32IfLE(rect.encoding);
+- if (rect.encoding == rfbEncodingLastRect)
+- break;
+
+- rect.r.x = Swap16IfLE(rect.r.x);
+- rect.r.y = Swap16IfLE(rect.r.y);
+- rect.r.w = Swap16IfLE(rect.r.w);
+- rect.r.h = Swap16IfLE(rect.r.h);
+-
+- if (rect.encoding == rfbEncodingXCursor ||
+- rect.encoding == rfbEncodingRichCursor) {
+- if (!HandleCursorShape(rect.r.x, rect.r.y, rect.r.w, rect.r.h,
+- rect.encoding)) {
+- return False;
+- }
+- continue;
+- }
++/*
++ * HandleRFBServerMessage.
++ */
+
+- if (rect.encoding == rfbEncodingPointerPos) {
+- if (!HandleCursorPos(rect.r.x, rect.r.y)) {
+- return False;
+- }
+- continue;
+- }
++Bool
++HandleRFBServerMessage()
++{
++ int db = 0;
++ rfbServerToClientMsg msg;
+
+- if ((rect.r.x + rect.r.w > si.framebufferWidth) ||
+- (rect.r.y + rect.r.h > si.framebufferHeight))
+- {
+- fprintf(stderr,"Rect too large: %dx%d at (%d, %d)\n",
+- rect.r.w, rect.r.h, rect.r.x, rect.r.y);
+- return False;
++ if (!ReadFromRFBServer((char *)&msg, 1)) {
++ return False;
+ }
+
+- if (rect.r.h * rect.r.w == 0) {
+- fprintf(stderr,"Zero size rect - ignoring\n");
+- continue;
+- }
+-
+- /* If RichCursor encoding is used, we should prevent collisions
+- between framebuffer updates and cursor drawing operations. */
+- SoftCursorLockArea(rect.r.x, rect.r.y, rect.r.w, rect.r.h);
++ switch (msg.type) {
+
+- switch (rect.encoding) {
+-
+- case rfbEncodingRaw:
++ case rfbSetColourMapEntries:
++ {
++ int i;
++ CARD16 rgb[3];
++ XColor xc;
+
+- bytesPerLine = rect.r.w * myFormat.bitsPerPixel / 8;
+- linesToRead = BUFFER_SIZE / bytesPerLine;
++ if (!ReadFromRFBServer(((char *)&msg) + 1, sz_rfbSetColourMapEntriesMsg - 1)) {
++ return False;
++ }
+
+- while (rect.r.h > 0) {
+- if (linesToRead > rect.r.h)
+- linesToRead = rect.r.h;
++ msg.scme.firstColour = Swap16IfLE(msg.scme.firstColour);
++ msg.scme.nColours = Swap16IfLE(msg.scme.nColours);
+
+- if (!ReadFromRFBServer(buffer,bytesPerLine * linesToRead))
+- return False;
++ for (i = 0; i < msg.scme.nColours; i++) {
++ if (!ReadFromRFBServer((char *)rgb, 6)) {
++ return False;
++ }
++ xc.pixel = msg.scme.firstColour + i;
++ xc.red = Swap16IfLE(rgb[0]);
++ xc.green = Swap16IfLE(rgb[1]);
++ xc.blue = Swap16IfLE(rgb[2]);
++ if (appData.useGreyScale) {
++ int ave = (xc.red + xc.green + xc.blue)/3;
++ xc.red = ave;
++ xc.green = ave;
++ xc.blue = ave;
++ }
++ xc.flags = DoRed|DoGreen|DoBlue;
++ XStoreColor(dpy, cmap, &xc);
++ }
+- CopyDataToScreen(buffer, rect.r.x, rect.r.y, rect.r.w,
+- linesToRead);
++ break;
++ }
+
+- rect.r.h -= linesToRead;
+- rect.r.y += linesToRead;
++ case rfbFramebufferUpdate:
++ {
++ rfbFramebufferUpdateRectHeader rect;
++ int linesToRead;
++ int bytesPerLine;
++ int i;
++ int usecs;
++
++ int area_copyrect = 0;
++ int area_tight = 0;
++ int area_zrle = 0;
++ int area_raw = 0;
++ if (db) fprintf(stderr, "FBU-0: %.6f\n", dnow());
+
+- }
+- break;
+ int skip_incFBU = 0;
+ sent_FBU = -1;
-+
- if (!ReadFromRFBServer(((char *)&msg.fu) + 1,
- sz_rfbFramebufferUpdateMsg - 1))
- return False;
-@@ -1038,6 +1108,16 @@
+
+- case rfbEncodingCopyRect:
+- {
+- rfbCopyRect cr;
+-
+- if (!ReadFromRFBServer((char *)&cr, sz_rfbCopyRect))
+- return False;
+-
+- cr.srcX = Swap16IfLE(cr.srcX);
+- cr.srcY = Swap16IfLE(cr.srcY);
+-
+- /* If RichCursor encoding is used, we should extend our
+- "cursor lock area" (previously set to destination
+- rectangle) to the source rectangle as well. */
+- SoftCursorLockArea(cr.srcX, cr.srcY, rect.r.w, rect.r.h);
+-
+- if (appData.copyRectDelay != 0) {
+- XFillRectangle(dpy, desktopWin, srcGC, cr.srcX, cr.srcY,
+- rect.r.w, rect.r.h);
+- XFillRectangle(dpy, desktopWin, dstGC, rect.r.x, rect.r.y,
+- rect.r.w, rect.r.h);
+- XSync(dpy,False);
+- usleep(appData.copyRectDelay * 1000);
+- XFillRectangle(dpy, desktopWin, dstGC, rect.r.x, rect.r.y,
+- rect.r.w, rect.r.h);
+- XFillRectangle(dpy, desktopWin, srcGC, cr.srcX, cr.srcY,
+- rect.r.w, rect.r.h);
++ if (!ReadFromRFBServer(((char *)&msg.fu) + 1, sz_rfbFramebufferUpdateMsg - 1)) {
++ return False;
}
- continue;
- }
-+ if (rect.encoding == rfbEncodingNewFBSize) {
-+ fprintf(stderr,"New Size: %dx%d at (%d, %d)\n",
-+ rect.r.w, rect.r.h, rect.r.x, rect.r.y);
-+ si.framebufferWidth = rect.r.w;
-+ si.framebufferHeight = rect.r.h;
-+ fprintf(stderr, "si: %d %d\n", si.framebufferWidth, si.framebufferHeight);
-+ ReDoDesktop();
-+
-+ continue;
-+ }
- if ((rect.r.x + rect.r.w > si.framebufferWidth) ||
- (rect.r.y + rect.r.h > si.framebufferHeight))
-@@ -1208,6 +1288,42 @@
- break;
- }
+- XCopyArea(dpy, desktopWin, desktopWin, gc, cr.srcX, cr.srcY,
+- rect.r.w, rect.r.h, rect.r.x, rect.r.y);
++ msg.fu.nRects = Swap16IfLE(msg.fu.nRects);
-+/* runge adds zrle: */
-+ case rfbEncodingZRLE:
-+ {
-+ switch (myFormat.bitsPerPixel) {
-+ case 8:
-+ if (!HandleZRLE8(rect.r.x,rect.r.y,rect.r.w,rect.r.h))
-+ return False;
-+ break;
-+ case 16:
-+ if (!HandleZRLE16(rect.r.x,rect.r.y,rect.r.w,rect.r.h))
-+ return False;
-+ break;
-+ case 32:
-+ {
-+ unsigned int maxColor=(myFormat.redMax<<myFormat.redShift)|
-+ (myFormat.greenMax<<myFormat.greenShift)|
-+ (myFormat.blueMax<<myFormat.blueShift);
-+ if ((myFormat.bigEndian && (maxColor&0xff)==0) ||
-+ (!myFormat.bigEndian && (maxColor&0xff000000)==0)) {
-+ if (!HandleZRLE24(rect.r.x,rect.r.y,rect.r.w,rect.r.h))
-+ return False;
-+ } else if (!myFormat.bigEndian && (maxColor&0xff)==0) {
-+ if (!HandleZRLE24Up(rect.r.x,rect.r.y,rect.r.w,rect.r.h))
-+ return False;
-+ } else if (myFormat.bigEndian && (maxColor&0xff000000)==0) {
-+ if (!HandleZRLE24Down(rect.r.x,rect.r.y,rect.r.w,rect.r.h))
-+ return False;
-+ } else if (!HandleZRLE32(rect.r.x,rect.r.y,rect.r.w,rect.r.h))
-+ return False;
-+ break;
-+ }
-+ }
-+ break;
-+ }
+- break;
+- }
++ for (i = 0; i < msg.fu.nRects; i++) {
++ if (!ReadFromRFBServer((char *)&rect, sz_rfbFramebufferUpdateRectHeader)) {
++ return False;
++ }
+
++ rect.encoding = Swap32IfLE(rect.encoding);
++ if (rect.encoding == rfbEncodingLastRect) {
++ break;
++ }
+
- default:
- fprintf(stderr,"Unknown rect encoding %d\n",
- (int)rect.encoding);
-@@ -1217,6 +1333,28 @@
- /* Now we may discard "soft cursor locks". */
- SoftCursorUnlockScreen();
- }
++ rect.r.x = Swap16IfLE(rect.r.x);
++ rect.r.y = Swap16IfLE(rect.r.y);
++ rect.r.w = Swap16IfLE(rect.r.w);
++ rect.r.h = Swap16IfLE(rect.r.h);
++
++ if (rect.encoding == rfbEncodingXCursor || rect.encoding == rfbEncodingRichCursor) {
++ if (db) fprintf(stderr, "FBU-Cur1 %.6f\n", dnow());
++ if (!HandleCursorShape(rect.r.x, rect.r.y, rect.r.w, rect.r.h, rect.encoding)) {
++ return False;
++ }
++ if (db) fprintf(stderr, "FBU-Cur2 %.6f\n", dnow());
++ continue;
++ }
++
++ if (rect.encoding == rfbEncodingPointerPos) {
++ if (db) fprintf(stderr, "FBU-Pos1 %.6f\n", dnow());
++ if (!HandleCursorPos(rect.r.x, rect.r.y)) {
++ return False;
++ }
++ if (db) fprintf(stderr, "FBU-Pos2 %.6f\n", dnow());
++ continue;
++ }
++ if (rect.encoding == rfbEncodingNewFBSize) {
++ fprintf(stderr,"New Size: %dx%d at (%d, %d)\n", rect.r.w, rect.r.h, rect.r.x, rect.r.y);
++ si.framebufferWidth = rect.r.w;
++ si.framebufferHeight = rect.r.h;
++ //fprintf(stderr, "si: %d %d\n", si.framebufferWidth, si.framebufferHeight);
++ ReDoDesktop();
++ continue;
++ }
++
++ if ((rect.r.x + rect.r.w > si.framebufferWidth) ||
++ (rect.r.y + rect.r.h > si.framebufferHeight)) {
++ fprintf(stderr,"Rect too large: %dx%d at (%d, %d)\n",
++ rect.r.w, rect.r.h, rect.r.x, rect.r.y);
++ return False;
++ }
++
++ if (rect.r.h * rect.r.w == 0) {
++ fprintf(stderr,"Zero size rect - ignoring\n");
++ continue;
++ }
++
++ /* If RichCursor encoding is used, we should prevent collisions
++ between framebuffer updates and cursor drawing operations. */
++ if (db) fprintf(stderr, "FBU-SCL1 %.6f\n", dnow());
++
++ SoftCursorLockArea(rect.r.x, rect.r.y, rect.r.w, rect.r.h);
++
++ if (db) fprintf(stderr, "FBU-SCL2 %.6f\n", dnow());
++
++ switch (rect.encoding) {
++
++ case rfbEncodingRaw:
++
++ bytesPerLine = rect.r.w * myFormat.bitsPerPixel / 8;
++ linesToRead = BUFFER_SIZE / bytesPerLine;
++
++ if (db) fprintf(stderr, "Raw: %dx%d+%d+%d\n", rect.r.w, rect.r.h, rect.r.x, rect.r.y);
++ area_raw += rect.r.w * rect.r.h;
++
++ while (rect.r.h > 0) {
++ if (linesToRead > rect.r.h) {
++ linesToRead = rect.r.h;
++ }
++
++ if (!ReadFromRFBServer(buffer,bytesPerLine * linesToRead)) {
++ return False;
++ }
++
++ CopyDataToScreen(buffer, rect.r.x, rect.r.y, rect.r.w, linesToRead);
++
++ rect.r.h -= linesToRead;
++ rect.r.y += linesToRead;
++ }
++ break;
++
++ case rfbEncodingCopyRect:
++ {
++ rfbCopyRect cr;
++
++ if (!ReadFromRFBServer((char *)&cr, sz_rfbCopyRect)) {
++ return False;
++ }
++
++ cr.srcX = Swap16IfLE(cr.srcX);
++ cr.srcY = Swap16IfLE(cr.srcY);
++
++ if (db) fprintf(stderr, "Copy: %dx%d+%d+%d\n", rect.r.w, rect.r.h, rect.r.x, rect.r.y);
++ area_copyrect += rect.r.w * rect.r.h;
++
++ /* If RichCursor encoding is used, we should extend our
++ "cursor lock area" (previously set to destination
++ rectangle) to the source rectangle as well. */
++
++ if (db) fprintf(stderr, "FBU-SCL3 %.6f\n", dnow());
++
++ SoftCursorLockArea(cr.srcX, cr.srcY, rect.r.w, rect.r.h);
++
++ if (db) fprintf(stderr, "FBU-SCL4 %.6f\n", dnow());
++
++ if (appData.copyRectDelay != 0) {
++ XFillRectangle(dpy, desktopWin, srcGC, cr.srcX, cr.srcY, rect.r.w, rect.r.h);
++ XFillRectangle(dpy, desktopWin, dstGC, rect.r.x, rect.r.y, rect.r.w, rect.r.h);
++ XSync(dpy,False);
++ usleep(appData.copyRectDelay * 1000);
++ XFillRectangle(dpy, desktopWin, dstGC, rect.r.x, rect.r.y, rect.r.w, rect.r.h);
++ XFillRectangle(dpy, desktopWin, srcGC, cr.srcX, cr.srcY, rect.r.w, rect.r.h);
++ }
++
++ if (db) fprintf(stderr, "FBU-CPA1 %.6f\n", dnow());
++ if (!appData.useBackingstore) {
++ copy_rect(rect.r.x, rect.r.y, rect.r.w, rect.r.h, cr.srcX, cr.srcY);
++ put_image(rect.r.x, rect.r.y, rect.r.x, rect.r.y, rect.r.w, rect.r.h);
++ XSync(dpy, False);
++ } else {
++ XCopyArea(dpy, desktopWin, desktopWin, gc, cr.srcX, cr.srcY,
++ rect.r.w, rect.r.h, rect.r.x, rect.r.y);
++ }
++ if (db) fprintf(stderr, "FBU-CPA2 %.6f\n", dnow());
++
++ break;
++ }
++
++ case rfbEncodingRRE:
++ {
++ switch (myFormat.bitsPerPixel) {
++ case 8:
++ if (!HandleRRE8(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) {
++ return False;
++ }
++ break;
++ case 16:
++ if (!HandleRRE16(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) {
++ return False;
++ }
++ break;
++ case 32:
++ if (!HandleRRE32(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) {
++ return False;
++ }
++ break;
++ }
++ break;
++ }
++
++ case rfbEncodingCoRRE:
++ {
++ switch (myFormat.bitsPerPixel) {
++ case 8:
++ if (!HandleCoRRE8(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) {
++ return False;
++ }
++ break;
++ case 16:
++ if (!HandleCoRRE16(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) {
++ return False;
++ }
++ break;
++ case 32:
++ if (!HandleCoRRE32(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) {
++ return False;
++ }
++ break;
++ }
++ break;
++ }
++
++ case rfbEncodingHextile:
++ {
++ switch (myFormat.bitsPerPixel) {
++ case 8:
++ if (!HandleHextile8(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) {
++ return False;
++ }
++ break;
++ case 16:
++ if (!HandleHextile16(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) {
++ return False;
++ }
++ break;
++ case 32:
++ if (!HandleHextile32(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) {
++ return False;
++ }
++ break;
++ }
++ break;
++ }
++
++ case rfbEncodingZlib:
++ {
++ switch (myFormat.bitsPerPixel) {
++ case 8:
++ if (!HandleZlib8(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) {
++ return False;
++ }
++ break;
++ case 16:
++ if (!HandleZlib16(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) {
++ return False;
++ }
++ break;
++ case 32:
++ if (!HandleZlib32(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) {
++ return False;
++ }
++ break;
++ }
++ break;
++ }
++
++ case rfbEncodingTight:
++ {
++ if (db) fprintf(stderr, "Tight: %dx%d+%d+%d\n", rect.r.w, rect.r.h, rect.r.x, rect.r.y);
++ area_tight += rect.r.w * rect.r.h;
++ if (db) fprintf(stderr, "FBU-TGH1 %.6f\n", dnow());
++
++ switch (myFormat.bitsPerPixel) {
++ case 8:
++ if (!HandleTight8(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) {
++ return False;
++ }
++ break;
++ case 16:
++ if (!HandleTight16(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) {
++ return False;
++ }
++ break;
++ case 32:
++ if (!HandleTight32(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) {
++ return False;
++ }
++ break;
++ }
++ if (db) fprintf(stderr, "FBU-TGH2 %.6f\n", dnow());
++ break;
++ }
++
++ /* runge adds zrle and zywrle: */
++ case rfbEncodingZRLE:
++ {
++ if (db) fprintf(stderr, "ZRLE: %dx%d+%d+%d\n", rect.r.w, rect.r.h, rect.r.x, rect.r.y);
++ area_zrle += rect.r.w * rect.r.h;
++ switch (myFormat.bitsPerPixel) {
++ case 8:
++ if (!HandleZRLE8(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) {
++ return False;
++ }
++ break;
++ case 16:
++ if (!HandleZRLE16(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) {
++ return False;
++ }
++ break;
++ case 32:
++ {
++ unsigned int maxColor=(myFormat.redMax<<myFormat.redShift)|
++ (myFormat.greenMax<<myFormat.greenShift)|
++ (myFormat.blueMax<<myFormat.blueShift);
++ if ((myFormat.bigEndian && (maxColor&0xff)==0) || (!myFormat.bigEndian && (maxColor&0xff000000)==0)) {
++ if (!HandleZRLE24(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) {
++ return False;
++ }
++ } else if (!myFormat.bigEndian && (maxColor&0xff)==0) {
++ if (!HandleZRLE24Up(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) {
++ return False;
++ }
++ } else if (myFormat.bigEndian && (maxColor&0xff000000)==0) {
++ if (!HandleZRLE24Down(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) {
++ return False;
++ }
++ } else if (!HandleZRLE32(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) {
++ return False;
++ }
++ break;
++ }
++ }
++ break;
++ }
++
++ default:
++ fprintf(stderr,"Unknown rect encoding %d\n", (int)rect.encoding);
++ return False;
++ }
+
+- case rfbEncodingRRE:
+- {
+- switch (myFormat.bitsPerPixel) {
+- case 8:
+- if (!HandleRRE8(rect.r.x,rect.r.y,rect.r.w,rect.r.h))
+- return False;
+- break;
+- case 16:
+- if (!HandleRRE16(rect.r.x,rect.r.y,rect.r.w,rect.r.h))
+- return False;
+- break;
+- case 32:
+- if (!HandleRRE32(rect.r.x,rect.r.y,rect.r.w,rect.r.h))
+- return False;
+- break;
+- }
+- break;
+- }
++ /* Now we may discard "soft cursor locks". */
++ if (db) fprintf(stderr, "FBU-SUL1 %.6f\n", dnow());
+
+- case rfbEncodingCoRRE:
+- {
+- switch (myFormat.bitsPerPixel) {
+- case 8:
+- if (!HandleCoRRE8(rect.r.x,rect.r.y,rect.r.w,rect.r.h))
+- return False;
+- break;
+- case 16:
+- if (!HandleCoRRE16(rect.r.x,rect.r.y,rect.r.w,rect.r.h))
+- return False;
+- break;
+- case 32:
+- if (!HandleCoRRE32(rect.r.x,rect.r.y,rect.r.w,rect.r.h))
+- return False;
+- break;
+- }
+- break;
+- }
++ SoftCursorUnlockScreen();
+
+- case rfbEncodingHextile:
+- {
+- switch (myFormat.bitsPerPixel) {
+- case 8:
+- if (!HandleHextile8(rect.r.x,rect.r.y,rect.r.w,rect.r.h))
+- return False;
+- break;
+- case 16:
+- if (!HandleHextile16(rect.r.x,rect.r.y,rect.r.w,rect.r.h))
+- return False;
+- break;
+- case 32:
+- if (!HandleHextile32(rect.r.x,rect.r.y,rect.r.w,rect.r.h))
+- return False;
+- break;
++ if (db) fprintf(stderr, "FBU-SUL2 %.6f\n", dnow());
+ }
+- break;
+- }
+
+- case rfbEncodingZlib:
+- {
+- switch (myFormat.bitsPerPixel) {
+- case 8:
+- if (!HandleZlib8(rect.r.x,rect.r.y,rect.r.w,rect.r.h))
+- return False;
+- break;
+- case 16:
+- if (!HandleZlib16(rect.r.x,rect.r.y,rect.r.w,rect.r.h))
+- return False;
+- break;
+- case 32:
+- if (!HandleZlib32(rect.r.x,rect.r.y,rect.r.w,rect.r.h))
+- return False;
+- break;
++ if (1 || area_copyrect) {
++ if (db) fprintf(stderr, "FBU-XSN1 %.6f\n", dnow());
++ XSync(dpy, False);
++ if (db) fprintf(stderr, "FBU-XSN2 %.6f\n", dnow());
+ }
+- break;
+- }
+-
+- case rfbEncodingTight:
+- {
+- switch (myFormat.bitsPerPixel) {
+- case 8:
+- if (!HandleTight8(rect.r.x,rect.r.y,rect.r.w,rect.r.h))
+- return False;
+- break;
+- case 16:
+- if (!HandleTight16(rect.r.x,rect.r.y,rect.r.w,rect.r.h))
+- return False;
+- break;
+- case 32:
+- if (!HandleTight32(rect.r.x,rect.r.y,rect.r.w,rect.r.h))
+- return False;
+- break;
+ sent_FBU = 0;
+ /*
+ * we need to be careful since Xt events are processed
@@ -2013,26 +4641,195 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
+ si.framebufferHeight, False);
+ skip_incFBU = 1;
+ }
-+ }
+ }
+- break;
+- }
+-
+- default:
+- fprintf(stderr,"Unknown rect encoding %d\n",
+- (int)rect.encoding);
+- return False;
+- }
+-
+- /* Now we may discard "soft cursor locks". */
+- SoftCursorUnlockScreen();
+- }
#ifdef MITSHM
/* if using shared memory PutImage, make sure that the X server has
-@@ -1228,8 +1366,12 @@
- XSync(dpy, False);
- #endif
+@@ -1224,59 +1597,138 @@
+ mainly to avoid copyrect using invalid screen contents - not sure
+ if we'd need it otherwise. */
-- if (!SendIncrementalFramebufferUpdateRequest())
-- return False;
-+
+- if (appData.useShm)
+- XSync(dpy, False);
++ if (appData.useShm) {
++ XSync(dpy, False);
++ } else
+ #endif
++ {
++ XSync(dpy, False);
++ }
++
+ if (skip_XtUpdate || skip_incFBU) {
+ ;
+ } else if (!SendIncrementalFramebufferUpdateRequest()) {
+ return False;
+ }
- break;
+- if (!SendIncrementalFramebufferUpdateRequest())
+- return False;
+-
+- break;
++ break;
}
-@@ -1296,12 +1438,19 @@
+
+ case rfbBell:
+ {
+- Window toplevelWin;
++ Window toplevelWin;
+
+- XBell(dpy, 0);
++ XBell(dpy, 0);
+
+- if (appData.raiseOnBeep) {
+- toplevelWin = XtWindow(toplevel);
+- XMapRaised(dpy, toplevelWin);
++ if (appData.raiseOnBeep) {
++ toplevelWin = XtWindow(toplevel);
++ XMapRaised(dpy, toplevelWin);
++ }
++
++ break;
+ }
+
+- break;
+- }
++ case rfbServerCutText:
++ {
++ if (!ReadFromRFBServer(((char *)&msg) + 1, sz_rfbServerCutTextMsg - 1)) {
++ return False;
++ }
+
+- case rfbServerCutText:
+- {
+- if (!ReadFromRFBServer(((char *)&msg) + 1,
+- sz_rfbServerCutTextMsg - 1))
+- return False;
++ msg.sct.length = Swap32IfLE(msg.sct.length);
++
++ if (serverCutText) {
++ free(serverCutText);
++ }
+
+- msg.sct.length = Swap32IfLE(msg.sct.length);
++ serverCutText = malloc(msg.sct.length+1);
+
+- if (serverCutText)
+- free(serverCutText);
++ if (!ReadFromRFBServer(serverCutText, msg.sct.length)) {
++ return False;
++ }
+
+- serverCutText = malloc(msg.sct.length+1);
++ serverCutText[msg.sct.length] = 0;
+
+- if (!ReadFromRFBServer(serverCutText, msg.sct.length))
+- return False;
++ newServerCutText = True;
+
+- serverCutText[msg.sct.length] = 0;
++ break;
++ }
+
+- newServerCutText = True;
++ case rfbTextChat:
++ {
++ char *buffer = NULL;
++ if (!ReadFromRFBServer(((char *)&msg) + 1, sz_rfbTextChatMsg - 1)) {
++ return False;
++ }
++ msg.tc.length = Swap32IfLE(msg.tc.length);
++ switch(msg.tc.length) {
++ case rfbTextChatOpen:
++ fprintf(stderr, "\n*ChatOpen*\n\nSend: ");
++ raiseme();
++ appData.chatActive = True;
++ break;
++ case rfbTextChatClose:
++ fprintf(stderr, "\n*ChatClose*\n");
++ raiseme();
++ appData.chatActive = False;
++ break;
++ case rfbTextChatFinished:
++ fprintf(stderr, "\n*ChatFinished*\n");
++ appData.chatActive = False;
++ break;
++ default:
++ buffer = (char *)malloc(msg.tc.length+1);
++ if (!ReadFromRFBServer(buffer, msg.tc.length)) {
++ free(buffer);
++ return False;
++ }
++ buffer[msg.tc.length] = '\0';
++ appData.chatActive = True;
++ GotChatText(buffer, msg.tc.length);
++ free(buffer);
++ }
++ break;
++ }
+
+- break;
+- }
++ case rfbRestartConnection:
++ {
++ rfbRestartConnectionMsg rc;
++ int len;
++ char *rs_str;
++ char buf[5] = "\xff\xff\xff\xff";
++ fprintf(stderr, "rfbRestartConnection. type=%d\n", (int) rc.type);
++ if (!ReadFromRFBServer((char *)&rc + 1, sz_rfbRestartConnectionMsg - 1)) {
++ return False;
++ }
++ len = Swap32IfLE(rc.length);
++ fprintf(stderr, "rfbRestartConnection. pad1=%d\n", (int) rc.pad1);
++ fprintf(stderr, "rfbRestartConnection. pad2=%d\n", (int) rc.pad2);
++ fprintf(stderr, "rfbRestartConnection. len=%d\n", len);
++ if (len) {
++ rs_str = (char *)malloc(2*len);
++ if (!ReadFromRFBServer(rs_str, len)) {
++ return False;
++ }
++ restart_session_pw = rs_str;
++ restart_session_len = len;
++ }
++ if (!WriteExact(rfbsock, buf, 4)) {
++ return False;
++ }
++ InitialiseRFBConnection();
++ SetVisualAndCmap();
++ SetFormatAndEncodings();
++ DesktopCursorOff();
++ SendFramebufferUpdateRequest(0, 0, si.framebufferWidth, si.framebufferHeight, False);
+
+- default:
+- fprintf(stderr,"Unknown message type %d from VNC server\n",msg.type);
+- return False;
+- }
++ break;
++ }
+
+- return True;
++ default:
++ fprintf(stderr,"Unknown message type %d from VNC server\n",msg.type);
++ return False;
++ }
++
++ return True;
+ }
+
+
+@@ -1296,12 +1748,19 @@
#define CONCAT2(a,b) a##b
#define CONCAT2E(a,b) CONCAT2(a,b)
@@ -2052,7 +4849,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
#undef BPP
#define BPP 16
#include "rre.c"
-@@ -1309,6 +1458,7 @@
+@@ -1309,6 +1768,7 @@
#include "hextile.c"
#include "zlib.c"
#include "tight.c"
@@ -2060,7 +4857,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
#undef BPP
#define BPP 32
#include "rre.c"
-@@ -1316,6 +1466,15 @@
+@@ -1316,6 +1776,15 @@
#include "hextile.c"
#include "zlib.c"
#include "tight.c"
@@ -2076,10 +4873,145 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
#undef BPP
/*
+@@ -1463,3 +1932,115 @@
+ cinfo->src = &jpegSrcManager;
+ }
+
++#define DO_ZYWRLE 0
++#if DO_ZYWRLE
++
++#define ZYWRLE_ENDIAN ENDIAN_LITTLE
++
++#undef END_FIX
++#if ZYWRLE_ENDIAN == ENDIAN_LITTLE
++# define END_FIX LE
++#elif ZYWRLE_ENDIAN == ENDIAN_BIG
++# define END_FIX BE
++#else
++# define END_FIX NE
++#endif
++#define ZYWRLE_DECODE
++
++#ifndef __RFB_CONCAT2E
++#define __RFB_CONCAT2(a,b) a##b
++#define __RFB_CONCAT2E(a,b) __RFB_CONCAT2(a,b)
++#endif
++
++#ifndef __RFB_CONCAT3E
++#define __RFB_CONCAT3(a,b,c) a##b##c
++#define __RFB_CONCAT3E(a,b,c) __RFB_CONCAT3(a,b,c)
++#endif
++
++#undef END_FIX
++#if ZYWRLE_ENDIAN == ENDIAN_LITTLE
++# define END_FIX LE
++#elif ZYWRLE_ENDIAN == ENDIAN_BIG
++# define END_FIX BE
++#else
++# define END_FIX NE
++#endif
++
++#include "zrletypes.h"
++#include "zrlepalettehelper.h"
++
++#if 0
++typedef unsigned short uint16_t;
++typedef unsigned int uint32_t;
++
++#ifdef CPIXEL
++#define PIXEL_T __RFB_CONCAT3E(uint,BPP,_t)
++#define zrleOutStreamWRITE_PIXEL __RFB_CONCAT2E(zrleOutStreamWriteOpaque,CPIXEL)
++#define ZRLE_ENCODE __RFB_CONCAT3E(zrleEncode,CPIXEL,END_FIX)
++#define ZRLE_ENCODE_TILE __RFB_CONCAT3E(zrleEncodeTile,CPIXEL,END_FIX)
++#define BPPOUT 24
++#elif BPP==15
++#define PIXEL_T __RFB_CONCAT3E(uint,16,_t)
++#define zrleOutStreamWRITE_PIXEL __RFB_CONCAT2E(zrleOutStreamWriteOpaque,16)
++#define ZRLE_ENCODE __RFB_CONCAT3E(zrleEncode,BPP,END_FIX)
++#define ZRLE_ENCODE_TILE __RFB_CONCAT3E(zrleEncodeTile,BPP,END_FIX)
++#define BPPOUT 16
++#else
++#define PIXEL_T __RFB_CONCAT3E(uint,BPP,_t)
++#define zrleOutStreamWRITE_PIXEL __RFB_CONCAT2E(zrleOutStreamWriteOpaque,BPP)
++#define ZRLE_ENCODE __RFB_CONCAT3E(zrleEncode,BPP,END_FIX)
++#define ZRLE_ENCODE_TILE __RFB_CONCAT3E(zrleEncodeTile,BPP,END_FIX)
++#define BPPOUT BPP
++#endif
++
++#else
++
++#ifdef CPIXEL
++#define PIXEL_T __RFB_CONCAT2E(zrle_U,BPP)
++#define zrleOutStreamWRITE_PIXEL __RFB_CONCAT2E(zrleOutStreamWriteOpaque,CPIXEL)
++#define ZRLE_ENCODE __RFB_CONCAT3E(zrleEncode,CPIXEL,END_FIX)
++#define ZRLE_ENCODE_TILE __RFB_CONCAT3E(zrleEncodeTile,CPIXEL,END_FIX)
++#define BPPOUT 24
++#elif BPP==15
++#define PIXEL_T __RFB_CONCAT2E(zrle_U,16)
++#define zrleOutStreamWRITE_PIXEL __RFB_CONCAT2E(zrleOutStreamWriteOpaque,16)
++#define ZRLE_ENCODE __RFB_CONCAT3E(zrleEncode,BPP,END_FIX)
++#define ZRLE_ENCODE_TILE __RFB_CONCAT3E(zrleEncodeTile,BPP,END_FIX)
++#define BPPOUT 16
++#else
++#define PIXEL_T __RFB_CONCAT2E(zrle_U,BPP)
++#define zrleOutStreamWRITE_PIXEL __RFB_CONCAT2E(zrleOutStreamWriteOpaque,BPP)
++#define ZRLE_ENCODE __RFB_CONCAT3E(zrleEncode,BPP,END_FIX)
++#define ZRLE_ENCODE_TILE __RFB_CONCAT3E(zrleEncodeTile,BPP,END_FIX)
++#define BPPOUT BPP
++#endif
++
++#endif
++
++#ifndef ZRLE_ONCE
++#define ZRLE_ONCE
++
++static const int bitsPerPackedPixel[] = {
++ 0, 1, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4
++};
++
++int zywrle_level;
++int zywrleBuf[rfbZRLETileWidth*rfbZRLETileHeight];
++
++static zrlePaletteHelper paletteHelper;
++
++#endif /* ZRLE_ONCE */
++
++#if 0
++void ZRLE_ENCODE_TILE (PIXEL_T* data, int w, int h, zrleOutStream* os);
++#endif
++
++#define BPP 16
++#include "zywrletemplate.c"
++#undef BPP
++#define BPP 32
++#include "zywrletemplate.c"
++#undef BPP
++
++#endif /* DO_ZYWRLE */
++
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rre.c vnc_unixsrc/vncviewer/rre.c
--- vnc_unixsrc.orig/vncviewer/rre.c 2000-06-11 08:00:53.000000000 -0400
-+++ vnc_unixsrc/vncviewer/rre.c 2007-02-03 20:45:57.000000000 -0500
-@@ -49,8 +49,12 @@
++++ vnc_unixsrc/vncviewer/rre.c 2007-02-17 22:52:24.000000000 -0500
+@@ -29,6 +29,18 @@
+ #define HandleRREBPP CONCAT2E(HandleRRE,BPP)
+ #define CARDBPP CONCAT2E(CARD,BPP)
+
++#define FillRectangle(x, y, w, h, color) \
++ { \
++ XGCValues _gcv; \
++ _gcv.foreground = color; \
++ if (!appData.useBackingstore) { \
++ FillScreen(x, y, w, h, _gcv.foreground); \
++ } else { \
++ XChangeGC(dpy, gc, GCForeground, &_gcv); \
++ XFillRectangle(dpy, desktopWin, gc, x, y, w, h); \
++ } \
++ }
++
+ static Bool
+ HandleRREBPP (int rx, int ry, int rw, int rh)
+ {
+@@ -49,11 +61,19 @@
#if (BPP == 8)
gcv.foreground = (appData.useBGR233 ? BGR233ToPixel[pix] : pix);
#else
@@ -2090,9 +5022,16 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rre.c vnc_unixsrc/vncviewer/r
#endif
+#endif
++#if 0
XChangeGC(dpy, gc, GCForeground, &gcv);
XFillRectangle(dpy, desktopWin, gc, rx, ry, rw, rh);
-@@ -70,8 +74,12 @@
++#else
++ FillRectangle(rx, ry, rw, rh, gcv.foreground);
++#endif
+
+ for (i = 0; i < hdr.nSubrects; i++) {
+ if (!ReadFromRFBServer((char *)&pix, sizeof(pix)))
+@@ -70,13 +90,23 @@
#if (BPP == 8)
gcv.foreground = (appData.useBGR233 ? BGR233ToPixel[pix] : pix);
#else
@@ -2103,26 +5042,159 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rre.c vnc_unixsrc/vncviewer/r
#endif
+#endif
++#if 0
XChangeGC(dpy, gc, GCForeground, &gcv);
XFillRectangle(dpy, desktopWin, gc, rx + subrect.x, ry + subrect.y,
-diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/shm.c vnc_unixsrc/vncviewer/shm.c
---- vnc_unixsrc.orig/vncviewer/shm.c 2000-06-11 08:00:53.000000000 -0400
-+++ vnc_unixsrc/vncviewer/shm.c 2006-07-26 23:30:42.000000000 -0400
-@@ -41,6 +41,10 @@
+ subrect.w, subrect.h);
++#else
++ FillRectangle(rx + subrect.x, ry + subrect.y, subrect.w, subrect.h, gcv.foreground);
++#endif
}
- }
-+Bool UsingShm() {
-+ return needShmCleanup;
+ return True;
+ }
++
++#undef FillRectangle
+diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/shm.c vnc_unixsrc/vncviewer/shm.c
+--- vnc_unixsrc.orig/vncviewer/shm.c 2000-06-11 08:00:53.000000000 -0400
++++ vnc_unixsrc/vncviewer/shm.c 2007-02-08 23:36:56.000000000 -0500
+@@ -33,68 +33,80 @@
+ void
+ ShmCleanup()
+ {
+- fprintf(stderr,"ShmCleanup called\n");
+- if (needShmCleanup) {
+- shmdt(shminfo.shmaddr);
+- shmctl(shminfo.shmid, IPC_RMID, 0);
+- needShmCleanup = False;
+- }
++ fprintf(stderr,"ShmCleanup called\n");
++ if (needShmCleanup) {
++ shmdt(shminfo.shmaddr);
++ shmctl(shminfo.shmid, IPC_RMID, 0);
++ needShmCleanup = False;
++ }
+}
+
++Bool UsingShm() {
++ return needShmCleanup;
+ }
+
static int
ShmCreationXErrorHandler(Display *dpy, XErrorEvent *error)
{
+- caughtShmError = True;
+- return 0;
++ caughtShmError = True;
++ return 0;
+ }
+
+ XImage *
+-CreateShmImage()
++CreateShmImage(int do_ycrop)
+ {
+- XImage *image;
+- XErrorHandler oldXErrorHandler;
+-
+- if (!XShmQueryExtension(dpy))
+- return NULL;
+-
+- image = XShmCreateImage(dpy, vis, visdepth, ZPixmap, NULL, &shminfo,
+- si.framebufferWidth, si.framebufferHeight);
+- if (!image) return NULL;
+-
+- shminfo.shmid = shmget(IPC_PRIVATE,
+- image->bytes_per_line * image->height,
+- IPC_CREAT|0777);
+-
+- if (shminfo.shmid == -1) {
+- XDestroyImage(image);
+- return NULL;
+- }
+-
+- shminfo.shmaddr = image->data = shmat(shminfo.shmid, 0, 0);
+-
+- if (shminfo.shmaddr == (char *)-1) {
+- XDestroyImage(image);
+- shmctl(shminfo.shmid, IPC_RMID, 0);
+- return NULL;
+- }
+-
+- shminfo.readOnly = True;
+-
+- oldXErrorHandler = XSetErrorHandler(ShmCreationXErrorHandler);
+- XShmAttach(dpy, &shminfo);
+- XSync(dpy, False);
+- XSetErrorHandler(oldXErrorHandler);
+-
+- if (caughtShmError) {
+- XDestroyImage(image);
+- shmdt(shminfo.shmaddr);
+- shmctl(shminfo.shmid, IPC_RMID, 0);
+- return NULL;
+- }
++ XImage *image;
++ XErrorHandler oldXErrorHandler;
++ int ymax = si.framebufferHeight;
++
++ if (!XShmQueryExtension(dpy)) {
++ return NULL;
++ }
++ if (!appData.useShm) {
++ return NULL;
++ }
++ if (do_ycrop) {
++ ymax = appData.yCrop;
++ }
++
++ image = XShmCreateImage(dpy, vis, visdepth, ZPixmap, NULL, &shminfo,
++ si.framebufferWidth, ymax);
++ if (!image) {
++ return NULL;
++ }
++
++ shminfo.shmid = shmget(IPC_PRIVATE, image->bytes_per_line * image->height, IPC_CREAT|0777);
++
++ if (shminfo.shmid == -1) {
++ XDestroyImage(image);
++ return NULL;
++ }
++
++ shminfo.shmaddr = image->data = shmat(shminfo.shmid, 0, 0);
++
++ if (shminfo.shmaddr == (char *)-1) {
++ XDestroyImage(image);
++ shmctl(shminfo.shmid, IPC_RMID, 0);
++ return NULL;
++ }
++
++ shminfo.readOnly = True;
++
++ oldXErrorHandler = XSetErrorHandler(ShmCreationXErrorHandler);
++ XShmAttach(dpy, &shminfo);
++ XSync(dpy, False);
++ XSetErrorHandler(oldXErrorHandler);
++
++ if (caughtShmError) {
++ XDestroyImage(image);
++ shmdt(shminfo.shmaddr);
++ shmctl(shminfo.shmid, IPC_RMID, 0);
++ return NULL;
++ }
+
+- needShmCleanup = True;
++ needShmCleanup = True;
+
+- fprintf(stderr,"Using shared memory PutImage\n");
++ fprintf(stderr,"Using shared memory PutImage ycrop=%d\n", do_ycrop);
+
+- return image;
++ return image;
+ }
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/sockets.c vnc_unixsrc/vncviewer/sockets.c
--- vnc_unixsrc.orig/vncviewer/sockets.c 2001-01-14 22:54:18.000000000 -0500
-+++ vnc_unixsrc/vncviewer/sockets.c 2007-02-03 22:47:29.000000000 -0500
-@@ -63,9 +63,14 @@
++++ vnc_unixsrc/vncviewer/sockets.c 2007-02-18 20:31:30.000000000 -0500
+@@ -63,15 +63,59 @@
XtRemoveInput(*id);
}
@@ -2131,32 +5203,596 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/sockets.c vnc_unixsrc/vncview
static void
ProcessXtEvents()
{
+- rfbsockReady = False;
+- XtAppAddInput(appContext, rfbsock, (XtPointer)XtInputReadMask,
+- rfbsockReadyCallback, NULL);
+- while (!rfbsockReady) {
+- XtAppProcessEvent(appContext, XtIMAll);
+- }
++ if (appData.chatActive) {
++ fd_set fds;
++ struct timeval tv;
++ int i, igot = -1, n = fileno(stdin);
++ char strs[100][512];
++ char buf[rfbTextMaxSize];
++
++ for (i=0; i < 100; i++) {
++ FD_ZERO(&fds);
++ FD_SET(n,&fds);
++ tv.tv_sec = 0;
++ tv.tv_usec = 0;
++ if (select(n+1, &fds, NULL, NULL, &tv) > 0) {
++ if (FD_ISSET(n, &fds)) {
++ fgets(strs[i], 512, stdin);
++ igot = i;
++ } else {
++ break;
++ }
++ } else {
++ break;
++ }
++ }
++ buf[0] = '\0';
++ for (i=0; i <= igot; i++) {
++ if (strlen(buf) + strlen(strs[i]) < rfbTextMaxSize) {
++ strcat(buf, strs[i]);
++ } else {
++ SendTextChat(buf);
++ buf[0] = '0';
++ }
++ }
++ if (buf[0] != '\0') {
++ SendTextChat(buf);
++ }
++ if (igot >= 0) fprintf(stderr, "Send: ");
++ }
+ if (skip_XtUpdate) {
+ return;
+ }
- rfbsockReady = False;
- XtAppAddInput(appContext, rfbsock, (XtPointer)XtInputReadMask,
- rfbsockReadyCallback, NULL);
++
++ rfbsockReady = False;
++ XtAppAddInput(appContext, rfbsock, (XtPointer)XtInputReadMask,
++ rfbsockReadyCallback, NULL);
++
++ while (!rfbsockReady) {
++ XtAppProcessEvent(appContext, XtIMAll);
++ }
+ }
+
+ Bool
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/tight.c vnc_unixsrc/vncviewer/tight.c
--- vnc_unixsrc.orig/vncviewer/tight.c 2002-04-30 09:07:31.000000000 -0400
-+++ vnc_unixsrc/vncviewer/tight.c 2007-02-03 20:52:34.000000000 -0500
-@@ -132,8 +132,13 @@
- gcv.foreground = (appData.useBGR233) ?
- BGR233ToPixel[fill_colour] : fill_colour;
- #else
-+#if (BPP == 16)
-+ gcv.foreground = (appData.useBGR565) ?
-+ BGR565ToPixel[fill_colour] : fill_colour;
++++ vnc_unixsrc/vncviewer/tight.c 2007-02-17 22:08:20.000000000 -0500
+@@ -129,14 +129,21 @@
+ #endif
+
+ #if (BPP == 8)
+- gcv.foreground = (appData.useBGR233) ?
+- BGR233ToPixel[fill_colour] : fill_colour;
++ gcv.foreground = (appData.useBGR233) ? BGR233ToPixel[fill_colour] : fill_colour;
+#else
++#if (BPP == 16)
++ gcv.foreground = (appData.useBGR565) ? BGR565ToPixel[fill_colour] : fill_colour;
+ #else
gcv.foreground = fill_colour;
#endif
+#endif
- XChangeGC(dpy, gc, GCForeground, &gcv);
- XFillRectangle(dpy, desktopWin, gc, rx, ry, rw, rh);
+- XChangeGC(dpy, gc, GCForeground, &gcv);
+- XFillRectangle(dpy, desktopWin, gc, rx, ry, rw, rh);
++ if (!appData.useBackingstore) {
++ FillScreen(rx, ry, rw, rh, gcv.foreground);
++ } else {
++ XChangeGC(dpy, gc, GCForeground, &gcv);
++ XFillRectangle(dpy, desktopWin, gc, rx, ry, rw, rh);
++ }
+ return True;
+ }
+
+diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer._man vnc_unixsrc/vncviewer/vncviewer._man
+--- vnc_unixsrc.orig/vncviewer/vncviewer._man 1969-12-31 19:00:00.000000000 -0500
++++ vnc_unixsrc/vncviewer/vncviewer._man 2007-02-18 18:25:14.000000000 -0500
+@@ -0,0 +1,497 @@
++'\" t
++.\" ** The above line should force tbl to be a preprocessor **
++.\" Man page for X vncviewer
++.\"
++.\" Copyright (C) 1998 Marcus.Brinkmann@ruhr-uni-bochum.de
++.\" Copyright (C) 2000,2001 Red Hat, Inc.
++.\" Copyright (C) 2001-2003 Constantin Kaplinsky <const@ce.cctpu.edu.ru>
++.\"
++.\" You may distribute under the terms of the GNU General Public
++.\" License as specified in the file LICENCE.TXT that comes with the
++.\" TightVNC distribution.
++.\"
++.TH vncviewer 1 "January 2003" "" "TightVNC"
++.SH NAME
++vncviewer \- an X viewer client for VNC
++.SH SYNOPSIS
++.B vncviewer
++.RI [\| options \|]
++.RI [\| host \|][\| :display \|]
++.br
++.B vncviewer
++.RI [\| options \|]
++.RI [\| host \|][\| ::port \|]
++.br
++.B vncviewer
++.RI [\| options \|]
++.IR \-listen
++.RI [\| display \|]
++.br
++.B vncviewer
++.IR \-help
++.br
++.SH DESCRIPTION
++.B vncviewer
++is an Xt\-based client application for the VNC (Virtual Network
++Computing) system. It can connect to any VNC\-compatible server such
++as \fBXvnc\fR or WinVNC, allowing you to control desktop environment
++of a different machine.
++
++You can use F8 to display a pop\-up utility menu. Press F8 twice to
++pass single F8 to the remote side.
++.SH OPTIONS
++.TP
++\fB\-help\fR
++Prints a short usage notice to stderr.
++.TP
++\fB\-listen\fR
++Make the viewer listen on port 5500+\fIdisplay\fR for reverse
++connections from a server. WinVNC supports reverse connections using
++the "Add New Client" menu option, or the \-connect command line
++option. \fBXvnc\fR requires the use of the helper program
++\fBvncconnect\fR.
++.TP
++\fB\-via\fR \fIgateway\fR
++Automatically create encrypted TCP tunnel to the \fIgateway\fR machine
++before connection, connect to the \fIhost\fR through that tunnel
++(TightVNC\-specific). By default, this option invokes SSH local port
++forwarding, assuming that SSH client binary can be accessed as
++/usr/bin/ssh. Note that when using the \fB\-via\fR option, the host
++machine name should be specified as known to the gateway machine, e.g.
++"localhost" denotes the \fIgateway\fR, not the machine where vncviewer
++was launched. See the ENVIRONMENT section below for the information on
++configuring the \fB\-via\fR option.
++.TP
++\fB\-shared\fR
++When connecting, specify that a shared connection is requested. In
++TightVNC, this is the default mode, allowing you to share the desktop
++with other clients already using it.
++.TP
++\fB\-noshared\fR
++When connecting, specify that the session may not be shared. This
++would either disconnect other connected clients or refuse your
++connection, depending on the server configuration.
++.TP
++\fB\-viewonly\fR
++Disable transfer of mouse and keyboard events from the client to the
++server.
++.TP
++\fB\-fullscreen\fR
++Start in full\-screen mode. Please be aware that operating in
++full\-screen mode may confuse X window managers. Typically, such
++conflicts cause incorrect handling of input focus or make the viewer
++window disappear mysteriously. See the grabKeyboard setting in the
++RESOURCES section below for a method to solve input focus problem.
++.TP
++\fB\-noraiseonbeep\fR
++By default, the viewer shows and raises its window on remote beep
++(bell) event. This option disables such behaviour
++(TightVNC\-specific).
++.TP
++\fB\-user\fR \fIusername\fR
++User name for Unix login authentication. Default is to use current
++Unix user name. If this option was given, the viewer will prefer Unix
++login authentication over the standard VNC authentication.
++.TP
++\fB\-passwd\fR \fIpasswd\-file\fR
++File from which to get the password (as generated by the
++\fBvncpasswd\fR(1) program). This option affects only the standard VNC
++authentication.
++.TP
++\fB\-encodings\fR \fIencoding\-list\fR
++TightVNC supports several different compression methods to encode
++screen updates; this option specifies a set of them to use in order of
++preference. Encodings are specified separated with spaces, and must
++thus be enclosed in quotes if more than one is specified. Available
++encodings, in default order for a remote connection, are "copyrect
++tight hextile zlib corre rre raw". For a local connection (to the same
++machine), the default order to try is "raw copyrect tight hextile zlib
++corre rre". Raw encoding is always assumed as a last option if no
++other encoding can be used for some reason. For more information on
++encodings, see the section ENCODINGS below.
++.TP
++\fB\-bgr233\fR
++Always use the BGR233 format to encode pixel data. This reduces
++network traffic, but colors may be represented inaccurately. The
++bgr233 format is an 8\-bit "true color" format, with 2 bits blue, 3
++bits green, and 3 bits red.
++.TP
++\fB\-owncmap\fR
++Try to use a PseudoColor visual and a private colormap. This allows
++the VNC server to control the colormap.
++.TP
++\fB\-truecolour\fR, \fB\-truecolor\fR
++Try to use a TrueColor visual.
++.TP
++\fB\-depth\fR \fIdepth\fR
++On an X server which supports multiple TrueColor visuals of different
++depths, attempt to use the specified one (in bits per pixel); if
++successful, this depth will be requested from the VNC server.
++.TP
++\fB\-compresslevel \fIlevel\fR
++Use specified compression \fIlevel\fR (0..9) for "tight" and "zlib"
++encodings (TightVNC\-specific). Level 1 uses minimum of CPU time and
++achieves weak compression ratios, while level 9 offers best
++compression but is slow in terms of CPU time consumption on the server
++side. Use high levels with very slow network connections, and low
++levels when working over high\-speed LANs. It's not recommended to use
++compression level 0, reasonable choices start from the level 1.
++.TP
++\fB\-quality \fIlevel\fR
++Use the specified JPEG quality \fIlevel\fR (0..9) for the "tight"
++encoding (TightVNC\-specific). Quality level 0 denotes bad image
++quality but very impressive compression ratios, while level 9 offers
++very good image quality at lower compression ratios. Note that the
++"tight" encoder uses JPEG to encode only those screen areas that look
++suitable for lossy compression, so quality level 0 does not always
++mean unacceptable image quality.
++.TP
++\fB\-nojpeg\fR
++Disable lossy JPEG compression in Tight encoding (TightVNC\-specific).
++Disabling JPEG compression is not a good idea in typical cases, as
++that makes the Tight encoder less efficient. You might want to use
++this option if it's absolutely necessary to achieve perfect image
++quality (see also the \fB\-quality\fR option).
++.TP
++\fB\-nocursorshape\fR
++Disable cursor shape updates, protocol extensions used to handle
++remote cursor movements locally on the client side
++(TightVNC\-specific). Using cursor shape updates decreases delays with
++remote cursor movements, and can improve bandwidth usage dramatically.
++.TP
++\fB\-x11cursor\fR
++Use a real X11 cursor with X-style cursor shape updates, instead of
++drawing the remote cursor on the framebuffer. This option also
++disables the dot cursor, and disables cursor position updates in
++non-fullscreen mode.
++.TP
++\fB\-autopass\fR
++Read a plain-text password from stdin. This option affects only the
++standard VNC authentication.
++
++.SH Enhanced TightVNC Viewer OPTIONS
++.TP
++Enhanced TightVNC Viewer web page is located at:
++.TP
++http://www.karlrunge.com/x11vnc/enhanced_tightvnc_viewer.html
++.TP
++Note: ZRLE encoding is now supported.
++.TP
++Note: F9 is shortcut to Toggle FullScreen mode.
++.TP
++\fB\-use64\fR
++In \fB\-bgr233\fR mode, use 64 colors instead of 256.
++.TP
++\fB\-bgr222\fR
++Same as \fB\-use64\fR.
++.TP
++\fB\-use8\fR
++In \fB\-bgr233\fR mode, use 8 colors instead of 256.
++.TP
++\fB\-bgr111\fR
++Same as \fB\-use8\fR.
++.TP
++\fB\-16bpp\fR
++If the vnc viewer X display is depth 24 at 32bpp
++request a 16bpp format from the VNC server to cut
++network traffic by up to 2X, then tranlate the
++pixels to 32bpp locally.
++.TP
++\fB\-bgr565\fR
++Same as \fB\-16bpp\fR.
++.TP
++\fB\-alpha\fR
++Use alphablending transparency for local cursors
++requires: x11vnc server, both client and server
++must be 32bpp and same endianness.
++.TP
++\fB\-ycrop\fR n
++Only show the top n rows of the framebuffer. For
++use with x11vnc \fB\-ncache\fR client caching option
++to help "hide" the pixel cache region.
++Use a negative value (e.g. \fB\-1\fR) for autodetection.
++Autodetection will always take place if the remote
++fb height is more than 2 times the width.
++.TP
++\fB\-sbwidth\fR n
++Scrollbar width, default is very narrow: 2 pixels,
++it is narrow to avoid distraction in \fB\-ycrop\fR mode.
++.TP
++\fB\-rawlocal\fR
++Prefer raw encoding for localhost, default is
++no, i.e. assumes you have a SSH tunnel instead.
++.TP
++\fB\-graball\fR
++Grab the entire X server when in fullscreen mode,
++needed by some old window managers like fvwm2.
++.TP
++\fB\-popupfix\fR
++Warp the popup back to the pointer position,
++needed by some old window managers like fvwm2.
++.TP
++\fB\-grabkbd\fR
++Grab the X keyboard when in fullscreen mode,
++needed by some window managers. Same as \fB\-grabkeyboard\fR.
++\fB\-grabkbd\fR is the default, use \fB\-nograbkbd\fR to disable.
++.TP
++\fB\-bs/-nobs\fR
++Whether or not to use X server Backingstore for the
++main viewer window. The default is to not, mainly
++because most Linux, etc, systems X servers disable
++*all* Backingstore by default. To re-enable it put
++
++Option "Backingstore"
++
++in the Device section of /etc/X11/xorg.conf.
++In -bs mode with no X server backingstore, whenever an
++area of the screen is re-exposed it must go out to the
++VNC server to retrieve the pixels. This is too slow.
++
++In -nobs mode, memory is allocated by the viewer to
++provide its own backing of the main viewer window. This
++actually makes some activities faster (changes in large
++regions) but can appear to "flash" too much.
++.TP
++\fB\-noshm\fR
++Disable use of MIT shared memory extension (not recommended)
++.TP
++\fB New Popup actions:\fR
++
++ Cursor Shape: ~ -nocursorshape
++ X11 Cursor: ~ -x11cursor
++ Cursor Alphablend: ~ -alpha
++ Disable JPEG: ~ -nojpeg
++ Prefer raw for localhost ~ -rawlocal
++ Full Color as many colors as local screen allows.
++ Grey scale (16 & 8-bpp) ~ -grey, for low colors 16/8bpp modes only.
++ 16 bit color (BGR565) ~ -bgr565
++ 8 bit color (BGR233) ~ -bgr233
++ 256 colors ~ -bgr233 default # of colors.
++ 64 colors ~ -bgr222 / -use64
++ 8 colors ~ -bgr111 / -use8
++
++
++ Disable Remote Input Ultravnc ext. Try to prevent input and
++ viewing of monitor at physical display.
++ Single Window Ultravnc ext. Grab and a single window.
++ (click on the window you want).
++ Set 1/n Server Scale Ultravnc ext. Scale desktop by 1/n.
++ prompt is from the terminal.
++ Text Chat Ultravnc ext. Do Text Chat, currently
++ input via the terminal (no window).
++
++ Note: the Ultravnc extensions only apply to servers that support
++ them. x11vnc/libvncserver supports some of them.
++
++.SH ENCODINGS
++The server supplies information in whatever format is desired by the
++client, in order to make the client as easy as possible to implement.
++If the client represents itself as able to use multiple formats, the
++server will choose one.
++
++.I Pixel format
++refers to the representation of an individual pixel. The most common
++formats are 24 and 16 bit "true\-color" values, and 8\-bit "color map"
++representations, where an arbitrary map converts the color number to
++RGB values.
++
++.I Encoding
++refers to how a rectangle of pixels are sent (all pixel information in
++VNC is sent as rectangles). All rectangles come with a header giving
++the location and size of the rectangle and an encoding type used by
++the data which follows. These types are listed below.
++.TP
++.B Raw
++The raw encoding simply sends width*height pixel values. All clients
++are required to support this encoding type. Raw is also the fastest
++when the server and viewer are on the same machine, as the connection
++speed is essentially infinite and raw encoding minimizes processing
++time.
++.TP
++.B CopyRect
++The Copy Rectangle encoding is efficient when something is being
++moved; the only data sent is the location of a rectangle from which
++data should be copied to the current location. Copyrect could also be
++used to efficiently transmit a repeated pattern.
++.TP
++.B RRE
++The Rise\-and\-Run\-length\-Encoding is basically a 2D version of
++run\-length encoding (RLE). In this encoding, a sequence of identical
++pixels are compressed to a single value and repeat count. In VNC, this
++is implemented with a background color, and then specifications of an
++arbitrary number of subrectangles and color for each. This is an
++efficient encoding for large blocks of constant color.
++.TP
++.B CoRRE
++This is a minor variation on RRE, using a maximum of 255x255 pixel
++rectangles. This allows for single\-byte values to be used, reducing
++packet size. This is in general more efficient, because the savings
++from sending 1\-byte values generally outweighs the losses from the
++(relatively rare) cases where very large regions are painted the same
++color.
++.TP
++.B Hextile
++Here, rectangles are split up in to 16x16 tiles, which are sent in a
++predetermined order. The data within the tiles is sent either raw or
++as a variant on RRE. Hextile encoding is usually the best choice for
++using in high\-speed network environments (e.g. Ethernet local\-area
++networks).
++.TP
++.B Zlib
++Zlib is a very simple encoding that uses zlib library to compress raw
++pixel data. This encoding achieves good compression, but consumes a
++lot of CPU time. Support for this encoding is provided for
++compatibility with VNC servers that might not understand Tight
++encoding which is more efficient than Zlib in nearly all real\-life
++situations.
++.TP
++.B Tight
++Like Zlib encoding, Tight encoding uses zlib library to compress the
++pixel data, but it pre\-processes data to maximize compression ratios,
++and to minimize CPU usage on compression. Also, JPEG compression may
++be used to encode color\-rich screen areas (see the description of
++\-quality and \-nojpeg options above). Tight encoding is usually the
++best choice for low\-bandwidth network environments (e.g. slow modem
++connections).
++.SH RESOURCES
++X resources that \fBvncviewer\fR knows about, aside from the
++normal Xt resources, are as follows:
++.TP
++.B shareDesktop
++Equivalent of \fB\-shared\fR/\fB\-noshared\fR options. Default true.
++.TP
++.B viewOnly
++Equivalent of \fB\-viewonly\fR option. Default false.
++.TP
++.B fullScreen
++Equivalent of \fB\-fullscreen\fR option. Default false.
++.TP
++.B grabKeyboard
++Grab keyboard in full-screen mode. This can help to solve problems
++with losing keyboard focus. Default false.
++.TP
++.B raiseOnBeep
++Equivalent of \fB\-noraiseonbeep\fR option, when set to false. Default
++true.
++.TP
++.B passwordFile
++Equivalent of \fB\-passwd\fR option.
++.TP
++.B userLogin
++Equivalent of \fB\-user\fR option.
++.TP
++.B passwordDialog
++Whether to use a dialog box to get the password (true) or get it from
++the tty (false). Irrelevant if \fBpasswordFile\fR is set. Default
++false.
++.TP
++.B encodings
++Equivalent of \fB\-encodings\fR option.
++.TP
++.B compressLevel
++Equivalent of \fB\-compresslevel\fR option (TightVNC\-specific).
++.TP
++.B qualityLevel
++Equivalent of \fB\-quality\fR option (TightVNC\-specific).
++.TP
++.B enableJPEG
++Equivalent of \fB\-nojpeg\fR option, when set to false. Default true.
++.TP
++.B useRemoteCursor
++Equivalent of \fB\-nocursorshape\fR option, when set to false
++(TightVNC\-specific). Default true.
++.TP
++.B useBGR233
++Equivalent of \fB\-bgr233\fR option. Default false.
++.TP
++.B nColours
++When using BGR233, try to allocate this many "exact" colors from the
++BGR233 color cube. When using a shared colormap, setting this resource
++lower leaves more colors for other X clients. Irrelevant when using
++truecolor. Default is 256 (i.e. all of them).
++.TP
++.B useSharedColours
++If the number of "exact" BGR233 colors successfully allocated is less
++than 256 then the rest are filled in using the "nearest" colors
++available. This resource says whether to only use the "exact" BGR233
++colors for this purpose, or whether to use other clients' "shared"
++colors as well. Default true (i.e. use other clients' colors).
++.TP
++.B forceOwnCmap
++Equivalent of \fB\-owncmap\fR option. Default false.
++.TP
++.B forceTrueColour
++Equivalent of \fB\-truecolour\fR option. Default false.
++.TP
++.B requestedDepth
++Equivalent of \fB\-depth\fR option.
++.TP
++.B useSharedMemory
++Use MIT shared memory extension if on the same machine as the X
++server. Default true.
++.TP
++.B wmDecorationWidth, wmDecorationHeight
++The total width and height taken up by window manager decorations.
++This is used to calculate the maximum size of the VNC viewer window.
++Default is width 4, height 24.
++.TP
++.B bumpScrollTime, bumpScrollPixels
++When in full screen mode and the VNC desktop is bigger than the X
++display, scrolling happens whenever the mouse hits the edge of the
++screen. The maximum speed of scrolling is bumpScrollPixels pixels
++every bumpScrollTime milliseconds. The actual speed of scrolling will
++be slower than this, of course, depending on how fast your machine is.
++Default 20 pixels every 25 milliseconds.
++.TP
++.B popupButtonCount
++The number of buttons in the popup window. See the README file for
++more information on how to customize the buttons.
++.TP
++.B debug
++For debugging. Default false.
++.TP
++.B rawDelay, copyRectDelay
++For debugging, see the README file for details. Default 0 (off).
++.SH ENVIRONMENT
++When started with the \fB\-via\fR option, vncviewer reads the
++\fBVNC_VIA_CMD\fR environment variable, expands patterns beginning
++with the "%" character, and executes result as a command assuming that
++it would create TCP tunnel that should be used for VNC connection. If
++not set, this environment variable defaults to "/usr/bin/ssh -f -L
++%L:%H:%R %G sleep 20".
++
++The following patterns are recognized in the \fBVNC_VIA_CMD\fR (note
++that all the patterns %G, %H, %L and %R must be present in the command
++template):
++.TP
++.B %%
++A literal "%";
++.TP
++.B %G
++gateway host name;
++.TP
++.B %H
++remote VNC host name, as known to the gateway;
++.TP
++.B %L
++local TCP port number;
++.TP
++.B %R
++remote TCP port number.
++.SH SEE ALSO
++\fBvncserver\fR(1), \fBXvnc\fR(1), \fBvncpasswd\fR(1),
++\fBvncconnect\fR(1), \fBssh\fR(1)
++.SH AUTHORS
++Original VNC was developed in AT&T Laboratories Cambridge. TightVNC
++additions was implemented by Constantin Kaplinsky. Many other people
++participated in development, testing and support.
++
++\fBMan page authors:\fR
++.br
++Marcus Brinkmann <Marcus.Brinkmann@ruhr-uni-bochum.de>,
++.br
++Terran Melconian <terran@consistent.org>,
++.br
++Tim Waugh <twaugh@redhat.com>,
++.br
++Constantin Kaplinsky <const@ce.cctpu.edu.ru>
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.c vnc_unixsrc/vncviewer/vncviewer.c
--- vnc_unixsrc.orig/vncviewer/vncviewer.c 2004-01-13 09:22:05.000000000 -0500
-+++ vnc_unixsrc/vncviewer/vncviewer.c 2007-02-04 00:05:10.000000000 -0500
++++ vnc_unixsrc/vncviewer/vncviewer.c 2007-02-18 18:45:43.000000000 -0500
@@ -22,6 +22,7 @@
*/
@@ -2165,31 +5801,41 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.c vnc_unixsrc/vncvi
char *programName;
XtAppContext appContext;
-@@ -29,6 +30,32 @@
+@@ -29,11 +30,47 @@
Widget toplevel;
-+static void set_sbwidth(int sbw) {
++void set_sbwidth(int sbw) {
+ char *q, *p, t[5];
+ int i, k, N = 4;
++ int db = 0;
+
+ if (sbw < 1) {
+ sbw = 2;
+ } else if (sbw > 100) {
+ sbw = 100;
+ }
++ if (db) fprintf(stderr, "sbw: %d\n", sbw);
+
+ sprintf(t, "%4d", sbw);
+ k = 0;
+ while (fallback_resources[k] != NULL) {
-+ q = strstr(fallback_resources[k], "%SBW");
++ q = strstr(fallback_resources[k], "horizontal.height: ");
++ if (!q) {
++ q = strstr(fallback_resources[k], "vertical.width: ");
++ }
+ if (q) {
+ p = strdup(fallback_resources[k]);
-+ q = strstr(p, "%SBW");
-+ for (i=0; i < N; i++) {
-+ *(q+i) = t[i];
++ q = strstr(p, ": ");
++ if (q) {
++ q++;
++ q++;
++ for (i=0; i < N; i++) {
++ *(q+i) = t[i];
++ }
++ fallback_resources[k] = p;
++ if (db) fprintf(stderr, "res: %s\n", p);
+ }
-+ fallback_resources[k] = p;
+ }
+ k++;
+ }
@@ -2198,46 +5844,172 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.c vnc_unixsrc/vncvi
int
main(int argc, char **argv)
{
-@@ -57,10 +84,24 @@
- }
- }
-
-+ if (argc > 1 && strstr(argv[1], "-h") == argv[1]) {
-+ usage();
-+ return 0;
-+ }
+- int i;
+- programName = argv[0];
++ int i, save_sbw;
++ programName = argv[0];
+
+ /* The -listen option is used to make us a daemon process which listens for
+ incoming connections from servers, rather than actively connecting to a
+@@ -45,89 +82,718 @@
+ listenForIncomingConnections() returns, setting the listenSpecified
+ flag. */
+
+- for (i = 1; i < argc; i++) {
+- if (strcmp(argv[i], "-listen") == 0) {
+- listenForIncomingConnections(&argc, argv, i);
+- break;
+- }
+- if (strcmp(argv[i], "-tunnel") == 0 || strcmp(argv[i], "-via") == 0) {
+- if (!createTunnel(&argc, argv, i))
+- exit(1);
+- break;
+- }
+- }
++ for (i = 1; i < argc; i++) {
++ if (strcmp(argv[i], "-listen") == 0) {
++ listenForIncomingConnections(&argc, argv, i);
++ break;
++ }
++ if (strcmp(argv[i], "-tunnel") == 0 || strcmp(argv[i], "-via") == 0) {
++ if (!createTunnel(&argc, argv, i)) {
++ exit(1);
++ }
++ break;
++ }
++ }
+
++ if (argc > 1 && strstr(argv[1], "-h") == argv[1]) {
++ usage();
++ return 0;
++ }
+
/* Call the main Xt initialisation function. It parses command-line options,
generating appropriate resource specs, and makes a connection to the X
display. */
-+ { int i, sbw = 2;
-+ for (i = 1; i < argc - 1; i++) {
-+ if (!strcmp(argv[i], "-sbwidth")) {
-+ sbw = atoi(argv[i+1]);
+- toplevel = XtVaAppInitialize(&appContext, "Vncviewer",
+- cmdLineOptions, numCmdLineOptions,
+- &argc, argv, fallback_resources,
+- XtNborderWidth, 0, NULL);
++ appData.sbWidth = 0;
++ if (getenv("VNCVIEWER_SBWIDTH")) {
++ int sbw = atoi(getenv("VNCVIEWER_SBWIDTH"));
++ if (sbw > 0) {
++ appData.sbWidth = sbw;
+ }
+ }
-+ set_sbwidth(sbw);
-+ }
++ if (appData.sbWidth == 0) {
++ int i, sbw = 0;
++ for (i = 1; i < argc - 1; i++) {
++ if (!strcmp(argv[i], "-sbwidth")) {
++ sbw = atoi(argv[i+1]);
++ }
++ }
++ if (sbw > 0) {
++ appData.sbWidth = sbw;
++ }
++ }
++ save_sbw = appData.sbWidth;
++ set_sbwidth(6);
++
++ toplevel = XtVaAppInitialize(&appContext, "Vncviewer", cmdLineOptions,
++ numCmdLineOptions, &argc, argv, fallback_resources,
++ XtNborderWidth, 0, NULL);
+
+- dpy = XtDisplay(toplevel);
++ dpy = XtDisplay(toplevel);
+
+ /* Interpret resource specs and process any remaining command-line arguments
+ (i.e. the VNC server name). If the server name isn't specified on the
+ command line, getArgsAndResources() will pop up a dialog box and wait
+ for one to be entered. */
+
+- GetArgsAndResources(argc, argv);
++ GetArgsAndResources(argc, argv);
+
- toplevel = XtVaAppInitialize(&appContext, "Vncviewer",
- cmdLineOptions, numCmdLineOptions,
- &argc, argv, fallback_resources,
-@@ -123,11 +164,443 @@
++ if (save_sbw) {
++ appData.sbWidth = save_sbw;
++ }
+
+ /* Unless we accepted an incoming connection, make a TCP connection to the
+ given VNC server */
+
+- if (!listenSpecified) {
+- if (!ConnectToRFBServer(vncServerHost, vncServerPort)) exit(1);
+- }
++ if (!listenSpecified) {
++ if (!ConnectToRFBServer(vncServerHost, vncServerPort)) {
++ exit(1);
++ }
++ }
+
+ /* Initialise the VNC connection, including reading the password */
+
+- if (!InitialiseRFBConnection()) exit(1);
++ if (!InitialiseRFBConnection()) {
++ exit(1);
++ }
+
+ /* Create the "popup" widget - this won't actually appear on the screen until
+ some user-defined event causes the "ShowPopup" action to be invoked */
+
+- CreatePopup();
++ CreatePopup();
+
+ /* Find the best pixel format and X visual/colormap to use */
+
+- SetVisualAndCmap();
++ SetVisualAndCmap();
+
+ /* Create the "desktop" widget, and perform initialisation which needs doing
+ before the widgets are realized */
+
+- ToplevelInitBeforeRealization();
++ ToplevelInitBeforeRealization();
+
+- DesktopInitBeforeRealization();
++ DesktopInitBeforeRealization();
+
+ /* "Realize" all the widgets, i.e. actually create and map their X windows */
+
+- XtRealizeWidget(toplevel);
++ XtRealizeWidget(toplevel);
+
+ /* Perform initialisation that needs doing after realization, now that the X
+ windows exist */
+
+- InitialiseSelection();
++ InitialiseSelection();
+
+- ToplevelInitAfterRealization();
++ ToplevelInitAfterRealization();
+
+- DesktopInitAfterRealization();
++ DesktopInitAfterRealization();
+
+ /* Tell the VNC server which pixel format and encodings we want to use */
+
+- SetFormatAndEncodings();
++ SetFormatAndEncodings();
+
+ /* Now enter the main loop, processing VNC messages. X events will
automatically be processed whenever the VNC connection is idle. */
- while (1) {
+- while (1) {
- if (!HandleRFBServerMessage())
- break;
-+ if (!HandleRFBServerMessage()) {
-+ break;
+- }
++ while (1) {
++ if (!HandleRFBServerMessage()) {
++ break;
++ }
+ }
- }
-
- Cleanup();
-
- return 0;
- }
++
++ Cleanup();
++
++ return 0;
++}
+
+/*
+ * Toggle8bpp
@@ -2260,6 +6032,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.c vnc_unixsrc/vncvi
+static void init_format_change(void) {
+ appDataNew.useBGR233 = appData.useBGR233;
+ appDataNew.useBGR565 = appData.useBGR565;
++ appDataNew.useGreyScale = appData.useGreyScale;
+ appDataNew.enableJPEG = appData.enableJPEG;
+ appDataNew.encodingsString = appData.encodingsString;
+ appDataNew.useRemoteCursor = appData.useRemoteCursor;
@@ -2269,6 +6042,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.c vnc_unixsrc/vncvi
+void cutover_format_change(void) {
+ appData.useBGR233 = appDataNew.useBGR233;
+ appData.useBGR565 = appDataNew.useBGR565;
++ appData.useGreyScale = appDataNew.useGreyScale;
+ appData.enableJPEG = appDataNew.enableJPEG;
+ appData.encodingsString = appDataNew.encodingsString;
+ appData.useRemoteCursor = appDataNew.useRemoteCursor;
@@ -2394,6 +6168,21 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.c vnc_unixsrc/vncvi
+ }
+}
+
++void
++ToggleGreyScale(Widget w, XEvent *ev, String *params, Cardinal *num_params)
++{
++ fprintf(stderr, "ToggleGreyScale\n");
++ init_format_change();
++ if (appData.useGreyScale) {
++ appDataNew.useGreyScale = False;
++ fprintf(stderr, "greyscale: off\n");
++ } else {
++ appDataNew.useGreyScale = True;
++ fprintf(stderr, "greyscale: on\n");
++ }
++ schedule_format_change();
++}
++
+/*
+ * ToggleJPEG
+ */
@@ -2532,6 +6321,117 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.c vnc_unixsrc/vncvi
+}
+
+void
++ToggleServerInput(Widget w, XEvent *ev, String *params, Cardinal *num_params)
++{
++ if (appData.serverInput) {
++ appData.serverInput= False;
++ fprintf(stderr, "serverInput: off\n");
++ SendServerInput(True);
++ } else {
++ appData.serverInput = True;
++ fprintf(stderr, "serverInput: on\n");
++ SendServerInput(False);
++ }
++}
++
++extern Cursor bogoCursor;
++Bool selectingSingleWindow = False;
+
+- Cleanup();
++void
++ToggleSingleWindow(Widget w, XEvent *ev, String *params, Cardinal *num_params)
++{
++ if (appData.singleWindow) {
++ appData.singleWindow= False;
++ fprintf(stderr, "singleWindow: off\n");
++ SendSingleWindow(-1, -1);
++ } else {
++ appData.singleWindow = True;
++ fprintf(stderr, "singleWindow: on\n");
++ selectingSingleWindow = True;
++ if (bogoCursor != None) {
++ XDefineCursor(dpy, desktopWin, bogoCursor);
++ }
++ }
++}
++
++void raiseme(void);
++
++void
++ToggleTextChat(Widget w, XEvent *ev, String *params, Cardinal *num_params)
++{
++ if (appData.chatActive) {
++ SendTextChatClose();
++ appData.chatActive= False;
++ fprintf(stderr, "\n*SentClose*\n\n");
++ } else {
++ SendTextChatOpen();
++ raiseme();
++ fprintf(stderr, "\n*SentOpen*\n\nSend: ");
++ appData.chatActive = True;
++ }
++}
++
++static int fooHandler(Display *dpy, XErrorEvent *error) {
++ return 0;
++}
++
++void raiseme(void) {
++ if (getenv("WINDOWID")) {
++ unsigned long w;
++ if (sscanf(getenv("WINDOWID"), "%lu", &w) == 1) {
++ ;
++ } else if (sscanf(getenv("WINDOWID"), "0x%lx", &w) == 1) {
++ ;
++ } else {
++ w = 0;
++ }
++ if (w != 0) {
++ XErrorHandler old = XSetErrorHandler(fooHandler);
++ XMapRaised(dpy, (Window) w);
++ XSync(dpy, False);
++ XSetErrorHandler(old);
++ }
++ }
++}
+
+- return 0;
++void
++DoServerScale(Widget w, XEvent *ev, String *params, Cardinal *num_params)
++{
++ char str[100], *q;
++ int n;
++ raiseme();
++ fprintf(stderr, "\n\n\a\nEnter integer n for 1/n server scaling: ");
++ str[0] = '\0';
++ fgets(str, 100, stdin);
++ q = strstr(str, "\n");
++ if (q) *q = '\0';
++ if (str[0] != '\0') {
++ n = atoi(str);
++ if (n >= 1 && n < 100) {
++ appData.serverScale = n;
++ SendServerScale(n);
++ SendFramebufferUpdateRequest(0, 0, si.framebufferWidth,
++ si.framebufferHeight, False);
++ }
++ }
++}
++
++void
++GotChatText(char *str, int len)
++{
++ raiseme();
++ fprintf(stderr, "\nChat: ");
++ write(2, str, len);
++ if (strstr(str, "\n")) {
++ fprintf(stderr, "Send: ");
++ } else {
++ fprintf(stderr, "\nSend: ");
++ }
++}
++
++void
+SetViewOnlyState(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+ if (appData.viewOnly)
@@ -2607,7 +6507,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.c vnc_unixsrc/vncvi
+ } else {
+ XtVaSetValues(w, XtNstate, False, NULL);
+ }
-+}
+ }
+
+void
+Set8ColorsState(Widget w, XEvent *ev, String *params, Cardinal *num_params)
@@ -2622,6 +6522,16 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.c vnc_unixsrc/vncvi
+}
+
+void
++SetGreyScaleState(Widget w, XEvent *ev, String *params, Cardinal *num_params)
++{
++ if (appData.useGreyScale) {
++ XtVaSetValues(w, XtNstate, True, NULL);
++ } else {
++ XtVaSetValues(w, XtNstate, False, NULL);
++ }
++}
++
++void
+SetZRLEState(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+ if (usingZRLE)
@@ -2666,44 +6576,143 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.c vnc_unixsrc/vncvi
+ XtVaSetValues(w, XtNstate, False, NULL);
+}
+
++void
++SetServerInputState(Widget w, XEvent *ev, String *params, Cardinal *num_params)
++{
++ if (!appData.serverInput)
++ XtVaSetValues(w, XtNstate, True, NULL);
++ else
++ XtVaSetValues(w, XtNstate, False, NULL);
++}
++
++void
++SetSingleWindowState(Widget w, XEvent *ev, String *params, Cardinal *num_params)
++{
++ if (appData.singleWindow)
++ XtVaSetValues(w, XtNstate, True, NULL);
++ else
++ XtVaSetValues(w, XtNstate, False, NULL);
++}
++
++void
++SetTextChatState(Widget w, XEvent *ev, String *params, Cardinal *num_params)
++{
++ if (appData.chatActive)
++ XtVaSetValues(w, XtNstate, True, NULL);
++ else
++ XtVaSetValues(w, XtNstate, False, NULL);
++}
++
+
+
+
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.h vnc_unixsrc/vncviewer/vncviewer.h
--- vnc_unixsrc.orig/vncviewer/vncviewer.h 2004-03-11 13:14:40.000000000 -0500
-+++ vnc_unixsrc/vncviewer/vncviewer.h 2007-02-04 12:39:56.000000000 -0500
-@@ -76,12 +76,17 @@
-
- String encodingsString;
-
++++ vnc_unixsrc/vncviewer/vncviewer.h 2007-02-18 14:18:58.000000000 -0500
+@@ -68,51 +68,69 @@
+ /* argsresources.c */
+
+ typedef struct {
+- Bool shareDesktop;
+- Bool viewOnly;
+- Bool fullScreen;
+- Bool grabKeyboard;
+- Bool raiseOnBeep;
+-
+- String encodingsString;
+-
- Bool useBGR233;
-+ int useBGR233;
- int nColours;
- Bool useSharedColours;
- Bool forceOwnCmap;
- Bool forceTrueColour;
- int requestedDepth;
-+ Bool useBGR565;
-+
-+ Bool grabAll;
-+ Bool overrideRedir;
-+ Bool popupFix;
-
- Bool useShm;
+- int nColours;
+- Bool useSharedColours;
+- Bool forceOwnCmap;
+- Bool forceTrueColour;
+- int requestedDepth;
+-
+- Bool useShm;
+-
+- int wmDecorationWidth;
+- int wmDecorationHeight;
+-
+- char *userLogin;
+-
+- char *passwordFile;
+- Bool passwordDialog;
+-
+- int rawDelay;
+- int copyRectDelay;
+-
+- Bool debug;
+-
+- int popupButtonCount;
+-
+- int bumpScrollTime;
+- int bumpScrollPixels;
+-
+- int compressLevel;
+- int qualityLevel;
+- Bool enableJPEG;
+- Bool useRemoteCursor;
+- Bool useX11Cursor;
+- Bool autoPass;
++ Bool shareDesktop;
++ Bool viewOnly;
++ Bool fullScreen;
++ Bool grabKeyboard;
++ Bool raiseOnBeep;
++
++ String encodingsString;
++
++ int useBGR233;
++ int nColours;
++ Bool useSharedColours;
++ Bool forceOwnCmap;
++ Bool forceTrueColour;
++ int requestedDepth;
++ Bool useBGR565;
++ Bool useGreyScale;
++
++ Bool grabAll;
++ Bool useBackingstore;
++ Bool overrideRedir;
++ Bool popupFix;
++
++ Bool useShm;
++
++ int wmDecorationWidth;
++ int wmDecorationHeight;
++
++ char *userLogin;
++
++ char *passwordFile;
++ Bool passwordDialog;
++
++ int rawDelay;
++ int copyRectDelay;
++
++ int yCrop;
++ int sbWidth;
++ Bool useCursorAlpha;
++ Bool useRawLocal;
++
++ Bool debug;
++
++ int popupButtonCount;
++
++ int bumpScrollTime;
++ int bumpScrollPixels;
++
++ int compressLevel;
++ int qualityLevel;
++ Bool enableJPEG;
++ Bool useRemoteCursor;
++ Bool useX11Cursor;
++ Bool autoPass;
++
++ Bool serverInput;
++ Bool singleWindow;
++ int serverScale;
++ Bool chatActive;
-@@ -96,6 +101,11 @@
- int rawDelay;
- int copyRectDelay;
-
-+ int yCrop;
-+ int sbWidth;
-+ Bool useCursorAlpha;
-+ Bool useRawLocal;
-+
- Bool debug;
-
- int popupButtonCount;
-@@ -113,6 +123,7 @@
} AppData;
extern AppData appData;
@@ -2711,7 +6720,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.h vnc_unixsrc/vncvi
extern char *fallback_resources[];
extern char vncServerHost[];
-@@ -130,6 +141,7 @@
+@@ -130,6 +148,7 @@
/* colour.c */
extern unsigned long BGR233ToPixel[];
@@ -2719,35 +6728,62 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.h vnc_unixsrc/vncvi
extern Colormap cmap;
extern Visual *vis;
-@@ -162,6 +174,9 @@
+@@ -160,8 +179,14 @@
+ extern void SendRFBEvent(Widget w, XEvent *event, String *params,
+ Cardinal *num_params);
extern void CopyDataToScreen(char *buf, int x, int y, int width, int height);
++extern void FillScreen(int x, int y, int width, int height, unsigned long fill);
extern void SynchroniseScreen();
+extern void ReDoDesktop();
+extern void DesktopCursorOff();
++extern void put_image(int x1, int y1, int x2, int y2, int width, int height);
++extern void copy_rect(int x, int y, int width, int height, int src_x, int src_y);
+
/* dialogs.c */
extern void ServerDialogDone(Widget w, XEvent *event, String *params,
-@@ -243,6 +258,7 @@
+@@ -229,6 +254,15 @@
+ extern Bool SendClientCutText(char *str, int len);
+ extern Bool HandleRFBServerMessage();
- extern XImage *CreateShmImage();
++extern Bool SendServerInput(Bool enabled);
++extern Bool SendSingleWindow(int x, int y);
++extern Bool SendServerScale(int n);
++
++extern Bool SendTextChat(char *str);
++extern Bool SendTextChatOpen(void);
++extern Bool SendTextChatClose(void);
++extern Bool SendTextChatFinish(void);
++
+ extern void PrintPixelFormat(rfbPixelFormat *format);
+
+ /* selection.c */
+@@ -241,8 +275,9 @@
+
+ /* shm.c */
+
+-extern XImage *CreateShmImage();
++extern XImage *CreateShmImage(int do_ycrop);
extern void ShmCleanup();
+extern Bool UsingShm();
/* sockets.c */
-@@ -271,3 +287,31 @@
+@@ -271,3 +306,42 @@
extern XtAppContext appContext;
extern Display* dpy;
extern Widget toplevel;
+
++extern void GotChatText(char *str, int len);
++
+extern void Toggle8bpp(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void Toggle16bpp(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void ToggleFullColor(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void Toggle256Colors(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void Toggle64Colors(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void Toggle8Colors(Widget w, XEvent *ev, String *params, Cardinal *num_params);
++extern void ToggleGreyScale(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void ToggleTightZRLE(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void ToggleViewOnly(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void ToggleJPEG(Widget w, XEvent *ev, String *params, Cardinal *num_params);
@@ -2755,6 +6791,10 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.h vnc_unixsrc/vncvi
+extern void ToggleCursorAlpha(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void ToggleX11Cursor(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void ToggleRawLocal(Widget w, XEvent *ev, String *params, Cardinal *num_params);
++extern void ToggleServerInput(Widget w, XEvent *ev, String *params, Cardinal *num_params);
++extern void ToggleSingleWindow(Widget w, XEvent *ev, String *params, Cardinal *num_params);
++extern void DoServerScale(Widget w, XEvent *ev, String *params, Cardinal *num_params);
++extern void ToggleTextChat(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+
+extern void SetViewOnlyState(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void SetNOJPEGState(Widget w, XEvent *ev, String *params, Cardinal *num_params);
@@ -2764,15 +6804,19 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.h vnc_unixsrc/vncvi
+extern void Set256ColorsState(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void Set64ColorsState(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void Set8ColorsState(Widget w, XEvent *ev, String *params, Cardinal *num_params);
++extern void SetGreyScaleState(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void SetZRLEState(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void SetCursorShapeState(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void SetCursorAlphaState(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void SetX11CursorState(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void SetRawLocalState(Widget w, XEvent *ev, String *params, Cardinal *num_params);
++extern void SetServerInputState(Widget w, XEvent *ev, String *params, Cardinal *num_params);
++extern void SetSingleWindowState(Widget w, XEvent *ev, String *params, Cardinal *num_params);
++extern void SetTextChatState(Widget w, XEvent *ev, String *params, Cardinal *num_params);
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.man vnc_unixsrc/vncviewer/vncviewer.man
--- vnc_unixsrc.orig/vncviewer/vncviewer.man 2004-03-11 13:14:40.000000000 -0500
-+++ vnc_unixsrc/vncviewer/vncviewer.man 2007-02-04 15:09:49.000000000 -0500
-@@ -168,6 +168,72 @@
++++ vnc_unixsrc/vncviewer/vncviewer.man 2007-02-18 18:25:14.000000000 -0500
+@@ -168,6 +168,121 @@
\fB\-autopass\fR
Read a plain-text password from stdin. This option affects only the
standard VNC authentication.
@@ -2841,14 +6885,90 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.man vnc_unixsrc/vnc
+Grab the X keyboard when in fullscreen mode,
+needed by some window managers. Same as \fB\-grabkeyboard\fR.
+\fB\-grabkbd\fR is the default, use \fB\-nograbkbd\fR to disable.
++.TP
++\fB\-bs/-nobs\fR
++Whether or not to use X server Backingstore for the
++main viewer window. The default is to not, mainly
++because most Linux, etc, systems X servers disable
++*all* Backingstore by default. To re-enable it put
++
++Option "Backingstore"
++
++in the Device section of /etc/X11/xorg.conf.
++In -bs mode with no X server backingstore, whenever an
++area of the screen is re-exposed it must go out to the
++VNC server to retrieve the pixels. This is too slow.
++
++In -nobs mode, memory is allocated by the viewer to
++provide its own backing of the main viewer window. This
++actually makes some activities faster (changes in large
++regions) but can appear to "flash" too much.
++.TP
++\fB\-noshm\fR
++Disable use of MIT shared memory extension (not recommended)
++.TP
++\fB New Popup actions:\fR
++
++ Cursor Shape: ~ -nocursorshape
++ X11 Cursor: ~ -x11cursor
++ Cursor Alphablend: ~ -alpha
++ Disable JPEG: ~ -nojpeg
++ Prefer raw for localhost ~ -rawlocal
++ Full Color as many colors as local screen allows.
++ Grey scale (16 & 8-bpp) ~ -grey, for low colors 16/8bpp modes only.
++ 16 bit color (BGR565) ~ -bgr565
++ 8 bit color (BGR233) ~ -bgr233
++ 256 colors ~ -bgr233 default # of colors.
++ 64 colors ~ -bgr222 / -use64
++ 8 colors ~ -bgr111 / -use8
++
++
++ Disable Remote Input Ultravnc ext. Try to prevent input and
++ viewing of monitor at physical display.
++ Single Window Ultravnc ext. Grab and a single window.
++ (click on the window you want).
++ Set 1/n Server Scale Ultravnc ext. Scale desktop by 1/n.
++ prompt is from the terminal.
++ Text Chat Ultravnc ext. Do Text Chat, currently
++ input via the terminal (no window).
++
++ Note: the Ultravnc extensions only apply to servers that support
++ them. x11vnc/libvncserver supports some of them.
+
.SH ENCODINGS
The server supplies information in whatever format is desired by the
client, in order to make the client as easy as possible to implement.
+diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/y.out vnc_unixsrc/vncviewer/y.out
+--- vnc_unixsrc.orig/vncviewer/y.out 1969-12-31 19:00:00.000000000 -0500
++++ vnc_unixsrc/vncviewer/y.out 2007-02-18 16:06:22.000000000 -0500
+@@ -0,0 +1,23 @@
++Connected to RFB server, using protocol version 3.3
++No authentication needed
++Desktop name "squirtle:0.0"
++VNC server default format:
++ 16 bits per pixel.
++ Least significant byte first in each pixel.
++ True colour: max red 31 green 63 blue 31, shift red 11 green 5 blue 0
++Using default colormap which is TrueColor. Pixel format:
++ 32 bits per pixel.
++ Least significant byte first in each pixel.
++ True colour: max red 255 green 255 blue 255, shift red 16 green 8 blue 0
++useShm: 1
++Using shared memory PutImage ycrop=0
++desktopWin backingstore: 0
++desktopWin save_under: 0
++
++*ChatOpen*
++
++send>
++Chat: Hola.
++send> send>
++Chat: Tryin' to chill dude, that's all....
++send> send> send> send> send> ShmCleanup called
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/zrle.c vnc_unixsrc/vncviewer/zrle.c
--- vnc_unixsrc.orig/vncviewer/zrle.c 2007-02-04 18:59:50.000000000 -0500
-+++ vnc_unixsrc/vncviewer/zrle.c 2007-02-03 20:57:56.000000000 -0500
-@@ -0,0 +1,449 @@
++++ vnc_unixsrc/vncviewer/zrle.c 2007-02-17 22:36:37.000000000 -0500
+@@ -0,0 +1,455 @@
+/*
+ * Copyright (C) 2005 Johannes E. Schindelin. All Rights Reserved.
+ *
@@ -2898,10 +7018,14 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/zrle.c vnc_unixsrc/vncviewer/
+
+#define FillRectangle(x, y, w, h, color) \
+ { \
-+ XGCValues gcv; \
-+ gcv.foreground = color; \
-+ XChangeGC(dpy, gc, GCForeground, &gcv); \
-+ XFillRectangle(dpy, desktopWin, gc, x, y, w, h); \
++ XGCValues _gcv; \
++ _gcv.foreground = color; \
++ if (!appData.useBackingstore) { \
++ FillScreen(x, y, w, h, _gcv.foreground); \
++ } else { \
++ XChangeGC(dpy, gc, GCForeground, &_gcv); \
++ XFillRectangle(dpy, desktopWin, gc, x, y, w, h); \
++ } \
+ }
+
+static int HandleZRLETile(
@@ -3298,15 +7422,1772 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/zrle.c vnc_unixsrc/vncviewer/
+#undef REALBPP
+
+#undef UNCOMP
++
++#undef FillRectangle
+diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/zrleencodetemplate.c vnc_unixsrc/vncviewer/zrleencodetemplate.c
+--- vnc_unixsrc.orig/vncviewer/zrleencodetemplate.c 1969-12-31 19:00:00.000000000 -0500
++++ vnc_unixsrc/vncviewer/zrleencodetemplate.c 2007-02-04 23:18:09.000000000 -0500
+@@ -0,0 +1,317 @@
++/*
++ * Copyright (C) 2002 RealVNC Ltd. All Rights Reserved.
++ * Copyright (C) 2003 Sun Microsystems, Inc.
++ *
++ * This is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This software is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this software; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
++ * USA.
++ */
++
++/*
++ * Before including this file, you must define a number of CPP macros.
++ *
++ * BPP should be 8, 16 or 32 depending on the bits per pixel.
++ * GET_IMAGE_INTO_BUF should be some code which gets a rectangle of pixel data
++ * into the given buffer. EXTRA_ARGS can be defined to pass any other
++ * arguments needed by GET_IMAGE_INTO_BUF.
++ *
++ * Note that the buf argument to ZRLE_ENCODE needs to be at least one pixel
++ * bigger than the largest tile of pixel data, since the ZRLE encoding
++ * algorithm writes to the position one past the end of the pixel data.
++ */
++
++#include "zrleoutstream.h"
++#include "zrlepalettehelper.h"
++#include <assert.h>
++
++/* __RFB_CONCAT2 concatenates its two arguments. __RFB_CONCAT2E does the same
++ but also expands its arguments if they are macros */
++
++#ifndef __RFB_CONCAT2E
++#define __RFB_CONCAT2(a,b) a##b
++#define __RFB_CONCAT2E(a,b) __RFB_CONCAT2(a,b)
++#endif
++
++#ifndef __RFB_CONCAT3E
++#define __RFB_CONCAT3(a,b,c) a##b##c
++#define __RFB_CONCAT3E(a,b,c) __RFB_CONCAT3(a,b,c)
++#endif
++
++#undef END_FIX
++#if ZYWRLE_ENDIAN == ENDIAN_LITTLE
++# define END_FIX LE
++#elif ZYWRLE_ENDIAN == ENDIAN_BIG
++# define END_FIX BE
++#else
++# define END_FIX NE
++#endif
++
++#ifdef CPIXEL
++#define PIXEL_T __RFB_CONCAT2E(zrle_U,BPP)
++#define zrleOutStreamWRITE_PIXEL __RFB_CONCAT2E(zrleOutStreamWriteOpaque,CPIXEL)
++#define ZRLE_ENCODE __RFB_CONCAT3E(zrleEncode,CPIXEL,END_FIX)
++#define ZRLE_ENCODE_TILE __RFB_CONCAT3E(zrleEncodeTile,CPIXEL,END_FIX)
++#define BPPOUT 24
++#elif BPP==15
++#define PIXEL_T __RFB_CONCAT2E(zrle_U,16)
++#define zrleOutStreamWRITE_PIXEL __RFB_CONCAT2E(zrleOutStreamWriteOpaque,16)
++#define ZRLE_ENCODE __RFB_CONCAT3E(zrleEncode,BPP,END_FIX)
++#define ZRLE_ENCODE_TILE __RFB_CONCAT3E(zrleEncodeTile,BPP,END_FIX)
++#define BPPOUT 16
++#else
++#define PIXEL_T __RFB_CONCAT2E(zrle_U,BPP)
++#define zrleOutStreamWRITE_PIXEL __RFB_CONCAT2E(zrleOutStreamWriteOpaque,BPP)
++#define ZRLE_ENCODE __RFB_CONCAT3E(zrleEncode,BPP,END_FIX)
++#define ZRLE_ENCODE_TILE __RFB_CONCAT3E(zrleEncodeTile,BPP,END_FIX)
++#define BPPOUT BPP
++#endif
++
++#ifndef ZRLE_ONCE
++#define ZRLE_ONCE
++
++static const int bitsPerPackedPixel[] = {
++ 0, 1, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4
++};
++
++int zywrle_level;
++int zywrleBuf[rfbZRLETileWidth*rfbZRLETileHeight];
++
++static zrlePaletteHelper paletteHelper;
++
++#endif /* ZRLE_ONCE */
++
++void ZRLE_ENCODE_TILE (PIXEL_T* data, int w, int h, zrleOutStream* os);
++
++#if BPP!=8
++#define ZYWRLE_ENCODE
++#include "zywrletemplate.c"
++#endif
++
++static void ZRLE_ENCODE (int x, int y, int w, int h,
++ zrleOutStream* os, void* buf
++ EXTRA_ARGS
++ )
++{
++ int ty;
++ for (ty = y; ty < y+h; ty += rfbZRLETileHeight) {
++ int tx, th = rfbZRLETileHeight;
++ if (th > y+h-ty) th = y+h-ty;
++ for (tx = x; tx < x+w; tx += rfbZRLETileWidth) {
++ int tw = rfbZRLETileWidth;
++ if (tw > x+w-tx) tw = x+w-tx;
++
++ GET_IMAGE_INTO_BUF(tx,ty,tw,th,buf);
++
++ ZRLE_ENCODE_TILE((PIXEL_T*)buf, tw, th, os);
++ }
++ }
++ zrleOutStreamFlush(os);
++}
++
++
++void ZRLE_ENCODE_TILE (PIXEL_T* data, int w, int h, zrleOutStream* os)
++{
++ /* First find the palette and the number of runs */
++
++ zrlePaletteHelper *ph;
++
++ int runs = 0;
++ int singlePixels = 0;
++
++ rfbBool useRle;
++ rfbBool usePalette;
++
++ int estimatedBytes;
++ int plainRleBytes;
++ int i;
++
++ PIXEL_T* ptr = data;
++ PIXEL_T* end = ptr + h * w;
++ *end = ~*(end-1); /* one past the end is different so the while loop ends */
++
++ ph = &paletteHelper;
++ zrlePaletteHelperInit(ph);
++
++ while (ptr < end) {
++ PIXEL_T pix = *ptr;
++ if (*++ptr != pix) {
++ singlePixels++;
++ } else {
++ while (*++ptr == pix) ;
++ runs++;
++ }
++ zrlePaletteHelperInsert(ph, pix);
++ }
++
++ /* Solid tile is a special case */
++
++ if (ph->size == 1) {
++ zrleOutStreamWriteU8(os, 1);
++ zrleOutStreamWRITE_PIXEL(os, ph->palette[0]);
++ return;
++ }
++
++ /* Try to work out whether to use RLE and/or a palette. We do this by
++ estimating the number of bytes which will be generated and picking the
++ method which results in the fewest bytes. Of course this may not result
++ in the fewest bytes after compression... */
++
++ useRle = FALSE;
++ usePalette = FALSE;
++
++ estimatedBytes = w * h * (BPPOUT/8); /* start assuming raw */
++
++#if BPP!=8
++ if( (zywrle_level>0)&& !(zywrle_level & 0x80) ){
++ estimatedBytes >>= zywrle_level;
++ }
++#endif
++
++ plainRleBytes = ((BPPOUT/8)+1) * (runs + singlePixels);
++
++ if (plainRleBytes < estimatedBytes) {
++ useRle = TRUE;
++ estimatedBytes = plainRleBytes;
++ }
++
++ if (ph->size < 128) {
++ int paletteRleBytes = (BPPOUT/8) * ph->size + 2 * runs + singlePixels;
++
++ if (paletteRleBytes < estimatedBytes) {
++ useRle = TRUE;
++ usePalette = TRUE;
++ estimatedBytes = paletteRleBytes;
++ }
++
++ if (ph->size < 17) {
++ int packedBytes = ((BPPOUT/8) * ph->size +
++ w * h * bitsPerPackedPixel[ph->size-1] / 8);
++
++ if (packedBytes < estimatedBytes) {
++ useRle = FALSE;
++ usePalette = TRUE;
++ estimatedBytes = packedBytes;
++ }
++ }
++ }
++
++ if (!usePalette) ph->size = 0;
++
++ zrleOutStreamWriteU8(os, (useRle ? 128 : 0) | ph->size);
++
++ for (i = 0; i < ph->size; i++) {
++ zrleOutStreamWRITE_PIXEL(os, ph->palette[i]);
++ }
++
++ if (useRle) {
++
++ PIXEL_T* ptr = data;
++ PIXEL_T* end = ptr + w * h;
++ PIXEL_T* runStart;
++ PIXEL_T pix;
++ while (ptr < end) {
++ int len;
++ runStart = ptr;
++ pix = *ptr++;
++ while (*ptr == pix && ptr < end)
++ ptr++;
++ len = ptr - runStart;
++ if (len <= 2 && usePalette) {
++ int index = zrlePaletteHelperLookup(ph, pix);
++ if (len == 2)
++ zrleOutStreamWriteU8(os, index);
++ zrleOutStreamWriteU8(os, index);
++ continue;
++ }
++ if (usePalette) {
++ int index = zrlePaletteHelperLookup(ph, pix);
++ zrleOutStreamWriteU8(os, index | 128);
++ } else {
++ zrleOutStreamWRITE_PIXEL(os, pix);
++ }
++ len -= 1;
++ while (len >= 255) {
++ zrleOutStreamWriteU8(os, 255);
++ len -= 255;
++ }
++ zrleOutStreamWriteU8(os, len);
++ }
++
++ } else {
++
++ /* no RLE */
++
++ if (usePalette) {
++ int bppp;
++ PIXEL_T* ptr = data;
++
++ /* packed pixels */
++
++ assert (ph->size < 17);
++
++ bppp = bitsPerPackedPixel[ph->size-1];
++
++ for (i = 0; i < h; i++) {
++ zrle_U8 nbits = 0;
++ zrle_U8 byte = 0;
++
++ PIXEL_T* eol = ptr + w;
++
++ while (ptr < eol) {
++ PIXEL_T pix = *ptr++;
++ zrle_U8 index = zrlePaletteHelperLookup(ph, pix);
++ byte = (byte << bppp) | index;
++ nbits += bppp;
++ if (nbits >= 8) {
++ zrleOutStreamWriteU8(os, byte);
++ nbits = 0;
++ }
++ }
++ if (nbits > 0) {
++ byte <<= 8 - nbits;
++ zrleOutStreamWriteU8(os, byte);
++ }
++ }
++ } else {
++
++ /* raw */
++
++#if BPP!=8
++ if( (zywrle_level>0)&& !(zywrle_level & 0x80) ){
++ ZYWRLE_ANALYZE( data, data, w, h, w, zywrle_level, zywrleBuf );
++ zywrle_level |= 0x80;
++ ZRLE_ENCODE_TILE( data, w, h, os );
++ zywrle_level &= 0x7F;
++ }else
++#endif
++ {
++#ifdef CPIXEL
++ PIXEL_T *ptr;
++ for (ptr = data; ptr < data+w*h; ptr++) {
++ zrleOutStreamWRITE_PIXEL(os, *ptr);
++ }
++#else
++ zrleOutStreamWriteBytes(os, (zrle_U8 *)data, w*h*(BPP/8));
++#endif
++ }
++ }
++ }
++}
++
++#undef PIXEL_T
++#undef zrleOutStreamWRITE_PIXEL
++#undef ZRLE_ENCODE
++#undef ZRLE_ENCODE_TILE
++#undef ZYWRLE_ENCODE_TILE
++#undef BPPOUT
+diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/zrleoutstream.c vnc_unixsrc/vncviewer/zrleoutstream.c
+--- vnc_unixsrc.orig/vncviewer/zrleoutstream.c 1969-12-31 19:00:00.000000000 -0500
++++ vnc_unixsrc/vncviewer/zrleoutstream.c 2005-05-15 10:57:54.000000000 -0400
+@@ -0,0 +1,275 @@
++/*
++ * Copyright (C) 2002 RealVNC Ltd. All Rights Reserved.
++ * Copyright (C) 2003 Sun Microsystems, Inc.
++ *
++ * This is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This software is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this software; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
++ * USA.
++ */
++
++#include "zrleoutstream.h"
++#include <stdlib.h>
++
++#define ZRLE_IN_BUFFER_SIZE 16384
++#define ZRLE_OUT_BUFFER_SIZE 1024
++#undef ZRLE_DEBUG
++
++static rfbBool zrleBufferAlloc(zrleBuffer *buffer, int size)
++{
++ buffer->ptr = buffer->start = malloc(size);
++ if (buffer->start == NULL) {
++ buffer->end = NULL;
++ return FALSE;
++ }
++
++ buffer->end = buffer->start + size;
++
++ return TRUE;
++}
++
++static void zrleBufferFree(zrleBuffer *buffer)
++{
++ if (buffer->start)
++ free(buffer->start);
++ buffer->start = buffer->ptr = buffer->end = NULL;
++}
++
++static rfbBool zrleBufferGrow(zrleBuffer *buffer, int size)
++{
++ int offset;
++
++ size += buffer->end - buffer->start;
++ offset = ZRLE_BUFFER_LENGTH (buffer);
++
++ buffer->start = realloc(buffer->start, size);
++ if (!buffer->start) {
++ return FALSE;
++ }
++
++ buffer->end = buffer->start + size;
++ buffer->ptr = buffer->start + offset;
++
++ return TRUE;
++}
++
++zrleOutStream *zrleOutStreamNew(void)
++{
++ zrleOutStream *os;
++
++ os = malloc(sizeof(zrleOutStream));
++ if (os == NULL)
++ return NULL;
++
++ if (!zrleBufferAlloc(&os->in, ZRLE_IN_BUFFER_SIZE)) {
++ free(os);
++ return NULL;
++ }
++
++ if (!zrleBufferAlloc(&os->out, ZRLE_OUT_BUFFER_SIZE)) {
++ zrleBufferFree(&os->in);
++ free(os);
++ return NULL;
++ }
++
++ os->zs.zalloc = Z_NULL;
++ os->zs.zfree = Z_NULL;
++ os->zs.opaque = Z_NULL;
++ if (deflateInit(&os->zs, Z_DEFAULT_COMPRESSION) != Z_OK) {
++ zrleBufferFree(&os->in);
++ free(os);
++ return NULL;
++ }
++
++ return os;
++}
++
++void zrleOutStreamFree (zrleOutStream *os)
++{
++ deflateEnd(&os->zs);
++ zrleBufferFree(&os->in);
++ zrleBufferFree(&os->out);
++ free(os);
++}
++
++rfbBool zrleOutStreamFlush(zrleOutStream *os)
++{
++ os->zs.next_in = os->in.start;
++ os->zs.avail_in = ZRLE_BUFFER_LENGTH (&os->in);
++
++#ifdef ZRLE_DEBUG
++ rfbLog("zrleOutStreamFlush: avail_in %d\n", os->zs.avail_in);
++#endif
++
++ while (os->zs.avail_in != 0) {
++ do {
++ int ret;
++
++ if (os->out.ptr >= os->out.end &&
++ !zrleBufferGrow(&os->out, os->out.end - os->out.start)) {
++ rfbLog("zrleOutStreamFlush: failed to grow output buffer\n");
++ return FALSE;
++ }
++
++ os->zs.next_out = os->out.ptr;
++ os->zs.avail_out = os->out.end - os->out.ptr;
++
++#ifdef ZRLE_DEBUG
++ rfbLog("zrleOutStreamFlush: calling deflate, avail_in %d, avail_out %d\n",
++ os->zs.avail_in, os->zs.avail_out);
++#endif
++
++ if ((ret = deflate(&os->zs, Z_SYNC_FLUSH)) != Z_OK) {
++ rfbLog("zrleOutStreamFlush: deflate failed with error code %d\n", ret);
++ return FALSE;
++ }
++
++#ifdef ZRLE_DEBUG
++ rfbLog("zrleOutStreamFlush: after deflate: %d bytes\n",
++ os->zs.next_out - os->out.ptr);
++#endif
++
++ os->out.ptr = os->zs.next_out;
++ } while (os->zs.avail_out == 0);
++ }
++
++ os->in.ptr = os->in.start;
++
++ return TRUE;
++}
++
++static int zrleOutStreamOverrun(zrleOutStream *os,
++ int size)
++{
++#ifdef ZRLE_DEBUG
++ rfbLog("zrleOutStreamOverrun\n");
++#endif
++
++ while (os->in.end - os->in.ptr < size && os->in.ptr > os->in.start) {
++ os->zs.next_in = os->in.start;
++ os->zs.avail_in = ZRLE_BUFFER_LENGTH (&os->in);
++
++ do {
++ int ret;
++
++ if (os->out.ptr >= os->out.end &&
++ !zrleBufferGrow(&os->out, os->out.end - os->out.start)) {
++ rfbLog("zrleOutStreamOverrun: failed to grow output buffer\n");
++ return FALSE;
++ }
++
++ os->zs.next_out = os->out.ptr;
++ os->zs.avail_out = os->out.end - os->out.ptr;
++
++#ifdef ZRLE_DEBUG
++ rfbLog("zrleOutStreamOverrun: calling deflate, avail_in %d, avail_out %d\n",
++ os->zs.avail_in, os->zs.avail_out);
++#endif
++
++ if ((ret = deflate(&os->zs, 0)) != Z_OK) {
++ rfbLog("zrleOutStreamOverrun: deflate failed with error code %d\n", ret);
++ return 0;
++ }
++
++#ifdef ZRLE_DEBUG
++ rfbLog("zrleOutStreamOverrun: after deflate: %d bytes\n",
++ os->zs.next_out - os->out.ptr);
++#endif
++
++ os->out.ptr = os->zs.next_out;
++ } while (os->zs.avail_out == 0);
++
++ /* output buffer not full */
++
++ if (os->zs.avail_in == 0) {
++ os->in.ptr = os->in.start;
++ } else {
++ /* but didn't consume all the data? try shifting what's left to the
++ * start of the buffer.
++ */
++ rfbLog("zrleOutStreamOverrun: out buf not full, but in data not consumed\n");
++ memmove(os->in.start, os->zs.next_in, os->in.ptr - os->zs.next_in);
++ os->in.ptr -= os->zs.next_in - os->in.start;
++ }
++ }
++
++ if (size > os->in.end - os->in.ptr)
++ size = os->in.end - os->in.ptr;
++
++ return size;
++}
++
++static int zrleOutStreamCheck(zrleOutStream *os, int size)
++{
++ if (os->in.ptr + size > os->in.end) {
++ return zrleOutStreamOverrun(os, size);
++ }
++ return size;
++}
++
++void zrleOutStreamWriteBytes(zrleOutStream *os,
++ const zrle_U8 *data,
++ int length)
++{
++ const zrle_U8* dataEnd = data + length;
++ while (data < dataEnd) {
++ int n = zrleOutStreamCheck(os, dataEnd - data);
++ memcpy(os->in.ptr, data, n);
++ os->in.ptr += n;
++ data += n;
++ }
++}
++
++void zrleOutStreamWriteU8(zrleOutStream *os, zrle_U8 u)
++{
++ zrleOutStreamCheck(os, 1);
++ *os->in.ptr++ = u;
++}
++
++void zrleOutStreamWriteOpaque8(zrleOutStream *os, zrle_U8 u)
++{
++ zrleOutStreamCheck(os, 1);
++ *os->in.ptr++ = u;
++}
++
++void zrleOutStreamWriteOpaque16 (zrleOutStream *os, zrle_U16 u)
++{
++ zrleOutStreamCheck(os, 2);
++ *os->in.ptr++ = ((zrle_U8*)&u)[0];
++ *os->in.ptr++ = ((zrle_U8*)&u)[1];
++}
++
++void zrleOutStreamWriteOpaque32 (zrleOutStream *os, zrle_U32 u)
++{
++ zrleOutStreamCheck(os, 4);
++ *os->in.ptr++ = ((zrle_U8*)&u)[0];
++ *os->in.ptr++ = ((zrle_U8*)&u)[1];
++ *os->in.ptr++ = ((zrle_U8*)&u)[2];
++ *os->in.ptr++ = ((zrle_U8*)&u)[3];
++}
++
++void zrleOutStreamWriteOpaque24A(zrleOutStream *os, zrle_U32 u)
++{
++ zrleOutStreamCheck(os, 3);
++ *os->in.ptr++ = ((zrle_U8*)&u)[0];
++ *os->in.ptr++ = ((zrle_U8*)&u)[1];
++ *os->in.ptr++ = ((zrle_U8*)&u)[2];
++}
++
++void zrleOutStreamWriteOpaque24B(zrleOutStream *os, zrle_U32 u)
++{
++ zrleOutStreamCheck(os, 3);
++ *os->in.ptr++ = ((zrle_U8*)&u)[1];
++ *os->in.ptr++ = ((zrle_U8*)&u)[2];
++ *os->in.ptr++ = ((zrle_U8*)&u)[3];
++}
+diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/zrleoutstream.h vnc_unixsrc/vncviewer/zrleoutstream.h
+--- vnc_unixsrc.orig/vncviewer/zrleoutstream.h 1969-12-31 19:00:00.000000000 -0500
++++ vnc_unixsrc/vncviewer/zrleoutstream.h 2004-05-25 06:05:15.000000000 -0400
+@@ -0,0 +1,62 @@
++/*
++ * Copyright (C) 2002 RealVNC Ltd. All Rights Reserved.
++ * Copyright (C) 2003 Sun Microsystems, Inc.
++ *
++ * This is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This software is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this software; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
++ * USA.
++ */
++
++#ifndef __ZRLE_OUT_STREAM_H__
++#define __ZRLE_OUT_STREAM_H__
++
++#include <zlib.h>
++#include "zrletypes.h"
++#include "rfb/rfb.h"
++
++typedef struct {
++ zrle_U8 *start;
++ zrle_U8 *ptr;
++ zrle_U8 *end;
++} zrleBuffer;
++
++typedef struct {
++ zrleBuffer in;
++ zrleBuffer out;
++
++ z_stream zs;
++} zrleOutStream;
++
++#define ZRLE_BUFFER_LENGTH(b) ((b)->ptr - (b)->start)
++
++zrleOutStream *zrleOutStreamNew (void);
++void zrleOutStreamFree (zrleOutStream *os);
++rfbBool zrleOutStreamFlush (zrleOutStream *os);
++void zrleOutStreamWriteBytes (zrleOutStream *os,
++ const zrle_U8 *data,
++ int length);
++void zrleOutStreamWriteU8 (zrleOutStream *os,
++ zrle_U8 u);
++void zrleOutStreamWriteOpaque8 (zrleOutStream *os,
++ zrle_U8 u);
++void zrleOutStreamWriteOpaque16 (zrleOutStream *os,
++ zrle_U16 u);
++void zrleOutStreamWriteOpaque32 (zrleOutStream *os,
++ zrle_U32 u);
++void zrleOutStreamWriteOpaque24A(zrleOutStream *os,
++ zrle_U32 u);
++void zrleOutStreamWriteOpaque24B(zrleOutStream *os,
++ zrle_U32 u);
++
++#endif /* __ZRLE_OUT_STREAM_H__ */
+diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/zrlepalettehelper.c vnc_unixsrc/vncviewer/zrlepalettehelper.c
+--- vnc_unixsrc.orig/vncviewer/zrlepalettehelper.c 1969-12-31 19:00:00.000000000 -0500
++++ vnc_unixsrc/vncviewer/zrlepalettehelper.c 2004-05-25 06:05:15.000000000 -0400
+@@ -0,0 +1,62 @@
++/*
++ * Copyright (C) 2002 RealVNC Ltd. All Rights Reserved.
++ * Copyright (C) 2003 Sun Microsystems, Inc.
++ *
++ * This is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This software is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this software; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
++ * USA.
++ */
++
++#include "zrlepalettehelper.h"
++#include <assert.h>
++#include <string.h>
++
++#define ZRLE_HASH(pix) (((pix) ^ ((pix) >> 17)) & 4095)
++
++void zrlePaletteHelperInit(zrlePaletteHelper *helper)
++{
++ memset(helper->palette, 0, sizeof(helper->palette));
++ memset(helper->index, 255, sizeof(helper->index));
++ memset(helper->key, 0, sizeof(helper->key));
++ helper->size = 0;
++}
++
++void zrlePaletteHelperInsert(zrlePaletteHelper *helper, zrle_U32 pix)
++{
++ if (helper->size < ZRLE_PALETTE_MAX_SIZE) {
++ int i = ZRLE_HASH(pix);
++
++ while (helper->index[i] != 255 && helper->key[i] != pix)
++ i++;
++ if (helper->index[i] != 255) return;
++
++ helper->index[i] = helper->size;
++ helper->key[i] = pix;
++ helper->palette[helper->size] = pix;
++ }
++ helper->size++;
++}
++
++int zrlePaletteHelperLookup(zrlePaletteHelper *helper, zrle_U32 pix)
++{
++ int i = ZRLE_HASH(pix);
++
++ assert(helper->size <= ZRLE_PALETTE_MAX_SIZE);
++
++ while (helper->index[i] != 255 && helper->key[i] != pix)
++ i++;
++ if (helper->index[i] != 255) return helper->index[i];
++
++ return -1;
++}
+diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/zrlepalettehelper.h vnc_unixsrc/vncviewer/zrlepalettehelper.h
+--- vnc_unixsrc.orig/vncviewer/zrlepalettehelper.h 1969-12-31 19:00:00.000000000 -0500
++++ vnc_unixsrc/vncviewer/zrlepalettehelper.h 2004-05-25 06:05:15.000000000 -0400
+@@ -0,0 +1,46 @@
++/*
++ * Copyright (C) 2002 RealVNC Ltd. All Rights Reserved.
++ * Copyright (C) 2003 Sun Microsystems, Inc.
++ *
++ * This is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This software is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this software; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
++ * USA.
++ */
++
++/*
++ * The PaletteHelper class helps us build up the palette from pixel data by
++ * storing a reverse index using a simple hash-table
++ */
++
++#ifndef __ZRLE_PALETTE_HELPER_H__
++#define __ZRLE_PALETTE_HELPER_H__
++
++#include "zrletypes.h"
++
++#define ZRLE_PALETTE_MAX_SIZE 127
++
++typedef struct {
++ zrle_U32 palette[ZRLE_PALETTE_MAX_SIZE];
++ zrle_U8 index[ZRLE_PALETTE_MAX_SIZE + 4096];
++ zrle_U32 key[ZRLE_PALETTE_MAX_SIZE + 4096];
++ int size;
++} zrlePaletteHelper;
++
++void zrlePaletteHelperInit (zrlePaletteHelper *helper);
++void zrlePaletteHelperInsert(zrlePaletteHelper *helper,
++ zrle_U32 pix);
++int zrlePaletteHelperLookup(zrlePaletteHelper *helper,
++ zrle_U32 pix);
++
++#endif /* __ZRLE_PALETTE_HELPER_H__ */
+diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/zrletypes.h vnc_unixsrc/vncviewer/zrletypes.h
+--- vnc_unixsrc.orig/vncviewer/zrletypes.h 1969-12-31 19:00:00.000000000 -0500
++++ vnc_unixsrc/vncviewer/zrletypes.h 2004-05-25 06:05:15.000000000 -0400
+@@ -0,0 +1,30 @@
++/*
++ * Copyright (C) 2002 RealVNC Ltd. All Rights Reserved.
++ *
++ * This is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This software is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this software; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
++ * USA.
++ */
++
++#ifndef __ZRLE_TYPES_H__
++#define __ZRLE_TYPES_H__
++
++typedef unsigned char zrle_U8;
++typedef unsigned short zrle_U16;
++typedef unsigned int zrle_U32;
++typedef signed char zrle_S8;
++typedef signed short zrle_S16;
++typedef signed int zrle_S32;
++
++#endif /* __ZRLE_TYPES_H__ */
+diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/zywrletemplate.c vnc_unixsrc/vncviewer/zywrletemplate.c
+--- vnc_unixsrc.orig/vncviewer/zywrletemplate.c 1969-12-31 19:00:00.000000000 -0500
++++ vnc_unixsrc/vncviewer/zywrletemplate.c 2007-02-04 23:24:16.000000000 -0500
+@@ -0,0 +1,804 @@
++
++/********************************************************************
++ * *
++ * THIS FILE IS PART OF THE 'ZYWRLE' VNC CODEC SOURCE CODE. *
++ * *
++ * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
++ * GOVERNED BY A FOLLOWING BSD-STYLE SOURCE LICENSE. *
++ * PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
++ * *
++ * THE 'ZYWRLE' VNC CODEC SOURCE CODE IS (C) COPYRIGHT 2006 *
++ * BY Hitachi Systems & Services, Ltd. *
++ * (Noriaki Yamazaki, Research & Developement Center) * *
++ * *
++ ********************************************************************
++Redistribution and use in source and binary forms, with or without
++modification, are permitted provided that the following conditions
++are met:
++
++- Redistributions of source code must retain the above copyright
++notice, this list of conditions and the following disclaimer.
++
++- Redistributions in binary form must reproduce the above copyright
++notice, this list of conditions and the following disclaimer in the
++documentation and/or other materials provided with the distribution.
++
++- Neither the name of the Hitachi Systems & Services, Ltd. nor
++the names of its contributors may be used to endorse or promote
++products derived from this software without specific prior written
++permission.
++
++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION
++OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ ********************************************************************/
++
++//#define ZYWRLE_ENCODE
++//#define ZYWRLE_DECODE
++#define ZYWRLE_QUANTIZE
++
++//[References]
++// PLHarr:
++// Senecal, J. G., P. Lindstrom, M. A. Duchaineau, and K. I. Joy, "An Improved N-Bit to N-Bit Reversible Haar-Like Transform," Pacific Graphics 2004, October 2004, pp. 371-380.
++// EZW:
++// Shapiro, JM: Embedded Image Coding Using Zerotrees of Wavelet Coefficients, IEEE Trans. Signal. Process., Vol.41, pp.3445-3462 (1993).
++
++
++// Template Macro stuffs.
++#undef ZYWRLE_ANALYZE
++#undef ZYWRLE_SYNTHESIZE
++#define ZYWRLE_ANALYZE __RFB_CONCAT3E(zywrleAnalyze,BPP,END_FIX)
++#define ZYWRLE_SYNTHESIZE __RFB_CONCAT3E(zywrleSynthesize,BPP,END_FIX)
++
++#define ZYWRLE_RGBYUV __RFB_CONCAT3E(zywrleRGBYUV,BPP,END_FIX)
++#define ZYWRLE_YUVRGB __RFB_CONCAT3E(zywrleYUVRGB,BPP,END_FIX)
++#define ZYWRLE_YMASK __RFB_CONCAT2E(ZYWRLE_YMASK,BPP)
++#define ZYWRLE_UVMASK __RFB_CONCAT2E(ZYWRLE_UVMASK,BPP)
++#define ZYWRLE_LOAD_PIXEL __RFB_CONCAT2E(ZYWRLE_LOAD_PIXEL,BPP)
++#define ZYWRLE_SAVE_PIXEL __RFB_CONCAT2E(ZYWRLE_SAVE_PIXEL,BPP)
++
++// Packing/Unpacking pixel stuffs.
++// Endian conversion stuffs.
++#undef S_0
++#undef S_1
++#undef L_0
++#undef L_1
++#undef L_2
++#if ZYWRLE_ENDIAN == ENDIAN_BIG
++# define S_0 1
++# define S_1 0
++# define L_0 3
++# define L_1 2
++# define L_2 1
++#else
++# define S_0 0
++# define S_1 1
++# define L_0 0
++# define L_1 1
++# define L_2 2
++#endif
++
++// Load/Save pixel stuffs.
++#define ZYWRLE_YMASK15 0xFFFFFFF8
++#define ZYWRLE_UVMASK15 0xFFFFFFF8
++#define ZYWRLE_LOAD_PIXEL15(pSrc,R,G,B) { \
++ R = (((unsigned char*)pSrc)[S_1]<< 1)& 0xF8; \
++ G = ((((unsigned char*)pSrc)[S_1]<< 6)|(((unsigned char*)pSrc)[S_0]>> 2))& 0xF8; \
++ B = (((unsigned char*)pSrc)[S_0]<< 3)& 0xF8; \
++}
++#define ZYWRLE_SAVE_PIXEL15(pDst,R,G,B) { \
++ R &= 0xF8; \
++ G &= 0xF8; \
++ B &= 0xF8; \
++ ((unsigned char*)pDst)[S_1] = (unsigned char)( (R>>1)|(G>>6) ); \
++ ((unsigned char*)pDst)[S_0] = (unsigned char)(((B>>3)|(G<<2))& 0xFF); \
++}
++#define ZYWRLE_YMASK16 0xFFFFFFFC
++#define ZYWRLE_UVMASK16 0xFFFFFFF8
++#define ZYWRLE_LOAD_PIXEL16(pSrc,R,G,B) { \
++ R = ((unsigned char*)pSrc)[S_1] & 0xF8; \
++ G = ((((unsigned char*)pSrc)[S_1]<< 5)|(((unsigned char*)pSrc)[S_0]>> 3))& 0xFC; \
++ B = (((unsigned char*)pSrc)[S_0]<< 3)& 0xF8; \
++}
++#define ZYWRLE_SAVE_PIXEL16(pDst,R,G,B) { \
++ R &= 0xF8; \
++ G &= 0xFC; \
++ B &= 0xF8; \
++ ((unsigned char*)pDst)[S_1] = (unsigned char)( R |(G>>5) ); \
++ ((unsigned char*)pDst)[S_0] = (unsigned char)(((B>>3)|(G<<3))& 0xFF); \
++}
++#define ZYWRLE_YMASK32 0xFFFFFFFF
++#define ZYWRLE_UVMASK32 0xFFFFFFFF
++#define ZYWRLE_LOAD_PIXEL32(pSrc,R,G,B) { \
++ R = ((unsigned char*)pSrc)[L_2]; \
++ G = ((unsigned char*)pSrc)[L_1]; \
++ B = ((unsigned char*)pSrc)[L_0]; \
++}
++#define ZYWRLE_SAVE_PIXEL32(pDst,R,G,B) { \
++ ((unsigned char*)pDst)[L_2] = (unsigned char)R; \
++ ((unsigned char*)pDst)[L_1] = (unsigned char)G; \
++ ((unsigned char*)pDst)[L_0] = (unsigned char)B; \
++}
++
++#ifndef ZYWRLE_ONCE
++#define ZYWRLE_ONCE
++
++#ifdef WIN32
++#define InlineX __inline
++#else
++#define InlineX inline
++#endif
++
++#ifdef ZYWRLE_ENCODE
++// Tables for Coefficients filtering.
++# ifndef ZYWRLE_QUANTIZE
++// Type A:lower bit omitting of EZW style.
++const static unsigned int zywrleParam[3][3]={
++ {0x0000F000,0x00000000,0x00000000},
++ {0x0000C000,0x00F0F0F0,0x00000000},
++ {0x0000C000,0x00C0C0C0,0x00F0F0F0},
++// {0x0000FF00,0x00000000,0x00000000},
++// {0x0000FF00,0x00FFFFFF,0x00000000},
++// {0x0000FF00,0x00FFFFFF,0x00FFFFFF},
++};
++# else
++// Type B:Non liner quantization filter.
++static const signed char zywrleConv[4][256]={
++{ // bi=5, bo=5 r=0.0:PSNR=24.849
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++},
++{ // bi=5, bo=5 r=2.0:PSNR=74.031
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 32,
++ 32, 32, 32, 32, 32, 32, 32, 32,
++ 32, 32, 32, 32, 32, 32, 32, 32,
++ 48, 48, 48, 48, 48, 48, 48, 48,
++ 48, 48, 48, 56, 56, 56, 56, 56,
++ 56, 56, 56, 56, 64, 64, 64, 64,
++ 64, 64, 64, 64, 72, 72, 72, 72,
++ 72, 72, 72, 72, 80, 80, 80, 80,
++ 80, 80, 88, 88, 88, 88, 88, 88,
++ 88, 88, 88, 88, 88, 88, 96, 96,
++ 96, 96, 96, 104, 104, 104, 104, 104,
++ 104, 104, 104, 104, 104, 112, 112, 112,
++ 112, 112, 112, 112, 112, 112, 120, 120,
++ 120, 120, 120, 120, 120, 120, 120, 120,
++ 0, -120, -120, -120, -120, -120, -120, -120,
++ -120, -120, -120, -112, -112, -112, -112, -112,
++ -112, -112, -112, -112, -104, -104, -104, -104,
++ -104, -104, -104, -104, -104, -104, -96, -96,
++ -96, -96, -96, -88, -88, -88, -88, -88,
++ -88, -88, -88, -88, -88, -88, -88, -80,
++ -80, -80, -80, -80, -80, -72, -72, -72,
++ -72, -72, -72, -72, -72, -64, -64, -64,
++ -64, -64, -64, -64, -64, -56, -56, -56,
++ -56, -56, -56, -56, -56, -56, -48, -48,
++ -48, -48, -48, -48, -48, -48, -48, -48,
++ -48, -32, -32, -32, -32, -32, -32, -32,
++ -32, -32, -32, -32, -32, -32, -32, -32,
++ -32, -32, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++},
++{ // bi=5, bo=4 r=2.0:PSNR=64.441
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 48, 48, 48, 48, 48, 48, 48, 48,
++ 48, 48, 48, 48, 48, 48, 48, 48,
++ 48, 48, 48, 48, 48, 48, 48, 48,
++ 64, 64, 64, 64, 64, 64, 64, 64,
++ 64, 64, 64, 64, 64, 64, 64, 64,
++ 80, 80, 80, 80, 80, 80, 80, 80,
++ 80, 80, 80, 80, 80, 88, 88, 88,
++ 88, 88, 88, 88, 88, 88, 88, 88,
++ 104, 104, 104, 104, 104, 104, 104, 104,
++ 104, 104, 104, 112, 112, 112, 112, 112,
++ 112, 112, 112, 112, 120, 120, 120, 120,
++ 120, 120, 120, 120, 120, 120, 120, 120,
++ 0, -120, -120, -120, -120, -120, -120, -120,
++ -120, -120, -120, -120, -120, -112, -112, -112,
++ -112, -112, -112, -112, -112, -112, -104, -104,
++ -104, -104, -104, -104, -104, -104, -104, -104,
++ -104, -88, -88, -88, -88, -88, -88, -88,
++ -88, -88, -88, -88, -80, -80, -80, -80,
++ -80, -80, -80, -80, -80, -80, -80, -80,
++ -80, -64, -64, -64, -64, -64, -64, -64,
++ -64, -64, -64, -64, -64, -64, -64, -64,
++ -64, -48, -48, -48, -48, -48, -48, -48,
++ -48, -48, -48, -48, -48, -48, -48, -48,
++ -48, -48, -48, -48, -48, -48, -48, -48,
++ -48, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++},
++{ // bi=5, bo=2 r=2.0:PSNR=43.175
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 88, 88, 88, 88, 88, 88, 88, 88,
++ 88, 88, 88, 88, 88, 88, 88, 88,
++ 88, 88, 88, 88, 88, 88, 88, 88,
++ 88, 88, 88, 88, 88, 88, 88, 88,
++ 88, 88, 88, 88, 88, 88, 88, 88,
++ 88, 88, 88, 88, 88, 88, 88, 88,
++ 88, 88, 88, 88, 88, 88, 88, 88,
++ 88, 88, 88, 88, 88, 88, 88, 88,
++ 0, -88, -88, -88, -88, -88, -88, -88,
++ -88, -88, -88, -88, -88, -88, -88, -88,
++ -88, -88, -88, -88, -88, -88, -88, -88,
++ -88, -88, -88, -88, -88, -88, -88, -88,
++ -88, -88, -88, -88, -88, -88, -88, -88,
++ -88, -88, -88, -88, -88, -88, -88, -88,
++ -88, -88, -88, -88, -88, -88, -88, -88,
++ -88, -88, -88, -88, -88, -88, -88, -88,
++ -88, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++}
++};
++const static signed char* zywrleParam[3][3][3]={
++ {{zywrleConv[0],zywrleConv[2],zywrleConv[0]},{zywrleConv[0],zywrleConv[0],zywrleConv[0]},{zywrleConv[0],zywrleConv[0],zywrleConv[0]}},
++ {{zywrleConv[0],zywrleConv[3],zywrleConv[0]},{zywrleConv[1],zywrleConv[1],zywrleConv[1]},{zywrleConv[0],zywrleConv[0],zywrleConv[0]}},
++ {{zywrleConv[0],zywrleConv[3],zywrleConv[0]},{zywrleConv[2],zywrleConv[2],zywrleConv[2]},{zywrleConv[1],zywrleConv[1],zywrleConv[1]}},
++};
++# endif
++#endif
++
++static InlineX void Harr( signed char* pX0, signed char* pX1 ){
++ // Piecewise-Linear Harr(PLHarr)
++ int X0=(int)*pX0, X1=(int)*pX1;
++ int orgX0=X0, orgX1=X1;
++ if( (X0^X1)&0x80 ){
++ // differ sign
++ X1 += X0;
++ if( ((X1^orgX1)&0x80)==0 ){
++ // |X1| > |X0|
++ X0 -= X1; // H = -B
++ }
++ }else{
++ // same sign
++ X0 -= X1;
++ if( ((X0^orgX0)&0x80)==0 ){
++ // |X0| > |X1|
++ X1 += X0; // L = A
++ }
++ }
++ *pX0 = (signed char)X1;
++ *pX1 = (signed char)X0;
++}
++// 1D-Wavelet transform.
++//
++// In coefficients array, the famous 'pyramid' decomposition is well used.
++//
++// 1D Model:
++// |L0L0L0L0|L0L0L0L0|H0H0H0H0|H0H0H0H0| : level 0
++// |L1L1L1L1|H1H1H1H1|H0H0H0H0|H0H0H0H0| : level 1
++//
++// But this method needs line buffer because H/L is different position from X0/X1.
++// So, I used 'interleave' decomposition instead of it.
++//
++// 1D Model:
++// |L0H0L0H0|L0H0L0H0|L0H0L0H0|L0H0L0H0| : level 0
++// |L1H0H1H0|L1H0H1H0|L1H0H1H0|L1H0H1H0| : level 1
++//
++// In this method, H/L and X0/X1 is always same position.
++// This lead us to more speed and less memory.
++// Of cause, the result of both method is quite same
++// because it's only difference that coefficient position.
++
++static InlineX void WaveletLevel( int* data, int size, int l, int SkipPixel ){
++ int s, ofs;
++ signed char* pX0;
++ signed char* end;
++
++ pX0 = (signed char*)data;
++ s = (8<<l)*SkipPixel;
++ end = pX0+(size>>(l+1))*s;
++ s -= 2;
++ ofs = (4<<l)*SkipPixel;
++ while( pX0 < end ){
++ Harr( pX0, pX0+ofs );
++ pX0++;
++ Harr( pX0, pX0+ofs );
++ pX0++;
++ Harr( pX0, pX0+ofs );
++ pX0 += s;
++ }
++}
++#define InvWaveletLevel(d,s,l,pix) WaveletLevel(d,s,l,pix)
++
++#ifdef ZYWRLE_ENCODE
++# ifndef ZYWRLE_QUANTIZE
++// Type A:lower bit omitting of EZW style.
++static InlineX void FilterWaveletSquare( int* pBuf, int width, int height, int level, int l ){
++ int r, s;
++ int x, y;
++ int* pH;
++ const unsigned int* pM;
++
++ pM = &(zywrleParam[level-1][l]);
++ s = 2<<l;
++ for( r=1; r<4; r++ ){
++ pH = pBuf;
++ if( r & 0x01 ){
++ pH += s>>1;
++ }
++ if( r & 0x02 ){
++ pH += (s>>1)*width;
++ }
++ for( y=0; y<height/s; y++ ){
++ for( x=0; x<width/s; x++ ){
++ // these are same following code.
++ // pH[x] = pH[x] / (~pM[x]+1) * (~pM[x]+1);
++ // ( round pH[x] with pM[x] bit )
++ // '&' operator isn't 'round' but is 'floor'.
++ // So, we must offset when pH[x] is negative.
++ if( ((signed char*)pH)[0] & 0x80 ){
++ ((signed char*)pH)[0] += ~((signed char*)pM)[0];
++ }
++ if( ((signed char*)pH)[1] & 0x80 ){
++ ((signed char*)pH)[1] += ~((signed char*)pM)[1];
++ }
++ if( ((signed char*)pH)[2] & 0x80 ){
++ ((signed char*)pH)[2] += ~((signed char*)pM)[2];
++ }
++ *pH &= *pM;
++ pH += s;
++ }
++ pH += (s-1)*width;
++ }
++ }
++}
++# else
++// Type B:Non liner quantization filter.
++//
++// Coefficients have Gaussian curve and smaller value which is
++// large part of coefficients isn't more important than larger value.
++// So, I use filter of Non liner quantize/dequantize table.
++// In general, Non liner quantize formula is explained as following.
++//
++// y=f(x) = sign(x)*round( ((abs(x)/(2^7))^ r )* 2^(bo-1) )*2^(8-bo)
++// x=f-1(y) = sign(y)*round( ((abs(y)/(2^7))^(1/r))* 2^(bi-1) )*2^(8-bi)
++// ( r:power coefficient bi:effective MSB in input bo:effective MSB in output )
++//
++// r < 1.0 : Smaller value is more important than larger value.
++// r > 1.0 : Larger value is more important than smaller value.
++// r = 1.0 : Liner quantization which is same with EZW style.
++//
++// r = 0.75 is famous non liner quantization used in MP3 audio codec.
++// In contrast to audio data, larger value is important in wavelet coefficients.
++// So, I select r = 2.0 table( quantize is x^2, dequantize sqrt(x) ).
++//
++// As compared with EZW style liner quantization, this filter tended to be
++// more sharp edge and be more compression rate but be more blocking noise and be less quality.
++// Especially, the surface of graphic objects has distinguishable noise in middle quality mode.
++//
++// We need only quantized-dequantized(filtered) value rather than quantized value itself
++// because all values are packed or palette-lized in later ZRLE section.
++// This lead us not to need to modify client decoder when we change
++// the filtering procedure in future.
++// Client only decodes coefficients given by encoder.
++static InlineX void FilterWaveletSquare( int* pBuf, int width, int height, int level, int l ){
++ int r, s;
++ int x, y;
++ int* pH;
++ const signed char** pM;
++
++ pM = zywrleParam[level-1][l];
++ s = 2<<l;
++ for( r=1; r<4; r++ ){
++ pH = pBuf;
++ if( r & 0x01 ){
++ pH += s>>1;
++ }
++ if( r & 0x02 ){
++ pH += (s>>1)*width;
++ }
++ for( y=0; y<height/s; y++ ){
++ for( x=0; x<width/s; x++ ){
++ ((signed char*)pH)[0] = pM[0][((unsigned char*)pH)[0]];
++ ((signed char*)pH)[1] = pM[1][((unsigned char*)pH)[1]];
++ ((signed char*)pH)[2] = pM[2][((unsigned char*)pH)[2]];
++ pH += s;
++ }
++ pH += (s-1)*width;
++ }
++ }
++}
++# endif
++
++static InlineX void Wavelet( int* pBuf, int width, int height, int level ){
++ int l, s;
++ int* pTop;
++ int* pEnd;
++
++ for( l=0; l<level; l++ ){
++ pTop = pBuf;
++ pEnd = pBuf+height*width;
++ s = width<<l;
++ while( pTop < pEnd ){
++ WaveletLevel( pTop, width, l, 1 );
++ pTop += s;
++ }
++ pTop = pBuf;
++ pEnd = pBuf+width;
++ s = 1<<l;
++ while( pTop < pEnd ){
++ WaveletLevel( pTop, height,l, width );
++ pTop += s;
++ }
++ FilterWaveletSquare( pBuf, width, height, level, l );
++ }
++}
++#endif
++#ifdef ZYWRLE_DECODE
++static InlineX void InvWavelet( int* pBuf, int width, int height, int level ){
++ int l, s;
++ int* pTop;
++ int* pEnd;
++
++ for( l=level-1; l>=0; l-- ){
++ pTop = pBuf;
++ pEnd = pBuf+width;
++ s = 1<<l;
++ while( pTop < pEnd ){
++ InvWaveletLevel( pTop, height,l, width );
++ pTop += s;
++ }
++ pTop = pBuf;
++ pEnd = pBuf+height*width;
++ s = width<<l;
++ while( pTop < pEnd ){
++ InvWaveletLevel( pTop, width, l, 1 );
++ pTop += s;
++ }
++ }
++}
++#endif
++
++// Load/Save coefficients stuffs.
++// Coefficients manages as 24 bits little-endian pixel.
++#define ZYWRLE_LOAD_COEFF(pSrc,R,G,B) { \
++ R = ((signed char*)pSrc)[2]; \
++ G = ((signed char*)pSrc)[1]; \
++ B = ((signed char*)pSrc)[0]; \
++}
++#define ZYWRLE_SAVE_COEFF(pDst,R,G,B) { \
++ ((signed char*)pDst)[2] = (signed char)R; \
++ ((signed char*)pDst)[1] = (signed char)G; \
++ ((signed char*)pDst)[0] = (signed char)B; \
++}
++
++// RGB <=> YUV conversion stuffs.
++// YUV coversion is explained as following formula in strict meaning:
++// Y = 0.299R + 0.587G + 0.114B ( 0<=Y<=255)
++// U = -0.169R - 0.331G + 0.500B (-128<=U<=127)
++// V = 0.500R - 0.419G - 0.081B (-128<=V<=127)
++//
++// I use simple conversion RCT(reversible color transform) which is described
++// in JPEG-2000 specification.
++// Y = (R + 2G + B)/4 ( 0<=Y<=255)
++// U = B-G (-256<=U<=255)
++// V = R-G (-256<=V<=255)
++
++#define ROUND(x) (((x)<0)?0:(((x)>255)?255:(x)))
++ // RCT is N-bit RGB to N-bit Y and N+1-bit UV.
++ // For make Same N-bit, UV is lossy.
++ // More exact PLHarr, we reduce to odd range(-127<=x<=127).
++#define ZYWRLE_RGBYUV1(R,G,B,Y,U,V,ymask,uvmask) { \
++ Y = (R+(G<<1)+B)>>2; \
++ U = B-G; \
++ V = R-G; \
++ Y -= 128; \
++ U >>= 1; \
++ V >>= 1; \
++ Y &= ymask; \
++ U &= uvmask; \
++ V &= uvmask; \
++ if( Y == -128 ){ \
++ Y += (0xFFFFFFFF-ymask+1); \
++ } \
++ if( U == -128 ){ \
++ U += (0xFFFFFFFF-uvmask+1); \
++ } \
++ if( V == -128 ){ \
++ V += (0xFFFFFFFF-uvmask+1); \
++ } \
++}
++#define ZYWRLE_YUVRGB1(R,G,B,Y,U,V) { \
++ Y += 128; \
++ U <<= 1; \
++ V <<= 1; \
++ G = Y-((U+V)>>2); \
++ B = U+G; \
++ R = V+G; \
++ G = ROUND(G); \
++ B = ROUND(B); \
++ R = ROUND(R); \
++}
++
++// coefficient packing/unpacking stuffs.
++// Wavelet transform makes 4 sub coefficient image from 1 original image.
++//
++// model with pyramid decomposition:
++// +------+------+
++// | | |
++// | L | Hx |
++// | | |
++// +------+------+
++// | | |
++// | H | Hxy |
++// | | |
++// +------+------+
++//
++// So, we must transfer each sub images individually in strict meaning.
++// But at least ZRLE meaning, following one decompositon image is same as
++// avobe individual sub image. I use this format.
++// (Strictly saying, transfer order is reverse(Hxy->Hy->Hx->L)
++// for simplified procedure for any wavelet level.)
++//
++// +------+------+
++// | L |
++// +------+------+
++// | Hx |
++// +------+------+
++// | Hy |
++// +------+------+
++// | Hxy |
++// +------+------+
++
++#define ZYWRLE_TRANSFER_COEFF(pBuf,data,r,width,height,level,TRANS) \
++ pH = pBuf; \
++ s = 2<<level; \
++ if( r & 0x01 ){ \
++ pH += s>>1; \
++ } \
++ if( r & 0x02 ){ \
++ pH += (s>>1)*width; \
++ } \
++ pEnd = pH+height*width; \
++ while( pH < pEnd ){ \
++ pLine = pH+width; \
++ while( pH < pLine ){ \
++ TRANS \
++ data++; \
++ pH += s; \
++ } \
++ pH += (s-1)*width; \
++ }
++
++#define ZYWRLE_PACK_COEFF(pBuf,data,r,width,height,level) \
++ ZYWRLE_TRANSFER_COEFF(pBuf,data,r,width,height,level,ZYWRLE_LOAD_COEFF(pH,R,G,B);ZYWRLE_SAVE_PIXEL(data,R,G,B);)
++
++#define ZYWRLE_UNPACK_COEFF(pBuf,data,r,width,height,level) \
++ ZYWRLE_TRANSFER_COEFF(pBuf,data,r,width,height,level,ZYWRLE_LOAD_PIXEL(data,R,G,B);ZYWRLE_SAVE_COEFF(pH,R,G,B);)
++
++#define ZYWRLE_SAVE_UNALIGN(data,TRANS) \
++ pTop = pBuf+w*h; \
++ pEnd = pTop + (w+uw)*(h+uh)-w*h; \
++ while( pTop < pEnd ){ \
++ TRANS \
++ data++; \
++ pTop++; \
++ }
++
++#define ZYWRLE_LOAD_UNALIGN(data,pData,TRANS) \
++ pTop = pBuf+w*h; \
++ if( uw ){ \
++ pData= data + w; \
++ pEnd = (int*)(pData+ h*scanline); \
++ while( pData < (PIXEL_T*)pEnd ){ \
++ pLine = (int*)(pData + uw); \
++ while( pData < (PIXEL_T*)pLine ){ \
++ TRANS \
++ pData++; \
++ pTop++; \
++ } \
++ pData += scanline-uw; \
++ } \
++ } \
++ if( uh ){ \
++ pData= data + h*scanline; \
++ pEnd = (int*)(pData+ uh*scanline); \
++ while( pData < (PIXEL_T*)pEnd ){ \
++ pLine = (int*)(pData + w); \
++ while( pData < (PIXEL_T*)pLine ){ \
++ TRANS \
++ pData++; \
++ pTop++; \
++ } \
++ pData += scanline-w; \
++ } \
++ } \
++ if( uw && uh ){ \
++ pData= data + w+ h*scanline; \
++ pEnd = (int*)(pData+ uh*scanline); \
++ while( pData < (PIXEL_T*)pEnd ){ \
++ pLine = (int*)(pData + uw); \
++ while( pData < (PIXEL_T*)pLine ){ \
++ TRANS \
++ pData++; \
++ pTop++; \
++ } \
++ pData += scanline-uw; \
++ } \
++ }
++
++static InlineX void zywrleCalcSize( int* pW, int* pH, int level ){
++ *pW &= ~((1<<level)-1);
++ *pH &= ~((1<<level)-1);
++}
++
++#endif // ZYWRLE_ONCE
++
++#ifndef CPIXEL
++#ifdef ZYWRLE_ENCODE
++static InlineX void ZYWRLE_RGBYUV( int* pBuf, PIXEL_T* data, int width, int height, int scanline ){
++ int R, G, B;
++ int Y, U, V;
++ int* pLine;
++ int* pEnd;
++ pEnd = pBuf+height*width;
++ while( pBuf < pEnd ){
++ pLine = pBuf+width;
++ while( pBuf < pLine ){
++ ZYWRLE_LOAD_PIXEL(data,R,G,B);
++ ZYWRLE_RGBYUV1(R,G,B,Y,U,V,ZYWRLE_YMASK,ZYWRLE_UVMASK);
++ ZYWRLE_SAVE_COEFF(pBuf,V,Y,U);
++ pBuf++;
++ data++;
++ }
++ data += scanline-width;
++ }
++}
++#endif
++#ifdef ZYWRLE_DECODE
++static InlineX void ZYWRLE_YUVRGB( int* pBuf, PIXEL_T* data, int width, int height, int scanline ){
++ int R, G, B;
++ int Y, U, V;
++ int* pLine;
++ int* pEnd;
++ pEnd = pBuf+height*width;
++ while( pBuf < pEnd ){
++ pLine = pBuf+width;
++ while( pBuf < pLine ){
++ ZYWRLE_LOAD_COEFF(pBuf,V,Y,U);
++ ZYWRLE_YUVRGB1(R,G,B,Y,U,V);
++ ZYWRLE_SAVE_PIXEL(data,R,G,B);
++ pBuf++;
++ data++;
++ }
++ data += scanline-width;
++ }
++}
++#endif
++
++#ifdef ZYWRLE_ENCODE
++PIXEL_T* ZYWRLE_ANALYZE ( PIXEL_T* dst, PIXEL_T* src, int w, int h, int scanline, int level, int* pBuf ){
++ int l;
++ int uw = w;
++ int uh = h;
++ int* pTop;
++ int* pEnd;
++ int* pLine;
++ PIXEL_T* pSrc;
++ int R, G, B;
++ int s;
++ int* pH;
++
++ zywrleCalcSize( &w, &h, level );
++ if( (w==0)||(h==0) ){
++ return NULL;
++ }
++ uw -= w;
++ uh -= h;
++
++ ZYWRLE_LOAD_UNALIGN(src,pSrc,*(PIXEL_T*)pTop=*pSrc;)
++ ZYWRLE_RGBYUV( pBuf, src, w, h, scanline );
++ Wavelet( pBuf, w, h, level );
++ for( l=0; l<level; l++ ){
++ ZYWRLE_PACK_COEFF( pBuf, dst, 3, w, h, l );
++ ZYWRLE_PACK_COEFF( pBuf, dst, 2, w, h, l );
++ ZYWRLE_PACK_COEFF( pBuf, dst, 1, w, h, l );
++ if( l == level-1 ){
++ ZYWRLE_PACK_COEFF( pBuf, dst, 0, w, h, l );
++ }
++ }
++ ZYWRLE_SAVE_UNALIGN(dst,*dst=*(PIXEL_T*)pTop;)
++ return dst;
++}
++#endif
++#ifdef ZYWRLE_DECODE
++PIXEL_T* ZYWRLE_SYNTHESIZE ( PIXEL_T* dst, PIXEL_T* src, int w, int h, int scanline, int level, int* pBuf ){
++ int l;
++ int uw = w;
++ int uh = h;
++ int* pTop;
++ int* pEnd;
++ int* pLine;
++ PIXEL_T* pDst;
++ int R, G, B;
++ int s;
++ int* pH;
++
++ zywrleCalcSize( &w, &h, level );
++ if( (w==0)||(h==0) ){
++ return NULL;
++ }
++ uw -= w;
++ uh -= h;
++
++ for( l=0; l<level; l++ ){
++ ZYWRLE_UNPACK_COEFF( pBuf, src, 3, w, h, l );
++ ZYWRLE_UNPACK_COEFF( pBuf, src, 2, w, h, l );
++ ZYWRLE_UNPACK_COEFF( pBuf, src, 1, w, h, l );
++ if( l == level-1 ){
++ ZYWRLE_UNPACK_COEFF( pBuf, src, 0, w, h, l );
++ }
++ }
++ ZYWRLE_SAVE_UNALIGN(src,*(PIXEL_T*)pTop=*src;)
++ InvWavelet( pBuf, w, h, level );
++ ZYWRLE_YUVRGB( pBuf, dst, w, h, scanline );
++ ZYWRLE_LOAD_UNALIGN(dst,pDst,*pDst=*(PIXEL_T*)pTop;)
++ return src;
++}
++#endif
++#endif // CPIXEL
++
++#undef ZYWRLE_RGBYUV
++#undef ZYWRLE_YUVRGB
++#undef ZYWRLE_LOAD_PIXEL
++#undef ZYWRLE_SAVE_PIXEL
diff -Naur vnc_unixsrc.orig/include/rfbproto.h vnc_unixsrc/include/rfbproto.h
--- vnc_unixsrc.orig/include/rfbproto.h 2004-05-27 03:02:02.000000000 -0400
-+++ vnc_unixsrc/include/rfbproto.h 2007-02-01 18:30:17.000000000 -0500
-@@ -435,6 +435,8 @@
++++ vnc_unixsrc/include/rfbproto.h 2007-02-18 13:04:35.000000000 -0500
+@@ -381,6 +381,10 @@
+ #define rfbBell 2
+ #define rfbServerCutText 3
+
++
++/* http://sourceforge.net/projects/vncsessmgr */
++#define rfbRestartConnection 82
++
+ #define rfbFileListData 130
+ #define rfbFileDownloadData 131
+ #define rfbFileUploadCancel 132
+@@ -403,6 +407,18 @@
+ #define rfbPointerEvent 5
+ #define rfbClientCutText 6
+
++/* ultra */
++
++#define rfbFileTransfer 7
++#define rfbSetScale 8
++#define rfbSetServerInput 9
++#define rfbSetSW 10
++#define rfbTextChat 11
++#define rfbKeyFrameRequest 12
++#define rfbPalmVNCSetScaleFactor 0xF
++
++
++
+ #define rfbFileListRequest 130
+ #define rfbFileDownloadRequest 131
+ #define rfbFileUploadRequest 132
+@@ -435,6 +451,11 @@
#define rfbEncodingTight 7
#define rfbEncodingZlibHex 8
+#define rfbEncodingZRLE 16
++// nyama/2006/08/02:new YUV-Wavlet lossy codec based on ZRLE (ZYWRLE)
++#define rfbEncodingZYWRLE 17
++
+
/* signatures for basic encoding types */
#define sig_rfbEncodingRaw "RAW_____"
#define sig_rfbEncodingCopyRect "COPYRECT"
+@@ -955,6 +976,36 @@
+ #define sz_rfbFileDownloadFailedMsg 4
+
+ /*-----------------------------------------------------------------------------
++ * RestartConnection - the server has restarted the client connection.
++ */
++
++typedef struct _rfbRestartConnectionMsg {
++ CARD8 type; /* always rfbRestartConnection */
++ CARD8 pad1;
++ CARD16 pad2;
++ CARD32 length;
++ /* followed by char text[length] */
++} rfbRestartConnectionMsg;
++
++#define sz_rfbRestartConnectionMsg 8
++
++
++typedef struct _rfbTextChatMsg {
++ CARD8 type; /* always rfbTextChat */
++ CARD8 pad1; // Could be used later as an additionnal param
++ CARD16 pad2; // Could be used later as text offset, for instance
++ CARD32 length; // Specific values for Open, close, finished (-1, -2, -3)
++ /* followed by char text[length] */
++} rfbTextChatMsg;
++
++#define sz_rfbTextChatMsg 8
++
++#define rfbTextMaxSize 4096
++#define rfbTextChatOpen 0xFFFFFFFF
++#define rfbTextChatClose 0xFFFFFFFE
++#define rfbTextChatFinished 0xFFFFFFFD
++
++/*-----------------------------------------------------------------------------
+ * Union of all server->client messages.
+ */
+
+@@ -968,6 +1019,8 @@
+ rfbFileDownloadDataMsg fdd;
+ rfbFileUploadCancelMsg fuc;
+ rfbFileDownloadFailedMsg fdf;
++ rfbRestartConnectionMsg rc;
++ rfbTextChatMsg tc;
+ } rfbServerToClientMsg;
+
+
+@@ -1221,6 +1274,41 @@
+
+ #define sz_rfbFileCreateDirRequestMsg 4
+
++/* ultra */
++typedef struct _rfbSetScaleMsg {
++ CARD8 type; /* always rfbSetScale */
++ CARD8 scale; /* Scale value 1<sv<n */
++ CARD16 pad;
++} rfbSetScaleMsg;
++
++#define sz_rfbSetScaleMsg 4
++
++typedef struct {
++ CARD8 type; /* always rfbSetScaleFactor */
++
++ CARD8 scale; /* Scale factor (positive non-zero integer) */
++ CARD16 pad2;
++} rfbPalmVNCSetScaleFactorMsg;
++
++#define sz_rfbPalmVNCSetScaleFactorMsg (4)
++
++typedef struct _rfbSetServerInputMsg {
++ CARD8 type; /* always rfbSetServerInputMsg */
++ CARD8 status; /* on or off */
++ CARD16 pad;
++} rfbSetServerInputMsg;
++
++#define sz_rfbSetServerInputMsg 4
++
++typedef struct _rfbSetSWMsg {
++ CARD8 type; /* always rfbSetSW */
++ CARD8 status;
++ CARD16 x;
++ CARD16 y;
++} rfbSetSWMsg;
++
++#define sz_rfbSetSWMsg 6
++
+ /*-----------------------------------------------------------------------------
+ * Union of all client->server messages.
+ */
+@@ -1241,4 +1329,9 @@
+ rfbFileDownloadCancelMsg fdc;
+ rfbFileUploadFailedMsg fuf;
+ rfbFileCreateDirRequestMsg fcdr;
++ rfbSetScaleMsg ssc;
++ rfbPalmVNCSetScaleFactorMsg pssf;
++ rfbSetServerInputMsg sim;
++ rfbSetSWMsg sw;
++ rfbTextChatMsg tc;
+ } rfbClientToServerMsg;