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 :print()\\nCtrlN: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 {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 "v_mycert" + bind .c.svcert.b "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 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 : SendRFBEvent()\n\ : SendRFBEvent()\n\ : 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\ +- ,: HidePopup() ++*popup*button1.translations: #override\\n\ ++ ,: HidePopup() + + *popup*button2.label: Quit viewer +-*popup*button2.translations: #override\n\ +- ,: Quit() ++*popup*button2.translations: #override\\n\ ++ ,: Quit() + +-*popup*button3.label: Full screen ++*popup*button3.label: Full screen (also F9) + *popup*button3.type: toggle +-*popup*button3.translations: #override\n\ +- : SetFullScreenState()\n\ +- ,: toggle() HidePopup() ToggleFullScreen() ++*popup*button3.translations: #override\\n\ ++ : SetFullScreenState()\\n\ ++ ,: toggle() ToggleFullScreen() HidePopup() + + *popup*button4.label: Clipboard: local -> remote +-*popup*button4.translations: #override\n\ +- ,: SelectionToVNC(always) HidePopup() ++*popup*button4.translations: #override\\n\ ++ ,: SelectionToVNC(always) HidePopup() + + *popup*button5.label: Clipboard: local <- remote +-*popup*button5.translations: #override\n\ +- ,: SelectionFromVNC(always) HidePopup() ++*popup*button5.translations: #override\\n\ ++ ,: SelectionFromVNC(always) HidePopup() + + *popup*button6.label: Request refresh +-*popup*button6.translations: #override\n\ +- ,: SendRFBEvent(fbupdate) HidePopup() ++*popup*button6.translations: #override\\n\ ++ ,: SendRFBEvent(fbupdate) HidePopup() + + *popup*button7.label: Send ctrl-alt-del +-*popup*button7.translations: #override\n\ +- ,: 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\ ++ ,: 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\ - ,: SendRFBEvent(key,F8) HidePopup() +-*popup*button8.translations: #override\n\ +- ,: SendRFBEvent(key,F8) HidePopup() ++*popup*button8.translations: #override\\n\ ++ ,: SendRFBEvent(key,F8) HidePopup() + +*popup*button9.label: Send F9 -+*popup*button9.translations: #override\n\ -+ ,: SendRFBEvent(key,F9) HidePopup() ++*popup*button9.translations: #override\\n\ ++ ,: SendRFBEvent(key,F9) HidePopup() + +*popup*button10.label: ViewOnly +*popup*button10.type: toggle -+*popup*button10.translations: #override\n\ -+ : SetViewOnlyState()\n\ -+ ,: toggle() ToggleViewOnly() HidePopup() ++*popup*button10.translations: #override\\n\ ++ : SetViewOnlyState()\\n\ ++ ,: toggle() ToggleViewOnly() HidePopup() + +*popup*button11.label: Cursor Shape +*popup*button11.type: toggle -+*popup*button11.translations: #override\n\ -+ : SetCursorShapeState()\n\ -+ ,: toggle() ToggleCursorShape() HidePopup() ++*popup*button11.translations: #override\\n\ ++ : SetCursorShapeState()\\n\ ++ ,: toggle() ToggleCursorShape() HidePopup() + +*popup*button12.label: X11 Cursor +*popup*button12.type: toggle -+*popup*button12.translations: #override\n\ -+ : SetX11CursorState()\n\ -+ ,: toggle() ToggleX11Cursor() HidePopup() ++*popup*button12.translations: #override\\n\ ++ : SetX11CursorState()\\n\ ++ ,: toggle() ToggleX11Cursor() HidePopup() + +*popup*button13.label: Cursor Alphablend +*popup*button13.type: toggle -+*popup*button13.translations: #override\n\ -+ : SetCursorAlphaState()\n\ -+ ,: toggle() ToggleCursorAlpha() HidePopup() ++*popup*button13.translations: #override\\n\ ++ : SetCursorAlphaState()\\n\ ++ ,: toggle() ToggleCursorAlpha() HidePopup() + +*popup*button14.label: Toggle Tight/ZRLE +*popup*button14.type: toggle -+*popup*button14.translations: #override\n\ -+ : SetZRLEState()\n\ -+ ,: toggle() ToggleTightZRLE() HidePopup() ++*popup*button14.translations: #override\\n\ ++ : SetZRLEState()\\n\ ++ ,: toggle() ToggleTightZRLE() HidePopup() + +*popup*button15.label: Disable JPEG +*popup*button15.type: toggle -+*popup*button15.translations: #override\n\ -+ : SetNOJPEGState()\n\ -+ ,: toggle() ToggleJPEG() HidePopup() ++*popup*button15.translations: #override\\n\ ++ : SetNOJPEGState()\\n\ ++ ,: toggle() ToggleJPEG() HidePopup() + +*popup*button16.label: Prefer raw for localhost +*popup*button16.type: toggle -+*popup*button16.translations: #override\n\ -+ : SetRawLocalState()\n\ -+ ,: toggle() ToggleRawLocal() HidePopup() ++*popup*button16.translations: #override\\n\ ++ : SetRawLocalState()\\n\ ++ ,: toggle() ToggleRawLocal() HidePopup() + +*popup*button17.label: Full Color +*popup*button17.type: toggle -+*popup*button17.translations: #override\n\ -+ : SetFullColorState()\n\ -+ ,: toggle() ToggleFullColor() HidePopup() ++*popup*button17.translations: #override\\n\ ++ : SetFullColorState()\\n\ ++ ,: 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\ -+ : Set16bppState()\n\ -+ ,: toggle() Toggle16bpp() HidePopup() ++*popup*button18.translations: #override\\n\ ++ : SetGreyScaleState()\\n\ ++ ,: 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\ -+ : Set8bppState()\n\ -+ ,: toggle() Toggle8bpp() HidePopup() ++*popup*button19.translations: #override\\n\ ++ : Set16bppState()\\n\ ++ ,: toggle() Toggle16bpp() HidePopup() + -+*popup*button20.label: - 256 colors ++*popup*button20.label: 8 bit color (BGR233) +*popup*button20.type: toggle -+*popup*button20.translations: #override\n\ -+ : Set256ColorsState()\n\ -+ ,: toggle() Toggle256Colors() HidePopup() ++*popup*button20.translations: #override\\n\ ++ : Set8bppState()\\n\ ++ ,: toggle() Toggle8bpp() HidePopup() + -+*popup*button21.label: - 64 colors ++*popup*button21.label: - 256 colors +*popup*button21.type: toggle -+*popup*button21.translations: #override\n\ -+ : Set64ColorsState()\n\ -+ ,: toggle() Toggle64Colors() HidePopup() ++*popup*button21.translations: #override\\n\ ++ : Set256ColorsState()\\n\ ++ ,: toggle() Toggle256Colors() HidePopup() + -+*popup*button22.label: - 8 colors ++*popup*button22.label: - 64 colors +*popup*button22.type: toggle -+*popup*button22.translations: #override\n\ -+ : Set8ColorsState()\n\ -+ ,: toggle() Toggle8Colors() HidePopup() ++*popup*button22.translations: #override\\n\ ++ : Set64ColorsState()\\n\ ++ ,: toggle() Toggle64Colors() HidePopup() ++ ++*popup*button23.label: - 8 colors ++*popup*button23.type: toggle ++*popup*button23.translations: #override\\n\ ++ : Set8ColorsState()\\n\ ++ ,: toggle() Toggle8Colors() HidePopup() ++ ++*popup*button24.label: Disable Remote Input ++*popup*button24.type: toggle ++*popup*button24.translations: #override\\n\ ++ : SetServerInputState()\\n\ ++ ,: toggle() ToggleServerInput() HidePopup() ++ ++*popup*button25.label: Single Window ++*popup*button25.type: toggle ++*popup*button25.translations: #override\\n\ ++ : SetSingleWindowState()\\n\ ++ ,: toggle() ToggleSingleWindow() HidePopup() ++ ++*popup*button26.label: Set 1/n Server Scale ++*popup*button26.translations: #override\\n\ ++ ,: DoServerScale() HidePopup() ++ ++*popup*button27.label: Text Chat ++*popup*button27.type: toggle ++*popup*button27.translations: #override\\n\ ++ : SetTextChatState()\\n\ ++ ,: 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:\ + : SelectionToVNC()\\n\ +@@ -45,8 +45,14 @@ "*viewport.useRight: True", "*viewport*Scrollbar*thumb: None", -+#if 0 -+ "vncviewer*.desktop.translations: #override Shift F8: ToggleFullScreen()", -+ "vncviewer*.desktop.translations: #override 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:\ - F8: ShowPopup()\\n\ @@ -146,9 +240,12 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v : SendRFBEvent()\\n\ : SendRFBEvent()\\n\ : SendRFBEvent()\\n\ -@@ -66,7 +76,8 @@ +@@ -64,9 +70,10 @@ + "*passwordDialog.dialog.value.translations: #override\\n\ + 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\ : 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\ + ,: Quit()", + +- "*popup*button3.label: Full screen", ++ "*popup*button3.label: Full screen (also F9)", + "*popup*button3.type: toggle", + "*popup*button3.translations: #override\\n\ + : SetFullScreenState()\\n\ +@@ -115,9 +122,127 @@ "*popup*button8.translations: #override\\n\ ,: SendRFBEvent(key,F8) HidePopup()", @@ -203,14 +309,6 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v + : SetZRLEState()\\n\ + ,: toggle() ToggleTightZRLE() HidePopup()", + -+#if 0 -+ "*popup*button14.label: - ZRLE/ZWYRLE", -+ "*popup*button14.type: toggle", -+ "*popup*button14.translations: #override\\n\ -+ : SetZRLEState()\\n\ -+ ,: 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 + : SetFullColorState()\\n\ + ,: 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\ -+ : Set16bppState()\\n\ -+ ,: toggle() Toggle16bpp() HidePopup()", ++ : SetGreyScaleState()\\n\ ++ ,: 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\ -+ : Set8bppState()\\n\ -+ ,: toggle() Toggle8bpp() HidePopup()", ++ : Set16bppState()\\n\ ++ ,: toggle() Toggle16bpp() HidePopup()", + -+ "*popup*button20.label: - 256 colors", ++ "*popup*button20.label: 8 bit color (BGR233)", + "*popup*button20.type: toggle", + "*popup*button20.translations: #override\\n\ -+ : Set256ColorsState()\\n\ -+ ,: toggle() Toggle256Colors() HidePopup()", ++ : Set8bppState()\\n\ ++ ,: toggle() Toggle8bpp() HidePopup()", + -+ "*popup*button21.label: - 64 colors", ++ "*popup*button21.label: - 256 colors", + "*popup*button21.type: toggle", + "*popup*button21.translations: #override\\n\ -+ : Set64ColorsState()\\n\ -+ ,: toggle() Toggle64Colors() HidePopup()", ++ : Set256ColorsState()\\n\ ++ ,: toggle() Toggle256Colors() HidePopup()", + -+ "*popup*button22.label: - 8 colors", ++ "*popup*button22.label: - 64 colors", + "*popup*button22.type: toggle", + "*popup*button22.translations: #override\\n\ ++ : Set64ColorsState()\\n\ ++ ,: toggle() Toggle64Colors() HidePopup()", ++ ++ "*popup*button23.label: - 8 colors", ++ "*popup*button23.type: toggle", ++ "*popup*button23.translations: #override\\n\ + : Set8ColorsState()\\n\ + ,: toggle() Toggle8Colors() HidePopup()", ++ ++ "*popup*button24.label: Disable Remote Input", ++ "*popup*button24.type: toggle", ++ "*popup*button24.translations: #override\\n\ ++ : SetServerInputState()\\n\ ++ ,: toggle() ToggleServerInput() HidePopup()", ++ ++ "*popup*button25.label: Single Window", ++ "*popup*button25.type: toggle", ++ "*popup*button25.translations: #override\\n\ ++ : SetSingleWindowState()\\n\ ++ ,: toggle() ToggleSingleWindow() HidePopup()", ++ ++ "*popup*button26.label: Set 1/n Server Scale", ++ "*popup*button26.translations: #override\\n\ ++ ,: DoServerScale() HidePopup()", ++ ++ "*popup*button27.label: Text Chat", ++ "*popup*button27.type: toggle", ++ "*popup*button27.translations: #override\\n\ ++ : SetTextChatState()\\n\ ++ ,: toggle() ToggleTextChat() HidePopup()", + NULL }; -@@ -135,6 +236,7 @@ ++#if 0 ++ "*popup*button14.label: - ZRLE/ZWYRLE", ++ "*popup*button14.type: toggle", ++ "*popup*button14.translations: #override\\n\ ++ : SetZRLEState()\\n\ ++ ,: 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 [] [][:]\n" + " %s [] [][::]\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< rcCursorY - rcHotY); + } + ++extern XImage *image; ++ + static void SoftCursorCopyArea(int oper) + { +- int x, y, w, h; ++ int x, y, w, h; + +- 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; ++ } + +- 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 (0) fprintf(stderr, "HandleCursorShape: SoftCursorCopyArea\n"); - SoftCursorCopyArea(OPER_SAVE); - SoftCursorDraw(); +- 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); ++ } + } -@@ -472,6 +484,139 @@ + 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 + #endif + ++#include ++ 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 + -#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 - +- - 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,45 +1685,153 @@ 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); - } - -+extern void FreeX11Cursor(void); + * 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); + +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, ") { ++ 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,1522 +2811,6383 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie } -@@ -729,6 +752,23 @@ - Bool requestCompressLevel = False; - Bool requestQualityLevel = False; - Bool requestLastRectEncoding = False; -+ Bool requestNewFBSizeEncoding = 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; -+ } +@@ -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; + } -+ skip_XtUpdate = 0; -+ } -+#endif - spf.type = rfbSetPixelFormat; - spf.format = myFormat; -@@ -736,6 +776,7 @@ - spf.format.greenMax = Swap16IfLE(spf.format.greenMax); - spf.format.blueMax = Swap16IfLE(spf.format.blueMax); +- rfbsock = ConnectToTcpAddr(host, port); ++ rfbsock = ConnectToTcpAddr(host, port); -+ - if (!WriteExact(rfbsock, (char *)&spf, sz_rfbSetPixelFormatMsg)) - return False; +- 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; ++ } -@@ -754,6 +795,12 @@ - encStrLen = strlen(encStr); - } +- return SetNonBlocking(rfbsock); ++ return SetNonBlocking(rfbsock); + } -+if (getenv("DEBUG_SETFORMAT")) { -+ fprintf(stderr, "encs: "); -+ write(2, encStr, encStrLen); -+ fprintf(stderr, "\n"); -+} -+ - if (strncasecmp(encStr,"raw",encStrLen) == 0) { - encs[se->nEncodings++] = Swap32IfLE(rfbEncodingRaw); - } else if (strncasecmp(encStr,"copyrect",encStrLen) == 0) { -@@ -775,6 +822,8 @@ - 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 { - fprintf(stderr,"Unknown encoding '%.*s'\n",encStrLen,encStr); - } -@@ -797,7 +846,7 @@ - if (appData.useRemoteCursor) { - if (se->nEncodings < MAX_ENCODINGS) - encs[se->nEncodings++] = Swap32IfLE(rfbEncodingXCursor); -- if (se->nEncodings < MAX_ENCODINGS) -+ if (se->nEncodings < MAX_ENCODINGS && !appData.useX11Cursor) - encs[se->nEncodings++] = Swap32IfLE(rfbEncodingRichCursor); - if (se->nEncodings < MAX_ENCODINGS) - encs[se->nEncodings++] = Swap32IfLE(rfbEncodingPointerPos); -@@ -806,10 +855,14 @@ - if (se->nEncodings < MAX_ENCODINGS && requestLastRectEncoding) { - encs[se->nEncodings++] = Swap32IfLE(rfbEncodingLastRect); - } -+ -+ if (se->nEncodings < MAX_ENCODINGS && requestNewFBSizeEncoding) { -+ encs[se->nEncodings++] = Swap32IfLE(rfbEncodingNewFBSize); -+ } - } - else { - if (SameMachine(rfbsock)) { -- if (!tunnelSpecified) { -+ if (!tunnelSpecified && appData.useRawLocal) { - fprintf(stderr,"Same machine: preferring raw encoding\n"); - encs[se->nEncodings++] = Swap32IfLE(rfbEncodingRaw); - } else { -@@ -819,6 +872,7 @@ - encs[se->nEncodings++] = Swap32IfLE(rfbEncodingCopyRect); - encs[se->nEncodings++] = Swap32IfLE(rfbEncodingTight); -+ encs[se->nEncodings++] = Swap32IfLE(rfbEncodingZRLE); - encs[se->nEncodings++] = Swap32IfLE(rfbEncodingHextile); - encs[se->nEncodings++] = Swap32IfLE(rfbEncodingZlib); - encs[se->nEncodings++] = Swap32IfLE(rfbEncodingCoRRE); -@@ -844,11 +898,14 @@ +@@ -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 (appData.useRemoteCursor) { - encs[se->nEncodings++] = Swap32IfLE(rfbEncodingXCursor); -- encs[se->nEncodings++] = Swap32IfLE(rfbEncodingRichCursor); -+ if (!appData.useX11Cursor) { -+ encs[se->nEncodings++] = Swap32IfLE(rfbEncodingRichCursor); -+ } - encs[se->nEncodings++] = Swap32IfLE(rfbEncodingPointerPos); - } +- if (!ReadFromRFBServer(pv, sz_rfbProtocolVersionMsg)) +- return False; ++ if (!ReadFromRFBServer(pv, sz_rfbProtocolVersionMsg)) { ++ return False; ++ } - encs[se->nEncodings++] = Swap32IfLE(rfbEncodingLastRect); -+ encs[se->nEncodings++] = Swap32IfLE(rfbEncodingNewFBSize); - } +- errorMessageOnReadFailure = True; ++ errorMessageOnReadFailure = True; - len = sz_rfbSetEncodingsMsg + se->nEncodings * 4; -@@ -889,6 +946,12 @@ - fur.w = Swap16IfLE(w); - fur.h = Swap16IfLE(h); +- pv[sz_rfbProtocolVersionMsg] = 0; ++ pv[sz_rfbProtocolVersionMsg] = 0; -+ if (incremental) { -+ sent_FBU = 1; -+ } else { -+ sent_FBU = 2; +- 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; + } -+ - if (!WriteExact(rfbsock, (char *)&fur, sz_rfbFramebufferUpdateRequestMsg)) - return False; -@@ -955,6 +1018,10 @@ - } +- 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); -+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; +- sprintf(pv, rfbProtocolVersionFormat, viewer_major, viewer_minor); ++ sprintf(pv, rfbProtocolVersionFormat, viewer_major, viewer_minor); -+ int skip_incFBU = 0; -+ sent_FBU = -1; -+ - if (!ReadFromRFBServer(((char *)&msg.fu) + 1, - sz_rfbFramebufferUpdateMsg - 1)) - return False; -@@ -1038,6 +1108,16 @@ - } - 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 (!WriteExact(rfbsock, pv, sz_rfbProtocolVersionMsg)) +- return False; ++ if (!WriteExact(rfbsock, pv, sz_rfbProtocolVersionMsg)) { ++ return False; ++ } - if ((rect.r.x + rect.r.w > si.framebufferWidth) || - (rect.r.y + rect.r.h > si.framebufferHeight)) -@@ -1208,6 +1288,42 @@ - break; - } +- /* 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; ++ } -+/* 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< +- return (int)secType; ++ return (int)secType; + } - char *programName; - XtAppContext appContext; -@@ -29,6 +30,32 @@ - Widget toplevel; +@@ -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; ++ } -+static void set_sbwidth(int sbw) { -+ char *q, *p, t[5]; -+ int i, k, N = 4; -+ -+ if (sbw < 1) { -+ sbw = 2; -+ } else if (sbw > 100) { -+ sbw = 100; +- 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; + } + -+ sprintf(t, "%4d", sbw); -+ k = 0; -+ while (fallback_resources[k] != NULL) { -+ q = strstr(fallback_resources[k], "%SBW"); -+ if (q) { -+ p = strdup(fallback_resources[k]); -+ q = strstr(p, "%SBW"); -+ for (i=0; i < N; i++) { -+ *(q+i) = t[i]; ++ /* 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; + } -+ fallback_resources[k] = p; ++ fprintf(stderr, "Enabling TightVNC protocol extensions\n"); ++ return rfbSecTypeTight; + } -+ k++; + } -+} -+ - int - main(int argc, char **argv) - { -@@ -57,10 +84,24 @@ - } - } - -+ 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]); +- 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; + } + } -+ set_sbwidth(sbw); -+ } + - toplevel = XtVaAppInitialize(&appContext, "Vncviewer", - cmdLineOptions, numCmdLineOptions, - &argc, argv, fallback_resources, -@@ -123,11 +164,443 @@ - automatically be processed whenever the VNC connection is idle. */ ++ free(secTypes); - while (1) { -- if (!HandleRFBServerMessage()) -- break; -+ if (!HandleRFBServerMessage()) { -+ break; +- 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"); + } - } - Cleanup(); +- return (int)secType; ++ return (int)secType; + } + - return 0; +@@ -451,6 +493,9 @@ + return True; } + ++static char *restart_session_pw = NULL; ++static int restart_session_len = 0; + -+/* -+ * Toggle8bpp -+ */ -+ -+static int last_ncolors = 0; -+static int save_useBGR233 = 0; -+static Bool save_useBGR565 = False; -+ -+static Widget b8 = NULL; -+static Widget b16 = NULL; -+static Widget bfull = NULL; -+ -+int do_format_change = 0; -+int do_cursor_change = 0; -+static void schedule_format_change(void) { -+ do_format_change = 1; -+ do_cursor_change = 0; -+} -+static void init_format_change(void) { -+ appDataNew.useBGR233 = appData.useBGR233; -+ appDataNew.useBGR565 = appData.useBGR565; -+ appDataNew.enableJPEG = appData.enableJPEG; -+ appDataNew.encodingsString = appData.encodingsString; -+ appDataNew.useRemoteCursor = appData.useRemoteCursor; -+ appDataNew.useX11Cursor = appData.useX11Cursor; -+ appDataNew.useRawLocal = appData.useRawLocal; -+} -+void cutover_format_change(void) { -+ appData.useBGR233 = appDataNew.useBGR233; -+ appData.useBGR565 = appDataNew.useBGR565; -+ appData.enableJPEG = appDataNew.enableJPEG; -+ appData.encodingsString = appDataNew.encodingsString; -+ appData.useRemoteCursor = appDataNew.useRemoteCursor; -+ appData.useX11Cursor = appDataNew.useX11Cursor; -+ appData.useRawLocal = appDataNew.useRawLocal; -+} -+ -+void -+Toggle8bpp(Widget w, XEvent *ev, String *params, Cardinal *num_params) -+{ -+ fprintf(stderr, "Toggle8bpp: %d\n", appData.useBGR233); -+ b8 = w; -+ init_format_change(); -+ if (appData.useBGR233) { -+ last_ncolors = appData.useBGR233; -+ appDataNew.useBGR233 = 0; -+ appDataNew.useBGR565 = save_useBGR565; -+ fprintf(stderr, "8bpp: off\n"); -+ } else { -+ if (!last_ncolors) last_ncolors = 256; -+ appDataNew.useBGR233 = last_ncolors; -+ save_useBGR565 = appData.useBGR565; -+ appDataNew.useBGR565 = False; -+ fprintf(stderr, "8bpp: on (%d colors)\n", appDataNew.useBGR233); + + /* + * 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; + } -+ schedule_format_change(); -+} -+ -+ -+void -+Toggle16bpp(Widget w, XEvent *ev, String *params, Cardinal *num_params) -+{ -+ fprintf(stderr, "Toggle16bpp: %d\n", appData.useBGR565); -+ b16 = w; -+ init_format_change(); -+ if (appData.useBGR565) { -+ appDataNew.useBGR565 = False; -+ appDataNew.useBGR233 = save_useBGR233; -+ fprintf(stderr, "16bpp: off\n"); + +- 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 { -+ appDataNew.useBGR565 = True; -+ save_useBGR233 = appData.useBGR233; -+ appDataNew.useBGR233 = 0; -+ fprintf(stderr, "16bpp: on\n"); ++ passwd = getpass("Password: "); + } -+ schedule_format_change(); -+} -+ -+void -+ToggleFullColor(Widget w, XEvent *ev, String *params, Cardinal *num_params) -+{ -+ fprintf(stderr, "ToggleFullColor\n"); -+ bfull = w; -+ init_format_change(); -+ if (appData.useBGR565 || appData.useBGR233) { -+ save_useBGR565 = appData.useBGR565; -+ appDataNew.useBGR565 = False; -+ save_useBGR233 = appData.useBGR233; -+ appDataNew.useBGR233 = 0; -+ fprintf(stderr, "FullColor: on\n"); + +- 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 (save_useBGR565) { -+ appDataNew.useBGR565 = True; -+ appDataNew.useBGR233 = 0; -+ fprintf(stderr, "FullColor off -> 16bpp.\n"); -+ } else { -+ appDataNew.useBGR565 = False; -+ if (!save_useBGR233) save_useBGR233 = 256; -+ appDataNew.useBGR233 = save_useBGR233; -+ fprintf(stderr, "FullColor off -> 8bpp.\n"); ++ if (!passwd || strlen(passwd) == 0) { ++ fprintf(stderr, "Reading password failed\n"); ++ return False; ++ } ++ if (strlen(passwd) > 8) { ++ passwd[8] = '\0'; + } + } -+ schedule_format_change(); -+} -+ -+/* -+ * ToggleNColors -+ */ ++ 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; + -+static Widget w256 = NULL; -+static Widget w64 = NULL; -+static Widget w8 = NULL; ++ fprintf(stderr, "Performing Unix login-style authentication\n"); + -+void -+Toggle256Colors(Widget w, XEvent *ev, String *params, Cardinal *num_params) -+{ -+ w256 = w; -+ if (appData.useBGR233 != 256) { -+ fprintf(stderr, "256 colors: on\n"); -+ init_format_change(); -+ last_ncolors = appDataNew.useBGR233 = 256; -+ save_useBGR565 = appData.useBGR565; -+ appDataNew.useBGR565 = False; -+ schedule_format_change(); ++ if (appData.userLogin) { ++ login = appData.userLogin; ++ } else { ++ ps = getpwuid(getuid()); ++ login = ps->pw_name; + } -+} -+ -+void -+Toggle64Colors(Widget w, XEvent *ev, String *params, Cardinal *num_params) -+{ -+ w64 = w; -+ if (appData.useBGR233 != 64) { -+ fprintf(stderr, "64 colors: on\n"); -+ init_format_change(); -+ last_ncolors = appDataNew.useBGR233 = 64; -+ save_useBGR565 = appData.useBGR565; -+ appDataNew.useBGR565 = False; -+ schedule_format_change(); + +- 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: "); + } -+} -+ -+void -+Toggle8Colors(Widget w, XEvent *ev, String *params, Cardinal *num_params) -+{ -+ w8 = w; -+ if (appData.useBGR233 != 8) { -+ fprintf(stderr, "8 colors: on\n"); -+ init_format_change(); -+ last_ncolors = appDataNew.useBGR233 = 8; -+ save_useBGR565 = appData.useBGR565; -+ appDataNew.useBGR565 = False; -+ schedule_format_change(); ++ 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); + + spf.type = rfbSetPixelFormat; + spf.format = myFormat; +@@ -736,6 +812,7 @@ + spf.format.greenMax = Swap16IfLE(spf.format.greenMax); + spf.format.blueMax = Swap16IfLE(spf.format.blueMax); + ++ + if (!WriteExact(rfbsock, (char *)&spf, sz_rfbSetPixelFormatMsg)) + return False; + +@@ -754,6 +831,12 @@ + encStrLen = strlen(encStr); + } + ++if (getenv("DEBUG_SETFORMAT")) { ++ fprintf(stderr, "encs: "); ++ write(2, encStr, encStrLen); ++ fprintf(stderr, "\n"); ++} ++ + if (strncasecmp(encStr,"raw",encStrLen) == 0) { + encs[se->nEncodings++] = Swap32IfLE(rfbEncodingRaw); + } else if (strncasecmp(encStr,"copyrect",encStrLen) == 0) { +@@ -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 +884,7 @@ + if (appData.useRemoteCursor) { + if (se->nEncodings < MAX_ENCODINGS) + encs[se->nEncodings++] = Swap32IfLE(rfbEncodingXCursor); +- if (se->nEncodings < MAX_ENCODINGS) ++ if (se->nEncodings < MAX_ENCODINGS && !appData.useX11Cursor) + encs[se->nEncodings++] = Swap32IfLE(rfbEncodingRichCursor); + if (se->nEncodings < MAX_ENCODINGS) + encs[se->nEncodings++] = Swap32IfLE(rfbEncodingPointerPos); +@@ -806,10 +893,14 @@ + if (se->nEncodings < MAX_ENCODINGS && requestLastRectEncoding) { + encs[se->nEncodings++] = Swap32IfLE(rfbEncodingLastRect); + } ++ ++ if (se->nEncodings < MAX_ENCODINGS && requestNewFBSizeEncoding) { ++ encs[se->nEncodings++] = Swap32IfLE(rfbEncodingNewFBSize); ++ } + } + else { + if (SameMachine(rfbsock)) { +- if (!tunnelSpecified) { ++ if (!tunnelSpecified && appData.useRawLocal) { + fprintf(stderr,"Same machine: preferring raw encoding\n"); + encs[se->nEncodings++] = Swap32IfLE(rfbEncodingRaw); + } else { +@@ -819,6 +910,7 @@ + + encs[se->nEncodings++] = Swap32IfLE(rfbEncodingCopyRect); + encs[se->nEncodings++] = Swap32IfLE(rfbEncodingTight); ++ encs[se->nEncodings++] = Swap32IfLE(rfbEncodingZRLE); + encs[se->nEncodings++] = Swap32IfLE(rfbEncodingHextile); + encs[se->nEncodings++] = Swap32IfLE(rfbEncodingZlib); + encs[se->nEncodings++] = Swap32IfLE(rfbEncodingCoRRE); +@@ -844,11 +936,14 @@ + + if (appData.useRemoteCursor) { + encs[se->nEncodings++] = Swap32IfLE(rfbEncodingXCursor); +- encs[se->nEncodings++] = Swap32IfLE(rfbEncodingRichCursor); ++ if (!appData.useX11Cursor) { ++ encs[se->nEncodings++] = Swap32IfLE(rfbEncodingRichCursor); ++ } + encs[se->nEncodings++] = Swap32IfLE(rfbEncodingPointerPos); + } + + encs[se->nEncodings++] = Swap32IfLE(rfbEncodingLastRect); ++ encs[se->nEncodings++] = Swap32IfLE(rfbEncodingNewFBSize); + } + + len = sz_rfbSetEncodingsMsg + se->nEncodings * 4; +@@ -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); ++ } ++ ++ pe.x = Swap16IfLE(x); ++ pe.y = Swap16IfLE(y); ++ return WriteExact(rfbsock, (char *)&pe, sz_rfbPointerEventMsg); + } + + +@@ -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); ++ ++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; + +- 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; + } + +- 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); + +- 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; ++ } ++ ++ 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<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-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 ++#if (BPP == 16) ++ gcv.foreground = (appData.useBGR565 ? BGR565ToPixel[pix] : pix); ++#else + gcv.foreground = pix; + #endif ++#endif + ++#if 0 + XChangeGC(dpy, gc, GCForeground, &gcv); + XFillRectangle(dpy, desktopWin, gc, rx, ry, rw, rh); ++#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 ++#if (BPP == 16) ++ gcv.foreground = (appData.useBGR565 ? BGR565ToPixel[pix] : pix); ++#else + gcv.foreground = pix; + #endif ++#endif + ++#if 0 + XChangeGC(dpy, gc, GCForeground, &gcv); + XFillRectangle(dpy, desktopWin, gc, rx + subrect.x, ry + subrect.y, + subrect.w, subrect.h); ++#else ++ FillRectangle(rx + subrect.x, ry + subrect.y, subrect.w, subrect.h, gcv.foreground); ++#endif + } + + 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-18 20:31:30.000000000 -0500 +@@ -63,15 +63,59 @@ + XtRemoveInput(*id); + } + ++extern int skip_XtUpdate; ++ + 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); ++ ++ 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-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); ++ 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 ++.\" ++.\" 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 , ++.br ++Terran Melconian , ++.br ++Tim Waugh , ++.br ++Constantin Kaplinsky +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-18 18:45:43.000000000 -0500 +@@ -22,6 +22,7 @@ + */ + + #include "vncviewer.h" ++#include + + char *programName; + XtAppContext appContext; +@@ -29,11 +30,47 @@ + + Widget toplevel; + ++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], "horizontal.height: "); ++ if (!q) { ++ q = strstr(fallback_resources[k], "vertical.width: "); ++ } ++ if (q) { ++ p = strdup(fallback_resources[k]); ++ 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); ++ } ++ } ++ k++; ++ } ++} ++ + int + main(int argc, char **argv) + { +- 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. */ + +- 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; ++ } ++ } ++ 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); ++ ++ 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) { +- if (!HandleRFBServerMessage()) +- break; +- } ++ while (1) { ++ if (!HandleRFBServerMessage()) { ++ break; ++ } ++ } ++ ++ Cleanup(); ++ ++ return 0; ++} ++ ++/* ++ * Toggle8bpp ++ */ ++ ++static int last_ncolors = 0; ++static int save_useBGR233 = 0; ++static Bool save_useBGR565 = False; ++ ++static Widget b8 = NULL; ++static Widget b16 = NULL; ++static Widget bfull = NULL; ++ ++int do_format_change = 0; ++int do_cursor_change = 0; ++static void schedule_format_change(void) { ++ do_format_change = 1; ++ do_cursor_change = 0; ++} ++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; ++ appDataNew.useX11Cursor = appData.useX11Cursor; ++ appDataNew.useRawLocal = appData.useRawLocal; ++} ++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; ++ appData.useX11Cursor = appDataNew.useX11Cursor; ++ appData.useRawLocal = appDataNew.useRawLocal; ++} ++ ++void ++Toggle8bpp(Widget w, XEvent *ev, String *params, Cardinal *num_params) ++{ ++ fprintf(stderr, "Toggle8bpp: %d\n", appData.useBGR233); ++ b8 = w; ++ init_format_change(); ++ if (appData.useBGR233) { ++ last_ncolors = appData.useBGR233; ++ appDataNew.useBGR233 = 0; ++ appDataNew.useBGR565 = save_useBGR565; ++ fprintf(stderr, "8bpp: off\n"); ++ } else { ++ if (!last_ncolors) last_ncolors = 256; ++ appDataNew.useBGR233 = last_ncolors; ++ save_useBGR565 = appData.useBGR565; ++ appDataNew.useBGR565 = False; ++ fprintf(stderr, "8bpp: on (%d colors)\n", appDataNew.useBGR233); ++ } ++ schedule_format_change(); ++} ++ ++ ++void ++Toggle16bpp(Widget w, XEvent *ev, String *params, Cardinal *num_params) ++{ ++ fprintf(stderr, "Toggle16bpp: %d\n", appData.useBGR565); ++ b16 = w; ++ init_format_change(); ++ if (appData.useBGR565) { ++ appDataNew.useBGR565 = False; ++ appDataNew.useBGR233 = save_useBGR233; ++ fprintf(stderr, "16bpp: off\n"); ++ } else { ++ appDataNew.useBGR565 = True; ++ save_useBGR233 = appData.useBGR233; ++ appDataNew.useBGR233 = 0; ++ fprintf(stderr, "16bpp: on\n"); ++ } ++ schedule_format_change(); ++} ++ ++void ++ToggleFullColor(Widget w, XEvent *ev, String *params, Cardinal *num_params) ++{ ++ fprintf(stderr, "ToggleFullColor\n"); ++ bfull = w; ++ init_format_change(); ++ if (appData.useBGR565 || appData.useBGR233) { ++ save_useBGR565 = appData.useBGR565; ++ appDataNew.useBGR565 = False; ++ save_useBGR233 = appData.useBGR233; ++ appDataNew.useBGR233 = 0; ++ fprintf(stderr, "FullColor: on\n"); ++ } else { ++ if (save_useBGR565) { ++ appDataNew.useBGR565 = True; ++ appDataNew.useBGR233 = 0; ++ fprintf(stderr, "FullColor off -> 16bpp.\n"); ++ } else { ++ appDataNew.useBGR565 = False; ++ if (!save_useBGR233) save_useBGR233 = 256; ++ appDataNew.useBGR233 = save_useBGR233; ++ fprintf(stderr, "FullColor off -> 8bpp.\n"); ++ } ++ } ++ schedule_format_change(); ++} ++ ++/* ++ * ToggleNColors ++ */ ++ ++static Widget w256 = NULL; ++static Widget w64 = NULL; ++static Widget w8 = NULL; ++ ++void ++Toggle256Colors(Widget w, XEvent *ev, String *params, Cardinal *num_params) ++{ ++ w256 = w; ++ if (appData.useBGR233 != 256) { ++ fprintf(stderr, "256 colors: on\n"); ++ init_format_change(); ++ last_ncolors = appDataNew.useBGR233 = 256; ++ save_useBGR565 = appData.useBGR565; ++ appDataNew.useBGR565 = False; ++ schedule_format_change(); ++ } ++} ++ ++void ++Toggle64Colors(Widget w, XEvent *ev, String *params, Cardinal *num_params) ++{ ++ w64 = w; ++ if (appData.useBGR233 != 64) { ++ fprintf(stderr, "64 colors: on\n"); ++ init_format_change(); ++ last_ncolors = appDataNew.useBGR233 = 64; ++ save_useBGR565 = appData.useBGR565; ++ appDataNew.useBGR565 = False; ++ schedule_format_change(); ++ } ++} ++ ++void ++Toggle8Colors(Widget w, XEvent *ev, String *params, Cardinal *num_params) ++{ ++ w8 = w; ++ if (appData.useBGR233 != 8) { ++ fprintf(stderr, "8 colors: on\n"); ++ init_format_change(); ++ last_ncolors = appDataNew.useBGR233 = 8; ++ save_useBGR565 = appData.useBGR565; ++ appDataNew.useBGR565 = False; ++ schedule_format_change(); ++ } ++} ++ ++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 ++ */ ++ ++void ++ToggleJPEG(Widget w, XEvent *ev, String *params, Cardinal *num_params) ++{ ++ init_format_change(); ++ if (appData.enableJPEG) { ++ appDataNew.enableJPEG = False; ++ fprintf(stderr, "JPEG: off\n"); ++ } else { ++ appDataNew.enableJPEG = True; ++ fprintf(stderr, "JPEG: on\n"); ++ } ++ schedule_format_change(); ++} ++ ++/* ++ * ToggleTightZRLE ++ */ ++ ++static Bool usingZRLE = False; ++ ++void ++ToggleTightZRLE(Widget w, XEvent *ev, String *params, Cardinal *num_params) ++{ ++ char prefTight[] = "copyrect tight zrle zlib hextile corre rre raw"; ++ char prefZRLE[] = "copyrect zrle tight zlib hextile corre rre raw"; ++ init_format_change(); ++ if (! appData.encodingsString) { ++ appDataNew.encodingsString = strdup(prefZRLE); ++ usingZRLE = True; ++ fprintf(stderr, "prefer: ZRLE\n"); ++ } else { ++ char *p, *q; ++ p = strstr(appData.encodingsString, "tight"); ++ q = strstr(appData.encodingsString, "zrle"); ++ if (! p) { ++ appDataNew.encodingsString = strdup(prefZRLE); ++ usingZRLE = True; ++ fprintf(stderr, "prefer: ZRLE\n"); ++ } else if (! q) { ++ appDataNew.encodingsString = strdup(prefTight); ++ usingZRLE = False; ++ fprintf(stderr, "prefer: Tight\n"); ++ } else { ++ if (p < q) { ++ appDataNew.encodingsString = strdup(prefZRLE); ++ usingZRLE = True; ++ fprintf(stderr, "prefer: ZRLE\n"); ++ } else { ++ appDataNew.encodingsString = strdup(prefTight); ++ usingZRLE = False; ++ fprintf(stderr, "prefer: Tight\n"); ++ } ++ } ++ } ++ schedule_format_change(); ++} ++ ++/* ++ * ToggleViewOnly ++ */ ++ ++void ++ToggleViewOnly(Widget w, XEvent *ev, String *params, Cardinal *num_params) ++{ ++ if (appData.viewOnly) { ++ appData.viewOnly = False; ++ fprintf(stderr, "viewonly: off\n"); ++ } else { ++ appData.viewOnly = True; ++ fprintf(stderr, "viewonly: on\n"); ++ } ++} ++ ++void ++ToggleCursorShape(Widget w, XEvent *ev, String *params, Cardinal *num_params) ++{ ++ init_format_change(); ++ if (appData.useRemoteCursor) { ++ appDataNew.useRemoteCursor = False; ++ fprintf(stderr, "useRemoteCursor: off\n"); ++ } else { ++ appDataNew.useRemoteCursor = True; ++ fprintf(stderr, "useRemoteCursor: on\n"); ++ } ++ schedule_format_change(); ++ if (!appDataNew.useRemoteCursor) { ++ do_cursor_change = 1; ++ } else { ++ do_cursor_change = -1; ++ } ++} ++ ++void ++ToggleCursorAlpha(Widget w, XEvent *ev, String *params, Cardinal *num_params) ++{ ++ if (appData.useCursorAlpha) { ++ appData.useCursorAlpha = False; ++ fprintf(stderr, "useCursorAlpha: off\n"); ++ } else { ++ appData.useCursorAlpha = True; ++ fprintf(stderr, "useCursorAlpha: on\n"); ++ } ++} ++ ++void ++ToggleX11Cursor(Widget w, XEvent *ev, String *params, Cardinal *num_params) ++{ ++ init_format_change(); ++ if (appData.useX11Cursor) { ++ appDataNew.useX11Cursor = False; ++ fprintf(stderr, "useX11Cursor: off\n"); ++ } else { ++ appDataNew.useX11Cursor = True; ++ fprintf(stderr, "useX11Cursor: on\n"); ++ } ++ schedule_format_change(); ++ do_cursor_change = 1; ++} ++ ++void ++ToggleRawLocal(Widget w, XEvent *ev, String *params, Cardinal *num_params) ++{ ++ init_format_change(); ++ if (appData.useRawLocal) { ++ appDataNew.useRawLocal = False; ++ fprintf(stderr, "useRawLocal: off\n"); ++ } else { ++ appDataNew.useRawLocal = True; ++ fprintf(stderr, "useRawLocal: on\n"); ++ } ++ schedule_format_change(); ++} ++ ++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) ++ XtVaSetValues(w, XtNstate, True, NULL); ++ else ++ XtVaSetValues(w, XtNstate, False, NULL); ++} ++ ++void ++SetNOJPEGState(Widget w, XEvent *ev, String *params, Cardinal *num_params) ++{ ++ if (appData.enableJPEG) ++ XtVaSetValues(w, XtNstate, False, NULL); ++ else ++ XtVaSetValues(w, XtNstate, True, NULL); ++} ++ ++void ++Set8bppState(Widget w, XEvent *ev, String *params, Cardinal *num_params) ++{ ++ if (appData.useBGR233) { ++ XtVaSetValues(w, XtNstate, True, NULL); ++ if (b16 != NULL) XtVaSetValues(b16, XtNstate, False, NULL); ++ if (bfull != NULL) XtVaSetValues(bfull, XtNstate, False, NULL); ++ } else { ++ XtVaSetValues(w, XtNstate, False, NULL); ++ } ++} ++ ++void ++Set16bppState(Widget w, XEvent *ev, String *params, Cardinal *num_params) ++{ ++ if (appData.useBGR565) { ++ XtVaSetValues(w, XtNstate, True, NULL); ++ if (b8 != NULL) XtVaSetValues(b8, XtNstate, False, NULL); ++ if (bfull != NULL) XtVaSetValues(bfull, XtNstate, False, NULL); ++ } else { ++ XtVaSetValues(w, XtNstate, False, NULL); ++ } ++} ++ ++void ++SetFullColorState(Widget w, XEvent *ev, String *params, Cardinal *num_params) ++{ ++ if (appData.useBGR565 || appData.useBGR233) { ++ XtVaSetValues(w, XtNstate, False, NULL); ++ } else { ++ XtVaSetValues(w, XtNstate, True, NULL); ++ if (b8 != NULL) XtVaSetValues(b8, XtNstate, False, NULL); ++ if (b16 != NULL) XtVaSetValues(b16, XtNstate, False, NULL); ++ } ++} ++ ++void ++Set256ColorsState(Widget w, XEvent *ev, String *params, Cardinal *num_params) ++{ ++ if (appData.useBGR233 == 256) { ++ XtVaSetValues(w, XtNstate, True, NULL); ++ if (w64 != NULL) XtVaSetValues(w64 , XtNstate, False, NULL); ++ if (w8 != NULL) XtVaSetValues(w8 , XtNstate, False, NULL); ++ } else { ++ XtVaSetValues(w, XtNstate, False, NULL); ++ } ++} ++ ++void ++Set64ColorsState(Widget w, XEvent *ev, String *params, Cardinal *num_params) ++{ ++ if (appData.useBGR233 == 64) { ++ XtVaSetValues(w, XtNstate, True, NULL); ++ if (w256 != NULL) XtVaSetValues(w256, XtNstate, False, NULL); ++ if (w8 != NULL) XtVaSetValues(w8 , XtNstate, False, NULL); ++ } else { ++ XtVaSetValues(w, XtNstate, False, NULL); ++ } + } ++ ++void ++Set8ColorsState(Widget w, XEvent *ev, String *params, Cardinal *num_params) ++{ ++ if (appData.useBGR233 == 8) { ++ XtVaSetValues(w, XtNstate, True, NULL); ++ if (w256 != NULL) XtVaSetValues(w256, XtNstate, False, NULL); ++ if (w64 != NULL) XtVaSetValues(w64 , XtNstate, False, NULL); ++ } else { ++ XtVaSetValues(w, XtNstate, False, NULL); ++ } ++} ++ ++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) ++ XtVaSetValues(w, XtNstate, True, NULL); ++ else ++ XtVaSetValues(w, XtNstate, False, NULL); ++} ++ ++void ++SetCursorShapeState(Widget w, XEvent *ev, String *params, Cardinal *num_params) ++{ ++ if (appData.useRemoteCursor) ++ XtVaSetValues(w, XtNstate, True, NULL); ++ else ++ XtVaSetValues(w, XtNstate, False, NULL); ++} ++ ++void ++SetCursorAlphaState(Widget w, XEvent *ev, String *params, Cardinal *num_params) ++{ ++ if (appData.useCursorAlpha) ++ XtVaSetValues(w, XtNstate, True, NULL); ++ else ++ XtVaSetValues(w, XtNstate, False, NULL); ++} ++ ++void ++SetX11CursorState(Widget w, XEvent *ev, String *params, Cardinal *num_params) ++{ ++ if (appData.useX11Cursor) ++ XtVaSetValues(w, XtNstate, True, NULL); ++ else ++ XtVaSetValues(w, XtNstate, False, NULL); ++} ++ ++void ++SetRawLocalState(Widget w, XEvent *ev, String *params, Cardinal *num_params) ++{ ++ if (appData.useRawLocal) ++ XtVaSetValues(w, XtNstate, True, NULL); ++ else ++ 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-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 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; + + } AppData; + + extern AppData appData; ++extern AppData appDataNew; + + extern char *fallback_resources[]; + extern char vncServerHost[]; +@@ -130,6 +148,7 @@ + /* colour.c */ + + extern unsigned long BGR233ToPixel[]; ++extern unsigned long BGR565ToPixel[]; + + extern Colormap cmap; + extern Visual *vis; +@@ -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, +@@ -229,6 +254,15 @@ + extern Bool SendClientCutText(char *str, int len); + extern Bool HandleRFBServerMessage(); + ++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 +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); ++extern void ToggleCursorShape(Widget w, XEvent *ev, String *params, Cardinal *num_params); ++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); ++extern void Set8bppState(Widget w, XEvent *ev, String *params, Cardinal *num_params); ++extern void Set16bppState(Widget w, XEvent *ev, String *params, Cardinal *num_params); ++extern void SetFullColorState(Widget w, XEvent *ev, String *params, Cardinal *num_params); ++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-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. ++ ++.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. +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-17 22:36:37.000000000 -0500 +@@ -0,0 +1,455 @@ ++/* ++ * Copyright (C) 2005 Johannes E. Schindelin. 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. ++ */ ++ ++/* ++ * zrle.c - handle zrle encoding. ++ * ++ * This file shouldn't be compiled directly. It is included multiple times by ++ * rfbproto.c, each time with a different definition of the macro BPP. For ++ * each value of BPP, this file defines a function which handles an zrle ++ * encoded rectangle with BPP bits per pixel. ++ */ ++ ++#ifndef REALBPP ++#define REALBPP BPP ++#endif ++ ++#if !defined(UNCOMP) || UNCOMP==0 ++#define HandleZRLE CONCAT2E(HandleZRLE,REALBPP) ++#define HandleZRLETile CONCAT2E(HandleZRLETile,REALBPP) ++#elif UNCOMP>0 ++#define HandleZRLE CONCAT3E(HandleZRLE,REALBPP,Down) ++#define HandleZRLETile CONCAT3E(HandleZRLETile,REALBPP,Down) ++#else ++#define HandleZRLE CONCAT3E(HandleZRLE,REALBPP,Up) ++#define HandleZRLETile CONCAT3E(HandleZRLETile,REALBPP,Up) ++#endif ++#undef CARDBPP ++#undef CARDREALBPP ++#define CARDBPP CONCAT2E(CARD, BPP) ++#define CARDREALBPP CONCAT2E(CARD,REALBPP) ++ ++#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 int HandleZRLETile( ++ unsigned char* buffer,size_t buffer_length, ++ int x,int y,int w,int h); ++ ++static Bool ++HandleZRLE (int rx, int ry, int rw, int rh) ++{ ++ rfbZRLEHeader header; ++ int remaining; ++ int inflateResult; ++ int toRead; ++ int min_buffer_size = rw * rh * (REALBPP / 8) * 2; ++ ++ /* First make sure we have a large enough raw buffer to hold the ++ * decompressed data. In practice, with a fixed REALBPP, fixed frame ++ * buffer size and the first update containing the entire frame ++ * buffer, this buffer allocation should only happen once, on the ++ * first update. ++ */ ++ if ( raw_buffer_size < min_buffer_size) { ++ ++ if ( raw_buffer != NULL ) { ++ ++ free( raw_buffer ); ++ ++ } ++ ++ raw_buffer_size = min_buffer_size; ++ raw_buffer = (char*) malloc( raw_buffer_size ); ++ ++ } ++ ++ if (!ReadFromRFBServer((char *)&header, sz_rfbZRLEHeader)) ++ return False; ++ ++ remaining = Swap32IfLE(header.length); ++ ++ /* Need to initialize the decompressor state. */ ++ decompStream.next_in = ( Bytef * )buffer; ++ decompStream.avail_in = 0; ++ decompStream.next_out = ( Bytef * )raw_buffer; ++ decompStream.avail_out = raw_buffer_size; ++ decompStream.data_type = Z_BINARY; ++ ++ /* Initialize the decompression stream structures on the first invocation. */ ++ if ( decompStreamInited == False ) { ++ ++ inflateResult = inflateInit( &decompStream ); ++ ++ if ( inflateResult != Z_OK ) { ++ fprintf(stderr, ++ "inflateInit returned error: %d, msg: %s\n", ++ inflateResult, ++ decompStream.msg); ++ return False; ++ } ++ ++ decompStreamInited = True; ++ ++ } ++ ++ inflateResult = Z_OK; ++ ++ /* Process buffer full of data until no more to process, or ++ * some type of inflater error, or Z_STREAM_END. ++ */ ++ while (( remaining > 0 ) && ++ ( inflateResult == Z_OK )) { ++ ++ if ( remaining > BUFFER_SIZE ) { ++ toRead = BUFFER_SIZE; ++ } ++ else { ++ toRead = remaining; ++ } ++ ++ /* Fill the buffer, obtaining data from the server. */ ++ if (!ReadFromRFBServer(buffer,toRead)) ++ return False; ++ ++ decompStream.next_in = ( Bytef * )buffer; ++ decompStream.avail_in = toRead; ++ ++ /* Need to uncompress buffer full. */ ++ inflateResult = inflate( &decompStream, Z_SYNC_FLUSH ); ++ ++ /* We never supply a dictionary for compression. */ ++ if ( inflateResult == Z_NEED_DICT ) { ++ fprintf(stderr, "zlib inflate needs a dictionary!\n"); ++ return False; ++ } ++ if ( inflateResult < 0 ) { ++ fprintf(stderr, ++ "zlib inflate returned error: %d, msg: %s\n", ++ inflateResult, ++ decompStream.msg); ++ return False; ++ } ++ ++ /* Result buffer allocated to be at least large enough. We should ++ * never run out of space! ++ */ ++ if (( decompStream.avail_in > 0 ) && ++ ( decompStream.avail_out <= 0 )) { ++ fprintf(stderr, "zlib inflate ran out of space!\n"); ++ return False; ++ } ++ ++ remaining -= toRead; ++ ++ } /* while ( remaining > 0 ) */ ++ ++ if ( inflateResult == Z_OK ) { ++ void* buf=raw_buffer; ++ int i,j; ++ ++ remaining = raw_buffer_size-decompStream.avail_out; ++ ++ for(j=0; jrw)?rw-i:rfbZRLETileWidth; ++ int subHeight=(j+rfbZRLETileHeight>rh)?rh-j:rfbZRLETileHeight; ++ int result=HandleZRLETile(buf,remaining,rx+i,ry+j,subWidth,subHeight); ++ ++ if(result<0) { ++ fprintf(stderr, "ZRLE decoding failed (%d)\n",result); ++return True; ++ return False; ++ } ++ ++ buf+=result; ++ remaining-=result; ++ } ++ } ++ else { ++ ++ fprintf(stderr, ++ "zlib inflate returned error: %d, msg: %s\n", ++ inflateResult, ++ decompStream.msg); ++ return False; ++ ++ } ++ ++ return True; ++} ++ ++#if REALBPP!=BPP && defined(UNCOMP) && UNCOMP!=0 ++#if UNCOMP>0 ++#define UncompressCPixel(pointer) ((*(CARDBPP*)pointer)>>UNCOMP) ++#else ++#define UncompressCPixel(pointer) ((*(CARDBPP*)pointer)<<(-(UNCOMP))) ++#endif ++#else ++#define UncompressCPixel(pointer) (*(CARDBPP*)pointer) ++#endif ++ ++static int HandleZRLETile( ++ unsigned char* buffer,size_t buffer_length, ++ int x,int y,int w,int h) { ++ unsigned char* buffer_copy = buffer; ++ unsigned char* buffer_end = buffer+buffer_length; ++ unsigned char type; ++ ++ if(buffer_length<1) ++ return -2; ++ ++ if (frameBufferLen < w * h * REALBPP/8) { ++ if(frameBuffer) { ++ free(frameBuffer); ++ } ++ frameBufferLen = w * h * REALBPP/8 * 2; ++ frameBuffer = (unsigned char *) malloc(frameBufferLen); ++ } ++ ++ type = *buffer; ++ buffer++; ++ switch(type) { ++ case 0: /* raw */ ++ { ++#if REALBPP!=BPP ++ int m0 = 0, i,j; ++ ++ if(1+w*h*REALBPP/8>buffer_length) { ++ fprintf(stderr, "expected %d bytes, got only %d (%dx%d)\n",1+w*h*REALBPP/8,buffer_length,w,h); ++ return -3; ++ } ++ ++ for(j=y*si.framebufferWidth; j<(y+h)*si.framebufferWidth; j+=si.framebufferWidth) { ++ for(i=x; ibuffer_length) ++ return -4; ++ ++ if ((BPP == 8 && appData.useBGR233) || (BPP == 16 && appData.useBGR565)) { ++ int m0; ++ for (m0=0; m0 < w*h; m0++) { ++ ((CARDBPP*)frameBuffer)[m0] = color; ++ } ++ CopyDataToScreen((char *)frameBuffer, x, y, w, h); ++ } else { ++ FillRectangle(x, y, w, h, color); ++ } ++if (0) fprintf(stderr, "cha2: %dx%d+%d+%d\n", w, h, x, y); ++ ++ buffer+=REALBPP/8; ++ ++ break; ++ } ++ case 2 ... 127: /* packed Palette */ ++ { ++ CARDBPP palette[16]; ++ int m0, i,j,shift, ++ bpp=(type>4?(type>16?8:4):(type>2?2:1)), ++ mask=(1<buffer_length) ++ return -5; ++ ++ /* read palette */ ++ for(i=0; i>shift)&mask]; ++ /* alt */ ++ CARDBPP color = palette[((*buffer)>>shift)&mask]; ++ CopyDataToScreen((char *)&color, i, j/si.framebufferWidth, 1, 1); ++# else ++ ((CARDBPP*)frameBuffer)[m0++] = palette[((*buffer)>>shift)&mask]; ++# endif ++ shift-=bpp; ++ if(shift<0) { ++ shift=8-bpp; ++ buffer++; ++ } ++ } ++ if(shift<8-bpp) ++ buffer++; ++ } ++ CopyDataToScreen((char *)frameBuffer, x, y, w, h); ++if (0) fprintf(stderr, "cha3: %dx%d+%d+%d\n", w, h, x, y); ++ ++ break; ++ } ++ /* case 17 ... 127: not used, but valid */ ++ case 128: /* plain RLE */ ++ { ++ int m0=0, i=0,j=0; ++ while(jbuffer_end) ++ return -7; ++ color = UncompressCPixel(buffer); ++ buffer+=REALBPP/8; ++ /* read run length */ ++ length=1; ++ while(*buffer==0xff) { ++ if(buffer+1>=buffer_end) ++ return -8; ++ length+=*buffer; ++ buffer++; ++ } ++ length+=*buffer; ++ buffer++; ++ while(j0) { ++# if 0 ++ ((CARDBPP*)frameBuffer)[(y+j)*si.framebufferWidth+x+i] = color; ++ /* alt */ ++ CopyDataToScreen((char *)&color, x+i, y+j, 1, 1); ++# else ++ ((CARDBPP*)frameBuffer)[m0++] = color; ++# endif ++ length--; ++ i++; ++ if(i>=w) { ++ i=0; ++ j++; ++ } ++ } ++ if(length>0) ++ fprintf(stderr, "Warning: possible ZRLE corruption\n"); ++ } ++ CopyDataToScreen((char *)frameBuffer, x, y, w, h); ++if (0) fprintf(stderr, "cha4: %dx%d+%d+%d\n", w, h, x, y); ++ ++ break; ++ } ++ case 129: /* unused */ ++ { ++ return -8; ++ } ++ case 130 ... 255: /* palette RLE */ ++ { ++ CARDBPP palette[128]; ++ int m0 = 0, i,j; ++ ++ if(2+(type-128)*REALBPP/8>buffer_length) ++ return -9; ++ ++ /* read palette */ ++ for(i=0; i=buffer_end) ++ return -10; ++ color = palette[(*buffer)&0x7f]; ++ length=1; ++ if(*buffer&0x80) { ++ if(buffer+1>=buffer_end) ++ return -11; ++ buffer++; ++ /* read run length */ ++ while(*buffer==0xff) { ++ if(buffer+1>=buffer_end) ++ return -8; ++ length+=*buffer; ++ buffer++; ++ } ++ length+=*buffer; ++ } ++ buffer++; ++ while(j0) { ++# if 0 ++ ((CARDBPP*)frameBuffer)[(y+j)*si.framebufferWidth+x+i] = color; ++ /* alt */ ++ CopyDataToScreen((char *)&color, x+i, y+j, 1, 1); ++# else ++ ((CARDBPP*)frameBuffer)[m0++] = color; ++# endif ++ length--; ++ i++; ++ if(i>=w) { ++ i=0; ++ j++; ++ } ++ } ++ if(length>0) ++ fprintf(stderr, "Warning: possible ZRLE corruption\n"); ++ } ++ CopyDataToScreen((char *)frameBuffer, x, y, w, h); ++if (0) fprintf(stderr, "cha5: %dx%d+%d+%d\n", w, h, x, y); ++ ++ break; ++ } ++ } ++ ++ return buffer-buffer_copy; ++} ++ ++#undef CARDBPP ++#undef CARDREALBPP ++#undef HandleZRLE ++#undef HandleZRLETile ++#undef UncompressCPixel ++#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 @@ +/* -+ * ToggleJPEG ++ * 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. + */ + -+void -+ToggleJPEG(Widget w, XEvent *ev, String *params, Cardinal *num_params) -+{ -+ init_format_change(); -+ if (appData.enableJPEG) { -+ appDataNew.enableJPEG = False; -+ fprintf(stderr, "JPEG: off\n"); -+ } else { -+ appDataNew.enableJPEG = True; -+ fprintf(stderr, "JPEG: on\n"); -+ } -+ schedule_format_change(); -+} -+ +/* -+ * ToggleTightZRLE ++ * 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. + */ + -+static Bool usingZRLE = False; ++#include "zrleoutstream.h" ++#include "zrlepalettehelper.h" ++#include + -+void -+ToggleTightZRLE(Widget w, XEvent *ev, String *params, Cardinal *num_params) -+{ -+ char prefTight[] = "copyrect tight zrle zlib hextile corre rre raw"; -+ char prefZRLE[] = "copyrect zrle tight zlib hextile corre rre raw"; -+ init_format_change(); -+ if (! appData.encodingsString) { -+ appDataNew.encodingsString = strdup(prefZRLE); -+ usingZRLE = True; -+ fprintf(stderr, "prefer: ZRLE\n"); -+ } else { -+ char *p, *q; -+ p = strstr(appData.encodingsString, "tight"); -+ q = strstr(appData.encodingsString, "zrle"); -+ if (! p) { -+ appDataNew.encodingsString = strdup(prefZRLE); -+ usingZRLE = True; -+ fprintf(stderr, "prefer: ZRLE\n"); -+ } else if (! q) { -+ appDataNew.encodingsString = strdup(prefTight); -+ usingZRLE = False; -+ fprintf(stderr, "prefer: Tight\n"); -+ } else { -+ if (p < q) { -+ appDataNew.encodingsString = strdup(prefZRLE); -+ usingZRLE = True; -+ fprintf(stderr, "prefer: ZRLE\n"); -+ } else { -+ appDataNew.encodingsString = strdup(prefTight); -+ usingZRLE = False; -+ fprintf(stderr, "prefer: Tight\n"); -+ } -+ } -+ } -+ schedule_format_change(); -+} ++/* __RFB_CONCAT2 concatenates its two arguments. __RFB_CONCAT2E does the same ++ but also expands its arguments if they are macros */ + -+/* -+ * ToggleViewOnly -+ */ ++#ifndef __RFB_CONCAT2E ++#define __RFB_CONCAT2(a,b) a##b ++#define __RFB_CONCAT2E(a,b) __RFB_CONCAT2(a,b) ++#endif + -+void -+ToggleViewOnly(Widget w, XEvent *ev, String *params, Cardinal *num_params) -+{ -+ if (appData.viewOnly) { -+ appData.viewOnly = False; -+ fprintf(stderr, "viewonly: off\n"); -+ } else { -+ appData.viewOnly = True; -+ fprintf(stderr, "viewonly: on\n"); -+ } -+} ++#ifndef __RFB_CONCAT3E ++#define __RFB_CONCAT3(a,b,c) a##b##c ++#define __RFB_CONCAT3E(a,b,c) __RFB_CONCAT3(a,b,c) ++#endif + -+void -+ToggleCursorShape(Widget w, XEvent *ev, String *params, Cardinal *num_params) -+{ -+ init_format_change(); -+ if (appData.useRemoteCursor) { -+ appDataNew.useRemoteCursor = False; -+ fprintf(stderr, "useRemoteCursor: off\n"); -+ } else { -+ appDataNew.useRemoteCursor = True; -+ fprintf(stderr, "useRemoteCursor: on\n"); -+ } -+ schedule_format_change(); -+ if (!appDataNew.useRemoteCursor) { -+ do_cursor_change = 1; -+ } else { -+ do_cursor_change = -1; -+ } -+} ++#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 + -+void -+ToggleCursorAlpha(Widget w, XEvent *ev, String *params, Cardinal *num_params) -+{ -+ if (appData.useCursorAlpha) { -+ appData.useCursorAlpha = False; -+ fprintf(stderr, "useCursorAlpha: off\n"); -+ } else { -+ appData.useCursorAlpha = True; -+ fprintf(stderr, "useCursorAlpha: on\n"); -+ } -+} ++#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 + -+void -+ToggleX11Cursor(Widget w, XEvent *ev, String *params, Cardinal *num_params) -+{ -+ init_format_change(); -+ if (appData.useX11Cursor) { -+ appDataNew.useX11Cursor = False; -+ fprintf(stderr, "useX11Cursor: off\n"); -+ } else { -+ appDataNew.useX11Cursor = True; -+ fprintf(stderr, "useX11Cursor: on\n"); -+ } -+ schedule_format_change(); -+ do_cursor_change = 1; -+} ++#ifndef ZRLE_ONCE ++#define ZRLE_ONCE + -+void -+ToggleRawLocal(Widget w, XEvent *ev, String *params, Cardinal *num_params) -+{ -+ init_format_change(); -+ if (appData.useRawLocal) { -+ appDataNew.useRawLocal = False; -+ fprintf(stderr, "useRawLocal: off\n"); -+ } else { -+ appDataNew.useRawLocal = True; -+ fprintf(stderr, "useRawLocal: on\n"); -+ } -+ schedule_format_change(); -+} ++static const int bitsPerPackedPixel[] = { ++ 0, 1, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 ++}; + -+void -+SetViewOnlyState(Widget w, XEvent *ev, String *params, Cardinal *num_params) -+{ -+ if (appData.viewOnly) -+ XtVaSetValues(w, XtNstate, True, NULL); -+ else -+ XtVaSetValues(w, XtNstate, False, NULL); -+} ++int zywrle_level; ++int zywrleBuf[rfbZRLETileWidth*rfbZRLETileHeight]; + -+void -+SetNOJPEGState(Widget w, XEvent *ev, String *params, Cardinal *num_params) -+{ -+ if (appData.enableJPEG) -+ XtVaSetValues(w, XtNstate, False, NULL); -+ else -+ XtVaSetValues(w, XtNstate, True, NULL); -+} ++static zrlePaletteHelper paletteHelper; + -+void -+Set8bppState(Widget w, XEvent *ev, String *params, Cardinal *num_params) -+{ -+ if (appData.useBGR233) { -+ XtVaSetValues(w, XtNstate, True, NULL); -+ if (b16 != NULL) XtVaSetValues(b16, XtNstate, False, NULL); -+ if (bfull != NULL) XtVaSetValues(bfull, XtNstate, False, NULL); -+ } else { -+ XtVaSetValues(w, XtNstate, False, NULL); -+ } -+} ++#endif /* ZRLE_ONCE */ + -+void -+Set16bppState(Widget w, XEvent *ev, String *params, Cardinal *num_params) -+{ -+ if (appData.useBGR565) { -+ XtVaSetValues(w, XtNstate, True, NULL); -+ if (b8 != NULL) XtVaSetValues(b8, XtNstate, False, NULL); -+ if (bfull != NULL) XtVaSetValues(bfull, XtNstate, False, NULL); -+ } else { -+ XtVaSetValues(w, XtNstate, False, NULL); -+ } -+} ++void ZRLE_ENCODE_TILE (PIXEL_T* data, int w, int h, zrleOutStream* os); + -+void -+SetFullColorState(Widget w, XEvent *ev, String *params, Cardinal *num_params) -+{ -+ if (appData.useBGR565 || appData.useBGR233) { -+ XtVaSetValues(w, XtNstate, False, NULL); -+ } else { -+ XtVaSetValues(w, XtNstate, True, NULL); -+ if (b8 != NULL) XtVaSetValues(b8, XtNstate, False, NULL); -+ if (b16 != NULL) XtVaSetValues(b16, XtNstate, False, NULL); -+ } -+} ++#if BPP!=8 ++#define ZYWRLE_ENCODE ++#include "zywrletemplate.c" ++#endif + -+void -+Set256ColorsState(Widget w, XEvent *ev, String *params, Cardinal *num_params) ++static void ZRLE_ENCODE (int x, int y, int w, int h, ++ zrleOutStream* os, void* buf ++ EXTRA_ARGS ++ ) +{ -+ if (appData.useBGR233 == 256) { -+ XtVaSetValues(w, XtNstate, True, NULL); -+ if (w64 != NULL) XtVaSetValues(w64 , XtNstate, False, NULL); -+ if (w8 != NULL) XtVaSetValues(w8 , XtNstate, False, NULL); -+ } else { -+ XtVaSetValues(w, XtNstate, False, NULL); -+ } -+} ++ 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; + -+void -+Set64ColorsState(Widget w, XEvent *ev, String *params, Cardinal *num_params) -+{ -+ if (appData.useBGR233 == 64) { -+ XtVaSetValues(w, XtNstate, True, NULL); -+ if (w256 != NULL) XtVaSetValues(w256, XtNstate, False, NULL); -+ if (w8 != NULL) XtVaSetValues(w8 , XtNstate, False, NULL); -+ } else { -+ XtVaSetValues(w, XtNstate, False, NULL); -+ } -+} ++ GET_IMAGE_INTO_BUF(tx,ty,tw,th,buf); + -+void -+Set8ColorsState(Widget w, XEvent *ev, String *params, Cardinal *num_params) -+{ -+ if (appData.useBGR233 == 8) { -+ XtVaSetValues(w, XtNstate, True, NULL); -+ if (w256 != NULL) XtVaSetValues(w256, XtNstate, False, NULL); -+ if (w64 != NULL) XtVaSetValues(w64 , XtNstate, False, NULL); -+ } else { -+ XtVaSetValues(w, XtNstate, False, NULL); -+ } ++ ZRLE_ENCODE_TILE((PIXEL_T*)buf, tw, th, os); ++ } ++ } ++ zrleOutStreamFlush(os); +} + -+void -+SetZRLEState(Widget w, XEvent *ev, String *params, Cardinal *num_params) ++ ++void ZRLE_ENCODE_TILE (PIXEL_T* data, int w, int h, zrleOutStream* os) +{ -+ if (usingZRLE) -+ XtVaSetValues(w, XtNstate, True, NULL); -+ else -+ XtVaSetValues(w, XtNstate, False, NULL); -+} ++ /* 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; ++ } + -+void -+SetCursorShapeState(Widget w, XEvent *ev, String *params, Cardinal *num_params) -+{ -+ if (appData.useRemoteCursor) -+ XtVaSetValues(w, XtNstate, True, NULL); -+ else -+ XtVaSetValues(w, XtNstate, False, NULL); -+} ++ if (ph->size < 17) { ++ int packedBytes = ((BPPOUT/8) * ph->size + ++ w * h * bitsPerPackedPixel[ph->size-1] / 8); + -+void -+SetCursorAlphaState(Widget w, XEvent *ev, String *params, Cardinal *num_params) -+{ -+ if (appData.useCursorAlpha) -+ XtVaSetValues(w, XtNstate, True, NULL); -+ else -+ XtVaSetValues(w, XtNstate, False, NULL); -+} ++ if (packedBytes < estimatedBytes) { ++ useRle = FALSE; ++ usePalette = TRUE; ++ estimatedBytes = packedBytes; ++ } ++ } ++ } + -+void -+SetX11CursorState(Widget w, XEvent *ev, String *params, Cardinal *num_params) -+{ -+ if (appData.useX11Cursor) -+ XtVaSetValues(w, XtNstate, True, NULL); -+ else -+ XtVaSetValues(w, XtNstate, False, NULL); -+} ++ if (!usePalette) ph->size = 0; + -+void -+SetRawLocalState(Widget w, XEvent *ev, String *params, Cardinal *num_params) -+{ -+ if (appData.useRawLocal) -+ XtVaSetValues(w, XtNstate, True, NULL); -+ else -+ XtVaSetValues(w, XtNstate, False, NULL); -+} ++ 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 { + -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; - -- Bool useBGR233; -+ int useBGR233; - int nColours; - Bool useSharedColours; - Bool forceOwnCmap; - Bool forceTrueColour; - int requestedDepth; -+ Bool useBGR565; ++ /* no RLE */ + -+ Bool grabAll; -+ Bool overrideRedir; -+ Bool popupFix; - - Bool useShm; - -@@ -96,6 +101,11 @@ - int rawDelay; - int copyRectDelay; - -+ int yCrop; -+ int sbWidth; -+ Bool useCursorAlpha; -+ Bool useRawLocal; ++ if (usePalette) { ++ int bppp; ++ PIXEL_T* ptr = data; + - Bool debug; - - int popupButtonCount; -@@ -113,6 +123,7 @@ - } AppData; - - extern AppData appData; -+extern AppData appDataNew; - - extern char *fallback_resources[]; - extern char vncServerHost[]; -@@ -130,6 +141,7 @@ - /* colour.c */ - - extern unsigned long BGR233ToPixel[]; -+extern unsigned long BGR565ToPixel[]; - - extern Colormap cmap; - extern Visual *vis; -@@ -162,6 +174,9 @@ - extern void CopyDataToScreen(char *buf, int x, int y, int width, int height); - extern void SynchroniseScreen(); - -+extern void ReDoDesktop(); -+extern void DesktopCursorOff(); ++ /* packed pixels */ + - /* dialogs.c */ - - extern void ServerDialogDone(Widget w, XEvent *event, String *params, -@@ -243,6 +258,7 @@ - - extern XImage *CreateShmImage(); - extern void ShmCleanup(); -+extern Bool UsingShm(); - - /* sockets.c */ - -@@ -271,3 +287,31 @@ - extern XtAppContext appContext; - extern Display* dpy; - extern Widget toplevel; ++ assert (ph->size < 17); + -+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 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); -+extern void ToggleCursorShape(Widget w, XEvent *ev, String *params, Cardinal *num_params); -+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); ++ bppp = bitsPerPackedPixel[ph->size-1]; + -+extern void SetViewOnlyState(Widget w, XEvent *ev, String *params, Cardinal *num_params); -+extern void SetNOJPEGState(Widget w, XEvent *ev, String *params, Cardinal *num_params); -+extern void Set8bppState(Widget w, XEvent *ev, String *params, Cardinal *num_params); -+extern void Set16bppState(Widget w, XEvent *ev, String *params, Cardinal *num_params); -+extern void SetFullColorState(Widget w, XEvent *ev, String *params, Cardinal *num_params); -+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 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); -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 @@ - \fB\-autopass\fR - Read a plain-text password from stdin. This option affects only the - standard VNC authentication. ++ for (i = 0; i < h; i++) { ++ zrle_U8 nbits = 0; ++ zrle_U8 byte = 0; + -+.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. ++ PIXEL_T* eol = ptr + w; + - .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/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 @@ ++ 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) 2005 Johannes E. Schindelin. All Rights Reserved. ++ * 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 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. ++ * 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. ++ * 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. + */ + -+/* -+ * zrle.c - handle zrle encoding. -+ * -+ * This file shouldn't be compiled directly. It is included multiple times by -+ * rfbproto.c, each time with a different definition of the macro BPP. For -+ * each value of BPP, this file defines a function which handles an zrle -+ * encoded rectangle with BPP bits per pixel. -+ */ ++#include "zrleoutstream.h" ++#include + -+#ifndef REALBPP -+#define REALBPP BPP -+#endif ++#define ZRLE_IN_BUFFER_SIZE 16384 ++#define ZRLE_OUT_BUFFER_SIZE 1024 ++#undef ZRLE_DEBUG + -+#if !defined(UNCOMP) || UNCOMP==0 -+#define HandleZRLE CONCAT2E(HandleZRLE,REALBPP) -+#define HandleZRLETile CONCAT2E(HandleZRLETile,REALBPP) -+#elif UNCOMP>0 -+#define HandleZRLE CONCAT3E(HandleZRLE,REALBPP,Down) -+#define HandleZRLETile CONCAT3E(HandleZRLETile,REALBPP,Down) -+#else -+#define HandleZRLE CONCAT3E(HandleZRLE,REALBPP,Up) -+#define HandleZRLETile CONCAT3E(HandleZRLETile,REALBPP,Up) -+#endif -+#undef CARDBPP -+#undef CARDREALBPP -+#define CARDBPP CONCAT2E(CARD, BPP) -+#define CARDREALBPP CONCAT2E(CARD,REALBPP) ++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; ++ } + -+#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); \ -+ } ++ 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; ++ } + -+static int HandleZRLETile( -+ unsigned char* buffer,size_t buffer_length, -+ int x,int y,int w,int h); ++ return os; ++} + -+static Bool -+HandleZRLE (int rx, int ry, int rw, int rh) ++void zrleOutStreamFree (zrleOutStream *os) +{ -+ rfbZRLEHeader header; -+ int remaining; -+ int inflateResult; -+ int toRead; -+ int min_buffer_size = rw * rh * (REALBPP / 8) * 2; ++ deflateEnd(&os->zs); ++ zrleBufferFree(&os->in); ++ zrleBufferFree(&os->out); ++ free(os); ++} + -+ /* First make sure we have a large enough raw buffer to hold the -+ * decompressed data. In practice, with a fixed REALBPP, fixed frame -+ * buffer size and the first update containing the entire frame -+ * buffer, this buffer allocation should only happen once, on the -+ * first update. -+ */ -+ if ( raw_buffer_size < min_buffer_size) { ++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 + -+ if ( raw_buffer != NULL ) { ++ while (os->zs.avail_in != 0) { ++ do { ++ int ret; + -+ free( raw_buffer ); ++ 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; + -+ raw_buffer_size = min_buffer_size; -+ raw_buffer = (char*) malloc( raw_buffer_size ); ++#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; ++ } + -+ if (!ReadFromRFBServer((char *)&header, sz_rfbZRLEHeader)) -+ return False; ++#ifdef ZRLE_DEBUG ++ rfbLog("zrleOutStreamFlush: after deflate: %d bytes\n", ++ os->zs.next_out - os->out.ptr); ++#endif + -+ remaining = Swap32IfLE(header.length); ++ os->out.ptr = os->zs.next_out; ++ } while (os->zs.avail_out == 0); ++ } + -+ /* Need to initialize the decompressor state. */ -+ decompStream.next_in = ( Bytef * )buffer; -+ decompStream.avail_in = 0; -+ decompStream.next_out = ( Bytef * )raw_buffer; -+ decompStream.avail_out = raw_buffer_size; -+ decompStream.data_type = Z_BINARY; ++ os->in.ptr = os->in.start; ++ ++ return TRUE; ++} + -+ /* Initialize the decompression stream structures on the first invocation. */ -+ if ( decompStreamInited == False ) { ++static int zrleOutStreamOverrun(zrleOutStream *os, ++ int size) ++{ ++#ifdef ZRLE_DEBUG ++ rfbLog("zrleOutStreamOverrun\n"); ++#endif + -+ inflateResult = inflateInit( &decompStream ); ++ 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); + -+ if ( inflateResult != Z_OK ) { -+ fprintf(stderr, -+ "inflateInit returned error: %d, msg: %s\n", -+ inflateResult, -+ decompStream.msg); -+ return False; -+ } ++ do { ++ int ret; + -+ decompStreamInited = True; ++ 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; + -+ inflateResult = Z_OK; ++#ifdef ZRLE_DEBUG ++ rfbLog("zrleOutStreamOverrun: calling deflate, avail_in %d, avail_out %d\n", ++ os->zs.avail_in, os->zs.avail_out); ++#endif + -+ /* Process buffer full of data until no more to process, or -+ * some type of inflater error, or Z_STREAM_END. -+ */ -+ while (( remaining > 0 ) && -+ ( inflateResult == Z_OK )) { ++ if ((ret = deflate(&os->zs, 0)) != Z_OK) { ++ rfbLog("zrleOutStreamOverrun: deflate failed with error code %d\n", ret); ++ return 0; ++ } + -+ if ( remaining > BUFFER_SIZE ) { -+ toRead = BUFFER_SIZE; -+ } -+ else { -+ toRead = remaining; -+ } ++#ifdef ZRLE_DEBUG ++ rfbLog("zrleOutStreamOverrun: after deflate: %d bytes\n", ++ os->zs.next_out - os->out.ptr); ++#endif + -+ /* Fill the buffer, obtaining data from the server. */ -+ if (!ReadFromRFBServer(buffer,toRead)) -+ return False; ++ os->out.ptr = os->zs.next_out; ++ } while (os->zs.avail_out == 0); + -+ decompStream.next_in = ( Bytef * )buffer; -+ decompStream.avail_in = toRead; ++ /* output buffer not full */ + -+ /* Need to uncompress buffer full. */ -+ inflateResult = inflate( &decompStream, Z_SYNC_FLUSH ); ++ 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; ++ } ++ } + -+ /* We never supply a dictionary for compression. */ -+ if ( inflateResult == Z_NEED_DICT ) { -+ fprintf(stderr, "zlib inflate needs a dictionary!\n"); -+ return False; -+ } -+ if ( inflateResult < 0 ) { -+ fprintf(stderr, -+ "zlib inflate returned error: %d, msg: %s\n", -+ inflateResult, -+ decompStream.msg); -+ return False; -+ } ++ if (size > os->in.end - os->in.ptr) ++ size = os->in.end - os->in.ptr; + -+ /* Result buffer allocated to be at least large enough. We should -+ * never run out of space! -+ */ -+ if (( decompStream.avail_in > 0 ) && -+ ( decompStream.avail_out <= 0 )) { -+ fprintf(stderr, "zlib inflate ran out of space!\n"); -+ return False; -+ } ++ return size; ++} + -+ remaining -= toRead; ++static int zrleOutStreamCheck(zrleOutStream *os, int size) ++{ ++ if (os->in.ptr + size > os->in.end) { ++ return zrleOutStreamOverrun(os, size); ++ } ++ return size; ++} + -+ } /* while ( remaining > 0 ) */ ++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; ++ } ++} + -+ if ( inflateResult == Z_OK ) { -+ void* buf=raw_buffer; -+ int i,j; ++void zrleOutStreamWriteU8(zrleOutStream *os, zrle_U8 u) ++{ ++ zrleOutStreamCheck(os, 1); ++ *os->in.ptr++ = u; ++} + -+ remaining = raw_buffer_size-decompStream.avail_out; ++void zrleOutStreamWriteOpaque8(zrleOutStream *os, zrle_U8 u) ++{ ++ zrleOutStreamCheck(os, 1); ++ *os->in.ptr++ = u; ++} + -+ for(j=0; jrw)?rw-i:rfbZRLETileWidth; -+ int subHeight=(j+rfbZRLETileHeight>rh)?rh-j:rfbZRLETileHeight; -+ int result=HandleZRLETile(buf,remaining,rx+i,ry+j,subWidth,subHeight); ++void zrleOutStreamWriteOpaque16 (zrleOutStream *os, zrle_U16 u) ++{ ++ zrleOutStreamCheck(os, 2); ++ *os->in.ptr++ = ((zrle_U8*)&u)[0]; ++ *os->in.ptr++ = ((zrle_U8*)&u)[1]; ++} + -+ if(result<0) { -+ fprintf(stderr, "ZRLE decoding failed (%d)\n",result); -+return True; -+ return False; -+ } ++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]; ++} + -+ buf+=result; -+ remaining-=result; -+ } -+ } -+ else { ++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]; ++} + -+ fprintf(stderr, -+ "zlib inflate returned error: %d, msg: %s\n", -+ inflateResult, -+ decompStream.msg); -+ return False; ++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__ + -+ return True; -+} ++#include ++#include "zrletypes.h" ++#include "rfb/rfb.h" + -+#if REALBPP!=BPP && defined(UNCOMP) && UNCOMP!=0 -+#if UNCOMP>0 -+#define UncompressCPixel(pointer) ((*(CARDBPP*)pointer)>>UNCOMP) -+#else -+#define UncompressCPixel(pointer) ((*(CARDBPP*)pointer)<<(-(UNCOMP))) -+#endif -+#else -+#define UncompressCPixel(pointer) (*(CARDBPP*)pointer) -+#endif ++typedef struct { ++ zrle_U8 *start; ++ zrle_U8 *ptr; ++ zrle_U8 *end; ++} zrleBuffer; + -+static int HandleZRLETile( -+ unsigned char* buffer,size_t buffer_length, -+ int x,int y,int w,int h) { -+ unsigned char* buffer_copy = buffer; -+ unsigned char* buffer_end = buffer+buffer_length; -+ unsigned char type; ++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. ++ */ + -+ if(buffer_length<1) -+ return -2; ++#include "zrlepalettehelper.h" ++#include ++#include + -+ if (frameBufferLen < w * h * REALBPP/8) { -+ if(frameBuffer) { -+ free(frameBuffer); -+ } -+ frameBufferLen = w * h * REALBPP/8 * 2; -+ frameBuffer = (unsigned char *) malloc(frameBufferLen); -+ } ++#define ZRLE_HASH(pix) (((pix) ^ ((pix) >> 17)) & 4095) + -+ type = *buffer; -+ buffer++; -+ switch(type) { -+ case 0: /* raw */ -+ { -+#if REALBPP!=BPP -+ int m0 = 0, i,j; ++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; ++} + -+ if(1+w*h*REALBPP/8>buffer_length) { -+ fprintf(stderr, "expected %d bytes, got only %d (%dx%d)\n",1+w*h*REALBPP/8,buffer_length,w,h); -+ return -3; -+ } ++void zrlePaletteHelperInsert(zrlePaletteHelper *helper, zrle_U32 pix) ++{ ++ if (helper->size < ZRLE_PALETTE_MAX_SIZE) { ++ int i = ZRLE_HASH(pix); + -+ for(j=y*si.framebufferWidth; j<(y+h)*si.framebufferWidth; j+=si.framebufferWidth) { -+ for(i=x; iindex[i] != 255 && helper->key[i] != pix) ++ i++; ++ if (helper->index[i] != 255) return; + -+#else -+# if 0 -+ CopyRectangle(buffer, x, y, w, h); -+# else -+ CopyDataToScreen((char *)buffer, x, y, w, h); -+# endif -+ buffer+=w*h*REALBPP/8; -+#endif -+ break; -+ } -+ case 1: /* solid */ -+ { -+ CARDBPP color = UncompressCPixel(buffer); ++ helper->index[i] = helper->size; ++ helper->key[i] = pix; ++ helper->palette[helper->size] = pix; ++ } ++ helper->size++; ++} + -+ if(1+REALBPP/8>buffer_length) -+ return -4; -+ -+ if ((BPP == 8 && appData.useBGR233) || (BPP == 16 && appData.useBGR565)) { -+ int m0; -+ for (m0=0; m0 < w*h; m0++) { -+ ((CARDBPP*)frameBuffer)[m0] = color; -+ } -+ CopyDataToScreen((char *)frameBuffer, x, y, w, h); -+ } else { -+ FillRectangle(x, y, w, h, color); -+ } -+if (0) fprintf(stderr, "cha2: %dx%d+%d+%d\n", w, h, x, y); ++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 ++ */ + -+ buffer+=REALBPP/8; ++#ifndef __ZRLE_PALETTE_HELPER_H__ ++#define __ZRLE_PALETTE_HELPER_H__ + -+ break; -+ } -+ case 2 ... 127: /* packed Palette */ -+ { -+ CARDBPP palette[16]; -+ int m0, i,j,shift, -+ bpp=(type>4?(type>16?8:4):(type>2?2:1)), -+ mask=(1<buffer_length) -+ return -5; ++#define ZRLE_PALETTE_MAX_SIZE 127 + -+ /* read palette */ -+ for(i=0; i>shift)&mask]; -+ /* alt */ -+ CARDBPP color = palette[((*buffer)>>shift)&mask]; -+ CopyDataToScreen((char *)&color, i, j/si.framebufferWidth, 1, 1); ++#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 -+ ((CARDBPP*)frameBuffer)[m0++] = palette[((*buffer)>>shift)&mask]; ++// 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 -+ shift-=bpp; -+ if(shift<0) { -+ shift=8-bpp; -+ buffer++; -+ } -+ } -+ if(shift<8-bpp) -+ buffer++; -+ } -+ CopyDataToScreen((char *)frameBuffer, x, y, w, h); -+if (0) fprintf(stderr, "cha3: %dx%d+%d+%d\n", w, h, x, y); ++#endif + -+ break; ++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 + } -+ /* case 17 ... 127: not used, but valid */ -+ case 128: /* plain RLE */ -+ { -+ int m0=0, i=0,j=0; -+ while(jbuffer_end) -+ return -7; -+ color = UncompressCPixel(buffer); -+ buffer+=REALBPP/8; -+ /* read run length */ -+ length=1; -+ while(*buffer==0xff) { -+ if(buffer+1>=buffer_end) -+ return -8; -+ length+=*buffer; -+ buffer++; ++ }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+1))*s; ++ s -= 2; ++ ofs = (4<>1; ++ } ++ if( r & 0x02 ){ ++ pH += (s>>1)*width; ++ } ++ for( y=0; y0) { -+# if 0 -+ ((CARDBPP*)frameBuffer)[(y+j)*si.framebufferWidth+x+i] = color; -+ /* alt */ -+ CopyDataToScreen((char *)&color, x+i, y+j, 1, 1); -+# else -+ ((CARDBPP*)frameBuffer)[m0++] = color; -+# endif -+ length--; -+ i++; -+ if(i>=w) { -+ i=0; -+ j++; -+ } ++ if( ((signed char*)pH)[1] & 0x80 ){ ++ ((signed char*)pH)[1] += ~((signed char*)pM)[1]; + } -+ if(length>0) -+ fprintf(stderr, "Warning: possible ZRLE corruption\n"); ++ if( ((signed char*)pH)[2] & 0x80 ){ ++ ((signed char*)pH)[2] += ~((signed char*)pM)[2]; ++ } ++ *pH &= *pM; ++ pH += s; + } -+ CopyDataToScreen((char *)frameBuffer, x, y, w, h); -+if (0) fprintf(stderr, "cha4: %dx%d+%d+%d\n", w, h, x, y); ++ 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<>1; ++ } ++ if( r & 0x02 ){ ++ pH += (s>>1)*width; ++ } ++ for( y=0; y=0; l-- ){ ++ pTop = pBuf; ++ pEnd = pBuf+width; ++ s = 1<buffer_length) -+ return -9; ++// 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; \ ++} + -+ /* read palette */ -+ for(i=0; i=buffer_end) -+ return -10; -+ color = palette[(*buffer)&0x7f]; -+ length=1; -+ if(*buffer&0x80) { -+ if(buffer+1>=buffer_end) -+ return -11; -+ buffer++; -+ /* read run length */ -+ while(*buffer==0xff) { -+ if(buffer+1>=buffer_end) -+ return -8; -+ length+=*buffer; -+ buffer++; -+ } -+ length+=*buffer; -+ } -+ buffer++; -+ while(j0) { -+# if 0 -+ ((CARDBPP*)frameBuffer)[(y+j)*si.framebufferWidth+x+i] = color; -+ /* alt */ -+ CopyDataToScreen((char *)&color, x+i, y+j, 1, 1); -+# else -+ ((CARDBPP*)frameBuffer)[m0++] = color; -+# endif -+ length--; -+ i++; -+ if(i>=w) { -+ i=0; -+ j++; -+ } -+ } -+ if(length>0) -+ fprintf(stderr, "Warning: possible ZRLE corruption\n"); -+ } -+ CopyDataToScreen((char *)frameBuffer, x, y, w, h); -+if (0) fprintf(stderr, "cha5: %dx%d+%d+%d\n", w, h, x, y); ++// 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); \ ++} + -+ break; -+ } ++// 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<>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; \ + } + -+ return buffer-buffer_copy; ++#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<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 1server messages. + */ +@@ -1241,4 +1329,9 @@ + rfbFileDownloadCancelMsg fdc; + rfbFileUploadFailedMsg fuf; + rfbFileCreateDirRequestMsg fcdr; ++ rfbSetScaleMsg ssc; ++ rfbPalmVNCSetScaleFactorMsg pssf; ++ rfbSetServerInputMsg sim; ++ rfbSetSWMsg sw; ++ rfbTextChatMsg tc; + } rfbClientToServerMsg;