namespace eval ::wizard {
    variable path ""
    variable current_form_type ""
    variable execute_proc
    variable prolog
    variable epilog
    variable pageframe
    variable help
    variable lastpage 0
    variable exec_style 0
    variable minimum
    variable maximum
    variable boxstart
    variable boxfinish
    variable boxbottom
    variable thermoitem
    
    variable curwizard ""
    variable curthemow ""
    variable allwidgets ""
    variable standalone 0
    
    variable pagenames ""
    variable pagedescr ""
}

# configure the buttons for a page

proc ::wizard::init_wizard {} {
    
    set ::wizard::current_form_type ""
    set ::wizard::lastpage 0
    set ::wizard::exec_style 0
    set ::wizard::curwizard ""
    set ::wizard::curthemow ""
    set ::wizard::standalone 0
    set ::wizard::pagenames ""
    set ::wizard::pagedescr ""
}

proc ::wizard::configure_buttons {page} {
    
    set d $::wizard::curwizard
    set in_frame $d.buts.variable
    foreach c [winfo children $in_frame] {
	destroy $c
    }

    # put up appropriate buttons for that page
    
    set col 0
    if {$page != 0} {
	button $in_frame.prev -text "<< Prev" \
	    -command "::wizard::setpage $page 0"
	blt_table $in_frame $in_frame.prev 0,$col \
	    -fill both -ipadx 2 -ipady 2 -padx 2 -pady 2
	incr col
    }
	    
    if {$page != $::wizard::lastpage - 1} {
	button $in_frame.next -text "Next >>" \
	    -command "::wizard::setpage $page 1"
	blt_table $in_frame $in_frame.next 0,$col \
	    -fill both -ipadx 2 -ipady 2 -padx 2 -pady 2
    } else {
	button $in_frame.done -text "Done" \
	    -command "::wizard::execute"
	blt_table $in_frame $in_frame.done 0,$col \
	    -fill both -ipadx 2 -ipady 2 -padx 2 -pady 2
    }
}

proc ::wizard::parse_button_proc {bp page} {
    if {[lindex $bp 0] == "__pageorder__"} {
	return "::wizard::pageorder [lrange $bp 1 end]"
    } else {
	return $bp
    }
}

# --------------------------------------------------------------------------
#
# proc ::wizard::parse_button_list
#
# Description: parse a wizard configuration page list
#
# syntax for entry in list is:
#
# <key> text varname value <proc_to_execute> <rowcol> ?columnspan?
#		?other_widget_options? ?other_blt_options?
#
# where:
#
# <key> --> {radiobutton | checkbutton | button | entry | label | custom}
# <proc_to_execute> --> {tcl statement | __pageorder__ <new suborder of pages>}
# <rowcol> --> "row col"
#
# custom executes proc_to_execute as a procedure that will build a
# portion or all of a page.  text, varname and value are irrelevent in
# this case and can be specified as "".  The user written proc to build the 
# page takes 3 arguments.  The first argument is the page frame
# (to build the form), the second argument is the "row,col" that was specified
# for the custom display and the the third argument is the current page number
#
# value is the value of the variable for that for radiobuttons.  Otherwise
# it is the initial value for the variable itself
#
# pageorder parameters specify a new suborder of pages.  The pages need
# not be from start to end but the code does not check for illegal cycles
# specified for the entire page order.
#
# inputs:
#
#	w	- page frame
#	list	- list of page entries
#	page	- current page number
#
# --------------------------------------------------------------------------

proc ::wizard::parse_button_list {w list page} {
    set n 0
    foreach desc $list {
	set key [lindex $desc 0]
	set text [lindex $desc 1]
	set var [lindex $desc 2]
	set value [lindex $desc 3]
	set button_proc [::wizard::parse_button_proc [lindex $desc 4] $page]
	
	# extract the row/col to put the widget
	
	set rowcol [lindex $desc 5]
	set row [lindex $rowcol 0]
	set col [lindex $rowcol 1]
	
	set len [llength $desc]
	if {$len > 6} {
	    set colspan ""
	    set colspan "-columnspan [lindex $desc 6]"
	} else {
	    set colspan ""
	}
	
	if {$len > 7} {
	    set othopts [lindex $desc 7]
	} else {
	    set othopts ""
	}
	
	if {$len > 8} {
	    set othbltopts [lindex $desc 8]
	} else {
	    set othbltopts ""
	}
	
	if {$var != ""} {
	    # puts "var = $var : value: [uplevel \#0 {set [set var]}]"
	    if {$key == "checkbutton" || $key == "radiobutton"} {
		set variable "-variable \$var"
	    } elseif {$key == "entry"} {
		set variable "-textvariable \$var"
	    } else {
		set variable ""
	    }
	} else {
	    set variable ""
	}
	
	if {$button_proc != ""} {
	    set cmd "-command \$button_proc"
	} else {
	    set cmd ""
	}
	
	set label "-text \$text"
	
	# set the initial value of the variable if not radiobutton
	# or custom options (ie button, checkbutton and entry)
	
	set val ""
	if {$key == "radiobutton"} {
	    set val "-value \$value"
	} elseif {$key != "custom" && $var != "" && $value != "__noinit__"} {
	    catch {uplevel \#0 "set [set var] [set value]"}
	}
	switch $key {
	    custom {
		eval $button_proc $w "{$row $col}" $page
	    }
	    
	    radiobutton -
	    checkbutton -
	    button {
		set com ""
		eval $key $w.$n $label $variable $val $othopts $cmd
	    }
	    
	    entry {
		
		# put the label into a one column dohicky
		
		if {$text != ""} {
		    eval label $w.$n $label
		    eval blt_table $w $w.$n $row,$col $othbltopts
		    incr col
		    incr n
		}
		eval entry $w.$n $variable $othopts
		$w.$n xview moveto 1
	    }
	    
	    label {
		eval label $w.$n $label $othopts
	    }
	}
	if {$key != "custom"} {
	    eval blt_table $w $w.$n $row,$col $colspan $othbltopts
	}
	incr n
    }
}

# --------------------------------------------------------------------------
#
# proc ::wizard::configure_from_file
#
# Description: Configure a wizard from a variable
#
# syntax for a wizard configuration file
#
# set <variable name> <page list>
#
# <page list> --> <page list entry> <page list>
#
# <page list entry> --> pagename <button list> <execute proc>
#			  ?help? ?prolog? ?epilog?
#
# where:
#
# pagename is a string name for page
# <button list> is a tcl list of button entries parsed above
# <execute proc> is the proc to execute in order after user presses "Done"
# help is html tag for help file (not implemented yet)
# prolog is an optional prolog script to be executed on entry to page
# epilog is an optional epilog script to be executed when user leaves page
#
# inputs:
#
#	file	- File to get configuration from
#	basefr	- base window frame name for paging thru wizard
#	cvar	- global variable name that is set in configuration file
#		  default is config_wizard_var
#	page	- current page number
#
# --------------------------------------------------------------------------


proc ::wizard::configure_from_file {file basefr {cvar config_wizard_var}} {
	
    global $cvar
    
    set page 0
    set prevpage 0
    set nextpage 1
    
    uplevel \#0 "source $file"
    foreach cv [set $cvar] {
	set len [llength $cv]
	set pagename [lindex $cv 0]
	set list [lindex $cv 1]
	set ::wizard::execute_proc($page) [lindex $cv 2]
	if {$len > 3} {
	    set ::wizard::help($page) [lindex $cv 3]
	} else {
	    set ::wizard::help($page) ""
	}
	
	if {$len > 4} {
	    set ::wizard::prolog($page) [lindex $cv 4]
	} else {
	    set ::wizard::prolog($page) ""
	}
	
	if {$len > 5} {
	    set ::wizard::epilog($page) [lindex $cv 5]
	} else {
	    set ::wizard::epilog($page) ""
	}
    
	# create the forms for this page
	
	set in_frame ${basefr}${page}
	form_choiceframe $in_frame
	form_frame $in_frame.sub flat 0 "0 0 -cols -"
	set ::wizard::pageframe($page) $in_frame.sub
	
	lappend ::wizard::pagenames $pagename
	lappend ::wizard::pagedescr "$page $prevpage $nextpage"
	::wizard::parse_button_list $in_frame.sub $list $page
		
	# advance prev/next page numbers
		
	set prevpage $page
	incr page
	incr nextpage
    }
    
    # one past last page index (ie, number of pages)
    
    set ::wizard::lastpage [expr $nextpage-1]
}

# --------------------------------------------------------------------------
# proc ::wizard::configure
#
# Description:     - Set up installation wizard
#
# Arguments: w     - window for wizard
#            toplv - 1 if w to be top_window, 0 if it is a frame
#	     title - list of titles.  title of 0 is the overall title for
#                    window.  If second entry in list, it is placed it
#                    tool logo
#            version Version that goes with 2nd entry (if 2nd entry given)
#            estyle  Wizard Execution style.  0 - no message 
#                    1 - Simple message, 2 - Use thermometer to show
#                    user progress of execution
#            uselogo If Logo is to be put up or not
#            stalone If this is a standalone installer this should be 1.
#		     If this is a part of a larger gui, then this should be 0.
#            args    List of a list of wizard window procs. 
#		     Wizard window proc is
#
#			proc wizwinproc {w} {...}
#
#                    where w is the frame to put entry stuff for that page.
#
#                    There can be 3 procs specified in a list entry.  The
#		     first is the "wizard window proc".  The wizard window
#                    proc returns a procedure to execute.  If the empty
#                    string is specified, no procedure for that page
#                    will be executed.  All procedures
#                    are delayed until "Done" pressed on last page.
#                    procedures that are executed should not take any
#                    arguments.  They are executed in page
#                    order.  Ie, proc associated with first page is
#                    executed first, then for 2nd page etc.  Finally
#                    each proc should return a number representing the
#                    integer representing percentage of work completed
#		     for use with execution style 2.
#
#		     The second proc specified in the list is optionally
#		     a prolog to be executed before entry into the page
#		     and the 3rd proc specified is an epilog executed when
#		     the user leaves the page.  If the empty string
#		     is specified, no action is taken.  Prolog and Epilog
#		     scripts are passed the base window name and the page
#		     number

proc ::wizard::configure {w toplv title version estyle uselogo stalone args} {
    global small_screen_hack
    
    # first, load the default configuration file.  Set which
    # form we are on and which strategy is selected for that form.

    switch $estyle {
	0 {}
	1 -
	2 { top_withdraw . }
	default {
	}
    }
    
    if ![winfo exists $w] {
	
	::wizard::init_wizard
    
	set ::wizard::exec_style $estyle
	set ::wizard::curwizard $w
	set ::wizard::standalone $stalone
	
	set ::wizard::allwidgets $w
	if {$stalone} { lappend ::wizard::allwidgets . }
    
	if {$toplv} {
	    top_window $w
	} else {
	    frame $w
	}
	
	set mlb [::wizard::find_file med-logo-bits.xbm]
	set mslb [::wizard::find_file med-smlogo-bits.xbm]
	if {$mlb == "" || $mslb == ""} {
	    set uselogo 0
	} else {
	    set logo_dir [file dirname $mlb]
	}
	
	# common to both with/without logo
	
	frame $w.f
	label $w.f.title -text $title
	
	set widgets ""
	set two 2
	if $small_screen_hack { set two 0 }
	    
	set row 0
	if $uselogo {
	    set tool_logo "$mlb \#0000ff $logo_dir/med-logo-mask.xbm \#547eff"
	    
	    set tool_logo_small "$mslb \#0000ff \
 $logo_dir/med-smlogo-mask.xbm \#547eff"
	    
	    # Add a \n to version text
	    
	    if {[llength $title] > 1} {
		if {![regsub " [lindex $title 1]" $version \
			  "\n[lindex $title 1]" tool_logotext]} {
		    set tool_logotext $version
		}
	    }
	    set tool_logo_relief flat
	    
	    frame $w.f.logo -borderwidth 2 -relief raised
	    label $w.f.logo.1 -borderwidth 2 -relief $tool_logo_relief \
		-anchor c

	    if {$small_screen_hack && [info exists tool_logo_small] &&
		[file exists [lindex $tool_logo_small 0]]} {
		set logo $tool_logo_small
	    } else {
		set logo $tool_logo
	    }
	    
	    switch [llength $logo] {
		1 {
		    set im [image create photo -palette 2/2/2 -file $logo]
		    $w.f.logo.1 configure -image $im
		}
		4 {
		    set im [image create bitmap -file [lindex $logo 0] \
				-foreground [lindex $logo 1] \
				-maskfile [lindex $logo 2] \
				-background [lindex $logo 3]]
		    $w.f.logo.1 configure -image $im
		}
	    }
	    pack $w.f.logo.1 -side top -fill none -padx 2 -pady 2 -anchor c
	    if [info exists tool_logotext] {
		frame $w.f.logo.2
		if ![string match {*\n*} $tool_logotext] {
		    #$w.f.logo.2 configure -height 12
		    #pack propagate $w.f.logo.2 0
		}
		label $w.f.logo.2.t -text $tool_logotext -anchor c
		pack $w.f.logo.2 -side top -fill x -pady 0
		pack $w.f.logo.2.t -side top -fill both
	    }

	    lappend widgets $w.f.logo
	}
	lappend widgets $w.f.title
	
	eval pack $widgets {-side left -fill both -padx $two -pady $two}
	blt_table $w $w.f $row,0 -anchor w -fill both
	incr row
	
	frame $w.empty0 -width 1 -height 10
	blt_table $w $w.empty0 $row,0
	incr row
	    
	# form_label $w.forms.lab "Form:" {0 0}
	form_frame $w.form flat 0 "$row 0"
	incr row
	
	set ::wizard::current_form_type fr0
	if {[lindex $args 0] == "-file"} {
	    set file [::wizard::find_file [lindex $args 1]]
	    if {$file == ""} {
		error "Wizard Configuration File \"[lindex $args 1]\" was \
 not found!"
	    }
	    if {[llength $args] < 3} {
		set configvarname config_wizard_var
	    } else {
		set configvarname [lindex $args 2]
	    }
	    ::wizard::configure_from_file $file $w.form.fr $configvarname
	} else {
	    set ::wizard::lastpage [llength $args]
	
	    set prevpage 0
	    set nextpage 1
	
	    for {set page 0} {$page < $::wizard::lastpage} {incr page} {
		form_choiceframe $w.form.fr${page}
		set in_frame $w.form.fr${page}
		form_frame $in_frame.sub flat 0 "0 0 -cols -"
		set ::wizard::pageframe($page) $in_frame.sub
		
		set disp [lindex $args $page]
		lappend ::wizard::pagenames $disp
		set allprocs [$disp $in_frame.sub]
		
		set ::wizard::execute_proc($page) [lindex $allprocs 0]
		set len [llength $allprocs]
		if {$len > 1} {
		    set ::wizard::prolog($page) [lindex $allprocs 1]
		} else {
		    set ::wizard::prolog($page) ""
		}
		if {$len > 2} {
		    set ::wizard::epilog($page) [lindex $allprocs 2]
		} else {
		    set ::wizard::epilog($page) ""
		}
		
		lappend ::wizard::pagedescr "$page $prevpage $nextpage"
		
		# advance prev/next page numbers
		
		set prevpage $page
		incr nextpage
	    }
	}
	    
	# user proc that executes once entire page setup complete
	
	::wizard::setup_complete
	
	futil_setup_switch $w.form ::wizard::current_form_type "-relwidth 1.0"
	
	frame $w.empty1 -width 1 -height 10
	blt_table $w $w.empty1 $row,0
	incr row
	    
	# Now bottom buttons
	
	frame $w.buts
	blt_table $w $w.buts $row,0 -anchor c
	
	frame $w.buts.variable
	button $w.buts.cancel -text "Cancel" -command "::wizard::finish"
	blt_table $w.buts $w.buts.variable 0,0
	blt_table $w.buts $w.buts.cancel 0,1 \
	    -fill both -ipadx 2 -ipady 2 -padx 2 -pady 2
	
	::wizard::configure_buttons 0
	
	# form_finish +100+100
	
	# $w configure -height [expr {[winfo height .config]+1}]
    }
    return $w
}

proc ::wizard::execute {} {
    
    set w $::wizard::curwizard
    
    # indicator that the wizard is executing window
    
    top_window .wiz
    set wizpage 1
    switch $::wizard::exec_style {
	0 {
	    set wizpage 0
	}
	1 {
	    message .wiz.msg -text "Wizard now executing.  Please stand by..."
	    pack .wiz.msg
	}
	
	2 {
	    set thermowid [::wizard::thermometer .wiz 300 0 100]
	    eval lappend ::wizard::allwidgets $thermowid
	}
    }
    
    top_withdraw $w
    
    if !$wizpage {
	destroy .wiz
    } else {
	lappend ::wizard::allwidgets .wiz
	.wiz config -cursor watch
    }
    
    for {set page 0} {$page < $::wizard::lastpage} {incr page} {
	update idletasks
	set nextproc $::wizard::execute_proc($page)
	if {$nextproc != ""} {
	    if [catch {set ret [eval uplevel \#0 $nextproc]} msg] {
		set ret \
		    [tk_dialog .err "Error" $msg "" 0 Dismiss "Stack Trace"]
		
		if {$ret == 1} {
		    set msg $::errorInfo
		    tk_dialog .err "Stack Trace" $msg "" 0 "Ok"
		}
		
		::wizard::finish
		return
	    } else {
		if {$::wizard::exec_style == 2} {
		    ::wizard::update_thermo .wiz $ret
		}
	    }
	}
    }
    
    tk_dialog .err "Done" "The Wizard has completed successfully" "" 0 \
	"Ok"
   
    ::wizard::finish
}

proc ::wizard::finish {} {
    foreach w $::wizard::allwidgets {
	destroy $w
    }
    unset ::wizard::current_form_type
}

# --------------------------------------------------------------
#
# Wizard Utilities
#

proc ::wizard::setup_complete {} {
    
    # users can write their own.  Executes after all pages setup
}

proc ::wizard::open_file {var text dir get_dir new_ok post_action {ext ""}} {
    upvar $var value
    
    if {$ext == ""} {
	set vis_func ""
    } else {
	set vis_func "mom3d_ext_ok $ext"
    }
    
    set old_file $value
    if {$old_file != ""} {
	set def $old_file
	if !$get_dir {
	    set basen [file tail $old_file]
	    set dirname [file dirname $old_file]
	    if {$basen == $old_file && $dirname == "." && $dir != ""} {
		set def $dir/$old_file
	    }
	}
    } else {
	set def $dir
    }
    
    set selected [file_select $text $def "File Selection" $get_dir \
		      $new_ok "" "" "" $vis_func]
    if {$selected != ""} {
	set value $selected
	if {$post_action != ""} {
	    config_fix_values 0
	    eval $post_action \{$selected\}
	}
    }
}

proc ::wizard::add_to_path {dir} {
    if [file isdirectory $dir] {
	lappend ::wizard::path $dir
    }
}

proc ::wizard::create_path {} {
    global env
    
    # priority: cwd GUIBASE_DIR cwd/guibase $::guibase_dir $::wizard_guibase
    # ICEM_ACN/lib/guibase ICEM_ACN/lib/med ICEM_ACN/lib/med/guibase 
    
    lappend ::wizard::path [pwd]
    
    if [info exists env(GUIBASE_DIR)] {
	::wizard::add_to_path $env(GUIBASE_DIR)
    }

    set guil [pwd]/guibase
    if [file isdirectory $guil] {
	::wizard::add_to_path $guil
    }

    if [info exists ::guibase_dir] {
	::wizard::add_to_path $::guibase_dir
    }

    if [info exists ::wizard_guibase] {
	::wizard::add_to_path $::wizard_guibase
    }

    if [info exists env(ICEM_ACN)] {
	::wizard::add_to_path $env(ICEM_ACN)/lib/guibase
	::wizard::add_to_path $env(ICEM_ACN)/lib/med/guibase
	::wizard::add_to_path $env(ICEM_ACN)/lib/med_gui
	::wizard::add_to_path $env(ICEM_ACN)/lib/med
    }
}

proc ::wizard::exists_equiv_file {file} {
	
    # try both the .tcl and .ptcl file.  If both exist, take
    # later one.  Otherwise if only one exists, use it directly
    # If we have any other file, just look for it
    
    set ext [file extension $file]
    if {$ext == ".tcl" || $ext == ".ptcl"} {
	set basename [file rootname $file]
    
	if {$ext == ".tcl"} {
	    set file2 ${basename}.ptcl
	} else {
	    set file2 ${basename}.tcl
	}
	    
	if {[file exists $file] && [file exists $file2]} {
	    if {[file mtime $file2] > [file mtime $file]} {
		set file $file2
	    }
	    return $file
	} else {
	    if {[file exists $file]} {
		return $file
	    } elseif {[file exists $file2]} {
		return $file2
	    }
	}
    } else {
	if [file exists $file] { return $file }
    }
    return ""
}

proc ::wizard::find_file {file} {
    
    set ret [::wizard::exists_equiv_file $file]
    if {$ret != ""} { return $ret }
    
    # create path if needed
    
    if ![info exists ::wizard::path] {
	::wizard::create_path
    }
    
    # go thru all directories on path and see
    # if we can find the file
    
    set basename [file tail $file]
    foreach dir $::wizard::path {
	set file $dir/$basename
	set ret [::wizard::exists_equiv_file $file]
	if {$ret != ""} { return $ret }
    }
    return ""
}
    
# find page we want to set

proc ::wizard::findpage {pagename defpage} {
    set page [lsearch $::wizard::pagenames $pagename]
    if {$page == -1} { set page $defpage }
    return $page
}

# set the actual page and reconfigure buttons for that page

proc ::wizard::setpage {curpage case} {
    
    # first see if dynamic execution of wizard has changed the meaning
    # what is the next and previous pages
    
    set pagedescr [lindex $::wizard::pagedescr $curpage]
    
    # execute epilog script for leaving page
    
    set epilog $::wizard::epilog($curpage)
    if {$epilog != ""} {eval $epilog $::wizard::pageframe($curpage) $curpage}
    
    if {$case == 0} {
	
	# previous page
	
	set page [lindex $pagedescr 1]
    } elseif {$case == 1} {
	
	# next page
	
	set page [lindex $pagedescr 2]
    }
    
    # execute prolog script to come into the page
    
    set prolog $::wizard::prolog($page)
    if {$prolog != ""} {eval $prolog $::wizard::pageframe($page) $page}
    
    set ::wizard::current_form_type fr$page
    ::wizard::configure_buttons $page
}

# change the order of pages

proc ::wizard::modifypageorder {pagename prevpage nextpage} {
    set curidx  [::wizard::findpage $pagename -1]
    set previdx [::wizard::findpage $prevpage -1]
    set nextidx [::wizard::findpage $nextpage -1]
    
    if {$curidx == -1 || $previdx == -1 || $nextidx == -1} {
	return
    } 
    
    # update current page and new pointers to previous and next pages
    
    set newdescr "$curidx $previdx $nextidx"
    set ::wizard::pagedescr \
	[lreplace $::wizard::pagedescr $curidx $curidx $newdescr]
    
    # Update the previous page descriptor if we are not the first page
    
    if {$previdx != $curidx} {
	set prevdescr [lindex $::wizard::pagedescr $previdx]
	set newdescr "$previdx [lindex $prevdescr 1] $curidx"
	set ::wizard::pagedescr \
	    [lreplace $::wizard::pagedescr $previdx $previdx $newdescr]
    }
    
    # Update the next page descriptor if we are not the last page
    
    if {$nextidx != $curidx} {
	set nextdescr [lindex $::wizard::pagedescr $nextidx]
	set newdescr "$nextidx $curidx [lindex $nextdescr 2]"
	set ::wizard::pagedescr \
	    [lreplace $::wizard::pagedescr $nextidx $nextidx $newdescr]
    }
}

# just modify the descriptor for pagename.  Used when we set the entire
# page order at once

proc ::wizard::modifypage {pagename prevpage nextpage} {
    set curidx  [::wizard::findpage $pagename -1]
    set previdx [::wizard::findpage $prevpage -1]
    set nextidx [::wizard::findpage $nextpage -1]
    
    if {$curidx == -1 || $previdx == -1 || $nextidx == -1} {
	return
    }
    
    set newdescr "$curidx $previdx $nextidx"
    set ::wizard::pagedescr \
	[lreplace $::wizard::pagedescr $curidx $curidx $newdescr]
}

# set a fixed order of pages

proc ::wizard::pageorder {args} {
    set npages [llength $args]
    if {$npages < 1} return
    
    # initial setting for cur/prev page names
    
    set curpagename [lindex $args 0]
    for {set i 0} {$i < $npages} {incr i} {
	
	# leave the previous page of the first page specified alone
	
	if {$i == 0} {
	    set curidx [::wizard::findpage $curpagename -1]
	    if {$curidx > -1} {
		set curdescr [lindex $::wizard::pagedescr $curidx]
		set previdx [lindex $curdescr 1]
		if {$previdx < 0} {
		    set previdx 0
		}
		if {$previdx >= $::wizard::lastpage} {
		    set previdx [expr $::wizard::lastpage-1]
		}
		set prevpagename [lindex $::wizard::pagenames $previdx]
	    } else {
		set prevpagename $curpagename
	    }
	}
	
	# leave the next page of the last page specified alone
	
	if {$i == $npages - 1} {
	    set curidx [::wizard::findpage $curpagename -1]
	    if {$curidx > -1} {
		set curdescr [lindex $::wizard::pagedescr $curidx]
		set nextidx [lindex $curdescr 2]
		if {$nextidx < 0} {
		    set nextidx 0
		}
		if {$nextidx >= $::wizard::lastpage} {
		    set nextidx [expr $::wizard::lastpage-1]
		}
		set nextpagename [lindex $::wizard::pagenames $nextidx]
	    } else {
		set nextpagename $curpagename
	    }
	} else {
	    set nextpagename [lindex $args [expr $i+1]]
	}
	::wizard::modifypage $curpagename $prevpagename $nextpagename
	
	# update prev, cur page names
	
	set prevpagename $curpagename
	set curpagename $nextpagename
    }
}

proc ::wizard::thermometer {w width min max} {
    set ::wizard::curthermow $w
    
    if {$w != "."} {
	set c $w.canv
	set l $w.thermolabel
    } else {
	set c .canv
	set l .thermolabel
    }
    
    if {[winfo exists $c] || [winfo exists $l]} {
	return [list $c $l]
    }
    set c [canvas $c]
    
    set thick 2
    set height 20
    
    set ::wizard::minimum $min
    set ::wizard::maximum $max
    
    set boxs  [expr 1 + $thick]
    set boxf [expr $width+$boxs]
    set boxb [expr $boxs+$height]
    set truebottom [expr $boxb]
    
    set coords "$boxs $boxs $boxf $boxb"
    eval {$c create rect} $coords {-outline black -width $thick}
    
    set thermocoords "$boxs $boxs $boxs $boxb"
    set thitem [eval {$c create rect} $thermocoords {-width 0 -fill blue}]
    
    set linex [expr $boxs+$width/2]
    set linecoords "$linex $truebottom $linex [expr $truebottom+5]"
    eval {$c create line} $linecoords {-width 1}
    
    set texttop [expr $truebottom+5+3]
    set mid [expr ($min+$max)/2.]
    $c create text 1 $texttop -text $min -anchor nw -justify left
    $c create text $linex $texttop -text $mid -anchor n -justify center
    $c create text $boxf $texttop -text $max -anchor ne -justify right
    
    $c configure -height [expr $texttop+20]
    
    label $l -text "Completed: 0%"
    grid $c -sticky news
    grid $l -sticky news
    update idletasks
    
    set ::wizard::boxstart $boxs
    set ::wizard::boxfinish $boxf
    set ::wizard::boxbottom $boxb
    set ::wizard::thermoitem $thitem
    
    return [list $c $l]
}
    
proc ::wizard::update_thermo {w val} {
    if {$w == ""} {
	set w $::wizard::curthermow
    }
    
    if {$w != "."} {
	set c $w.canv
	set l $w.thermolabel
    } else {
	set c .canv
	set l .thermolabel
    }
    
    set val [expr ($val > $::wizard::minimum) ? \
		 (($val < $::wizard::maximum) ? $val : $::wizard::maximum) \
		 : $::wizard::minimum]
    
    set percent [expr ($val-$::wizard::minimum)/double($::wizard::maximum - \
							 $::wizard::minimum)]
						       
    set width [expr $::wizard::boxfinish - $::wizard::boxstart]
    set perwid [expr $width*$percent]
    set thermox [expr $::wizard::boxstart+int($perwid)]
    
    # get rid of old value and create new one
    
    $c delete $::wizard::thermoitem
    set thermocoords "$::wizard::boxstart $::wizard::boxstart $thermox \
 $::wizard::boxbottom"
    set ::wizard::thermoitem \
	[eval {$c create rect} $thermocoords {-width 0 -fill blue}]
    
    $l configure -text "Completed: [expr int(100*$percent)]%"
}
