#!/bin/sh
# the exec restarts using tclsh which in turn ignores
# the command because of this backslash: \
exec mash-VERSION "$0" -name bin/setup -- "$@"

#
# Copyright (c) 1993-1996 The Regents of the University of California.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
# 3. All advertising materials mentioning features or use of this software
#    must display the following acknowledgement:
#	This product includes software developed by the University of
#	California, Berkeley and the Network Research Group at
#	Lawrence Berkeley Laboratory.
# 4. Neither the name of the University nor of the Laboratory may be used
#    to endorse or promote products derived from this software without
#    specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
# @(#) $Header: /usr/src/mash/repository/mash/mash-1/head.tcl,v 1.3 1997/08/15 07:23:36 mccanne Exp $ (LBL)
#
if {$tcl_platform(platform) == "windows"} {
	if ![file exists mash.exe] {		
		if [file exists mash\\mash.exe] {
			puts "changing dir to mash"
			cd mash
		}
	} 
}
proc isWidgetObject { cl } {
	if { [$cl info heritage WidgetObject] != {} || $cl=="WidgetObject" } {
		return 1
	} else {
		return 0
	}
}
Class WidgetClass -superclass Class
WidgetClass proc unknown { cl args } {
	set private_options(-configspec) ""
	set private_options(-default) ""
	set private_options(-alias) ""
	set len [llength $args]
	for { set idx 0 } { $idx < $len } { incr idx 2 } {
		if { [info exists private_options([lindex $args $idx])] } {
			set private_options([lindex $args $idx]) \
					[lindex $args [expr $idx+1]]
			set args [lreplace $args $idx [expr $idx+1]]
			incr idx -2
		}
	}
	set idx [lsearch $args "-superclass"]
	if { $idx!=-1 } {
		incr idx
		if { [llength $args] <= $idx } {
			error "missing argument for option '-superclass'"
		}
		set superclasses [lindex $args $idx]
		set need_WidgetObject 1
		foreach superclass $superclasses {
			if { [$superclass info heritage WidgetObject]!="" } {
				set need_WidgetObject 0
				break
			}
		}
		if { $need_WidgetObject && $cl!="WidgetObject"} {
			lappend superclasses WidgetObject
			set args [lreplace $args $idx $idx $superclasses]
		}
	} else {
		if { $cl!="WidgetObject" } {
			lappend args -superclass WidgetObject
		}
	}
	eval [list $self] next [list $cl] $args
	$cl heritage_defaults
	foreach option [array names private_options] {
		set arg $private_options($option)
		$cl set_[string range $option 1 end] $arg
	}
}
WidgetClass proc set_widget_default { } {
	set count 0
	while [winfo exists .dummy_${count}__] { incr count }
	set dummy .dummy_${count}__
	button $dummy
	$self set_widget_default_ $dummy { -background -foreground \
			-activebackground -activeforeground -borderwidth \
			-cursor -disabledforeground -highlightbackground\
			-highlightcolor -highlightthickness -takefocus \
			{-boldfont -font} }
	destroy $dummy
	entry $dummy
	$self set_widget_default_ $dummy { -font -selectbackground \
			-selectforeground -selectborderwidth }
	destroy $dummy
}
WidgetClass proc set_widget_default_ { path options } {
	$self instvar widget_defaults_
	foreach option $options {
		if { [llength $option]==1 } {
			set option [lindex $option 0]
			set widget_defaults_($option) [$path cget $option]
		} else {
			set widget_defaults_([lindex $option 0]) \
					[$path cget [lindex $option 1]]
		}
	}
}
WidgetClass proc widget_default { option } {
	$self instvar widget_defaults_
	if { [info exists widget_defaults_($option) ] } {
		return $widget_defaults_($option)
	} else {
		error "no such default option \"$option\""
	}
}
WidgetClass proc translate_default { option value } {
	if { ![string compare $value "WidgetDefault"] } {
		return [WidgetClass widget_default $option]
	} elseif { [regexp {WidgetDefault\((.*)\)} $value dummy \
			defaultOption] } {
		return [WidgetClass widget_default $defaultOption]
	}
	return $value
}
WidgetClass set_widget_default
WidgetClass instproc heritage_defaults { } {
	set heritage [$self info heritage]
	set len [expr [llength $heritage]-1]
	while { $len >= 0 } {
		set cl [lindex $heritage $len]
		incr len -1
		if { [isWidgetObject $cl] } {
			$self configspec_ [$cl info configspec] 1
			$self default_ [$cl info default]
		}
	}
}
WidgetClass instproc set_configspec { specs } {
	$self configspec_ $specs 0
}
WidgetClass instproc configspec_ { specs {isAncestor} } {
	$self instvar configspec_
	foreach spec $specs {
		if { ! $isAncestor } {
			set option  [lindex $spec 0]
			set default [lindex $spec 3]
			set spec [lreplace $spec 3 3 [WidgetClass \
					translate_default $option $default]]
			set configspec_($option) $spec
		}
		option add *$self.[lindex $spec 1] \
				[lindex $spec 3] widgetDefault
	}
}
WidgetClass instproc set_alias { aliases } {
	$self instvar configspec_
	foreach alias $aliases {
		set al   [lindex $alias 0]
		set orig [lindex $alias 1]
		if { ![info exists configspec_($orig)] } {
			error "no configspec $orig (specified in alias list)"
		}
		set configspec_($al) $configspec_($orig)
	}
}
WidgetClass instproc set_default { defaults } {
	$self default_ $defaults
	$self set defaults_ $defaults
}
WidgetClass instproc default_ { defaults } {
	foreach default $defaults {
		set option [lindex $default 0]
		set star [string last "*" $option]
		set dot  [string last "." $option]
		if { $star < $dot } {
			set idx [expr $dot+1]
		} else {
			set idx [expr $star+1]
		}
		option add *${self}$option [WidgetClass translate_default \
				-[string tolower [string range $option $idx \
				end]] [lindex $default 1]] widgetDefault
	}
}
WidgetClass instproc create { widget args } {
	eval [list $self] next [list _o$widget] [list $widget] $args
	return $widget
}
WidgetClass instproc info { option args } {
	if { $option == "default" } {
		if { $args != "" } {
			error "extra arguments in call to 'info $option'"
		}
		return [$self set defaults_]
	} elseif { $option == "configspec" } {
		$self instvar configspec_
		set len [llength $args]
		if { $len == 0 } {
			set list {}
			foreach el [array names configspec_] {
				lappend list $configspec_($el)
			}
			return $list
		}
		if { [llength $args] != 1 } {
			error "extra arguments in call to 'info $option'"
		}
		if { [info exists configspec_($args)] } {
			return $configspec_($args)
		} else {
			return ""
		}
		return [eval [list $self] next [list $option] $args]
	} else {
		return [eval [list $self] next [list $option] $args]
	}
}
WidgetClass WidgetObject -configspec {
	{-options options Options {} widget_options widget_options}
}
WidgetObject instproc init { widget args } {
	$self next
	$self instvar path_ widget_proc_
	set path_ $widget
	$self create_root_widget $widget
	if { ![winfo exists $widget] } {
		error "must create a widget $widget inside\
				[$self info class]::create_root_widget"
	}
	$self instvar widget_proc_
	set widget_proc_ "proc_$self"
	rename $widget $widget_proc_
	proc ::$widget { args } "return \[uplevel [list $self] \$args\]"
	$self build_widget $widget
	set heritage [[$self info class] info heritage]
	set idx 0
	for { set idx [expr [llength $heritage]-1] } {$idx>=0} {incr idx -1} {
		set cl [lindex $heritage $idx]
		if { [isWidgetObject $cl] } {
			$self configure_default $cl
		}
	}
	$self configure_default [$self info class]
	if { $args!="" } {
		eval [list $self] configure $args
	}
	bind <Destroy> $widget "delete $self"
}
WidgetObject instproc create_root_widget { path } {
	frame $path -class [$self info class]
}
WidgetObject instproc build_widget { path } {
}
WidgetObject instproc info { option args } {
	switch $option {
		"path" {
			if { $args != "" } {
				error "extra arguments in call to 'info $option'"
			}
			return [$self set path_]
		}
		default {
			return [eval [list $self] next [list $option] $args]
		}
	}
}
WidgetObject instproc unknown { method args } {
	return [eval [list $self] widget_proc [list $method] $args]
}
WidgetObject instproc widget_proc { args } {
	$self instvar widget_proc_
	return [eval [list $widget_proc_] $args]
}
WidgetObject instproc config { args } {
	return [eval [list $self] configure $args]
}
WidgetObject instproc configure_default { cl } {
	set path [$self info path]
	set widget_class [winfo class $path]
	if { $widget_class == [$self info class] } {
		foreach spec [$cl info configspec] {
			set optVal [option get $path [lindex $spec 1] $cl]
			$self configure [lindex $spec 0] $optVal
		}
	} else {
		foreach spec [$cl info configspec] {
			$self configure [lindex $spec 0] [lindex $spec 3]
		}
	}
}
WidgetObject instproc configure { args } {
	set len [llength $args]
	switch $len {
		0 { return [$self configure_all] }
		1 { return [$self configure_one $args] }
		default {
			if { $len % 2 != 0 } {
				error "odd number of arguments for configure"
			}
			for { set i 0 } { $i < $len } { incr i 2 } {
				$self configure_one [lindex $args $i] \
						[lindex $args [expr $i+1]]
			}
		}
	}
}
WidgetObject instproc configure_one { args } {
	set option [lindex $args 0]
	if { [string index $option 0] != "-" } {
		error "invalid option $option: must start with -"
	}
	set option [string range $option 1 end]
	set spec [[$self info class] info configspec -$option]
	if { $spec!="" } {
		set config_proc [lindex $spec 4]
		set cget_proc   [lindex $spec 5]
		if { $cget_proc=={} } { set cget_proc $config_proc }
		if { [llength $args] < 2 } {
			return [lreplace $spec 4 end [$self $cget_proc \
					"-$option"]]
		} else {
			return [$self $config_proc "-$option" [lindex $args 1]]
		}
	}
	foreach cl [[$self info class] info heritage] {
		if { [isWidgetObject $cl] } {
			set spec [$cl info configspec -$option]
			if { $spec!="" } {
				set config_proc [lindex $spec 4]
				set cget_proc   [lindex $spec 5]
				if { $cget_proc=={} } {
					set cget_proc $config_proc
				}
				if { [llength $args] < 2 } {
					return [lreplace $spec 4 end \
							[$self $cget_proc \
							"-$option"]]
				} else {
					return [$self $config_proc "-$option" \
							[lindex $args 1]]
				}
			}
		}
	}
	return [eval [list $self] widget_proc configure $args]
}
WidgetObject instproc configure_all { } {
	set result [$self configure_all_ [$self info class]]
	foreach cl [[$self info class] info heritage] {
		if { [isWidgetObject $cl] } {
			set result [concat $result [$self configure_all_ $cl]]
		}
	}
	set result [concat $result [$self widget_proc configure]]
	return $result
}
WidgetObject instproc configure_all_ { cl } {
	set result ""
	foreach spec [$cl info configspec] {
		set option [lindex $spec 0]
		if { $option != "-options" } {
			lappend result [$self configure $option]
		}
	}
	return $result
}
WidgetObject instproc cget { option } {
	return [lindex [$self configure_one $option] 4]
}
WidgetObject instproc widget_options { option args } {
	if { [llength $args]==0 } {
		error "options has no value; cannot read it"
	}
	set root [$self info path]
	foreach option [lindex $args 0] {
		set opt [string trim [lindex $option 0]]
		set arg [lindex $option 1]
		set lastdot [string last . $opt]
		if { $lastdot <= 0 } {
			set path $root
		} else {
			set firstdot  [string first . $opt]
			set path [string range $opt 0 [expr $firstdot-1]]
			set path [$self subwidget $path]
			if { $firstdot < $lastdot } {
				set path $path.[string range $opt \
						[expr $firstdot+1] \
						[expr $lastdot -1]]
			}
		}
		set opt [string range $opt [expr $lastdot+1] end]
		$path configure -$opt $arg
	}
}
WidgetObject instproc subwidget { widget args } {
	set path "[$self info path].$widget"
	if { ![winfo exists $path] } {
		$self instvar subwidgets_
		if { ![info exists subwidgets_($widget)] } {
			error "no subwidget $widget inside [$self info path]"
		}
		set path $subwidgets_($widget)
	}
	if { [llength $args]==0 } {
		return $path
	}
	return [eval [list $path] $args]
}
WidgetObject instproc set_subwidget { name path } {
	$self instvar subwidgets_
	$self set subwidgets_($name) $path
}
WidgetObject instproc ignore_args { args } {
}
WidgetObject instproc do_when_idle { command } {
	$self instvar do_idle_ids_
	set command [string trim $command]
	if ![info exists do_idle_ids_($command)] {
		set do_idle_ids_($command) \
				[after idle "WidgetObject do_idle_ \
				[list $self] [list $command]"]
	}
}
WidgetObject proc do_idle_ { o command } {
	$o instvar do_idle_ids_
	catch {unset do_idle_ids_($command)}
	if { [info command $o]!=$o } {
		return
	}
	set w [$o info path]
	if {![winfo exists $w] || [string compare [winfo class $w] \
			[$o info class]] != 0} {
		return
	} else {
		uplevel #0 $command
	}
}
WidgetClass proc transparent_gif { {color {}} } {
	global TRANSPARENT_GIF_COLOR
	if { $color!={} } {
		set TRANSPARENT_GIF_COLOR $color
	} else {
		set TRANSPARENT_GIF_COLOR [$self widget_default -background]
	}
}
WidgetClass proc EntryBindings { tag } {
	bind $tag <FocusIn>  "$self EntryBindings_FocusIn %W"
	bind $tag <FocusOut> "$self EntryBindings_FocusOut %W"
}
WidgetClass proc EntryBindings_FocusIn { entry } {
	if [string compare [$entry get] ""] {
		$entry selection from 0
		$entry selection to   end
		$entry icursor end
	} else {
		$entry selection clear
	}
}
WidgetClass proc EntryBindings_FocusOut { entry } {
    $entry selection clear
}
WidgetClass EntryBindings Entry
WidgetClass transparent_gif
WidgetClass Dialog -configspec {
	{ -defaultfocus defaultFocus DefaultFocus {} config_defaultfocus } 
	{ -title title Title {} config_wm_option }
	{ -transient transient Transient {} config_transient }
	{ -result result Result {} config_result cget_result }
	{ -modal modal Modal 1 config_option }
	{ -closecmd closeCmd CloseCmd {} config_option }
}
Dialog instproc create_root_widget { path } {
	toplevel $path -class [$self info class]
	wm withdraw $path
	wm protocol $path WM_DELETE_WINDOW "$self cancel"
}
Dialog instproc config_defaultfocus { option args } {
	if { [llength $args]==0 } {
		return [$self set default_focus_]
	} else {
		$self set default_focus_ [string trim [lindex $args 0]]
	}
}
Dialog instproc config_wm_option { option args } {
	if { [llength $args]==0 } {
		return [wm [string range [string trim $option] 1 end] \
				[$self info path]]
	} else {
		wm [string range [string trim $option] 1 end] \
				[$self info path] [lindex $args 0]
	}
}
Dialog instproc config_transient { option args } {
	set path [$self info path]
	if { [llength $args]==0 } {
		return [wm transient $path]
	} else {
		set is_mapped [winfo ismapped $path]
		wm transient $path [lindex $args 0]
		if { !$is_mapped } {
			wm withdraw $path
		}
	}
}
Dialog instproc center { } {
	set path [$self info path]
	wm withdraw $path
	update idletasks
	update
	set x [expr [winfo screenwidth $path]/2 - [winfo reqwidth $path]/2 \
			- [winfo vrootx [winfo parent $path]]]
	set y [expr [winfo screenheight $path]/2 - [winfo reqheight $path]/2 \
			- [winfo vrooty [winfo parent $path]]]
	wm geom $path +$x+$y
	wm deiconify $path
	raise $path
}
Dialog instproc grab { {start_focus {}} } {
	$self instvar old_focus_ old_grab_ grab_status_	
	set path [$self info path]
	set old_focus_ [focus]
	set old_grab_ [grab current $path]
	if {$old_grab_ != ""} {
		set grab_status_ [grab status $old_grab_]
	}
	grab $path
	if { [string trim $start_focus]=={} } {
		set start_focus [$self cget -defaultfocus]
	}
	if { $start_focus != {} } {
		focus [eval [list $self] subwidget $start_focus]
	}
}
Dialog instproc release { } {
	$self instvar old_focus_ old_grab_ grab_status_
	catch {focus $old_focus_}
	grab release [$self info path]
	if {$old_grab_ != ""} {
		if {$grab_status_ == "global"} {
			grab -global $old_grab_
		} else {
			grab $old_grab_
		}
	}
}
Dialog instproc wait { } {
	$self tkvar result_
	catch { unset result_ }
	tkwait variable [$self tkvarname result_]
	return $result_
}
Dialog instproc invoke { {start_focus {}} } {
	$self instvar old_focus_ old_grab_ grab_status_
	set path [$self info path]
	$self center
	if { [$self cget -modal] } {
		$self grab $start_focus
		set result [$self wait]
		$self release
		wm withdraw $path
		$self invoke_closecmd
		return $result
	} else {
		if { [string trim $start_focus]=={} } {
			set start_focus [$self cget -defaultfocus]
		}
		if { $start_focus != {} } {
			focus [eval [list $self] subwidget $start_focus]
		}
		$self tkvar result_
		catch { unset result_ }
		trace variable result_ w "Dialog nonmodal_result_ [list $self]\
				; $self ignore_args"
		return ""
	}
}
Dialog instproc cancel { } {
	$self configure -result {}
}
Dialog instproc config_result { option value } {
	$self tkvar result_
	set result_ $value
}
Dialog instproc cget_result { option } {
	$self tkvar result_
	if { [info exists result_] } {
		return $result_
	} else {
		return ""
	}
}
Dialog instproc config_option { option args } {
	$self instvar config_
	if { [llength $args]==0 } {
		return $config_($option)
	} else {
		set config_($option) [lindex $args 0]
	}
}
Dialog instproc invoke_closecmd { } {
	set closecmd [$self cget -closecmd]
	if { [string trim $closecmd]!={} } {
		uplevel #0 $closecmd
	}
}
Dialog proc nonmodal_result_ { dlg } {
	if { [info command $dlg]==$dlg } {
		set path [$dlg info path]
		if { ![winfo exists $path] } return
		wm deiconify [$dlg info path]
		$dlg tkvar result_
		trace vdelete result_ w "Dialog nonmodal_result_ $dlg"
		$dlg invoke_closecmd
	}
}
Dialog proc transient { cl args } {
	set count 0
	set path .dialog__$count
	while { [winfo exists $path] } {
		set path .dialog__$count
		incr count
	}
	eval $cl [list $path] $args
	set modal [$path cget -modal]
	if { ! $modal } {
		set command [$path cget -closecmd]
		append command "; destroy $path"
		$path configure -closecmd $command
		return [$path invoke]
	} else {
		set result [$path invoke]
		destroy $path
		return $result
	}
}
WidgetClass CompoundButton -configspec {
	{ -relief relief Relief raised config_all }
	{ -background background Background WidgetDefault config_all }
	{ -foreground foreground Foreground WidgetDefault config_all }
	{ -state state State normal config_all }
	{ -font font Font WidgetDefault config_all }
	{ -command command Command "" config_command }
} -alias {
	{ -bg -background }
	{ -fg -foreground }
} -default {
	{ .highlightThickness WidgetDefault }
	{ .takeFocus 1 }
	{ .borderWidth WidgetDefault }
	{ .relief raised }
}
CompoundButton proc root { className path } {
	while { $path!="" && [winfo class $path]!=$className } {
		set path [winfo parent $path]
	}
	return $path
}
CompoundButton proc init_ { cl } {
	$self instvar init_done_
	if [info exists init_done_($cl)] return
	set init_done_($cl) 1
	bind $cl <B1-Motion> "\[$self root $cl %W\] b1_motion %W %x %y"
	bind $cl <Button-1>  "\[$self root $cl %W\] button_down"
	bind $cl <ButtonRelease-1> "\[$self root $cl %W\] button_up"
}
CompoundButton instproc init { args } {
	CompoundButton init_ [$self info class]
	eval [list $self] next $args
	$self set button_down_ 0
	$self set entered_ 0
}
CompoundButton instproc build_widget { path } {
	bind $path <Enter> "$self enter"
	bind $path <Leave> "$self leave"
	bind $path <Key-space> "$self invoke_with_ui"
}
CompoundButton instproc add { args } {
	set widget_type [lindex $args 0]
	set subwidget   [lindex $args 1]
	set path        [$self info path].$subwidget
	eval [list $widget_type] [list $path] [lrange $args 2 end]
	$self instvar config_
	foreach name [array names config_] {
		$path configure $name $config_($name)
	}
	if { ![catch {$path configure -takefocus}] } {
		$path configure -takefocus 0
	}
	if { ![catch {$path configure -highlightthickness}] } {
		$path configure -highlightthickness 0
	}
	set tags [bindtags $path]
	set idx [lsearch $tags [winfo class $path]]
	if { $idx!=-1 } {
		set tags [lreplace $tags $idx $idx]
	}
	set cl [$self info class]
	if { [lsearch $tags $cl] == -1 } {
		set tags [concat $cl $tags]
	}
	bindtags $path $tags
	return $subwidget
}
CompoundButton instproc remove { subwidget } {
	destroy [$self info path].$subwidget
}
CompoundButton instproc invoke { } {
	set command [$self cget -command]
	if { [string trim $command]!={} } {
		uplevel #0 $command
	}
}
CompoundButton instproc config_command { option args } {
	$self instvar config_
	if { [llength $args] == 0 } {
		return $config_(-command)
	} else {
		set config_(-command) [lindex $args 0]
	}
}
CompoundButton instproc config_all { option args } {
	$self instvar config_
	if { [llength $args]==0 } {
		return $config_($option)
	} else {
		set value [lindex $args 0]
		set config_($option) $value
		if { ![catch {$self widget_proc configure $option}] } {
			$self widget_proc configure $option $value
		}
		foreach child [winfo children [$self info path]] {
			if { ![catch {$child configure $option}] } {
				$child configure $option $value
			}
		}
	}
}
CompoundButton instproc button_down { } {
	$self instvar button_down_ saved_relief_
	set saved_relief_ [$self cget -relief]
	if { [$self cget -state] != "disabled" } {
		set button_down_ 1
		$self configure -relief sunken
	}
}
CompoundButton instproc button_up { } {
	$self instvar entered_ button_down_ saved_relief_
	if { $button_down_ } {
		set button_down_ 0
		$self configure -relief $saved_relief_
		if { $entered_ && [$self cget -state] != "disabled" } {
			$self invoke
		}
	}
}
CompoundButton instproc b1_motion { widget x y } {
	$self instvar button_down_ entered_
	if { !$button_down_ } return
	set root [$self info path]
	if { $widget!=$root } {
		incr x [winfo x $widget]
		incr y [winfo y $widget]
	}
	if { $x >= 0 && $y >= 0 && $x < [winfo width $root] && \
			$y < [winfo height $root] } {
		if { ! $entered_ } {
			$self enter
		}
	} else {
		if { $entered_ } {
			$self leave
		}
	}
}
CompoundButton instproc enter { } {
	$self instvar entered_ button_down_
	if { [$self cget -state] != "disabled" } {
		if { $button_down_ } {
			$self configure -relief sunken
		}
		set entered_ 1
	}
}
CompoundButton instproc leave { } {
	$self instvar entered_ button_down_ saved_relief_
	if { $button_down_ } {
		$self configure -relief $saved_relief_
	}
	set entered_ 0
}
CompoundButton instproc invoke_with_ui { } {
	if {[$self cget -state] != "disabled"} {
		set oldRelief [$self cget -relief]
		$self configure -relief sunken
		update idletasks
		after 100
		$self configure -relief $oldRelief
		$self invoke
	}
}
WidgetClass ImageTextButton -superclass CompoundButton -configspec {
	{ -orient orient Orient horizontal config_orient }
	{ -style style Style imagetext config_style }
	{ -image image Image {} config_imageoption }
	{ -text text Text {} config_textoption }
	{ -underline underline Underline -1 config_textoption }
	{ -command command Command {} config_textoption }
} -alias {
	{ -under -underline }
} -default {
	{ *Button.borderWidth 0 }
	{ *Button.highlightThickness 0 }
	{ *Button.padX 1 }
	{ *Button.padY 1 }
}
ImageTextButton instproc build_widget { path } {
	$self next $path
	$self add button image
	$self add button text
}
ImageTextButton instproc repack { } {
	set path   [$self info path]
	catch { pack forget $path.image }
	catch { pack forget $path.text  }
	switch [$self cget -orient] {
		horizontal {
			set side left
		}
		vertical -
		default {
			set side top
		}
	}
	switch [$self cget -style] {
		imagetext {
			set list "[list $path.image] [list $path.text]"
		}
		image {
			set list $path.image
		}
		text {
			set list $path.text
		}
	}
	eval pack $list -side [list $side] -expand 1 -fill both -padx 2
}
ImageTextButton instproc config_orient { option {orient {}} } {
	$self instvar orient_
	switch -exact -- $orient {
		{} {
			if { [info exists orient_] } {
				return $orient_
			} else {
				return vertical
			}
		}
		vertical -
		horizontal {
			set orient_ $orient
			$self repack
		}
		default {
			error "invalid orientation $orient"
		}
	}
}
ImageTextButton instproc config_style { option {style {}} } {
	$self instvar style_
	switch -exact -- $style {
		{} {
			if { [info exists style_] } {
				return $style_
			} else {
				return imagetext
			}
		}
		imagetext -
		image -
		text {
			set style_ $style
			$self repack
		}
		default {
			error "invalid style $style"
		}
	}
}
ImageTextButton instproc config_imageoption { option args } {
	if { [llength $args]==0 } {
		return [$self subwidget image cget $option]
	} else {
		$self subwidget image configure $option [lindex $args 0]
	}
}
ImageTextButton instproc config_textoption { option args } {
	if { [llength $args]==0 } {
		return [$self subwidget text cget $option]
	} else {
		$self subwidget text configure $option [lindex $args 0]
	}
}
WidgetClass LabeledWidget -configspec {
	{ -label  label Label {} config_label }
	{ -underline underline Underline -1 config_underline }
	{ -widget widget Widget {} config_widget }
	{ -orient orient Orient horizontal config_orient }
} -alias {
	{ -under -underline }
}
LabeledWidget instproc build_widget { path } {
	label $path.label -anchor w
	$self set widget_ ""
}
LabeledWidget instproc config_label { option args } {
	if { [llength $args]==0 } {
		return [$self subwidget label cget -text]
	} else {
		$self subwidget label configure -text [lindex $args 0]
	}
}
LabeledWidget instproc config_underline { option args } {
	if { [llength $args]==0 } {
		return [$self subwidget label cget -underline]
	} else {
		$self subwidget label configure -underline [lindex $args 0]
	}
}
LabeledWidget instproc config_widget { option args } {
	$self instvar widget_
	if { [llength $args]==0 } {
		return $widget_
	} else {
		set widget [lindex $args 0]
		if { $widget != "" && [winfo parent $widget]!=[winfo parent \
				[$self info path]] } {
			error "\"$widget\" must have the same parent as\
					\"[$self info path]\""
		}
		catch { pack forget $widget_ }
		set widget_ $widget
		$self repack
	}
}
LabeledWidget instproc config_orient { option args } {
	$self instvar orient_
	if { [llength $args]==0 } {
		if { [info exists orient_] } {
			return $orient_
		} else {
			return horizontal
		}
	} else {
		$self set orient_ [lindex $args 0]
		$self repack
	}
}
LabeledWidget instproc repack { } {
	$self instvar widget_
	set label [$self subwidget label]
	catch { pack forget $label $widget_ }
	set orient [$self cget -orient]
	switch -exact -- $orient {
		horizontal {
			set side left
			set label_fill x
		}
		vertical {
			set side top
			set label_fill y
		}
		default {
			error "invalid orientation \"$orient\""
		}
	}
	pack $label -side $side -fill $label_fill -anchor w
	if { $widget_!="" } {
		set path [$self info path]
		pack $widget_ -side $side -fill both -expand 1 -in $path
		raise $widget_ $path
	}
}
set imageObject__ [new Image/GIF "\107\111\106\70\71\141\26\134\43\24\134\43\302\134\43\134\43\330\330\330\370\374\370\134\43\134\43\134\43\70\370\60\200\200\200\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\41\371\4\1\134\43\134\43\134\43\134\43\54\134\43\134\43\134\43\134\43\26\134\43\24\134\43\134\43\3\123\10\272\334\376\120\205\40\142\234\103\20\142\33\316\133\267\174\202\306\111\323\103\232\47\20\14\231\367\146\354\70\233\50\134\134\156\255\13\203\234\17\260\347\323\155\204\73\142\21\106\100\326\74\277\201\223\247\212\106\223\112\211\125\367\204\314\176\130\221\134\43\334\355\224\302\242\5\57\224\146\120\333\360\106\2\134\43\73"]
image create photo Icons(check) -data $imageObject__
set imageObject__ [new Image/GIF "\107\111\106\70\71\141\24\134\43\24\134\43\302\134\43\134\43\330\330\330\370\374\370\134\43\134\43\134\43\370\24\100\200\200\200\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\41\371\4\1\134\43\134\43\134\43\134\43\54\134\43\134\43\134\43\134\43\24\134\43\24\134\43\134\43\3\126\10\272\274\21\55\212\366\306\210\312\116\27\354\330\214\47\154\225\46\20\215\367\1\345\167\22\250\43\12\235\11\303\114\255\332\67\266\153\267\230\157\367\22\16\211\306\43\21\263\370\251\100\251\31\21\232\231\265\134\134\306\347\253\64\352\125\261\267\116\327\13\340\305\36\305\344\70\31\214\264\335\311\5\216\331\110\134\43\134\43\73"]
image create photo Icons(cross) -data $imageObject__
set imageObject__ [new Image/GIF "\107\111\106\70\71\141\22\134\43\22\134\43\302\134\43\134\43\330\330\330\134\43\134\43\134\43\370\374\370\270\274\270\70\370\60\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\41\371\4\1\134\43\134\43\134\43\134\43\54\134\43\134\43\134\43\134\43\22\134\43\22\134\43\134\43\3\112\10\272\334\376\360\205\71\243\232\42\347\52\363\40\104\60\154\116\40\14\50\50\242\103\320\230\254\312\266\14\34\207\63\175\11\140\357\343\256\335\357\47\12\2\114\224\200\52\251\73\236\156\53\226\321\11\235\115\251\51\234\264\44\235\154\45\121\24\47\222\274\132\42\11\134\43\73"]
image create photo Icons(plus) -data $imageObject__
set imageObject__ [new Image/GIF "\107\111\106\70\71\141\22\134\43\22\134\43\302\134\43\134\43\330\330\330\134\43\134\43\134\43\370\374\370\270\274\270\70\370\60\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\41\371\4\1\134\43\134\43\134\43\134\43\54\134\43\134\43\134\43\134\43\22\134\43\22\134\43\134\43\3\101\10\272\334\376\360\205\71\243\232\42\347\52\363\370\337\346\4\2\150\202\101\103\236\147\272\254\154\373\12\104\155\337\301\340\2\344\355\23\271\35\211\102\44\352\146\61\31\62\171\144\300\222\273\27\63\352\314\231\70\221\242\145\273\110\134\43\134\43\73"]
image create photo Icons(minus) -data $imageObject__
set imageObject__ [new Image/GIF "\107\111\106\70\71\141\24\134\43\24\134\43\302\134\43\134\43\330\330\330\120\124\120\134\43\134\43\134\43\270\274\270\370\374\370\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\41\371\4\1\134\43\134\43\134\43\134\43\54\134\43\134\43\134\43\134\43\24\134\43\24\134\43\134\43\3\134\134\10\272\334\356\41\312\327\242\270\170\104\32\260\317\301\43\175\327\4\21\232\44\15\32\24\14\4\312\6\162\272\274\132\254\301\173\72\53\253\330\13\365\122\205\30\64\42\257\270\71\11\227\273\143\5\106\30\106\233\225\130\25\152\312\52\225\105\21\325\212\303\42\265\270\136\13\302\222\105\164\153\27\153\116\224\162\214\166\212\276\221\134\43\134\43\73"]
image create photo Icons(trashcan) -data $imageObject__
set imageObject__ [new Image/GIF "\107\111\106\70\71\141\50\134\43\50\134\43\302\134\43\134\43\330\330\330\170\174\134\43\370\374\134\43\270\274\270\134\43\134\43\134\43\170\174\170\134\43\134\43\134\43\134\43\134\43\134\43\41\371\4\1\134\43\134\43\134\43\134\43\54\134\43\134\43\134\43\134\43\50\134\43\50\134\43\134\43\3\270\10\272\334\376\60\312\111\253\275\70\353\27\372\316\201\40\14\304\147\205\342\110\24\346\204\246\53\333\162\151\112\26\362\314\274\165\254\357\265\332\55\247\343\5\175\77\143\160\230\264\21\236\3\30\256\330\173\76\235\323\26\317\172\225\22\65\106\56\101\210\334\204\271\307\54\70\50\20\57\313\30\145\300\252\204\237\330\52\50\233\31\307\267\273\154\166\56\176\2\163\112\42\174\25\207\210\4\121\176\202\20\213\60\204\52\152\22\222\224\75\226\221\231\44\215\204\211\234\224\150\204\220\13\230\42\244\176\241\15\250\171\216\245\233\100\231\264\136\137\247\265\265\103\267\270\271\240\61\262\73\142\303\304\303\70\307\24\307\312\313\314\315\301\17\316\321\316\77\324\325\326\327\330\11\134\43\73"]
image create photo Icons(warning) -data $imageObject__
set imageObject__ [new Image/GIF "\107\111\106\70\71\141\20\134\43\12\134\43\241\134\43\134\43\330\330\330\370\374\370\134\43\134\43\134\43\200\200\200\41\371\4\1\134\43\134\43\134\43\134\43\54\134\43\134\43\134\43\134\43\20\134\43\12\134\43\134\43\2\35\204\217\171\301\355\201\202\230\264\212\21\155\35\70\153\256\134\43\322\326\205\343\125\206\42\252\266\356\133\134\43\134\43\73"]
image create photo Icons(minimize) -data $imageObject__
set imageObject__ [new Image/GIF "\107\111\106\70\71\141\20\134\43\12\134\43\241\134\43\134\43\330\330\330\370\374\370\134\43\134\43\134\43\200\200\200\41\371\4\1\134\43\134\43\134\43\134\43\54\134\43\134\43\134\43\134\43\20\134\43\12\134\43\134\43\2\35\204\217\251\26\273\41\206\103\120\304\11\252\275\157\173\231\150\236\5\62\343\131\2\303\312\266\51\226\24\134\43\73"]
image create photo Icons(maximize) -data $imageObject__
set imageObject__ [new Image/GIF "\107\111\106\70\71\141\24\134\43\17\134\43\362\134\43\134\43\330\330\330\177\177\177\377\377\134\43\377\377\377\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\41\371\4\1\134\43\134\43\134\43\134\43\54\134\43\134\43\134\43\134\43\24\134\43\17\134\43\134\43\3\101\10\272\334\276\41\306\367\2\20\27\130\12\63\306\222\344\4\103\151\236\145\100\64\344\347\171\52\73\274\56\270\62\55\15\337\320\134\134\277\61\334\340\127\13\366\164\56\243\42\107\274\50\65\241\150\210\267\40\130\257\130\54\147\313\110\134\43\134\43\73"]
image create photo Icons(folder) -data $imageObject__
set imageObject__ [new Image/GIF "\107\111\106\70\71\141\24\134\43\17\134\43\302\134\43\134\43\330\330\330\170\174\170\370\374\370\270\274\270\370\374\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\41\371\4\1\134\43\134\43\134\43\134\43\54\134\43\134\43\134\43\134\43\24\134\43\17\134\43\134\43\3\105\10\272\334\316\41\306\367\202\270\67\120\50\6\361\203\40\111\216\365\235\41\46\26\215\5\242\150\300\56\143\75\22\62\247\356\362\220\323\35\330\253\20\231\1\137\110\331\17\50\104\21\215\114\344\111\6\125\330\154\205\252\42\313\355\166\67\340\105\2\134\43\73"]
image create photo Icons(folderopen) -data $imageObject__
set imageObject__ [new Image/GIF "\107\111\106\70\71\141\24\134\43\17\134\43\362\134\43\134\43\330\330\330\177\177\177\377\377\134\43\377\377\377\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\41\371\4\1\134\43\134\43\134\43\134\43\54\134\43\134\43\134\43\134\43\24\134\43\17\134\43\134\43\3\105\10\272\334\276\41\306\367\2\20\27\130\12\63\306\222\344\4\103\151\236\145\100\64\344\27\174\236\312\16\227\4\203\53\323\206\157\234\103\64\220\47\43\323\15\134\134\267\332\117\101\42\362\160\263\344\255\10\341\131\43\113\5\141\313\355\166\71\140\106\2\134\43\73"]
image create photo Icons(folderup) -data $imageObject__
set imageObject__ [new Image/GIF "\107\111\106\70\71\141\17\134\43\17\134\43\241\134\43\134\43\330\330\330\170\174\170\370\374\370\134\43\134\43\134\43\41\371\4\1\134\43\134\43\134\43\134\43\54\134\43\134\43\134\43\134\43\17\134\43\17\134\43\134\43\2\62\204\217\151\301\315\12\202\230\263\51\111\205\113\222\325\66\40\130\126\205\107\347\224\42\111\5\346\242\245\332\33\261\352\31\67\67\154\273\242\3\244\1\6\304\242\21\202\64\24\134\43\134\43\73"]
image create photo Icons(textfile) -data $imageObject__
set imageObject__ [new Image/GIF "\107\111\106\70\71\141\22\134\43\22\134\43\204\134\43\134\43\330\330\330\170\174\170\134\43\370\360\360\370\360\134\43\134\43\134\43\360\374\360\134\43\374\360\134\43\370\370\360\370\370\134\43\170\170\134\43\374\370\370\370\360\134\43\174\170\134\43\134\43\360\134\43\134\43\170\134\43\134\43\370\134\43\134\43\160\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\41\371\4\1\134\43\134\43\134\43\134\43\54\134\43\134\43\134\43\134\43\22\134\43\22\134\43\134\43\5\144\40\40\216\144\151\212\101\32\234\145\52\14\57\101\260\100\134\43\303\205\220\317\147\140\14\277\327\141\300\153\275\4\210\237\62\121\34\331\24\260\5\122\260\140\64\121\57\45\20\310\64\331\250\103\341\300\332\313\231\165\344\336\21\361\142\60\257\43\31\143\156\45\64\32\360\270\214\340\160\30\356\171\47\16\2\200\64\45\203\17\170\206\44\20\177\201\47\62\213\64\41\134\43\73"]
image create photo Icons(browse) -data $imageObject__
set imageObject__ [new Image/GIF "\107\111\106\70\71\141\11\134\43\10\134\43\241\134\43\134\43\330\330\330\370\374\370\134\43\134\43\134\43\200\200\200\41\371\4\1\134\43\134\43\134\43\134\43\54\134\43\134\43\134\43\134\43\11\134\43\10\134\43\134\43\2\25\204\21\247\41\243\50\242\63\54\112\150\355\10\134\134\217\11\150\17\360\115\5\134\43\73"]
image create photo Icons(up) -data $imageObject__
set imageObject__ [new Image/GIF "\107\111\106\70\71\141\11\134\43\10\134\43\241\134\43\134\43\330\330\330\370\374\370\134\43\134\43\134\43\200\200\200\41\371\4\1\134\43\134\43\134\43\134\43\54\134\43\134\43\134\43\134\43\11\134\43\10\134\43\134\43\2\24\4\202\141\33\342\143\222\23\3\266\71\55\246\54\257\310\175\6\264\24\134\43\73"]
image create photo Icons(down) -data $imageObject__
set imageObject__ [new Image/GIF "\107\111\106\70\71\141\11\134\43\10\134\43\241\134\43\134\43\330\330\330\370\374\370\134\43\134\43\134\43\200\200\200\41\371\4\1\134\43\134\43\134\43\134\43\54\134\43\134\43\134\43\134\43\11\134\43\10\134\43\134\43\2\25\204\43\143\213\222\354\242\152\321\215\200\321\330\12\320\356\125\17\125\15\5\134\43\73"]
image create photo Icons(fastup) -data $imageObject__
set imageObject__ [new Image/GIF "\107\111\106\70\71\141\11\134\43\10\134\43\241\134\43\134\43\330\330\330\134\43\134\43\134\43\200\200\200\370\374\370\41\371\4\1\134\43\134\43\134\43\134\43\54\134\43\134\43\134\43\134\43\11\134\43\10\134\43\134\43\2\23\104\216\41\60\251\134\43\333\131\154\330\27\335\144\216\362\15\145\136\1\134\43\73"]
image create photo Icons(fastdown) -data $imageObject__
set imageObject__ [new Image/GIF "\107\111\106\70\71\141\34\134\43\24\134\43\245\134\43\134\43\370\370\370\340\340\370\230\230\340\150\150\300\370\340\370\134\43\134\43\300\134\43\134\43\230\134\43\134\43\150\300\230\150\370\370\300\250\300\370\340\300\134\43\300\300\230\300\300\134\43\150\134\43\300\340\340\300\370\370\340\150\150\150\250\254\230\150\134\43\150\340\340\134\43\370\370\230\150\150\340\230\150\134\43\150\150\134\43\300\300\340\340\340\150\300\230\134\43\370\370\150\340\370\370\230\150\150\370\370\134\43\134\43\150\340\230\150\300\340\340\340\300\300\150\370\340\134\43\150\150\230\230\230\300\134\43\150\300\150\134\43\230\340\340\230\134\43\134\43\340\230\230\230\300\230\300\230\230\134\43\340\300\150\300\230\340\370\340\150\370\340\230\370\340\300\340\300\230\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\134\43\41\371\4\1\134\43\134\43\134\43\134\43\54\134\43\134\43\134\43\134\43\34\134\43\24\134\43\134\43\6\375\100\200\160\110\54\32\217\110\100\100\60\150\22\222\120\245\240\140\60\34\14\210\104\62\200\124\120\253\13\206\241\241\65\6\12\216\7\244\50\250\32\42\15\111\141\102\131\263\251\207\205\135\330\256\322\37\163\13\25\106\26\125\27\30\24\104\31\137\6\13\11\4\31\32\203\154\125\33\21\33\223\112\214\15\34\104\1\4\35\240\134\43\213\6\33\36\21\211\103\205\206\37\103\113\5\5\40\5\41\42\124\227\245\231\1\156\215\166\147\273\6\27\43\206\300\44\104\253\300\235\232\225\45\140\46\156\164\173\134\43\3\156\15\223\175\33\15\206\44\47\156\202\105\323\225\203\276\36\15\124\320\137\325\204\156\50\51\1\40\277\245\51\52\324\107\35\214\6\367\273\124\36\53\125\54\134\134\105\2\230\30\200\342\300\204\26\54\340\35\150\341\202\24\76\21\107\136\344\203\127\5\226\241\124\256\346\255\243\270\353\340\2\30\321\134\43\264\271\320\300\205\206\30\51\144\244\170\200\62\305\14\15\51\122\304\110\20\122\110\134\43\21\20\152\106\51\22\4\134\43\73"]
image create photo Icons(cal) -data $imageObject__
set imageObject__ [new Image/GIF "\107\111\106\70\67\141\15\134\43\24\134\43\360\134\43\134\43\377\377\377\134\43\134\43\134\43\54\134\43\134\43\134\43\134\43\15\134\43\24\134\43\134\43\2\55\204\217\11\301\235\254\240\11\152\322\145\35\306\162\172\172\65\20\10\162\143\145\155\110\130\256\254\232\225\127\105\242\134\134\344\314\250\356\255\221\377\113\341\64\207\2\134\43\73"]
image create photo Icons(ear) -data $imageObject__
set imageObject__ [new Image/GIF "\107\111\106\70\67\141\20\134\43\20\134\43\360\134\43\134\43\377\377\377\134\43\134\43\134\43\54\134\43\134\43\134\43\134\43\20\134\43\20\134\43\134\43\2\51\204\17\21\310\271\353\40\202\312\120\106\157\332\107\147\316\171\226\3\116\326\327\164\222\324\150\151\7\277\343\374\262\45\326\246\166\154\352\271\121\134\43\134\43\73"]
image create photo Icons(hand) -data $imageObject__
WidgetClass MessageBox -superclass Dialog -configspec {
	{ -image image Image {} config_image  }
	{ -text  text  Text  {} config_text   }
	{ -type  type  Type  {ok} config_type }
} -default {
	{ .transient . }
	{ .title "Message" }
	{ *image.padX 10 }
	{ *image.padY 5 }
	{ *text.wrapLength 3i }
	{ *ImageTextButton.borderWidth 1 }
	{ *ImageTextButton.highlightThickness 1 }	
}
MessageBox instproc build_widget { path } {
	frame $path.bot -relief raised -bd 1
	pack  $path.bot -side bottom -fill x
	frame $path.top -relief raised -bd 1
	pack  $path.top -side top -fill both -expand 1
	label $path.image
	label $path.text -justify left
	pack $path.image -side left -in $path.top
	pack $path.text -side right -fill both -expand 1 -in $path.top
}
MessageBox instproc config_image { option args } {
	if { [llength $args]==0 } {
		return [$self subwidget image cget -image]
	} else {
		$self subwidget image configure -image [lindex $args 0]
	}
}
MessageBox instproc config_text { option args } {
	if { [llength $args]==0 } {
		return [$self subwidget text cget -text]
	} else {
		$self subwidget text configure -text [lindex $args 0]
	}
}
MessageBox instproc config_type { option args } {
	if { [llength $args]==0 } {
		return [$self set type_]
	}
	$self instvar type_
	set type_ [lindex $args 0]
	foreach button [pack slaves [$self subwidget bot]] {
		destroy $button
	}
	switch -exact -- $type_ {
		abortretryignore {
			set buttons {
				{abort  -text Abort -under 0 \
						-image Icons(cross)}
				{retry  -text Retry -under 0 
						-image Icons(redo) }
				{ignore -text Ignore -under 0 -style text}
			}
		}
		ok {
			set buttons {
				{ok -text OK -under 0 -image Icons(check)}
			}
		}
		okcancel {
			set buttons {
				{ok -text OK -under 0 -image Icons(check) }
				{cancel -text Cancel -under 0 \
						-image Icons(cross) }
			}
		}
		retrycancel {
			set buttons {
				{retry  -text Retry  -under 0 \
						-image Icons(redo) }
				{cancel -text Cancel -under 0 \
						-image Icons(cross) }
			}
		}
		yesno {
			set buttons {
				{yes -text Yes -under 0 -image Icons(check) }
				{no  -text No  -under 0 -image Icons(cross) }
			}
		}
		yesnocancel {
			set buttons {
				{yes -text Yes -under 0 -image Icons(check) }
				{no  -text No  -under 0 -image Icons(cross) }
				{cancel -text Cancel -under 0 -style text}
			}
		}
		none {
			set buttons {}
		}
		default {
			set buttons $type_
		}
	}
	set i 0
	set path [$self info path]
	foreach button [subst $buttons] {
		set name [lindex $button 0]
		set opts [lrange $button 1 end]
		if ![string compare $opts {}] {
			set capName [string toupper [string index \
					$name 0]][string range $name 1 end]
			set opts [list -text $capName]
		}
		eval ImageTextButton $path.$name $opts -orient horizontal \
				-command [list "$self configure -result $name"]
		pack $path.$name -in $path.bot -side left -expand 1 -fill y \
				-padx 3m -pady 2m
		set underIdx [$path.$name cget -under]
		if {$underIdx >= 0} {
			set key [string index [$path.$name cget -text] \
					$underIdx]
			bind $path <Alt-[string tolower $key]> \
					"$path.$name invoke_with_ui"
			bind $path <Alt-[string toupper $key]> \
					"$path.$name invoke_with_ui"
			bind $path <KeyPress-[string tolower $key]> \
					"$path.$name invoke_with_ui"
			bind $path <KeyPress-[string toupper $key]> \
					"$path.$name invoke_with_ui"
		}
		incr i
	}
}
MessageBox instproc config_type_ { option args } {
	if { [llength $args]==0 } {
		return [$self set type_]
	}
	$self instvar type_
	set type_ [lindex $args 0]
	set path [$self info path]
	foreach button [pack slaves [$self subwidget bot]] {
		if { $button == "$path.default" } {
			eval destroy [pack slaves $button]
		}
		destroy $button
	}
	switch -exact -- $type_ {
		abortretryignore {
			set buttons {
				{abort  -width 6 -text Abort -under 0 \
						-image Icons(cross)}
				{retry  -width 6 -text Retry -under 0 \
						-image Icons(redo) }
				{ignore -width 6 -text Ignore -under 0}
			}
		}
		ok {
			set buttons {
				{ok -width 6 -text OK -under 0 \
						-image Icons(check)}
			}
		}
		okcancel {
			set buttons {
				{ok     -width 6 -text OK     -under 0 \
						-image Icons(check) }
				{cancel -width 6 -text Cancel -under 0 \
						-image Icons(cross) }
			}
		}
		retrycancel {
			set buttons {
				{retry  -width 6 -text Retry  -under 0 \
						-image Icons(redo) }
				{cancel -width 6 -text Cancel -under 0 \
						-image Icons(cross) }
			}
		}
		yesno {
			set buttons {
				{yes    -width 6 -text Yes -under 0 \
						-image Icons(check) }
				{no     -width 6 -text No  -under 0 \
						-image Icons(cross) }
			}
		}
		yesnocancel {
			set buttons {
				{yes    -width 6 -text Yes -under 0 \
						-image Icons(check) }
				{no     -width 6 -text No  -under 0 \
						-image Icons(cross) }
				{cancel -width 6 -text Cancel -under 0}
			}
		}
		default {
			error "invalid message box type \"$type_\",\
					must be abortretryignore, ok,\
					okcancel, retrycancel, yesno or\
					yesnocancel"
		}
	}
	set default [$self cget -default]
	if { $default=="" } {
		set default [lindex [lindex $buttons 0] 0]
		$self configure -default $default
	} else {
		set valid 0
		foreach button $buttons {
			if { ![string compare $default [lindex $button 0]] } {
				set valid 1
				break
			}
		}
		if { ! $valid } {
			error "invalid default button \"$default\""
		}
	}
	set i 0
	set path [$self info path]
	foreach button [subst $buttons] {
		set name [lindex $button 0]
		set opts [lrange $button 1 end]
		if ![string compare $opts {}] {
			set capName [string toupper [string index \
					$name 0]][string range $name 1 end]
			set opts [list -text $capName]
		}
		eval ImageTextButton $path.$name $opts \
				-command [list "$self configure -result $name"]
		if ![string compare $name $default] {
			frame $path.default -relief flat -bd 1 -bg black
			raise $path.$name $path.default
			pack $path.default -in $path.bot -side left -expand 1 \
					-padx 3m -pady 2m
			pack $path.$name -in $path.default
		} else {
			pack $path.$name -in $path.bot -side left -expand 1 \
					-padx 3m -pady 2m
		}
		set underIdx [$path.$name cget -under]
		if {$underIdx >= 0} {
			set key [string index [$path.$name cget -text] \
					$underIdx]
			bind $path <Alt-[string tolower $key]> \
					"$path.$name invoke_with_ui"
			bind $path <Alt-[string toupper $key]> \
					"$path.$name invoke_with_ui"
		}
		incr i
	}
	bind $path <Return> "$path.$default invoke_with_ui"
}
WidgetClass ProgressBar -configspec {
	{ -min min Min 0 config_min cget_min }
	{ -max max Max 100 config_max cget_max }
	{ -value val Val 0 config_value cget_value }
	{ -width width Width 200 config_width cget_width }
	{ -height height Height 20 config_height cget_height }
}
ProgressBar private build_widget { path } {
	$self set min_ 0
	$self set max_ 0
	$self set value_ 0
	canvas $path.canvas
	bind $path.canvas <Configure> "$self refresh"
	pack $path.canvas -side top -fill both -expand true
}
ProgressBar private config_min { option value } {
	$self instvar min_ max_
	set min_ $value
	if { $min_ > $max_ } { set max_ $min_ }
	$self do_when_idle "$self refresh"
}
ProgressBar private cget_min { option } {
	return [$self set min_]
}
ProgressBar private config_max { option value } {
	$self instvar min_ max_
	set max_ $value
	if { $min_ > $max_ } { set min_ $max_ }
	$self do_when_idle "$self refresh"
}
ProgressBar private cget_max { option } {
	return [$self set max_]
}
ProgressBar private config_value { option v } {
	$self instvar min_ max_
	if { $v < $min_ } { set v $min_ }
	if { $v > $max_ } { set v $max_ }
	$self set value_ $v
	$self do_when_idle "$self refresh"
}
ProgressBar private cget_value { option } {
	return [$self set value_]
}
ProgressBar instproc config_height { option height } {
	$self subwidget canvas configure -height $height
	$self do_when_idle "$self refresh"
}
ProgressBar instproc cget_height { option } {
	return [$self subwidget canvas cget -height]
}
ProgressBar instproc config_width { option width } {
	$self subwidget canvas configure -width $width
	$self do_when_idle "$self refresh"
}
ProgressBar instproc cget_width { option } {
	return [$self subwidget canvas cget -width]
}
ProgressBar instproc refresh { } {
	$self instvar min_ max_ value_
	set canv [$self subwidget canvas]
	set width  [winfo width $canv]
	set height [winfo height $canv]
	if {""==[$canv find withtag border]} {
		set t [$canv create rectangle 2 2 2 2]
		$canv addtag border withtag $t
	}
	$canv coords border 2 2 [expr $width - 2] [expr $height - 2]
	if {""==[$canv find withtag progress]} {
		set t [$canv create rectangle 2 2 2 2 -fill blue \
				-outline blue]
		$canv addtag progress withtag $t
	}
	if { $max_==$min_ } {
		set w 4
	} else {
		set w [expr 4 + ($width - 8)*($value_ - $min_)/($max_ - $min_)]
	}
	$canv coords progress 4 4 $w [expr $height - 4]
}
WidgetClass ProgressBox -superclass MessageBox -configspec {
	{ -min min Min 0 config_min cget_min }
	{ -max max Max 100 config_max cget_max }
	{ -text text Text {} config_text cget_text }
	{ -value val Val 0 config_value cget_value }
	{ -width width Width 200 config_width cget_width }
	{ -height height Height 20 config_height cget_height }
	{ -type type Type none config_type cget_type }
} 
ProgressBox instproc build_widget { path } {
	$self next $path
	canvas $path.progcanv
	pack $path.progcanv -side top -fill both -expand true
}
ProgressBox instproc config_text {args} {
	eval $self next $args
}
ProgressBox instproc config_min { option value } {
	$self set min_ $value
}
ProgressBox instproc cget_min { option } {
	return [$self set min_]
}
ProgressBox instproc config_max { option value } {
	$self set max_ $value
}
ProgressBox instproc cget_max { option } {
	return [$self set max_]
}
ProgressBox instproc config_value { option v } {
	$self set value_ $v
	$self do_when_idle "$self refresh"
}
ProgressBox instproc cget_value { option } {
	return [$self set value_]
}
ProgressBox instproc config_height { option height } {
	$self set height_ $height
	[$self subwidget progcanv] configure -height $height
	$self do_when_idle "$self refresh"
}
ProgressBox instproc cget_height { option } {
	return [$self set height_]
}
ProgressBox instproc config_width { option width } {
	$self set width_ $width
	[$self subwidget progcanv] configure -width $width
	$self do_when_idle "$self refresh"
}
ProgressBox instproc cget_width { option } {
	return [$self set width_]
}
ProgressBox instproc refresh { } {
	$self instvar min_ max_ value_ width_ height_
	if {!( [info exists min_] && [info exists max_] \
			&& [info exists value_] && [info exists width_] \
			&& [info exists height_] ) } {
		return
	}
	set canv [$self subwidget progcanv]
	$canv configure -width $width_ -height $height_
	if {""==[$canv find withtag border]} {
		set t [$canv create rectangle 2 2 2 2]
		$canv addtag border withtag $t
	}
	$canv coords border 2 2 [expr $width_ - 2] [expr $height_ - 2]
	if {""==[$canv find withtag progress]} {
		set t [$canv create rectangle 2 2 2 2 -fill blue \
				-outline blue]
		$canv addtag progress withtag $t
	}
	if { $max_==$min_ } {
		set w 4
	} else {
		set w [expr 4 + ($width_ - 8)*($value_ - $min_)/($max_-$min_)]
	}
	$canv coords progress 4 4 $w [expr $height_ - 4]
}
WidgetClass ScrolledWidget -configspec {
	{ -scrollbar scrollbar Scrollbar {none} config_scroll cget_scroll }
}
ScrolledWidget instproc build_widget { path } {
	$self instvar main_
	frame  $path.dummy -borderwidth 0 -relief flat
	set main_ [$self create_main_widget $path]
	scrollbar $path.vscroll -command "$main_ yview" -orient vertical
	scrollbar $path.hscroll -command "$main_ xview" \
			-orient horizontal
	$main_ configure -yscrollcommand "$path.vscroll set"
	$main_ configure -xscrollcommand "$path.hscroll set"
	pack $path.dummy -side top -fill both -expand 1
	pack $main_ -side left -anchor nw -fill both -expand 1 \
			-in $path.dummy
}
ScrolledWidget instproc create_main_widget { path } {
	error "cannot create object of class [$self info class];\
			every subclass MUST redefine the create_main_widget\
			method"
}
ScrolledWidget instproc config_scroll { option scroll } {
	$self instvar main_
	set path [$self info path]
	catch {
		pack forget $path.vscroll
		pack forget $path.hscroll
	}
	switch $scroll {
		horizontal {
			pack $path.hscroll -side bottom -fill x \
					-before $path.dummy
		}
		vertical {
			pack $path.vscroll -side right -fill y \
					-in $path.dummy -before $main_
		}
		both {
			pack $path.hscroll -side bottom -fill x \
					-before $path.dummy
			pack $path.vscroll -side right -fill y \
					-in $path.dummy -before $main_
		}
		auto {
			error "function not implemented"
		}
		default {
			set scroll none
		}
	}
	$self set scroll_ $scroll
}
ScrolledWidget instproc cget_scroll { option } {
	$self instvar scroll_
	if [info exists scroll_] { return $scroll_ } else { return none }
}
WidgetClass ScrolledCanvas -superclass ScrolledWidget
ScrolledCanvas instproc create_main_widget { path } {
	return [canvas $path.bbox]
}
WidgetClass ScrolledText -superclass ScrolledWidget
ScrolledText instproc create_main_widget { path } {
	return [text $path.text]
}
WidgetClass ScrolledWindow -superclass ScrolledCanvas
ScrolledWindow instproc build_widget { path } {
	$self next $path
	frame $path.bbox.window
	$path.bbox create window 0 0 -anchor nw -window $path.bbox.window
	$self set_subwidget window $path.bbox.window
	bind $path.bbox.window <Configure> "+$self ev_window_resize %w %h"
}
ScrolledWindow instproc ev_window_resize { width height } {
	[$self subwidget bbox] configure -scrollregion "0 0 $width $height"
}
WidgetClass ScrolledWindow/Expand -superclass ScrolledWindow
ScrolledWindow/Expand instproc build_widget { path } {
	$self next $path
	set dummy [frame [$self subwidget bbox].dummy_ -width 0 -height 0 \
			-relief flat -bg [[$self subwidget window] cget -bg]]
	pack $dummy -side top -in [$self subwidget window]
	bind [$self subwidget bbox] <Configure> "+$self ev_bbox_resize_ %w %h"
}
ScrolledWindow/Expand instproc ev_bbox_resize_ { w h } {
	set window [$self subwidget window]
	set bbox   [$self subwidget bbox]
	$bbox.dummy_ configure \
			-width [expr $w - ([$bbox cget -bd] + \
			[$window cget -bd] + [$bbox cget -highlightthickness] \
			+ [$window cget -highlightthickness]) * 2]
}
WidgetClass ScrolledText -superclass ScrolledWidget
ScrolledText instproc create_main_widget { path } {
	return [text $path.text]
}
image create photo SetupIcon -file lib/setup/setup.gif
WidgetClass SetupDialog -superclass Dialog -default {
	{ *Label.font WidgetDefault }
	{ *Button.borderWidth 1 }
	{ *Button.highlightThickness 1 }
}
SetupDialog private build_skeleton { path button_list } {
	frame $path.container
	label $path.logo -image SetupIcon
	frame $path.main
	pack $path.logo -padx 10 -pady 5 -side left -in $path.container
	pack $path.main -padx 10 -pady 5 -side left -fill both -expand 1 \
			-in $path.container
	frame $path.separator -height 2 -borderwidth 2 -relief groove
	frame $path.buttons
	foreach b $button_list {
		set b_name [string tolower $b]
		button $path.$b_name -text $b \
				-command "$self configure -result $b"
		pack $path.$b_name -side left -padx 3 -pady 0 -in $path.buttons
	}
	pack $path.buttons -anchor e -side bottom -pady 5
	pack $path.separator -padx 5 -pady 5 -fill x -side bottom
	pack $path.container -fill both -expand 1 -side top
	return $path.main
}
SetupDialog public verify { direction } {
	return 1
}
SetupDialog public interpret_result { result } {
	return $result
}
WidgetClass WelcomeDlg -superclass SetupDialog -default {
	{ .title "Welcome to Setup" }
}
WelcomeDlg private build_widget { path } {
	set setup [Setup instance]
	$setup instvar appname_
	set path [$self build_skeleton $path [list Next Cancel]]
	label $path.label -justify left -text \
			"Welcome to the $appname_ Setup program.\
			\n\nThis program will install $appname_ on \
			\nyour computer"
	pack $path.label -side top -padx 5 -pady 10
}
WidgetClass CopyrightDlg -superclass SetupDialog -default {
	{ .title "Copyright Message" }
	{ *Text*borderWidth 1 }
	{ *Scrollbar*borderWidth 1 }
	{ *Scrollbar*width 10 }
}
CopyrightDlg private build_widget { path } {
	set setup [Setup instance]
	$setup instvar copyright_
	if [catch {set file [open $copyright_ "r"]} ] {
		set msg "Could not open COPYRIGHT file: $copyright_"
	} else {
		set msg ""
		while { [gets $file line] >= 0 } {
			append msg "$line\n"
		}
		close $file		
	}
	set path [$self build_skeleton $path [list Accept Cancel]]
	ScrolledText $path.copyright -scrollbar both -options \
			{ {text.width 50} {text.height 16} {text.wrap none} }
	$path.copyright subwidget text insert end $msg
	$path.copyright subwidget text configure -state disabled
	pack $path.copyright -fill both -expand 1
}
CopyrightDlg private interpret_result { result } {
	if { $result=="accept" } { return "next" } else { return $result }
}
WidgetClass ChooseDstDlg -superclass SetupDialog -default {
	{ .title "Choose Destination Location" }
	{ *Entry.borderWidth 1 }
}
ChooseDstDlg private build_widget { path } {
	set setup [Setup instance]
	$setup instvar appname_
	set path [$self build_skeleton $path [list Back Next Cancel]]
	label $path.label -justify left -text \
			"Setup will install $appname_ in the following \
			directory\n\nTo install to this directory, click Next\
			\n\nTo install to a different directory, click Browse\
			\nand select another directory\
			\n\nYou can choose not to install $appname_, by\
			clicking\nCancel to exit Setup\n"
	$self tkvar dest_
	set dest_ [$setup set destination_]
	frame $path.frame -borderwidth 2 -relief groove
	entry $path.dest -textvariable [$self tkvarname dest_]
	button $path.browse -text "Browse..." -command "$self browse"
	pack $path.label -side top -pady 5 -padx 5
	pack $path.dest -in $path.frame -side left -fill both -expand 1 \
			-padx 5 -pady 2
	pack $path.browse -in $path.frame -side right -fill y -padx 5 -pady 2
	pack $path.frame -side top -padx 5 -pady 10 -fill x
}
ChooseDstDlg private browse { } {
	set setup [Setup instance]
	set dirdlg [$setup get_dirdlg]
	$self tkvar dest_
	set dirname [$setup get_real_dir $dest_]
	$dirdlg configure -title "Choose Destination Location"
	$dirdlg subwidget dirbox configure -allownonexistent 1
	$dirdlg configure -options [list [list dirbox.directory $dirname]]
	set retval [$dirdlg invoke]
	if { $retval!={} } {
		$self tkvar dest_
		set dest_ $retval
	}
}
ChooseDstDlg private verify { direction } {
	if { $direction=="back" } { return 1 }
	set setup [Setup instance]
	$self tkvar dest_
	$setup instvar destination_
	if [file isdirectory $dest_] {
		set destination_ $dest_
		return 1
	} elseif [file exists $dest_] {
		Dialog transient MessageBox \
				-text "\n\"$dest_\" is not a directory. Please\
				select a different directory.\n\n" \
				-image Icons(warning) -type ok
		return 0
	} else {
		set retval [Dialog transient MessageBox \
				-text "\nDirectory \"$dest_\" does not exist.\
				\nWould you like to create it?\n\n" \
				-image Icons(warning) -type yesno]
		if { $retval=="yes" } {
			set retval [$setup create_dir $dest_]
			if { $retval == {} } {
				set destination_ $dest_
				return 1
			} else {
				Dialog transient MessageBox -type ok -text \
						"\nError occurred while\
						creating \"$dest_\":\n$retval\n\
						\nPlease correct this problem\
						or select a different\
						directory\n\n" \
						-image Icons(warning) -type ok
				return 0
			}
		} else {
			return 0
		}
	}
}
WidgetClass InstallTypeDlg -superclass SetupDialog -default {
	{ .title "Select Installation Type" }
	{ *Radiobutton.borderWidth 1 }
}
InstallTypeDlg private build_widget { path } {
	set setup [Setup instance]
	$setup instvar install_types_
	set path [$self build_skeleton $path [list Back Next Cancel]]
	label $path.label -justify left -text \
			"Select the type of installation you would like\
			\nSetup to perform:"
	pack $path.label -side top -fill x -pady 5 -padx 5
	set cnt 0
	foreach type $install_types_ {
		set label [string toupper [string index $type 0]][string \
				tolower [string range $type 1 end]]
		set b [radiobutton $path.b$cnt -text $label -value $type \
				-anchor w \
				-variable [$self tkvarname installtype_]]
		pack $b -side top -anchor w -fill x -padx 15
		incr cnt
	}
	$self instvar help_
	set help_ [label $path.help -justify left -text {} -anchor sw]
	pack $path.help -side bottom -fill both -expand 1 -padx 5 \
			-pady 5
	$self tkvar installtype_
	trace variable installtype_ w "$self update_help; $self ignore_args"
	set installtype_ [lindex $install_types_ 0]
}
InstallTypeDlg private update_help { } {
	$self tkvar installtype_
	$self instvar help_
	set setup [Setup instance]
	$setup instvar install_types_ install_types_help_
	set idx [lsearch $install_types_ $installtype_]
	if { $idx >= 0 } {
		$help_ configure -text \
				[lindex $install_types_help_ $idx]
	} else {
		$help configure -text {}
	}
}
InstallTypeDlg private verify { direction } {
	if { $direction=="back" } { return 1 }
	$self tkvar installtype_
	set setup [Setup instance]
	if { [string tolower $installtype_]=="custom" } {
		while { 1 } {
			set retval [$setup do_dialog CustomDlg]
			if { $retval=={} } { set retval 1 }
			if { $retval!=0 } break
		}
		if { $retval==-1 } { return 0 }
		$setup set install_components_ \
			[.customdlg get_install_components]
	} else {
		$setup set install_components_ \
			[$setup set components_($installtype_)]	
	}
	return 1
}
WidgetClass CustomDlg -superclass SetupDialog -default {
	{ .title "Exit Setup" }
	{ *Checkbutton.borderWidth 1 }
}
CustomDlg private build_widget { path } {
	set setup [Setup instance]
	$setup instvar components_
	set path [$self build_skeleton $path "Back Next Cancel"]
	label $path.label -text \
			"Here is a list of components that Setup can install\
			\nto your system. You may customize your installation\
			\nby selecting or unselecting any of these components"
	pack $path.label -side top -pady 5 -padx 5
	frame $path.frame -borderwidth 2 -relief groove
	$self tkvar custom_
	set cnt 0
	foreach component $components_(custom) {
		if { [lsearch $components_(typical) $component] != -1 } {
			set custom_($component) 1
		} else {
			set custom_($component) 0
		}
		checkbutton $path.chk$cnt -text $component -anchor w -variable\
				[$self tkvarname custom_($component)]
		bind $path.chk$cnt <Enter> "$self update_help \{$component\}"
		pack $path.chk$cnt -fill x -padx 15
		incr cnt
	}
	pack $path.frame -side top -padx 5 -pady 10 -fill x
	$self instvar help_
	set help_ [label $path.help -justify left -text {} -anchor sw]
	pack $path.help -side bottom -fill both -expand 1 -padx 5 \
			-pady 5
}
CustomDlg private update_help { component } {
	set setup [Setup instance]
	$setup instvar component_help_
	$self instvar help_
	if [info exists component_help_($component)] {
		$help_ configure -text $component_help_($component)
	} else {
		$help_ configure -text ""
	}
}
CustomDlg public get_install_components { } {
	$self tkvar custom_
	set list {}
	foreach component [array names custom_] {
		if { $custom_($component)==1 } { lappend list $component }
	}
	return $list
}
WidgetClass CancelDlg -superclass SetupDialog -default {
	{ .title "Exit Setup" }
}
CancelDlg private build_widget { path } {
	set setup [Setup instance]
	$setup instvar appname_
	set path [$self build_skeleton $path [list Resume Exit]]
	$self subwidget logo configure -image Icons(warning)
	label $path.label -justify left -text \
			"Setup is not complete. If you quit the Setup program\
			\nnow, $appname_ will not be installed.\
			\n\nYou may run the Setup program at a later time to\
			\ncomplete the installation.\
			\n\nTo continue installing the program, click Resume.\
			\nTo quit the Setup program, click Exit."
	pack $path.label -side top -pady 10
}
WidgetClass SetupProgress -superclass Dialog -default {
	{ .title "Installation in progress" }
	{ *Label.font WidgetDefault }
}
SetupProgress private destroy { } {
	image delete image${self}_blank
}
SetupProgress private build_widget { path } {
	set cnt 0
	set blank [image create photo image${self}_blank]
	$blank copy Icons(check)
	$blank blank
	frame $path.list
	foreach item [$self checklist] {
		frame $path.f$cnt
		label $path.check$cnt -image $blank
		label $path.label$cnt -justify left -text $item -anchor w
		pack $path.check$cnt -in $path.f$cnt -side left
		pack $path.label$cnt -in $path.f$cnt -side left -fill both \
				-expand 1 -anchor w
		pack $path.f$cnt -fill x -side top -padx 5 -in $path.list
		incr cnt
	}
	pack $path.list -padx 5 -pady 10 -fill x -side top
	frame $path.separator -height 2 -borderwidth 2 -relief groove
	pack $path.separator -padx 5 -pady 5 -fill x -side top
	label $path.info -justify left -anchor w
	pack $path.info -fill x -padx 10
	ProgressBar $path.bar
	pack $path.bar -fill x -padx 10 -pady 10
}
SetupProgress public check { index } {
	if [winfo exists [$self info path].check$index] {
		$self subwidget check$index configure -image Icons(check)
	}
}
SetupProgress public check_next { } {
	$self instvar check_cnt_
	if { ![info exists check_cnt_] } {
		set check_cnt_ 0
	}
	$self check $check_cnt_
	incr check_cnt_
}
SetupProgress private checklist { } {
	return [list "Copy files"]
}
WidgetClass DropDown -configspec {
	{ -variable variable Variable {} config_var cget_var }
	{ -value value Value {} config_value cget_value }
	{ -state state State {normal} config_state }
} -alias {
	{ -var -variable }
} -default {
	{ *button.relief raised }
	{ *button.indicatorOn 1 }
	{ *button.highlightThickness 2 }
	{ *button.takeFocus 1 }
	{ *button.padX 2 }
	{ *button.padY 1 }
	{ *menu.tearOff 0 }
	{ *menu*borderWidth 1 }
	{ *menu*activeBorderWidth 1 }
}
DropDown instproc build_widget { path } {
	menubutton $path.button -menu $path.button.menu
	pack $path.button -fill both -expand 1 -padx 0 -pady 0 -side left
	menu $path.button.menu
	$self set_subwidget menu $path.button.menu
	$self config_var -variable {}
	set script [bind Menubutton <Key-space>]
	bind $path.button <Key-Down> $script
}
DropDown instproc config_var { option var } {
	$self instvar var_
	if { [info exists var_] && $var_!="" } {
		upvar #0 $var_ global_var
		catch { trace vdelete global_var w "$self var_trace" }
	}
	if { $var=="" } {
		set var_ [$self tkvarname defvar_]
	} else {
		set var_ $var
	}
	upvar #0 $var_ global_var
	trace variable global_var w "$self var_trace"
	if { ![info exists global_var] || $global_var=="" } {
		$self set_default_var
	} else {
		$self var_trace $var_ "" w
	}
}
DropDown instproc cget_var { option } {
	$self instvar var_
	if { $var_==[$self tkvarname defvar_] } {
		return ""
	} else {
		return $var_
	}
}
DropDown instproc config_value { option value } {
	$self set_var $value
}
DropDown instproc cget_value { option } {
	upvar #0 [$self set var_] global_var
	if [info exists global_var] {
		return $global_var
	} else {
		return ""
	}
}
DropDown instproc config_state { option {value {}} } {
	if { $value=={} } {
		return [$self subwidget button cget -state]
	} else {
		$self subwidget button configure -state $value
	}
}
DropDown instproc index { index } {
	if { $index=="end" } {
		set index [$self subwidget menu index $index]
		if { $index=="none" } {
			set index -1
		} else {
			incr index
		}
	} else {
		set index [$self subwidget menu index $index]
		if { $index=="none" } {
			set index -1
		}
	}
	return $index
}
DropDown instproc insert { index args } {
	set index [$self index $index]
	if { $index==-1 } {
		set index 0
	}
	foreach arg $args {
		$self insert_item $index $arg
		incr index
	}
	upvar #0 [$self set var_] global_var
	if { ![info exists global_var] || $global_var=="" } {
		$self set_default_var
	}
}
DropDown instproc insert_separator { index } {
	$self subwidget menu insert $index separator
}
DropDown instproc insert_item { index value } {
	$self subwidget menu insert $index command -label $value \
			-command "[list $self] set_var [list $value]"
}
DropDown instproc delete { index1 {index2 {}} } {
	if { $index2=="" } { set index2 $index1 }
	$self subwidget menu delete $index1 $index2
}
DropDown instproc set_var { value } {
	upvar #0 [$self set var_] global_var
	set global_var $value
}
DropDown instproc set_default_var { } {
	set menu [$self subwidget menu]
	set last [$self index end]
	if { $last=="none" } { set last -1 }
	for { set idx 0 } { $idx < $last } { incr idx } {
		if { [$menu type $idx]=="command" } break
	}
	if { $idx < $last } {
		$menu invoke $idx
	} else {
		upvar #0 [$self set var_] global_var
		set global_var ""
	}
}
DropDown instproc var_trace { args } {
	upvar #0 [$self set var_] global_var
	$self subwidget button configure -text $global_var
}
WidgetClass DropDown/Color -superclass DropDown
DropDown/Color instproc insert_item { index value } {
	if { [string index $value 0]=="/" } {
		$self subwidget menu insert $index command \
				-label [list [string range $value 1 end]] \
				-command "[list $self] set_var [list $value]"
	} else {
		$self subwidget menu insert $index command -label {    } \
				-background [list $value] \
				-activebackground [list $value] \
				-command "[list $self] set_var [list $value]"
	}
}
DropDown/Color instproc var_trace { args } {
	upvar #0 [$self set var_] global_var
	if { $global_var=="" } return
	if { $global_var=="/custom" } {
		set current_color [$self subwidget button cget -background]
		set color [tk_chooseColor -title "Choose color" \
				-initialcolor $current_color]
		if { $color=={} } return
		$self insert end $color
		set global_var $color
	}
	$self subwidget button configure -background $global_var \
			-activebackground $global_var -text "    "
}
WidgetClass DropDown/Font -superclass DropDown
DropDown/Font instproc insert_item { index value } {
	$self subwidget menu insert $index command -label ABCabc \
			-font [list $value] \
			-command "[list $self] set_var [list $value]"
}
DropDown/Font instproc var_trace { args } {
	upvar #0 [$self set var_] global_var
	if { $global_var=="" } return
	$self subwidget button configure -font $global_var -text "ABCabc"
}
WidgetClass DropDown/Text -superclass DropDown -configspec {
	{-entryVal entryVal EntryVal {} config_entryVal cget_entryVal}	
} -default {
	{ .highlightThickness 2 }
	{ .takeFocus 0 }
	{ .relief sunken }
	{ .borderWidth 2 }
	{ *button.highlightThickness 0 }
	{ *button.takeFocus 0 }
	{ *button.padX 0 }
	{ *button.padY 0 }
	{ *entry.highlightThickness 0 }
	{ *entry.takeFocus 1 }
	{ *entry.relief flat }
	{ *entry.borderWidth 0 }
}
DropDown/Text instproc config_entryVal { option value} {
	$self subwidget entry delete 0 end
	$self subwidget entry insert 0 $value
}
DropDown/Text instproc cget_entryVal { option value} {
	return [$self subwidget entry get]
}
DropDown/Text instproc build_widget { path } {
	entry $path.entry
	pack $path.entry -side left -fill both -expand 1
	$self next $path
	pack configure $path.button -side right -fill y -expand 0
	set script [bind Menubutton <Key-space>]
	regsub -all -- {%W} $script $path.button new_script
	bind $path.entry <Key-Down> $new_script
	bind $path.entry <Return> "$self set_var \[%W get\]"
	bind $path.entry <FocusOut> "$self restore_var"
}
DropDown/Text instproc restore_var {} {
	upvar #0 [$self set var_] global_var
	if [info exists global_var] {
		$self set_var $global_var
	}
}
DropDown/Text instproc config_state { option {value {}} } {
	if { $value=={} } {
		return [$self subwidget cget button -state]
	} else {
		$self subwidget button configure -state $value
		$self subwidget entry  configure -state $value
	}
}
DropDown/Text instproc set_var { value } {
	$self config_entryVal {} $value
	$self next $value
}
DropDown/Text instproc clear { } {
	$self set_var ""
}
DropDown/Text instproc var_trace { args } {
	set path [$self info path]
	if { [$path.entry selection present] && [focus]==$path } {
		$path.entry selection from 0
		$path.entry selection to   end
		$path.entry icursor end
	}
}
DropDown/Text instproc ev_key_down_ { } {
	set button [$self subwidget button]
	set takefocus [$button cget -takefocus]
	$button configure -takefocus 1
	set oldfocus [focus]
	focus $button
	event generate $button <Key-space>
	focus $oldfocus
	$button configure -takefocus $takefocus
}
WidgetClass EntryWithHistory -superclass DropDown/Text -configspec {
	{ -maxhistory maxHistory MaxHistory 15 config_maxhist cget_maxhist }
}
EntryWithHistory instproc add_history { } {
	set value [$self cget -value]
	regsub -all -- {\*} $value {\*} val1
	regsub -all -- {\?} $val1  {\?} val2
	regsub -all -- {\[} $val2  {\[} val1
	regsub -all -- {\]} $val1  {\]} val2
	catch { $self subwidget menu delete "$val2" }
	$self insert 0 $value
	set index [$self subwidget menu index end]
	set maxhistory [$self cget_maxhist -maxhistory]
	if { $index!="none" && $index >= $maxhistory } {
		$self subwidget menu delete $maxhistory end
	}
}
EntryWithHistory instproc config_maxhist { option value } {
	$self instvar max_history_
	set max_history_ $value
	set index [$self subwidget menu index end]
	if { $index!="none" && $index >= $max_history_ } {
		$self subwidget menu delete $index end
	}
}
EntryWithHistory instproc cget_maxhist { option } {
	$self instvar max_history_
	if [info exists max_history_] { return $max_history_ } else {return 0}
}
WidgetClass ListLabelItem -configspec {
	{ -value       value       Value       {}            config_value }
	{ -select      select      Select      0             config_option }
	{ -highlight   highlight   Highlight   0             config_option }
	{ -relief relief Relief flat config_relief cget_relief }
	{ -normalbackground normalBackground NormalBackground \
			WidgetDefault(-background) config_option }
	{ -normalforeground normalForeground NormalForeground \
			WidgetDefault(-foreground) config_option }
	{ -normalrelief normalRelief NormalRelief flat config_option }
	{ -selectbackground selectBackground SelectBackground WidgetDefault \
			config_option }
	{ -selectforeground selectForeground SelectForeground WidgetDefault \
			config_option }
	{ -selectrelief selectRelief SelectRelief sunken config_option }
	{ -highlightrelief highlightRelief HighlightRelief raised \
			config_option }
}
ListLabelItem instproc init { args } {
	$self instvar config_
	set config_(-value) {}
	set config_(-select) 0
	set config_(-highlight) 0
	set config_(-normalbackground) Black
	set config_(-normalforeground) Black
	set config_(-normalrelief)     flat
	set config_(-selectbackground) Black
	set config_(-selectforeground) Black
	set config_(-selectrelief)     sunken
	set config_(-highlightrelief)  raised
	eval [list $self] next $args	
}
ListLabelItem instproc create_root_widget { path } {
	label $path -anchor w
	if { [option get $path padX Label]=="" } {
		$path configure -padx 1
	}
	if { [option get $path padX Label]=="" } {
		$path configure -pady 1
	}
}
ListLabelItem instproc config_value { option args } {
	$self instvar config_
	if { [llength $args]==0 } {
		return [$self widget_proc cget -text]
	} else {
		$self widget_proc configure -text [lindex $args 0]
	}
}
ListLabelItem instproc config_option { option args } {
	$self instvar config_
	if { [llength $args]==0 } {
		return $config_($option)
	} else {
		set value [lindex $args 0]
		set config_($option) $value
		$self config_[string range $option 1 end] $value
	}
}
ListLabelItem instproc config_relief { option value } {
	$self widget_proc configure -relief $value
}
ListLabelItem instproc cget_relief { option } {
	$self widget_proc cget -relief
}
ListLabelItem instproc config_normalbackground { value } {
	if { ![$self set config_(-select)] } {
		$self widget_proc configure -bg $value
	}
}
ListLabelItem instproc config_normalforeground { value } {
	if { ![$self set config_(-select)] } {
		$self widget_proc configure -fg $value
	}
}
ListLabelItem instproc config_normalrelief { value } {
	if { ![$self set config_(-select)] && \
			![$self set config_(-highlight)] } {
		$self widget_proc configure -relief $value
	}
}
ListLabelItem instproc config_selectbackground { value } {
	if { [$self set config_(-select)] } {
		$self widget_proc configure -bg $value
	}
}
ListLabelItem instproc config_selectforeground { value } {
	if { [$self set config_(-select)] } {
		$self widget_proc configure -fg $value
	}
}
ListLabelItem instproc config_selectrelief { value } {
	if { [$self set config_(-select)] && \
		![$self set config_(-highlight)] } {
		$self widget_proc configure -relief $value
	}
}
ListLabelItem instproc config_highlightrelief { value } {
	if { [$self set config_(-highlight)] } {
		$self widget_proc configure -relief $value
	}
}
ListLabelItem instproc config_select { value } {
	$self instvar config_
	if { $value } {
		$self widget_proc configure -bg $config_(-selectbackground)
		$self widget_proc configure -fg $config_(-selectforeground)
		if { !$config_(-highlight) } {
			$self widget_proc configure \
					-relief $config_(-selectrelief)
		}
	} else {
		$self widget_proc configure -bg $config_(-normalbackground)
		$self widget_proc configure -fg $config_(-normalforeground)
		if { !$config_(-highlight) } {
			$self widget_proc configure \
					-relief $config_(-normalrelief)
		}
	}
}
ListLabelItem instproc config_highlight { value } {
	$self instvar config_
	if { $value } {
		$self widget_proc configure -relief $config_(-highlightrelief)
	} else {
		if { $config_(-select) } {
			$self widget_proc configure \
					-relief $config_(-selectrelief)
		} else {
			$self widget_proc configure \
					-relief $config_(-normalrelief)
		}
	}
}
WidgetClass ScrolledListbox -superclass ScrolledWindow -configspec {
	{ -itemclass itemClass ItemClass ListLabelItem config_option }
	{ -browsecmd browseCmd BrowseCmd "" config_option }
	{ -command command Command "" config_option }
	{ -selectmode selectMode SelectMode single config_selectmode }
} -default {
	{ *window.takeFocus 1 }
	{ *window.highlightThickness 0 }
}
ScrolledListbox instproc build_widget { path } {
	$self next $path
	set window [$self subwidget window]
	frame $window.dummy_ -width 0 -height 0 -relief flat \
			-bg [$window cget -bg]
	pack $window.dummy_ -side top
	$self create_bindtag
	$self set count_ 0
	$self set highlight_ ""
}
ScrolledListbox instproc create_bindtag { } {
	bind [$self subwidget bbox] <Configure> "+$self ev_bbox_resize_ %w %h"
	set window [$self subwidget window]
	bind $window <KeyPress-Up> "$self ev_key_up_"
	bind $window <KeyPress-Down> "$self ev_key_down_"
	bind $window <KeyPress-space> "$self ev_key_space_"
	bind Bindings_$self <ButtonPress-1> "+$self selection.toggle -widget \
			\[$self root_widget_ %W\]; $self browse \
			\[$self widget_to_id_ \[$self root_widget_ %W\]\]"
	bind Bindings_$self <Double-1> "+$self invoke \
			\[$self widget_to_id_ \[$self root_widget_ %W\]\]"
	bind Bindings_$self <Enter> "+if \{ \[$self root_widget_ %W\] == \
			\"%W\" \} \{ $self highlight.set -widget %W \}"
	bind Bindings_$self <Leave> "+if \{ \[$self root_widget_ %W\] == \
			\"%W\" \} \{ $self highlight.clear -widget %W \}"
}
ScrolledListbox instproc ev_bbox_resize_ { w h } {
	set window [$self subwidget window]
	set bbox   [$self subwidget bbox]
	$window.dummy_ configure \
			-width [expr $w - ([$bbox cget -bd] + \
			[$window cget -bd] + [$bbox cget -highlightthickness] \
			+ [$window cget -highlightthickness]) * 2]
}
ScrolledListbox instproc ev_key_up_ { } {
	set highlight [$self highlight.get]
	if { $highlight != "" } {
		set list [$self widget_list_]
		set idx [lsearch $list [$self id_to_widget_ $highlight]]
		if { $idx <= 0 } {
			return
		}
		incr idx -1
	} else {
		set idx 0
	}
	$self see $idx
	$self highlight.set $idx
}
ScrolledListbox instproc ev_key_down_ { } {
	set highlight [$self highlight.get]
	if { $highlight != "" } {
		set list [$self widget_list_]
		set idx [lsearch $list [$self id_to_widget_ $highlight]]
		if { $idx < 0 || $idx >= [expr [llength $list]-1] } {
			return
		}
		incr idx 1
	} else {
		set idx 0
	}
	$self see $idx
	$self highlight.set $idx
}
ScrolledListbox instproc ev_key_space_ { } {
	set highlight [$self highlight.get]
	if { $highlight != "" } {
		$self selection.toggle -id $highlight
		$self browse $highlight
	}
}
ScrolledListbox instproc root_widget_ { path } {
	set window [$self subwidget window]
	set widget $path
	while { $widget!="" && [winfo parent $widget] != $window } {
		set widget [winfo parent $widget]
	}
	if { $widget=="" } {
		error "invalid widget $path"
	}
	return $widget
}
ScrolledListbox instproc widget_list_ { } {
	set list [pack slaves [$self subwidget window]]
	return [lrange $list 1 end]
}
ScrolledListbox instproc config_option { option args } {
	$self instvar config_
	if { [llength $args]==0 } {
		return $config_($option)
	} else {
		set config_($option) [lindex $args 0]
	}
}
ScrolledListbox instproc config_selectmode { option args } {
	$self instvar config_
	if { [llength $args]==0 } {
		return $config_(-selectmode)
	}
	set value [lindex $args 0]
	switch -exact -- $value {
		single {
			set config_(-selectmode) "single"
			set selection [lindex [$self selection.get all] 0]
			$self selection.clear all
			if { $selection!="" } {
				$self selection.set -id $selection
			}
		}
		multiple {
			set config_(-selectmode) "multiple"
		}
		none {
			set config_(-selectmode) "none"
			$self selection.clear all
		}
		default {
			error "invalid selectmode \"$value\". must be one of\
					\"single\", \"multiple\", or \"none\""
		}
	}
}
ScrolledListbox instproc browse { id } {
	set browsecmd [$self cget -browsecmd]
	if { $browsecmd!="" } {
		uplevel #0 $browsecmd $id
	}
}
ScrolledListbox instproc invoke { id } {
	set command [$self cget -command]
	if { $command!="" } {
		uplevel #0 $command $id
	}
}
ScrolledListbox instproc ID_ { idVar arguments { idx 0 } } {
	upvar $idVar id
	if { [llength $arguments] <= $idx } {
		error "missing arguments"
	}
	set arg [lindex $arguments $idx]
	switch -exact -- $arg {
		-id {
			set end [expr $idx+2]
			if { [llength $arguments] < $end } {
				error "missing argument for \"-id\""
			}
			set id [lindex $arguments [expr $idx+1]]
			return $end
		}
		-widget {
			set end [expr $idx+2]
			if { [llength $arguments] < $end } {
				error "missing argument for \"-widget\""
			}
			set widget [lindex $arguments [expr $idx+1]]
			set id [$self widget_to_id_ $widget]
			return $end
		}
		-value {
			set end [expr $idx+2]
			if { [llength $arguments] < $end } {
				error "missing argument for \"-value\""
			}
			set widget [lindex $arguments [expr $idx+1]]
			set id [$self value_to_id_ $widget]
			return $end
		}
		default {
			set id [$self index_to_id_ $arg]
			return [expr $idx+1]
		}
	}
}
ScrolledListbox instproc widget_to_id_ { widget } {
	$self instvar widget_to_id_
	if [info exists widget_to_id_($widget)] {
		return $widget_to_id_($widget)
	} else {
		error "invalid widget \"$widget\""
	}
}
ScrolledListbox instproc value_to_id_ { value } {
	foreach widget [self widget_list_] {
		if { $value == [$self info.value -widget $widget] } {
			return $id
		}
	}
	error "invalid value \"$value\""
}
ScrolledListbox instproc index_to_id_ { index } {
	set widget [lindex [$self widget_list_] $index]
	if { $widget=="" } {
		error "invalid index \"$index\""
	}
	return [$self widget_to_id_ $widget]
}
ScrolledListbox instproc id_to_widget_ { id } {
	$self instvar id_to_widget_
	if [info exists id_to_widget_($id)] {
		return $id_to_widget_($id)
	} else {
		error "invalid id \"$id\""
	}
}
ScrolledListbox instproc id_to_value_ { id } {
	set widget [$self id_to_widget_ $id]
	return [$widget cget -value]
}
ScrolledListbox instproc insert { where args } {
	$self instvar count_ id_to_widget_ widget_to_id_
	switch -exact -- $where {
		end {
			set where ""
		}
		after {
			set idx [$self ID where_id $args]
			set where "-after [$self id_to_widget_ $where_id]"
			set args [lrange $args $idx end]
		}
		before {
			set idx [$self ID where_id $args]
			set where "-before [$self id_to_widget_ $where_id]"
			set args [lrange $args $idx end]
		}
		default {
			error "invalid argument \"$where\". must be one of\
					\"end\", \"after\", or \"before\""
		}
	}
	set window [$self subwidget window]
	set item_class [$self cget -itemclass]
	if { $item_class=="" } {
		error "must configure -itemclass before inserting any elements"
	}
	foreach arg $args {
		if { [lindex $arg 0] == "-id" } {
			if { [llength $arg] <= 1 } {
				error "missing argument for \"-id\""
			}
			set id [lindex $arg 1]
			set arg [lrange $arg 2 end]
		} else {
			set id #$count_
		}
		if { [info exists id_to_widget_($id)] } {
			error "id \"$id\" already exists"
		}
		set widget $window.item_$count_
		incr count_
		$item_class $widget -value $arg
		$self bindtag_recursive_ $widget
		if { $where=="" } {
			pack $widget -side top -fill x -expand 1
		} else {
			eval pack [list $widget] -side top -fill x -expand 1 \
					$where
		}
		set id_to_widget_($id) $widget
		set widget_to_id_($widget) $id
	}
}
ScrolledListbox instproc delete { args } {
	$self instvar id_to_widget_ widget_to_id_ selection_ highlight_
	if { [lindex $args 0]=="all" } {
		if { [llength $args]!=1 } {
			error "extra arguments starting at argument 2"
		}
		foreach widget [$self widget_list_] {
			destroy $widget
		}
		catch {
			unset id_to_widget_
			unset widget_to_id_
			unset selection_
		}
		set highlight_ ""
	} else {
		set id [eval [list $self] info.id $args]
		set widget [$self id_to_widget_ $id]
		destroy $widget
		catch {
			unset id_to_widget_($id)
			unset widget_to_id_($widget)
			unset selection_($id)
		}
		if { $highlight_==$id } {
			set highlight_ ""
		}
	}
}
ScrolledListbox instproc bindtag_recursive_ { widget } {
	$self bindtag_ $widget
	foreach path [winfo children $widget] {
		$self bindtag_recursive_ $path
	}
}
ScrolledListbox instproc bindtag_ { widget } {
	set tags [bindtags $widget]
	if {[lsearch -exact $tags Bindings_$self] == -1} {
		bindtags $widget [concat [list Bindings_$self] $tags]
	}
}
ScrolledListbox instproc see { args } {
	set id [eval [list $self] info.id $args]
	set widget [$self id_to_widget_ $id]
	set y1 [winfo y $widget]
	set y2 [expr $y1 + [winfo height $widget] - 1]
	set viewable [$self subwidget bbox yview]
	set scrollregion [$self subwidget bbox cget -scrollregion]
	set height [expr [lindex $scrollregion 3] - [lindex $scrollregion 1]]
	set bbox_y1 [expr $height * [lindex $viewable 0] + \
			[lindex $scrollregion 1]]
	set bbox_y2 [expr $height * [lindex $viewable 1] + \
			[lindex $scrollregion 1]]
	if { $y1 < $bbox_y1 } {
		set bbox_y1 $y1
		$self subwidget bbox yview moveto \
				[expr double($bbox_y1)/double($height)]
	} elseif { $y2 > $bbox_y2 } {
		set bbox_y1 [expr $y2 - ($bbox_y2 - $bbox_y1)]
		$self subwidget bbox yview moveto \
				[expr double($bbox_y1)/double($height)]
	}
}
ScrolledListbox instproc info { method args } {
	if { [$class info instprocs info.$method] == "info.$method" } {
		return [eval [list $self] [list info.$method] $args]
	} else {
		return [eval [list $self] next [list $method] $args]
	}
}
ScrolledListbox instproc info.id { args } {
	set idx [$self ID_ id $args]
	if { [llength $args] > $idx } {
		error "extra arguments starting with argument $idx"
	}
	return $id
}
ScrolledListbox instproc info.widget { args } {
	set id [eval [list $self] info.id $args]
	return [$self id_to_widget_ $id]
}
ScrolledListbox instproc info.value { args } {
	set id [eval [list $self] info.id $args]
	return [$self id_to_value_ $id]
}
ScrolledListbox instproc info.all { {what {}} } {
	switch -exact -- $what {
		{} -
		-id {
			set ids {}
			foreach widget [$self widget_list_] {
				lappend ids [$self widget_to_id_ $widget]
			}
			return $ids
		}
		-widget {
			return [$self widget_list_]
		}
		-value {
			set values
			foreach widget [$self widget_list_] {
				set id [$self widget_to_id_ $widget]
				lappend values [$self id_to_value_ $id]
			}
			return $values
		}
		default {
			error "invalid argument \"$what\". must be one of\
					\"-id\", \"-widget\", or \"-value\""
		}
	}
}
ScrolledListbox instproc info.exists { args } {
	set len [llength $args]
	if { $len > 2 } {
		error "extra arguments"
	}
	switch -exact -- [lindex $args 0] {
		-id {
			if { $len < 2 } {
				error "missing argument for \"-id\""
			}
			return [info exists id_to_widget_([lindex $args 1])]
		}
		-widget {
			if { $len < 2 } {
				error "missing argument for \"-widget\""
			}
			return [info exists widget_to_id_([lindex $args 1])]
		}
		-value {
			if { $len < 2 } {
				error "missing argument for \"-widget\""
			}
			return ![catch {$self value_to_id_ [lindex $args 1]}]
		}
		default {
			if { $len > 1 } {
				error "extra arguments"
			}
			return ![catch {$self index_to_id_ [lindex $args 1]}]
		}
	}
}
ScrolledListbox instproc info.numelems { } {
	return [llength [$self widget_list_]]
}
ScrolledListbox instproc selection { method args } {
	eval [list $self] [list selection.$method] $args
}
ScrolledListbox instproc selection.set { args } {
	$self instvar selection_
	set selectmode [$self cget -selectmode]
	if { $selectmode=="none" } {
		return
	}
	if { [lindex $args 0]=="all" } {
		if { [llength $args] > 1 } {
			error "extra arguments starting at argument 2"
		}
		foreach widget [$self widget_list_] {
			$self selection.set -widget $widget
		}
	}
	set id [eval [list $self] info.id $args]
	if { [info exists selection_($id)] } {
		return
	}
	if { [$self cget -selectmode]=="single" } {
		$self selection.clear all
	}
	set selection_($id) 1
	set widget [$self id_to_widget_ $id]
	$widget configure -select 1
}
ScrolledListbox instproc selection.get { args } {
	$self instvar selection_
	if { [llength $args]==0 } {
		return [array names selection_]
	}
	if { [lindex $args 0]=="all" } {
		if { [llength $args] > 1 } {
			error "extra arguments starting at argument 2"
		}
		return [array names selection_]
	}
	set id [eval [list $self] info.id $args]
	if { [info exists selection_($id)] } {
		return $id
	} else {
		return ""
	}
}
ScrolledListbox instproc selection.clear { args } {
	$self instvar selection_
	if { [llength $args]==0 } {
		$self selection.clear_all_
		return
	}
	if { [lindex $args 0]=="all" } {
		if { [llength $args] > 1 } {
			error "extra arguments starting at argument 2"
		}
		$self selection.clear_all_
		return
	}
	set id [eval [list $self] info.id $args]
	if { [info exists selection_($id)] } {
		unset selection_($id)
		[$self id_to_widget_ $id] configure -select 0
	} else {
		return
	}
}
ScrolledListbox instproc selection.clear_all_ { } {
	$self instvar selection_
	foreach id [array names selection_] {
		unset selection_($id)
		[$self id_to_widget_ $id] configure -select 0
	}
}
ScrolledListbox instproc selection.toggle { args } {
	set id [eval [list $self] info.id $args]
	if { [$self selection.get -id $id]=="" } {
		$self selection.set -id $id
	} else {
		$self selection.clear -id $id
	}
}
ScrolledListbox instproc highlight { method args } {
	eval [list $self] [list highlight.$method] $args
}
ScrolledListbox instproc highlight.set { args } {
	$self instvar highlight_
	set id [eval [list $self] info.id $args]
	if { $id == $highlight_ } {
		return
	}
	if { $highlight_!="" } {
		[$self id_to_widget_ $highlight_] configure -highlight 0
	}
	set highlight_ $id
	[$self id_to_widget_ $id] configure -highlight 1
}
ScrolledListbox instproc highlight.get { args } {
	$self instvar highlight_
	if { [llength $args]==0 } {
		return $highlight_
	}
	set id [eval [list $self] info.id $args]
	if { $highlight_==$id } {
		return $id
	} else {
		return ""
	}
}
ScrolledListbox instproc highlight.clear { args } {
	$self instvar highlight_
	if { [llength $args]==0 } {
		[$self id_to_widget_ $highlight_] configure -highlight 0
		set highlight_ ""
	} else {
		set id [eval [list $self] info.id $args]
		if { $highlight_==$id } {
			[$self id_to_widget_ $highlight_] configure \
					-highlight 0
			set highlight_ ""
		}
	}
}
ScrolledListbox instproc highlight.toggle { args } {
	$self instvar highlight_
	if { [llength $args]==0 } {
		$self highlight.clear
	} else {
		set id [eval [list $self] info.id $args]
		if { $id == $highlight_ } {
			$self highlight.clear
		} else {
			$self highlight.set -id $id
		}
	}
}
WidgetClass HierarchicalListboxItem -configspec {
	{ -value       value       Value       {}            config_value }
	{ -select      select      Select      0             config_option }
	{ -highlight   highlight   Highlight   0             config_option }
	{ -normalbackground normalBackground NormalBackground \
			WidgetDefault(-background) config_option }
	{ -normalforeground normalForeground NormalForeground \
			WidgetDefault(-foreground) config_option }
	{ -normalrelief normalRelief NormalRelief flat config_option }
	{ -selectbackground selectBackground SelectBackground WidgetDefault \
			config_option }
	{ -selectforeground selectForeground SelectForeground WidgetDefault \
			config_option }
	{ -selectrelief selectRelief SelectRelief sunken config_option }
	{ -highlightrelief highlightRelief HighlightRelief raised \
			config_option }
} -default {
	{ .borderWidth WidgetDefault }
	{ *font WidgetDefault }
	{ *Label.padX 1 }
	{ *Label.padY 0 }
	{ *Label.borderWidth 0 }
}
HierarchicalListboxItem instproc init { args } {
	$self instvar config_
	set config_(-value) {}
	set config_(-select) 0
	set config_(-highlight) 0
	set config_(-normalbackground) Black
	set config_(-normalforeground) Black
	set config_(-normalrelief)     flat
	set config_(-selectbackground) Black
	set config_(-selectforeground) Black
	set config_(-selectrelief)     sunken
	set config_(-highlightrelief)  raised
	eval [list $self] next $args	
}
HierarchicalListboxItem instproc build_widget { path } {
	label $path.padding
	label $path.image
	label $path.text -anchor w
	pack $path.padding -side left
	pack $path.image -side left
	pack $path.text  -side left -fill x -anchor w
}
HierarchicalListboxItem instproc config_value { option args } {
	$self instvar config_
	if { [llength $args]==0 } {
		if [info exists config_(-value)] {
			return $config_(-value)
		} else {
			return ""
		}
	} else {
		set value [lindex $args 0]
		set image [lindex $value 0]
		set config_(-value) [lindex $value 1]
		set split [split $config_(-value) "/"]
		if { $config_(-value)=="/" || [llength $split] <= 1 } {
			set level 0
			set label $config_(-value)
		} else {
			set level [llength $split]
			set label [lindex $split [expr $level-1]]
		}
		$self subwidget padding configure -padx [expr $level * 4]
		$self subwidget image   configure -image $image
		$self subwidget text    configure -text  $label
	}
}
HierarchicalListboxItem instproc config_option { option args } {
	$self instvar config_
	if { [llength $args]==0 } {
		return $config_($option)
	} else {
		set value [lindex $args 0]
		$self config_[string range $option 1 end] $value
		set config_($option) $value
	}
}
HierarchicalListboxItem instproc config_background { value } {
	set path [$self info path]
	$path configure -bg $value
	foreach label [winfo children $path] {
		$label configure -bg $value
	}
}
HierarchicalListboxItem instproc config_foreground { value } {
	foreach label [winfo children [$self info path]] {
		$label configure -fg $value
	}
}
HierarchicalListboxItem instproc config_relief { value } {
	[$self info path] configure -relief $value
}
HierarchicalListboxItem instproc config_normalbackground { value } {
	if { ![$self set config_(-select)] } {
		$self config_background $value
	}
}
HierarchicalListboxItem instproc config_normalforeground { value } {
	if { ![$self set config_(-select)] } {
		$self config_foreground $value
	}
}
HierarchicalListboxItem instproc config_normalrelief { value } {
	if { ![$self set config_(-select)] && \
			![$self set config_(-highlight)] } {
		$self config_relief $value
	}
}
HierarchicalListboxItem instproc config_selectbackground { value } {
	if { [$self set config_(-select)] } {
		$self config_background $value
	}
}
HierarchicalListboxItem instproc config_selectforeground { value } {
	if { [$self set config_(-select)] } {
		$self config_foreground $value
	}
}
HierarchicalListboxItem instproc config_selectrelief { value } {
	if { [$self set config_(-select)] && \
		![$self set config_(-highlight)] } {
		$self config_relief $value
	}
}
HierarchicalListboxItem instproc config_highlightrelief { value } {
	if { [$self set config_(-highlight)] } {
		$self config_relief $value
	}
}
HierarchicalListboxItem instproc config_select { value } {
	$self instvar config_
	if { $value } {
		$self config_background $config_(-selectbackground)
		$self config_foreground $config_(-selectforeground)
		if { !$config_(-highlight) } {
			$self config_relief $config_(-selectrelief)
		}
	} else {
		$self config_background $config_(-normalbackground)
		$self config_foreground $config_(-normalforeground)
		if { !$config_(-highlight) } {
			$self config_relief $config_(-normalrelief)
		}
	}
}
HierarchicalListboxItem instproc config_highlight { value } {
	$self instvar config_
	if { $value } {
		$self config_relief $config_(-highlightrelief)
	} else {
		if { $config_(-select) } {
			$self config_relief $config_(-selectrelief)
		} else {
			$self config_relief $config_(-normalrelief)
		}
	}
}
WidgetClass MultiColumnListbox -superclass ScrolledCanvas -configspec {
	{ -browsecmd browseCmd BrowseCmd "" config_option }
	{ -command command Command "" config_option }
	{ -selectbackground selectBackground SelectBackground #a0a0ff \
			config_option }
	{ -font font Font WidgetDefault	config_option }
} -default {
	{ .scrollbar horizontal }
	{ *hscroll.highlightThickness 0 }
	{ *hscroll.takeFocus 0 }
	{ *bbox.borderWidth 2 }
	{ *bbox.width 400 }
	{ *bbox.height 120 }
}
MultiColumnListbox instproc config_option { option args } {
	$self instvar data
	if { [llength $args] == {} } {
		return $data($option)
	} else {
		set data($option) [lindex $args 0]
	}
}
MultiColumnListbox instproc build_widget { path } {
	$self instvar data
	$self next $path
	set data(canvas) [$self subwidget bbox]
	set data(sbar) [$self subwidget hscroll]
	set data(maxIW) 1
	set data(maxIH) 1
	set data(maxTW) 1
	set data(maxTH) 1
	set data(numItems) 0
	set data(curItem)  {}
	set data(noScroll) 1
	bind $data(canvas) <Configure> "+$self arrange"
	bind $data(canvas) <1>         "$self btn1 %x %y"
	bind $data(canvas) <B1-Motion> "$self motion1 %x %y"
	bind $data(canvas) <Double-1>  "$self double1 %x %y"
	bind $data(canvas) <ButtonRelease-1> "tkCancelRepeat"
	bind $data(canvas) <B1-Leave>  "$self leave1 %x %y"
	bind $data(canvas) <B1-Enter>  "tkCancelRepeat"
	bind $data(canvas) <Up>        "$self up_down -1"
	bind $data(canvas) <Down>      "$self up_down  1"
	bind $data(canvas) <Left>      "$self left_right -1"
	bind $data(canvas) <Right>     "$self left_right  1"
	bind $data(canvas) <Return>    "$self return_key"
	bind $data(canvas) <KeyPress>  "$self key_press %A"
	bind $data(canvas) <Control-KeyPress> ";"
	bind $data(canvas) <Alt-KeyPress>  ";"
	bind $data(canvas) <FocusIn>   "$self focus_in"
}
MultiColumnListbox instproc auto_scan { } {
	$self instvar data
	global tkPriv
	set x $tkPriv(x)
	set y $tkPriv(y)
	if $data(noScroll) {
		return
	}
	if {$x >= [winfo width $data(canvas)]} {
		$data(canvas) xview scroll 1 units
	} elseif {$x < 0} {
		$data(canvas) xview scroll -1 units
	} elseif {$y >= [winfo height $data(canvas)]} {
	} elseif {$y < 0} {
	} else {
		return
	}
	$self motion1 $x $y
	set tkPriv(afterId) [after 50 $self auto_scan]
}
MultiColumnListbox instproc delete_all {} {
	$self instvar data
	$self instvar itemList
	$data(canvas) delete all
	catch {unset data(selected)}
	catch {unset data(rect)}
	catch {unset data(list)}
	catch {unset itemList}
	set data(numItems) 0
	set data(curItem)  {}
}
MultiColumnListbox instproc add {image text} {
	$self instvar data
	$self instvar itemList
	$self instvar textList
	set iTag [$data(canvas) create image 0 0 -image $image -anchor nw]
	set tTag [$data(canvas) create text  0 0 -text  $text  -anchor nw \
			-font $data(-font)]
	set rTag [$data(canvas) create rect  0 0 0 0 -fill "" -outline ""]
	set b [$data(canvas) bbox $iTag]
	set iW [expr [lindex $b 2]-[lindex $b 0]]
	set iH [expr [lindex $b 3]-[lindex $b 1]]
	if {$data(maxIW) < $iW} {
		set data(maxIW) $iW
	}
	if {$data(maxIH) < $iH} {
		set data(maxIH) $iH
	}
	set b [$data(canvas) bbox $tTag]
	set tW [expr [lindex $b 2]-[lindex $b 0]]
	set tH [expr [lindex $b 3]-[lindex $b 1]]
	if {$data(maxTW) < $tW} {
		set data(maxTW) $tW
	}
	if {$data(maxTH) < $tH} {
		set data(maxTH) $tH
	}
	lappend data(list) [list $iTag $tTag $rTag $iW $iH $tW $tH \
			$data(numItems)]
	set itemList($rTag) [list $iTag $tTag $text $data(numItems)]
	set textList($data(numItems)) [string tolower $text]
	incr data(numItems)
}
MultiColumnListbox instproc arrange {} {
	$self instvar data
	if ![info exists data(list)] {
		if {[info exists data(canvas)] && \
				[winfo exists $data(canvas)]} {
			set data(noScroll) 1
			$data(sbar) config -command ""
		}
		return
	}
	set W [winfo width  $data(canvas)]
	set H [winfo height $data(canvas)]
	set pad [expr [$data(canvas) cget -highlightthickness] + \
			[$data(canvas) cget -bd]]
	incr W -[expr $pad*2]
	incr H -[expr $pad*2]
	set dx [expr $data(maxIW) + $data(maxTW) + 4]
	if {$data(maxTH) > $data(maxIH)} {
		set dy $data(maxTH)
	} else {
		set dy $data(maxIH)
	}
	set shift [expr $data(maxIW) + 4]
	set x [expr $pad * 2]
	set y [expr $pad * 1]
	set usedColumn 0
	foreach pair $data(list) {
		set usedColumn 1
		set iTag [lindex $pair 0]
		set tTag [lindex $pair 1]
		set rTag [lindex $pair 2]
		set iW   [lindex $pair 3]
		set iH   [lindex $pair 4]
		set tW   [lindex $pair 5]
		set tH   [lindex $pair 6]
		set i_dy [expr ($dy - $iH)/2]
		set t_dy [expr ($dy - $tH)/2]
		$data(canvas) coords $iTag $x                 [expr $y + $i_dy]
		$data(canvas) coords $tTag [expr $x + $shift] [expr $y + $t_dy]
		$data(canvas) coords $tTag [expr $x + $shift] [expr $y + $t_dy]
		$data(canvas) coords $rTag $x $y [expr $x+$dx] [expr $y+$dy]
		incr y $dy
		if {[expr $y + $dy] >= $H} {
			set y [expr $pad * 1]
			incr x $dx
			set usedColumn 0
		}
	}
	if {$usedColumn} {
		set sW [expr $x + $dx]
	} else {
		set sW $x
	}
	if {$sW < $W} {
		$data(canvas) config -scrollregion "$pad $pad $sW $H"
		$data(sbar) config -command ""
		$data(canvas) xview moveto 0
		set data(noScroll) 1
	} else {
		$data(canvas) config -scrollregion "$pad $pad $sW $H"
		$data(sbar) config -command "$data(canvas) xview"
		set data(noScroll) 0
	}
	set data(itemsPerColumn) [expr ($H-$pad)/$dy]
	if {$data(itemsPerColumn) < 1} {
		set data(itemsPerColumn) 1
	}
	if {$data(curItem) != {}} {
		$self select [lindex [lindex $data(list) $data(curItem)] 2] 0
	}
}
MultiColumnListbox instproc invoke {} {
	$self instvar data
	if {[string compare $data(-command) ""] && \
			[info exists data(selected)]} {
		eval $data(-command) [list $data(selected)]
	}
}
MultiColumnListbox instproc see {rTag} {
	$self instvar data
	$self instvar itemList
	if $data(noScroll) {
		return
	}
	set sRegion [$data(canvas) cget -scrollregion]
	if ![string compare $sRegion {}] {
		return
	}
	if ![info exists itemList($rTag)] {
		return
	}
	set bbox [$data(canvas) bbox $rTag]
	set pad [expr [$data(canvas) cget -highlightthickness] + \
			[$data(canvas) cget -bd]]
	set x1 [lindex $bbox 0]
	set x2 [lindex $bbox 2]
	incr x1 -[expr $pad * 2]
	incr x2 -[expr $pad * 1]
	set cW [expr [winfo width $data(canvas)] - $pad*2]
	set scrollW [expr [lindex $sRegion 2]-[lindex $sRegion 0]+1]
	set dispX [expr int([lindex [$data(canvas) xview] 0]*$scrollW)]
	set oldDispX $dispX
	if {[expr $x2 - $dispX] >= $cW} {
		set dispX [expr $x2 - $cW]
	}
	if {[expr $x1 - $dispX] < 0} {
		set dispX $x1
	}
	if {$oldDispX != $dispX} {
		set fraction [expr double($dispX)/double($scrollW)]
		$data(canvas) xview moveto $fraction
	}
}
MultiColumnListbox instproc select_at_XY {x y} {
	$self instvar data
	$self select [$data(canvas) find closest \
			[$data(canvas) canvasx $x] [$data(canvas) canvasy $y]]
}
MultiColumnListbox instproc select {rTag {callBrowse 1}} {
	$self instvar data
	$self instvar itemList
	if ![info exists itemList($rTag)] {
		return
	}
	set iTag   [lindex $itemList($rTag) 0]
	set tTag   [lindex $itemList($rTag) 1]
	set text   [lindex $itemList($rTag) 2]
	set serial [lindex $itemList($rTag) 3]
	if ![info exists data(rect)] {
		set data(rect) [$data(canvas) create rect 0 0 0 0 \
				-fill $data(-selectbackground) \
				-outline $data(-selectbackground)]
	}
	$data(canvas) lower $data(rect)
	set bbox [$data(canvas) bbox $tTag]
	eval $data(canvas) coords $data(rect) $bbox
	set data(curItem) $serial
	set data(selected) $text
	if {$callBrowse} {
		if [string compare $data(-browsecmd) ""] {
			eval $data(-browsecmd) [list $text]
		}
	}
}
MultiColumnListbox instproc unselect {} {
	$self instvar data
	if [info exists data(rect)] {
		$data(canvas) delete $data(rect)
		unset data(rect)
	}
	if [info exists data(selected)] {
		unset data(selected)
	}
	set data(curItem)  {}
}
MultiColumnListbox instproc get {} {
	$self instvar data
	if [info exists data(selected)] {
		return $data(selected)
	} else {
		return ""
	}
}
MultiColumnListbox instproc btn1 {x y} {
	$self instvar data
	focus $data(canvas)
	$self select_at_XY $x $y
}
MultiColumnListbox instproc motion1 {x y} {
	global tkPriv
	set tkPriv(x) $x
	set tkPriv(y) $y
	$self select_at_XY $x $y
}
MultiColumnListbox instproc double1 {x y} {
	$self instvar data
	if {$data(curItem) != {}} {
		$self invoke
	}
}
MultiColumnListbox instproc return_key {} {
	$self invoke
}
MultiColumnListbox instproc leave1 {x y} {
	global tkPriv
	set tkPriv(x) $x
	set tkPriv(y) $y
	$self auto_scan
}
MultiColumnListbox instproc focus_in {} {
	$self instvar data
	if ![info exists data(list)] {
		return
	}
	if {$data(curItem) == {}} {
		set rTag [lindex [lindex $data(list) 0] 2]
		$self select $rTag
	}
}
MultiColumnListbox instproc up_down {amount} {
	$self instvar data
	if ![info exists data(list)] {
		return
	}
	if {$data(curItem) == {}} {
		set rTag [lindex [lindex $data(list) 0] 2]
	} else {
		set oldRTag [lindex [lindex $data(list) $data(curItem)] 2]
		set rTag [lindex [lindex $data(list) [expr \
				$data(curItem)+$amount]] 2]
		if ![string compare $rTag ""] {
			set rTag $oldRTag
		}
	}
	if [string compare $rTag ""] {
		$self select $rTag
		$self see $rTag
	}
}
MultiColumnListbox instproc left_right {amount} {
	$self instvar data
	if ![info exists data(list)] {
		return
	}
	if {$data(curItem) == {}} {
		set rTag [lindex [lindex $data(list) 0] 2]
	} else {
		set oldRTag [lindex [lindex $data(list) $data(curItem)] 2]
		set newItem [expr $data(curItem)+($amount*\
				$data(itemsPerColumn))]
		set rTag [lindex [lindex $data(list) $newItem] 2]
		if ![string compare $rTag ""] {
			set rTag $oldRTag
		}
	}
	if [string compare $rTag ""] {
		$self select $rTag
		$self see $rTag
	}
}
MultiColumnListbox instproc key_press {key} {
	global tkPriv
	set w [$self info path]
	append tkPriv(ILAccel,$w) $key
	$self goto $tkPriv(ILAccel,$w)
	catch {
		after cancel $tkPriv(ILAccel,$w,afterId)
	}
	set tkPriv(ILAccel,$w,afterId) [after 500 $self reset]
}
MultiColumnListbox instproc goto {text} {
	$self instvar data
	$self instvar textList
	global tkPriv
	if ![info exists data(list)] {
		return
	}
	if {[string length $text] == 0} {
		return
	}
	if {$data(curItem) == {} || $data(curItem) == 0} {
		set start  0
	} else {
		set start  $data(curItem)
	}
	set text [string tolower $text]
	set theIndex -1
	set less 0
	set len [string length $text]
	set len0 [expr $len-1]
	set i $start
	while 1 {
		set sub [string range $textList($i) 0 $len0]
		if {[string compare $text $sub] == 0} {
			set theIndex $i
			break
		}
		incr i
		if {$i == $data(numItems)} {
			set i 0
		}
		if {$i == $start} {
			break
		}
	}
	if {$theIndex > -1} {
		set rTag [lindex [lindex $data(list) $theIndex] 2]
		$self select $rTag 0
		$self see $rTag
	}
}
MultiColumnListbox instproc reset { } {
	global tkPriv
	set w [$self info path]
	catch {unset tkPriv(ILAccel,$w)}
}
WidgetClass FileBox -default {
	{ *font WidgetDefault }
	{ *Button.borderWidth 1 }
	{ *Menubutton.borderWidth 1 }
	{ *Menu.borderWidth 1 }
	{ *Entry.borderWidth 1 }
	{ *Button.highlightThickness 1 }
	{ *Menubutton.highlightThickness 1 }
	{ *MultiColumnListbox.bbox.highlightThickness 1 }
	{ *Entry.highlightThickness 1 }
	{ *MultiColumnListbox.bbox.borderWidth 1 }
	{ *MultiColumnListbox.bbox.relief sunken }
	{ *MultiColumnListbox.Scrollbar.borderWidth 1 }
	{ *MultiColumnListbox.Scrollbar.width 10 }
	{ *Menubutton.anchor w }
	{ *Menubutton.padX 5 }
} -configspec {
	{ -filetypes fileTypes FileTypes "" config_filetypes cget_filetypes }
	{ -directory directory Directory "" config_directory cget_directory }
	{ -filename  filename  Filename  "" config_filename  cget_filename  }
	{ -browsecmd browseCmd BrowseCmd "" config_browsecmd cget_browsecmd }
	{ -command   command   command   "" config_command   cget_command   }
}
FileBox instproc build_widget { path } {
	set f1 [frame $path.f1]
	label $f1.label -text "Directory:" -underline 0
	DropDown $f1.directory -variable [$self tkvarname directory_]
	button $f1.upbutton -image Icons(folderup) \
			-command "$self up_folder_cmd"
	pack $f1.upbutton -side right -padx 4 -fill both
	pack $f1.label -side left -padx 4 -fill both
	pack $f1.directory -expand yes -fill both -padx 4
	$self set_subwidget directory $f1.directory
	$self set_subwidget upbutton  $f1.upbutton
	MultiColumnListbox $path.listbox -browsecmd "$self list_browse" \
			-command "$self list_command"
	set f2 [frame $path.f2]
	label $f2.label -text "File name:" -anchor e -width 14 -underline 5
	entry $f2.filename -textvariable [$self tkvarname filename_]
	pack $f2.label -side left -padx 4
	pack $f2.filename -expand yes -fill both -padx 2 -pady 2
	$self set_subwidget filename $f2.filename
	$self set_subwidget filename_label $f2.label
	set f3 [frame $path.f3]
	label $f3.label -text "Files of type:" -anchor e -width 14 \
			-underline 9
	DropDown $f3.filetypes -variable [$self tkvarname filetypes_]
	pack $f3.label -side left -padx 4
	pack $f3.filetypes -expand yes -fill x -side right
	$self set_subwidget filetypes_label $f3.label
	$self set_subwidget filetypes $f3.filetypes
	pack $f1 -side top -fill x -pady 4
	pack $f3 -side bottom -fill x
	pack $f2 -side bottom -fill x
	pack $path.listbox -expand yes -fill both -padx 4 -pady 2
	set filename [$self subwidget filename]
	bind $filename <Return>   "$self entry_command"
	bind $filename <FocusIn>  "$self subwidget listbox unselect"
	set w [winfo toplevel $path]
	bind $w <Alt-d> "focus [$self subwidget directory subwidget button]"
	bind $w <Alt-t> "focus [$self subwidget filetypes subwidget button]"
	bind $w <Alt-n> "focus [$self subwidget filename]"
	$self tkvar directory_ filetypes_
	$self tkvar filter_
	trace variable directory_ w "$self do_when_idle \"$self update\"; \
			$self ignore_args"
	trace variable filetypes_ w "$self set_filter; \
			$self ignore_args"
	trace variable filter_(current) w "$self do_when_idle \
			\"$self update\"; $self ignore_args"
	$self do_when_idle "$self update"
}
FileBox instproc config_directory { option value } {
	if { $value=={} } {
		set value [pwd]
	}
	$self tkvar directory_
	set directory_ $value
}
FileBox instproc cget_directory { option } {
	$self tkvar directory_
	return $directory_
}
FileBox instproc config_filename { option value } {
	$self tkvar filename_
	set filename_ $value
}
FileBox instproc cget_filename { option } {
	$self tkvar filename_
	return $filename_
}
FileBox instproc config_filetypes { option value } {
	set filetypes [$self subwidget filetypes]
	$filetypes delete 0 end
	$self tkvar filetypes_
	set filetypes_ ""
	$self tkvar filter_
	catch { unset filter_ }
	if { [trace vinfo filter_(current)]=="" } {
		trace variable filter_(current) w "$self do_when_idle \
				\"$self update\"; $self ignore_args"
	}
	if { [llength $value]==0 } {
		$filetypes configure -state disabled
		$self subwidget filetypes_label configure -foreground \
				[$filetypes subwidget button cget \
				-disabledforeground]
		set filter_(all) ""
		set filter_(current) ""
	} else {
		$filetypes configure -state normal
		$self subwidget filetypes_label configure -foreground \
				[$filetypes subwidget button cget \
				-foreground]
		foreach filetype $value {
			set name [lindex $filetype 0]
			append name " ("
			set filter ""
			set first 1
			foreach ext [lindex $filetype 1] {
				set ext [string trim $ext]
				if { $first } {
					set first 0
				} else {
					append name ", "
				}
				if { $ext=="*" } {
					append name "*"
					lappend filter ".*" "*"
				} else {
					append name "*$ext"
					lappend filter "*$ext"
				}
			}
			append name ")"
			set filter_(filter_for_$name) $filter
			$filetypes insert end $name
		}
		set filter_(all) $value
	}
}
FileBox instproc cget_filetypes { option } {
	$self tkvar filter_
	if { [info exists filter_(all)] } {
		return $filter_(all)
	} else {
		return ""
	}
}
FileBox instproc config_browsecmd { option value } {
	$self instvar browsecmd_
	set browsecmd_ [string trim $value]
}
FileBox instproc cget_browsecmd { option } {
	$self instvar browsecmd_
	return $browsecmd_
}
FileBox instproc config_command { option value } {
	$self instvar command_
	set command_ [string trim $value]
}
FileBox instproc cget_command { option } {
	$self instvar command_
	return $command_
}
FileBox instproc set_filter { args } {
	$self tkvar filter_
	$self tkvar filetypes_
	if { [info exists filter_(filter_for_$filetypes_)] } {
		set filter_(current) $filter_(filter_for_$filetypes_)
	} else {
		set filter_(current) $filetypes_
	}
}
FileBox instproc current_filter { args } {
        $self tkvar filter_
        return $filter_(current)
}
FileBox instproc invoke { cmdType args } {
	set varname "${cmdType}_"
	$self instvar "$varname cmd"
	if { $cmd!="" } {
		uplevel #0 $cmd $args
	}
}
FileBox instproc list_browse { text } {
	$self tkvar directory_ filename_
	if {$text == ""} {
		return
	}
	set file [file join $directory_ $text]
		set filename_ $text
	$self invoke browsecmd $text
}
FileBox instproc list_command { text } {
	$self tkvar directory_ filename_
	if {$text == ""} {
		return
	}
	set file [file join $directory_ $text]
	if [file isdirectory $file] {
		set appPWD [pwd]
		if [catch {cd $file}] {
			Dialog transient MessageBox -type ok -text \
				"Cannot change to the directory \"$file\".\
				\nPermission denied." -image Icons(warning)
		} else {
			cd $appPWD
			set directory_ $file
		}
	} else {
		set filename_ $text
		$self invoke command $text
	}
}
FileBox instproc up_folder_cmd { } {
	$self tkvar directory_
	if [string compare $directory_ "/"] {
		set directory_ [file dirname $directory_]
	}
}
FileBox instproc entry_command { } {
	$self tkvar directory_ filename_ filetypes_
	set list [$self resolve_file $directory_ $filename_]
	set flag [lindex $list 0]
	set path [lindex $list 1]
	set file [lindex $list 2]
	case $flag {
		OK {
			set directory_ $path
			set filename_  $file
			if [string compare $file ""] {
				$self invoke command
			}
		}
		PATTERN {
			set directory_ $path
			set filetypes_ $file
		}
		FILE {
			set directory_ $path
			set filename_  $file
			$self invoke command
		}
		PATH {
			Dialog transient MessageBox -image Icons(warning) \
					-type ok -text \
					"Directory \"$path\" does not exist."
			set entry [$self subwidget filename]
			$entry select from 0
			$entry select to end
			$entry icursor end
		}
		CHDIR {
			Dialog transient MessageBox -type ok -text \
					"Cannot change to the directory \"$path\".\nPermission denied."	-image Icons(warning)
			set entry [$self subwidget filename]
			$entry select from 0
			$entry select to end
			$entry icursor end
		}
		ERROR {
			Dialog transient MessageBox -type ok -text \
					"Invalid file name \"$path\"."\
					-image Icons(warning)
			set entry [$self subwidget filename]
			$entry select from 0
			$entry select to end
			$entry icursor end
		}
	}
}
FileBox instproc resolve_file {context text} {
	set appPWD [pwd]
	set path [file join $context $text]
	if [catch {file exists $path}] {
		return [list ERROR $path ""]
	}
	if [file exists $path] {
		if [file isdirectory $path] {
			if [catch {
				cd $path
			}] {
				return [list CHDIR $path ""]
			}
			set directory [pwd]
			set file ""
			set flag OK
			cd $appPWD
		} else {
			if [catch {
				cd [file dirname $path]
			}] {
				return [list CHDIR [file dirname $path] ""]
			}
			set directory [pwd]
			set file [file tail $path]
			set flag OK
			cd $appPWD
		}
	} else {
		set dirname [file dirname $path]
		if [file exists $dirname] {
			if [catch {
				cd $dirname
			}] {
				return [list CHDIR $dirname ""]
			}
			set directory [pwd]
			set file [file tail $path]
			if [regexp {[*]|[?]} $file] {
				set flag PATTERN
			} else {
				set flag FILE
			}
			cd $appPWD
		} else {
			set directory $dirname
			set file [file tail $path]
			set flag PATH
		}
	}
	return [list $flag $directory $file]
}
FileBox instproc update { } {
	$self instvar updateId_
	catch {unset updateId_}
	set appPWD [pwd]
	set dir [$self cget -directory]
	if [catch {
		cd $dir
	}] {
		Dialog transient MessageBox -type ok -text \
				"Cannot change to the directory \"$dir\".\
				\nPermission denied." -image Icons(warning)
		cd $appPWD
		return
	}
	set entry [$self subwidget filename]
	set toplevel [winfo toplevel [$self info path]]
	set entryCursor [$entry cget -cursor]
	set toplevelCursor [$toplevel cget -cursor]
	$entry    config -cursor watch
	$toplevel config -cursor watch
	update idletasks
	set listbox [$self subwidget listbox]
	$listbox delete_all
	foreach f [lsort -command tclSortNoCase [glob -nocomplain .* *]] {
		if ![string compare $f .] {
			continue
		}
		if ![string compare $f ..] {
			continue
		}
		if [file isdirectory ./$f] {
			if ![info exists hasDoneDir($f)] {
				$listbox add Icons(folder) $f
				set hasDoneDir($f) 1
			}
		}
	}
	$self tkvar filter_
	if { ![string compare $filter_(current) *] || \
			$filter_(current)=="" } {
		set files [lsort -command tclSortNoCase \
				[glob -nocomplain .* *]]
	} else {
		set files [lsort -command tclSortNoCase \
				[eval glob -nocomplain $filter_(current)]]
	}
	set top 0
	foreach f $files {
		if ![file isdir $f] {
			if ![info exists hasDoneFile($f)] {
				$listbox add Icons(textfile) $f
				set hasDoneFile($f) 1
			}
		}
	}
	$listbox arrange
	set list ""
	set dir ""
	$self tkvar directory_
	foreach subdir [file split $directory_] {
		set dir [file join $dir $subdir]
		lappend list $dir
	}
	$self subwidget directory delete 0 end
	eval [list $self] subwidget directory insert end $list
	cd $appPWD
	$entry    config -cursor $entryCursor
	$toplevel config -cursor $toplevelCursor
}
WidgetClass DirectoryBox -configspec {
	{ -directory directory Directory { } config_directory cget_directory }
	{ -browsecmd browseCmd BrowseCmd { } config_option }
	{ -command command Command { } config_option }
	{ -allownonexistent allowNonexistent AllowNonexistent { 0 }
	config_option }
} -default {
	{ *font WidgetDefault }
	{ *Entry.borderWidth 1 }
	{ *Entry.highlightThickness 1 }
	{ *ScrolledListbox.borderWidth 1 }
	{ *ScrolledListbox.relief sunken }
	{ *ScrolledListbox.scrollbar both }
	{ *ScrolledListbox.itemClass HierarchicalListboxItem }
	{ *ScrolledListbox.bbox.highlightThickness 1 }
	{ *ScrolledListbox.Scrollbar.borderWidth 1 }
	{ *ScrolledListbox.Scrollbar.borderWidth 1 }
	{ *ScrolledListbox.Scrollbar.highlightThickness 1 }
	{ *ScrolledListbox.Scrollbar.width 10 }
	{ *HierarchicalListboxItem.borderWidth 1 }
}	
DirectoryBox instproc build_widget { path } {
	ScrolledListbox $path.dirbox -browsecmd "$self browse" \
			-command "$self invoke; $self ignore_args"
	frame $path.f1
	label $path.entry_label -text "Directory:"
	entry $path.entry -textvariable [$self tkvarname entry_]
	pack $path.entry_label -side left -in $path.f1
	pack $path.entry -side right -fill x -expand 1 -in $path.f1
	pack $path.f1 -side bottom -fill x
	pack $path.dirbox -side top -fill both -expand 1
	bind $path <Map> "$self set_trace"
	bind $path.entry <Return>   "$self entry_invoke"
	bind $path.entry <FocusIn>  "$self entry_focus_in"
	bind $path.entry <FocusOut> "$self entry_focus_out"
}
DirectoryBox instproc config_directory { option dir } {
	$self tkvar directory_
	if { [string trim $dir]=={} } {
		set directory_ [pwd]
	} else {
		set directory_ $dir
	}
}
DirectoryBox instproc cget_directory { option } {
	$self tkvar directory_
	return $directory_
}
DirectoryBox private set_trace { } {
	$self tkvar directory_
	trace variable directory_ w "$self do_when_idle \"$self update\"; \
			$self ignore_args"
	if [info exists directory_] {
		set directory_ $directory_
	}
	bind [$self info path] <Map> ""
}
DirectoryBox instproc config_option { option args } {
	$self instvar config_
	if { [llength $args]==0 } {
		return $config_($option)
	} else {
		set config_($option) [string trim [lindex $args 0]]
	}
}
DirectoryBox instproc entry_invoke { } {
	$self tkvar entry_ directory_
	set path [file join $directory_ $entry_]
	if { ![file isdirectory $path] } {
		if { ![$self cget -allownonexistent] } {
			Dialog transient MessageBox -type ok -text \
					"Invalid directory \"$path\"" \
					-image Icons(warning)
		} elseif { ![file exists $path] } {
			set retval [Dialog transient MessageBox \
					-type yesno -text \
					"Directory \"$path\" does\nnot exist\
					\n\nWould you like to create it?" \
					-image Icons(warning)]
			if { $retval=="yes" } {
				if [$self create_dir $path] {
					set directory_ $path
					set entry_ ""
				}
			}
		} else {
			Dialog transient MessageBox -type ok -text \
					"There is already a file with the\
					\nsame name" -image Icons(warning)
		}
	} else {
		set directory_ $path
		set entry_ ""
	}
}
DirectoryBox private create_dir { path } {
	set dir ""
	foreach split [file split $path] {
		set dir [file join $dir $split]
		if { ![file exists $dir] } {
			if [catch {file mkdir $dir}] {
				Dialog transient MessageBox -type ok -text \
						"Error occurred while creating\
						\"$dir\"" -image Icons(warning)
				return 0
			}
		}
	}
	return 1
}
DirectoryBox instproc entry_focus_in { } {
	$self tkvar entry_
	set entry [$self subwidget entry]
	if [string compare $entry_ ""] {
		$entry selection from 0
		$entry selection to   end
		$entry icursor end
	} else {
		$entry selection clear
	}
}
DirectoryBox instproc entry_focus_out { } {
	$self subwidget entry selection clear
}
DirectoryBox instproc browse { id } {
	$self tkvar directory_
	set directory [$self subwidget dirbox info value -id $id]
	if { [string compare $directory $directory_] } {
		focus [$self subwidget dirbox subwidget window]
		global tcl_platform
		if { $tcl_platform(platform) == "windows" } {
			if { [string first "/" $directory] == -1 } {
				append directory "/"
			}
		}
		set directory_ $directory
		set browsecmd [$self cget -browsecmd]
		if { $browsecmd != {} } {
			uplevel #0 $browsecmd $directory
		}
	}
}
DirectoryBox instproc invoke { } {
	set command [$self cget -command]
	if { $command != {} } {
		$self tkvar directory_
		uplevel #0 $command $directory_
	}
}
DirectoryBox instproc update { } {
	set directory [$self cget -directory]
	set appPWD [pwd]
	if [catch {
		cd $directory
		set directory [pwd]
	}] {
		Dialog transient MessageBox -type ok -text \
				"Cannot change to the directory \"$directory\"\
				\nPermission denied." -image Icons(warning)
		cd $appPWD
		return
	}
	set dirbox [$self subwidget dirbox]
	$dirbox delete all
	set toplevel [winfo toplevel [$self info path]]
	set toplevelCursor [$toplevel cget -cursor]
	$toplevel config -cursor watch
	update idletasks
	set split [file split $directory]
	set root [lindex $split 0]
	foreach volume [file volume] {
		global tcl_platform
		if { $tcl_platform(platform)=="windows" } {
			set print_vol [string toupper \
					[lindex [split $volume "/"] 0]]
		} else {
			set print_vol $volume
		}
		if { [string tolower $volume]==[string tolower $directory] } {
			$dirbox insert end [list -id curdir Icons(folderopen)\
					$print_vol]
		} else {
			$dirbox insert end [list Icons(folder)\
					$print_vol]
		}
		if { [string tolower $volume]==[string tolower $root] } {
			set dir $root
			foreach subdir [lrange $split 1 end] {
				set dir [file join $dir $subdir]
				if { $dir==$directory } {
					$dirbox insert end [list -id curdir \
							Icons(folderopen) $dir]
				} else {
					$dirbox insert end [list Icons(folder)\
							$dir]
				}
			}
			foreach dir [lsort -command tclSortNoCase \
					[glob -nocomplain .* *]] {
				if ![string compare $dir .] {
					continue
				}
				if ![string compare $dir ..] {
					continue
				}
				set isdir 0
				if { [catch {file isdir $dir} isdir]==0 && \
						$isdir } {
					if ![info exists hasDoneDir($dir)] {
						set path [file join $directory\
								$dir]
						$dirbox insert end [list \
								Icons(folder) \
								$path]
						set hasDoneDir($dir) 1
					}
				}
			}
		}
	}
	cd $appPWD
	$toplevel config -cursor $toplevelCursor
	$dirbox selection set -id curdir
	$self tkvar entry_
	set entry_ $directory
}
WidgetClass FileDialog -superclass Dialog -configspec {
	{ -type type Type open config_type cget_type }
} -default {
	{ *font WidgetDefault }
	{ *ImageTextButton.borderWidth 1 }
	{ *ImageTextButton.highlightThickness 1 }
}
FileDialog instproc build_widget { path } {
	frame   $path.frame
	FileBox $path.filebox -command "$self command; $self ignore_args"
	frame   $path.buttonbox
	ImageTextButton $path.buttonbox.ok -underline 0 -text "Open" \
			-image Icons(check) -orient horizontal \
			-command "$self invoke_ok_ \
			\[string tolower \[$path.buttonbox.ok cget -text\]\]"
	ImageTextButton $path.buttonbox.cancel -image Icons(cross) \
			-orient horizontal -text "Cancel" -underline 0 \
			-command "$self cancel"
	bind $path <Alt-o> "$self invoke_ok_ open"
	bind $path <Alt-s> "$self invoke_ok_ save"
	bind $path <KeyPress-Escape> "$self cancel"
	pack $path.buttonbox.ok $path.buttonbox.cancel -side left -anchor e\
			-padx 5 -pady 2
	pack $path.buttonbox -side bottom -in $path.frame -anchor e
	pack $path.filebox -side top -fill both -expand 1 -in $path.frame
	pack $path.frame -side left -fill both -expand 1
	$self set_subwidget ok     $path.buttonbox.ok
	$self set_subwidget cancel $path.buttonbox.cancel
}
FileDialog instproc config_type { option type } {
	set ok "[$self subwidget buttonbox].ok"
	switch -exact -- $type {
		open {
			$ok configure -text "Open"
		}
		save {
			$ok configure -text "Save"
		}
		default {
			error "invalid type specification; must be 'open' or\
					'save'"
		}
	}
}
FileDialog instproc cget_type { option } {
	set ok "[$self subwidget buttonbox].ok"
	return [string tolower [$ok cget -text]]
}
FileDialog instproc invoke_ok_ { type } {
	if { [$self cget -type] == $type } {
		$self subwidget filebox entry_command
	}
}
FileDialog instproc command { } {
	set filebox [$self subwidget filebox]
	set dir  [$filebox cget -directory]
	set file [$filebox cget -filename]
	if  { $file=="" } return
	set path [file join $dir $file]
	set exists [file exists $path]
	set type   [$self cget -type]
	if { ![string compare $type open] && !$exists } {
		Dialog transient MessageBox -image Icons(warning) -type ok \
				-text "File \"$path\" does not exist."
		return
	}
	if {![string compare $type save] && $exists} {
		set reply [Dialog transient MessageBox -image Icons(warning) \
				-type yesno -text \
				"File \"$path\" already exists.\
				\nDo you want to overwrite it?"]
		if ![string compare $reply "no"] {
			return
		}
	}
	$self config -result $path
}
FileDialog instproc cancel { } {
	$self config -result ""
}
WidgetClass DirectoryDialog -superclass Dialog -default {
	{ *font WidgetDefault }
	{ *ImageTextButton.borderWidth 1 }
	{ *ImageTextButton.highlightThickness 1 }
}
DirectoryDialog instproc build_widget { path } {
	frame  $path.frame
	DirectoryBox $path.dirbox -command "$self ok; $self ignore_args"
	frame  $path.buttonbox
	ImageTextButton $path.buttonbox.ok -underline 0 -text "Ok" \
			-image Icons(check) -orient horizontal \
			-command "$self ok"
	ImageTextButton $path.buttonbox.cancel -text "Cancel" -underline 0 \
			-image Icons(cross) -orient horizontal \
			-command "$self cancel"
	bind $path <KeyPress-Escape> "$self cancel"
	pack $path.buttonbox.ok $path.buttonbox.cancel -side left -anchor e\
			-padx 5 -pady 2
	pack $path.buttonbox -side bottom -in $path.frame -anchor e
	pack $path.dirbox -side top -fill both -expand 1 -in $path.frame
	pack $path.frame -side left -fill both -expand 1
	$self set_subwidget ok     $path.buttonbox.ok
	$self set_subwidget cancel $path.buttonbox.cancel
}
DirectoryDialog instproc ok { } {
	$self configure -result [$self subwidget dirbox cget -directory]
}
Class Setup
Setup proc.public instance { } {
	return [$self set instance_]
}
Setup public init { } {
	$self next
	Setup set instance_ $self
	if { [Setup system]=="Win32" } {
		$self set destination_ "C:/Program Files"
	} else {
		$self set destination_ "/usr/local"
	}
	$self set appname_ "your-app"
	$self set company_name_ ""
	$self set copyright_ {}
	$self set install_types_ [list typical custom]
	$self set install_types_help_ [list \
			"This is the recommended installation." \
			"Select this option to customize your\
			\ninstallation. Setup will prompt you to\
			\nselect individual components from the\
			\ncomplete installation list" ]
	$self set components(typical) {}
	$self set components(custom) {}
}
Setup proc.public system { } {
	global tcl_platform
	if { $tcl_platform(platform)=="windows" } {
		return Win32
	} else {
		return Unix
	}
}	
Setup public run { } {
	$self do_interactive
	$self do_install
	$self do_finish
}
Setup private do_interactive { } {
	set dialogs [$self dialog_list]
	foreach cls [concat CancelDlg CustomDlg $dialogs] {
		set path ".[string tolower $cls]"
		$cls $path
	}
	if { ![catch {set next [$path subwidget next]}] } {
		$next configure -text "Finish" -command "$path configure \
				-result Finish"
	}
	set cur_dlg [lindex $dialogs 0]
	while { 1 } {
		set retval [$self do_dialog $cur_dlg]
		if { $retval=={} } {
			break
		} elseif { $retval != 0 } {
			set idx [lsearch $dialogs $cur_dlg]
			set cur_dlg [lindex $dialogs \
					[expr $idx + $retval]]
		}
        }
}
Setup public do_dialog { dlg } {
	set path ".[string tolower $dlg]"
	set retval [string tolower [$path invoke]]
	switch -exact -- [$path interpret_result $retval] {
		"back" {
			if [$path verify back] {
				return -1
			}
		}
		"next" {
			if [$path verify next] {
				return 1
			}
		}
		"finish" {
			if [$path verify finish] {
				return {}
			}
		}
		"cancel" {
			if { [.canceldlg invoke]=="Exit" } {
				exit
			}
		}
	}
	return 0
}
Setup public do_install { } {
	SetupProgress .progress
	.progress center
	$self copy_files
	.progress check_next
	update
	after 5000
	destroy .progress
}
Setup private copy_files { } {
	$self instvar install_components_ files_
	set total [llength $install_components_]
	set idx 0
	set progress [winfo exists .progress]
	foreach component $install_components_ {
		set num_files [llength $files_($component)]
		set done [expr $idx*$num_files]
		if { $progress } {
			.progress subwidget bar configure \
					-max [expr $num_files*$total] \
					-value $done
			.progress subwidget info configure -text \
					"Copying $component"
			update
		}
		foreach file $files_($component) {
			if [catch {set files [glob $file]}] {
				set files $file
			}
			foreach f $files { $self copy_file $f }
			incr done
			if { $progress } {
				.progress subwidget bar configure -value $done
				update
			}
		}
		incr idx
	}
	if { $progress } {
		.progress subwidget info configure -text {}
	}
}
Setup private copy_file { file } {
	$self instvar destination_ replace_all_
	if { ![info exists replace_all_] } { set replace_all_ 0 }
	if { ![file readable $file] } {
		$self warn "Cannot find source file \"$file\"\
				\nSome components seem to be missing from\
				\nthe installation package. Setup will\
				\nignore this file."
		return
	}
	set destfile [file join $destination_ $file]
	set destdir [file dirname $destfile]
	set retval [$self create_dir $destdir]
	if { $retval != {} } {
		$self warn "Could not create directory \"$destdir\":\n$retval\
				\nSetup will ignore this error and continue\
				\nwith the rest of the installation."
		return
	}
	if { [file exists $destfile] && $replace_all_==0 } {
		if { ![$self should_replace $destfile $file] } {
			continue
		}
	}
	if {[catch {file copy -force -- $file $destfile} msg]} {
		$self warn "Could not copy file:\n$msg\
				\nSetup will ignore this error and continue\
				\nwith the rest of the installation."
		return
	}
}
Setup private should_replace { dest src } {
	set text "File \"$dest\" already exists.\
			\nDo you want to replace it with \"$src\"?\n\n"
	if { ![catch {file stat $dest dstat}] && \
			![catch {file stat $src sstat}] } {
		append text "    $dest:\
				\n        Last modified: [clock format \
				$dstat(ctime) -format \
				{%a %b %d %H:%M:%S %Z %Y}]\
				\n        Size: $dstat(size) bytes\
				\n    $src:\
				\n        Last modified: [clock format \
				$sstat(ctime) -format \
				{%a %b %d %H:%M:%S %Z %Y}]\
				\n        Size: $sstat(size) bytes\n\n"
	}
	set retval [Dialog transient MessageBox -text $text \
			-image Icons(warning) -options { {text.wraplength 0} }\
			-type \
			{ {replace -text Replace -under 0 -image Icons(check)}\
			{ replaceall -text {Replace All} -under 8 } \
			{ skip -text "Skip" -under 0 -image Icons(cross) } }]
	switch -exact -- $retval {
		"replace" {
			return 1
		}
		"replaceall" {
			$self set replace_all_ 1
			return 1
		}
		"skip" {
			return 0
		}
	}
	return 0
}
Setup private warn { msg } {
	$self instvar appname_ error_occurred_
	if { [Dialog transient MessageBox -text "Error occurred in $appname_\
			Setup.\n\n$msg\n\nWould you like to continue with the\
			setup?..." -image Icons(warning) -type yesno]=="no" } {
		exit
	}
	set error_occurred_ 1
}
Setup private do_finish { } {
	$self instvar appname_
	$self instvar error_occurred_
	if [info exists error_occurred_] {
		set text "\nThere were errors during the Setup process.\
				\nThe application may not have been installed\
				\nproperly.\
				\n\nYou could try to rectify those errors and\
				\ninvoke Setup again.\n\n"
		Dialog transient MessageBox -text $text -image Icons(warning) \
				-type ok
	} else {
		$self success
	}
	exit
}
Setup private success { } {
	set text "\n$appname_ has been successfully installed\
			\on your system.\n"
	Dialog transient MessageBox -text $text -image Icons(cal) \
			-type ok
}
Setup public dialog_list { } {
	$self instvar copyright_ install_types_
	set list [list WelcomeDlg]
	if { $copyright_ != {} } { lappend list CopyrightDlg }
	lappend list ChooseDstDlg
	if { [llength $install_types_] > 0 } { lappend list InstallTypeDlg }
	return $list
}
Setup public get_dirdlg { } {
	$self instvar dirdlg_
	if [info exists dirdlg_] { return $dirdlg_ }
	set dirdlg_ [DirectoryDialog .dirdlg]
	return $dirdlg_
}
Setup public get_real_dir { dirname } {
	while { $dirname != {} } {
		if [file isdirectory $dirname] {
			break
		}
		set newdir [file dirname $dirname]
		if { $newdir == $dirname } break
		set dirname $newdir
	}
	return $dirname
}
Setup private create_dir { path } {
	set dir ""
	foreach split [file split $path] {
		set dir [file join $dir $split]
		if { ![file exists $dir] } {
			if [catch {file mkdir $dir} msg] {
				return $msg
			}
		}
	}
	return {}
}
Class Setup/MASH -superclass Setup
Setup/MASH public init { } {
	$self next
	$self set appname_ "MASH"
	$self set copyright_ "lib/setup/COPYRIGHT"
	if { [Setup system]=="Win32" } {
		$self set destination_ "C:/Program Files/mash"
	}
	$self set components_(typical) [list "mash binaries" scripts mplug]
	$self set components_(custom) [$self set components_(typical)]
	$self set {component_help_(mash binaries)} \
			"This installs the executable files for\
			\nthe MASH shell and the Session Directory\
			\ntool"
	$self set component_help_(scripts) \
			"These are the various scripts for multimedia\
			\nconferencing that run on the MASH platform"
	$self set component_help_(mplug) \
			"This is a Web browser plugin for the MASH\
			\nplatform. It includes the plugin shared\
			\nlibrary and helper scripts and initialization\
			\nfiles"
	if { [Setup system]=="Win32" } {
		$self set {files_(mash binaries)} \
				[list mash.exe rsdr.exe tclpip80.dll]
	} else {
		global mash
		$self set {files_(mash binaries)} \
				[list bin/mash-$mash(version) bin/rsdr]
	}
	if { [Setup system]=="Win32" } {
		$self set files_(scripts) \
				[list vic vat mb recorder player \
				vic.exe vat.exe mb.exe \
				recorder.exe player.exe \
				lib/setup/setup lib/setup/setup.gif \
				lib/setup/COPYRIGHT]
	} else {
		$self set files_(scripts) \
				[list bin/vic bin/vat bin/mb \
				bin/recorder bin/player \
				lib/setup/setup lib/setup/setup.gif \
				lib/setup/COPYRIGHT]
	}
	$self instvar files_	
	 set files_(mplug) \
			 [list lib/npmplug* lib/prefs-mplug \
			 lib/mplug-test.html lib/mplug-test.mash]
	if  { [Setup system]=="Win32" } {
		lappend files_(mplug) script-loader 
	} else {
		lappend files_(mplug) bin/script-loader
	}
}
Setup/MASH public dialog_list { } {
	set list [$self next]
	lappend list SetEnvironDlg InstallMPlugDlg
	return $list
}
Setup/MASH public do_install { } {
	SetupProgress/MASH .progress
	.progress center
	$self copy_files
	$self link_mash
	.progress check_next
	update
	$self update_environment
	.progress check_next
	update
	$self install_mplug
	.progress check_next
	update
	destroy .progress
}
Setup/MASH public success { } {
	$self instvar appname_ destination_
	set text "\n$appname_ has been successfully installed\
			\on your system.\n"
	if {[Setup system]=="Win32"} {
		set bin [file nativename $destination_]
	} else {
		set bin [file nativename [file join $destination_ bin]]
	}
	set lib [file nativename [file join $destination_ lib]]
	append text "\nYou can find the executable files associated with\
			\n$appname_ in \"$bin\".\
			\nThe libraries, examples and initialization files\
			\nfor the various applications are in\
			\n\"$lib\"\n\
			\nEnjoy playing around with your new software!!!\n\n"
	set retval [Dialog transient MessageBox -text $text -image Icons(cal) \
			-type \
			{ {readme -text "View README.TXT" -under 0 \
			-image Icons(textfile) } \
			{ exit -text "Exit" -under 1 -image Icons(cross) } }]
	if { $retval == "readme" } {
		ReadmeDlg .readmedlg
		.readmedlg invoke
	}
}
Setup/MASH private link_mash { } {
	if { [Setup system]!="Unix" } return
	$self instvar destination_
	global mash
	set to [file join $destination_ bin/mash]
	$self copy_or_symlink/[Setup system] mash-$mash(version) $to
}
Setup/MASH private update_environment { } {
	$self instvar update_user_environ_ update_system_environ_
	.progress subwidget bar configure -max 2 -value 0
	update
	if { $update_user_environ_==1 } {
		.progress subwidget info configure -text \
				"Updating user environment"
		update
		$self update_user_environment/[Setup system]
	}
	.progress subwidget bar configure -value 1
	if { $update_system_environ_==1 } {
		.progress subwidget info configure -text \
				"Updating system environment"
		update
		$self update_system_environment/[Setup system]
	}
	.progress subwidget bar configure -value 2
	update
}
Setup/MASH private update_user_environment/Unix {} {
	$self instvar destination_
	QueryUnixRCFilesDlg .query
	set list [.query invoke]
	set comment "\n\n# Environment variables for MASH\n"
	set envline(.cshrc)   "${comment}setenv MASH_HOME $destination_"
	set envline(.tcshrc)  $envline(.cshrc)
	set envline(.profile) "${comment}MASH_HOME=$destination_\
			\nexport MASH_HOME"
	set shells(.cshrc)   "csh and tcsh"
	set shells(.tcshrc)  "tcsh"
	set shells(.profile) "sh and bash"
	foreach rcfile $list {
		$self update_environment_file "~/$rcfile" $envline($rcfile) \
				$shells($rcfile)
	}
}
Setup/MASH private update_system_environment/Unix {} {
	$self instvar destination_
	$self update_environment_file /etc/csh.cshrc \
			"setenv MASH_HOME $destination_" "csh and tcsh"
	$self update_environment_file /etc/profile \
			"MASH_HOME=$destination_\nexport MASH_HOME" \
			"sh and bash"
}
Setup/MASH private update_environment_file { filename envline shells } {
	if [file exists $filename] {
		if { [catch { set file [open $filename a] } msg ] } {
			set file ""
		}
	} else {
		if { [catch { set file [open $filename w] } msg ] } {
			set file ""
		}
	}
	if { $file=="" } {
		$self warn "Could not open $filename:\n$msg\n\nUnable to \
				update environment for $shells"
	} else {
		puts $file $envline
		close $file
	}
}
Setup/MASH private update_user_environment/Win32 { } {
	global tcl_platform
	if { $tcl_platform(os)=="Windows 95" } {
		$self update_user_environment/Win95
	} else {
		$self update_user_environment/WinNT
	}
}
Setup/MASH private update_system_environment/Win32 { } {
	global tcl_platform
	if { $tcl_platform(os)=="Windows NT" } {
		$self update_system_environment/WinNT
	}
}
Setup/MASH private update_user_environment/Win95 { } {
	$self instvar destination_
	set dest [file nativename $destination_]
	$self update_environ_file C:/autoexec.bat \
			"set MASH_HOME=\"$dest\"" "Windows 95"
	global env
	if { ![info exists env(HOME)] || env(HOME)=="" } {
		set def_home "C:\\"
		$self update_environment_file C:/autoexec.bat \
				"set HOME=\"$def_home\"" "Windows 95"
		Dialog transient MessageBox -text "\
				\nSetup has set your HOME environment variable\
				\nto ${def_home}. It is recommended that you\
				\nchange this to a directory where you store\
				\nyour local files.\n\
				\nSetup will look for a directory \".mash\" in\
				\nthis sub-directory for user-customized\
				\noptions.\n\
				\nYou can update your environment settings by\
				\nmanually editing the C:\\autoexec.bat file\
				\n\n" -image Icons(warning) -type ok
	}
}
Setup/MASH private update_user_environment/WinNT { } {
	$self instvar destination_
	set dest [file nativename $destination_]
	putregistry "HKEY_CURRENT_USER\\Environment" "MASH_HOME" $dest
	if { [catch {set HOME [getregistry \
			"HKEY_CURRENT_USER\\Environment" HOME]}] || \
			$HOME=={} } {
		set def_home "C:\\"
		putregistry "HKEY_CURRENT_USER\\Environment" "HOME" $def_home
		Dialog transient MessageBox -text "\
				\nSetup has set your HOME environment variable\
				\nto ${def_home}. It is recommended that you\
				\nchange this to a directory where you store\
				\nyour local files.\n\
				\nSetup will look for a directory \".mash\" in\
				\nthis sub-directory for user-customized\
				\noptions.\n\
				\nYou can update your environment settings by\
				\nselecting \"System\" from the Control Panel\
				\nand choosing the \"Environment\" tab.\n\n" \
				-image Icons(warning) -type ok
	}
}
Setup/MASH private update_system_environment/WinNT { } {
	$self instvar destination_
	set dest [file nativename $destination_]
	set key "HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\"
	append key "Control\\Session Manager\\Environment"
	putregistry $key "MASH_HOME" $dest
	if { [catch {set HOME [getregistry $key HOME]}] || $HOME=={} } {
		set def_home "C:\\"
		putregistry $key "HOME" $def_home
		Dialog transient MessageBox -text "\
				\nSetup has set a system-wide HOME environment\
				\nvariable to ${def_home}. It is recommended\
				\nthat you change this on a per-user basis\
				\nto a directory where the user stores his/her\
				\nlocal files.\n\
				\nSetup will look for a directory \".mash\" in\
				\nthis sub-directory for user-customized\
				\noptions.\n\
				\nYou can update your environment settings by\
				\nselecting \"System\" from the Control Panel\
				\nand choosing the \"Environment\" tab.\n\n" \
				-image Icons(warning) -type ok
	}
}
Setup/MASH private install_mplug { } {
	$self instvar install_components_
	if { [lsearch $install_components_ mplug] == -1 } {
		return
	}
	$self instvar destination_
	set npmplug_so [file join $destination_ lib/npmplug.*]
	if { [catch { set npmplug_so [glob $npmplug_so] } msg] } {
		$self warn "Could not find MASH plugin files:\n$msg\n\
				\nSome components seem to be missing from the\
				\ninstallation package."
		return
	}
	$self instvar mplug_dest_
	.progress subwidget bar configure -max [llength $mplug_dest_] \
			-value 0
	.progress subwidget info configure -text \
			"Installing MASH plugin"
	update
	set done 0
	foreach dir $mplug_dest_ {
		set msg [$self create_dir $dir]
		if { $msg!={} } {
			$self warn "Could not create directory:\
					$dir\n$msg"
		}
		foreach file $npmplug_so {
			$self copy_or_symlink/[Setup system] $file $dir
		}
		incr done
		.progress subwidget bar configure -value $done
		update
	}
	.progress subwidget info configure -text \
			"Updating preferences file for MASH plugin"
	update
	$self update_prefs_mplug
}
Setup/MASH private copy_or_symlink/Unix { src dest } {
	set src  [$self do_tilde_subst $src]
	set dest [$self do_tilde_subst $dest]
	if {[catch { set retval [exec ln -nsf "$src" "$dest"] } msg ] } {
		$self warn "Could not create symbolic links between\
				\n$src and $dest:\n$msg"
		return
	} else {
		set retval [string trim $retval]
		if { $retval!={} } {
			$self warn "Possible error while creating symbolic\
					links\nbetween $src and $dest\n:\
					\n$retval"
			return
		}
	}
}
Setup/MASH private copy_or_symlink/Win32 { src dest } {
	if {[catch { file copy -force -- $src $dest } msg ] } {
		$self warn "Could not copy MASH plugin files\
				\n$src to $dest"
		return
	}
}
Setup/MASH private do_tilde_subst { file } {
	set split [file split $file]
	if { [lindex $split 0] == "~" } {
		global env
		if [info exists env(HOME)] {
			set file [eval file join \
					[lreplace $split 0 0 $env(HOME)]]
		} else {
			set file [eval file join [lreplace $split 0 0]]
		}
	}
	return $file
}
Setup/MASH private update_prefs_mplug { } {
	$self instvar destination_
	set prefs_mplug [file join $destination_ "lib/prefs-mplug"]
	if { ![file exists $prefs_mplug] } {
		$self warn "Could not find file \"$prefs_mplug\"\
				\nSome components seem to be missing from the\
				installation\npackage."
		return
	}
	if { [catch {set file [open $prefs_mplug]} msg] } {
		$self warn "Error occurred while opening the MASH plugin\
				\npreferences file \"$prefs_mplug\"\n($msg)\
				\n\nSetup will not be able to update the\
				\plugin preferences."
		return
	}
	set mash_home [file nativename $destination_]
	set buffer ""
	while { [gets $file line] >= 0 } {
		set line [string trim $line]
		set first [string index $line 0]
		if { $first!="#" } {
			regsub -all -- {\$MASH_HOME} $line $mash_home line
		}
		append buffer "$line\n"
	}
	close $file
	if { [catch {set file [open $prefs_mplug w]} msg] } {
		$self warn "Error occurred while writing to the MASH plugin\
				\npreferences file \"$prefs_mplug\"\n($msg)\
				\n\nSetup will not be able to update the\
				\plugin preferences."
		return
	}
	if { [catch {puts -nonewline $file $buffer} msg] } {
		$self warn "Error occurred while writing to the MASH plugin\
				\npreferences file \"$prefs_mplug\"\n($msg)\
				\n\nSetup will not be able to update the\
				\plugin preferences."
		return
	}
	close $file
}
WidgetClass SetEnvironDlg -superclass SetupDialog -default {
	{ .title "Update Environment Variables" }
	{ *Checkbutton.borderWidth 1 }
}
SetEnvironDlg private build_widget { path } {
	$self tkvar update_user_environ_ update_system_environ_
	set path [$self build_skeleton $path [list Back Next Cancel]]
	label $path.label -justify left -text \
			"Setup will attempt to reconfigure you environment\
			\nby adding the appropriate system variables to your\
			\nstartup files\
			\n\nSetup can reconfigure the environment for either,\
			\njust you (User Environment), or the entire\
			\nsystem (System Environment), or both. You must have\
			\nadministrative/root priviledges in order to update\
			\nthe System Enviroment. Check that box only if you\
			\nhave those priviledges.\
			\n\nOn UNIX systems, you can get root priviledges by\
			\nrunning Setup as the \"root\" user. On Windows\
			\nsystems, you must be the Administrator in order to\
			\nupdate the System Environment\
			\n\nYou can choose to skip this step completely by not\
			\nselecting either of the following choices.\n"
	frame $path.frame -borderwidth 2 -relief groove
	label $path.envlabel -text "Update environment variables"
	set update_user_environ_ 1
	set update_system_environ_ 0
	checkbutton $path.user -text "User Environment (only yours)" \
			-variable [$self tkvarname update_user_environ_]
	checkbutton $path.system -text "System Environment (global)" \
			-variable [$self tkvarname update_system_environ_]
	global tcl_platform
	if { $tcl_platform(os)=="Windows 95" } {
		$path.system configure -state disabled
	}
	pack $path.label -side top -pady 5 -padx 5
	pack $path.envlabel -in $path.frame -side top -anchor w -padx 5 -pady 2
	pack $path.user   -in $path.frame -side top -anchor w -padx 20 -pady 1
	pack $path.system -in $path.frame -side top -anchor w -padx 20 -pady 1
	pack $path.frame -side top -padx 5 -pady 10 -fill x
}
SetEnvironDlg private verify { direction } {
	if { $direction=="back" } { return 1 }
	set setup [Setup instance]
	$self tkvar update_user_environ_ update_system_environ_
	$setup set update_user_environ_ $update_user_environ_
	$setup set update_system_environ_ $update_system_environ_
	return 1
}
WidgetClass InstallMPlugDlg -superclass SetupDialog -default {
	{ .title "Copy MASH plugin files" }
	{ *Checkbutton.borderWidth 1 }
}
InstallMPlugDlg private build_widget { path } {
	set setup [Setup instance]
	$setup instvar appname_
	set path [$self build_skeleton $path [list Back Next Cancel]]
	set text \
			"The $appname_ software comes with a plugin for\
			Netscape and\nMicrosoft Internet Explorer that can be\
			used to enhance\nthe capabilities of your web-browser\
			by allowing\nit to browse the MBone and participate\
			in MBone sessions\
			\n\nSetup must copy the plugin files to your browser's\
			directory,\nin order for it to work.\n\
			\nThe Setup program has auto-detected the following\
			browser\nplugin directories on your system. Please\
			select \"Add to list\"\
			\nto make additions to this list.\n\n"
	if { [Setup system]=="Unix" } {
		append text \
				"Your browser's plugin directory is usually a\
				directory called\n\"plugins\" somewhere under\
				your browser's installation.\
				\nFor example,\
				/usr/local/netscape/lib/plugins\n\
				\nPlease note that you might require root\
				priviledges in order to\ninstall the plugin\
				in some of these directories.\n"
	} else {
		append text \
				"Your browser's plugin directory is usually a\
				directory called \"Plugins\" somewhere under\
				\nyour browser's installation.\
				\nFor example,\
				\n    C:\\Program Files\\Netscape\\Communicator\\Program\\Plugins, or\
				\n    C:\\Program Files\\Microsoft Internet\\Plugins\n\
				\nPlease note that you might require administrative\
				priviledges in order to\ninstall the plugin\
				in some of these directories.\n"
	}
	label $path.label -justify left -text $text
	pack $path.label -side top -pady 5 -padx 5
	frame $path.f1 -borderwidth 2 -relief groove
	frame $path.f2
	label $path.cplabel -text "Copy MASH plugin files to:" -justify left \
			-anchor w
	pack $path.cplabel -in $path.f2 -side left -anchor w -padx 5 -pady 0 \
			-fill x -expand 1
	button $path.add -text "Add to list..." -command "$self add"
	pack $path.add -in $path.f2 -side right -anchor e -padx 5 -pady 0
	pack $path.f2 -in $path.f1 -padx 0 -pady 2 -fill x
	$self tkvar copy_list_
	set copy_list_(count) 0
	foreach mplugpath [$self search_browsers] {
		set copy_list_(path,$mplugpath) 0
		checkbutton $path.check$copy_list_(count) -text $mplugpath \
				-variable \
				[$self tkvarname copy_list_(path,$mplugpath)]
		pack $path.check$copy_list_(count) -in $path.f1 -side top \
				-anchor w -padx 20 -pady 1
		incr copy_list_(count)
	}
	pack $path.f1 -side top -padx 5 -pady 10 -fill x
	label $path.disabled -justify left -anchor w -text \
			"The installation that you have chosen does not\
			\ninclude the MASH plugin. If you would like to\
			\ninstall the plugin, please hit \"Back\" and\
			\nchange your installation options."
}
InstallMPlugDlg private verify { direction } {
	if { $direction=="back" } { return 1 }
	$self tkvar copy_list_
	set setup [Setup instance]
	$setup instvar mplug_dest_
	set mplug_dest_ {}
	foreach name [array names copy_list_ "path,*"] {
		if { $copy_list_($name) } {
			set filepath [string range $name 5 end]
			lappend mplug_dest_ $filepath
		}
	}
	return 1
}
InstallMPlugDlg public invoke { args } {
	set setup [Setup instance]
	$setup instvar install_components_
	if { [lsearch $install_components_ mplug] == -1 } {
		$self set_state disabled
	} else {
		$self set_state normal
	}
	return [eval [list $self] next $args]
}
InstallMPlugDlg private set_state { state } {
	$self tkvar copy_list_
	set path [$self subwidget main]
	for { set idx 0 } { $idx < $copy_list_(count) } { incr idx } {
		 $path.check$idx configure -state $state
	}
	$path.add configure -state $state
	if { $state=="disabled" } {
		set fg [$path.add cget -disabledforeground]
		pack $path.disabled -side top -padx 5 -pady 5 -anchor w
	} else {
		set fg [$path.add cget -foreground]
		catch {pack forget $path.disabled}
	}
	$path.label configure -foreground $fg
	$path.cplabel configure -foreground $fg
}
InstallMPlugDlg private search_browsers { } {
	return [$self search_browsers/[Setup system]]
}
InstallMPlugDlg private add { } {
	$self tkvar copy_list_
	set setup [Setup instance]
	set dirdlg [$setup get_dirdlg]
	$dirdlg configure -title "Choose browser plugin directory"
	$dirdlg subwidget dirbox configure -allownonexistent 0
	set retval [$dirdlg invoke]
	if { $retval!={} } {
		set path [$self info path]
		set copy_list_(path,$retval) 1
		checkbutton $path.check$copy_list_(count) -text $retval \
				-variable \
				[$self tkvarname copy_list_(path,$retval)]
		pack $path.check$copy_list_(count) -in $path.main.f1 \
				-side top \
				-anchor w -padx 20 -pady 1
		incr copy_list_(count)
	}
}
InstallMPlugDlg private search_browsers/Unix { } {
	set list [list ~/.netscape/plugins]
	foreach dir [list /usr/local/netscape/lib/plugins \
			/usr/local/lib/netscape/plugins] {
		if [file isdirectory $dir] { lappend list $dir }
	}
	return $list
}
InstallMPlugDlg private search_browsers/Win32 { } {
	set list {}
	set key "HKEY_LOCAL_MACHINE\\Software\\Classes\\"
	append key "http\\shell\\open\\command"
	if { ![catch {set browser [getregistry $key ""]}] && $browser!={} } {
		set browser [string trim $browser]
		set idx [string first " -" $browser]
		if { $idx==-1 } { set idx [string first " \"-" $browser] }
		if { $idx!=-1 } {
			set pathname [string trim [string range $browser 0 \
					[expr $idx-1]]]
		} else {
			set pathname $browser
		}
		set plugindir [file join [file dirname $pathname] Plugins]
		if [file isdirectory $plugindir] {
			set list [list $plugindir]
		}
	}
	foreach dir [list "C:/Program Files/Netscape/Communicator/Program/Plugins" "C:/Program Files/Netscape/Navigator/Program/Plugins" "C:/Program Files/Microsoft Internet/Plugins" "C:/Program Files/Plus!/Microsoft Internet/Plugins" "C:/Program Files/Internet"] {
		if [file isdirectory $dir] {
			if { [lsearch [string tolower $list] \
					[string tolower $dir]] == -1 } {
				lappend list $dir
			}
		}
	}
	return $list
}
WidgetClass QueryUnixRCFilesDlg -superclass Dialog -default {
	{ .title "Select RC files" }
	{ *Checkbutton.borderWidth 1 }
	{ *ImageTextButton.borderWidth 1 }
	{ *Label.font WidgetDefault }	
}
QueryUnixRCFilesDlg private build_widget { path } {
	label $path.label -justify left -anchor w -text \
			"Setup can update one or more of the following startup\
			\nfiles in your home directory. Please select which\
			\nones you would like Setup to update, depending on\
			\nyour preferred shell"
	checkbutton $path.cshrc -text ".cshrc (csh and tcsh)" -anchor w \
			-variable [$self tkvarname cshrc]
	checkbutton $path.tcshrc -text ".tcshrc (tcsh only)" -anchor w \
			-variable [$self tkvarname tcshrc]
	checkbutton $path.profile -text ".profile (sh and bash)" -anchor w \
			-variable [$self tkvarname profile]
	ImageTextButton $path.ok -text "Ok" -image Icons(check) \
			-command "$self ok"
	pack $path.label -side top -fill x -padx 10 -pady 10
	pack $path.cshrc $path.tcshrc $path.profile -fill x -padx 20
	pack $path.ok -anchor e -padx 20 -pady 15
}
QueryUnixRCFilesDlg private ok { } {
	$self tkvar cshrc tcshrc profile
	set list {}
	if { $cshrc   } { lappend list .cshrc   }
	if { $tcshrc  } { lappend list .tcshrc  }
	if { $profile } { lappend list .profile }
	$self configure -result $list
}
WidgetClass SetupProgress/MASH -superclass SetupProgress
SetupProgress/MASH private checklist { } {
	set list [$self next]
	lappend list "Update environment variables" "Install MASH plugin"
	return $list
}
WidgetClass ReadmeDlg -superclass SetupDialog -default {
	{ .title "README.TXT" }
	{ *Text*borderWidth 1 }
	{ *Scrollbar*borderWidth 1 }
	{ *Scrollbar*width 10 }
}
ReadmeDlg private build_widget { path } {
	if [catch {set file [open README.TXT "r"]} msg ] {
		set msg "Could not open README file:\n$msg"
	} else {
		set msg ""
		while { [gets $file line] >= 0 } {
			append msg "$line\n"
		}
		close $file		
	}
	set path [$self build_skeleton $path [list Exit]]
	ScrolledText $path.readme -scrollbar both -options \
			{ {text.width 60} {text.height 16} {text.wrap none} }
	$path.readme subwidget text insert end $msg
	$path.readme subwidget text configure -state disabled
	pack $path.readme -fill both -expand 1
}
option add *MessageBox*Label.font [WidgetClass widget_default -font]
option add *MessageBox*Label.wrapLength 0
wm withdraw .
if { $argv != {} } {
	foreach file $argv { source $file }
}
set cls [lindex [Setup info subclass] 0]
if { $cls=={} } { set cls Setup }
[new $cls] run
