1#!/bin/sh
2# the next line restarts using wish. \
3exec wish "$0" "$@"
4catch {rename send {}}
5#
6# Copyright (C) 2004-2009 Karl J. Runge <runge@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
61global env started time_count
62set started ""
63proc 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
78if [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
85proc set_template {} {
86	global template
87	set template "
88Row: Actions   Clients   Permissions  Keyboard    Pointer  Help
89Row: Displays  Screen    Tuning       Debugging   Misc
90
91Actions
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
113Help
114	=DGA gui
115	=DGA all
116
117Clients
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
145Displays
146	=D display:
147	=F auth:
148	=S reflect:
149	=D desktop:
150	=D rfbport:
151	=S autoport:
152	=0 gui:
153
154Screen
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
203Keyboard
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
222Pointer
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
243Misc
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
287Debugging
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
309Permissions
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
366Tuning
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
439proc set_internal_help {} {
440	global helptext helpall
441
442	# set some internal item help here:
443	set helptext(start) "
444Launch x11vnc with the settings you have prescribed in the gui.
445The x11vnc process is started in an xterm window so you can see the
446output, kill it, etc.
447
448By viewing this help item, the command built so far will be displayed
449in the gui text area.  Have a look.  If you Press start it will be shown
450as well and you will be asked to confirm running it.
451
452If you want to use a saved profile \"rc file\" you can do \"Misc -> rc\" and
453select the file and simply start x11vnc using the rc file.  Alternatively,
454you could first use the \"Actions -> load-settings\" action to load in
455an \"rc file\" and then press \"Actions -> start\" to start up x11vnc
456based on those values.
457"
458	set helptext(stop) "
459The \"Actions -> stop\" action sends a signal to the running x11vnc
460server indicating it should shutdown all connections and exit.
461
462The GUI stays running in case you want to start a new x11vnc or attach
463to another one.  Use \"Actions -> Quit\" if you then want to have the
464gui exit. Use \"Actions -> stop+quit\" to have both exit at once.
465"
466
467	set helptext(show-start-cmd) "
468Displays in the text area what the x11vnc start command (i.e. the command
469run by \"Actions -> start\") looks like for the current values of the
470settings.  This can be done even in the attached state.  Intended for
471debugging the gui.  The help item for \"Actions -> start\" gives the
472same info.
473
474If you want to load in a saved profile \"rc file\" use \"Misc -> rc\"
475and select the file.  \"Actions -> load-settings\" does a similar thing
476with an rc-file, but reading the file and setting the gui variables to
477its values.
478"
479
480	set helptext(debug_gui) "
481Set debug_gui to get more output printed in the text area.
482"
483
484	set helptext(detach) "
485No longer be associated with the x11vnc server.  Switch to the
486non-connected state.  The x11vnc server keeps running: it does not exit.
487
488You can either later reattach to it \"Actions -> attach\", or start
489up a new x11vnc \"Actions -> start\", or exit \"Actions -> Quit\".
490"
491
492	set helptext(attach) "
493Attach to a running x11vnc server, if possible.  Switches to connected
494state if successful.  Usually the channel used to attach is via the X
495display (VNC_CONNECT rootwin property) being polled by the x11vnc server.
496To change or set the X display to use do \"Displays -> display\".
497
498Sometimes the \"-connect /path/to/filename\" is used as the communcation
499channel.  The running x11vnc has to know that \"/path/to/filename\"
500is the communication channel (i.e. it is using the same -connect option).
501"
502
503	set helptext(ping) "
504Check if x11vnc still responds to \"ping\" remote command.
505"
506
507	set helptext(update-all) "
508Query the x11vnc server for the current values of all variables.
509Populate the values into the gui's database.
510
511Normally the gui will refresh this info every time it interacts with
512the x11vnc server (including after a few minutes of inactivity), so one
513doesn't need to use this action very often (unless something else is
514changing the state of the x11vnc server, or new clients have connected,
515etc).
516"
517
518	set helptext(clear-all) "
519Forget any variable settings either entered in by you or set at the
520default.  Basically sets everything to 0 or the string (unset).
521
522This action is only available in \"startup\" mode, not when connected
523to a running x11vnc server (in that case the variable settings reflect
524the state of the running x11vnc).  To detach from a running x11vnc
525server use \"Actions -> detach\"; to completely stop the x11vnc server
526use \"Actions -> stop\".
527"
528
529	set helptext(defaults-all) "
530Reset all variable settings to the default values.  Basically sets
531everything to the default queries \"x11vnc -QD var\" retrieved at startup.
532
533This action is only available in \"startup\" mode, not when connected
534to a running x11vnc server (in that case the variable settings reflect
535the state of the running x11vnc).  To detach from a running x11vnc
536server use \"Actions -> detach\"; to completely stop the x11vnc server
537use \"Actions -> stop\".
538"
539
540	set helptext(load-settings) "
541Read in the \"rc file\" you prescribe in the dialog and then set the
542variables to those in the rc-file.  Any variables not mentioned in the
543rc-file are set to their default value.
544
545You could then do \"Actions -> start\" to start x11vnc with these
546parameters.  Or you could make some further changes to variables
547using the gui before starting x11vnc.
548
549This action is only available in \"startup\" mode, not when connected
550to a running x11vnc server (in that case the variable settings reflect
551the state of the running x11vnc).  To detach from a running x11vnc
552server use \"Actions -> detach\"; to completely stop the x11vnc server
553use \"Actions -> stop\".
554"
555
556	set helptext(save-settings) "
557Construct a ~/.x11vncrc file based on the current settings and
558offer to save it in a file (default ~/.x11vncrc).  If saved in a
559file other than the default, you can access the profile by using
560the \"-rc <filename>\" option when starting x11vnc.
561
562If an rc file entry begins with \"#d\" that means the current
563setting is at the Default value and so you probably want to leave
564it commented out with the \"#\" character.
565
566If an rc file entry begins with \"#?\" that means we think
567you probably do not really want to force the value to this setting.
568
569In either case, feel free to uncomment the line and/or change any
570of the parameter values in the file.
571"
572
573	set helptext(all-settings) "
574Displays the gui's database of all of the x11vnc server's current
575settings.  Use \"Actions -> update-all\"  or \"Control+R\" to
576refresh this list if it ever gets out of sync.
577"
578
579	set helptext(remote-cmd) "
580Run a remote command (-R) or query (-Q) directly.  Only a few
581remote commands are not on a menu, but for those few you can
582run the command directly this way.  Just enter the command into
583the Entry box when prompted.  Use the prefix \"Q:\" to indicate
584a -Q query.  Examples: \"zero:20,20,100,100\", \"Q:ext_xfixes\"
585"
586
587	set helptext(stop+quit) "
588Send the stop command to the x11vnc server, then terminate the tkx11vnc gui.
589"
590
591	set helptext(show-logfile) "
592View the current contents of the logfile (if it exists and is accessible
593by the gui process).
594"
595
596	set helptext(tail-logfile) "
597Run 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) "
602Terminate the tkx11vnc gui.  Any x11vnc server will be left running.
603"
604
605	set helptext(current) "
606Shows a menu of currently connected VNC clients on the x11vnc server.
607
608Allows you to find more information about them, change their input
609permissions, or disconnect them.
610
611Note that the File transfer permission only applies to UltraVNC
612file transfer, not TightVNC file transfer.
613
614You will be prompted to confirm any disconnections.
615"
616
617	set helptext(client) "
618After selecting a VNC client from the \"Clients -> current\" menu,
619you will be presented with a dialog that shows the information
620about the VNC client.
621
622You can choose to disconnect the client by clicking on the
623\"Disconnect\" checkbox and pressing \"OK\".  There will be a
624confirmation dialog to doublecheck.
625
626Alternatively, you can fine tune the VNC client's input permissions
627by selecting any of the Keystrokes, Mouse-Motion, Button-Click,
628Clipboard-Input, or Files checkboxes and pressing \"OK\".  This is like
629the \"-input\" option but on a per-client basis.
630
631To not change any aspects of the VNC client press \"Cancel\".
632"
633
634	set helptext(solid_color) "
635Set the -solid color value.
636"
637
638	set helptext(xrandr_mode) "
639Set the -xrandr mode value.
640"
641
642	set helptext(unixpw_list) "
643Set the -unixpw usernames list value.
644"
645
646	set helptext(unixpw_nis_list) "
647Set the -unixpw_nis usernames list value.
648"
649
650	set helptext(stunnel_pem) "
651Set the -stunnel pem filename value.
652"
653
654	set helptext(ssl_pem) "
655Set the -ssl pem filename value.
656"
657
658	set helptext(wireframe_mode) "
659Set the -wireframe mode string value.
660"
661
662	set helptext(simple-gui) "
663Toggle between menu items corresponding the most basic ones
664and all possible settings.  I.e. toggle between a simple gui
665and one for power users.
666"
667
668	set helptext(Tray) "
669The tray/icon mode (started with \"x11vnc -gui tray ...\", etc.) presents
670a small icon that indicates the status of the running x11vnc server.
671
672Depending on your environment, this icon may be embedded in a system
673tray or applet dock, or simply be a standalone window.  \"-gui tray\"
674will attempt to embed the icon in the system tray, while \"-gui icon\"
675is for a standalone window.  Use \"-gui tray=setpass\" (or icon=setpass)
676to be prompted to set the session password at startup.
677
678When the icon has a light background, that means no VNC viewers are
679currently connected to the VNC display.
680
681When the icon has a dark background (i.e. reverse-video), that means at
682least one VNC viewer is connected to the VNC display.
683
684Moving the mouse pointer over the icon will popup a \"status balloon\"
685indicating the VNC display name and the names and info of any connected VNC
686viewers.  Press the middle mouse button if the balloon does not appear.
687
688Clicking the left or right mouse button on the icon displays a menu
689of 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
738Termination:
739
740If the x11vnc server stops for any reason, the tray/icon gui will exit.
741
742If you delete the tray/icon (e.g. X out button), that is the same
743as the \"Stop x11vnc\" action in the menu. (This will disconnect any
744VNC viewer you are currently using to access the display since the
745x11vnc server is terminated).
746
747To terminate the tray/icon gui window but not the x11vnc server press
748Control-C on the tray/icon window.  You can also do this (and much
749more) 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) "
765The Properties dialog allows you to set some basic parameters of a
766running x11vnc server.  After modifying them press \"OK\" or \"Apply\"
767to 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
850Don'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:) "
884x11vnc has what seems like hundreds of tuning parameters!  In this
885sub-menu we place some lesser used ones.  Most likely you'll want to
886leave them at their default values, but you can try them out quickly
887with the gui to see if they improve things.
888"
889
890	set helptext(Passwords:) "
891The items in this sub-menu pertain to setting passwords.  Note that x11vnc
892has two types of password files: RealVNC-style ones (you can create them
893with x11vnc -storepasswd or other VNC utility program) you use these
894via -rfbauth; and plain-text file passwords you use via -passwdfile.
895
896Normally passwords cannot be changed by remote-control (e.g. the gui),
897but for the case of the \"Icon\" and \"Tray\" modes this constraint has
898been relaxed.
899
900In neither the RealVNC-style nor the plain-text file cases should the
901password files be readable by users you do not want to access the VNC
902server.  Contrary to popular belief, the  RealVNC-style passwords are
903not encrypted, merely obscured.
904
905x11vnc has the even less secure -passwd and -viewpasswd supplied on
906the command line.  Be careful with these since they could be read by
907users with something like the ps(1) command.  On some operating systems
908x11vnc tries to quickly overwrite them on the command line but it doesn't
909work everywhere.
910
911Regarding ViewOnly passwords (where a VNC client using that password
912can only watch the screen, not interact with it), this is not available
913with -rfbauth, but only with -passwdfile, -passwd, and -viewpasswd.
914"
915
916	set helptext(SSL:) "
917In this sub-menu we provide the options related to SSL encrpytion
918and authentication.
919
920There is a built-in mode (-ssl) using the OpenSSL library, and a 2nd
921using the external stunnel program (-stunnel, that needs to be installed
922on the system).  Either may require or benefit from having PEM certificate
923files specified.
924
925"
926
927	set helptext(Misc-Perms:) "
928In this sub-menu we provide some lesser used permission options.
929
930Regarding -alwaysshared, -nevershared, and -dontdisconnect, you probably
931should never use them and just use x11vnc's -shared and -forever options
932instead (these give basically the same functionality and if you mixed
933them too much unexpected things may happen).
934"
935#'
936
937	set helptext(AlphaBlending:) "
938In this sub-menu we provide some tweak parameters for cursors (little
939icon at the mouse pointer) that have transparency (i.e. an Alpha channel
940in addition to Red, Green, and Blue RGB channels).  For these cursors,
941some of the graphics underneath the cursor is allowed to be blended in:
942e.g. a drop-shadow (a terrible effect IMNSHO).
943
944AlphaBlending for x11vnc is only available when the XFIXES X extension is
945present (since otherwise it cannot see the cursors at all and so applies
946heuristics to show some fake cursors).  AlphaBlending is only a problem
947with x11vnc when the cursors are not opaque.
948
949Opaque cursors (e.g. bitmap or simply colored cursor) are rendered
950correctly by x11vnc.  Only when there is transparency does x11vnc have
951to make some approximation to transform the cursor to be opaque (the
952VNC protocol does not provide for an alpha channel in cursors, only RGB).
953
954The items in this sub-menu let you tweak x11vnc's approximation scheme
955for cursors with transparency.  Hopefully you won't have to use them.
956Certain cursor \"themes\" may require adjustment however.
957"
958#'
959	set helptext(OverlayVisuals:) "
960In this sub-menu are some options that involve fixing color problems
961for \"Overlay\" or \"Multi-Depth\" visuals.  This problem is rare
962since overlay and multi-depth visual video hardware is rare.
963Some Sun, SGI, and HP machines are known to have them.
964
965The short answer is if you have a multi-depth visual display (e.g.  8 and
96624 bits), and you see messed up colors in x11vnc try the \"-overlay\"
967option on Solaris or IRIX.
968
969A 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
992OK, now, finally, to the Overlay Visuals.  Some hardware (or software
993emulations) allow different depth visuals to be used on the display
994at the same time.  The pixels of windows using different depth visuals
995may overlap.
996
997The most common seems to be both 8 and 24 depth visuals on a 32bpp setup.
99824 of the pixels can be used for one visual and the remaining 8 for the
999other.  This is sometimes referred to as \"8+24\" mode.  Furthermore,
1000a speedup is achieved because writing graphics data to, say, the 8bit
1001visual does not destroy the image data in the 24bit visual.  Evidently
1002popup menus can be done very quickly this way: they use the 8bit visual
1003and when the popup goes away the graphics data in the 24bit visual is
1004immediately reexposed without having the application redraw it.
1005
1006Also, some legacy applications can only use 8bpp visuals.  But in these
1007days of high color graphics and web browsers one would like the rest
1008of the desktop to use depth 24 visuals.  They often work on the multi
1009depth visuals.
1010
1011How does this effect x11vnc?  x11vnc nearly always polls the root window
1012(container of all other windows).  The root window will be one depth,
1013e.g. 8 or 24.  Any windows using the *other* depth will appear to have
1014messed up colors (or just be black or some other solid color) when viewed
1015via x11vnc.
1016
1017How to fix?  Solaris and IRIX provide an API to extract the full snapshot
1018of the display with all the colors correct.  It comes to x11vnc as depth
101924 TrueColor.  To enable this use the \"-overlay\" option.  Performance
1020may be slower, but if the colors are correct that is a big improvement.
1021"
1022
1023	set helptext(8-Bit-Color:) "
1024Some older displays (e.g. with limited Video RAM) use 8 bits-per-pixel
1025color.  This allows for only 256 different colors on the screen at the
1026same time.  This sometimes leads to problems with viewing these 8bpp
1027displays via x11vnc.  This sub-menu has some options that correspond to
1028workarounds for this case.  If you can configure the machine to use 16bpp
1029it may be worth it to avoid the color problems (e.g. color flashing
1030as the 8bit colormap is switched).
1031"
1032	set helptext(SubWindow:) "
1033This sub-menu has a couple options regarding having x11vnc poll a
1034single window, not the entire display.  This way just the window
1035is shared.
1036
1037Note if the application pops up multiple windows they are not tracked
1038and shared.  So this is not application sharing.  The application has to
1039be very simple (e.g. a simple terminal or the image window on a webcam)
1040for this mode to be usable.
1041"
1042	set helptext(ResizeRotate:) "
1043This sub-menu has some options regarding screens that support the X
1044Resize, Reflection, and Rotation Extension (RANDR), and one expects screen
1045resizing, reflection, or rotation to take place during the x11vnc session.
1046This is pretty rare, but x11vnc seems to handle it reasonably well using
1047this X extension.
1048
1049This mode is on by default in -id mode to try to track the changing
1050size of the SubWindow.  It is not on by default for full-screen mode
1051because of the extra overhead, etc.
1052"
1053
1054	set helptext(WireFrame:) "
1055This sub-menu has some options for the x11vnc wireframing speedup scheme.
1056
1057For x11vnc, Wireframing means to watch for toplevel windows being Opaquely
1058Moved or Resized.  When x11vnc detects this, it stops polling the screen
1059and simply shows a \"wireframe\" outline of the window as it is being
1060moved or resized.  This avoids \"screen polling thrashing\" when the
1061screen is changing so rapidly during this period.  For various reasons
1062this is usually much faster then letting the window manager do its
1063own wireframing (you are encouraged to do Opaque moves and resizes
1064when using x11vnc!)
1065
1066Also, once a moved window is released in its new position, x11vnc uses
1067the VNC CopyRect encoding to very efficiently update the VNC viewers
1068(each just copies the image data locally).
1069
1070This sort of scheme was used much in the 1990's on local displays because
1071video hardware was slow at the time.  x11vnc tries to use this same trick
1072as a speedup for its activities (the network is much slower than video
1073hardware writes, and the video hardware reads that x11vnc uses to poll
1074the screen are still slow today).
1075"
1076#'"
1077
1078	set helptext(Safe:) "
1079In this sub-menu are some options for making x11vnc operations
1080more, or less, safe.  E.g. disable the running of external commands, etc.
1081
1082You can also turn off the Remote control channel (NOTE that doing that
1083will disable the GUI from being able to communicate with x11vnc).
1084"
1085
1086	set helptext(X-ext:) "
1087In this sub-menu are a few rarely used options regarding some X extensions
1088used by x11vnc.
1089"
1090	set helptext(Clipping:) "
1091In this sub-menu are some options regarding clipping or blacking out
1092portions of the Screen.  E.g. under XINERAMA when the multiple monitors
1093are not the same size.
1094
1095"
1096	set helptext(Misc-Screen:) "
1097In this sub-menu are some little used options modifying aspects of
1098the screen source.
1099"
1100
1101	set helptext(Settings:) "
1102In this sub-menu are some options for saving and loading option settings.
1103The default file to store settings in is ~/.x11vncrc, but you can save
1104different \"profiles\" in other files for later use.
1105
1106"
1107	set helptext(Java-applet:) "
1108In this sub-menu are some options for running the built-in HTTP server
1109that delivers the TightVNC Java VNC Viewer applet (VncViewer.jar) to
1110clients.  The viewer runs in their Web browser.
1111
1112The default port listened on is 5800, so the URL is typically:
1113
1114	http://hostname:5800/
1115
1116but this can be altered by -httpport, etc.
1117"
1118
1119	set helptext(Chat:) "
1120In this sub-menu are some options for enabling a local chat window
1121and starting or stopping the current chat.  This is the UltraVNC
1122Text Chat support in x11vnc.
1123"
1124
1125	set helptext(ScrollCopyRect:) "
1126This sub-menu has some options for the x11vnc Scroll detection and
1127CopyRect speedup scheme.
1128
1129For this mode, x11vnc \"spies\" on communication between the X server and
1130applications using the RECORD extension.  It looks for various patterns
1131to detect a scrolled window.  This only works for some applications,
1132fortunately some important ones.
1133
1134Once the scroll is detected it uses the VNC CopyRect encoding for a
1135big speedup.  Screen polling is also sped up for this scheme.
1136
1137There are many tweakable parameters for this mode and they are described
1138in the sub-menu items.
1139"
1140
1141	set helptext(XDAMAGE:) "
1142The DAMAGE X extension allows the X server to send signals to x11vnc
1143telling it which regions of the screen have been changed.  This improves
1144x11vnc's performance markedly.  The DAMAGE extension must be available
1145on the display for this to work.
1146
1147Unfortunately DAMAGE cannot be trusted completely for the changed regions,
1148because often the reported changed region is much larger than the actual
1149changed regions.  Nevertheless, x11vnc uses the DAMAGE information very
1150effectively as hints to improve its performance.
1151
1152The items in the sub-menu allow tweaking x11vnc's DAMAGE algorithm.
1153"
1154
1155	set helptext(Ncache:) "
1156A simple client-side (viewer) caching scheme is enabled with the
1157\"-ncache n\" option.  It simply uses \"n\" framebuffer sized areas
1158below the actual display for caching window pixel data.
1159
1160Drawbacks are it uses a lot of RAM (roughly n times more), and the
1161pixels cache area is visible in the viewers.
1162
1163The items in the sub-menu allow tweaking x11vnc's -ncache algorithm.
1164"
1165
1166	set helptext(SharedMemory:) "
1167This sub-menu provides some options regarding SYSV shared memory usage
1168(shm) by x11vnc.  Usually you want shm turned on because the x11vnc
1169process is nearly always running on the same machine the X server process
1170is running on.  SharedMemory gives a performance speedup.  However, if you
1171need to modify this scenario for special usage these options allow you to.
1172"
1173
1174	set helptext(Misc-Debug:) "
1175This sub-menu contains a lot of debugging parameters usually used
1176for debugging x11vnc itself.  This is unlike the -debug_pointer and
1177-debug_keyboard options that are useful in learning information, quirks,
1178etc. about your local display and environment.
1179"
1180
1181	set helptext(Selection:) "
1182This sub-menu contains some options centering around the Selection
1183(also referred to as the Clipboard, Cutbuffers, etc).  x11vnc will try
1184to exchange the selections between the VNC viewers and the X server.
1185You can adjust that behavior with these options.
1186"
1187
1188	set helptext(WindowView) "
1189Set 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
1205Note that in \"full\" mode if you delete the full gui window the gui
1206terminates (but the x11vnc server keeps running).  However under \"icon\"
1207or \"tray\" mode if you bring up the full gui window via \"Properties ->
1208Advanced\" and then delete it the gui does NOT terminate.
1209
1210Also note that by default in \"icon\" mode if you delete the icon
1211window both the gui *and* the x11vnc server terminate.
1212"
1213
1214	set helptext(gui) "
1215tkx11vnc is a simple frontend to x11vnc.  Nothing fancy, it merely
1216provides an interface to each of the many x11vnc command line options and
1217remote control commands.  See \"Help -> all\" for much info about x11vnc.
1218
1219For a simplier gui, run x11vnc in \"tray\" or \"icon\" mode such as
1220\"-gui tray\", \"-gui icon\", or \"-gui tray=setpass\".  In that
1221mode the full gui is only available under \"Advanced ...\".
1222
1223Also, \"-gui ez\" will show fewer menu items (toggle via Misc -> simple_gui)
1224
1225All menu items have a (?) button one can click on to get more information
1226about the option or command.
1227
1228There 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
1234Most people will just use state 1).
1235
1236In state 1) the Menu items available in the menus are those that
1237correspond to the x11vnc \"remote control\" commands.  See the -remote
1238entry under \"Help -> all\" for a complete list.  Also available is
1239the \"Actions -> stop\" item to shut down the running x11vnc server,
1240thereby changing to state 2).  There are other actions available too.
1241
1242In state 2) the Menu items available in the menus (\"Actions\", \"Clients\",
1243etc.) are those that correspond to command line options used in starting
1244an x11vnc process, and the \"Actions -> start\" item executes
1245x11vnc thereby changing to state 1).  To see what x11vnc startup command
1246you have built so far, look at the (?) help for  \"Actions -> start\"
1247and it will show you what the command looks like.
1248
1249There is much overlap between the menu items available in state 1)
1250and state 2), but it is worth keeping in mind it is not 100%.
1251For 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
1255Also note that there may be *two* separate X displays involved, not just
1256one:  1) the X display x11vnc will be polling (and making available to
1257VNC viewers), and 2) the X display this GUI is intended to display on.
1258
1259For example, one might use ssh to access the remote machine where the
1260GUI would display on :11 and x11vnc would poll display :0.  By default
1261the gui will display on the value in the DISPLAY env. variable followed
1262by the value from the -display option.  To override this, use something
1263like: \"-gui otherhost:0\", etc.
1264
1265
1266GUI components:
1267--- ----------
1268
12691) 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
12732) 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
12793) 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
12834) 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
12875) 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
1299CASCADES BUG: There is a bug not yet worked around for the cascade menus
1300where the (?) help button gets in the way.  To get the mouse over to
1301the cascade menu click and release mouse to activate the cascade, then
1302you can click on its items.  Dragging with a mouse button held down will
1303not work (sorry!).
1304
1305
1306Key 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
1315set under_wally "
1316Misc:
1317
1318Since x11vnc has so many settings and to avoid further confusion,
1319the libvncserver options:
1320
1321	-alwaysshared
1322	-nevershared
1323	-dontdisconnect
1324
1325are not available for changing in a running x11vnc (even though it
1326is feasible).  These options overlap with the x11vnc options -shared
1327and -forever which are hopefully enough for most usage.  They may be
1328specified for x11vnc startup if desired.
1329
1330"
1331
1332global beginner_mode
1333if {$beginner_mode} {
1334	set helptext(gui) "
1335tkx11vnc is a simple frontend to x11vnc.  It is currently running in
1336\"ez\" or \"simple\" mode.  For many more options run it in normal
1337mode by toggling \"Misc -> simple_gui\".
1338
1339All menu items have a (?) button one can click on to get more information
1340about the option or command.
1341
1342GUI components:
1343--- ----------
1344
13451) 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
13492) 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
13553) 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
13594) 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
13635) 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
1374CASCADES BUG: There is a bug not yet worked around for the cascade menus
1375where the (?) help button gets in the way.  To get the mouse over to
1376the cascade menu click and release mouse to activate the cascade, then
1377you can click on its items.  Dragging with a mouse button held down will
1378not work (sorry!).
1379
1380"
1381}
1382
1383}
1384
1385proc 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
1394proc 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
1405proc textheight {text} {
1406	set count 0;
1407	foreach line [split $text "\n"] {
1408		incr count
1409	}
1410	return $count
1411}
1412
1413proc 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
1438proc 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
1448proc 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
1514proc 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
1546proc 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
1584proc 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
1675proc 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
1738proc tweak_both {new old} {
1739	tweak_help $new $old
1740	tweak_remote_help $new $old
1741}
1742
1743proc 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
1752proc 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
1761proc 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
1816proc 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
1874proc 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:
1883proc 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
1895proc menus_enable {} {
1896	global menus_disabled
1897
1898	menus_state "normal"
1899	set menus_disabled 0
1900}
1901
1902proc menus_disable {} {
1903	global menus_disabled
1904
1905	set menus_disabled 1
1906	menus_state "disabled"
1907}
1908
1909# Entry box utilities:
1910proc 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
1939proc entry_enable {{x "all"}} {
1940	entry_state $x normal
1941}
1942
1943proc entry_disable {{x "all"}} {
1944	entry_state $x disabled
1945}
1946
1947proc 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}
1955proc entry_focus {} {
1956	global entry_box
1957	focus $entry_box
1958}
1959proc entry_select {} {
1960	global entry_box
1961	$entry_box selection range 0 end
1962}
1963proc entry_get {} {
1964	global entry_box
1965	return [$entry_box get]
1966}
1967proc entry_insert {str} {
1968	global entry_box
1969	entry_delete
1970	$entry_box insert end $str
1971	$entry_box icursor end
1972}
1973proc entry_delete {} {
1974	global entry_box
1975	$entry_box delete 0 end
1976}
1977
1978
1979# Utilities for remote control and updating vars.
1980
1981proc 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
2106proc 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
2146proc 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
2254proc 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
2292proc 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
2349proc 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.
2358proc 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
2436proc 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:
2443proc 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
2463proc 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
2539proc 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
2634proc 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
2667proc 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
2722proc 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
2738proc 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
2785proc 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
2870proc 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
2964proc 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
2986proc defaults_all {} {
2987	copy_default_vars
2988	append_text "Reset all variables to default values.\n"
2989}
2990
2991proc 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
3026proc 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
3052proc 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
3062proc 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
3087proc 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
3118proc 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
3144proc 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
3168proc 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
3184proc 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
3198proc 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:
3207proc 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
3299proc 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
3305proc 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
3355proc menu_help {item} {
3356	if ![help_win $item] {
3357		textwin "nohelp" "No help available" \
3358			"Sorry, no help avaiable for \"$item\""
3359	}
3360}
3361
3362proc 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
3372proc is_action {item} {
3373	return [opt_match A $item]
3374}
3375
3376proc 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
3386proc is_browse {item} {
3387	return [opt_match F $item]
3388}
3389
3390proc 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
3402proc 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
3414proc 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
3435proc 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
3467proc set_x11_display {name} {
3468	global x11_display
3469	set x11_display "x11vnc X display: $name"
3470	set_name "tkx11vnc - $name"
3471}
3472proc 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}
3480proc set_vnc_url {name} {
3481	global vnc_url
3482	set vnc_url $name
3483}
3484proc no_x11_display {} {
3485	set_x11_display "(*none*)"
3486	set_name "tkx11vnc"
3487}
3488proc no_vnc_display {} {
3489	set_vnc_display "(*none*)"
3490}
3491proc no_vnc_url {} {
3492	set_vnc_url "(*none*)"
3493}
3494
3495proc 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
3511proc 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
3543proc 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
3650proc 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
3686proc 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
3718proc 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
3771proc 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
3808proc 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
3828proc 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
3879proc 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
4095proc 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
4123proc menu_posted {} {
4124	check_update_vars
4125}
4126
4127proc props_widgets {state} {
4128	global props_buttons
4129	foreach w $props_buttons {
4130		$w configure -state $state
4131	}
4132	update
4133}
4134
4135proc 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
4347proc 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
4369proc 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
4698proc 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
4709proc 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
4738proc do_disconnect_all {} {
4739	push_new_value "disconnect" "disconnect" "all" 1
4740}
4741
4742proc do_disconnect_client {id} {
4743	push_new_value "disconnect" "disconnect" "$id" 1
4744}
4745
4746proc 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
4780proc 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
4791proc 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
4852proc 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
4904proc 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
4922proc 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
4931proc 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
4940proc 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
4994proc 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
5004proc 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
5027proc 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
5054proc 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
5167proc 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
5185proc 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
5205proc 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
5227proc 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
5245proc 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
5294proc 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
5317proc 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
5459proc 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
5490proc 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
5506proc 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
5515proc 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
5626proc 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
5840proc menu_bindings {m} {
5841	set db 0
5842	if {$db} {puts "menu_bindings $m"}
5843
5844	bind $m <<MenuSelect>> {
5845#syntax hilite bug \
5846MenuSelect>>
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
5884proc 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
5912proc 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
5945proc 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
5955proc 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
6086proc 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
6096proc 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
6107proc show_start_cmd {} {
6108	set msg [get_start_x11vnc_txt]
6109	append_text "$msg\n"
6110}
6111
6112proc 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
6134proc 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
6250proc 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
6301proc 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
6392proc 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
6472proc 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
6485proc 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
6537proc set_view_variable {val} {
6538	global menu_var
6539	set menu_var(WindowView) $val
6540}
6541proc 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
6549proc dono {a b c} {
6550	exit 1;
6551}
6552
6553proc 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
6690proc 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
6728proc setup_client_tail {} {
6729	global client_tail
6730	if {$client_tail != ""} {
6731		fileevent $client_tail readable read_client_tail
6732	}
6733}
6734
6735proc 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
6746proc 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
6761proc 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
6836proc 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
6844if [info exists env(X11VNC_GUI_TIME)] {
6845	dtime M
6846}
6847
6848wm withdraw .
6849
6850global env x11vnc_prog x11vnc_cmdline x11vnc_xdisplay x11vnc_connect;
6851global x11vnc_xdisplay0
6852global x11vnc_client_file x11vnc_gui_geom x11vnc_started vnc_url
6853global x11vnc_gui_params
6854global x11vnc_auth_file x11vnc_connect_file beginner_mode simple_gui_created
6855global helpall helptext helpremote helplabel hostname osname
6856global all_settings reply_xdisplay always_update
6857global max_text_height max_text_width
6858global text_height
6859global menu_var unset_str menus_disabled
6860global bfont ffont sfont snfont old_labels have_labelframes
6861global connected_to_x11vnc
6862global cache_all_query_vars
6863global last_query_all_time query_all_freq client_tail client_sock client_info_read
6864global icon_mode icon_mode_at_startup x11vnc_icon_mode
6865global tray_embed tray_running icon_setpasswd icon_embed_id
6866global icon_noadvanced icon_minimal
6867global make_gui_count text_area_str
6868global gui_argv0 gui_start_mode
6869global screen_height screen_width
6870
6871set unset_str "(unset)"
6872set vnc_url $unset_str
6873set connected_to_x11vnc 0
6874set menus_disabled 0
6875set max_text_height 40
6876set max_text_width 90
6877set text_height 14
6878set bfont "-adobe-helvetica-bold-r-*-*-*-120-*-*-*-*-*-*"
6879set sfont "-adobe-helvetica-bold-r-*-*-*-100-*-*-*-*-*-*"
6880set snfont "-adobe-helvetica-medium-r-*-*-*-100-*-*-*-*-*-*"
6881set ffont "fixed"
6882
6883set got_helv 0
6884catch {
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
6895if {$got_helv} {
6896	set bfont  "Helvetica -12 bold"
6897	set sfont  "Helvetica -10 bold"
6898	set snfont "Helvetica -10"
6899}
6900
6901set ls ""
6902catch {set ls [font metrics $bfont -linespace]}
6903if {$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!!
6924set ls ""
6925catch {set ls [font metrics $ffont -linespace]}
6926set fs ""
6927catch {set fs [font metrics $ffont -fixed]}
6928set redo 0
6929if {$fs != "" && $fs != "1"} {
6930	set redo 1
6931}
6932if {$ls != "" && $ls > 14} {
6933	set redo 1
6934}
6935if {$redo} {
6936	foreach fn [font names] {
6937		if {$fn == "TkFixedFont"} {
6938			set ffont $fn
6939			break
6940		}
6941	}
6942}
6943
6944set help_indent 24;
6945set reply_xdisplay ""
6946set all_settings "None so far."
6947set always_update 1
6948set cache_all_query_vars ""
6949set query_all_freq 120
6950set last_query_all_time [clock seconds]
6951set client_tail ""
6952set client_sock ""
6953set client_info_read 0
6954set make_gui_count 0
6955set text_area_str ""
6956set gui_argv0 $argv0
6957set gui_start_mode ""
6958
6959if {$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}
6965if {[regexp {^[34]} $tk_version] || $tk_version == "8.0"} {
6966	set old_labels 1
6967} else {
6968	set old_labels 0
6969}
6970set have_labelframes 1
6971if {$tk_version < 8.4} {
6972	set have_labelframes 0
6973}
6974
6975set screen_height [winfo screenheight .]
6976set screen_width  [winfo screenwidth  .]
6977if {$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}
6992if {[info exists env(X11VNC_GUI_TEXT_HEIGHT)]} {
6993	set max_text_height $env(X11VNC_GUI_TEXT_HEIGHT)
6994}
6995if {[info exists env(X11VNC_GUI_TEXT_WIDTH)]} {
6996	set max_text_width  $env(X11VNC_GUI_TEXT_WIDTH)
6997}
6998
6999if {"$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
7026set_view_variable "full"
7027
7028#puts [exec env | grep X11VNC]
7029
7030# Read environment for clues:
7031
7032set x11vnc_client_file "";
7033if {[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
7054if {[info exists env(X11VNC_PROG)]} {
7055	set x11vnc_prog $env(X11VNC_PROG);
7056} else {
7057	set x11vnc_prog "x11vnc";
7058}
7059
7060if {[info exists env(X11VNC_CMDLINE)]} {
7061	set x11vnc_cmdline $env(X11VNC_CMDLINE);
7062} else {
7063	set x11vnc_cmdline "";
7064}
7065
7066if {[info exists env(X11VNC_CONNECT)]} {
7067	set x11vnc_connect 1
7068} else {
7069	set x11vnc_connect 0;
7070}
7071
7072if {[info exists env(X11VNC_GUI_GEOM)]} {
7073	set x11vnc_gui_geom $env(X11VNC_GUI_GEOM);
7074} else {
7075	set x11vnc_gui_geom ""
7076}
7077if {[info exists env(X11VNC_GUI_PARAMS)]} {
7078	set x11vnc_gui_params $env(X11VNC_GUI_PARAMS);
7079} else {
7080	set x11vnc_gui_params ""
7081}
7082
7083if {[info exists env(X11VNC_FONT_BOLD)]} {
7084	set bfont $env(X11VNC_FONT_BOLD)
7085}
7086if {[info exists env(X11VNC_FONT_BOLD_SMALL)]} {
7087	set sfont $env(X11VNC_FONT_BOLD_SMALL)
7088}
7089if {[info exists env(X11VNC_FONT_REG_SMALL)]} {
7090	set snfont $env(X11VNC_FONT_REG_SMALL)
7091}
7092if {[info exists env(X11VNC_FONT_FIXED)]} {
7093	set ffont $env(X11VNC_FONT_FIXED)
7094}
7095
7096if {[info exists env(X11VNC_CONNECT_FILE)]} {
7097	set x11vnc_connect_file $env(X11VNC_CONNECT_FILE);
7098} else {
7099	set x11vnc_connect_file "";
7100}
7101
7102set x11vnc_started 0
7103if {[info exists env(X11VNC_STARTED)]} {
7104	set x11vnc_started 1
7105}
7106
7107set x11vnc_xdisplay ""
7108if {[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}
7122set x11vnc_xdisplay0 $x11vnc_xdisplay
7123
7124if {[info exists env(X11VNC_AUTH_FILE)]} {
7125	set x11vnc_auth_file $env(X11VNC_AUTH_FILE)
7126} else {
7127	set x11vnc_auth_file ""
7128}
7129
7130set simple_gui_created 0
7131if {[info exists env(X11VNC_SIMPLE_GUI)]} {
7132	set beginner_mode 1
7133} else {
7134	set beginner_mode 0
7135}
7136
7137set icon_mode 0
7138set x11vnc_icon_mode 0
7139set tray_embed 0
7140set tray_running 0
7141
7142if {![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}
7153set icon_mode_at_startup $env(X11VNC_ICON_MODE_AT_STARTUP)
7154
7155if {![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
7170set icon_setpasswd 0
7171if {[info exists env(X11VNC_ICON_SETPASS)]} {
7172	if {$env(X11VNC_ICON_SETPASS) != ""} {
7173		set icon_setpasswd 1
7174	}
7175}
7176
7177set icon_noadvanced 0
7178if {[info exists env(X11VNC_ICON_NOADVANCED)]} {
7179	set icon_noadvanced 1
7180}
7181
7182set icon_minimal 0
7183if {[info exists env(X11VNC_ICON_MINIMAL)]} {
7184	set icon_minimal 1
7185}
7186
7187if {[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
7194set hostname [exec uname -n]
7195set osname [exec uname]
7196
7197if {[regexp -nocase {IRIX} $osname]} {
7198	# IRIX "fixed" font is huge and doublespaced... 
7199	set ffont $snfont
7200}
7201if {[regexp -nocase {Darwin} $osname]} {
7202	set ffont {Monaco 10}
7203	set bfont {system}
7204}
7205
7206if {"$argv" == "-portprompt"} {
7207	do_port_prompt
7208	exit 0
7209}
7210
7211#puts [exec env]
7212#puts "x11vnc_xdisplay: $x11vnc_xdisplay"
7213
7214set env(X11VNC_STD_HELP) 1
7215
7216# scrape the help output for the text and remote control vars:
7217parse_help;
7218parse_remote_help;
7219parse_query_help;
7220
7221# tweaks to duplicate help text:
7222tweak_remote_help lock deny
7223tweak_remote_help unlock deny
7224
7225tweak_both quiet q
7226tweak_help logfile o
7227tweak_both xwarppointer xwarp
7228tweak_both screen_blank sb
7229
7230set_template
7231
7232set_name "tkx11vnc"
7233
7234key_bindings;
7235
7236get_default_vars
7237
7238dtime D
7239
7240proc 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
7306if {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
7316if {$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