Home | History | Annotate | Download | only in x11vnc
      1 #!/bin/sh
      2 # the next line restarts using wish. \
      3 exec wish "$0" "$@"
      4 catch {rename send {}}
      5 #
      6 # Copyright (C) 2004-2009 Karl J. Runge <runge (at] karlrunge.com>
      7 # All rights reserved.
      8 #
      9 #  This is free software; you can redistribute it and/or modify
     10 #  it under the terms of the GNU General Public License as published by
     11 #  the Free Software Foundation; either version 2 of the License, or
     12 #  (at your option) any later version.
     13 #
     14 #  This software is distributed in the hope that it will be useful,
     15 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
     16 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     17 #  GNU General Public License for more details.
     18 #
     19 #  You should have received a copy of the GNU General Public License
     20 #  along with this software; if not, write to the Free Software
     21 #  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
     22 #  USA.
     23 
     24 #
     25 # tkx11vnc v0.2
     26 # This is a simple frontend to x11vnc.  It uses the remote control
     27 # and query features (-remote/-query aka -R/-Q) to interact with it. 
     28 # It is just a quick-n-dirty hack (it parses -help output, etc), but
     29 # it could be of use playing with or learning about the (way too) many
     30 # parameters x11vnc has.
     31 # 
     32 # It can be used to interact with a running x11vnc (see the x11vnc
     33 # -gui option), or to set the parameters and then start up x11vnc.  
     34 # 
     35 
     36 #
     37 # Below is a simple picture of how the gui should be laid out and how
     38 # the menus should be organized.  Most menu items correspond to remote
     39 # control commands. A trailing ":" after the item name means it is a string
     40 # to be set rather than a boolean that can be toggled (e.g. the entry
     41 # box must be used).
     42 #
     43 # Some tweak options may be set in the prefix "=" string.
     44 #	A means it is an "Action" (not a true variable)
     45 #	R means it is an action only valid in remote mode.
     46 #	S means it is an action only valid in startup mode.
     47 #	Q means it is an action worth querying after running.
     48 #	P means the string can be +/- appended/deleted (string may not
     49 #         be the same after the remote command)
     50 #	G means gui internal item
     51 #	F means can be set via file browse
     52 #	D means for simple gui
     53 #	-C:val1,... means it will be a checkbox (radio button)
     54 #	   the "-" means no other options follow
     55 #	0 means to skip the item.
     56 #	-- means add a separator
     57 #
     58 #       The =GAL ... =GAL LOFF stuff is to provide submenus.
     59 #
     60 
     61 global env started time_count
     62 set started ""
     63 proc dtime {{msg ""}} {
     64 	global started time_count
     65 	if {$started == ""} {
     66 		return
     67 	}
     68 	set diff [expr "[exec gtod.bin] - $started"]
     69 	set diff [format "%.2f" $diff]
     70 	incr time_count
     71 	if {$msg == ""} {
     72 		set msg $time_count
     73 	}
     74 	puts -nonewline stderr "$msg $diff " 
     75 	puts stderr [clock format [clock seconds]]
     76 }
     77 
     78 if [info exists env(X11VNC_GUI_TIME)] {
     79 	global started time_count
     80 	set started [exec gtod.bin]
     81 	set time_count 0
     82 	dtime "S"
     83 }
     84 
     85 proc set_template {} {
     86 	global template
     87 	set template "
     88 Row: Actions   Clients   Permissions  Keyboard    Pointer  Help
     89 Row: Displays  Screen    Tuning       Debugging   Misc
     90 
     91 Actions
     92 	=SA start
     93 	=RA stop
     94 	--
     95 	=DSA attach
     96 	=DRA detach
     97 	--
     98 	=RA ping
     99 	=RA update-all
    100 	=GAL Settings::
    101 	=GA save-settings
    102 	=SFA load-settings:
    103 	=SA defaults-all
    104 	=0SA clear-all
    105 	--
    106 	=F rc:
    107 	norc
    108 	=GAL LOFF
    109 	-- D
    110 	=DRA stop+quit 
    111 	=DGA Quit 
    112 
    113 Help
    114 	=DGA gui
    115 	=DGA all
    116 
    117 Clients
    118 	=DRQA current:
    119 	=DF   connect:
    120 	=DRQA disconnect:
    121 	--
    122 	accept:
    123 	afteraccept:
    124 	gone:
    125 	vncconnect
    126 	zeroconf
    127 	-- D
    128 	tightfilexfer
    129 	ultrafilexfer
    130 	proxy:
    131 	=GAL Chat::
    132 	chatwindow
    133 	=DRA chaton
    134 	=DRA chatoff
    135 	=GAL LOFF
    136 	=GAL Java-applet::
    137 	=D http
    138 	httpdir:
    139 	httpport:
    140 	https:
    141 	httpsredir:
    142 	enablehttpproxy
    143 	=GAL LOFF
    144 
    145 Displays
    146 	=D display:
    147 	=F auth:
    148 	=S reflect:
    149 	=D desktop:
    150 	=D rfbport:
    151 	=S autoport:
    152 	=0 gui:
    153 
    154 Screen
    155 	=DRA refresh
    156 	=RA reset
    157 	=RA blacken
    158 	-- D
    159 	=D scale:
    160 	scale_cursor:
    161 	--
    162 	=D solid
    163 	solid_color:
    164 	--
    165 	=GAL OverlayVisuals::
    166 	overlay
    167 	overlay_nocursor
    168 	8to24
    169 	8to24_opts:
    170 	=GAL LOFF
    171 	=GAL 8-Bit-Color::
    172 	flashcmap
    173 	shiftcmap:
    174 	notruecolor
    175 	=GAL LOFF
    176 	=GAL SubWindow::
    177 	id:
    178 	sid:
    179 	=RA id_cmd:
    180 	=GAL LOFF
    181 	=GAL ResizeRotate::
    182 	= xrandr
    183 	=-C:resize,newfbsize,exit xrandr_mode:
    184 	rotate:
    185 	padgeom:
    186 	=GAL LOFF
    187 	=GAL Clipping::
    188 	=P blackout:
    189 	xinerama
    190 	clip:
    191 	=GAL LOFF
    192 	=GAL Misc-Screen::
    193 	fixscreen:
    194 	visual:
    195 	rawfb:
    196 	pipeinput:
    197 	uinput_accel:
    198 	uinput_reset:
    199 	uinput_always:
    200 	24to32
    201 	=GAL LOFF
    202 
    203 Keyboard
    204 	=D norepeat
    205 	=D add_keysyms
    206 	modtweak
    207 	xkb
    208 	--
    209 	capslock
    210 	skip_lockkeys
    211 	--
    212 	skip_keycodes:
    213 	skip_dups
    214 	sloppy_keys
    215 	--
    216 	=FP remap:
    217 	clear_mods
    218 	clear_keys
    219 	clear_all
    220 	=RA clear_locks
    221 
    222 Pointer
    223 	=D-C:none,arrow,X,some,most cursor:
    224 	=-C:1,2,3,4,5,6 arrow:
    225 	--
    226 	cursorpos
    227 	=D nocursorshape
    228 	--
    229 	noxfixes
    230 	cursor_drag
    231 	=GAL AlphaBlending::
    232 	noalphablend
    233 	alphacut:
    234 	alphafrac:
    235 	alpharemove
    236 	=GAL LOFF
    237 	--
    238 	buttonmap:
    239 	--
    240 	xwarppointer
    241 	always_inject
    242 
    243 Misc
    244 	=GD-C:full,icon,tray WindowView:
    245 	=GD simple-gui
    246 	-- D
    247 	=GA all-settings
    248 	=RA remote-cmd:
    249 	=GAL Selection::
    250 	=D nosel
    251 	noprimary
    252 	nosetprimary
    253 	noclipboard
    254 	nosetclipboard
    255 	seldir:
    256 	=GAL LOFF
    257 	=GAL X-ext::
    258 	xtrap
    259 	noxrecord
    260 	=RQA reset_record
    261 	=GAL LOFF
    262 	=GAL MacOSX::
    263 	macnosaver
    264 	macnowait
    265 	macwheel:
    266 	macnoswap
    267 	macnoresize
    268 	maciconanim:
    269 	macmenu
    270 	=GAL LOFF
    271 	--
    272 	6
    273 	noipv6
    274 	noipv4
    275 	--
    276 	nofb
    277 	=D nobell
    278 	nolookup
    279 	rfbversion:
    280 	bg
    281 	=S loop
    282 	=S loopbg
    283 	=S sleepin:
    284 	=-C:ignore,exit sigpipe:
    285 	=0 inetd
    286 
    287 Debugging
    288 	debug_pointer
    289 	debug_keyboard
    290 	=F logfile:
    291 	=GA show-logfile
    292 	=GA tail-logfile
    293 	quiet
    294 	--
    295 	=GA show-start-cmd
    296 	=DG debug_gui
    297 	=GAL Misc-Debug::
    298 	debug_xevents
    299 	debug_xdamage
    300 	=-C:0,1,2,3 debug_wireframe:
    301 	debug_scroll
    302 	debug_tiles
    303 	debug_grabs
    304 	debug_sel
    305 	debug_ncache
    306 	dbg
    307 	=GAL LOFF
    308 
    309 Permissions
    310 	=DRQA lock
    311 	=DRQA unlock
    312 	=D shared
    313 	=D forever
    314 	--
    315 	=DFP allow:
    316 	=D localhost
    317 	=RA allowonce:
    318 	listen:
    319 	-- D
    320 	=D viewonly
    321 	input:
    322 	--
    323 	=GAL Passwords::
    324 	passwd:
    325 	viewpasswd:
    326 	=F passwdfile:
    327 	=F rfbauth:
    328 	usepw
    329 	--
    330 	unixpw
    331 	unixpw_list:
    332 	unixpw_nis
    333 	unixpw_nis_list:
    334 	=0 storepasswd
    335 	=GAL LOFF
    336 	=GAL SSL::
    337 	ssl
    338 	=F ssl_pem:
    339 	stunnel
    340 	=F stunnel_pem:
    341 	=F ssldir:
    342 	=F sslverify:
    343 	ssltimeout:
    344 	--
    345 	enc:
    346 	=GAL LOFF
    347 	=GAL Misc-Perms::
    348 	safer
    349 	unsafe
    350 	=RA noremote
    351 	=0S alwaysshared
    352 	=0S nevershared
    353 	=0S dontdisconnect
    354 	=SQA deny_all
    355 	timeout:
    356 	grabkbd
    357 	grabptr
    358 	grabalways
    359 	grablocal:
    360 	forcedpms
    361 	clientdpms
    362 	noserverdpms
    363 	noultraext
    364 	=GAL LOFF
    365 
    366 Tuning
    367 	=D-C:0,1,2,3,4 pointer_mode:
    368 	input_skip:
    369 	allinput
    370 	=D nodragging
    371 	-- D
    372 	speeds:
    373 	=D wait:
    374 	defer:
    375 	=D nap
    376 	screen_blank:
    377 	--
    378 	=GAL WireFrame::
    379 	wireframe
    380 	wireframe_mode:
    381 	=-C:never,top,always wirecopyrect:
    382 	=GAL LOFF
    383 	=GAL ScrollCopyRect::
    384 	=-C:never,keys,mouse,always scrollcopyrect:
    385 	scr_area:
    386 	scr_skip:
    387 	scr_inc:
    388 	scr_keys:
    389 	scr_term:
    390 	scr_keyrepeat:
    391 	scr_parms:
    392 	=GAL LOFF
    393 	=GAL XDAMAGE::
    394 	xdamage
    395 	xd_area:
    396 	xd_mem:
    397 	=GAL LOFF
    398 	=GAL Ncache::
    399 	ncache
    400 	ncache_size:
    401 	ncache_cr
    402 	ncache_no_moveraise
    403 	ncache_no_dtchange
    404 	ncache_old_wm
    405 	ncache_no_rootpixmap
    406 	ncache_keep_anims
    407 	ncache_pad:
    408 	=RA ncache_reset_rootpixmap
    409 	=GAL LOFF
    410 	--
    411 	=GAL SharedMemory::
    412 	noshm
    413 	flipbyteorder
    414 	onetile
    415 	=GAL LOFF
    416 	=GAL Misc-Tuning::
    417 	progressive:
    418 	fs:
    419 	gaps:
    420 	grow:
    421 	fuzz:
    422 	extra_fbur:
    423 	wait_ui:
    424 	setdefer:
    425 	nowait_bog
    426 	slow_fb:
    427 	xrefresh:
    428 	readtimeout:
    429 	snapfb
    430 	threads
    431 	wmdt:
    432 	rfbwait:
    433 	nodpms
    434 	nofbpm
    435 	=GAL LOFF
    436 "
    437 }
    438 
    439 proc set_internal_help {} {
    440 	global helptext helpall
    441 
    442 	# set some internal item help here:
    443 	set helptext(start) "
    444 Launch x11vnc with the settings you have prescribed in the gui.
    445 The x11vnc process is started in an xterm window so you can see the
    446 output, kill it, etc.
    447 
    448 By viewing this help item, the command built so far will be displayed
    449 in the gui text area.  Have a look.  If you Press start it will be shown
    450 as well and you will be asked to confirm running it.
    451 
    452 If you want to use a saved profile \"rc file\" you can do \"Misc -> rc\" and
    453 select the file and simply start x11vnc using the rc file.  Alternatively,
    454 you could first use the \"Actions -> load-settings\" action to load in
    455 an \"rc file\" and then press \"Actions -> start\" to start up x11vnc
    456 based on those values.
    457 "
    458 	set helptext(stop) "
    459 The \"Actions -> stop\" action sends a signal to the running x11vnc
    460 server indicating it should shutdown all connections and exit.
    461 
    462 The GUI stays running in case you want to start a new x11vnc or attach
    463 to another one.  Use \"Actions -> Quit\" if you then want to have the
    464 gui exit. Use \"Actions -> stop+quit\" to have both exit at once.
    465 "
    466 
    467 	set helptext(show-start-cmd) "
    468 Displays in the text area what the x11vnc start command (i.e. the command
    469 run by \"Actions -> start\") looks like for the current values of the
    470 settings.  This can be done even in the attached state.  Intended for
    471 debugging the gui.  The help item for \"Actions -> start\" gives the
    472 same info.
    473 
    474 If you want to load in a saved profile \"rc file\" use \"Misc -> rc\"
    475 and select the file.  \"Actions -> load-settings\" does a similar thing
    476 with an rc-file, but reading the file and setting the gui variables to
    477 its values.
    478 "
    479 
    480 	set helptext(debug_gui) "
    481 Set debug_gui to get more output printed in the text area.
    482 "
    483 
    484 	set helptext(detach) "
    485 No longer be associated with the x11vnc server.  Switch to the
    486 non-connected state.  The x11vnc server keeps running: it does not exit.
    487 
    488 You can either later reattach to it \"Actions -> attach\", or start
    489 up a new x11vnc \"Actions -> start\", or exit \"Actions -> Quit\".
    490 "
    491 
    492 	set helptext(attach) "
    493 Attach to a running x11vnc server, if possible.  Switches to connected
    494 state if successful.  Usually the channel used to attach is via the X
    495 display (VNC_CONNECT rootwin property) being polled by the x11vnc server.
    496 To change or set the X display to use do \"Displays -> display\".
    497 
    498 Sometimes the \"-connect /path/to/filename\" is used as the communcation
    499 channel.  The running x11vnc has to know that \"/path/to/filename\"
    500 is the communication channel (i.e. it is using the same -connect option).
    501 "
    502 
    503 	set helptext(ping) "
    504 Check if x11vnc still responds to \"ping\" remote command.
    505 "
    506 
    507 	set helptext(update-all) "
    508 Query the x11vnc server for the current values of all variables.
    509 Populate the values into the gui's database.
    510 
    511 Normally the gui will refresh this info every time it interacts with
    512 the x11vnc server (including after a few minutes of inactivity), so one
    513 doesn't need to use this action very often (unless something else is
    514 changing the state of the x11vnc server, or new clients have connected,
    515 etc).
    516 "
    517 
    518 	set helptext(clear-all) "
    519 Forget any variable settings either entered in by you or set at the
    520 default.  Basically sets everything to 0 or the string (unset).
    521 
    522 This action is only available in \"startup\" mode, not when connected
    523 to a running x11vnc server (in that case the variable settings reflect
    524 the state of the running x11vnc).  To detach from a running x11vnc
    525 server use \"Actions -> detach\"; to completely stop the x11vnc server
    526 use \"Actions -> stop\".
    527 "
    528 
    529 	set helptext(defaults-all) "
    530 Reset all variable settings to the default values.  Basically sets
    531 everything to the default queries \"x11vnc -QD var\" retrieved at startup.
    532 
    533 This action is only available in \"startup\" mode, not when connected
    534 to a running x11vnc server (in that case the variable settings reflect
    535 the state of the running x11vnc).  To detach from a running x11vnc
    536 server use \"Actions -> detach\"; to completely stop the x11vnc server
    537 use \"Actions -> stop\".
    538 "
    539 
    540 	set helptext(load-settings) "
    541 Read in the \"rc file\" you prescribe in the dialog and then set the
    542 variables to those in the rc-file.  Any variables not mentioned in the
    543 rc-file are set to their default value.
    544 
    545 You could then do \"Actions -> start\" to start x11vnc with these
    546 parameters.  Or you could make some further changes to variables
    547 using the gui before starting x11vnc.
    548 
    549 This action is only available in \"startup\" mode, not when connected
    550 to a running x11vnc server (in that case the variable settings reflect
    551 the state of the running x11vnc).  To detach from a running x11vnc
    552 server use \"Actions -> detach\"; to completely stop the x11vnc server
    553 use \"Actions -> stop\".
    554 "
    555 
    556 	set helptext(save-settings) "
    557 Construct a ~/.x11vncrc file based on the current settings and
    558 offer to save it in a file (default ~/.x11vncrc).  If saved in a
    559 file other than the default, you can access the profile by using
    560 the \"-rc <filename>\" option when starting x11vnc.
    561 
    562 If an rc file entry begins with \"#d\" that means the current
    563 setting is at the Default value and so you probably want to leave
    564 it commented out with the \"#\" character.
    565 
    566 If an rc file entry begins with \"#?\" that means we think
    567 you probably do not really want to force the value to this setting.
    568 
    569 In either case, feel free to uncomment the line and/or change any
    570 of the parameter values in the file. 
    571 "
    572 
    573 	set helptext(all-settings) "
    574 Displays the gui's database of all of the x11vnc server's current
    575 settings.  Use \"Actions -> update-all\"  or \"Control+R\" to
    576 refresh this list if it ever gets out of sync.
    577 "
    578 
    579 	set helptext(remote-cmd) "
    580 Run a remote command (-R) or query (-Q) directly.  Only a few
    581 remote commands are not on a menu, but for those few you can
    582 run the command directly this way.  Just enter the command into
    583 the Entry box when prompted.  Use the prefix \"Q:\" to indicate
    584 a -Q query.  Examples: \"zero:20,20,100,100\", \"Q:ext_xfixes\"  
    585 "
    586 
    587 	set helptext(stop+quit) "
    588 Send the stop command to the x11vnc server, then terminate the tkx11vnc gui.
    589 "
    590 
    591 	set helptext(show-logfile) "
    592 View the current contents of the logfile (if it exists and is accessible
    593 by the gui process).
    594 "
    595 
    596 	set helptext(tail-logfile) "
    597 Run the tail(1) command with -f option on the logfile in an xterm.
    598 (if it exists and is accessible by the gui process).
    599 "
    600 
    601 	set helptext(Quit) "
    602 Terminate the tkx11vnc gui.  Any x11vnc server will be left running.
    603 "
    604 
    605 	set helptext(current) "
    606 Shows a menu of currently connected VNC clients on the x11vnc server.
    607 
    608 Allows you to find more information about them, change their input
    609 permissions, or disconnect them.
    610 
    611 Note that the File transfer permission only applies to UltraVNC
    612 file transfer, not TightVNC file transfer.
    613 
    614 You will be prompted to confirm any disconnections.
    615 "
    616 
    617 	set helptext(client) "
    618 After selecting a VNC client from the \"Clients -> current\" menu,
    619 you will be presented with a dialog that shows the information
    620 about the VNC client.
    621 
    622 You can choose to disconnect the client by clicking on the 
    623 \"Disconnect\" checkbox and pressing \"OK\".  There will be a
    624 confirmation dialog to doublecheck.
    625 
    626 Alternatively, you can fine tune the VNC client's input permissions
    627 by selecting any of the Keystrokes, Mouse-Motion, Button-Click,
    628 Clipboard-Input, or Files checkboxes and pressing \"OK\".  This is like
    629 the \"-input\" option but on a per-client basis.
    630 
    631 To not change any aspects of the VNC client press \"Cancel\".
    632 "
    633 
    634 	set helptext(solid_color) "
    635 Set the -solid color value.
    636 "
    637 
    638 	set helptext(xrandr_mode) "
    639 Set the -xrandr mode value.
    640 "
    641 
    642 	set helptext(unixpw_list) "
    643 Set the -unixpw usernames list value.
    644 "
    645 
    646 	set helptext(unixpw_nis_list) "
    647 Set the -unixpw_nis usernames list value.
    648 "
    649 
    650 	set helptext(stunnel_pem) "
    651 Set the -stunnel pem filename value.
    652 "
    653 
    654 	set helptext(ssl_pem) "
    655 Set the -ssl pem filename value.
    656 "
    657 
    658 	set helptext(wireframe_mode) "
    659 Set the -wireframe mode string value.
    660 "
    661 
    662 	set helptext(simple-gui) "
    663 Toggle between menu items corresponding the most basic ones
    664 and all possible settings.  I.e. toggle between a simple gui
    665 and one for power users.
    666 "
    667 
    668 	set helptext(Tray) "
    669 The tray/icon mode (started with \"x11vnc -gui tray ...\", etc.) presents
    670 a small icon that indicates the status of the running x11vnc server.
    671 
    672 Depending on your environment, this icon may be embedded in a system
    673 tray or applet dock, or simply be a standalone window.  \"-gui tray\"
    674 will attempt to embed the icon in the system tray, while \"-gui icon\"
    675 is for a standalone window.  Use \"-gui tray=setpass\" (or icon=setpass)
    676 to be prompted to set the session password at startup.
    677 
    678 When the icon has a light background, that means no VNC viewers are
    679 currently connected to the VNC display.
    680 
    681 When the icon has a dark background (i.e. reverse-video), that means at
    682 least one VNC viewer is connected to the VNC display.
    683 
    684 Moving the mouse pointer over the icon will popup a \"status balloon\"
    685 indicating the VNC display name and the names and info of any connected VNC
    686 viewers.  Press the middle mouse button if the balloon does not appear.
    687 
    688 Clicking the left or right mouse button on the icon displays a menu
    689 of actions:
    690 
    691     Properties      - Brings up the Properties dialog to set some basic
    692                       parameters.  The full tkx11vnc GUI may be accessed
    693                       via the \"Advanced ...\" button.  Press \"Help\"
    694                       in the Properties dialog for more info.
    695     
    696     Help            - Displays this help text.
    697     
    698     New Client      - Presents an entry box where you type in the name
    699                       of a computer that is running a VNC viewer in
    700                       \"listen\" mode (e.g. vncviewer -listen).  For a
    701                       non-standard listening port use \"host:port\".
    702 
    703                       Pressing \"OK\" will initiate the reverse
    704                       connection.  Use a blank hostname to skip it.
    705     
    706     Disconnect      - Shows a popup menu of connected clients.  Click on
    707                       one to disconnect it, or click on \"All Clients\"
    708                       disconnect all clients.
    709 
    710     Window View     - Switch between the \"full\" gui (also known as
    711                       \"Advanced\"), \"icon\" mode (small icon window with
    712                       popups), or \"tray\" mode (small icon embedded in the
    713                       system tray).  This is a shortcut for the action:
    714                       \"Properties -> Advanced -> Misc -> WindowView\".
    715     
    716     Stop x11vnc     - Directs the x11vnc server to disconnect all vncviewers
    717                       and then exit.  The tray/icon GUI then exits as well.
    718 
    719     Logfile         - Show the logfile if x11vnc is being run with one.
    720 
    721     Custom          - If you have a \$HOME/.x11vnc.gui file each uncommented
    722                       line in it becomes an additional menu item for this
    723                       menu.  The remote control command is run directly
    724                       via \"x11vnc -R <command>\", or if prefixed with 
    725                       \"action:\" runs a gui internal action, or if \"sep\"
    726                       adds a separator.  Set X11VNC_CUSTOM_GUI to use
    727                       a different filename.  Example file contents:
    728 
    729                              scale:3/4
    730                              scale:1
    731                              scale_cursor:1
    732                              sep
    733                              action:all-settings
    734                              #debug_keyboard
    735                              sep
    736                              action:Quit
    737 
    738 Termination:
    739 
    740 If the x11vnc server stops for any reason, the tray/icon gui will exit.
    741 
    742 If you delete the tray/icon (e.g. X out button), that is the same
    743 as the \"Stop x11vnc\" action in the menu. (This will disconnect any
    744 VNC viewer you are currently using to access the display since the
    745 x11vnc server is terminated).
    746 
    747 To terminate the tray/icon gui window but not the x11vnc server press
    748 Control-C on the tray/icon window.  You can also do this (and much
    749 more) via Properties -> Advanced -> Actions -> Quit
    750 "
    751 
    752 	set helptext(NewClient) "
    753     New Client      - Presents an entry box where you type in the name
    754                       of a computer that is running a VNC viewer in
    755                       \"listen\" mode (e.g. vncviewer -listen).  For a
    756                       non-standard listening port use \"host:port\".
    757 
    758                       Pressing \"OK\" will initiate the reverse
    759                       connection.  Use a blank hostname to skip it, or
    760                       delete (\"X-out\") the window.
    761     
    762 "
    763 
    764 	set helptext(Properties) "
    765 The Properties dialog allows you to set some basic parameters of a
    766 running x11vnc server.  After modifying them press \"OK\" or \"Apply\"
    767 to apply the changes, or press \"Cancel\" to skip applying them.
    768 
    769  Accept Connections:
    770 
    771    Toggles whether VNC viewers are allowed to connect or not.  It corresponds
    772    to the \"-R unlock\" and \"-R lock\" remote-control commands.
    773 
    774  Ask for Confirmation:
    775 
    776    Toggles whether a popup menu will be presented at the X display when
    777    a new VNC viewer attempts to connect.  The person sitting at the X
    778    display can choose to accept or reject the connection or accept the
    779    connection in ViewOnly mode.  It corresponds to the \"-R accept:popup\"
    780    and \"-R accept:\" remote-control commands.
    781    
    782  All Clients ViewOnly:
    783 
    784    Toggles whether the entire VNC desktop is view only.  All clients
    785    will only be able to watch when this is set (regardless of how they
    786    logged in).  It corresponds to the \"-R viewonly\" and \"-R noviewonly\"
    787    remote-control commands.
    788    
    789  Shared:
    790 
    791    Toggles whether multiple simultaneous viewer connections are allowed
    792    or not.  It corresponds to the \"-R shared\" and \"-R noshared\"
    793    remote-control commands.
    794 
    795  Advertise Service (Zeroconf):
    796 
    797    Toggles whether this VNC server should advertize itself via Zeroconf
    798    (also called Bonjour, mDNS, and avahi).  Then VNC viewers can then find
    799    this service on the local network.  It corresponds to the \"-R zeroconf\"
    800    and \"-R nozeroconf\" remote-control commands.
    801 
    802  Serve Java Viewer Applet:
    803 
    804    Toggles whether this VNC server should serve up a Java VNC Viewer
    805    applet via HTTP on http://hostname:5800/ (or port 5800+n for VNC
    806    port 5900+n).  A java enabled Web Browser can then connect to the
    807    desktopby VNC.  If SSL is active then the HTTPS URL https://hostname:5900/
    808    (etc.) will work as well.  This requires the x11vnc java viewer jar file
    809    (shared/x11vnc/classes) to be installed.  It corresponds to the
    810    \"-R http\" and \"-R nohttp\" remote commands.
    811 
    812  Solid Background Color:
    813 
    814    To improve VNC performance, if this option is set, then x11vnc will try
    815    to make the desktop background a solid color (which compresses extremely
    816    well compared to photo images, etc.)  It corresponds to the \"-R solid\"
    817    and \"-R nosolid\" remote commands.
    818 
    819  Password:
    820 
    821    Lets you set the session password viewers may use to gain full access
    822    to the display.  This will only work if x11vnc was started with the
    823    -gui icon or -gui tray mode.
    824    
    825  ViewOnly Password:
    826 
    827    Lets you set the session password viewers may use to gain view only
    828    access to the display.  This will only work if x11vnc was started with
    829    the -gui icon or -gui tray mode.
    830 
    831 
    832  NOTE: These \"session\" passwords only last for the current x11vnc
    833  session (they are not remembered, see the -storepasswd, -passwdfile,
    834  and -rfbauth x11vnc options for using stored passwords).
    835 
    836  If you set \"Password\" to the empty string that makes the \"ViewOnly
    837  Password\" empty as well and removes the need for any password to log in.
    838 
    839  If you set \"ViewOnly Password\" to the empty string that just removes
    840  the ViewOnly log in aspect: \"Password\" is still required to log in.
    841 
    842  - The \"Help\" button shows this help text.
    843    
    844  - The \"Advanced ...\" button replaces the Properties dialog with the full
    845    tkx11vnc GUI.  All dynamic settings can be modified in the full GUI.
    846 
    847 
    848 ==========================================================================
    849 
    850 Don't Lock Yourself Out:
    851 
    852    If you are sitting at the physical X display you cannot get into too
    853    much trouble setting the Properties dialog values.
    854 
    855    However IF you are using a VNC Viewer to REMOTELY access the X display
    856    some items in the Properties dialog can lock you out of further access:
    857 
    858       \"Accept Connections\"  if you disable this remotely, and
    859       accidentally disconnect your VNC viewer then you will not be
    860       able to reconnect.
    861    
    862       \"Ask for Confirmation\"  if you enable this only someone
    863       sitting at the X display can confirm any new VNC connections.
    864       Furthermore, any current VNC viewers will be blocked while
    865       waiting for the confirmation (times out in 120 sec by default). 
    866    
    867       \"All Clients ViewOnly\"  if you enable this remotely, well
    868       you can no longer provide input to disable it.
    869    
    870    If you do lock yourself out you could log in remotely and start up
    871    a second x11vnc and connect to that one to try to fix things in the
    872    first one.
    873 
    874    Note that if there are two or more x11vnc's on the same display the
    875    use of the GUI may be ill-behaved.  Terminate the second x11vnc as
    876    soon as you have fixed the setting in the first one.  Use of a remote
    877    control command, e.g. \"x11vnc -R noviewonly\" or \"x11vnc -R unlock\"
    878    is a good way to avoid this problem.
    879 "
    880 
    881 	set helptext(all) $helpall
    882 
    883 	set helptext(Misc-Tuning:) "
    884 x11vnc has what seems like hundreds of tuning parameters!  In this
    885 sub-menu we place some lesser used ones.  Most likely you'll want to
    886 leave them at their default values, but you can try them out quickly
    887 with the gui to see if they improve things.
    888 "
    889 
    890 	set helptext(Passwords:) "
    891 The items in this sub-menu pertain to setting passwords.  Note that x11vnc
    892 has two types of password files: RealVNC-style ones (you can create them
    893 with x11vnc -storepasswd or other VNC utility program) you use these
    894 via -rfbauth; and plain-text file passwords you use via -passwdfile.
    895 
    896 Normally passwords cannot be changed by remote-control (e.g. the gui),
    897 but for the case of the \"Icon\" and \"Tray\" modes this constraint has
    898 been relaxed.
    899 
    900 In neither the RealVNC-style nor the plain-text file cases should the
    901 password files be readable by users you do not want to access the VNC
    902 server.  Contrary to popular belief, the  RealVNC-style passwords are
    903 not encrypted, merely obscured.
    904 
    905 x11vnc has the even less secure -passwd and -viewpasswd supplied on
    906 the command line.  Be careful with these since they could be read by
    907 users with something like the ps(1) command.  On some operating systems
    908 x11vnc tries to quickly overwrite them on the command line but it doesn't
    909 work everywhere.
    910 
    911 Regarding ViewOnly passwords (where a VNC client using that password
    912 can only watch the screen, not interact with it), this is not available
    913 with -rfbauth, but only with -passwdfile, -passwd, and -viewpasswd.
    914 "
    915 
    916 	set helptext(SSL:) "
    917 In this sub-menu we provide the options related to SSL encrpytion
    918 and authentication.
    919 
    920 There is a built-in mode (-ssl) using the OpenSSL library, and a 2nd
    921 using the external stunnel program (-stunnel, that needs to be installed
    922 on the system).  Either may require or benefit from having PEM certificate
    923 files specified.
    924 
    925 "
    926 
    927 	set helptext(Misc-Perms:) "
    928 In this sub-menu we provide some lesser used permission options.
    929 
    930 Regarding -alwaysshared, -nevershared, and -dontdisconnect, you probably
    931 should never use them and just use x11vnc's -shared and -forever options
    932 instead (these give basically the same functionality and if you mixed
    933 them too much unexpected things may happen).
    934 "
    935 #'
    936 
    937 	set helptext(AlphaBlending:) "
    938 In this sub-menu we provide some tweak parameters for cursors (little
    939 icon at the mouse pointer) that have transparency (i.e. an Alpha channel
    940 in addition to Red, Green, and Blue RGB channels).  For these cursors,
    941 some of the graphics underneath the cursor is allowed to be blended in:
    942 e.g. a drop-shadow (a terrible effect IMNSHO).
    943 
    944 AlphaBlending for x11vnc is only available when the XFIXES X extension is
    945 present (since otherwise it cannot see the cursors at all and so applies
    946 heuristics to show some fake cursors).  AlphaBlending is only a problem
    947 with x11vnc when the cursors are not opaque.
    948 
    949 Opaque cursors (e.g. bitmap or simply colored cursor) are rendered
    950 correctly by x11vnc.  Only when there is transparency does x11vnc have
    951 to make some approximation to transform the cursor to be opaque (the
    952 VNC protocol does not provide for an alpha channel in cursors, only RGB).
    953 
    954 The items in this sub-menu let you tweak x11vnc's approximation scheme
    955 for cursors with transparency.  Hopefully you won't have to use them.
    956 Certain cursor \"themes\" may require adjustment however.
    957 "
    958 #'
    959 	set helptext(OverlayVisuals:) "
    960 In this sub-menu are some options that involve fixing color problems
    961 for \"Overlay\" or \"Multi-Depth\" visuals.  This problem is rare
    962 since overlay and multi-depth visual video hardware is rare. 
    963 Some Sun, SGI, and HP machines are known to have them.
    964 
    965 The short answer is if you have a multi-depth visual display (e.g.  8 and
    966 24 bits), and you see messed up colors in x11vnc try the \"-overlay\"
    967 option on Solaris or IRIX.
    968 
    969 A brief Background on pixels, color, and visuals:
    970 
    971    Pixels (picture elements) are kept in video memory as a certain number
    972    of bits-per-pixel (bpp).  Most common are 8bpp, 16bpp, and 32bpp.
    973    Less common are 24bpp, 4bpp, and 1bpp (monochrome).
    974 
    975    How pixel values (i.e. values of the bits) are rendered into colors on
    976    the screen can be done via different \"Recipes\".  These different
    977    recipes are referred to as \"visuals\".  E.g. for 8bpp there is
    978    a PseudoColor visual that maintains a mapping (that can be changed
    979    dynamically) of the pixel values (256 possible ones) into RGB values.
    980    Other 8bpp visuals, e.g. StaticGrey and TrueColor have fixed, regular
    981    mappings and so provide less variation in kinds of colors.
    982 
    983    A visual's \"depth\" is how many of the pixels are used in the
    984    actual recipe.  This may sound wasteful (i.e. not using some of the
    985    bits), but for 32bpp (4 billion colors) that is too much and nearly
    986    always only 24 for them are used.  The most common Visual seems to
    987    be depth 24 TrueColor at 32bpp.  This provides 16 million colors
    988    which is more than the number of pixels on most screens (1280x1024 =
    989    1.3 million pixels).  Another sometimes used visual that ignores some
    990    bits is depth 15 TrueColor at 16bpp.
    991 
    992 OK, now, finally, to the Overlay Visuals.  Some hardware (or software
    993 emulations) allow different depth visuals to be used on the display
    994 at the same time.  The pixels of windows using different depth visuals
    995 may overlap.
    996 
    997 The most common seems to be both 8 and 24 depth visuals on a 32bpp setup.
    998 24 of the pixels can be used for one visual and the remaining 8 for the
    999 other.  This is sometimes referred to as \"8+24\" mode.  Furthermore,
   1000 a speedup is achieved because writing graphics data to, say, the 8bit
   1001 visual does not destroy the image data in the 24bit visual.  Evidently
   1002 popup menus can be done very quickly this way: they use the 8bit visual
   1003 and when the popup goes away the graphics data in the 24bit visual is
   1004 immediately reexposed without having the application redraw it.
   1005 
   1006 Also, some legacy applications can only use 8bpp visuals.  But in these
   1007 days of high color graphics and web browsers one would like the rest
   1008 of the desktop to use depth 24 visuals.  They often work on the multi
   1009 depth visuals.
   1010 
   1011 How does this effect x11vnc?  x11vnc nearly always polls the root window
   1012 (container of all other windows).  The root window will be one depth,
   1013 e.g. 8 or 24.  Any windows using the *other* depth will appear to have
   1014 messed up colors (or just be black or some other solid color) when viewed
   1015 via x11vnc.
   1016 
   1017 How to fix?  Solaris and IRIX provide an API to extract the full snapshot
   1018 of the display with all the colors correct.  It comes to x11vnc as depth
   1019 24 TrueColor.  To enable this use the \"-overlay\" option.  Performance
   1020 may be slower, but if the colors are correct that is a big improvement.
   1021 "
   1022 
   1023 	set helptext(8-Bit-Color:) "
   1024 Some older displays (e.g. with limited Video RAM) use 8 bits-per-pixel
   1025 color.  This allows for only 256 different colors on the screen at the
   1026 same time.  This sometimes leads to problems with viewing these 8bpp
   1027 displays via x11vnc.  This sub-menu has some options that correspond to
   1028 workarounds for this case.  If you can configure the machine to use 16bpp
   1029 it may be worth it to avoid the color problems (e.g. color flashing
   1030 as the 8bit colormap is switched).
   1031 "
   1032 	set helptext(SubWindow:) "
   1033 This sub-menu has a couple options regarding having x11vnc poll a 
   1034 single window, not the entire display.  This way just the window
   1035 is shared.
   1036 
   1037 Note if the application pops up multiple windows they are not tracked
   1038 and shared.  So this is not application sharing.  The application has to
   1039 be very simple (e.g. a simple terminal or the image window on a webcam)
   1040 for this mode to be usable.
   1041 "
   1042 	set helptext(ResizeRotate:) "
   1043 This sub-menu has some options regarding screens that support the X
   1044 Resize, Reflection, and Rotation Extension (RANDR), and one expects screen
   1045 resizing, reflection, or rotation to take place during the x11vnc session.
   1046 This is pretty rare, but x11vnc seems to handle it reasonably well using
   1047 this X extension.
   1048 
   1049 This mode is on by default in -id mode to try to track the changing
   1050 size of the SubWindow.  It is not on by default for full-screen mode
   1051 because of the extra overhead, etc.
   1052 "
   1053 
   1054 	set helptext(WireFrame:) "
   1055 This sub-menu has some options for the x11vnc wireframing speedup scheme.
   1056 
   1057 For x11vnc, Wireframing means to watch for toplevel windows being Opaquely
   1058 Moved or Resized.  When x11vnc detects this, it stops polling the screen
   1059 and simply shows a \"wireframe\" outline of the window as it is being
   1060 moved or resized.  This avoids \"screen polling thrashing\" when the
   1061 screen is changing so rapidly during this period.  For various reasons
   1062 this is usually much faster then letting the window manager do its
   1063 own wireframing (you are encouraged to do Opaque moves and resizes
   1064 when using x11vnc!)
   1065 
   1066 Also, once a moved window is released in its new position, x11vnc uses
   1067 the VNC CopyRect encoding to very efficiently update the VNC viewers
   1068 (each just copies the image data locally).
   1069 
   1070 This sort of scheme was used much in the 1990's on local displays because
   1071 video hardware was slow at the time.  x11vnc tries to use this same trick
   1072 as a speedup for its activities (the network is much slower than video
   1073 hardware writes, and the video hardware reads that x11vnc uses to poll
   1074 the screen are still slow today).
   1075 "
   1076 #'"
   1077 
   1078 	set helptext(Safe:) "
   1079 In this sub-menu are some options for making x11vnc operations
   1080 more, or less, safe.  E.g. disable the running of external commands, etc.
   1081 
   1082 You can also turn off the Remote control channel (NOTE that doing that
   1083 will disable the GUI from being able to communicate with x11vnc).
   1084 "
   1085 
   1086 	set helptext(X-ext:) "
   1087 In this sub-menu are a few rarely used options regarding some X extensions
   1088 used by x11vnc.
   1089 "
   1090 	set helptext(Clipping:) "
   1091 In this sub-menu are some options regarding clipping or blacking out
   1092 portions of the Screen.  E.g. under XINERAMA when the multiple monitors
   1093 are not the same size.
   1094 
   1095 "
   1096 	set helptext(Misc-Screen:) "
   1097 In this sub-menu are some little used options modifying aspects of
   1098 the screen source.
   1099 "
   1100 
   1101 	set helptext(Settings:) "
   1102 In this sub-menu are some options for saving and loading option settings.
   1103 The default file to store settings in is ~/.x11vncrc, but you can save
   1104 different \"profiles\" in other files for later use.
   1105 
   1106 "
   1107 	set helptext(Java-applet:) "
   1108 In this sub-menu are some options for running the built-in HTTP server
   1109 that delivers the TightVNC Java VNC Viewer applet (VncViewer.jar) to
   1110 clients.  The viewer runs in their Web browser.
   1111 
   1112 The default port listened on is 5800, so the URL is typically:
   1113 
   1114 	http://hostname:5800/
   1115 
   1116 but this can be altered by -httpport, etc.
   1117 "
   1118 
   1119 	set helptext(Chat:) "
   1120 In this sub-menu are some options for enabling a local chat window
   1121 and starting or stopping the current chat.  This is the UltraVNC 
   1122 Text Chat support in x11vnc.
   1123 "
   1124 
   1125 	set helptext(ScrollCopyRect:) "
   1126 This sub-menu has some options for the x11vnc Scroll detection and
   1127 CopyRect speedup scheme.
   1128 
   1129 For this mode, x11vnc \"spies\" on communication between the X server and
   1130 applications using the RECORD extension.  It looks for various patterns
   1131 to detect a scrolled window.  This only works for some applications,
   1132 fortunately some important ones.
   1133 
   1134 Once the scroll is detected it uses the VNC CopyRect encoding for a
   1135 big speedup.  Screen polling is also sped up for this scheme.
   1136 
   1137 There are many tweakable parameters for this mode and they are described
   1138 in the sub-menu items.
   1139 "
   1140 
   1141 	set helptext(XDAMAGE:) "
   1142 The DAMAGE X extension allows the X server to send signals to x11vnc
   1143 telling it which regions of the screen have been changed.  This improves
   1144 x11vnc's performance markedly.  The DAMAGE extension must be available
   1145 on the display for this to work.
   1146 
   1147 Unfortunately DAMAGE cannot be trusted completely for the changed regions,
   1148 because often the reported changed region is much larger than the actual
   1149 changed regions.  Nevertheless, x11vnc uses the DAMAGE information very
   1150 effectively as hints to improve its performance.
   1151 
   1152 The items in the sub-menu allow tweaking x11vnc's DAMAGE algorithm.
   1153 "
   1154 
   1155 	set helptext(Ncache:) "
   1156 A simple client-side (viewer) caching scheme is enabled with the
   1157 \"-ncache n\" option.  It simply uses \"n\" framebuffer sized areas
   1158 below the actual display for caching window pixel data.  
   1159 
   1160 Drawbacks are it uses a lot of RAM (roughly n times more), and the
   1161 pixels cache area is visible in the viewers.
   1162 
   1163 The items in the sub-menu allow tweaking x11vnc's -ncache algorithm.
   1164 "
   1165 
   1166 	set helptext(SharedMemory:) "
   1167 This sub-menu provides some options regarding SYSV shared memory usage
   1168 (shm) by x11vnc.  Usually you want shm turned on because the x11vnc
   1169 process is nearly always running on the same machine the X server process
   1170 is running on.  SharedMemory gives a performance speedup.  However, if you
   1171 need to modify this scenario for special usage these options allow you to.
   1172 "
   1173 
   1174 	set helptext(Misc-Debug:) "
   1175 This sub-menu contains a lot of debugging parameters usually used
   1176 for debugging x11vnc itself.  This is unlike the -debug_pointer and
   1177 -debug_keyboard options that are useful in learning information, quirks,
   1178 etc. about your local display and environment.
   1179 "
   1180 
   1181 	set helptext(Selection:) "
   1182 This sub-menu contains some options centering around the Selection
   1183 (also referred to as the Clipboard, Cutbuffers, etc).  x11vnc will try
   1184 to exchange the selections between the VNC viewers and the X server.
   1185 You can adjust that behavior with these options.
   1186 "
   1187 
   1188 	set helptext(WindowView) "
   1189 Set the Window View Mode for the gui.  There are three modes:
   1190 
   1191   - full:  Presents the full gui (Actions, Clients, etc, buttons,
   1192            and the Text area and Set/Entry box).
   1193 
   1194   - icon:  Presents a small icon instead of the full gui.  Moving
   1195            the mouse over it shows the VNC display name and any
   1196            connected clients.  Clicking on the icon pops up a menu
   1197            of actions to perform.  Among them is \"Properties\" that
   1198            allows setting more parameters.  Clicking on \"Advanced\"
   1199            in \"Properties\" brings up the full gui.
   1200 
   1201   - tray:  Attempt to embed the small icon in the system tray.  If
   1202            this fails it will resort to icon mode where the small icon
   1203            is a standalone window.
   1204 
   1205 Note that in \"full\" mode if you delete the full gui window the gui
   1206 terminates (but the x11vnc server keeps running).  However under \"icon\"
   1207 or \"tray\" mode if you bring up the full gui window via \"Properties ->
   1208 Advanced\" and then delete it the gui does NOT terminate.
   1209 
   1210 Also note that by default in \"icon\" mode if you delete the icon
   1211 window both the gui *and* the x11vnc server terminate.
   1212 "
   1213 
   1214 	set helptext(gui) "
   1215 tkx11vnc is a simple frontend to x11vnc.  Nothing fancy, it merely
   1216 provides an interface to each of the many x11vnc command line options and
   1217 remote control commands.  See \"Help -> all\" for much info about x11vnc.
   1218 
   1219 For a simplier gui, run x11vnc in \"tray\" or \"icon\" mode such as
   1220 \"-gui tray\", \"-gui icon\", or \"-gui tray=setpass\".  In that
   1221 mode the full gui is only available under \"Advanced ...\".
   1222 
   1223 Also, \"-gui ez\" will show fewer menu items (toggle via Misc -> simple_gui)
   1224 
   1225 All menu items have a (?) button one can click on to get more information
   1226 about the option or command.
   1227 
   1228 There are two states tkx11vnc can be in:
   1229 
   1230 	1) Available to control a running x11vnc process.
   1231 
   1232 	2) Getting ready to start a x11vnc process.
   1233 
   1234 Most people will just use state 1).
   1235 
   1236 In state 1) the Menu items available in the menus are those that
   1237 correspond to the x11vnc \"remote control\" commands.  See the -remote
   1238 entry under \"Help -> all\" for a complete list.  Also available is
   1239 the \"Actions -> stop\" item to shut down the running x11vnc server,
   1240 thereby changing to state 2).  There are other actions available too.
   1241 
   1242 In state 2) the Menu items available in the menus (\"Actions\", \"Clients\",
   1243 etc.) are those that correspond to command line options used in starting
   1244 an x11vnc process, and the \"Actions -> start\" item executes
   1245 x11vnc thereby changing to state 1).  To see what x11vnc startup command
   1246 you have built so far, look at the (?) help for  \"Actions -> start\"
   1247 and it will show you what the command looks like.
   1248 
   1249 There is much overlap between the menu items available in state 1)
   1250 and state 2), but it is worth keeping in mind it is not 100%.
   1251 For example, you cannot set passwords or password files in state 1).
   1252 (update: simple password setting is now allowed in \"tray\" or \"icon\" mode).
   1253 
   1254 
   1255 Also note that there may be *two* separate X displays involved, not just
   1256 one:  1) the X display x11vnc will be polling (and making available to
   1257 VNC viewers), and 2) the X display this GUI is intended to display on.
   1258 
   1259 For example, one might use ssh to access the remote machine where the
   1260 GUI would display on :11 and x11vnc would poll display :0.  By default
   1261 the gui will display on the value in the DISPLAY env. variable followed
   1262 by the value from the -display option.  To override this, use something
   1263 like: \"-gui otherhost:0\", etc.
   1264 
   1265 
   1266 GUI components: 
   1267 --- ----------
   1268 
   1269 1) At the top of the gui is a info text label where information will
   1270    be posted, e.g. when traversing menu items text indicating how to get
   1271    help on the item and its current value will be displayed.
   1272 
   1273 2) Below the info label is the area where the menu buttons, \"Actions\",
   1274    \"Clients\", etc., are presented.  If a menu item has a checkbox,
   1275    it corresponds to a boolean on/off variable.  Otherwise it is
   1276    either a string variable, or an action not associated with a
   1277    variable (for the most part).
   1278 
   1279 3) Below the menu button area is a label indicating the current x11vnc
   1280    X display being polled and the corresponding VNC display name.  Both
   1281    will be \"(*none*)\" when there is no connection established.
   1282 
   1283 4) Below the x11 and vnc displays label is a text area there scrolling
   1284    information about actions being taken and commands being run is displayed.
   1285    To scroll click in the area and use PageUp/PageDown or the arrow keys.
   1286 
   1287 5) At the bottom is an entry area.  When one selects a menu item that
   1288    requires supplying a string value, the label will be set to the
   1289    parameter name and one types in the new value.  Then one presses the
   1290    \"OK\" button or presses \"Enter\" to set the value.  Or you can press
   1291    \"Cancel\" or \"Escape\" to avoid changing the variable.
   1292 
   1293    Many variables are boolean toggles (for example, \"Permissions ->
   1294    viewonly\") or Radio button selections.  Selecting these menu items
   1295    will NOT activate the entry area but rather toggle the variable
   1296    immediately.
   1297 
   1298 
   1299 CASCADES BUG: There is a bug not yet worked around for the cascade menus
   1300 where the (?) help button gets in the way.  To get the mouse over to
   1301 the cascade menu click and release mouse to activate the cascade, then
   1302 you can click on its items.  Dragging with a mouse button held down will
   1303 not work (sorry!).
   1304 
   1305 
   1306 Key Bindings:
   1307 
   1308 	In the Text Area: Control-/ selects all of the text.
   1309 	Anywhere: Control-d invokes \"Actions -> detach\"
   1310 	Anywhere: Control-a invokes \"Actions -> attach\"
   1311 	Anywhere: Control-p invokes \"Actions -> ping\"
   1312 	Anywhere: Control-u and Control-r invoke \"Actions -> update-all\"
   1313 "
   1314 
   1315 set under_wally "
   1316 Misc:
   1317 
   1318 Since x11vnc has so many settings and to avoid further confusion,
   1319 the libvncserver options:
   1320 
   1321 	-alwaysshared
   1322 	-nevershared
   1323 	-dontdisconnect
   1324 
   1325 are not available for changing in a running x11vnc (even though it
   1326 is feasible).  These options overlap with the x11vnc options -shared
   1327 and -forever which are hopefully enough for most usage.  They may be
   1328 specified for x11vnc startup if desired.
   1329 
   1330 "
   1331 
   1332 global beginner_mode
   1333 if {$beginner_mode} {
   1334 	set helptext(gui) "
   1335 tkx11vnc is a simple frontend to x11vnc.  It is currently running in
   1336 \"ez\" or \"simple\" mode.  For many more options run it in normal
   1337 mode by toggling \"Misc -> simple_gui\".
   1338 
   1339 All menu items have a (?) button one can click on to get more information
   1340 about the option or command.
   1341 
   1342 GUI components: 
   1343 --- ----------
   1344 
   1345 1) At the top of the gui is a info text label where information will
   1346    be posted, e.g. when traversing menu items text indicating how to get
   1347    help on the item and its current value will be displayed.
   1348 
   1349 2) Below the info label is the area where the menu buttons, \"Actions\",
   1350    \"Clients\", etc., are presented.  If a menu item has a checkbox,
   1351    it corresponds to a boolean on/off variable.  Otherwise it is
   1352    either a string variable, or an action not associated with a
   1353    variable (for the most part).
   1354 
   1355 3) Below the menu button area is a label indicating the current x11vnc
   1356    X display being polled and the corresponding VNC display name.  Both
   1357    will be \"(*none*)\" when there is no connection established.
   1358 
   1359 4) Below the x11 and vnc displays label is a text area there scrolling
   1360    information about actions being taken and commands being run is displayed.
   1361    To scroll click in the area and use PageUp/PageDown or the arrow keys.
   1362 
   1363 5) At the bottom is an entry area.  When one selects a menu item that
   1364    requires supplying a string value, the label will be set to the
   1365    parameter name and one types in the new value.  Then one presses the
   1366    \"OK\" button or presses \"Enter\" to set the value.  Or you can press
   1367    \"Cancel\" or \"Escape\" to avoid changing the variable.
   1368 
   1369    Many variables are boolean toggles (for example, \"Permissions ->
   1370    viewonly\") or Radio button selections.  Selecting these menu items
   1371    will NOT activate the entry area but rather toggle the variable
   1372    immediately.
   1373 
   1374 CASCADES BUG: There is a bug not yet worked around for the cascade menus
   1375 where the (?) help button gets in the way.  To get the mouse over to
   1376 the cascade menu click and release mouse to activate the cascade, then
   1377 you can click on its items.  Dragging with a mouse button held down will
   1378 not work (sorry!).
   1379 
   1380 "
   1381 }
   1382 
   1383 }
   1384 
   1385 proc center_win {w} {
   1386 	wm withdraw $w
   1387 	set x [expr [winfo screenwidth  $w]/2 - [winfo reqwidth  $w]/2];
   1388 	set y [expr [winfo screenheight $w]/2 - [winfo reqheight $w]/2];
   1389 	wm geometry $w +$x+$y
   1390 	wm deiconify $w
   1391 	update
   1392 }
   1393 
   1394 proc textwidth {text} {
   1395 	set min 0;
   1396 	foreach line [split $text "\n"] {
   1397 		set n [string length $line]
   1398 		if {$n > $min} {
   1399 			set min $n
   1400 		}
   1401 	}
   1402 	return $min
   1403 }
   1404 
   1405 proc textheight {text} {
   1406 	set count 0;
   1407 	foreach line [split $text "\n"] {
   1408 		incr count
   1409 	}
   1410 	return $count
   1411 }
   1412 
   1413 proc set_name {name} {
   1414 	global full_win icon_mode
   1415 	global saved_set_name
   1416 
   1417 	if {![info exists saved_set_name]} {
   1418 		set saved_set_name "tkx11vnc"
   1419 	}
   1420 	if {$name == "RESTORE"} {
   1421 		set name $saved_set_name
   1422 	} else {
   1423 		set saved_set_name $name
   1424 	}
   1425 	if {![info exists full_win]} {
   1426 		return
   1427 	}
   1428 	set w "."
   1429 	if {$icon_mode} {
   1430 		wm title    $w "$name"
   1431 		wm iconname $w "$name"
   1432 		set w $full_win
   1433 	}
   1434 	wm title    $w "$name"
   1435 	wm iconname $w "$name"
   1436 }
   1437 
   1438 proc make_toplevel {w {title ""}} {
   1439 	catch {destroy $w}
   1440 	toplevel  $w;
   1441 	bind $w <Escape> "destroy $w"
   1442 	if {$title != ""} {
   1443 		wm title    $w $title
   1444 		wm iconname $w $title
   1445 	}
   1446 }
   1447 
   1448 proc textwin {name title text {entry ""}} {
   1449 	global max_text_height max_text_width
   1450 	global bfont ffont
   1451 
   1452 	set width  [textwidth $text]
   1453 	incr width
   1454 	if {$width > $max_text_width} {
   1455 		set width $max_text_width
   1456 	}
   1457 	set height [textheight $text]
   1458 	if {$height > $max_text_height} {
   1459 		set height $max_text_height
   1460 	}
   1461 
   1462 	set w ".text_$name"
   1463 	make_toplevel $w $title
   1464 
   1465 	frame     $w.f -bd 0;
   1466 	pack      $w.f -fill both -expand 1
   1467 	text      $w.f.t -width $width -height $height -setgrid 1 -bd 2 \
   1468 			-yscrollcommand "$w.f.y set" -relief ridge \
   1469 			-font $ffont;
   1470 	scrollbar $w.f.y -orient v -relief sunken -command "$w.f.t yview";
   1471 	button    $w.f.b -text "Dismiss" -command "destroy $w" -font $bfont \
   1472 			-pady 2
   1473 
   1474 	$w.f.t insert 1.0 $text;
   1475 
   1476 	bind $w <Enter> "focus $w.f.t"
   1477 
   1478 	if {$entry != ""} {
   1479 		# varname+Label Name
   1480 		set list [split $entry "+"]
   1481 		set varname [lindex $list 0]
   1482 		set labname [lindex $list 1]
   1483 		frame $w.f.ef -bd 1 -relief groove
   1484 		label $w.f.ef.l -text "$labname" -anchor w -font $bfont
   1485 		entry $w.f.ef.e -relief sunken -font $ffont \
   1486 			-textvariable $varname
   1487 		button $w.f.ef.b -text "OK" -font $bfont \
   1488 			-command "set ${varname}_ok 1; destroy $w" 
   1489 		bind $w.f.ef.e <KeyPress-Return> "set ${varname}_ok 1; destroy $w"
   1490 		
   1491 		pack $w.f.ef.l -side left
   1492 		pack $w.f.ef.e -side left -fill x -expand 1
   1493 		pack $w.f.ef.b -side right
   1494 	}
   1495 
   1496 	wm withdraw $w
   1497 	pack $w.f.b -side bottom -fill x 
   1498 	if {$entry != ""} {
   1499 		pack $w.f.ef -side bottom -fill x 
   1500 		bind $w <Enter> "focus $w.f.ef.e"
   1501 		$w.f.ef.e icursor end
   1502 	} else {
   1503 		bind $w <Enter> "focus $w.f.t"
   1504 	}
   1505 	pack $w.f.y -side right -fill y;
   1506 	pack $w.f.t -side top -fill both -expand 1;
   1507 	update
   1508 
   1509 	center_win $w
   1510 
   1511 	return $w
   1512 }
   1513 
   1514 proc active_when_connected {item} {
   1515 	global helpremote helptext
   1516 	global icon_mode
   1517 
   1518 	if {$icon_mode} {
   1519 		if {$item == "passwd"} {
   1520 			return 1
   1521 		}
   1522 		if {$item == "viewpasswd"} {
   1523 			return 1
   1524 		}
   1525 	}
   1526 
   1527 	if {[opt_match G $item]} {
   1528 		return 1
   1529 	} elseif {[opt_match R $item]} {
   1530 		return 1
   1531 	} elseif {[opt_match S $item]} {
   1532 		return 0
   1533 	} elseif {[is_action $item]} {
   1534 		if {[opt_match R $item]} {
   1535 			return 1
   1536 		} else {
   1537 			return 0
   1538 		}
   1539 	} elseif {[info exists helpremote($item)]} {
   1540 		return 1
   1541 	} else {
   1542 		return 0
   1543 	}
   1544 }
   1545 
   1546 proc active_when_starting {item} {
   1547 	global helpremote helptext beginner_mode
   1548 
   1549 	if {$beginner_mode} {
   1550 		if {[opt_match G $item]} {
   1551 			return 1
   1552 		}
   1553 		if {$item == "display"} {
   1554 			return 1
   1555 		}
   1556 		if {$item == "attach"} {
   1557 			return 1
   1558 		}
   1559 		if {$item == "debug_gui"} {
   1560 			return 1
   1561 		}
   1562 		return 0
   1563 	}
   1564 
   1565 	if {[opt_match G $item]} {
   1566 		return 1
   1567 	} elseif {[opt_match S $item]} {
   1568 		return 1
   1569 	} elseif {[opt_match R $item]} {
   1570 		return 0
   1571 	} elseif {[is_action $item]} {
   1572 		if {[opt_match S $item]} {
   1573 			return 1
   1574 		} else {
   1575 			return 0
   1576 		}
   1577 	} elseif {[info exists helptext($item)]} {
   1578 		return 1
   1579 	} else {
   1580 		return 0
   1581 	}
   1582 }
   1583 
   1584 proc help_win {item} {
   1585 	global helptext helpremote menu_var
   1586 	global query_ans query_aro
   1587 	global beginner_mode
   1588 
   1589 	set ok 0
   1590 	set text "Help on $item:\n\n"
   1591 
   1592 	if {$item == "NewClient"} {
   1593 		;
   1594 	} elseif {[is_gui_internal $item]} {
   1595 		if {$item != "gui" && $item != "all" && $item != "Misc-Tuning:" \
   1596 		    && $item != "Properties" && $item != "Tray"} {
   1597 			append text "    + Is a gui internal Action (cannot be set).\n";
   1598 		}
   1599 	} elseif {[is_action $item]} {
   1600 		append text "    + Is a remote control Action (cannot be set).\n";
   1601 	} elseif {[active_when_connected $item]} {
   1602 		append text "    + Can be changed in a running x11vnc.\n";
   1603 	} else {
   1604 		append text "    - Cannot be changed in a running x11vnc.\n";
   1605 	}
   1606 	if {$item == "NewClient"} {
   1607 		;
   1608 	} elseif {[is_gui_internal $item]} {
   1609 		;
   1610 	} elseif {[active_when_starting $item]} {
   1611 		append text "    + Can be set at x11vnc startup.\n";
   1612 	} else {
   1613 		if {! $beginner_mode} {
   1614 			append text "    - Cannot be set at x11vnc startup.\n";
   1615 		}
   1616 	}
   1617 	append text "\n"
   1618 
   1619 	if {[info exists helptext($item)]} {
   1620 		append text "\n"
   1621 		if {[is_gui_internal $item]} {
   1622 			append text "==== x11vnc help: ====\n";
   1623 		} else {
   1624 			append text "==== x11vnc startup option help: ====\n";
   1625 		}
   1626 		append text "\n"
   1627 		append text $helptext($item)
   1628 		append text "\n"
   1629 		set ok 1
   1630 	}
   1631 
   1632 	if {[info exists helpremote($item)]} {
   1633 		append text "\n"
   1634 		append text "==== x11vnc remote control help: ====\n";
   1635 		append text "\n"
   1636 		append text $helpremote($item)
   1637 		set ok 1
   1638 	}
   1639 
   1640 	if {![is_action $item] && [info exists menu_var($item)]} {
   1641 		global unset_str
   1642 		append text "\n\n"
   1643 		append text "==== current $item value: ====\n";
   1644 		append text "\n"
   1645 
   1646 		if {$item == "passwd" || $item == "viewpasswd"} {
   1647 			;
   1648 		} elseif {$menu_var($item) == ""} {
   1649 			append text "$unset_str\n"
   1650 		} else {
   1651 			append text "$menu_var($item)\n"
   1652 		}
   1653 		if {$item == "http" || $item == "httpdir" || $item == "httpport"} {
   1654 			global vnc_url;
   1655 			append text "\nURL: $vnc_url\n"
   1656 		}
   1657 	}
   1658 
   1659 	if {$item == "start"} {
   1660 		set str [get_start_x11vnc_txt]
   1661 		append_text "$str\n"
   1662 #		append text "\nPossible \$HOME/.x11vncrc settings for this command:\n\n"
   1663 #		set rctxt [get_start_x11vnc_cmd 1]
   1664 #		append text "$rctxt\n"
   1665 	}
   1666 
   1667 	regsub -all { } $item " " name
   1668 
   1669 	if {$ok} {
   1670 		textwin $name "x11vnc help: $item" "$text";
   1671 	}
   1672 	return $ok
   1673 }
   1674 
   1675 proc parse_help {} {
   1676 	global env x11vnc_prog;
   1677 	global helpall helptext;
   1678 
   1679 	set helppipe [open "| $x11vnc_prog -help" "r"];
   1680 	if {$helppipe == ""} {
   1681 		puts stderr "failed to run $x11vnc_prog -help";
   1682 		exit 1;
   1683 	}
   1684 
   1685 	set sawopts 0;
   1686 	set curropt "";
   1687 	while {[gets $helppipe line] > -1} {
   1688 		append helpall "$line\n"	
   1689 
   1690 		# XXX
   1691 		if {[regexp {^Options:} $line]} {
   1692 			set sawopts 1;
   1693 			continue;
   1694 		}
   1695 		# XXX
   1696 		if {[regexp {^These options} $line]} {
   1697 			continue;
   1698 		}
   1699 		# tweak aliases:
   1700 		regsub {^-zeroconf} $line "-zero_conf" line
   1701 		regsub {^-avahi   } $line "-zeroconf" line
   1702 
   1703 		if {! $sawopts} {
   1704 			continue;
   1705 		}
   1706 		if {[regexp {^-([0-9A-z_][0-9A-z_]*)} $line match name]} {
   1707 			set allnames($name) 1;
   1708 			if {"$curropt" != "no$name" && "no$curropt" != "$name"} {
   1709 				set curropt $name;
   1710 				set helptext($curropt) "$line\n";
   1711 			} else {
   1712 				append helptext($curropt) "$line\n";
   1713 			}
   1714 		} elseif {$curropt != ""} {
   1715 			append helptext($curropt) "$line\n";
   1716 		}
   1717 	}
   1718 	foreach name [array names allnames] {
   1719 		if {[regexp {^no} $name]} {
   1720 			regsub {^no} $name "" pair
   1721 		} else {
   1722 			set pair "no$name"
   1723 		}
   1724 		if {[info exists helptext($name)]} {
   1725 			if ![info exists helptext($pair)] {
   1726 				set helptext($pair) $helptext($name);
   1727 			}
   1728 		} elseif {[info exists helptext($pair)]} {
   1729 			if ![info exists helptext($name)] {
   1730 				set helptext($name) $helptext($pair);
   1731 			}
   1732 		}
   1733 	}
   1734 
   1735 	set_internal_help
   1736 }
   1737 
   1738 proc tweak_both {new old} {
   1739 	tweak_help $new $old
   1740 	tweak_remote_help $new $old
   1741 }
   1742 
   1743 proc tweak_remote_help {new old} {
   1744 	global helpremote
   1745 	if ![info exists helpremote($new)] {
   1746 		if {[info exists helpremote($old)]} {
   1747 			set helpremote($new) $helpremote($old)
   1748 		}
   1749 	}
   1750 }
   1751 
   1752 proc tweak_help {new old} {
   1753 	global helptext
   1754 	if ![info exists helptext($new)] {
   1755 		if {[info exists helptext($old)]} {
   1756 			set helptext($new) $helptext($old)
   1757 		}
   1758 	}
   1759 }
   1760 
   1761 proc parse_remote_help {} {
   1762 	global helpremote helptext help_indent remote_name;
   1763 
   1764 	set sawopts 0;
   1765 	set curropt "";
   1766 	set possopts "";
   1767 	set offset [expr $help_indent - 1];
   1768 	foreach line [split $helptext(remote) "\n"] {
   1769 		
   1770 		set line [string range $line $offset end];
   1771 
   1772 		# XXX
   1773 		if {[regexp {^The following -remote/-R commands} $line]} {
   1774 			set sawopts 1;
   1775 			continue;
   1776 		}
   1777 		# XXX
   1778 		if {[regexp {^The vncconnect.*command} $line]} {
   1779 			set sawopts 0;
   1780 		}
   1781 
   1782 		if {! $sawopts} {
   1783 			continue;
   1784 		}
   1785 		if {[regexp {^([0-9A-z_][0-9A-z_:]*)} $line match name]} {
   1786 			regsub {:.*$} $name "" popt
   1787 			lappend possopts $popt
   1788 			if {"$curropt" != "no$name" && "no$curropt" != "$name"} {
   1789 				set curropt $name;
   1790 				regsub {:.*$} $curropt "" curropt
   1791 				set remote_name($curropt) $name
   1792 				set helpremote($curropt) "$line\n";
   1793 			} else {
   1794 				append helpremote($curropt) "$line\n";
   1795 			}
   1796 		} elseif {$curropt != ""} {
   1797 			append helpremote($curropt) "$line\n";
   1798 		}
   1799 	}
   1800 
   1801 	foreach popt $possopts {
   1802 		if {[info exists helpremote($popt)]} {
   1803 			continue
   1804 		}
   1805 		if {[regexp {^no} $popt]} {
   1806 			regsub {^no} $popt "" try
   1807 		} else {
   1808 			set try "no$popt"
   1809 		}
   1810 		if {[info exists helpremote($try)]} {
   1811 			set helpremote($popt) $helpremote($try)
   1812 		}
   1813 	}
   1814 }
   1815 
   1816 proc parse_query_help {} {
   1817 	global query_ans query_aro query_ans_list query_aro_list helptext;
   1818 
   1819 	set sawans 0;
   1820 	set sawaro 0;
   1821 	set ans_str ""
   1822 	set aro_str ""
   1823 
   1824 	foreach line [split $helptext(query) "\n"] {
   1825 
   1826 		if {! $sawans && [regexp {^ *ans=} $line]} {
   1827 			set sawans 1
   1828 		}
   1829 		if {! $sawans} {
   1830 			continue
   1831 		}
   1832 
   1833 		if {[regexp {^ *aro=} $line]} {
   1834 			set sawaro 1
   1835 		}
   1836 		if {$sawaro && [regexp {^[ 	]*$} $line]} {
   1837 			set sawans 0
   1838 			break
   1839 		}
   1840 
   1841 		regsub {ans=} $line "" line
   1842 		regsub {aro=} $line "" line
   1843 		set line [string trim $line]
   1844 
   1845 		if {$sawaro} {
   1846 			set aro_str "$aro_str $line"
   1847 		} else {
   1848 			set ans_str "$ans_str $line"
   1849 		}
   1850 	}
   1851 
   1852 	regsub -all {  *} $ans_str " " ans_str
   1853 	regsub -all {  *} $aro_str " " aro_str
   1854 
   1855 	set ans_str [string trim $ans_str]
   1856 	set aro_str [string trim $aro_str]
   1857 	set query_ans_list [split $ans_str]
   1858 	set query_aro_list [split $aro_str]
   1859 
   1860 	foreach item $query_ans_list {
   1861 		if {[regexp {^[ 	]*$} $item]} {
   1862 			continue
   1863 		}
   1864 		set query_ans($item) 1
   1865 	}
   1866 	foreach item $query_aro_list {
   1867 		if {[regexp {^[ 	]*$} $item]} {
   1868 			continue
   1869 		}
   1870 		set query_aro($item) 1
   1871 	}
   1872 }
   1873 
   1874 proc in_debug_mode {} {
   1875 	global menu_var
   1876 	if {![info exists menu_var(debug_gui)]} {
   1877 		return 0
   1878 	}
   1879 	return $menu_var(debug_gui)
   1880 }
   1881 
   1882 # Menubar utilities:
   1883 proc menus_state {state} {
   1884 	global menu_b
   1885 
   1886 	foreach case [array names menu_b] {
   1887 		set menu_button $menu_b($case)
   1888 		if {![winfo exists $menu_button]} {
   1889 			continue
   1890 		}
   1891 		$menu_button configure -state $state
   1892 	}
   1893 }
   1894 
   1895 proc menus_enable {} {
   1896 	global menus_disabled
   1897 
   1898 	menus_state "normal"
   1899 	set menus_disabled 0
   1900 }
   1901 
   1902 proc menus_disable {} {
   1903 	global menus_disabled
   1904 
   1905 	set menus_disabled 1
   1906 	menus_state "disabled"
   1907 }
   1908 
   1909 # Entry box utilities:
   1910 proc entry_state {x state} {
   1911 	global entry_box entry_label entry_ok entry_help entry_skip entry_browse
   1912 	global old_labels
   1913 	if {$x == "all"} {
   1914 		if {!$old_labels} {
   1915 			$entry_label configure -state $state
   1916 		}
   1917 		$entry_box    configure -state $state
   1918 		$entry_ok     configure -state $state
   1919 		$entry_skip   configure -state $state
   1920 		$entry_help   configure -state $state
   1921 		$entry_browse configure -state $state
   1922 	} elseif {$x == "label"} {
   1923 		if {!$old_labels} {
   1924 			$entry_label configure -state $state
   1925 		}
   1926 	} elseif {$x == "box"} {
   1927 		$entry_box    configure -state $state
   1928 	} elseif {$x == "ok"} {
   1929 		$entry_ok     configure -state $state
   1930 	} elseif {$x == "skip"} {
   1931 		$entry_skip   configure -state $state
   1932 	} elseif {$x == "help"} {
   1933 		$entry_help   configure -state $state
   1934 	} elseif {$x == "browse"} {
   1935 		$entry_browse configure -state $state
   1936 	}
   1937 }
   1938 
   1939 proc entry_enable {{x "all"}} {
   1940 	entry_state $x normal
   1941 }
   1942 
   1943 proc entry_disable {{x "all"}} {
   1944 	entry_state $x disabled
   1945 }
   1946 
   1947 proc entry_browse_button {{show 1}} {
   1948 	global entry_browse
   1949 	if {$show} {
   1950 		pack $entry_browse -side left
   1951 	}  else {
   1952 		pack forget $entry_browse
   1953 	}
   1954 }
   1955 proc entry_focus {} {
   1956 	global entry_box
   1957 	focus $entry_box
   1958 }
   1959 proc entry_select {} {
   1960 	global entry_box
   1961 	$entry_box selection range 0 end
   1962 }
   1963 proc entry_get {} {
   1964 	global entry_box
   1965 	return [$entry_box get]
   1966 }
   1967 proc entry_insert {str} {
   1968 	global entry_box
   1969 	entry_delete
   1970 	$entry_box insert end $str
   1971 	$entry_box icursor end
   1972 }
   1973 proc entry_delete {} {
   1974 	global entry_box
   1975 	$entry_box delete 0 end
   1976 }
   1977 
   1978 
   1979 # Utilities for remote control and updating vars.
   1980 
   1981 proc push_new_value {item name new {query 1}} {
   1982 	global menu_var always_update remote_output query_output
   1983 	global query_result_list
   1984 
   1985 	set debug [in_debug_mode]
   1986 
   1987 	set getout 0
   1988 	set print_getout 0;
   1989 
   1990 	set do_query_all 0
   1991 
   1992 	set newnew ""
   1993 	if {$item == "disconnect"} {
   1994 		set newnew "N/A"
   1995 		set do_query_all 1
   1996 	} elseif {$always_update} {
   1997 		set do_query_all 1
   1998 	}
   1999 
   2000 	if {$item == "remote-cmd"} {
   2001 		# kludge for arbitrary remote command:
   2002 		if {[regexp {^Q:} $new]} {
   2003 			# extra kludge for Q:var to mean -Q var
   2004 			regsub {^Q:} $new "" new
   2005 			set qonly 1
   2006 		} else {
   2007 			set qonly 0
   2008 		}
   2009 		# need to extract item from new:
   2010 		set qtmp $new
   2011 		regsub {:.*$} $qtmp "" qtmp
   2012 		if {$qonly} {
   2013 			set rargs [list "-Q" "$qtmp"]
   2014 			set print_getout 1
   2015 			set qargs ""
   2016 		} else {
   2017 			set rargs [list "-R" "$new"]
   2018 			set qargs ""
   2019 		}
   2020 		set getout 1
   2021 
   2022 	} elseif {[value_is_string $item]} {
   2023 		# string var:
   2024 		set rargs [list "-R" "$name:$new"]
   2025 		set qargs [list "-Q" "$name"]
   2026 	} else {
   2027 		# boolean var:
   2028 		set rargs [list "-R" "$name"]
   2029 		set qargs [list "-Q" "$name"]
   2030 	}
   2031 
   2032 	if {! $query && ! $always_update} {
   2033 		set getout 1
   2034 	} elseif {$item == "noremote"} {
   2035 		set getout 1
   2036 	} elseif {[is_action $item] && ![opt_match Q $item] && $rargs != ""} {
   2037 		set getout 1
   2038 	} elseif {[regexp {^(sid|id)$} $item] && ![regexp {^0x} $new]} {
   2039 		set getout 1
   2040 	}
   2041 
   2042 	set remote_output ""
   2043 	set query_output ""
   2044 
   2045 	if {!$debug} {
   2046 		if [regexp {passwd} $rargs] {
   2047 			append_text "x11vnc ..."
   2048 		} else {
   2049 			append_text "x11vnc $rargs ..."
   2050 		}
   2051 	}
   2052 
   2053 	if {$getout} {
   2054 		set remote_output [run_remote_cmd $rargs]
   2055 		if {$print_getout} {
   2056 			append_text "\t$remote_output"
   2057 		}
   2058 		append_text "\n"
   2059 		return
   2060 	}
   2061 
   2062 	if {$do_query_all} {
   2063 		set all [all_query_vars]
   2064 		set qargs [list "-Q" $all]
   2065 
   2066 		global last_query_all_time
   2067 		set last_query_all_time [clock seconds]
   2068 	}
   2069 
   2070 	set rqargs [concat $rargs $qargs]
   2071 
   2072 	set query [run_remote_cmd $rqargs]
   2073 	set query_output $query
   2074 
   2075 	set query_result_list ""
   2076 
   2077 	if {$newnew != ""} {
   2078 		set new $newnew
   2079 	}
   2080 
   2081 	if {![see_if_ok $query $item "$name:$new"]} {
   2082 		# failed
   2083 		if  {[regexp {^a..=} $query]} {
   2084 			# but some result came back
   2085 			# synchronize everything with a 2nd call.
   2086 			set query_output [query_all 1]
   2087 		} else {
   2088 			# server may be dead
   2089 			if {$item != "ping" && $item != "attach"} {
   2090 				try_connect
   2091 			}
   2092 		}
   2093 	} else {
   2094 		# succeeded
   2095 		# synchronize this variable (or variables)
   2096 		# for a speedup used the list parsed by see_if_ok.
   2097 		update_menu_vars "USE_LIST"
   2098 
   2099 		if {$do_query_all} {
   2100 			global all_settings
   2101 			set all_settings $query
   2102 		}
   2103 	}
   2104 }
   2105 
   2106 proc set_kmbc_str {} {
   2107 	global vl_bk vl_bm vl_bb vl_bc vl_bf vr_bk vr_bm vr_bb vr_bc vr_bf
   2108 
   2109 	set str ""
   2110 	if {$vl_bk} {
   2111 		append str "K"
   2112 	}
   2113 	if {$vl_bm} {
   2114 		append str "M"
   2115 	}
   2116 	if {$vl_bb} {
   2117 		append str "B"
   2118 	}
   2119 	if {$vl_bc} {
   2120 		append str "C"
   2121 	}
   2122 	if {$vl_bf} {
   2123 		append str "F"
   2124 	}
   2125 	if {$vr_bk || $vr_bm || $vr_bb || $vr_bc || $vr_bf} {
   2126 		append str ","
   2127 	}
   2128 	if {$vr_bk} {
   2129 		append str "K"
   2130 	}
   2131 	if {$vr_bm} {
   2132 		append str "M"
   2133 	}
   2134 	if {$vr_bb} {
   2135 		append str "B"
   2136 	}
   2137 	if {$vr_bc} {
   2138 		append str "C"
   2139 	}
   2140 	if {$vr_bf} {
   2141 		append str "F"
   2142 	}
   2143 	entry_insert $str
   2144 }
   2145 
   2146 proc insert_input_window {} {
   2147 	global text_area cleanup_window
   2148 	global ffont menu_var
   2149 	global vl_bk vl_bm vl_bb vl_bc vl_bf vr_bk vr_bm vr_bb vr_bc vr_bf
   2150 
   2151 	append_text "\nUse these checkboxes to set the input permissions, "
   2152 	append_text "or type in the \"KMBCF...\"\n"
   2153 	append_text "-input string manually.  Then press \"OK\" or \"Cancel\".\n"
   2154 	append_text "(note: an empty setting means use the default behavior, "
   2155 	append_text "see viewonly)\n\n"
   2156 	set w "$text_area.wk_f"
   2157 	catch {destroy $w}
   2158 	frame $w -bd 1 -relief ridge -cursor {top_left_arrow}
   2159 	set fl $w.fl
   2160 	frame $fl
   2161 	set fr $w.fr
   2162 	frame $fr
   2163 	label $fl.l -font $ffont -text "Normal clients:   "
   2164 	checkbutton $fl.bk -pady 1 -font $ffont -anchor w -variable vl_bk \
   2165 		-pady 1 -command set_kmbc_str -text "Keystrokes" 
   2166 	checkbutton $fl.bm -font $ffont -anchor w -variable vl_bm \
   2167 		-pady 1 -command set_kmbc_str -text "Mouse-Motion" 
   2168 	checkbutton $fl.bb -font $ffont -anchor w -variable vl_bb \
   2169 		-pady 1 -command set_kmbc_str -text "Button-Click"
   2170 	checkbutton $fl.bc -font $ffont -anchor w -variable vl_bc \
   2171 		-pady 1 -command set_kmbc_str -text "Clipboard-Input"
   2172 	checkbutton $fl.bf -font $ffont -anchor w -variable vl_bf \
   2173 		-pady 1 -command set_kmbc_str -text "Files"
   2174 	label $fr.l -pady 1 -font $ffont -text "View-Only clients:"
   2175 	checkbutton $fr.bk -font $ffont -anchor w -variable vr_bk \
   2176 		-pady 1 -command set_kmbc_str -text "Keystrokes" 
   2177 	checkbutton $fr.bm -font $ffont -anchor w -variable vr_bm \
   2178 		-pady 1 -command set_kmbc_str -text "Mouse-Motion" 
   2179 	checkbutton $fr.bb -font $ffont -anchor w -variable vr_bb \
   2180 		-pady 1 -command set_kmbc_str -text "Button-Click"
   2181 	checkbutton $fr.bc -font $ffont -anchor w -variable vr_bc \
   2182 		-pady 1 -command set_kmbc_str -text "Clipboard-Input"
   2183 	checkbutton $fr.bf -font $ffont -anchor w -variable vr_bf \
   2184 		-pady 1 -command set_kmbc_str -text "Files"
   2185 
   2186 	if {[info exists menu_var(input)]} {
   2187 		set input_str $menu_var(input)
   2188 	} else {
   2189 		set input_str ""
   2190 	}
   2191 
   2192 	if {[regexp {(.*),(.*)} $input_str match normal viewonly]} {
   2193 		;
   2194 	} else {
   2195 		set normal $input_str
   2196 		set viewonly ""
   2197 	}
   2198 	set vl_bk 0
   2199 	set vl_bm 0
   2200 	set vl_bb 0
   2201 	set vl_bc 0
   2202 	set vl_bf 0
   2203 
   2204 	set vr_bk 0
   2205 	set vr_bm 0
   2206 	set vr_bb 0
   2207 	set vr_bc 0
   2208 	set vr_bf 0
   2209 
   2210 	if {[regexp -nocase {K} $normal]} {
   2211 		set vl_bk 1
   2212 	}
   2213 	if {[regexp -nocase {M} $normal]} {
   2214 		set vl_bm 1
   2215 	}
   2216 	if {[regexp -nocase {B} $normal]} {
   2217 		set vl_bb 1
   2218 	}
   2219 	if {[regexp -nocase {C} $normal]} {
   2220 		set vl_bc 1
   2221 	}
   2222 	if {[regexp -nocase {F} $normal]} {
   2223 		set vl_bf 1
   2224 	}
   2225 	if {[regexp -nocase {K} $viewonly]} {
   2226 		set vr_bk 1
   2227 	}
   2228 	if {[regexp -nocase {M} $viewonly]} {
   2229 		set vr_bm 1
   2230 	}
   2231 	if {[regexp -nocase {B} $viewonly]} {
   2232 		set vr_bb 1
   2233 	}
   2234 	if {[regexp -nocase {C} $viewonly]} {
   2235 		set vr_bc 1
   2236 	}
   2237 	if {[regexp -nocase {F} $viewonly]} {
   2238 		set vr_bf 1
   2239 	}
   2240 
   2241 	pack $fl.l $fl.bk $fl.bm $fl.bb $fl.bc $fl.bf -side top -fill x
   2242 	pack $fr.l $fr.bk $fr.bm $fr.bb $fr.bc $fr.bf -side top -fill x
   2243 	pack $fl $fr -side left
   2244 	update
   2245 	update idletasks
   2246 	$text_area window create end -window $w
   2247 	$text_area see end
   2248 	$text_area insert end "\n"
   2249 #	$text_area insert end "\n\n\n\n\n\n\n\n\n"
   2250 
   2251 	set cleanup_window $w
   2252 }
   2253 
   2254 proc set_ca_str {w} {
   2255 	global ca_bk ca_bm ca_bb ca_bc ca_bf ca_di
   2256 
   2257 	if {$ca_di} {
   2258 		entry_insert "disconnect"
   2259 		$w.bk configure -state disabled
   2260 		$w.bm configure -state disabled
   2261 		$w.bb configure -state disabled
   2262 		$w.bc configure -state disabled
   2263 		$w.bf configure -state disabled
   2264 		return
   2265 	}
   2266 
   2267 	$w.bk configure -state normal
   2268 	$w.bm configure -state normal
   2269 	$w.bb configure -state normal
   2270 	$w.bc configure -state normal
   2271 	$w.bf configure -state normal
   2272 
   2273 	set str ""
   2274 	if {$ca_bk} {
   2275 		append str "K"
   2276 	}
   2277 	if {$ca_bm} {
   2278 		append str "M"
   2279 	}
   2280 	if {$ca_bb} {
   2281 		append str "B"
   2282 	}
   2283 	if {$ca_bc} {
   2284 		append str "C"
   2285 	}
   2286 	if {$ca_bf} {
   2287 		append str "F"
   2288 	}
   2289 	entry_insert $str
   2290 }
   2291 
   2292 proc insert_client_action_window {input} {
   2293 	global text_area cleanup_window
   2294 	global ffont menu_var
   2295 	global ca_bk ca_bm ca_bb ca_bc ca_bf ca_di
   2296 
   2297 	append_text "\nUse these checkboxes to set the input permissions "
   2298 	append_text "for this client\n-OR- whether to disconnect it instead.  "
   2299 	append_text "Then press \"OK\" or \"Cancel\".\n\n"
   2300 	set w "$text_area.ca_f"
   2301 	catch {destroy $w}
   2302 	frame $w -bd 1 -relief ridge -cursor {top_left_arrow}
   2303 	checkbutton $w.di -pady 1 -font $ffont -anchor w -variable ca_di \
   2304 		-pady 1 -command "set_ca_str $w" -text "Disconnect  " 
   2305 	checkbutton $w.bk -font $ffont -anchor w -variable ca_bk \
   2306 		-pady 1 -command "set_ca_str $w" -text "Keystrokes" 
   2307 	checkbutton $w.bm -font $ffont -anchor w -variable ca_bm \
   2308 		-pady 1 -command "set_ca_str $w" -text "Mouse-Motion" 
   2309 	checkbutton $w.bb -font $ffont -anchor w -variable ca_bb \
   2310 		-pady 1 -command "set_ca_str $w" -text "Button-Click"
   2311 	checkbutton $w.bc -font $ffont -anchor w -variable ca_bc \
   2312 		-pady 1 -command "set_ca_str $w" -text "Clipboard"
   2313 	checkbutton $w.bf -font $ffont -anchor w -variable ca_bf \
   2314 		-pady 1 -command "set_ca_str $w" -text "Files"
   2315 
   2316 	set ca_di 0
   2317 	set ca_bk 0
   2318 	set ca_bm 0
   2319 	set ca_bb 0
   2320 	set ca_bf 0
   2321 	set ca_bc 0
   2322 
   2323 	if {[regexp -nocase {K} $input]} {
   2324 		set ca_bk 1
   2325 	}
   2326 	if {[regexp -nocase {M} $input]} {
   2327 		set ca_bm 1
   2328 	}
   2329 	if {[regexp -nocase {B} $input]} {
   2330 		set ca_bb 1
   2331 	}
   2332 	if {[regexp -nocase {C} $input]} {
   2333 		set ca_bc 1
   2334 	}
   2335 	if {[regexp -nocase {F} $input]} {
   2336 		set ca_bf 1
   2337 	}
   2338 
   2339 	pack $w.di $w.bk $w.bm $w.bb $w.bc $w.bf -side left
   2340 	update
   2341 	update idletasks
   2342 	$text_area window create end -window $w
   2343 	$text_area see end
   2344 	$text_area insert end "\n"
   2345 
   2346 	set cleanup_window $w
   2347 }
   2348 
   2349 proc cleanup_text_window {} {
   2350 	global cleanup_window
   2351 	if {[info exists cleanup_window]} {
   2352 		catch {destroy $cleanup_window}
   2353 	}
   2354 }
   2355 
   2356 # For updating a string variable.   Also used for simple OK/Cancel dialogs
   2357 # with entry = 0.
   2358 proc entry_dialog {item {entry 1}} {
   2359 	global menu_var entry_str entry_set entry_dialog_item
   2360 	global unset_str connected_to_x11vnc entry_box
   2361 
   2362 	set entry_str "Set $item"
   2363 	set entry_set 0
   2364 	set entry_dialog_item $item
   2365 
   2366 	entry_enable
   2367 	menus_disable
   2368 
   2369 	if {$item == "passwd" || $item == "viewpasswd"} {
   2370 		$entry_box configure -show "*"
   2371 	}
   2372 
   2373 	if {$entry} {
   2374 		entry_insert ""
   2375 		if {[info exists menu_var($item)] &&
   2376 		    $menu_var($item) != $unset_str} {
   2377 			entry_insert $menu_var($item)
   2378 			entry_select
   2379 		}
   2380 
   2381 		if {[is_browse $item]} {
   2382 			entry_browse_button
   2383 		}
   2384 		set_info "Set parameter in entry box, "
   2385 		entry_focus
   2386 	} else {
   2387 		entry_disable box
   2388 	}
   2389 
   2390 	set clean_text_window 0;
   2391 
   2392 	if {$item == "input"} {
   2393 		insert_input_window
   2394 		set clean_text_window 1
   2395 	}
   2396 
   2397 	update
   2398 
   2399 	# wait for user reply:
   2400 	vwait entry_set
   2401 
   2402 	set rc $entry_set
   2403 	set entry_set 0
   2404 
   2405 	set value [entry_get]
   2406 	update
   2407 
   2408 	entry_browse_button 0
   2409 	set entry_str "Set... :"
   2410 
   2411 	entry_delete
   2412 	entry_disable
   2413 	menus_enable
   2414 
   2415 	if {$clean_text_window} {
   2416 		cleanup_text_window;
   2417 	}
   2418 
   2419 	update
   2420 
   2421 	if {! $entry} {
   2422 		;
   2423 	} elseif {$rc} {
   2424 		set menu_var($item) $value
   2425 	} else {
   2426 		if {[in_debug_mode]} {
   2427 			append_text "skipped setting $item\n"
   2428 		}
   2429 	}
   2430 
   2431 	$entry_box configure -show ""
   2432 
   2433 	return $rc
   2434 }
   2435 
   2436 proc warning_dialog {msg {item "gui"} } {
   2437 	append_text $msg
   2438 	# just reuse the entry widgets for a yes/no dialog
   2439 	return [entry_dialog $item 0]
   2440 }
   2441 
   2442 # For updating a boolean toggle:
   2443 proc check_var {item} {
   2444 	global menu_var
   2445 
   2446 	set inval $menu_var($item);
   2447 
   2448 	if {$item == "debug_gui"} {
   2449 		return "";
   2450 	}
   2451 
   2452 	set rname $item
   2453 	if {! $inval} {
   2454 		if {[regexp {^no} $item]} {
   2455 			regsub {^no} $rname "" rname
   2456 		} else {
   2457 			set rname "no$rname"
   2458 		}
   2459 	}
   2460 	return $rname
   2461 }
   2462 
   2463 proc see_if_ok {query item expected} {
   2464 	global query_result_list
   2465 
   2466 	set ok 0
   2467 	set found ""
   2468 
   2469 	set query_result_list [split_query $query]
   2470 
   2471 	foreach q $query_result_list {
   2472 		# XXX following will crash if $item is not a good regexp
   2473 		# need to protect it \Q$item\E style...
   2474 #		if {[regexp "^$item:" $q]} {
   2475 #			set found $q
   2476 #		}
   2477 		if {[string first "$item:" $q] == 0} {
   2478 			set found $q
   2479 		}
   2480 		if {$q == $expected} {
   2481 			set ok 1
   2482 			if {$found != ""} {
   2483 				break;
   2484 			}
   2485 		}
   2486 	}
   2487 	if {$found == ""} {
   2488 		set msg $query
   2489 		regsub {^a..=} $msg {} msg
   2490 		if {[string length $msg] > 60} {
   2491 			set msg [string range $msg 0 60]
   2492 		}
   2493 	} else {
   2494 		set msg $found
   2495 	}
   2496 	if {!$ok && $found != ""} {
   2497 		# check for floating point match:
   2498 		set v1 ""
   2499 		set v2 ""
   2500 		regexp {:([0-9.][0-9.]*)$} $found m0 v1
   2501 		regexp {:([0-9.][0-9.]*)$} $expected m0 v2
   2502 		if {$v1 != "" && $v2 != ""} {
   2503 			set diff ""
   2504 			catch {set diff [expr "$v1 - $v2"]}
   2505 			if {$diff != ""} {
   2506 				if {$diff < 0} {
   2507 					set diff [expr "0.0 - $diff"]
   2508 				}
   2509 				if {$diff < 0.00001} {
   2510 					set ok 1
   2511 				}
   2512 			}
   2513 		}
   2514 	}
   2515 	if {$ok} {
   2516 		append_text "\tSet OK  ($msg)\n"
   2517 		return 1
   2518 
   2519 	} elseif {[opt_match P $item] && [regexp {:(-|\+)} $expected]} {
   2520 		# e.g. blackout:+30x30+20+20
   2521 		append_text "\t($msg)\n"
   2522 		return 1
   2523 	} elseif {[regexp {:[0-9]\.[0-9]} $expected]} {
   2524 		append_text "\t($msg)\n"
   2525 		return 1
   2526 	} elseif {$item == "connect" || $item == "disconnect"
   2527 	    || $item == "client" || $item == "client_input"} {
   2528 		append_text "\t($msg)\n"
   2529 		return 1
   2530 	} elseif {$item == "passwd" || $item == "viewpasswd"} {
   2531 		append_text "\t($msg)\n"
   2532 		return 1
   2533 	} else {
   2534 		append_text "\t*FAILED* $msg\n"
   2535 		return 0
   2536 	}
   2537 }
   2538 
   2539 proc get_default_vars {} {
   2540 	global default_var env
   2541 
   2542 	set qry [all_query_vars]
   2543 
   2544 	append qry ",vncconnect"
   2545 
   2546 	set q ""
   2547 	set i 0
   2548 	set all ""
   2549 	foreach s [split $qry ","] {
   2550 		if {$q != ""} {
   2551 			append q ","
   2552 		}
   2553 		append q $s
   2554 		incr i
   2555 		if {$i > 50} {
   2556 			set qargs [list "-QD" $q]
   2557 			set a [run_remote_cmd $qargs]
   2558 			if [info exists env(TKX11VNC_PRINT_ALL_QD)] {
   2559 				puts $q
   2560 				puts $a
   2561 				puts "---------------"
   2562 			}
   2563 			if {$all != ""} {
   2564 				append all ","
   2565 			}
   2566 			append all $a
   2567 			set q ""
   2568 			set i 0
   2569 		}
   2570 	}
   2571 	if {$q != ""} {
   2572 		set qargs [list "-QD" $q]
   2573 		set a [run_remote_cmd $qargs]
   2574 		if [info exists env(TKX11VNC_PRINT_ALL_QD)] {
   2575 			puts $q
   2576 			puts $a
   2577 			puts "---------------"
   2578 		}
   2579 		if {$all != ""} {
   2580 			append all ","
   2581 		}
   2582 		append all $a
   2583 	}
   2584 
   2585 # old way, qry too long...
   2586 #	set qargs [list "-QD" $qry]
   2587 #	set all [run_remote_cmd $qargs]
   2588 
   2589 	if {[regexp {ans=} $all]} {
   2590 		#append_text "Retrieved all default settings.\n"
   2591 	} else {
   2592 		#append_text "Failed to retrieve default settings.\n"
   2593 	}
   2594 
   2595 	set query_result_list [split_query $all]
   2596 
   2597 	set default_var(gui) ""
   2598 
   2599 	foreach piece $query_result_list {
   2600 		if {[regexp {^([^:][^:]*):(.*)$} $piece m0 item val]} {
   2601 			if {$val == "N/A"} {
   2602 				if {$item == "vncconnect"} {
   2603 					set val 1
   2604 				} else {
   2605 					set val ""
   2606 				}
   2607 			}
   2608 			if {$item == "display"} {
   2609 				set val ""
   2610 			} elseif {$item == "desktop"} {
   2611 				set val ""
   2612 			} elseif {$item == "auth"} {
   2613 				set val ""
   2614 			} elseif {$item == "gui"} {
   2615 				continue
   2616 			} 
   2617 			# some hacks we do here for now..
   2618 			if {$item == "cursor" && $val == ""} {
   2619 				set val "most"
   2620 			} elseif {$item == "scrollcopyrect" && $val == ""} {
   2621 				set val "always"
   2622 			} elseif {$item == "wirecopyrect" && $val == ""} {
   2623 				set val "always"
   2624 #			} elseif {$item == "overlay_nocursor" && $val == 0} {
   2625 #				set val 1
   2626 			}
   2627 
   2628 			set default_var($item) $val
   2629 #puts "default: $item -> $val"
   2630 		}
   2631 	}
   2632 }
   2633 
   2634 proc tilde_expand {file} {
   2635 	global env
   2636 	if {[file exists $file]} {
   2637 		return $file
   2638 	}
   2639 
   2640 	set user ""
   2641 	if {[info exists env(USER)]} {
   2642 		set user $env(USER)
   2643 	}
   2644 	if {$user == "" && [info exists env(LOGNAME)]} {
   2645 		set user $env(LOGNAME)
   2646 	}
   2647 
   2648 	set home ""
   2649 	if {[info exists env(HOME)]} {
   2650 		set home $env(HOME)
   2651 	} elseif {$user != ""} {
   2652 		set home "/home/$user"
   2653 	}
   2654 
   2655 	if {[regexp {^~} $file]} {
   2656 		if {[regexp {^~/} $file]} {
   2657 			if {$home != ""} {
   2658 				regsub {^~} $file $home file
   2659 			}
   2660 		} else {
   2661 			regsub {^~} $file "/home/" file
   2662 		}
   2663 	}
   2664 	return $file
   2665 }
   2666 
   2667 proc insert_cmdline_vars {} {
   2668 	global env cmd_var menu_var default_var x11vnc_cmdline
   2669 	if {![info exists x11vnc_cmdline]} {
   2670 		return
   2671 	}
   2672 	if {$x11vnc_cmdline == ""} {
   2673 		return
   2674 	}
   2675 	set cmd_var(novar) 1 
   2676 	set str [string trim $x11vnc_cmdline]
   2677 
   2678 	while {[regexp -- {^-} $str]} {
   2679 		if {[regexp -- {^--*([^ \t][^ \t]*)(.*)$} $str m var rest]} {
   2680 			set rest [string trim $rest]
   2681 			set var [string trim $var]
   2682 			if {[regexp {^\{\{([^\}]*)\}\}(.*)} $rest m val rest]} {
   2683 				set str [string trim $rest]
   2684 				set cmd_var($var) $val
   2685 			} else {
   2686 				set str $rest
   2687 				set cmd_var($var) "boolean"
   2688 			}
   2689 		} else {
   2690 			break
   2691 		}
   2692 	}
   2693 
   2694 	if {[info exists cmd_var(rc)]} {
   2695 		load_settings $cmd_var(rc)
   2696 	} elseif {[info exists cmd_var(norc)]} {
   2697 		;
   2698 	} else {
   2699 		set filex [tilde_expand "~/.x11vncrc"]
   2700 		if {[file exists $filex]} {
   2701 			load_settings $filex
   2702 		}
   2703 	}
   2704 
   2705 	foreach var [array names cmd_var] {
   2706 		if {$var == "novar"} {
   2707 			continue
   2708 		}
   2709 		if {[regexp {^[ \t]*$} $var]} {
   2710 			continue
   2711 		}
   2712 		if {[info exists menu_var($var)]} {
   2713 			if {$cmd_var($var) == "boolean"} {
   2714 				set menu_var($var) 1
   2715 			} else {
   2716 				set menu_var($var) $cmd_var($var)
   2717 			}
   2718 		}
   2719 	}
   2720 }
   2721 
   2722 proc copy_default_vars {} {
   2723 	global menu_var default_var
   2724 	foreach item [array names default_var] {
   2725 		if {[info exists menu_var($item)]} {
   2726 			if {[info exists default_var($item)]} {
   2727 				set menu_var($item) $default_var($item)
   2728 			}
   2729 		}
   2730 	}
   2731 	foreach item [array names menu_var] {
   2732 		if {[info exists default_var($item)]} {
   2733 			set menu_var($item) $default_var($item)
   2734 		}
   2735 	}
   2736 }
   2737 
   2738 proc update_menu_vars {{query ""}} {
   2739 	global all_settings menu_var query_result_list
   2740 	global x11vnc_icon_mode
   2741 
   2742 	set debug [in_debug_mode]
   2743 
   2744 	if {$query == "USE_LIST"} {
   2745 		;
   2746 	} elseif {$query == ""} {
   2747 		set query_result_list [split_query $all_settings]
   2748 	} else {
   2749 		set query_result_list [split_query $query]
   2750 	}
   2751 
   2752 	foreach piece $query_result_list {
   2753 #puts stderr "UMV: $piece"
   2754 		if [regexp {icon_mode:0} $piece] {
   2755 			set x11vnc_icon_mode 0
   2756 			#puts stderr "x11vnc_icon_mode: $x11vnc_icon_mode"
   2757 		}
   2758 		if [regexp {icon_mode:1} $piece] {
   2759 			set x11vnc_icon_mode 1
   2760 			#puts stderr "x11vnc_icon_mode: $x11vnc_icon_mode"
   2761 		}
   2762 		# XXX ipv6
   2763 		if {[regexp {^([^:][^:]*):(.*)$} $piece m0 item val]} {
   2764 			if {[info exists menu_var($item)]} {
   2765 				set old $menu_var($item)
   2766 #puts stderr "     $old"
   2767 				if {$val == "N/A"} {
   2768 					continue
   2769 				}
   2770 				set menu_var($item) $val
   2771 			}
   2772 			if {$item == "clients"} {
   2773 				update_clients_menu $val
   2774 			} elseif {$item == "display"} {
   2775 				set_x11_display $val
   2776 			} elseif {$item == "vncdisplay"} {
   2777 				set_vnc_display $val
   2778 			} elseif {$item == "http_url"} {
   2779 				set_vnc_url $val
   2780 			}
   2781 		}
   2782 	}
   2783 }
   2784 
   2785 proc load_settings {{file ""}} {
   2786 	global menu_var default_var env
   2787 
   2788 	if {$file == ""} {
   2789 		if {![info exists menu_var(load-settings)]} {
   2790 			return
   2791 		}
   2792 		set file $menu_var(load-settings)
   2793 	}
   2794 	if {$file == ""} {
   2795 		return
   2796 	}
   2797 
   2798 	set fh ""
   2799 	set filex [tilde_expand $file]
   2800 	catch {set fh [open $filex "r"]}
   2801 
   2802 	if {$fh == ""} {
   2803 		append_text "load_settings: *** failed to open $filex ***\n"
   2804 		return
   2805 	}
   2806 	copy_default_vars
   2807 
   2808 	set str ""
   2809 	while {[gets $fh line] > -1} {
   2810 		regsub -all {\\#} $line {__QUOTED_HASH__} line
   2811 		if {[regexp {^[ \t]*#} $line]} {
   2812 			continue
   2813 		}
   2814 		for {set i 0} {$i < 5} {incr i} {
   2815 			regsub {#.*$} $line "" line
   2816 		}
   2817 		if {[regexp {^[ \t]*$} $line]} {
   2818 			continue
   2819 		}
   2820 		regsub -all {__QUOTED_HASH__} $line {#} line
   2821 		if {[regexp {\\$} $line]} {
   2822 			regsub {\\$} $line " " line
   2823 			append str "$line"
   2824 		} else {
   2825 			append str "$line\n"
   2826 		}
   2827 	}
   2828 	close $fh
   2829 
   2830 	set count 0
   2831 	set parms ""
   2832 
   2833 	foreach line [split $str "\n"] {
   2834 		set line [string trim $line]
   2835 		regsub {^--*} $line "" line
   2836 		regsub -all {[ \t][ \t]*} $line " " line
   2837 		set list [split $line]
   2838 		set item [lindex $list 0]
   2839 		set value [lindex $list 1]
   2840 		if {[regexp {^[ \t]*$} $item]} {
   2841 			continue
   2842 		}
   2843 		if {$item == "gui"} {
   2844 			continue
   2845 		}
   2846 		if {[info exists menu_var($item)]} {
   2847 			if {[value_is_bool $item]} {
   2848 				set menu_var($item) 1
   2849 				incr count
   2850 				append parms "  -$item\n"
   2851 			} elseif {[value_is_string $item]} {
   2852 				if {$value != ""} {
   2853 					set menu_var($item) $value
   2854 					set nitem [get_nitem $item]
   2855 					append parms "  -$nitem $value\n"
   2856 					incr count
   2857 				}
   2858 			}
   2859 		}
   2860 	}
   2861 	append_text "loaded $count parameter settings from $filex"
   2862 	if {$count > 0} {
   2863 		append_text ":\n"
   2864 		append_text $parms
   2865 	} else {
   2866 		append_text ".\n"
   2867 	}
   2868 }
   2869 
   2870 proc save_settings {} {
   2871 	set rc_text [get_settings_rcfile]
   2872 
   2873 	set top "#
   2874 # This file is based on the current x11vnc settings and can be used as
   2875 # as a ~/.x11vncrc defaults file.  If saved to another filename, these
   2876 # settings can be passed to x11vnc at startup via \"-rc <filename>\".
   2877 #
   2878 # The rc file comment character is \"#\".  Use \"\\#\" for the literal char.
   2879 # You can continue lines using \"\\\" as the last character of a line.
   2880 #
   2881 # Lines beginning with \"#d\" indicate the parameter value is at its default
   2882 # setting and you probably want to leave it commented out.
   2883 #
   2884 # Lines beginning with \"#?\" indicate parameters you probably do not
   2885 # want to hardwire to the current setting (uncomment if you want that).
   2886 # 
   2887 # Some parameters are boolean, e.g. -forever, and take no value; while
   2888 # the others, e.g. -wait 50, take a string or numerical value.
   2889 #
   2890 # For booleans, the line will end with comment \"default: on\" or
   2891 # \"default: off\" indicating the default setting.  (Note: often
   2892 # \"-nofoobar\" corresponds to option \"-foobar\" and the former is
   2893 # \"the default\", e.g. -norepeat).
   2894 #
   2895 # For string or numerical options, the value \"\" in a line below
   2896 # means the default is unset and you will need to supply some non-empty
   2897 # value to use the parameter.  For reference, if the default differs
   2898 # from your value it placed at the end of the line as a comment.
   2899 # 
   2900 # Feel free to uncomment or comment any of the lines or to change any
   2901 # of the values of the parameters.  Don't be surprised that most if not
   2902 # all of the lines below are commented out (x11vnc has so many parameters,
   2903 # most of them will be at their default values).
   2904 #-------------------------------------------------------------------------
   2905 
   2906 "
   2907 
   2908 	set rc_text "$top$rc_text"
   2909 
   2910 	global env save_settings_var save_settings_var_ok
   2911 	if {[info exists env(HOME)]} {
   2912 		set save_settings_var "$env(HOME)/.x11vncrc"
   2913 	} else {
   2914 		set save_settings_var ".x11vncrc"
   2915 	}
   2916 	set save_settings_var_ok 0
   2917 
   2918 	set w [textwin "save_settings" "Save Settings..." $rc_text \
   2919 		"save_settings_var+Save as:"]
   2920 
   2921 	tkwait window $w
   2922 
   2923 	if {$save_settings_var_ok == 1} {
   2924 		set file $save_settings_var
   2925 		if {$file == ""} {
   2926 			return
   2927 		}
   2928 		set file [tilde_expand $file]
   2929 		append_text "\nSaving current settings to $file ...\n" 
   2930 		if {[file exists $file]} {
   2931 			set backup "${file}~"
   2932 			append_text "Backing up $file -> $backup ...\n"
   2933 			catch {file delete -force $backup}
   2934 			set emsg "*** Backup to $backup failed. ***\n"
   2935 			if {![file exists $backup]} {
   2936 				catch {file copy -force $file $backup}
   2937 				if {![file exists $backup]} {
   2938 					append_text $emsg
   2939 					bell
   2940 				}
   2941 			} else {
   2942 				append_text $emsg
   2943 				bell
   2944 			}
   2945 		}
   2946 		set fh ""
   2947 		catch {set fh [open $file "w"]}
   2948 		if {$fh != ""} {
   2949 			puts $fh $rc_text
   2950 			close $fh
   2951 			if {![file exists $file]} {
   2952 				append_text "*** Saving to $file failed. ***\n"
   2953 				bell
   2954 			} else {
   2955 				append_text "Done.\n"
   2956 			}
   2957 		} else {
   2958 			append_text "*** Open of $file failed. ***\n"
   2959 			bell
   2960 		}
   2961 	}
   2962 }
   2963 
   2964 proc clear_all {} {
   2965 	global menu_var unset_str
   2966 
   2967 	set debug [in_debug_mode]
   2968 	
   2969 	foreach item [array names menu_var] {
   2970 		if {$item == "debug_gui"} {
   2971 			continue
   2972 		}
   2973 		if {[info exists menu_var($item)]} {
   2974 			if {[is_action $item]} {
   2975 				set menu_var($item) ""
   2976 			} elseif {[value_is_bool $item]} {
   2977 				set menu_var($item) 0
   2978 			} elseif {[value_is_string $item]} {
   2979 				set menu_var($item) $unset_str
   2980 			}
   2981 		}
   2982 	}
   2983 	append_text "Cleared all settings.\n"
   2984 }
   2985 
   2986 proc defaults_all {} {
   2987 	copy_default_vars
   2988 	append_text "Reset all variables to default values.\n"
   2989 }
   2990 
   2991 proc all_query_vars {} {
   2992 	global query_ans_list query_aro_list all_settings
   2993 	global cache_all_query_vars
   2994 	
   2995 	if {$cache_all_query_vars != ""} {
   2996 		return $cache_all_query_vars
   2997 	}
   2998 
   2999 	set qry ""
   3000 	foreach item $query_ans_list {
   3001 		if {$qry == ""} {
   3002 			set qry $item
   3003 		} else {
   3004 			append qry ",$item"
   3005 		}
   3006 	}
   3007 	foreach item $query_aro_list {
   3008 		if {$qry == ""} {
   3009 			set qry $item
   3010 		} else {
   3011 			append qry ",$item"
   3012 		}
   3013 	}
   3014 	set cache_all_query_vars $qry
   3015 
   3016 	global env
   3017 	if [info exists env(TKX11VNC_PRINT_ALL_VARS)] {
   3018 		puts "--------------- BEGIN ALL VARS ---------------"
   3019 		puts $qry
   3020 		puts "--------------- END ALL VARS ---------------"
   3021 	}
   3022 
   3023 	return $qry
   3024 }
   3025 
   3026 proc query_all {{quiet 0}} {
   3027 	global query_ans_list query_aro_list all_settings
   3028 	global last_query_all_time
   3029 
   3030 	dtime 1
   3031 	set qry [all_query_vars]
   3032 
   3033 	set qargs [list "-Q" $qry]
   3034 	set all [run_remote_cmd $qargs]
   3035 
   3036 	if {[regexp {ans=} $all]} {
   3037 		if {! $quiet} {
   3038 			append_text "Retrieved all current settings.\n"
   3039 		}
   3040 		set all_settings $all
   3041 		update_menu_vars $all
   3042 	} else {
   3043 		if {! $quiet} {
   3044 			append_text "Failed to retrieve current settings.\n"
   3045 		}
   3046 	}
   3047 	set last_query_all_time [clock seconds]
   3048 	dtime 2
   3049 	return $all
   3050 }
   3051 
   3052 proc set_info {str} {
   3053 	global info_str info_label
   3054 #set w1 [$info_label cget -width]
   3055 #set w2 [winfo width $info_label]
   3056 #puts "set_info: w=$w1  winfo=$w2"
   3057 #append_text "$str\n"
   3058 	set info_str "$str"
   3059 	update
   3060 }
   3061 
   3062 proc append_text {str} {
   3063 	global text_area text_area_str
   3064 
   3065 	if {![info exists text_area_str]} {
   3066 		set text_area_str ""
   3067 	}
   3068 	append text_area_str $str
   3069 
   3070 	if {![info exists text_area]} {
   3071 		puts stderr $str
   3072 		return
   3073 	}
   3074 	if {$text_area == ""} {
   3075 		puts stderr $str
   3076 		return
   3077 	}
   3078 	if {![winfo exists $text_area]} {
   3079 		puts stderr $str
   3080 		return
   3081 	}
   3082 	
   3083 	$text_area insert end $str
   3084 	$text_area see end
   3085 }
   3086 
   3087 proc show_all_settings {} {
   3088 	global all_settings
   3089 	global client_sock client_tail
   3090 	global x11vnc_client_file
   3091 
   3092 	set txt "\nRead-Write settings:\n\n"
   3093 	foreach item [split_query $all_settings]  {
   3094 		regsub {:} $item {: } item
   3095 		append txt "  $item\n"
   3096 		if {[regexp {noremote} $item]} {
   3097 			append txt "\nRead-Only settings:\n\n"
   3098 		}
   3099 	}
   3100 	append txt "\nInternal settings:\n\n"
   3101 	append txt "x11vnc_client_file: $x11vnc_client_file\n"
   3102 	if {[info exists client_tail]} {
   3103 		append txt "client_tail: $client_tail\n"
   3104 	} else {
   3105 		append txt "client_tail: unset\n"
   3106 	}
   3107 	if {[info exists client_sock]} {
   3108 		append txt "client_sock: $client_sock\n"
   3109 	} else {
   3110 		append txt "client_sock: unset\n"
   3111 	}
   3112 	set estr ""
   3113 	catch {set estr [exec env | grep -i X11VNC]}
   3114 	append txt "$estr\n"
   3115 	textwin "Settings" "All Current Settings" $txt
   3116 }
   3117 
   3118 proc show_logfile {} {
   3119 	global menu_var unset_str
   3120 
   3121 	set logfile [tilde_expand $menu_var(logfile)]
   3122 	
   3123 	if {$logfile == "" || $logfile == $unset_str} {
   3124 		set txt "\nNo logfile was specified at x11vnc startup.\n\n"	
   3125 	} elseif {![file exists $logfile]} {
   3126 		set txt "\nLogfile \"$logfile\" does not exist.\n\n"
   3127 	} else {
   3128 		set fh "-3"
   3129 		set err ""
   3130 		catch {set fh [open $logfile "r"]} err
   3131 		if {$fh == "-3"} {
   3132 			set txt "\nError opening \"$logfile\" $err.\n\n"
   3133 		} else {
   3134 			set txt "\nLogfile \"$logfile\" current contents:\n"
   3135 			while {[gets $fh line] > -1} {
   3136 				append txt "$line\n"
   3137 			}
   3138 			close $fh
   3139 		}
   3140 	}
   3141 	textwin "Logfile" "Logfile" $txt
   3142 }
   3143 
   3144 proc tail_logfile {} {
   3145 	global menu_var unset_str ffont
   3146 	set logfile $menu_var(logfile)
   3147 	
   3148 	set txt ""
   3149 	if {$logfile == "" || $logfile == $unset_str} {
   3150 		set txt "\nNo logfile was specified at x11vnc startup.\n\n"	
   3151 	} elseif {![file exists $logfile]} {
   3152 		set txt "\nLogfile \"$logfile\" does not exist.\n\n"
   3153 	} else {
   3154 		set cmd ""
   3155 		set xterm_cmd "xterm -sb -fn $ffont -geometry 80x45 -title x11vnc-logfile -e"
   3156 		set cmd [split $xterm_cmd]
   3157 		lappend cmd "tail"
   3158 		lappend cmd "-3000f"
   3159 		lappend cmd $logfile
   3160 		lappend cmd "&"
   3161 		catch {[eval exec $cmd]}
   3162 	}
   3163 	if {$txt != ""} {
   3164 		textwin "Logfile" "Logfile" $txt
   3165 	}
   3166 }
   3167 
   3168 proc set_connected {yesno} {
   3169 	global connected_to_x11vnc
   3170 	set orig $connected_to_x11vnc
   3171 	
   3172 	if {$yesno == "yes"} {
   3173 		set connected_to_x11vnc 1
   3174 	} else {
   3175 		set connected_to_x11vnc 0
   3176 		no_x11_display
   3177 		no_vnc_display
   3178 	}
   3179 	if {$orig != $connected_to_x11vnc} {
   3180 		set_widgets
   3181 	}
   3182 }
   3183 
   3184 proc detach_from_display {} {
   3185 	global connected_to_x11vnc reply_xdisplay x11vnc_xdisplay
   3186 	set str "Detaching from X display."
   3187 	if {$reply_xdisplay != ""} {
   3188 		set str "Detaching from $reply_xdisplay."
   3189 	} elseif {$x11vnc_xdisplay != ""} {
   3190 		set str "Detaching from $x11vnc_xdisplay."
   3191 	}
   3192 	if {$connected_to_x11vnc} {
   3193 		append_text "$str\n"
   3194 	}
   3195 	set_connected no
   3196 }
   3197 
   3198 proc do_stop_quit {} {
   3199 	push_new_value "stop" "stop" 1 0
   3200 	set_connected no
   3201 	update
   3202 	after 250
   3203 	destroy .
   3204 }
   3205 
   3206 # Menu item is an action:
   3207 proc do_action {item} {
   3208 	global menu_var connected_to_x11vnc beginner_mode
   3209 
   3210 	if {[in_debug_mode]} {
   3211 		append_text "action: \"$item\"\n"
   3212 	}
   3213 #puts "action: \"$item\"\n"
   3214 
   3215 	if {$item == "ping"} {
   3216 		if {$beginner_mode} {
   3217 			try_connect_and_query_all
   3218 		} else {
   3219 			try_connect
   3220 		}
   3221 		return
   3222 	} elseif {$item == "start"} {
   3223 		start_x11vnc
   3224 		return
   3225 	} elseif {$item == "detach"} {
   3226 		detach_from_display
   3227 		return
   3228 	} elseif {$item == "attach"} {
   3229 		try_connect_and_query_all
   3230 		return
   3231 	} elseif {$item == "update-all"} {
   3232 		query_all
   3233 		return
   3234 	} elseif {$item == "clear-all"} {
   3235 		clear_all
   3236 		return
   3237 	} elseif {$item == "defaults-all"} {
   3238 		defaults_all
   3239 		return
   3240 	} elseif {$item == "save-settings"} {
   3241 		save_settings
   3242 		return
   3243 	} elseif {$item == "show-start-cmd"} {
   3244 		show_start_cmd
   3245 		return
   3246 	} elseif {$item == "all-settings"} {
   3247 		show_all_settings
   3248 		return
   3249 	} elseif {$item == "show-logfile"} {
   3250 		show_logfile
   3251 		return
   3252 	} elseif {$item == "tail-logfile"} {
   3253 		tail_logfile
   3254 		return
   3255 	} elseif {$item == "Misc-Tuning:"} {
   3256 		menu_help "$item"
   3257 		return
   3258 	} elseif {$item == "WindowView"} {
   3259 		change_view_state
   3260 		return
   3261 	} elseif {$item == "quit" || $item == "Quit"} {
   3262 		destroy .
   3263 		exit 0
   3264 	} elseif {$item == "stop+quit"} {
   3265 		do_stop_quit
   3266 	}
   3267 
   3268 	if {[value_is_string $item]} {
   3269 		if {! [entry_dialog $item]} {
   3270 			return
   3271 		}
   3272 		set new $menu_var($item)
   3273 		set name $item
   3274 	} else {
   3275 		set new 1
   3276 		set name $item
   3277 	}
   3278 
   3279 	if {$item == "load-settings"} {
   3280 		load_settings
   3281 		return
   3282 	}
   3283 
   3284 	if {! $connected_to_x11vnc} {
   3285 		;
   3286 	} elseif {[regexp {^(stop|quit|exit|shutdown)$} $item]} {
   3287 		# just do -R
   3288 		append_text "stopping remote x11vnc server...\n"
   3289 		push_new_value $item $name $new 0
   3290 		set_connected no
   3291 		
   3292 	} elseif {[opt_match Q $item]} {
   3293 		push_new_value $item $name $new 1
   3294 	} else {
   3295 		push_new_value $item $name $new 0
   3296 	}
   3297 }
   3298 
   3299 proc ptime {time} {
   3300 	set usec [lindex [split $time] 0]
   3301 	set sec [format "%.3f" [expr "$usec / 1000000.0"]]
   3302 	puts "time: $sec secs."
   3303 }
   3304 
   3305 proc do_var {item} {
   3306 	global connected_to_x11vnc item_cascade menu_var
   3307 
   3308 	set debug [in_debug_mode]
   3309 
   3310 	set string 0
   3311 	if {[is_action $item] || $item == "WindowView"} {
   3312 		# Menu item is action:
   3313 		if {$debug} {
   3314 			ptime [time {do_action $item}]
   3315 		} else {
   3316 			do_action $item
   3317 		}
   3318 		return
   3319 	}
   3320 
   3321 	if {[value_is_string $item]} {
   3322 		# Menu item is a string:
   3323 		if {$item_cascade($item) != ""} {
   3324 			# Cascade sets variable automatically
   3325 		} else {
   3326 			# Otherwise Entry box
   3327 			if {![entry_dialog $item]} {
   3328 				return
   3329 			}
   3330 		}
   3331 		set new $menu_var($item)
   3332 		set name $item
   3333 	} else {
   3334 		# Menu item is a boolean:
   3335 		set name [check_var $item]
   3336 		if {$name == ""} {
   3337 			return
   3338 		}
   3339 		set new 1
   3340 	}
   3341 	if {$connected_to_x11vnc} {
   3342 		if {$debug} {
   3343 			ptime [time {push_new_value $item $name $new 1}]
   3344 		} else {
   3345 			push_new_value $item $name $new 1
   3346 		}
   3347 
   3348 		if {$item == "http"} {
   3349 			global vnc_url
   3350 			append_text "  URL: $vnc_url\n"
   3351 		}
   3352 	}
   3353 }
   3354 
   3355 proc menu_help {item} {
   3356 	if ![help_win $item] {
   3357 		textwin "nohelp" "No help available" \
   3358 			"Sorry, no help avaiable for \"$item\""
   3359 	}
   3360 }
   3361 
   3362 proc opt_match {c item} {
   3363 	global item_opts
   3364 	if {[info exists item_opts($item)]} {
   3365 		if {[regexp "^\[A-z\]*$c" $item_opts($item)]} {
   3366 			return 1
   3367 		}
   3368 	}
   3369 	return 0
   3370 }
   3371 
   3372 proc is_action {item} {
   3373 	return [opt_match A $item]
   3374 }
   3375 
   3376 proc is_gui_internal {item} {
   3377 	if {$item == "Properties"} {
   3378 		return 1
   3379 	}
   3380 	if {$item == "Tray"} {
   3381 		return 1
   3382 	}
   3383 	return [opt_match G $item]
   3384 }
   3385 
   3386 proc is_browse {item} {
   3387 	return [opt_match F $item]
   3388 }
   3389 
   3390 proc value_is_string {item} {
   3391 	global item_bool
   3392 	if {![info exists item_bool($item)]} {
   3393 		return 0
   3394 	}
   3395 	if {! $item_bool($item)} {
   3396 		return 1
   3397 	} else {
   3398 		return 0
   3399 	}
   3400 }
   3401 
   3402 proc value_is_bool {item} {
   3403 	global item_bool
   3404 	if {![info exists item_bool($item)]} {
   3405 		return 0
   3406 	}
   3407 	if {$item_bool($item)} {
   3408 		return 1
   3409 	} else {
   3410 		return 0
   3411 	}
   3412 }
   3413 
   3414 proc split_query0 {query} {
   3415 	# original slower way with regexp/regsub
   3416 	regsub -all {aro=} $query {ans=} query
   3417 	set items {}
   3418 	while {1} {
   3419 		if {! [regexp {^ans=(.*)$} $query m0 m1]} {
   3420 			break
   3421 		}
   3422 		set item $m1
   3423 		set m2 ""
   3424 		regexp {,ans=.*$} $item m2
   3425 		regsub {,ans=.*$} $item "" item
   3426 		if {$item != ""} {
   3427 			lappend items $item
   3428 		}
   3429 		set query $m2
   3430 		regsub {^,} $query "" query
   3431 	}
   3432 	return $items
   3433 }
   3434 
   3435 proc split_query {query} {
   3436 	regsub -all {aro=} $query {ans=} query
   3437 	set items {}
   3438 	while {1} {
   3439 		set n [string first "ans=" $query]
   3440 		if {$n < 0} {
   3441 			break
   3442 		}
   3443 		set from [expr $n+4]
   3444 
   3445 		set m [string first ",ans=" $query]
   3446 		if {$m < 0} {
   3447 			set more 0
   3448 			set item [string range $query $from end]
   3449 		} else {
   3450 			set more 1
   3451 			set to   [expr $m-1]
   3452 			set item [string range $query $from $to]
   3453 		}
   3454 		if {$item != ""} {
   3455 			lappend items $item
   3456 		}
   3457 		if {$more} {
   3458 			incr m
   3459 			set query [string range $query $m end]
   3460 		} else {
   3461 			set query ""
   3462 		}
   3463 	}
   3464 	return $items
   3465 }
   3466 
   3467 proc set_x11_display {name} {
   3468 	global x11_display
   3469 	set x11_display "x11vnc X display: $name"
   3470 	set_name "tkx11vnc - $name"
   3471 }
   3472 proc set_vnc_display {name} {
   3473 	global vnc_display icon_mode
   3474 	set vnc_display "VNC display: $name"
   3475 
   3476 	if {$icon_mode} {
   3477 		set_icon_label
   3478 	}
   3479 }
   3480 proc set_vnc_url {name} {
   3481 	global vnc_url
   3482 	set vnc_url $name
   3483 }
   3484 proc no_x11_display {} {
   3485 	set_x11_display "(*none*)"
   3486 	set_name "tkx11vnc"
   3487 }
   3488 proc no_vnc_display {} {
   3489 	set_vnc_display "(*none*)"
   3490 }
   3491 proc no_vnc_url {} {
   3492 	set_vnc_url "(*none*)"
   3493 }
   3494 
   3495 proc get_vnc_display_number {} {
   3496 	global vnc_display
   3497 	if ![info exists vnc_display] {
   3498 		return "none"
   3499 	}
   3500 	if {$vnc_display == ""} {
   3501 		return "none"
   3502 	}
   3503 	set str $vnc_display
   3504 	regsub {VNC display: *} $str "" str
   3505 	if [regexp {:([0-9][0-9]*)} $str m0 n] {
   3506 		return $n
   3507 	}
   3508 	return "none"
   3509 }
   3510 
   3511 proc fetch_displays {} {
   3512 
   3513 	set qargs [list "-Q" "display,vncdisplay"]
   3514 	set result [run_remote_cmd $qargs]
   3515 
   3516 	set got_x11 0
   3517 	set got_vnc 0
   3518 	set got_url 0
   3519 
   3520 	foreach item [split_query $result] {
   3521 		if {[regexp {^display:(.*)$} $item m0 m1]} {
   3522 			set_x11_display $m1
   3523 			set got_x11 1
   3524 		} elseif {[regexp {^vncdisplay:(.*)$} $item m0 m1]} {
   3525 			set_vnc_display $m1
   3526 			set got_vnc 1
   3527 		} elseif {[regexp {^http_url:(.*)$} $item m0 m1]} {
   3528 			set_vnc_url $m1
   3529 			set got_url 1
   3530 		}
   3531 	}
   3532 	if {! $got_x11} {
   3533 		no_x11_display
   3534 	}
   3535 	if {! $got_vnc} {
   3536 		no_vnc_display
   3537 	}
   3538 	if {! $got_url} {
   3539 		no_vnc_url
   3540 	}
   3541 }
   3542 
   3543 proc client_dialog {client} {
   3544 	set cid ""
   3545 	set host ""
   3546 	set ip ""
   3547 	global menu_var text_area cleanup_window item_bool
   3548 
   3549 	#<id>:<ip>:<port>:<user>:<unix>:<hostname>:<input>:<loginview>:<time>
   3550 	append_text "\nClient info string:\n - $client\n\n"
   3551 	if {[regexp {^(.*):(.*):(.*):(.*):(.*):(.*):(.*):(.*):(.*)$} \
   3552 	    $client m0 m1 m2 m3 m4 m5 m6 m7 m8 m9]} {
   3553 		set cid  $m1
   3554 		set ip   $m2
   3555 		set port $m3
   3556 		set user $m4
   3557 		set unix $m5
   3558 		set host $m6
   3559 		regsub {\..*$} $host "" host
   3560 		set input $m7
   3561 		set logvo $m8
   3562 		set ltime $m9
   3563 		append_text "Host: $host, Port: $port, User: $user"
   3564 		if {$unix != "" && $unix != "none"} {
   3565 			append_text ", Unix: $unix"
   3566 		}
   3567 		append_text ", IP: $ip, Id: $cid\n"
   3568 		append_text " - originally logged in as: "
   3569 		if {$logvo == "1" } {
   3570 			append_text "View-Only Client"
   3571 		} else {
   3572 			append_text "Normal Client"
   3573 		}
   3574 		if {$ltime != ""} {
   3575 			set tim [clock format $ltime]
   3576 			append_text ",  $tim"
   3577 		}
   3578 		append_text "\n"
   3579 		append_text " - currently allowed input: "
   3580 		set sk 0
   3581 		set sm 0
   3582 		set sb 0
   3583 		set sc 0
   3584 		set sf 0
   3585 		if {[regexp -nocase {K} $input]} {
   3586 			append_text "Keystrokes"
   3587 			set sk 1
   3588 		}
   3589 		if {[regexp -nocase {M} $input]} {
   3590 			if {$sk} {
   3591 				append_text ", "
   3592 			}
   3593 			append_text "Mouse-Motion"
   3594 			set sm 1
   3595 		}
   3596 		if {[regexp -nocase {B} $input]} {
   3597 			if {$sk || $sm} {
   3598 				append_text ", "
   3599 			}
   3600 			append_text "Button-Click"
   3601 			set sb 1
   3602 		}
   3603 		if {[regexp -nocase {C} $input]} {
   3604 			if {$sk || $sm || $sb} {
   3605 				append_text ", "
   3606 			}
   3607 			append_text "Clipboard"
   3608 			set sm 1
   3609 		}
   3610 		if {[regexp -nocase {F} $input]} {
   3611 			if {$sk || $sm || $sb || $sf} {
   3612 				append_text ", "
   3613 			}
   3614 			append_text "Files"
   3615 			set sf 1
   3616 		}
   3617 		if {! $sk && ! $sm && ! $sb && ! $sm && ! $sf} {
   3618 			append_text "None"
   3619 		}
   3620 		append_text "\n"
   3621 	}
   3622 	if {$cid == ""} {
   3623 		append_text "Invalid client info string: $client\n"
   3624 		return
   3625 	}
   3626 
   3627 	regsub -all {_} $input "" input
   3628 	set menu_var(client) "$input"
   3629 	set item_bool(client) 0
   3630 
   3631 	insert_client_action_window $input
   3632 	set rc [entry_dialog client 1]
   3633 
   3634 	cleanup_text_window
   3635 
   3636 	set val $menu_var(client)
   3637 	#puts "rc: $rc  val: $val"
   3638 
   3639 	if {! $rc} {
   3640 		return;
   3641 	} elseif {[regexp -nocase {(disconnect|close)} $val]} {
   3642 		disconnect_dialog $client
   3643 	} else {
   3644 		regsub -all -nocase {[^KMBCF]} $val "" val
   3645 		set item_bool(client_input) 0
   3646 		push_new_value "client_input" "client_input" "$cid:$val" 0
   3647 	}
   3648 }
   3649 
   3650 proc disconnect_dialog {client} {
   3651 	set cid ""
   3652 	set host ""
   3653 	set msg "\n"
   3654 	append msg "*** Client info string:\n    $client\n"
   3655 	if {[regexp {^(.*):(.*):(.*):(.*):(.*):(.*):(.*):(.*):(.*)$} \
   3656 	    $client m0 m1 m2 m3 m4 m5 m6 m7 m8 m9]} {
   3657 		set cid  $m1
   3658 		set ip   $m2
   3659 		set port $m3
   3660 		set user $m4
   3661 		set unix $m5
   3662 		set host $m6
   3663 		regsub {\..*$} $host "" host
   3664 		set input $m7
   3665 		set logvo $m8
   3666 		set ltime $m9
   3667 		append_text "Host: $host, Port: $port, IP: $ip, User: $user"
   3668 		if {$unix != "" && $unix != "none"} {
   3669 			append_text ", Unix: $unix"
   3670 		}
   3671 		append_text ", Id: $cid\n"
   3672 	}
   3673 	if {$cid == ""} {
   3674 		append_text "Invalid client info string: $client\n"
   3675 		return
   3676 	}
   3677 	append msg "*** To *DISCONNECT* this client press \"OK\" again, otherwise press \"Cancel\"\n"
   3678 	bell
   3679 	if {[warning_dialog $msg "current"]} {
   3680 		push_new_value "disconnect" "disconnect" $cid 1
   3681 	} else {
   3682 		append_text "disconnect cancelled.\n"
   3683 	}
   3684 }
   3685 
   3686 proc update_clients_and_repost {} {
   3687 	global item_cascade menu_m menu_b
   3688 
   3689 	append_text "Refreshing connected clients list... "
   3690 	query_all 1
   3691 	update
   3692 
   3693 	set saw 0
   3694 	set casc $item_cascade(current)
   3695 	set last [$casc index end]
   3696 	for {set i 0} {$i <= $last} {incr i} {
   3697 		if {[$casc type $i] == "separator"} {
   3698 			continue
   3699 		}
   3700 		set name [$casc entrycget $i -label]
   3701 		if {[regexp {^num-clients} $name]} {
   3702 			continue
   3703 		}
   3704 		if {[regexp {^refresh-list} $name]} {
   3705 			continue
   3706 		}
   3707 		if {! $saw} {
   3708 			append_text "\n"
   3709 		}
   3710 		set saw 1
   3711 		append_text "client: $name\n"
   3712 	}
   3713 	if {! $saw} {
   3714 		append_text "done.\n"
   3715 	}
   3716 }
   3717 
   3718 proc update_clients_menu {list} {
   3719 	global item_cascade ffont
   3720 	global saved_clients_str
   3721 
   3722 	if {![info exists saved_clients_str]} {
   3723 		set saved_clients_str ""
   3724 	}
   3725 	if {$list == "INIT"} {
   3726 		set list $saved_clients_str
   3727 	} else {
   3728 		set saved_clients_str $list
   3729 	}
   3730 
   3731 	set subm $item_cascade(current);
   3732 	catch {destroy $subm}
   3733 	menu $subm -tearoff 0 -font $ffont
   3734 	$subm add command
   3735 	$subm add command -label "refresh-list" \
   3736 		-command "update_clients_and_repost"
   3737 	$subm add separator
   3738 	set count 0
   3739 	foreach client [split $list ","] {
   3740 		if {![regexp {^[a-z0-9]*[a-z0-9]:} $client]} {
   3741 			#append_text "Skipping client line: "
   3742 			#append_text $client
   3743 			#append_text "\n"
   3744 			continue
   3745 		}
   3746 		regsub -all {[{}()~!$&*|;'"`{}<>\[\]]} $client "" client
   3747 		#'
   3748 		if {[regexp {^(.*):(.*):(.*):(.*):(.*):(.*):(.*):(.*):(.*)$} \
   3749 		    $client m0 m1 m2 m3 m4 m5 m6 m7 m8 m9]} {
   3750 			set id   $m1
   3751 			set user $m4
   3752 			set unix $m5
   3753 			set host $m6
   3754 			regsub {\..*$} $host "" host
   3755 			set clabel "$host $id"
   3756 			if {$unix != "" && $unix != "none"} {
   3757 				set clabel "$unix@$clabel"
   3758 			} elseif {$user != "unknown-user"} {
   3759 				set clabel "$user@$clabel"
   3760 			}
   3761 		} else {
   3762 			regsub {:.*$} $client "" clabel
   3763 		}
   3764 		$subm add command -label "$clabel" \
   3765 			-command "client_dialog \{$client\}"
   3766 		incr count
   3767 	}
   3768 	$subm entryconfigure 0 -label "num-clients: $count"
   3769 }
   3770 
   3771 proc set_widgets {} {
   3772 	global connected_to_x11vnc item_case item_menu item_entry menu_m
   3773 
   3774 	foreach item [array names item_case] {
   3775 		if ![info exists item_case($item)] { continue; }
   3776 		set case $item_case($item)
   3777 		if ![info exists item_menu($item)] { continue; }
   3778 		set menu $item_menu($item)
   3779 		if ![info exists item_entry($item)] { continue; }
   3780 		set entry $item_entry($item)
   3781 		if {$entry < 0} {
   3782 			# skip case under beginner_mode 
   3783 			continue
   3784 		}
   3785 		set type [$menu type $entry]
   3786 		if {$type == "separator" || $type == "tearoff"} {
   3787 			continue
   3788 		}
   3789 		if {![winfo exists $menu]} {
   3790 			continue
   3791 		}
   3792 		if {$connected_to_x11vnc} {
   3793 			if {[active_when_connected $item]} {
   3794 				$menu entryconfigure $entry -state normal
   3795 			} else {
   3796 				$menu entryconfigure $entry -state disabled
   3797 			}
   3798 		} else {
   3799 			if {[active_when_starting $item]} {
   3800 				$menu entryconfigure $entry -state normal
   3801 			} else {
   3802 				$menu entryconfigure $entry -state disabled
   3803 			}
   3804 		}
   3805 	}
   3806 }
   3807 
   3808 proc toggle_simple_gui {} {
   3809 	global beginner_mode simple_gui_created
   3810 	global connected_to_x11vnc make_gui_count
   3811 
   3812 	if {$beginner_mode} {
   3813 		append_text "\nSwitching to simple-gui mode.\n"
   3814 	} else {
   3815 		append_text "\nSwitching to power-user gui mode.\n"
   3816 	}
   3817 
   3818 	if {$make_gui_count == 1} {
   3819 		incr make_gui_count
   3820 	}
   3821 	set simple_gui_created 1
   3822 	make_menu_items
   3823 	set_widgets
   3824 	set_internal_help
   3825 	append_text "\n"
   3826 }
   3827 
   3828 proc little_qs {m} {
   3829 	global bfont ffont beginner_mode
   3830 	global helpremote helptext helplabel
   3831 	global tk_version osname
   3832 
   3833 	if {$tk_version < 8.0} {
   3834 		return
   3835 	}
   3836 	if {$osname == "Darwin"} {
   3837 		return
   3838 	}
   3839 
   3840 	set n [$m index end]
   3841 
   3842 	for {set i 0} {$i <= $n} {incr i} {
   3843 		set type [$m type $i]
   3844 #puts "$m - $i - $type"
   3845 		if {$type == "separator"} {
   3846 			$m add separator
   3847 		} elseif {$type == "tearoff"} {
   3848 			continue;
   3849 		} else {
   3850 			set label [$m entrycget $i -label]
   3851 			set str ""
   3852 			if {[info exists helpremote($label)]} {
   3853 				set str "(?)"
   3854 			} elseif {[info exists helptext($label)]} {
   3855 				set str "(?)"
   3856 			}
   3857 			$m add command -label $str \
   3858 				-font $ffont \
   3859 				-command "menu_help $label";
   3860 
   3861 			if {$str == ""} {
   3862 				$m entryconfigure end -state disabled
   3863 			}
   3864 			set arg "$m,$i"
   3865 #puts "helplabel: $arg -> $label"
   3866 			set helplabel($arg) $label
   3867 			set j [$m index end]
   3868 			set arg "$m,$j"
   3869 			set helplabel($arg) $label
   3870 		}
   3871 		if {$i == 0} {
   3872 			$m entryconfigure end -columnbreak 1
   3873 		}
   3874 	}
   3875 
   3876 	menu_bindings $m
   3877 }
   3878 
   3879 proc make_menu_items {} {
   3880 	global template 
   3881 	global menu_b menu_m menu_count
   3882 	global item_opts item_bool item_case item_menu item_entry menu_var unset_str
   3883 	global item_cascade
   3884 	global bfont ffont beginner_mode simple_gui_created
   3885 	global helptext helpremote helplabel
   3886 
   3887 	# some tweaks...
   3888 	if {![info exists menu_var(deny)]} {
   3889 		set menu_var(deny) 0
   3890 	}
   3891 
   3892 	set case "";
   3893 	set L_casc ""
   3894 	set L_casc_count 0
   3895 	set L_menus [list]
   3896 
   3897 	# Extract the menu items:
   3898 	foreach line [split $template "\n"] {
   3899 		if {[regexp {^Row:} $line]} {
   3900 			continue
   3901 		}
   3902 		if {[regexp {^[A-z]} $line]} {
   3903 			set case [string trim $line]
   3904 
   3905 			if {$simple_gui_created} {
   3906 				set i0 0
   3907 				#if {$case == "Misc"} { # kludge for simple_gui
   3908 				#	set i0 1
   3909 				#}
   3910 				catch {$menu_m($case) delete $i0 end}
   3911 			}
   3912 			set menu_count($case) 0
   3913 			continue;
   3914 		}
   3915 
   3916 		set item [string trim $line]
   3917 		regsub -all {  *} $item " " item
   3918 		if {$item == ""} {
   3919 			continue;
   3920 		}
   3921 		set opts ""
   3922 		if {[regexp {^=} $item]} {
   3923 			set opts [lindex [split $item] 0]
   3924 			regsub {^=} $opts "" opts
   3925 			set item [lindex [split $item] 1]
   3926 		}
   3927 		if {[regexp {^0} $opts]} {
   3928 			continue;
   3929 		}
   3930 		if {[regexp {:$} $item]} {
   3931 			set bool 0
   3932 		} else {
   3933 			set bool 1
   3934 		}
   3935 		regsub {:$} $item {} item
   3936 
   3937 		if {$item == "LOFF"} {
   3938 			set L_casc ""
   3939 			continue
   3940 		}
   3941 
   3942 		if {$item == "-- D"} {
   3943 			set beginner_sep 1
   3944 			set item "--"
   3945 		} else {
   3946 			set beginner_sep 0
   3947 		}
   3948 
   3949 		set item_opts($item) $opts
   3950 		set item_case($item) $case
   3951 		set item_bool($item) $bool
   3952 		set item_cascade($item) ""
   3953 
   3954 		if {$L_casc == ""} {
   3955 			set item_entry($item) $menu_count($case)
   3956 			set m $menu_m($case)
   3957 		} else {
   3958 			# hack for cascades for crowded menus.  See =GAL opts.
   3959 			set item_entry($item) $L_casc_count
   3960 			set m $L_casc
   3961 		}
   3962 
   3963 		set mvar 0 
   3964 
   3965 		if {$beginner_mode && ! $beginner_sep && ![opt_match D $item]} {
   3966 			set item_entry($item) "-1"
   3967 			continue;
   3968 		}
   3969 
   3970 		set item_menu($item) $m
   3971 
   3972 		if {0} { puts "ITEM: $item\t- $opts\t- $case\t- \
   3973 			$bool\t- $menu_count($case)" }
   3974 
   3975 		# Create the menu items, its variables, etc., etc.
   3976 
   3977 		if {$item == "--"} {
   3978 			$m add separator
   3979 
   3980 		} elseif {$item == "Quit"} {
   3981 			# Quit item must shut us down:
   3982 			$m add command -label "$item" -underline 0 \
   3983 				-font $ffont \
   3984 				-command {destroy .; exit 0}
   3985 
   3986 		} elseif {$case == "Help"} {
   3987 			# Help is simple help:
   3988 			$m add command -label "$item" \
   3989 				-font $ffont \
   3990 				-command "menu_help $item"
   3991 
   3992 		} elseif {[opt_match L $item]} {
   3993 			# Special sub-menu cascade (=GAL ends with LOFF)
   3994 			set subm $m.casc_L$menu_count($case)
   3995 			catch {destroy $subm}
   3996 			menu $subm -tearoff 0 -font $ffont
   3997 			set item_cascade($item) $subm
   3998 			$m add cascade -label "$item" \
   3999 				-font $ffont \
   4000 				-menu $subm
   4001 			set L_casc $subm
   4002 			set L_casc_count -1
   4003 			lappend L_menus $L_casc
   4004 
   4005 		} elseif {$item == "current"} {
   4006 			# Current clients cascade
   4007 			set subm $m.current_cascade
   4008 			catch {destroy $subm}
   4009 			set item_cascade($item) $subm
   4010 			update_clients_menu "INIT"
   4011 			$m add cascade -label "$item" \
   4012 				-font $ffont \
   4013 				-menu $subm
   4014 
   4015 		} elseif {[is_action $item]} {
   4016 			# Action
   4017 			$m add command -label "$item" \
   4018 				-font $ffont \
   4019 				-command "do_var $item"
   4020 			if {![info exists menu_var($item)]} {
   4021 				set menu_var($item) "";	# for convenience
   4022 			}
   4023 
   4024 		} elseif {! $item_bool($item)} {
   4025 			# String
   4026 			if {[regexp -- {-C:(.*)} $item_opts($item) m0 m1]} {
   4027 				# Radiobutton select
   4028 				set subm $m.radio_cascade$menu_count($case)
   4029 				catch {destroy $subm}
   4030 				menu $subm -tearoff 0 -font $ffont
   4031 				foreach val [split $m1 ","] {
   4032 					$subm add radiobutton -label "$val" \
   4033 						-command "do_var $item" \
   4034 						-value "$val" \
   4035 						-font $ffont \
   4036 						-variable menu_var($item)
   4037 				}
   4038 				$m add cascade -label "$item" \
   4039 					-font $ffont \
   4040 					-menu $subm
   4041 				set item_cascade($item) $subm
   4042 			} else {
   4043 				# Arbitrary_string
   4044 				$m add command -label "$item" \
   4045 					-font $ffont \
   4046 					-command "do_var $item"
   4047 			}
   4048 			set mvar 1
   4049 
   4050 		} elseif {$item == "simple-gui"} {
   4051 			$m add checkbutton -label "$item" \
   4052 				-command "toggle_simple_gui" \
   4053 				-font $ffont \
   4054 				-variable beginner_mode
   4055 		} else {
   4056 			# Boolean
   4057 			$m add checkbutton -label "$item" \
   4058 				-command "do_var $item" \
   4059 				-font $ffont \
   4060 				-variable menu_var($item)
   4061 			if {![info exists menu_var($item)]} {
   4062 				set menu_var($item) 0
   4063 			}
   4064 		}
   4065 
   4066 		if {$L_casc_count == -1} {
   4067 			incr menu_count($case)
   4068 			incr L_casc_count
   4069 		} elseif {$L_casc != ""} {
   4070 			incr L_casc_count
   4071 		} else {
   4072 			incr menu_count($case)
   4073 		}
   4074 
   4075 		if {$mvar} {
   4076 			if {![info exists menu_var($item)]} {
   4077 				set menu_var($item) $unset_str
   4078 			}
   4079 		}
   4080 	}
   4081 
   4082 	# Now make the little "(?)" help buttons
   4083 	global osname
   4084 	foreach case [array names menu_m] {
   4085 		if {$case == "Help"} {
   4086 			continue;
   4087 		}
   4088 		little_qs $menu_m($case);
   4089 	}
   4090 	foreach m $L_menus {
   4091 		little_qs $m
   4092 	}
   4093 }
   4094 
   4095 proc check_update_vars {} {
   4096 	global last_query_all_time query_all_freq icon_mode
   4097 	global connected_to_x11vnc client_tail client_sock
   4098 
   4099 	set now [clock seconds]
   4100 
   4101 	set delay $query_all_freq
   4102 	if {$client_tail != "" && $client_sock == ""} {
   4103 		set delay [expr 2 * $query_all_freq]
   4104 	}
   4105 
   4106 	if {$connected_to_x11vnc} {
   4107 		set quiet 0
   4108 		set refresh [expr "$last_query_all_time + $delay"]
   4109 
   4110 		# puts "menu_posted $now $last_query_all_time"
   4111 		# puts "menu_posted $refresh"
   4112 
   4113 		if {$now > $refresh} {
   4114 			append_text "Refreshing current settings... "
   4115 			query_all $quiet
   4116 			if {$quiet} {
   4117 				append_text "done\n"
   4118 			}
   4119 		}
   4120 	}
   4121 }
   4122 
   4123 proc menu_posted {} {
   4124 	check_update_vars
   4125 }
   4126 
   4127 proc props_widgets {state} {
   4128 	global props_buttons
   4129 	foreach w $props_buttons {
   4130 		$w configure -state $state	
   4131 	}
   4132 	update
   4133 }
   4134 
   4135 proc props_apply {} {
   4136 	global props_accept props_confirm props_viewonly props_shared 
   4137 	global props_zeroconf props_javaview props_solid
   4138 	global props_passwd props_viewpasswd
   4139 	global prop0_accept prop0_confirm prop0_viewonly prop0_shared
   4140 	global prop0_zeroconf prop0_javaview prop0_solid
   4141 	global prop0_passwd prop0_viewpasswd
   4142 	global menu_var
   4143 	global client_sock
   4144 
   4145 	props_widgets disabled
   4146 
   4147 	set aft 500
   4148 	if {[info exists client_sock]} {
   4149 		if {$client_sock != ""} {
   4150 			set aft 150
   4151 		}
   4152 	}
   4153 	set did 0
   4154 
   4155 	set fail 0
   4156 
   4157 	if {$props_confirm != $prop0_confirm} {
   4158 		if {$did > 0} {after $aft}; incr did
   4159 		if {$props_confirm} {
   4160 			push_new_value "accept" "accept" "popup" 1
   4161 		} else {
   4162 			push_new_value "accept" "accept" "" 1
   4163 		}
   4164 		if {$menu_var(accept) == "popup"} {
   4165 			set props_confirm 1
   4166 		} elseif {$menu_var(accept) == ""} {
   4167 			set props_confirm 0
   4168 		}
   4169 		if {$props_confirm == $prop0_confirm} {incr fail}
   4170 		set prop0_confirm $props_confirm
   4171 	}
   4172 
   4173 	if {$props_viewonly != $prop0_viewonly} {
   4174 		if {$did > 0} {after $aft}; incr did
   4175 		if {$props_viewonly} {
   4176 			push_new_value "viewonly" "viewonly" 1 1
   4177 		} else {
   4178 			push_new_value "viewonly" "noviewonly" 1 1
   4179 		}
   4180 		if {$menu_var(viewonly)} {
   4181 			set props_viewonly 1
   4182 		} else {
   4183 			set props_viewonly 0
   4184 		}
   4185 		if {$props_viewonly == $prop0_viewonly} {incr fail}
   4186 		set prop0_viewonly $props_viewonly
   4187 	}
   4188 
   4189 	if {$props_shared != $prop0_shared} {
   4190 		if {$did > 0} {after $aft}; incr did
   4191 		if {$props_shared} {
   4192 			push_new_value "shared" "shared" 1 1
   4193 		} else {
   4194 			push_new_value "shared" "noshared" 1 1
   4195 		}
   4196 		if {$menu_var(shared)} {
   4197 			set props_shared 1
   4198 		} else {
   4199 			set props_shared 0
   4200 		}
   4201 		if {$props_shared == $prop0_shared} {incr fail}
   4202 		set prop0_shared $props_shared
   4203 	}
   4204 
   4205 	if {$props_zeroconf != $prop0_zeroconf} {
   4206 		if {$did > 0} {after $aft}; incr did
   4207 		if {$props_zeroconf} {
   4208 			push_new_value "zeroconf" "zeroconf" 1 1
   4209 		} else {
   4210 			push_new_value "zeroconf" "nozeroconf" 1 1
   4211 		}
   4212 		if {$menu_var(zeroconf)} {
   4213 			set props_zeroconf 1
   4214 		} else {
   4215 			set props_zeroconf 0
   4216 		}
   4217 		if {$props_zeroconf == $prop0_zeroconf} {incr fail}
   4218 		set prop0_zeroconf $props_zeroconf
   4219 	}
   4220 
   4221 	if {$props_javaview != $prop0_javaview} {
   4222 		if {$did > 0} {after $aft}; incr did
   4223 		if {$props_javaview} {
   4224 			push_new_value "http" "http" 1 1
   4225 		} else {
   4226 			push_new_value "http" "nohttp" 1 1
   4227 		}
   4228 		if {$menu_var(http)} {
   4229 			set props_javaview 1
   4230 		} else {
   4231 			set props_javaview 0
   4232 		}
   4233 		if {$props_javaview == $prop0_javaview} {incr fail}
   4234 		set prop0_javaview $props_javaview
   4235 	}
   4236 
   4237 	if {$props_solid != $prop0_solid} {
   4238 		if {$did > 0} {after $aft}; incr did
   4239 		if {$props_solid} {
   4240 			push_new_value "solid" "solid" 1 1
   4241 		} else {
   4242 			push_new_value "solid" "nosolid" 1 1
   4243 		}
   4244 		if {$menu_var(solid)} {
   4245 			set props_solid 1
   4246 		} else {
   4247 			set props_solid 0
   4248 		}
   4249 		if {$props_solid == $prop0_solid} {incr fail}
   4250 		set prop0_solid $props_solid
   4251 	}
   4252 
   4253 	set fpw 0
   4254 	if {$props_passwd != $prop0_passwd} {
   4255 		set fpw 1
   4256 	}
   4257 	set vpw 0
   4258 	if {$props_viewpasswd != $prop0_viewpasswd} {
   4259 		set vpw 1
   4260 	}
   4261 
   4262 	set pw_ord [list]
   4263 	if {!$fpw && !$vpw } {
   4264 		# neither change
   4265 		;
   4266 	} elseif {$fpw && !$vpw} {
   4267 		# full password change
   4268 		if {$props_passwd == ""} {
   4269 			if {$prop0_viewpasswd != ""} {
   4270 				# set view to "" as well and first
   4271 				set props_viewpasswd ""
   4272 				set pw_ord [list vpw fpw]
   4273 			} else {
   4274 				set pw_ord [list fpw]
   4275 			}
   4276 		} else {
   4277 			# assume view state OK
   4278 			set pw_ord [list fpw]
   4279 		}
   4280 		
   4281 	} elseif {!$fpw && $vpw} {
   4282 		# view password change
   4283 		if {$props_viewpasswd == ""} {
   4284 			# assume full state OK
   4285 			set pw_ord [list vpw]
   4286 		} else {
   4287 			if {$prop0_passwd == ""} {
   4288 				# could be trouble, x11vnc makes random
   4289 				# full passwd...
   4290 				set pw_ord [list vpw]
   4291 			} else {
   4292 				# OK, full non-null.
   4293 				set pw_ord [list vpw]
   4294 			}
   4295 		}
   4296 	} elseif {$fpw && $vpw} {
   4297 		# both full and view password change
   4298 		if {$props_passwd == "" && $props_viewpasswd == ""} {
   4299 			# OK, do view first
   4300 			set pw_ord [list vpw fpw]
   4301 		} elseif {$props_passwd == "" && $props_viewpasswd != ""} {
   4302 			# Not good, do view first anyway x11vnc will fix.
   4303 			set pw_ord [list vpw fpw]
   4304 		} elseif {$props_passwd != "" && $props_viewpasswd == ""} {
   4305 			# OK, view first
   4306 			set pw_ord [list vpw fpw]
   4307 		} elseif {$props_passwd != "" && $props_viewpasswd != ""} {
   4308 			# OK, full first
   4309 			set pw_ord [list fpw vpw]
   4310 		}
   4311 	}
   4312 
   4313 	foreach case $pw_ord {
   4314 		if {$case == "fpw"} {
   4315 			if {$did > 0} {after $aft}; incr did
   4316 			push_new_value "passwd" "passwd" "$props_passwd" 1
   4317 			if {$props_passwd == $prop0_passwd} {incr fail}
   4318 			set prop0_passwd $props_passwd
   4319 		}
   4320 		if {$case == "vpw"} {
   4321 			if {$did > 0} {after $aft}; incr did
   4322 			push_new_value "viewpasswd" "viewpasswd" "$props_viewpasswd" 1
   4323 			if {$props_viewpasswd == $prop0_viewpasswd} {incr fail}
   4324 			set prop0_viewpasswd $props_viewpasswd
   4325 		}
   4326 	}
   4327 
   4328 	if {$props_accept != $prop0_accept} {
   4329 		if {$did > 0} {after $aft}; incr did
   4330 		if {$props_accept} {
   4331 			push_new_value "unlock" "unlock" 1 0
   4332 		} else {
   4333 			push_new_value "lock" "lock" 1 0
   4334 		}
   4335 		if {$props_accept == $prop0_accept} {incr fail}
   4336 		set prop0_accept $props_accept
   4337 	}
   4338 
   4339 	props_widgets normal
   4340 	if {$fail > 0} {
   4341 		return 0
   4342 	} else {
   4343 		return 1
   4344 	}
   4345 }
   4346 
   4347 proc props_advanced {} {
   4348 	global icon_mode props_win full_win
   4349 	global props_advanced_first
   4350 
   4351 	if ![info exists props_advanced_first] {
   4352 		center_win $full_win
   4353 		set props_advanced_first 1
   4354 		set first 1
   4355 	} else {
   4356 		set first 0
   4357 	}
   4358 	update
   4359 	wm deiconify $full_win
   4360 	update
   4361 
   4362 	if {$first} {
   4363 		set w $full_win
   4364 		wm minsize $w [winfo width $w] [winfo height $w]
   4365 	}
   4366 	push_new_value "remote-cmd" "remote-cmd" "Q:clients" 1
   4367 }
   4368 
   4369 proc do_props {} {
   4370 	global props_accept props_confirm props_viewonly props_shared
   4371 	global props_zeroconf props_javaview props_solid
   4372 	global props_passwd props_viewpasswd
   4373 	global prop0_accept prop0_confirm prop0_viewonly prop0_shared
   4374 	global prop0_zeroconf prop0_javaview prop0_solid
   4375 	global prop0_passwd prop0_viewpasswd
   4376 	global menu_var unset_str
   4377 	global have_labelframes ffont bfont
   4378 	global props_buttons icon_noadvanced
   4379 	global icon_mode icon_mode_at_startup
   4380 	global screen_height screen_width
   4381 	global do_props_msg
   4382 
   4383 	set msg ""
   4384 	if {[info exists do_props_msg]} {
   4385 		set msg $do_props_msg
   4386 	}
   4387 
   4388 	check_update_vars
   4389 
   4390 	set pady 0.5m
   4391 	set pady 0.3m
   4392 	if {$screen_height <= 360} {
   4393 		set pady 0m
   4394 	}
   4395 
   4396 	if [info exists menu_var(deny)] {
   4397 		if {$menu_var(deny) == $unset_str || $menu_var(deny) == 0} {
   4398 			set props_accept 1
   4399 		} else {
   4400 			set props_accept 0
   4401 		}
   4402 	} else {
   4403 		set menu_var(deny) 0
   4404 		set props_accept 1
   4405 	}
   4406 	set prop0_accept $props_accept
   4407 
   4408 	if [info exists menu_var(accept)] {
   4409 		if {$menu_var(accept) == $unset_str || $menu_var(accept) == ""} {
   4410 			set props_confirm 0
   4411 		} else {
   4412 			set props_confirm 1
   4413 		}
   4414 	} else {
   4415 		set menu_var(accept) ""
   4416 		set props_confirm 0
   4417 	}
   4418 	set prop0_confirm $props_confirm
   4419 
   4420 	if [info exists menu_var(viewonly)] {
   4421 		if {$menu_var(viewonly) == $unset_str || $menu_var(viewonly) == ""} {
   4422 			set props_viewonly 0
   4423 		} elseif ($menu_var(viewonly)) {
   4424 			set props_viewonly 1
   4425 		} else {
   4426 			set props_viewonly 0
   4427 		}
   4428 	} else {
   4429 		set menu_var(viewonly) 0
   4430 		set props_viewonly 0
   4431 	}
   4432 	set prop0_viewonly $props_viewonly
   4433 
   4434 	if [info exists menu_var(shared)] {
   4435 		if {$menu_var(shared) == $unset_str || $menu_var(shared) == ""} {
   4436 			set props_shared 0
   4437 		} elseif ($menu_var(shared)) {
   4438 			set props_shared 1
   4439 		} else {
   4440 			set props_shared 0
   4441 		}
   4442 	} else {
   4443 		set menu_var(shared) 0
   4444 		set props_shared 0
   4445 	}
   4446 	set prop0_shared $props_shared
   4447 
   4448 	if [info exists menu_var(zeroconf)] {
   4449 		if {$menu_var(zeroconf) == $unset_str || $menu_var(zeroconf) == ""} {
   4450 			set props_zeroconf 0
   4451 		} elseif ($menu_var(zeroconf)) {
   4452 			set props_zeroconf 1
   4453 		} else {
   4454 			set props_zeroconf 0
   4455 		}
   4456 	} else {
   4457 		set menu_var(zeroconf) 0
   4458 		set props_zeroconf 0
   4459 	}
   4460 	set prop0_zeroconf $props_zeroconf
   4461 
   4462 	if [info exists menu_var(http)] {
   4463 		if {$menu_var(http) == $unset_str || $menu_var(http) == ""} {
   4464 			set props_javaview 0
   4465 		} elseif ($menu_var(http)) {
   4466 			set props_javaview 1
   4467 		} else {
   4468 			set props_javaview 0
   4469 		}
   4470 	} else {
   4471 		set menu_var(http) 0
   4472 		set props_javaview 0
   4473 	}
   4474 	set prop0_javaview $props_javaview
   4475 
   4476 	if [info exists menu_var(solid)] {
   4477 		if {$menu_var(solid) == $unset_str || $menu_var(solid) == ""} {
   4478 			set props_solid 0
   4479 		} elseif ($menu_var(solid)) {
   4480 			set props_solid 1
   4481 		} else {
   4482 			set props_solid 0
   4483 		}
   4484 	} else {
   4485 		set menu_var(solid) 0
   4486 		set props_solid 0
   4487 	}
   4488 	set prop0_solid $props_solid
   4489 
   4490 	if ![info exists props_passwd] {
   4491 		set props_passwd ""
   4492 	}
   4493 	set prop0_passwd $props_passwd
   4494 
   4495 	if ![info exists props_viewpasswd] {
   4496 		set props_viewpasswd ""
   4497 	}
   4498 	set prop0_viewpasswd $props_viewpasswd
   4499 
   4500 	if [info exists props_buttons] {
   4501 		catch {unset props_buttons}
   4502 	}
   4503 	set props_buttons [list]
   4504 
   4505 	set wp .props
   4506 	set w $wp
   4507 	catch {destroy $wp}
   4508 	toplevel $wp
   4509 	wm title $wp "x11vnc Properties"
   4510 	frame $w.lf
   4511 	set w $w.lf
   4512 	set b1 "$w.buttons1"
   4513 	frame $b1
   4514 	button $b1.ok -text OK -command "if {\[props_apply\]} {destroy $wp}" -font $bfont
   4515 	button $b1.cancel -text Cancel -command "destroy $wp" -font $bfont
   4516 	button $b1.apply  -text Apply -command "props_apply" -font $bfont
   4517 
   4518 	bind $w <KeyPress-Escape> "destroy $wp"
   4519 
   4520 	pack $b1.ok $b1.cancel $b1.apply -side left -expand 0
   4521 	lappend props_buttons $b1.apply $b1.cancel $b1.ok
   4522 
   4523 	set b2 "$w.buttons2"
   4524 	frame $b2
   4525 
   4526 	button $b2.advanced -text " Advanced ... " \
   4527 		-command "destroy $wp; props_advanced" -font $bfont
   4528 	if {! $icon_noadvanced} {
   4529 		lappend props_buttons $b2.advanced
   4530 		pack $b2.advanced -side left -expand 0
   4531 	}
   4532 
   4533 	button $b2.help -text "  Help  " -command "menu_help Properties" -font $bfont
   4534 	lappend props_buttons $b2.help
   4535 	pack $b2.help -side left -expand 0
   4536 
   4537 	set pw "$w.passwd"
   4538 	if {$have_labelframes} {
   4539 		labelframe $pw -text "Password" -font $bfont
   4540 	} else {
   4541 		frame $pw
   4542 		set l $pw.l
   4543 		label $l -text "Password:" -justify left -anchor w -font $bfont
   4544 		pack $pw.l -fill x -expand 1 -padx 1m -pady 0m -side top
   4545 	}
   4546 	entry $pw.e -show "*" -textvariable props_passwd -font $bfont
   4547 	pack $pw.e -fill x -expand 1 -padx 1m -pady $pady -side top
   4548 
   4549 	global x11vnc_icon_mode
   4550 	if {! $x11vnc_icon_mode} {
   4551 		catch { $pw.e configure -state disabled}
   4552 		if {! $have_labelframes} {
   4553 			catch { $pw.l configure -state disabled}
   4554 		}
   4555 	} else {
   4556 		lappend props_buttons $pw.e
   4557 	}
   4558 
   4559 
   4560 	set vp "$w.viewpw"
   4561 	if {$have_labelframes} {
   4562 		labelframe $vp -text "ViewOnly Password" -font $bfont
   4563 	} else {
   4564 		frame $vp
   4565 		set l $vp.l
   4566 		label $l -text "ViewOnly Password:" -justify left -anchor w -font $bfont
   4567 		pack $vp.l -fill x -expand 1 -padx 1m -pady 0m -side top
   4568 	}
   4569 	entry $vp.e -show "*" -textvariable props_viewpasswd -font $bfont
   4570 	pack $vp.e -fill x -expand 1 -padx 1m -pady $pady -side top
   4571 
   4572 	if {! $x11vnc_icon_mode} {
   4573 		catch { $vp.e configure -state disabled}
   4574 		if {! $have_labelframes} {
   4575 			catch { $vp.l configure -state disabled}
   4576 		}
   4577 	} else {
   4578 		lappend props_buttons $vp.e
   4579 	}
   4580 
   4581 	if {! $icon_mode_at_startup} {
   4582 		$vp.e configure -state disabled
   4583 		catch {$vp.l configure -state disabled}
   4584 		catch {$vp configure -state disabled}
   4585 		catch {$vp configure -foreground grey60}
   4586 		$pw.e configure -state disabled
   4587 		catch {$pw.l configure -state disabled}
   4588 		catch {$pw configure -state disabled}
   4589 		catch {$pw configure -foreground grey60}
   4590 	}
   4591 
   4592 	set sb "$w.solid"
   4593 	frame $sb
   4594 	checkbutton $sb.button -text "Solid Background Color" \
   4595 		-variable props_solid -anchor w -font $bfont
   4596 	pack $sb.button -fill x -expand 1 -padx 1m -pady $pady
   4597 
   4598 	set jv "$w.javaview"
   4599 	frame $jv
   4600 	checkbutton $jv.button -text "Serve Java Viewer Applet" \
   4601 		-variable props_javaview -anchor w -font $bfont
   4602 	pack $jv.button -fill x -expand 1 -padx 1m -pady $pady
   4603 
   4604 	set zc "$w.zeroconf"
   4605 	frame $zc
   4606 	checkbutton $zc.button -text "Advertise Service (Zeroconf)" \
   4607 		-variable props_zeroconf -anchor w -font $bfont
   4608 	pack $zc.button -fill x -expand 1 -padx 1m -pady $pady
   4609 
   4610 	set sh "$w.shared"
   4611 	frame $sh
   4612 	checkbutton $sh.button -text "Shared" \
   4613 		-variable props_shared -anchor w -font $bfont
   4614 	pack $sh.button -fill x -expand 1 -padx 1m -pady $pady
   4615 
   4616 	set vo "$w.viewonly"
   4617 	frame $vo
   4618 	checkbutton $vo.button -text "All Clients ViewOnly" \
   4619 		-variable props_viewonly -anchor w -font $bfont
   4620 	pack $vo.button -fill x -expand 1 -padx 1m -pady $pady
   4621 
   4622 	set cf "$w.confirm"
   4623 	frame $cf
   4624 	checkbutton $cf.button -text "Ask for Confirmation" \
   4625 		-variable props_confirm -anchor w -font $bfont
   4626 	pack $cf.button -fill x -expand 1 -padx 1m -pady $pady
   4627 
   4628 	set ac "$w.accept"
   4629 	frame $ac
   4630 	checkbutton $ac.button -text "Accept Connections" \
   4631 		-variable props_accept -anchor w -font $bfont
   4632 	pack $ac.button -fill x -expand 1 -padx 1m -pady $pady
   4633 
   4634 	set px "6m"
   4635 	pack $b1 -side bottom -fill x -pady $pady -padx $px
   4636 	pack $b2 -side bottom -fill x -pady $pady -padx $px
   4637 	pack $vp -side bottom -fill x -pady $pady -padx $px
   4638 	pack $pw -side bottom -fill x -pady $pady -padx $px
   4639 	pack $sb -side bottom -fill x -pady 0m -padx $px
   4640 	pack $jv -side bottom -fill x -pady 0m -padx $px
   4641 	pack $zc -side bottom -fill x -pady 0m -padx $px
   4642 	pack $sh -side bottom -fill x -pady 0m -padx $px
   4643 	pack $vo -side bottom -fill x -pady 0m -padx $px
   4644 	pack $cf -side bottom -fill x -pady 0m -padx $px
   4645 	pack $ac -side bottom -fill x -pady 0m -padx $px
   4646 
   4647 	global show_props_instructions
   4648 	if {![info exists show_props_instructions]} {
   4649 		set show_props_instructions 1
   4650 	}
   4651 
   4652 	wm withdraw .props
   4653 
   4654 	set wl $w
   4655 
   4656 	pack $wl -side left
   4657 
   4658 	if {$msg != ""} {
   4659 		set tw [textwidth $msg]
   4660 		set th [textheight $msg]
   4661 		set th [expr $th - 1]
   4662 		set ms ".props.msg"
   4663 		text $ms -font $ffont -relief ridge -width $tw -height $th
   4664 		$ms insert 1.0 $msg
   4665 
   4666 		set si "$wl.instructions"
   4667 		frame $si
   4668 		checkbutton $si.button -text "Show Instructions" \
   4669 			-variable show_props_instructions -anchor w -font $bfont \
   4670 			-command "toggle_instructions $ms $pady $px"
   4671 
   4672 		pack $si.button -fill x -expand 1 -padx 1m -pady $pady
   4673 		pack $si -side bottom -fill x -pady 0m -padx $px
   4674 
   4675 		if {$show_props_instructions} {
   4676 			pack $ms -side left -fill both
   4677 		}
   4678 
   4679 		update
   4680 	}
   4681 
   4682 
   4683 	lappend props_buttons $ac.button $cf.button $vo.button $sh.button $zc.button $jv.button $sb.button
   4684 
   4685 	
   4686 	set w .props
   4687 	update
   4688 	wm resizable $w 1 0
   4689 	center_win $w
   4690 	update
   4691 
   4692 	#wm minsize $w [winfo width $w] [winfo height $w]
   4693 
   4694 	tkwait window $w
   4695 	set show_props_instructions 0
   4696 }
   4697 
   4698 proc toggle_instructions {ms pady px} {
   4699 	global show_props_instructions
   4700 	if {$show_props_instructions} {
   4701 		pack $ms -side left -fill both
   4702 	} else {
   4703 		pack forget $ms
   4704 	}
   4705 	catch {pack .props}
   4706 	update
   4707 }
   4708 
   4709 proc do_new_client {} {
   4710 	global newclient ffont bfont
   4711 
   4712 	set w .newclient
   4713 	catch {destroy $w}
   4714 	toplevel $w
   4715 	label $w.l -text "Hostname: " -font $bfont
   4716 	set newclient ""
   4717 	entry $w.e -width 16 -textvariable newclient -font $bfont 
   4718 	button $w.b -text OK -command "destroy $w" -font $bfont
   4719 	button $w.h -text Help -command "menu_help NewClient" -font $bfont
   4720 	bind $w.e <Return> "update; after 100; destroy $w"
   4721 
   4722 	wm title $w "New Client"
   4723 
   4724 	pack $w.l $w.e $w.h $w.b -side left -pady 1m -padx 0.5m
   4725 	focus $w.e
   4726 	center_win $w
   4727 	update 
   4728 	
   4729 	tkwait window $w
   4730 
   4731 	regsub -all {[{}()~!$&*|;'"`{}<>\[\]]} $newclient "" newclient
   4732 	#'
   4733 	if {$newclient != ""} {
   4734 		push_new_value "connect" "connect" "$newclient" 1
   4735 	}
   4736 }
   4737 
   4738 proc do_disconnect_all {} {
   4739 	push_new_value "disconnect" "disconnect" "all" 1
   4740 }
   4741 
   4742 proc do_disconnect_client {id} {
   4743 	push_new_value "disconnect" "disconnect" "$id" 1
   4744 }
   4745 
   4746 proc popup_post {m} {
   4747 	global popup_cascade_posted client_balloon
   4748 	global client_id_list
   4749 
   4750 	set popup_cascade_posted 0
   4751 	
   4752 	set wd "$m.disconnect"
   4753 
   4754 	if {![winfo exists $wd]} {
   4755 		return
   4756 	}
   4757 
   4758 	catch {$wd delete 0 end}
   4759 
   4760 	$wd add command -label "Disconnect client:"
   4761 	$wd add separator
   4762 	$wd add command -label "All Clients" -command do_disconnect_all
   4763 
   4764 	if {![info exists client_id_list]} {
   4765 		return
   4766 	}
   4767 
   4768 	foreach client $client_id_list {
   4769 		if {$client == ""} {
   4770 			continue
   4771 		}
   4772 		if {[regexp {^([^:]*):(.*)$} $client mat id lab]} {
   4773 			set nid [expr "$id + 0"]
   4774 			$wd add command -label "$nid $lab" \
   4775 				-command "do_disconnect_client $id"
   4776 		}
   4777 	}
   4778 }
   4779 
   4780 proc pmenu {m x y} {
   4781 	if {![winfo exists $m]} {
   4782 		return
   4783 	}
   4784 	set x [expr $x-10]
   4785 	set y [expr $y-10]
   4786 	$m post $x $y
   4787 	# XXX more care needed
   4788 	grab set -global $m
   4789 }
   4790 
   4791 proc set_client_balloon {str} {
   4792 	global client_balloon vnc_display
   4793 	global client_id_list
   4794 
   4795 	set client_id_list [list]
   4796 	
   4797 	set client_balloon "$vnc_display"
   4798 	set count 0
   4799 	regsub -all {^.*aro=clients:} $str "" str
   4800 	regsub -all {aro=.*$} $str "" str
   4801 	regsub -all {ans=.*$} $str "" str
   4802 	foreach client [split $str ","] {
   4803 		#puts "client: $client"
   4804 		if [regexp {^[ 	]*$} $client] {
   4805 			continue
   4806 		}
   4807 		if {[regexp {^(.*):(.*):(.*):(.*):(.*):(.*):(.*):(.*):(.*)$} \
   4808 		    $client m0 m1 m2 m3 m4 m5 m6 m7 m8 m9]} {
   4809 			set id    $m1
   4810 			set nid   [expr "$m1 + 0"]
   4811 			set ip    $m2
   4812 			set port  $m3
   4813 			set user  $m4
   4814 			set unix  $m5
   4815 			if {[string length $user] >= 24} {
   4816 				# weird identd hash...
   4817 				set user [string range $user 0 8]
   4818 				set user "${user}..."
   4819 			}
   4820 			if {$unix != "" && $unix != "none"} {
   4821 				set user $unix
   4822 			}
   4823 			set host  $m6
   4824 			set input $m7
   4825 			set vo    $m8
   4826 			set ltime $m9
   4827 			if [regexp {^[ 	]*$} $host] {
   4828 				set host $ip
   4829 			}
   4830 			set client_balloon "${client_balloon}\n$nid $user\@$host"
   4831 			if {$vo == "1"} {
   4832 				set client_balloon "${client_balloon} - view"
   4833 				lappend client_id_list "$id:$user\@$host - view"
   4834 			} else {
   4835 				set client_balloon "${client_balloon} - full"
   4836 				lappend client_id_list "$id:$user\@$host - full"
   4837 			}
   4838 		} else {
   4839 			set i [expr $count+1]
   4840 			if {$i == 1} {
   4841 				set client_balloon "${client_balloon}\nunknown-host$i"
   4842 			}
   4843 		}
   4844 		incr count
   4845 	}
   4846 	if {$count == 0} {
   4847 		set client_balloon "${client_balloon}\nNo connections."
   4848 	}
   4849 	icon_win_cfg $count
   4850 }
   4851 
   4852 proc read_client_info {channel} {
   4853 	global x11vnc_client_file client_str client_info_read
   4854 	global read_client_info_lock
   4855 	global read_clients
   4856 	set db 0
   4857 
   4858 	set read_clients 0
   4859 
   4860 	if {![info exists read_client_info_lock]} {
   4861 		set read_client_info_lock 0
   4862 	}
   4863 
   4864 	if {$channel != ""} {
   4865 
   4866 		if {$read_client_info_lock} {
   4867 			return
   4868 		}
   4869 		set read_client_info_lock 1
   4870 		after 100
   4871 		set str ""
   4872 		set count [gets $channel str]
   4873 		if {$db} {puts stderr "read_client_info-$channel: $str"}
   4874 
   4875 		if {$count == -1 || [eof $channel]} {
   4876 			close $channel
   4877 			catch {file delete $x11vnc_client_file}
   4878 			set read_client_info_lock 0
   4879 			clean_icon_exit
   4880 		}
   4881 		if {$count > 0 && ![regexp {^[ 	]*$} $str]} {
   4882 			set client_info_read 1
   4883 			if {$str == "quit"} {
   4884 				catch {file delete $x11vnc_client_file}
   4885 				set read_client_info_lock 0
   4886 				clean_icon_exit
   4887 			} elseif {$str == "skip"} {
   4888 				;
   4889 			} elseif [regexp {^clients:} $str] {
   4890 				regsub {^clients:} $str "" str
   4891 				set read_clients 1
   4892 				if {$str == "none"} {
   4893 					set str ""
   4894 				}
   4895 				update_clients_menu $str
   4896 				set client_str $str
   4897 				set_client_balloon $str
   4898 			}
   4899 		}
   4900 		set read_client_info_lock 0
   4901 	}
   4902 }
   4903 
   4904 proc check_set_vnc_display {} {
   4905 	
   4906 	global read_clients check_set_vnc_display_done
   4907 
   4908 	if {[info exists check_set_vnc_display_done]} {
   4909 		return
   4910 	}
   4911 	if {[info exists read_clients]} {
   4912 		if {$read_clients} {
   4913 			after 250
   4914 			query_all
   4915 			global client_str
   4916 			set_client_balloon $client_str
   4917 			set check_set_vnc_display_done 1
   4918 		}
   4919 	}
   4920 }
   4921 
   4922 proc read_client_tail {} {
   4923 	global client_tail
   4924 
   4925 	if {$client_tail != ""} {
   4926 		read_client_info $client_tail
   4927 		check_set_vnc_display
   4928 	}
   4929 }
   4930 
   4931 proc read_client_sock {} {
   4932 	global client_sock
   4933 
   4934 	if {$client_sock != ""} {
   4935 		read_client_info $client_sock
   4936 		check_set_vnc_display
   4937 	}
   4938 }
   4939 
   4940 proc show_client_balloon {} {
   4941 	global icon_mode icon_win props_win full_win
   4942 	global client_balloon ffont connected_to_x11vnc
   4943 
   4944 	set noinfo "tkx11vnc: no client information"
   4945 	set noinfo "$noinfo\navailable from x11vnc ..."
   4946 	if ![info exists client_balloon] {
   4947 		set client_balloon $noinfo
   4948 	}
   4949 	if {$client_balloon == ""} {
   4950 		set client_balloon $noinfo
   4951 	}
   4952 	if {! [info exists icon_win]} {
   4953 		return
   4954 	} elseif {$icon_win == ""} {
   4955 		return
   4956 	} elseif {! [winfo exists $icon_win]} {
   4957 		return
   4958 	}
   4959 
   4960 	set x [expr [winfo rootx $icon_win] + ([winfo width $icon_win]/2)]
   4961 	set y [expr [winfo rooty $icon_win] + [winfo height $icon_win] + 4]
   4962 
   4963 	set infotext $client_balloon
   4964 	if {!$connected_to_x11vnc} {
   4965 		set infotext "Not currently attached to x11vnc\nLast available info:\n$infotext"
   4966 	}
   4967 
   4968 	set w .client_balloon
   4969 	catch {destroy $w}
   4970 	toplevel $w -bg black -screen [winfo screen $icon_win]
   4971 	wm overrideredirect $w 1
   4972 	label $w.l -text "$infotext" -relief flat -bg "#ffffaa" -fg black \
   4973 		-padx 2 -pady 0 -anchor w -justify left -font $ffont
   4974 	pack $w.l -side left -padx 1 -pady 1
   4975 
   4976 	set w2 [winfo reqwidth  $w.l]
   4977 	set h2 [winfo reqheight $w.l]
   4978 
   4979 	set W [winfo screenwidth  $w]
   4980 	set H [winfo screenheight $w]
   4981 
   4982 	if {[expr $x+$w2] > $W} {
   4983 		set w3 [winfo width $icon_win]
   4984 		set x [expr "$W - $w2 - $w3 - 4"] 
   4985 	}
   4986 	if {[expr $y+$h2] > $H} {
   4987 		set h3 [winfo height $icon_win]
   4988 		set y [expr "$H - $h2 - $h3 - 4"] 
   4989 	}
   4990 
   4991 	wm geometry $w +${x}+${y}
   4992 }
   4993 
   4994 proc kill_client_balloon {} {
   4995 	global client_balloon_id client_balloon_win
   4996 	if [info exists client_balloon_id] {
   4997 		catch {after cancel $client_balloon_id}
   4998 	}
   4999 	if [winfo exists .client_balloon] {
   5000 		destroy .client_balloon
   5001 	}
   5002 }
   5003 
   5004 proc icon_win_cfg {clients} {
   5005 	global icon_win client_tail client_sock client_info_read
   5006 
   5007 	if {! [info exists icon_win]} {
   5008 		return
   5009 	} elseif {$icon_win == ""} {
   5010 		return
   5011 	} elseif {! [winfo exists $icon_win]} {
   5012 		return
   5013 	}
   5014 	if {$clients > 0} {
   5015 		$icon_win configure -bg black -fg white
   5016 	} else {
   5017 		$icon_win configure -bg white -fg black
   5018 	}
   5019 
   5020 	if {$client_tail == "" || !$client_info_read} {
   5021 		if {$client_sock == ""} {
   5022 			$icon_win configure -fg red
   5023 		}
   5024 	}
   5025 }
   5026 
   5027 proc server_accept {sock addr port} {
   5028 	global socket_cookie server socket_got_callback
   5029 	global client_tail client_sock
   5030 	set db 0
   5031 
   5032 	if {$db} {puts stderr "sock=$sock addr=$addr port=$port"}
   5033 
   5034 	update; update idletasks
   5035 	after 50
   5036 	update; update idletasks
   5037 	set count [gets $sock str]
   5038 
   5039 	if {$count >= 0} {
   5040 		set str [string trim $str]
   5041 		if {$db} {puts stderr "server_accept: \"$str\""}
   5042 		if {$str == "COOKIE:$socket_cookie"} {
   5043 			set client_sock $sock
   5044 			if {$db} {puts stderr "cookie matched. $client_sock"}
   5045 		} else {
   5046 			if {$db} {puts stderr "cookie NO matched."}
   5047 		}
   5048 	}
   5049 	catch {close $server}
   5050 	set socket_got_callback 1
   5051 	if {$db} {puts stderr "socket_got_callback $socket_got_callback"}
   5052 }
   5053 
   5054 proc try_client_info_sock {} {
   5055 	global socket_cookie server socket_got_callback
   5056 	global x11vnc_started x11vnc_xdisplay hostname client_sock
   5057 	global x11vnc_xdisplay0 menu_var
   5058 
   5059 	set db 0
   5060 #dtime t1
   5061 	set start 13037
   5062 	set tries 100
   5063 	set socket_got_callback 0
   5064 
   5065 	set xd $x11vnc_xdisplay
   5066 	if {$xd == "" && $x11vnc_xdisplay0 != ""} {
   5067 		set xd $x11vnc_xdisplay0
   5068 	}
   5069 	if {$xd == "" && [info exists menu_var(display)]} {
   5070 		set xd $menu_var(display)
   5071 	}
   5072 
   5073 	set myaddr ""
   5074 	regsub {\..*$} $hostname "" shost
   5075 	if {$x11vnc_started} {
   5076 		set myaddr "127.0.0.1"
   5077 	} elseif {$xd != ""} {
   5078 		if {[regexp {^:} $xd]} {
   5079 			set myaddr "127.0.0.1"
   5080 		} elseif {[regexp -nocase "^$shost" $xd]} {
   5081 			set myaddr "127.0.0.1"
   5082 		} elseif {[regexp -nocase "^localhost" $xd]} {
   5083 			set myaddr "127.0.0.1"
   5084 		} else {
   5085 			set myaddr $hostname
   5086 		}
   5087 	} else {
   5088 		set myaddr $hostname
   5089 	}
   5090 	
   5091 	for {set i 0} {$i <= $tries} {incr i} {
   5092 		set port [expr $start + $i]
   5093 		set server [socket -server server_accept -myaddr $myaddr $port]
   5094 		if {$server == ""} {
   5095 			continue
   5096 		}
   5097 		if {[eof $server]} {
   5098 			continue
   5099 		}
   5100 		set err ""
   5101 		catch {set err [fconfigure $server -error]}
   5102 		#puts "err: $server: $err"
   5103 		if {$err == ""} {
   5104 			break
   5105 		}
   5106 	}
   5107 	if {$server == ""} {
   5108 		append_text "try_client_info_sock: server socket failed.\n"
   5109 		return
   5110 	}
   5111 	if {! $x11vnc_started} {
   5112 		run_remote_cmd [list "-nosync" "-R" "noop"]
   5113 		if {$db} {dtime A}
   5114 		after 250
   5115 		if {$db} {dtime A}
   5116 	}
   5117 
   5118 	# set the cookie to some obscured randomness
   5119 	set socket_cookie [clock clicks]
   5120 	set r [expr rand()]
   5121 	if {$r != ""} {
   5122 		append socket_cookie $r
   5123 	}
   5124 	set r ""
   5125 	catch {set r [winfo id .]}
   5126 	if {$r != ""} {
   5127 		append socket_cookie $r
   5128 	}
   5129 	if {[regexp {([0-9])([0-9])$} [clock clicks] m m1 m2]} {
   5130 		regsub -all {\.} $socket_cookie $m1 socket_cookie
   5131 		regsub -all {x}  $socket_cookie $m2 socket_cookie
   5132 	}
   5133 	run_remote_cmd [list "-nosync" "-R" \
   5134 		"client_info_sock:$myaddr:$port:$socket_cookie"]
   5135 #dtime t2
   5136 	if {$db} {puts "client_info_sock:$myaddr:$port:$socket_cookie"}
   5137 	for {set i 0} {$i < 10} {incr i} {
   5138 		after 50
   5139 		update; update idletasks
   5140 #dtime aa
   5141 		if {$socket_got_callback != 0} {
   5142 #puts "break-"
   5143 			break
   5144 		}
   5145 	}
   5146 #dtime t3
   5147 
   5148 	set aftid ""
   5149 	if {$socket_got_callback == 0} {
   5150 		set aftid [after 10000 {set socket_got_callback 2}]
   5151 		tkwait variable socket_got_callback
   5152 	}
   5153 
   5154 	if {$aftid != ""} {
   5155 		catch {after cancel $aftid}
   5156 	}
   5157 
   5158 	if {$socket_got_callback != 1} {
   5159 		puts stderr "try_client_info_sock failed: no callback\n"
   5160 		catch {close $server}
   5161 	} else {
   5162 		setup_client_sock 1
   5163 	}
   5164 #dtime t4
   5165 }
   5166 
   5167 proc set_icon_label {} {
   5168 	global icon_win
   5169 
   5170 	set lab [get_icon_label]
   5171 
   5172 	if {! [info exists icon_win]} {
   5173 		return
   5174 	} elseif {$icon_win == ""} {
   5175 		return
   5176 	} elseif {! [winfo exists $icon_win]} {
   5177 		return
   5178 	}
   5179 	
   5180 	if {[info exists icon_win]} {
   5181 		$icon_win configure -text $lab
   5182 	}
   5183 }
   5184 
   5185 proc get_icon_label {{set 0}} {
   5186 	global icon_minimal 
   5187 
   5188 	set lab0 "x11\nvnc"
   5189 	
   5190 	if {$icon_minimal} {
   5191 		set lab [get_vnc_display_number]
   5192 		if {$lab != "none"} {
   5193 			#set lab "  :$lab"
   5194 			set lab ":$lab"
   5195 		} else {
   5196 			set lab "-"
   5197 		}
   5198 	} else {
   5199 		set lab $lab0
   5200 	}
   5201 	return $lab
   5202 }
   5203 
   5204 # currently unused
   5205 proc lmenu {menu} {
   5206 	global popup_cascade_posted
   5207 	global left_iconwin_menu
   5208 	set left_iconwin_menu 1
   5209 	after 100
   5210 	update
   5211 	if {!$popup_cascade_posted && $left_iconwin_menu} {
   5212 		for {set i 0} {$i < 3} {incr i} {
   5213 			after 100
   5214 			update
   5215 		}
   5216 		if {!$popup_cascade_posted && $left_iconwin_menu} {
   5217 			$menu unpost
   5218 			return
   5219 		}
   5220 	}
   5221 	# kludge for WindowView
   5222 	if {$popup_cascade_posted} {
   5223 		focus $menu
   5224 	}
   5225 }
   5226 
   5227 proc old_balloon {} {
   5228 	global client_str saved_clients_str
   5229 	set str ""
   5230 	if {[info exists client_str]} {
   5231 		if {$client_str != ""} {
   5232 			set str $client_str
   5233 		}
   5234 	}
   5235 	if {$str == ""} {
   5236 		if {[info exists saved_clients_str]} {
   5237 			set str $saved_clients_str
   5238 		}
   5239 	}
   5240 	if {$str != ""} {
   5241 		set_client_balloon $str
   5242 	}
   5243 }
   5244 
   5245 proc get_custom_menu_items {} {
   5246 	global env custom_last_read
   5247 
   5248 	if {![info exists custom_last_read]} {
   5249 		set custom_last_read 0
   5250 	}
   5251 	if {[info exists env(X11VNC_CUSTOM_GUI)]} {
   5252 		set custom "$env(X11VNC_CUSTOM_GUI)"
   5253 	} elseif {![info exists env(HOME)]} {
   5254 		return [list "none"]
   5255 	} else {
   5256 		set custom "$env(HOME)/.x11vnc.gui"
   5257 	}
   5258 	if {![file exists $custom]} {
   5259 		return [list "none"]
   5260 	}
   5261 
   5262 #	if {[file mtime $custom] <= $custom_last_read} {
   5263 #		return [list "nochange"]
   5264 #	}
   5265 
   5266 	set in ""
   5267 	catch {set in [open $custom "r"]} 
   5268 	if {$in == ""} {
   5269 		return [list "none"]
   5270 	}
   5271 
   5272 	set custom_last_read [clock seconds]
   5273 
   5274 	set count 0
   5275 	while {[gets $in line] > -1} {
   5276 		if {[regexp {^[ \t]*#} $line]} {
   5277 			continue
   5278 		}
   5279 		set line [string trim $line]
   5280 		if {$line != ""} {
   5281 			lappend items $line
   5282 			incr count
   5283 		}
   5284 	}
   5285 	close $in
   5286 	
   5287 	if {$count > 0} {
   5288 		return $items
   5289 	} else {
   5290 		return [list "none"]
   5291 	}
   5292 }
   5293 
   5294 proc make_custom_menu {menu font} {
   5295 	set items [get_custom_menu_items]
   5296 	set i0 [lindex $items 0]
   5297 	catch {$menu delete 0 end}
   5298 	if {$i0 != "none"} {
   5299 		$menu add command -font $font -label "Custom items:"
   5300 		$menu add separator
   5301 		foreach item $items {
   5302 			if {$item == "sep" || $item == "separator"} {
   5303 				$menu add separator
   5304 				continue
   5305 			}
   5306 			if {[regexp {^action:(.*)$} $item m action]} {
   5307 				$menu add command -font $font -label "$action" \
   5308 				    -command "do_var $action"
   5309 				continue
   5310 			}
   5311 			$menu add command -font $font -label "$item" \
   5312 		 	    -command "run_remote_cmd \[list \"-R\" \"$item\"\]"
   5313 		}
   5314 	}
   5315 }
   5316 
   5317 proc make_icon {} {
   5318 	global icon_mode icon_embed_id icon_win props_win full_win
   5319 	global tray_embed tray_running env
   5320 	global x11vnc_client_file client_tail client_sock client_str saved_clients_str
   5321 	global client_balloon_id
   5322 	global bfont sfont snfont ffont
   5323 	global icon_minimal gui_start_mode
   5324 	global popup_cascade_posted menu_var x11vnc_gui_geom
   5325 	set min_x 24
   5326 	set min_y 24
   5327 	
   5328 	set font $bfont
   5329 	set mfont $font
   5330 
   5331 	if {$tray_embed} {
   5332 		set font $sfont
   5333 		set mfont $snfont
   5334 	}
   5335 	if {[info exists env(X11VNC_ICON_FONT)]} {
   5336 		set font $env(X11VNC_ICON_FONT)
   5337 	}
   5338 	if {[regexp {([0-9][0-9]*)x([0-9][0-9]*)} $x11vnc_gui_geom m mx my]} {
   5339 		if {$mx < $min_x} {
   5340 			set min_x $mx
   5341 		}
   5342 		if {$my < $min_y} {
   5343 			set min_y $my
   5344 		}
   5345 	}
   5346 	wm minsize . $min_x $min_y
   5347 
   5348 	if {$tray_embed && $tray_running} {
   5349 		wm withdraw .
   5350 	}
   5351 
   5352 	set l .icon
   5353 	set icon_win $l
   5354 	catch destroy {$icon_win}
   5355 	if {$icon_minimal} {
   5356 		set bw 1
   5357 	} else {
   5358 		set bw 5
   5359 	}
   5360 	set lab [get_icon_label]
   5361 	label $l -text $lab -borderwidth $bw -font $font
   5362 	icon_win_cfg 0
   5363 
   5364 
   5365 	set popup_cascade_posted 0
   5366 	pack $l -fill both -expand 1
   5367 	set menu "$l.menu"
   5368 	menu $menu -tearoff 0 -postcommand "popup_post $menu"
   5369 	$menu add command -font $mfont -label "Properties" -command do_props
   5370 	$menu add command -font $mfont -label "Help" -command "menu_help Tray"
   5371 	$menu add command -font $mfont -label "Logfile" -command show_logfile
   5372 	$menu add separator
   5373 	$menu add command -font $mfont -label "New Client" -command do_new_client
   5374 
   5375 	set wd "$menu.disconnect"
   5376 	catch {destroy $wd}
   5377 	menu $wd -tearoff 0 -font $ffont \
   5378 		-postcommand {set popup_cascade_posted 1}
   5379 	$wd add command -label "Disconnect client:"
   5380 	$wd add separator
   5381 	$wd add command -label "All Clients" -command do_disconnect_all
   5382 	$menu add cascade -font $mfont -label "Disconnect:" -menu $wd
   5383 
   5384 	$menu add separator
   5385 
   5386 	set wv "$menu.windowview"
   5387 	catch {destroy $wv}
   5388 	menu $wv -tearoff 0 -font $ffont \
   5389 		-postcommand {set popup_cascade_posted 1}
   5390 	foreach val {full icon tray} {
   5391 		$wv add radiobutton -label "$val" \
   5392 			-value "$val" -font $ffont \
   5393 			-command "do_var WindowView" \
   5394 			-variable menu_var(WindowView)
   5395 	}
   5396 	$menu add cascade -font $mfont -label "Window View:" -menu $wv
   5397 
   5398 	$menu add command -font $mfont -label "Dismiss" -command "$menu unpost"
   5399 	$menu add command -font $mfont -label "Stop x11vnc" -command clean_icon_exit
   5400 
   5401 	set items [get_custom_menu_items]
   5402 	set i0 [lindex $items 0]
   5403 	if {$i0 != "none" && $i0 != "nochange"} {
   5404 		$menu add separator
   5405 		set cm "$menu.custom"
   5406 		catch {destroy $cm}
   5407 		menu $cm -tearoff 0 -font $ffont \
   5408 			-postcommand "set popup_cascade_posted 1; make_custom_menu $cm $ffont"
   5409 		$menu add cascade -font $mfont -label "Custom:" -menu $cm
   5410 	}
   5411 
   5412 	bind $icon_win <ButtonRelease-1> "pmenu $menu %X %Y"
   5413 	bind $icon_win <ButtonRelease-3> "pmenu $menu %X %Y"
   5414 	bind $icon_win <Enter> {set client_balloon_id [after 500 show_client_balloon]}
   5415 	bind $icon_win <Button> {kill_client_balloon}
   5416 	bind $icon_win <Leave>  {kill_client_balloon}
   5417 	bind $icon_win <Shift-ButtonRelease-1> {kill_client_balloon; show_client_balloon}
   5418 	bind $icon_win <ButtonRelease-2> {kill_client_balloon; show_client_balloon}
   5419 #	bind $menu <Leave> "lmenu $menu"
   5420 #	bind $menu <Enter> "set left_iconwin_menu 0"
   5421 #	bind $menu <KeyPress-Escape> "$menu unpost"
   5422 
   5423 	bind . <Control-KeyPress-c> {destroy .; exit 0}
   5424 
   5425 	if {!$tray_embed || !$tray_running} {
   5426 		global x11vnc_gui_geom
   5427 		if {$x11vnc_gui_geom != ""} {
   5428 			set doit 1
   5429 			if {[regexp {x} $x11vnc_gui_geom]} {
   5430 				if {$gui_start_mode == "full"} {
   5431 					set doit 0
   5432 				}
   5433 			} 
   5434 			if {$doit} {
   5435 				wm geometry . $x11vnc_gui_geom
   5436 			}
   5437 		}
   5438 	}
   5439 	wm iconname . "tkx11vnc"
   5440 	wm title . "tkx11vnc"
   5441 	update
   5442 	if {$tray_embed && $tray_running} {
   5443 		#wm deiconify .;   #  why did we have this???
   5444 		#after 10000 {wm deiconify .; puts "reqheight [winfo reqheight .]"; puts "reqwidth  [winfo reqwidth  .]"; puts "height [winfo height .]"; puts "width  [winfo width  .]"}
   5445 	} else {
   5446 		wm deiconify .
   5447 	}
   5448 	update
   5449 
   5450 #puts "reqheight [winfo reqheight .]"
   5451 #puts "reqwidth  [winfo reqwidth  .]"
   5452 #puts "height [winfo height .]"
   5453 #puts "width  [winfo width  .]"
   5454 #puts "AAA"
   5455 
   5456 	old_balloon
   5457 }
   5458 
   5459 proc setup_client_channel {} {
   5460 	global client_sock client_tail
   5461 
   5462 # XXX/setup_client_channel
   5463 	if {$client_sock == "" } {
   5464 		stop_watch on
   5465 		try_client_info_sock
   5466 		if {$client_sock == "" } {
   5467 			after 500
   5468 			try_client_info_sock
   5469 		}
   5470 		stop_watch off
   5471 	}
   5472 	if {$client_tail == "" && $client_sock == ""} {
   5473 		set m "\n"
   5474 		set m "${m}tkx11vnc:\n"
   5475 		set m "${m}\n"
   5476 		set m "${m}    Warning -- running in icon/tray mode but the\n"
   5477 		set m "${m}    connected client info channel from x11vnc is\n"
   5478 		set m "${m}    not working.  The viewer client list and icon\n"
   5479 		set m "${m}    color indicator will not be accurate.\n"
   5480 		set m "${m}\n"
   5481 		set m "${m}    You may need to restart \"x11vnc -gui tray ...\"\n"
   5482 		set m "${m}    for this to work properly.\n"
   5483 		set m "${m}\n"
   5484 		textwin "Warning" "Warning" $m
   5485 		update
   5486 	}
   5487 	dtime C
   5488 }
   5489 
   5490 proc clean_client_tail {} {
   5491 	global client_tail client_info_read
   5492 	if [info exists client_tail] {
   5493 		if {$client_tail != ""} {
   5494 			set p ""
   5495 			catch {set p [pid $client_tail]}
   5496 			if {$p != ""} {
   5497 				catch {exec kill -TERM $p >/dev/null 2>/dev/null}
   5498 			}
   5499 			catch {close $client_tail}
   5500 			set client_tail ""
   5501 		}
   5502 	}
   5503 	set client_info_read 0
   5504 }
   5505 
   5506 proc clean_icon_exit {} {
   5507 	clean_client_tail
   5508 	push_new_value "stop" "stop" 1 0
   5509 	set_connected no
   5510 	update
   5511 	destroy .
   5512 	exit
   5513 }
   5514 
   5515 proc make_gui {mode} {
   5516 	global icon_mode tray_embed tray_running full_win icon_win
   5517 	global top_widget_names x11vnc_gui_geom
   5518 	global gui_current_state make_gui_count
   5519 	global x11vnc_connect connected_to_x11vnc
   5520 	global x11_display
   5521 	global gui_start_mode
   5522 
   5523 	incr make_gui_count
   5524 
   5525 	if {$gui_start_mode == ""} {
   5526 		set gui_start_mode $mode
   5527 	}
   5528 
   5529 	wm withdraw .
   5530 
   5531 	set full_geom ""
   5532 	if {[winfo exists .full]} {
   5533 		catch {set full_geom [wm geometry .full]}
   5534 	}
   5535 
   5536 	set fw .full
   5537 	set full_win $fw
   5538 	catch {pack forget $full_win}
   5539 	catch {pack forget $icon_win}
   5540 	catch {destroy $full_win}
   5541 	catch {destroy $icon_win}
   5542 
   5543 	wm minsize . 1 1
   5544 
   5545 	set gui_current_state ""
   5546 
   5547 	if {$mode == "full"} {
   5548 		frame $fw
   5549 		set icon_mode 0
   5550 
   5551 		wm protocol .     WM_DELETE_WINDOW "destroy .; exit"
   5552 		make_widgets $fw
   5553 
   5554 		set w "."
   5555 		wm geometry $w ""
   5556 		if {$x11vnc_gui_geom != ""} {
   5557 			set doit 1
   5558 			if {[regexp {x} $x11vnc_gui_geom]} {
   5559 				if {$gui_start_mode != $mode} {
   5560 					set doit 0
   5561 				}
   5562 			}
   5563 			if {$doit} {
   5564 				wm geometry $w $x11vnc_gui_geom
   5565 			}
   5566 		}
   5567 		pack $fw -fill both -expand 1
   5568 
   5569 	} elseif {$mode == "icon" || $mode == "tray"} {
   5570 
   5571 		toplevel $fw
   5572 		wm withdraw $fw
   5573 
   5574 		wm protocol $fw WM_DELETE_WINDOW "wm withdraw .full"
   5575 		wm protocol .   WM_DELETE_WINDOW "clean_icon_exit"
   5576 		
   5577 		if {$mode == "icon"} {
   5578 			set tray_embed 0
   5579 		} elseif {$mode == "tray"} {
   5580 			set tray_embed 1
   5581 		}
   5582 		set icon_mode 1
   5583 		make_widgets $fw
   5584 		set w $fw
   5585 		make_icon
   5586 		wm geometry $fw ""
   5587 		wm geometry .   ""
   5588 	} else {
   5589 		return
   5590 	}
   5591 	set_view_variable $mode
   5592 	set gui_current_state $mode
   5593 
   5594 
   5595 	update
   5596 	if {!$tray_embed || !$tray_running} {
   5597 		wm deiconify .
   5598 	}
   5599 	update idletasks
   5600 	wm minsize $w [winfo width $w] [winfo height $w]
   5601 	if {$mode == "full" && $make_gui_count > 1} {
   5602 		center_win .
   5603 	}
   5604 
   5605 
   5606 	if {$make_gui_count == 1} {
   5607 		copy_default_vars
   5608 		if {$x11vnc_connect} {
   5609 			try_connect_and_query_all
   5610 		} else {
   5611 			insert_cmdline_vars
   5612 		}
   5613 	} else {
   5614 		set_name "RESTORE"
   5615 	}
   5616 
   5617 	setup_client_tail
   5618 
   5619 	set_widgets
   5620 
   5621 	if {$mode == "tray"} {
   5622 		setup_tray_embed
   5623 	}
   5624 }
   5625 
   5626 proc make_widgets {top} {
   5627 	global template make_gui_count
   5628 	global menu_b menu_m menu_count
   5629 	global item_opts item_bool item_case item_menu item_entry menu_var unset_str
   5630 	global item_cascade
   5631 	global info_label info_str x11_display vnc_display
   5632 	global text_area text_area_str
   5633 	global entry_box entry_str entry_set entry_label entry_ok entry_browse
   5634 	global entry_help entry_skip
   5635 	global bfont ffont beginner_mode
   5636 	global helptext helpremote helplabel
   5637 	global icon_mode icon_win props_win full_win
   5638 	global top_widget_names
   5639 	global screen_height screen_width
   5640 
   5641 
   5642 	# Make the top label
   5643 	set label_width 84
   5644 	if {$screen_width <= 400} {
   5645 		set label_width 64
   5646 	}
   5647 	set info_label "$top.info"
   5648 	label $info_label -textvariable info_str -bd 2 -relief groove \
   5649 		-anchor w -width $label_width -font $ffont
   5650 	pack $info_label -side top -fill x -expand 0
   5651 
   5652 	set top_widget_names(info) $info_label
   5653 
   5654 	# Extract the Rows:
   5655 	set row 0;
   5656 	set colmax 0;
   5657 	foreach line [split $template "\n"] {
   5658 		if {[regexp {^Row: (.*)} $line rest]} {
   5659 			set col 0
   5660 			foreach case [split $rest] {
   5661 				if {$case == "" || $case == "Row:"} {
   5662 					continue
   5663 				}
   5664 				set menu_row($case) $row
   5665 				set menu_col($case) $col
   5666 
   5667 				lappend cases($col) $case;
   5668 				set len [string length $case]
   5669 				if {[info exists max_len($col)]} {
   5670 					if {$len > $max_len($col)} {
   5671 						set max_len($col) $len
   5672 					}
   5673 				} else {
   5674 					set max_len($col) $len
   5675 				}
   5676 				incr col
   5677 				if {$col > $colmax} {
   5678 					set colmax $col
   5679 				}
   5680 			}
   5681 			incr row;
   5682 		}
   5683 	}
   5684 
   5685 	# Make frames for the rows and make the menu buttons.
   5686 	set f "$top.menuframe"
   5687 	frame $f
   5688 	for {set c 0} {$c < $colmax} {incr c} {
   5689 		set colf "$f.menuframe$c"
   5690 		frame $colf
   5691 		pack $colf -side left -fill y
   5692 		set fbg [$colf cget -background]
   5693 		foreach case $cases($c) {
   5694 			set menub "$colf.menu$case";
   5695 			set menu "$colf.menu$case.menu";
   5696 			set menu_b($case) $menub
   5697 			set menu_m($case) $menu
   5698 			set ul 0
   5699 			foreach char [split $case ""] {
   5700 				set char [string tolower $char]
   5701 				if {![info exists underlined($char)]} {
   5702 					set underlined($char) 1
   5703 					break
   5704 				}
   5705 				incr ul
   5706 			}
   5707 			global osname
   5708 			set tstr "$case"
   5709 			if {$osname == "Darwin"} {
   5710 				#set tstr " $case   "
   5711 			}
   5712 			menubutton $menub -text "$tstr" -underline $ul \
   5713 				-anchor w -menu $menu -background $fbg \
   5714 				-font $bfont
   5715 			pack $menub -side top -fill x
   5716 			menu $menu -tearoff 0 -postcommand menu_posted
   5717 		}
   5718 	}
   5719 	pack $f -side top -fill x
   5720 	set top_widget_names(menuframe) $f
   5721 
   5722 	make_menu_items
   5723 
   5724 	# Make the x11 and vnc display label bar:
   5725 	set df "$top.displayframe"
   5726 	frame $df -bd 1 -relief groove
   5727 	set top_widget_names(displayframe) $df
   5728 
   5729 	set df_x11 "$df.xdisplay"
   5730 
   5731 	if {$make_gui_count == 1} {
   5732 		no_x11_display
   5733 	}
   5734 	set lw [expr {$label_width / 2}]
   5735 	label $df_x11 -textvariable x11_display -width $lw -anchor w \
   5736 		-font $ffont
   5737 
   5738 	set df_vnc "$df.vdisplay"
   5739 
   5740 	if {$make_gui_count == 1} {
   5741 		no_vnc_display
   5742 	}
   5743 	label $df_vnc -textvariable vnc_display -width $lw -anchor w \
   5744 		-font $ffont
   5745 
   5746 	pack $df_x11 $df_vnc -side left 
   5747 	pack $df -side top -fill x
   5748 
   5749 	# text area
   5750 	global text_height
   5751 	set text_area "$top.text"
   5752 	if {$screen_width <= 400} {
   5753 		text $text_area -height $text_height -width $label_width \
   5754 			-relief ridge -font $ffont
   5755 	} else {
   5756 		text $text_area -height $text_height -relief ridge -font $ffont
   5757 	}
   5758 	pack $text_area -side top -fill both -expand 1
   5759 	set top_widget_names(text) $text_area
   5760 
   5761 
   5762 	if {$text_area_str == ""} {
   5763 		set str "Click Help -> gui for overview."
   5764 		append_text "\n$str\n\n"
   5765 	} else {
   5766 		append_text $text_area_str
   5767 	}
   5768 
   5769 	# Make entry box stuff
   5770 	set ef "$top.entryframe"
   5771 	frame $ef -bd 1 -relief groove
   5772 	set top_widget_names(entryframe) $ef
   5773 
   5774 	# Entry Label
   5775 	set ef_label "$ef.label"
   5776 	label $ef_label -textvariable entry_str -anchor w -font $bfont
   5777 
   5778 	set entry_str "Set... : "
   5779 	set ef_entry "$ef.entry"
   5780 	entry $ef_entry -relief sunken -font $ffont
   5781 	bind $ef_entry <KeyPress-Return> {set entry_set 1}
   5782 	bind $ef_entry <KeyPress-Escape> {set entry_set 0}
   5783 
   5784 	set ok_s "OK"
   5785 	set cancel_s "Cancel"
   5786 	set help_s "Help"
   5787 	set browse_s "Browse..."
   5788 	global osname
   5789 	if {$osname == "Darwin"} {
   5790 		set ok_s " OK   "
   5791 		set cancel_s " Cancel   "
   5792 		set help_s " Help   "
   5793 		set browse_s " Browse...   "
   5794 	}
   5795 
   5796 	# Entry OK button
   5797 	set bpx "1m"
   5798 	set bpy "1"
   5799 	set hlt "0"
   5800 	set ef_ok "$ef.ok"
   5801 	button $ef_ok -text $ok_s -pady $bpy -padx $bpx -command {set entry_set 1} \
   5802 		-highlightthickness $hlt \
   5803 		-font $bfont
   5804 
   5805 	# Entry Skip button
   5806 	set ef_skip "$ef.skip"
   5807 	button $ef_skip -text $cancel_s -pady $bpy -padx $bpx -command {set entry_set 0} \
   5808 		-highlightthickness $hlt \
   5809 		-font $bfont
   5810 
   5811 	# Entry Help button
   5812 	set ef_help "$ef.help"
   5813 	button $ef_help -text $help_s -pady $bpy -padx $bpx -command \
   5814 		{menu_help $entry_dialog_item} -font $bfont \
   5815 		-highlightthickness $hlt
   5816 
   5817 	# Entry Browse button
   5818 	set ef_browse "$ef.browse"
   5819 	button $ef_browse -text $browse_s -pady $bpy -padx $bpx -font $bfont \
   5820 		-highlightthickness $hlt \
   5821 		-command {entry_insert [tk_getOpenFile]} 
   5822 
   5823 	pack $ef_label -side left
   5824 	pack $ef_entry -side left -fill x -expand 1
   5825 	pack $ef_ok   -side right
   5826 	pack $ef_skip -side right
   5827 	pack $ef_help -side right
   5828 	pack $ef -side bottom -fill x
   5829 
   5830 	set entry_ok $ef_ok
   5831 	set entry_skip $ef_skip
   5832 	set entry_help $ef_help
   5833 	set entry_box $ef_entry
   5834 	set entry_browse $ef_browse
   5835 	set entry_label $ef_label
   5836 	entry_disable
   5837 
   5838 }
   5839 
   5840 proc menu_bindings {m} {
   5841 	set db 0
   5842 	if {$db} {puts "menu_bindings $m"}
   5843 
   5844 	bind $m <<MenuSelect>> {
   5845 #syntax hilite bug \
   5846 MenuSelect>>
   5847 		set n [%W index active]
   5848 		set db 0
   5849 		if {$db} {puts stderr "menu_bindings %W $n"}
   5850 		set label "    "
   5851 		if {$n != "none"} {
   5852 			set str %W,$n
   5853 			set which ""
   5854 
   5855 			if {$db} {puts "menu_bindings $str"}
   5856 			if {[info exists helplabel($str)]} {
   5857 				set vname [format %%-16s $helplabel($str)]
   5858 				set label "Click (?) for help on: $vname"
   5859 				set which $helplabel($str)
   5860 			}
   5861 			if {$which == ""} {
   5862 				;
   5863 			} elseif {$which == "passwd" || $which == "viewpasswd"} {
   5864 				;
   5865 			} elseif {[is_action $which]} {
   5866 				if {[info exists menu_var($which)] 
   5867 				    && $menu_var($which) != ""} {
   5868 					set label "$label value: $menu_var($which)"
   5869 				} else {
   5870 					set label "$label (is action)"
   5871 				}
   5872 			} elseif {[info exists menu_var($which)]} {
   5873 				set label "$label value: $menu_var($which)"
   5874 				if {$which == "http"} {
   5875 					global vnc_url
   5876 					set label "$label  URL: $vnc_url"
   5877 				}
   5878 			}
   5879 		}
   5880 		set_info $label
   5881 	}
   5882 }
   5883 
   5884 proc key_bindings {} {
   5885 	global env menus_disabled
   5886 	if {[info exists env(USER)] && $env(USER) == "runge"} {
   5887 		# quick restart
   5888 		bind . <Control-KeyPress-k> {exec $argv0 $argv &; destroy .}
   5889 	}
   5890 	bind . <Control-KeyPress-p> { \
   5891 		global menus_disabled; \
   5892 		if {!$menus_disabled} {try_connect_and_query_all} \
   5893 	}
   5894 	bind . <Control-KeyPress-u> { \
   5895 		global menus_disabled; \
   5896 		if {!$menus_disabled} {query_all 0} \
   5897 	}
   5898 	bind . <Control-KeyPress-r> { \
   5899 		global menus_disabled; \
   5900 		if {!$menus_disabled} {query_all 0} \
   5901 	}
   5902 	bind . <Control-KeyPress-d> { \
   5903 		global menus_disabled; \
   5904 		if {!$menus_disabled} {detach_from_display} \
   5905 	}
   5906 	bind . <Control-KeyPress-a> { \
   5907 		global menus_disabled; \
   5908 		if {!$menus_disabled} {try_connect_and_query_all} \
   5909 	}
   5910 }
   5911 
   5912 proc stop_watch {onoff} {
   5913 	global orig_cursor text_area entry_box
   5914 
   5915 	set widgets [list .]
   5916 	if [info exists text_area] {
   5917 		if {$text_area != ""} {
   5918 			lappend widgets $text_area
   5919 		}
   5920 	}
   5921 	if [info exists entry_box] {
   5922 		if {$entry_box != ""} {
   5923 			lappend widgets $entry_box
   5924 		}
   5925 	}
   5926 
   5927 	if {$onoff == "on"} {
   5928 		foreach item $widgets {
   5929 			if {![winfo exists $item]} {
   5930 				continue
   5931 			}
   5932 			$item config -cursor {watch}
   5933 		}
   5934 	} else {
   5935 		foreach item $widgets {
   5936 			if {![winfo exists $item]} {
   5937 				continue
   5938 			}
   5939 			$item config -cursor {}
   5940 		}
   5941 	}
   5942 	update
   5943 }
   5944 
   5945 proc double_check_noremote {} {
   5946 	set msg "\n\n"
   5947 	append msg "*** WARNING: setting \"noremote\" will disable ALL remote control commands (i.e.\n"
   5948 	append msg "*** WARNING: *this* gui will be locked out). Do you really want to do this?\n"
   5949 	append msg "*** WARNING: If so, press \"OK\", otherwise press \"Cancel\"\n"
   5950 	append msg "\n"
   5951 	bell
   5952 	return [warning_dialog $msg "noremote"]
   5953 }
   5954 
   5955 proc get_settings_rcfile {} {
   5956 	global menu_var default_var unset_str
   5957 	global x11vnc_gui_params
   5958 
   5959 	set rc_txt ""
   5960 
   5961 	set menu_var(gui) $x11vnc_gui_params
   5962 
   5963 	foreach item [lsort [array names menu_var]] {
   5964 		if {$item == "gui"} {
   5965 			;
   5966 		} elseif {![active_when_starting $item]} {
   5967 			continue
   5968 		} elseif {[is_action $item]} {
   5969 			continue
   5970 		}
   5971 		if {$item == "debug_gui"} {
   5972 			continue
   5973 		} elseif {$item == "WindowView"} {
   5974 			continue
   5975 		} elseif {$item == "rc" || $item == "norc"} {
   5976 			continue
   5977 		} elseif {$item == "loop"} {
   5978 			continue
   5979 		} elseif {$item == "loopbg"} {
   5980 			continue
   5981 		}
   5982 
   5983 		set def ""
   5984 		if {[info exists default_var($item)]} {
   5985 			set def $default_var($item)
   5986 		}
   5987 
   5988 
   5989 		set qst ""
   5990 		set hmm "#? "
   5991 		if {$item == "display"} {
   5992 			set qst $hmm
   5993 		} elseif {$item == "desktop"} {
   5994 			set qst $hmm
   5995 		} elseif {$item == "dontdisconnect"} {
   5996 			set qst $hmm
   5997 		} elseif {$item == "alwaysshared"} {
   5998 			set qst $hmm
   5999 		} elseif {$item == "nevershared"} {
   6000 			set qst $hmm
   6001 		} elseif {$item == "gui"} {
   6002 			set qst $hmm
   6003 		}
   6004 
   6005 		if {![info exists menu_var($item)]} {
   6006 			set mv $def
   6007 		} else {
   6008 			set mv $menu_var($item)
   6009 		}
   6010 #puts "item=$item def=$def mv=$mv"
   6011 		if {$mv == $unset_str} {
   6012 			set mv ""
   6013 		}
   6014 		set ntab 3
   6015 
   6016 		if {$item == "gui" || [value_is_string $item]} {
   6017 			set nitem [get_nitem $item]
   6018 
   6019 			if {$mv == "" && $def != ""}  {
   6020 				set qst $hmm
   6021 			}
   6022 			set n 0
   6023 			if {$qst != ""} {
   6024 				append rc_txt $qst
   6025 				incr n [string length $qst]
   6026 			} elseif {$mv == $def} {
   6027 				append rc_txt "#d "
   6028 				incr n [string length "#d "]
   6029 			}
   6030 			set mt $mv
   6031 			regsub -all {#} $mt {\#} mt
   6032 			if {$mt == ""} {
   6033 				set mt {""}
   6034 			}
   6035 			append rc_txt "-$nitem $mt"
   6036 
   6037 			if {$mv != $def} {
   6038 				set m [string length "-$nitem $mt"]
   6039 				incr n $m
   6040 				set n [expr $n / 8]
   6041 				set c 0
   6042 				for {set i $n} {$i <= $ntab} {incr i} {
   6043 					append rc_txt "\t"
   6044 					incr c
   6045 				}
   6046 				if {$c == 0} {
   6047 					append rc_txt "\t"
   6048 				}
   6049 				regsub -all {#} $def {\#} def
   6050 				if {$def == ""} {
   6051 					set def {""}
   6052 				}
   6053 				append rc_txt "# default:  $def"
   6054 			}
   6055 			append rc_txt "\n"
   6056 
   6057 		} elseif {[value_is_bool $item]} {
   6058 			set n 0
   6059 			if {$qst != ""} {
   6060 				append rc_txt $qst
   6061 				incr n [string length $qst]
   6062 			} elseif {$mv == $def} {
   6063 				append rc_txt "#d "
   6064 				incr n [string length "#d "]
   6065 			}
   6066 			if {$def == 1} {
   6067 				set dv "on"
   6068 			} else {
   6069 				set dv "off"
   6070 			}
   6071 			append rc_txt "-$item"
   6072 			set m [string length "-$item"]
   6073 			incr n $m
   6074 			set n [expr $n / 8]
   6075 			for {set i $n} {$i <= $ntab} {incr i} {
   6076 				append rc_txt "\t"
   6077 			}
   6078 			append rc_txt "# default: $dv"
   6079 			append rc_txt "\n"
   6080 
   6081 		}
   6082 	}
   6083 	return $rc_txt
   6084 }
   6085 
   6086 proc double_check_start_x11vnc {} {
   6087 	global hostname
   6088 	set msg [get_start_x11vnc_txt]
   6089 	bell
   6090 	append msg "\n"
   6091 	append msg "*** To run the above command on machine \"$hostname\" (thereby\n"
   6092 	append msg "*** starting x11vnc) press \"OK\", otherwise press \"Cancel\".\n"
   6093 	return [warning_dialog $msg "start"]
   6094 }
   6095 
   6096 proc get_start_x11vnc_txt {} {
   6097 	set cmd [get_start_x11vnc_cmd]
   6098 	set str [join $cmd]
   6099 	set msg ""
   6100 	append msg "\n"
   6101 	append msg "==== The command built so far is: ====\n";
   6102 	append msg "\n"
   6103 	append msg "$str\n"
   6104 	return $msg
   6105 }
   6106 
   6107 proc show_start_cmd {} {
   6108 	set msg [get_start_x11vnc_txt]
   6109 	append_text "$msg\n"
   6110 }
   6111 
   6112 proc get_nitem {item} {
   6113 	set nitem $item
   6114 	if {$nitem == "screen_blank"} {
   6115 		set nitem "sb"
   6116 	} elseif {$nitem == "xrandr_mode"} {
   6117 		set nitem "xrandr"
   6118 	} elseif {$nitem == "unixpw_list"} {
   6119 		set nitem "unixpw"
   6120 	} elseif {$nitem == "unixpw_nis_list"} {
   6121 		set nitem "unixpw_nis"
   6122 	} elseif {$nitem == "stunnel_pem"} {
   6123 		set nitem "stunnel"
   6124 	} elseif {$nitem == "ssl_pem"} {
   6125 		set nitem "ssl"
   6126 	} elseif {$nitem == "wireframe_mode"} {
   6127 		set nitem "wireframe"
   6128 	} elseif {$nitem == "solid_color"} {
   6129 		set nitem "solid"
   6130 	}
   6131 	return $nitem
   6132 }
   6133 
   6134 proc get_start_x11vnc_cmd {{show_rc 0}} {
   6135 	global cmd_var menu_var default_var unset_str x11vnc_prog
   6136 
   6137 	set xterm_cmd "xterm -iconic -geometry 80x35 -title x11vnc-console -e"
   6138 
   6139 	set cmd [split $xterm_cmd]
   6140 
   6141 	lappend cmd $x11vnc_prog
   6142 
   6143 	lappend cmd "-gui"
   6144 	lappend cmd "none"
   6145 
   6146 	set rc_txt ""
   6147 
   6148 	set saw_id 0
   6149 
   6150 	foreach item [lsort [array names menu_var]] {
   6151 		if {$item == "gui"} {
   6152 			continue
   6153 		} elseif {![active_when_starting $item]} {
   6154 			continue
   6155 		} elseif {[is_action $item]} {
   6156 			continue
   6157 		} elseif {$item == "debug_gui"} {
   6158 			continue
   6159 		} elseif {$item == "WindowView"} {
   6160 			continue
   6161 		}
   6162 
   6163 		if {$item == "id" || $item == "sid"} {
   6164 			set val $menu_var($item);
   6165 			if {$val == "0x0" || $val == "root"} {
   6166 				continue
   6167 			}
   6168 		}
   6169 		if {$item == "sid" && $saw_id} {
   6170 			continue
   6171 		}
   6172 		if {$item == "id"} {
   6173 			set saw_id 1
   6174 		} elseif {$item == "httpport" && $menu_var($item) == "0"} {
   6175 			continue
   6176 		} elseif {$item == "progressive" && $menu_var($item) == "0"} {
   6177 			continue
   6178 		} elseif {$item == "dontdisconnect" && $menu_var($item) == "-1"} {
   6179 			continue
   6180 		} elseif {$item == "alwaysshared" && $menu_var($item) == "-1"} {
   6181 			continue
   6182 		}
   6183 
   6184 		if {[value_is_bool $item]} {
   6185 			if {[info exists menu_var($item)]} {
   6186 				set add 1
   6187 				if {[info exists default_var($item)]} {
   6188 					if {$menu_var($item) == $default_var($item)} {
   6189 						set add 0;
   6190 					}
   6191 				} elseif {! $menu_var($item)} {
   6192 					set add 0
   6193 				}
   6194 				if {$add} {
   6195 					lappend cmd "-$item"
   6196 					append rc_txt "-$item\n"
   6197 				}
   6198 			}
   6199 		} elseif {[value_is_string $item]} {
   6200 			if {![info exists menu_var($item)]} {
   6201 				continue
   6202 			}
   6203 			if {$menu_var($item) != "" && $menu_var($item) != $unset_str} {
   6204 				set add 1
   6205 				set nitem [get_nitem $item]
   6206 
   6207 				if {[info exists default_var($item)]} {
   6208 					if {$menu_var($item) == $default_var($item)} {
   6209 						set add 0;
   6210 					}
   6211 				}
   6212 				if {$add} {
   6213 					lappend cmd "-$nitem"
   6214 					set mv $menu_var($item)
   6215 
   6216 					if {[regexp {^~} $mv]}  {
   6217 						if {$item == "auth" ||
   6218 						    $item == "rc" ||
   6219 						    $item == "accept" || 
   6220 						    $item == "connect" || 
   6221 						    $item == "allow" || 
   6222 						    $item == "passwdfile" || 
   6223 						    $item == "o" || 
   6224 						    $item == "logfile" || 
   6225 						    $item == "remap" || 
   6226 						    $item == "httpdir"} { 
   6227 							set mv [tilde_expand $mv]
   6228 						}
   6229 					}
   6230 					
   6231 					lappend cmd $mv
   6232 					set mt $mv
   6233 					regsub -all {#} $mt {\#} mt
   6234 					append rc_txt "-$nitem $mt\n"
   6235 				}
   6236 			}
   6237 		}
   6238 	}
   6239 	lappend cmd "2>"
   6240 	lappend cmd "/dev/null"
   6241 	lappend cmd "&"
   6242 	
   6243 	if {$show_rc} {
   6244 		return $rc_txt
   6245 	} else {
   6246 		return $cmd
   6247 	}
   6248 }
   6249 
   6250 proc start_x11vnc {} {
   6251 	global menu_var unset_str
   6252 	global x11vnc_prog x11vnc_xdisplay
   6253 	global connected_to_x11vnc
   6254 
   6255 	if {$connected_to_x11vnc} {
   6256 		append_text "\n"
   6257 		append_text "WARNING: Still connected to an x11vnc server.\n"
   6258 		append_text "WARNING: Use \"stop\" or \"detach\" first.\n"
   6259 		return 0
   6260 	}
   6261 
   6262 	if {![double_check_start_x11vnc]} {
   6263 		return
   6264 	}
   6265 
   6266 	set x11vnc_xdisplay ""
   6267 	if {[info exists menu_var(display)]} {
   6268 		if {$menu_var(display) != "" && $menu_var(display) != $unset_str} {
   6269 			set x11vnc_xdisplay $menu_var(display)
   6270 		}
   6271 	}
   6272 
   6273 	set cmd [get_start_x11vnc_cmd]
   6274 
   6275 	set str [join $cmd]
   6276 	regsub { -e} $str " -e \\\n   " str
   6277 
   6278 	if {0} {
   6279 		puts "running: $str"
   6280 		foreach word $cmd {
   6281 			puts "   word: $word"
   6282 		}
   6283 	}
   6284 
   6285 	append_text "Starting x11vnc in an iconified xterm with command:\n"
   6286 	append_text "  $str\n\n"
   6287 	catch {[eval exec $cmd]}
   6288 	after 500
   6289 	try_connect_and_query_all 3
   6290 	if {!$connected_to_x11vnc} {
   6291 		append_text "\nStarting x11vnc seems to have failed.\n"
   6292 		if {[regexp -- {-o } $str] || [regexp -- {-logfile} $str]} {
   6293 			append_text "Examine the logfile (Debugging -> show-logfile) for error messages.\n"
   6294 		} else {
   6295 			append_text "Rerun with a logfile (if needed) and examine the logfile\n"
   6296 			append_text "(Debugging -> show-logfile) for error messages.\n"
   6297 		}
   6298 	}
   6299 }
   6300 
   6301 proc run_remote_cmd_via_sock {opts} {
   6302 	global client_sock
   6303 
   6304 	set db 0
   6305 	if {[file channels $client_sock] == ""} {
   6306 		set client_sock ""
   6307 		return "fail"
   6308 	}
   6309 	if {[eof $client_sock]} {
   6310 		catch {close $client_sock}
   6311 		set client_sock ""
   6312 		return "fail"
   6313 	}
   6314 	set result ""
   6315 		
   6316 	setup_client_sock 0
   6317 
   6318 	set docmd ""
   6319 	foreach opt $opts {
   6320 		if {$opt == "-R"} {
   6321 			set docmd "-R"
   6322 			continue
   6323 		} elseif {$opt == "-Q"} {
   6324 			set docmd "-Q"
   6325 			continue
   6326 		}
   6327 
   6328 		if {$docmd == ""} {
   6329 			continue
   6330 		} elseif {$docmd == "-R"} {
   6331 			set str "cmd=$opt"
   6332 		} elseif {$docmd == "-Q"} {
   6333 			set str "qry=$opt"
   6334 		} else {
   6335 			set docmd ""
   6336 			continue
   6337 		}
   6338 
   6339 		if {$db} {puts stderr "run_remote_cmd_via_sock: $docmd \"$str\""}
   6340 		catch {puts $client_sock $str}
   6341 		if {$db} {puts stderr "run_remote_cmd_via_sock: flush"}
   6342 		catch {flush $client_sock}
   6343 		if {$db} {puts stderr "run_remote_cmd_via_sock: gets"}
   6344 		catch {gets $client_sock res}
   6345 		if {$db} {puts stderr "run_remote_cmd_via_sock: \"$res\""}
   6346 		set res [string trim $res]
   6347 
   6348 		if [regexp {=clients:} $res] {
   6349 			regsub {^.*=clients:} $res "" cres
   6350 			regsub {,aro=.*$} $cres "" cres
   6351 			regsub {,ans=.*$} $cres "" cres
   6352 			if {$cres == "none"} {
   6353 				set cres ""
   6354 			}
   6355 			update_clients_menu $cres
   6356 			set client_str $cres
   6357 			set_client_balloon $cres
   6358 		}
   6359 
   6360 		if [regexp {^clients:} $res] {
   6361 			regsub {^clients:} $res "" tmp
   6362 			if {$tmp == "none"} {
   6363 				set tmp ""
   6364 			}
   6365 			update_clients_menu $tmp
   6366 			set client_str $tmp
   6367 			set_client_balloon $tmp
   6368 
   6369 			if ![regexp {^clients} $opt] {
   6370 				# we could block here...
   6371 				if {$db} {puts stderr "run_remote_cmd_via_sock: gets"}
   6372 				gets $client_sock res
   6373 				if {$db} {puts stderr "run_remote_cmd_via_sock: \"$res\""}
   6374 				set res [string trim $res]
   6375 			}
   6376 		}
   6377 
   6378 		set docmd ""
   6379 
   6380 		if {$res != ""} {
   6381 			append result "$res\n"
   6382 		}
   6383 	}
   6384 	
   6385 	setup_client_sock 1
   6386 
   6387 	set result [string trim $result]
   6388 
   6389 	return $result
   6390 }
   6391 
   6392 proc run_remote_cmd {opts} {
   6393 	global menu_var x11vnc_prog x11vnc_cmdline x11vnc_xdisplay
   6394 	global x11vnc_auth_file x11vnc_connect_file
   6395 	global client_sock
   6396 
   6397 	set debug [in_debug_mode]
   6398 
   6399 	if {[lindex $opts 0] == "-R" && [lindex $opts 1] == "noremote"} {
   6400 		set str [join $opts]
   6401 		if ![double_check_noremote] {
   6402 			append_text "skipping: x11vnc $str"
   6403 			return ""
   6404 		} else {
   6405 			append_text "running: x11vnc $str (please do \"Actions -> detach\" to clean things up)\n"
   6406 			append_text "subsequent -R/-Q commands should fail..."
   6407 		}
   6408 	}
   6409 
   6410 	if {$client_sock != ""} {
   6411 		menus_disable
   6412 		stop_watch on
   6413 		set result [run_remote_cmd_via_sock $opts]
   6414 		stop_watch off
   6415 		menus_enable
   6416 		if {$result != "fail"} {
   6417 			return $result
   6418 		}
   6419 	}
   6420 
   6421 	set cmd ""
   6422 
   6423 	lappend cmd $x11vnc_prog;
   6424 
   6425 	if {$x11vnc_connect_file != ""} {
   6426 		lappend cmd "-connect"
   6427 		lappend cmd $x11vnc_connect_file
   6428 	} else {
   6429 		if {$x11vnc_xdisplay != ""} {
   6430 			lappend cmd "-display"
   6431 			lappend cmd $x11vnc_xdisplay
   6432 		}
   6433 		if {$x11vnc_auth_file != ""} {
   6434 			lappend cmd "-auth"
   6435 			lappend cmd $x11vnc_auth_file
   6436 		}
   6437 	}
   6438 	lappend cmd "-sync"
   6439 	foreach word $opts {
   6440 		lappend cmd $word
   6441 	}
   6442 	lappend cmd "2>"
   6443 	lappend cmd "/dev/null"
   6444 
   6445 	if {0 || $debug} {
   6446 		set str [join $cmd]
   6447 		puts "running: $str"
   6448 		foreach word $cmd {
   6449 			puts "   word: $word"
   6450 		}
   6451 	}
   6452 
   6453 	set output ""
   6454 	menus_disable
   6455 
   6456 	stop_watch on
   6457 	catch {set output [eval exec $cmd]}
   6458 	stop_watch off
   6459 
   6460 	menus_enable
   6461 	if {$debug} {
   6462 		if {[string length $output] > 100} {
   6463 			set str [string range $output 0 100]
   6464 			append_text "output: $str ...\n"
   6465 		} else {
   6466 			append_text "output: $output\n"
   6467 		}
   6468 	}
   6469 	return $output
   6470 }
   6471 
   6472 proc try_connect_and_query_all {{n 2}} {
   6473 	for {set i 0} {$i < $n} {incr i} {
   6474 		if {$i > 0} {
   6475 			after 500
   6476 			append_text "trying again ...\n"
   6477 		}
   6478 		if {[try_connect]} {
   6479 			query_all
   6480 			break
   6481 		}
   6482 	}
   6483 }
   6484 
   6485 proc try_connect {} {
   6486 	global x11vnc_xdisplay connected_to_x11vnc reply_xdisplay
   6487 	global menu_var unset_str
   6488 
   6489 	set db 0
   6490 #dtime c1
   6491 
   6492 	if {! $connected_to_x11vnc} {
   6493 		if {[info exists menu_var(display)]} {
   6494 			set d $menu_var(display)
   6495 			if {$d != "" && $d != $unset_str && $d != $x11vnc_xdisplay} {
   6496 				set x11vnc_xdisplay $menu_var(display)
   6497 				append_text "Setting X display to: $x11vnc_xdisplay\n"
   6498 			}
   6499 		}
   6500 	}
   6501 
   6502 	set_info "Pinging $x11vnc_xdisplay ..."
   6503 	set rargs [list "-Q" "ping"]
   6504 	set result [run_remote_cmd $rargs]
   6505 #dtime c2a
   6506 
   6507 	if {$db} {puts "try_connect: \"$result\""}
   6508 
   6509 	if {[regexp {^ans=ping:} $result]} {
   6510 		regsub {^ans=ping:} $result {} reply_xdisplay
   6511 		set msg "Connected to $reply_xdisplay"
   6512 		set_info $msg
   6513 		append_text "$msg\n"
   6514 		set_connected yes
   6515 
   6516 		setup_client_channel
   6517 #dtime c2b
   6518 		setup_client_sock 1
   6519 		setup_client_tail
   6520 
   6521 		fetch_displays
   6522 #dtime c3a
   6523 		return 1
   6524 	} else {
   6525 		set str "x11vnc server."
   6526 		if {$x11vnc_xdisplay != ""} {
   6527 			set str $x11vnc_xdisplay
   6528 		}
   6529 		set msg "No reply from $str"
   6530 		set_info $msg
   6531 		append_text "$msg\n"
   6532 		set_connected no
   6533 		return 0
   6534 	}
   6535 }
   6536 
   6537 proc set_view_variable {val} {
   6538 	global menu_var
   6539 	set menu_var(WindowView) $val
   6540 }
   6541 proc get_view_variable {} {
   6542 	global menu_var
   6543 	if {![info exists menu_var(WindowView)]} {
   6544 		set menu_var(WindowView) "none"
   6545 	}
   6546 	return $menu_var(WindowView)
   6547 }
   6548 
   6549 proc dono {a b c} {
   6550 	exit 1;
   6551 }
   6552 
   6553 proc do_port_prompt {} {
   6554 	global bfont ffont
   6555 	global port_reply port_set
   6556 
   6557 	set guess 5900
   6558 	for {set i 0} {$i < 50} {incr i} {
   6559 		set fh ""
   6560 		set try [expr $guess + $i]
   6561 		catch {set fh [socket -server dono $try]}
   6562 		if {$fh != ""} {
   6563 			catch {close $fh}
   6564 			set guess $try
   6565 			break;
   6566 		}
   6567 	}
   6568 	set hn ""
   6569 	catch {set hn [exec uname -n]}
   6570 	if {$hn == ""} {
   6571 		set hn "hostname"
   6572 	}
   6573 
   6574 	set text " Set the x11vnc Listening Port:
   6575 
   6576     VNC Display :0 corresponds to TCP port 5900
   6577     VNC Display :1 corresponds to TCP port 5901
   6578     etc.
   6579 
   6580  In the Entry below, indicate a Port for x11vnc to listen on. 
   6581 
   6582  Note that to connect to x11vnc, a VNC Viewer will need to
   6583  know your selection, for example:
   6584 
   6585     vncviewer $hn:0
   6586     vncviewer $hn:1
   6587     etc.
   6588 
   6589  Your firewall may block incoming connections to TCP ports;
   6590  if it does you may need to reconfigure it. 
   6591     
   6592  You can also set some additional parameters:
   6593 
   6594     - Enable SSL encryption.
   6595       (requires an SSL enabled vncviewer, such as SSVNC)  
   6596     - Listen only on localhost. (e.g. for an SSH tunnel)
   6597     - Enable UltraVNC or TightVNC File transfer.
   6598 "
   6599 	set port_set $guess
   6600 	set port_reply ""
   6601 
   6602 	toplevel .pp
   6603 	wm title .pp "Select x11vnc port"
   6604 
   6605 	wm protocol .   WM_DELETE_WINDOW "destroy .; exit"
   6606 	wm protocol .pp WM_DELETE_WINDOW "destroy .pp; exit"
   6607 
   6608 	label .pp.m -text "$text" -relief ridge -justify left -font $ffont
   6609 
   6610 	global tk_version
   6611 	set tkold 0
   6612 	if [info exists tk_version] {
   6613 		if [regexp {^8\.[0-3]$} $tk_version] {
   6614 			set tkold 1
   6615 		}
   6616 		if [regexp {^[3-7]\.} $tk_version] {
   6617 			set tkold 1
   6618 		}
   6619 	}
   6620 
   6621 	if {$tkold} {
   6622 		frame .pp.f -bd 1 -relief ridge
   6623 	} else {
   6624 		frame .pp.f -bd 1 -relief ridge -pady 2
   6625 	}
   6626 	label .pp.f.l -text "Port: " -font $bfont
   6627 	entry .pp.f.e -width 8 -textvariable port_set -font $ffont
   6628 	global enable_ssl; set enable_ssl 0
   6629 	if [info exists env(X11VNC_SSL_ENABLED)] {
   6630 		set enable_ssl 1
   6631 	}
   6632 	checkbutton .pp.f.ssl -relief raised -pady 3 -padx 3 -text "Enable SSL" -variable enable_ssl -font $bfont
   6633 	global localhost; set localhost 0
   6634 	if [info exists env(X11VNC_LOCALHOST_ENABLED)] {
   6635 		set localhost 1
   6636 	}
   6637 	checkbutton .pp.f.loc -relief raised -pady 3 -padx 3 -text "Listen on localhost" -variable localhost -font $bfont
   6638 	pack .pp.f.l .pp.f.e -side left
   6639 	pack .pp.f.loc .pp.f.ssl -side right
   6640 
   6641 	if {$tkold} {
   6642 		frame .pp.t -bd 1 -relief ridge
   6643 	} else {
   6644 		frame .pp.t -bd 1 -relief ridge -pady 2
   6645 	}
   6646 	global file_transfer; set file_transfer "none"
   6647 	if [info exists env(X11VNC_FILETRANSFER_ENABLED)] {
   6648 		set file_transfer $env(X11VNC_FILETRANSFER_ENABLED)
   6649 	}
   6650 	label .pp.t.l -text "File Transfer: " -font $bfont
   6651 	radiobutton .pp.t.none  -text "None" -variable file_transfer -value "none" -font $bfont
   6652 	radiobutton .pp.t.ultra -text "UltraVNC" -variable file_transfer -value "ultra" -font $bfont
   6653 	radiobutton .pp.t.tight -text "TightVNC" -variable file_transfer -value "tight" -font $bfont
   6654 	pack .pp.t.l .pp.t.none .pp.t.ultra .pp.t.tight -side left
   6655 
   6656 	frame .pp.o -bd 1 -relief ridge
   6657 	button .pp.o.ok -text "OK" -command "set port_reply 1; destroy .pp" -font $bfont
   6658 	button .pp.o.cancel -text "Cancel" -command "set port_reply 0; destroy .pp" -font $bfont
   6659 	pack .pp.o.ok .pp.o.cancel -side left -fill x -expand 1
   6660 	pack .pp.m -side top -fill x -expand 1 
   6661 	pack .pp.f .pp.t .pp.o -side top -fill x
   6662 
   6663 	focus .pp.f.e
   6664 	.pp.f.e icursor end
   6665 
   6666 	wm withdraw .pp
   6667 	update
   6668 	center_win .pp
   6669 
   6670 	wm minsize .pp [winfo width .pp] [winfo height .pp]
   6671 
   6672 	bind .pp.f.e <KeyPress-Return> "set port_reply 1; destroy .pp"
   6673 
   6674 	vwait port_reply
   6675 
   6676 	if {$port_reply} {
   6677 		regsub -all {^:} $port_set "" port_set
   6678 		regsub -all {[ \t]} $port_set "" port_set
   6679 		if {[regexp {^[0-9][0-9]*$} $port_set]} {
   6680 			if {$port_set < 0} {
   6681 				set port_set [expr 0 - $port_set]
   6682 			} elseif {$port_set < 200} {
   6683 				set port_set [expr $port_set + 5900]
   6684 			} 
   6685 			puts "$port_set:ssl${enable_ssl}:localhost$localhost:ft_$file_transfer"
   6686 		}
   6687 	}
   6688 }
   6689 
   6690 proc change_view_state {} {
   6691 	global menu_var gui_current_state
   6692 
   6693 	set new [get_view_variable]
   6694 
   6695 	if {![info exists gui_current_state]} {
   6696 		set gui_current_state ""
   6697 	}
   6698 	set old $gui_current_state
   6699 	#puts "$old -> $new"
   6700 
   6701 	if {$old == $new} {
   6702 		return
   6703 	}
   6704 
   6705 	if {$old == "full" || $old == "icon" || $old == "tray"} {
   6706 		;
   6707 	} else {
   6708 		set old "none"
   6709 	}
   6710 
   6711 	if {$new == "full" || $new == "icon" || $new == "tray"} {
   6712 		if {$old == "tray"} {
   6713 			# sigh XReparentWindow would be too easy...
   6714 			# undo_tray_embed
   6715 			restart_everything $new
   6716 			destroy .
   6717 			exit
   6718 		}
   6719 		make_gui $new
   6720 		if {$new == "tray"} {
   6721 			wm withdraw .
   6722 		}
   6723 	} else {
   6724 		set_view_variable $old
   6725 	}
   6726 }
   6727 
   6728 proc setup_client_tail {} {
   6729 	global client_tail
   6730 	if {$client_tail != ""} {
   6731 		fileevent $client_tail readable read_client_tail
   6732 	}
   6733 }
   6734 
   6735 proc setup_client_sock {{enable 1}} {
   6736 	global client_sock
   6737 	if {$client_sock != ""} {
   6738 		if {$enable} {
   6739 			fileevent $client_sock readable read_client_sock
   6740 		} else {
   6741 			fileevent $client_sock readable ""
   6742 		}
   6743 	}
   6744 }
   6745 
   6746 proc setup_tray_embed {} {
   6747 	update
   6748 	set w [winfo width .]
   6749 	set h [winfo height .]
   6750 	if {$w < 24} {
   6751 		set w 24
   6752 	}
   6753 	if {$h < 24} {
   6754 		set h 24
   6755 	}
   6756 	wm minsize . $w $h
   6757 	set wid [winfo id .]	
   6758 	push_new_value "remote-cmd" "remote-cmd" "trayembed:$wid" 0
   6759 }
   6760 
   6761 proc restart_everything {gui_mode} {
   6762 	global env gui_argv0 x11vnc_prog full_win
   6763 	global icon_mode_at_startup
   6764 	global tray_embed tray_running
   6765 	if {$gui_mode == "full"} {
   6766 		set env(X11VNC_ICON_MODE) 0
   6767 	} elseif {$gui_mode == "icon"} {
   6768 		set env(X11VNC_ICON_MODE) 1
   6769 	} elseif {$gui_mode == "tray"} {
   6770 		if {$tray_running} {
   6771 			set env(X11VNC_ICON_MODE) "RUNNING"
   6772 		} else {
   6773 			set env(X11VNC_ICON_MODE) "TRAY"
   6774 		}
   6775 	}
   6776 	puts stderr ""
   6777 	puts stderr "tkx11vnc: restarting gui to leave tray mode."
   6778 	puts stderr "  new gui will be running in the background."
   6779 	puts stderr "  use kill(1) rather than Ctrl-C to kill it."
   6780 	puts stderr ""
   6781 	if {[info exists env(X11VNC_RESTART_DEPTH)]} {
   6782 		set n $env(X11VNC_RESTART_DEPTH)
   6783 		incr n
   6784 		set env(X11VNC_RESTART_DEPTH) $n
   6785 	} else {
   6786 		set env(X11VNC_RESTART_DEPTH) 0
   6787 	}
   6788 	set env(X11VNC_ICON_SETPASS) ""
   6789 
   6790 	if {![info exists env(X11VNC_WISHCMD)]} {
   6791 		puts stderr "failure in restart_everything."
   6792 		exit 1;
   6793 	}
   6794 
   6795 	set code [exec $x11vnc_prog -printgui]
   6796 	if {[string length $code] < 20000} {
   6797 		puts stderr "failure in restart_everything."
   6798 		exit 1;
   6799 	}
   6800 	set tmp "/tmp/x11vnc[pid]"
   6801 	append tmp [clock clicks]
   6802 	set tmp2 ""
   6803 	catch {set tmp2 [exec mktemp $tmp.XXXXXX 2>/dev/null]}
   6804 	if {$tmp2 != "" && [file exists $tmp2]} {
   6805 		set tmp $tmp2
   6806 	} else {
   6807 		file delete -force $tmp
   6808 		if {[file exists $tmp]} {
   6809 			puts stderr "failure in restart_everything."
   6810 			exit 1;
   6811 		}
   6812 	}
   6813 	set fh [open $tmp "a"]
   6814 	if {![file owned $tmp]}  {
   6815 		puts stderr "failure in restart_everything."
   6816 		exit 1;
   6817 	}
   6818 	file attributes $tmp -permissions "0400"
   6819 	puts $fh $code
   6820 	close $fh
   6821 
   6822 	#puts stderr [exec ls -l $tmp]
   6823 
   6824 	wm withdraw .
   6825 	catch {wm withdraw $full_win}
   6826 	update
   6827 
   6828 	exec $env(X11VNC_WISHCMD) $tmp &
   6829 	after 2000
   6830 	file delete -force $tmp
   6831 	
   6832 	destroy .
   6833 	exit
   6834 }
   6835 
   6836 proc undo_tray_embed {} {
   6837 	set wid [winfo id .]	
   6838 	push_new_value "remote-cmd" "remote-cmd" "trayunembed:$wid" 0
   6839 }
   6840 
   6841 ############################################################################
   6842 # main:
   6843 
   6844 if [info exists env(X11VNC_GUI_TIME)] {
   6845 	dtime M
   6846 }
   6847 
   6848 wm withdraw .
   6849 
   6850 global env x11vnc_prog x11vnc_cmdline x11vnc_xdisplay x11vnc_connect;
   6851 global x11vnc_xdisplay0
   6852 global x11vnc_client_file x11vnc_gui_geom x11vnc_started vnc_url
   6853 global x11vnc_gui_params
   6854 global x11vnc_auth_file x11vnc_connect_file beginner_mode simple_gui_created
   6855 global helpall helptext helpremote helplabel hostname osname
   6856 global all_settings reply_xdisplay always_update
   6857 global max_text_height max_text_width
   6858 global text_height
   6859 global menu_var unset_str menus_disabled
   6860 global bfont ffont sfont snfont old_labels have_labelframes
   6861 global connected_to_x11vnc
   6862 global cache_all_query_vars
   6863 global last_query_all_time query_all_freq client_tail client_sock client_info_read
   6864 global icon_mode icon_mode_at_startup x11vnc_icon_mode
   6865 global tray_embed tray_running icon_setpasswd icon_embed_id
   6866 global icon_noadvanced icon_minimal
   6867 global make_gui_count text_area_str
   6868 global gui_argv0 gui_start_mode
   6869 global screen_height screen_width
   6870 
   6871 set unset_str "(unset)"
   6872 set vnc_url $unset_str
   6873 set connected_to_x11vnc 0
   6874 set menus_disabled 0
   6875 set max_text_height 40
   6876 set max_text_width 90
   6877 set text_height 14
   6878 set bfont "-adobe-helvetica-bold-r-*-*-*-120-*-*-*-*-*-*"
   6879 set sfont "-adobe-helvetica-bold-r-*-*-*-100-*-*-*-*-*-*"
   6880 set snfont "-adobe-helvetica-medium-r-*-*-*-100-*-*-*-*-*-*"
   6881 set ffont "fixed"
   6882 
   6883 set got_helv 0
   6884 catch {
   6885 	foreach fam [font families]  {
   6886 		if {$fam == "helvetica"} {
   6887 			set got_helv 1
   6888 		}
   6889 		if {$fam == "Helvetica"} {
   6890 			set got_helv 1
   6891 		}
   6892 	}
   6893 }
   6894 
   6895 if {$got_helv} {
   6896 	set bfont  "Helvetica -12 bold"
   6897 	set sfont  "Helvetica -10 bold"
   6898 	set snfont "Helvetica -10"
   6899 }
   6900 
   6901 set ls ""
   6902 catch {set ls [font metrics $bfont -linespace]}
   6903 if {$ls != "" && $ls > 14} {
   6904 	# some recent setups have BIG rendering for the above fonts.
   6905 	# on recent (8/08) debian these are really ragged:
   6906 	set bfont "-adobe-helvetica-bold-r-*-*-*-90-*-*-*-*-*-*"
   6907 	set sfont "-adobe-helvetica-bold-r-*-*-*-75-*-*-*-*-*-*"
   6908 	set snfont "-adobe-helvetica-medium-r-*-*-*-75-*-*-*-*-*-*"
   6909 
   6910 	set ls ""
   6911 	catch {set ls [font metrics $bfont -linespace]}
   6912 	if {$ls != "" && $ls < 14} {
   6913 		# these are bigger but look better... but for how long?
   6914 		set bfont "-adobe-helvetica-bold-r-*-*-*-100-*-*-*-*-*-*"
   6915 		set sfont "-adobe-helvetica-bold-r-*-*-*-80-*-*-*-*-*-*"
   6916 		set snfont "-adobe-helvetica-medium-r-*-*-*-80-*-*-*-*-*-*"
   6917 
   6918 		# maybe consider... {-font font Font {Helvetica -12 bold} {Helvetica -12 bold}}
   6919 		# or stick with system font like ssvnc.
   6920 	}
   6921 }
   6922 
   6923 # need to check if "fixed" font under XFT on tk8.5 is actually fixed width!!
   6924 set ls ""
   6925 catch {set ls [font metrics $ffont -linespace]}
   6926 set fs ""
   6927 catch {set fs [font metrics $ffont -fixed]}
   6928 set redo 0
   6929 if {$fs != "" && $fs != "1"} {
   6930 	set redo 1
   6931 }
   6932 if {$ls != "" && $ls > 14} {
   6933 	set redo 1
   6934 }
   6935 if {$redo} {
   6936 	foreach fn [font names] {
   6937 		if {$fn == "TkFixedFont"} {
   6938 			set ffont $fn
   6939 			break
   6940 		}
   6941 	}
   6942 }
   6943 
   6944 set help_indent 24;
   6945 set reply_xdisplay ""
   6946 set all_settings "None so far."
   6947 set always_update 1
   6948 set cache_all_query_vars ""
   6949 set query_all_freq 120
   6950 set last_query_all_time [clock seconds]
   6951 set client_tail ""
   6952 set client_sock ""
   6953 set client_info_read 0
   6954 set make_gui_count 0
   6955 set text_area_str ""
   6956 set gui_argv0 $argv0
   6957 set gui_start_mode ""
   6958 
   6959 if {$tk_version < 8.0} {
   6960 	puts stderr ""
   6961 	puts stderr "*** tkx11vnc: tk version is old $tk_version, please use 8.0 or higher."
   6962 	puts stderr "***           will try to continue with reduced functionality..."
   6963 	puts stderr ""
   6964 }
   6965 if {[regexp {^[34]} $tk_version] || $tk_version == "8.0"} {
   6966 	set old_labels 1
   6967 } else {
   6968 	set old_labels 0
   6969 }
   6970 set have_labelframes 1
   6971 if {$tk_version < 8.4} {
   6972 	set have_labelframes 0
   6973 }
   6974 
   6975 set screen_height [winfo screenheight .]
   6976 set screen_width  [winfo screenwidth  .]
   6977 if {$screen_height < 700} {
   6978 	# short screen, netbook?
   6979 	set max_text_height 30
   6980 	if {$screen_height < 500} {
   6981 		# short screen, PDA?
   6982 		set max_text_height 22
   6983 		set text_height 13
   6984 		if {$screen_height <= 360} {
   6985 			# very short.
   6986 			set max_text_height 16
   6987 			set max_text_width  60
   6988 			set text_height 11
   6989 		}
   6990 	}
   6991 }
   6992 if {[info exists env(X11VNC_GUI_TEXT_HEIGHT)]} {
   6993 	set max_text_height $env(X11VNC_GUI_TEXT_HEIGHT)
   6994 }
   6995 if {[info exists env(X11VNC_GUI_TEXT_WIDTH)]} {
   6996 	set max_text_width  $env(X11VNC_GUI_TEXT_WIDTH)
   6997 }
   6998 
   6999 if {"$argv" == "-spit"} {
   7000 	set fh [open $argv0 r]
   7001 	puts "#ifndef _TKX11VNC_H"
   7002 	puts "#define _TKX11VNC_H"
   7003 	puts "#ifdef NOGUI"
   7004 	puts "char gui_code\[\] = \"\";"
   7005 	puts "#else"
   7006 	puts "/*"
   7007 	puts " * tkx11vnc.h: generated by 'tkx11vnc -spit'"
   7008 	puts " * Abandon all hope, ye who enter here..."
   7009 	puts " * ...edit tkx11vnc instead."
   7010 	puts " */"
   7011 	puts "	char gui_code\[\] ="
   7012 	while {[gets $fh line] > -1} {
   7013 		regsub -all {\\} $line {\\\\} line
   7014 		regsub -all {"} $line {\\"} line
   7015 		puts "\"$line\\n\""
   7016 	}
   7017 	puts "#endif"
   7018 	puts "/* ifdef NOGUI */"
   7019 	puts "#endif"
   7020 	puts "/* ifndef _TKX11VNC_H */"
   7021 	close $fh
   7022 	puts ";"
   7023 	exit 0
   7024 }
   7025 
   7026 set_view_variable "full"
   7027 
   7028 #puts [exec env | grep X11VNC]
   7029 
   7030 # Read environment for clues:
   7031 
   7032 set x11vnc_client_file "";
   7033 if {[info exists env(X11VNC_CLIENT_FILE)]} {
   7034 	set x11vnc_client_file $env(X11VNC_CLIENT_FILE);
   7035 	set file $x11vnc_client_file
   7036 
   7037 	set client_tail ""
   7038 	if {[file exists $file] && [file isfile $file]} {
   7039 		if {[file readable $file] && [file owned $file]} {
   7040 			set client_tail [open "|tail -f $x11vnc_client_file" "r"]
   7041 		}
   7042 	}
   7043 	if {$client_tail != ""} {
   7044 		gets $client_tail tmp
   7045 		if [eof $client_tail] {
   7046 #puts "eof $client_tail"
   7047 			clean_client_tail
   7048 			set client_tail ""
   7049 		}
   7050 	}
   7051 	catch {file delete -force $x11vnc_client_file}
   7052 }
   7053 
   7054 if {[info exists env(X11VNC_PROG)]} {
   7055 	set x11vnc_prog $env(X11VNC_PROG);
   7056 } else {
   7057 	set x11vnc_prog "x11vnc";
   7058 }
   7059 
   7060 if {[info exists env(X11VNC_CMDLINE)]} {
   7061 	set x11vnc_cmdline $env(X11VNC_CMDLINE);
   7062 } else {
   7063 	set x11vnc_cmdline "";
   7064 }
   7065 
   7066 if {[info exists env(X11VNC_CONNECT)]} {
   7067 	set x11vnc_connect 1
   7068 } else {
   7069 	set x11vnc_connect 0;
   7070 }
   7071 
   7072 if {[info exists env(X11VNC_GUI_GEOM)]} {
   7073 	set x11vnc_gui_geom $env(X11VNC_GUI_GEOM);
   7074 } else {
   7075 	set x11vnc_gui_geom ""
   7076 }
   7077 if {[info exists env(X11VNC_GUI_PARAMS)]} {
   7078 	set x11vnc_gui_params $env(X11VNC_GUI_PARAMS);
   7079 } else {
   7080 	set x11vnc_gui_params ""
   7081 }
   7082 
   7083 if {[info exists env(X11VNC_FONT_BOLD)]} {
   7084 	set bfont $env(X11VNC_FONT_BOLD)
   7085 }
   7086 if {[info exists env(X11VNC_FONT_BOLD_SMALL)]} {
   7087 	set sfont $env(X11VNC_FONT_BOLD_SMALL)
   7088 }
   7089 if {[info exists env(X11VNC_FONT_REG_SMALL)]} {
   7090 	set snfont $env(X11VNC_FONT_REG_SMALL)
   7091 }
   7092 if {[info exists env(X11VNC_FONT_FIXED)]} {
   7093 	set ffont $env(X11VNC_FONT_FIXED)
   7094 }
   7095 
   7096 if {[info exists env(X11VNC_CONNECT_FILE)]} {
   7097 	set x11vnc_connect_file $env(X11VNC_CONNECT_FILE);
   7098 } else {
   7099 	set x11vnc_connect_file "";
   7100 }
   7101 
   7102 set x11vnc_started 0
   7103 if {[info exists env(X11VNC_STARTED)]} {
   7104 	set x11vnc_started 1
   7105 }
   7106 
   7107 set x11vnc_xdisplay ""
   7108 if {[info exists env(X11VNC_XDISPLAY)]} {
   7109 	set x11vnc_xdisplay $env(X11VNC_XDISPLAY);
   7110 	set x11vnc_connect 1
   7111 
   7112 } elseif {$argv != "" && [regexp {:[0-9]} $argv]} {
   7113 	set env(X11VNC_XDISPLAY) "$argv"
   7114 	set x11vnc_xdisplay "$argv"
   7115 	set x11vnc_connect 1
   7116 
   7117 } elseif {[info exists env(DISPLAY)]} {
   7118 	set x11vnc_xdisplay $env(DISPLAY);
   7119 } else {
   7120 	set x11vnc_xdisplay ":0";
   7121 }
   7122 set x11vnc_xdisplay0 $x11vnc_xdisplay
   7123 
   7124 if {[info exists env(X11VNC_AUTH_FILE)]} {
   7125 	set x11vnc_auth_file $env(X11VNC_AUTH_FILE)
   7126 } else {
   7127 	set x11vnc_auth_file ""
   7128 }
   7129 
   7130 set simple_gui_created 0
   7131 if {[info exists env(X11VNC_SIMPLE_GUI)]} {
   7132 	set beginner_mode 1
   7133 } else {
   7134 	set beginner_mode 0
   7135 }
   7136 
   7137 set icon_mode 0
   7138 set x11vnc_icon_mode 0
   7139 set tray_embed 0
   7140 set tray_running 0
   7141 
   7142 if {![info exists env(X11VNC_ICON_MODE_AT_STARTUP)]} {
   7143 	if {[info exists env(X11VNC_ICON_MODE)]} {
   7144 		if {$env(X11VNC_ICON_MODE) != 0} {
   7145 			set env(X11VNC_ICON_MODE_AT_STARTUP) 1
   7146 		} else {
   7147 			set env(X11VNC_ICON_MODE_AT_STARTUP) 0
   7148 		}
   7149 	} else {
   7150 		set env(X11VNC_ICON_MODE_AT_STARTUP) 0
   7151 	}
   7152 }
   7153 set icon_mode_at_startup $env(X11VNC_ICON_MODE_AT_STARTUP)
   7154 
   7155 if {![info exists env(X11VNC_ICON_MODE)]} {
   7156 	set icon_mode 0
   7157 } elseif {$env(X11VNC_ICON_MODE) == "" || $env(X11VNC_ICON_MODE) == "0"} {
   7158 	set icon_mode 0
   7159 } else {
   7160 	set icon_mode 1
   7161 	set_view_variable "icon"
   7162 	if [regexp -nocase {TRAY} $env(X11VNC_ICON_MODE)] {
   7163 		set tray_embed 1
   7164 	}
   7165 	if [regexp -nocase {RUNNING} $env(X11VNC_ICON_MODE)] {
   7166 		set tray_running 1
   7167 	}
   7168 }
   7169 
   7170 set icon_setpasswd 0
   7171 if {[info exists env(X11VNC_ICON_SETPASS)]} {
   7172 	if {$env(X11VNC_ICON_SETPASS) != ""} {
   7173 		set icon_setpasswd 1
   7174 	}
   7175 }
   7176 
   7177 set icon_noadvanced 0
   7178 if {[info exists env(X11VNC_ICON_NOADVANCED)]} {
   7179 	set icon_noadvanced 1
   7180 }
   7181 
   7182 set icon_minimal 0
   7183 if {[info exists env(X11VNC_ICON_MINIMAL)]} {
   7184 	set icon_minimal 1
   7185 }
   7186 
   7187 if {[info exists env(X11VNC_ICON_EMBED_ID)]} {
   7188 	set icon_embed_id $env(X11VNC_ICON_EMBED_ID)
   7189 } else {
   7190 	set icon_embed_id ""
   7191 }
   7192 
   7193 
   7194 set hostname [exec uname -n]
   7195 set osname [exec uname]
   7196 
   7197 if {[regexp -nocase {IRIX} $osname]} {
   7198 	# IRIX "fixed" font is huge and doublespaced... 
   7199 	set ffont $snfont
   7200 }
   7201 if {[regexp -nocase {Darwin} $osname]} {
   7202 	set ffont {Monaco 10}
   7203 	set bfont {system}
   7204 }
   7205 
   7206 if {"$argv" == "-portprompt"} {
   7207 	do_port_prompt
   7208 	exit 0
   7209 }
   7210 
   7211 #puts [exec env]
   7212 #puts "x11vnc_xdisplay: $x11vnc_xdisplay"
   7213 
   7214 set env(X11VNC_STD_HELP) 1
   7215 
   7216 # scrape the help output for the text and remote control vars:
   7217 parse_help;
   7218 parse_remote_help;
   7219 parse_query_help;
   7220 
   7221 # tweaks to duplicate help text:
   7222 tweak_remote_help lock deny
   7223 tweak_remote_help unlock deny
   7224 
   7225 tweak_both quiet q
   7226 tweak_help logfile o
   7227 tweak_both xwarppointer xwarp
   7228 tweak_both screen_blank sb
   7229 
   7230 set_template
   7231 
   7232 set_name "tkx11vnc"
   7233 
   7234 key_bindings;
   7235 
   7236 get_default_vars
   7237 
   7238 dtime D
   7239 
   7240 proc check_setpasswd {} {
   7241 	global env icon_setpasswd
   7242 	global do_props_msg
   7243 	set do_props_msg ""
   7244 	if {$icon_setpasswd} {
   7245 		set m "\n"
   7246 		set m "${m} Note the x11vnc icon in the system tray.\n" 
   7247 		set m "${m} This panel is its 'Properties' dialog.\n" 
   7248 		set m "${m}\n" 
   7249 		set m "${m} To specify a Session Password and to\n" 
   7250 		set m "${m} allow VNC viewers to connect, follow\n" 
   7251 		set m "${m} these steps:\n" 
   7252 		set m "${m}\n" 
   7253 		set m "${m} Enter a passwd in the Password field\n" 
   7254 		set m "${m} (it can be left blank.)  You can also\n" 
   7255 		set m "${m} supply a ViewOnly passwd if desired.\n" 
   7256 		set m "${m}\n" 
   7257 		set m "${m} Set 'Accept Connections' and then Press \n" 
   7258 		set m "${m} 'Apply' to allow incoming connections.\n" 
   7259 		set m "${m}\n" 
   7260 		set m "${m} No Viewer can connect until you do this.\n" 
   7261 		set m "${m}\n" 
   7262 		set m "${m} The passwords are only for this x11vnc\n" 
   7263 		set m "${m} session and are not saved.  Run x11vnc\n" 
   7264 		set m "${m} manually for more control (e.g. -rfbauth \n" 
   7265 		set m "${m} for a saved password.)\n" 
   7266 		set m "${m}\n" 
   7267 		set m "${m} See 'Help' for details on each option.\n" 
   7268 
   7269 		global x11vnc_cmdline
   7270 
   7271 		set dossl 0
   7272 		if {[info exists x11vnc_cmdline]} {
   7273 			if [regexp -- {-ssl} $x11vnc_cmdline] {
   7274 				set dossl 1
   7275 			}
   7276 		}
   7277 		if {$dossl || [info exists env(X11VNC_GOT_SSL)]} {
   7278 			set m "${m}\n" 
   7279 			set m "${m} SSL encryption mode active.  You can\n" 
   7280 			set m "${m} find your Public Cert in the Logfile\n" 
   7281 			set m "${m} and also the ~/.vnc/certs directory.\n" 
   7282 		}
   7283 
   7284 		if {[info exists env(X11VNC_SETPASS_FAIL)]} {
   7285 			set pp 5900
   7286 			if {[info exists env(X11VNC_GOT_RFBPORT_VAL)]} {
   7287 				if {$env(X11VNC_GOT_RFBPORT_VAL) > 0} {
   7288 					set pp $env(X11VNC_GOT_RFBPORT_VAL)
   7289 				}
   7290 			}
   7291 			
   7292 			set m     " The x11vnc program failed to start! \n"
   7293 			set m "${m}\n" 
   7294 			set m "${m} Maybe there is another VNC server\n"
   7295 			set m "${m} already listening on port $pp?\n"
   7296 			set m "${m}\n" 
   7297 			set m "${m} You will need to start over after\n"
   7298 			set m "${m} you make sure x11vnc can start.\n"
   7299 		}
   7300 		
   7301 		set do_props_msg $m
   7302 		do_props
   7303 	}
   7304 }
   7305 
   7306 if {0} {
   7307 	if {[info exists env(X11VNC_ICON_SETPASS)]} {
   7308 		if {$env(X11VNC_ICON_SETPASS) == "2"} {
   7309 			global icon_mode_at_startup icon_mode
   7310 			set icon_mode_at_startup 1
   7311 			set icon_mode 2
   7312 		}
   7313 	}
   7314 }
   7315 
   7316 if {$icon_mode} {
   7317 	if {$icon_mode == 2} {
   7318 		make_gui "full"
   7319 	} elseif {$tray_embed} {
   7320 		make_gui "tray"
   7321 	} else {
   7322 		make_gui "icon"
   7323 	}
   7324 	dtime G
   7325 	old_balloon
   7326 	check_setpasswd
   7327 	push_new_value "remote-cmd" "remote-cmd" "Q:clients" 1
   7328 } else {
   7329 	make_gui "full"
   7330 	dtime G
   7331 	check_setpasswd
   7332 }
   7333 
   7334 
   7335 # main loop.
   7336