# tkfbox.tcl --
#
#	Implements the "TK" standard file selection dialog box. This
#	dialog box is used on the Unix platforms whenever the tk_strictMotif
#	flag is not set.
#
#	The "TK" standard file selection dialog box is similar to the
#	file selection dialog box on Win2000(TM). The user can navigate
#	the directories by clicking on the folder icons or by
#	selecting the "Look in:" option menu. The user can select
#	files by clicking on the file icons or by entering a filename
#	in the "Filename:" entry.
#
# RCS: @(#) $Id: tkfbox.tcl,v 1.5 2006/11/21 21:32:25 matt Exp $
#
# Copyright (c) 1994-1998 Sun Microsystems, Inc.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# File taken from Tk8.4.6 and adapted to tk8.3.3 with ICEM's new options -- Matt Middleton 10/13/2004
# Then updated for Tk8.4.12 -- 1/6/2006
# This requires the files, tkfprops.tcl and ResizeButs.tcl
# Add these lines to the file "tclIndex":
# set auto_index(ResizeButs) [list source [file join $dir ResizeButs.tcl]]
# set auto_index(tk_fileProperties) [list source [file join $dir tkfprops.tcl]]
#----------------------------------------------------------------------
#
#		      I C O N   L I S T
#
# This is a pseudo-widget that implements the icon list inside the 
# ::tk::dialog::file::tkFDialog dialog box.
#
#----------------------------------------------------------------------

# ::tk::IconList --
#
#	Creates an IconList widget.
#
proc ::tk::IconList {w args} {
    IconList_Config $w $args
    IconList_Create $w
}

# returns index numbers
proc ::tk::IconList_Index {w i {arg ""}} {
    upvar #0 ::tk::$w data
    upvar #0 ::tk::$w:fileList fileList

    if {![info exists data(list)]} {set data(list) {}}
    switch -regexp -- $i {
	"^-?[0-9]+$" {
	    if { $i < 0 } {
		set i 0
	    }
	    if { $i >= [llength $data(list)] } {
		set i [expr {[llength $data(list)] - 1}]
	    }
	    return $i
	}
	"^active$" {
	    if {$arg != ""} {
		set i [tk::IconList_Index $w $arg]
		set data(index,active) [lindex $data(list) $i]
	    } else {
		return [lsearch $data(list) $data(index,active)]
	    }
	}
	"^anchor$" {
	    return [lsearch $data(list) $data(index,anchor)]
	}
	"^end$" {
	    return [expr {[llength $data(list)] - 1}]
	}
	"@-?[0-9]+,-?[0-9]+" {
	    scan $i "@%d,%d" x y
	    set item [$data(nameCanvas) find closest $x $y]
	    set item [lindex [$data(nameCanvas) itemcget $item -tags] 1]
	    if {[scan $item "item%d" item] != 1} return
	    return [lsearch $data(list) $item]
	}
	"-?[0-9]+,-?[0-9]+ to -?[0-9]+,-?[0-9]+" {
	    # This part returns the item numbers instead of the index numbers
	    scan $i "%d,%d to %d,%d" x1 y1 x2 y2
	    set items [$data(nameCanvas) find overlapping $x1 $y1 $x2 $y2]
	    set ret ""
	    foreach item $items {
		set tags [$data(nameCanvas) itemcget $item -tags]
		set type [lindex $tags 0]
		if {$type == "icon" || $type == "text"} {
		    if {[scan [lindex $tags 1] "item%d" item] == 1} {lappend ret $item}
		}
	    }
	    return [lsort -integer -unique $ret]
	}
	"^-text$" {
	    set i 0
	    foreach item $data(list) {
		if [string equal $arg [lindex $fileList($item) 0]] {return $i}
		incr i
	    }
	    return -1
	}
    }
}

# Takes in index numbers
proc ::tk::IconList_Selection {w op args} {
    upvar ::tk::$w data

    if ![info exists data(list)] return
    set arglen [llength $args]
    switch -exact -- $op {
	"anchor" {
	    if { $arglen == 1 } {
		set i [tk::IconList_Index $w [lindex $args 0]]
		set data(index,anchor) [lindex $data(list) $i]
	    } else {
		return [lsearch $data(list) $data(index,anchor)]
	    }
	}
	"clear" {
	    if { $arglen == 2 } {
		foreach {first last} $args {
		    break
		}
	    } elseif { $arglen == 1 } {
		set first [set last [lindex $args 0]]
	    } else {
		error "wrong # args: should be [lindex [info level 0] 0] path\
			clear first ?last?"
	    }
	    set first [IconList_Index $w $first]
	    set last [IconList_Index $w $last]
	    if { $first > $last } {
		set tmp $first
		set first $last
		set last $tmp
	    }
	    set clear_items [lrange $data(list) $first $last]
	    set new_selection {}
	    foreach item $data(selection) {
		if {[lsearch $clear_items $item] < 0} {
		    lappend new_selection $item
		}
	    }
	    set data(selection) $new_selection
	    event generate $w <<ListboxSelect>>
	    if {$arglen == 1} {IconList_DrawSelection $w remove $first} \
	    else {IconList_DrawSelection $w}
	    if ![llength $data(selection)] {set data(index,anchor) ""}
	}
	"includes" {
	    set item [lindex $data(list) [lindex $args 0]]
	    set index [lsearch -exact $data(selection) $item]
	    return [expr {$index != -1}]
	}
	"set" {
	    if { $arglen == 2 } {
		foreach {first last} $args break
	    } elseif { $arglen == 1 } {
		set last [set first [lindex $args 0]]
	    } else {
		error "wrong # args: should be [lindex [info level 0] 0] path\
			set first ?last?"
	    }

	    set first [IconList_Index $w $first]
	    set last [IconList_Index $w $last]
	    if { $first > $last } {
		set tmp $first
		set first $last
		set last $tmp
	    }
	    set data(selection) [concat $data(selection) [lrange $data(list) $first $last]]
	    set data(selection) [lsort -integer -unique $data(selection)]
	    event generate $w <<ListboxSelect>>
	    if {$arglen == 1} {IconList_DrawSelection $w add $first} \
	    else {IconList_DrawSelection $w}
	}
    }
}

# returns item numbers
proc ::tk::IconList_Curselection {w} {
    upvar ::tk::$w data
    return $data(selection)
}

# Can take in one index number
proc ::tk::IconList_DrawSelection {w args} {
    upvar ::tk::$w data
    upvar ::tk::$w:itemList itemList

    if {$args != ""} {
	set op [lindex $args 0]
	set item [lindex $data(list) [lindex $args 1]]
    } else {
	set op ""
    }
    if {$op == "remove"} {
	$data(nameCanvas) delete "selection && item$item"
	IconList_UpdateIcons $w
	return
    } elseif {$op == "add"} {
	set selection $item
    } else {
	$data(nameCanvas) delete selection
	set selection $data(selection)
    }
    foreach item $selection {
	set tTag [lindex $itemList($item) 1]
	$data(nameCanvas) create rect [$data(nameCanvas) bbox $tTag] -fill #a0a0ff -outline #a0a0ff -tags "selection item$item"
    }
    $data(nameCanvas) lower selection
    IconList_UpdateIcons $w
}

# Takes in item number
proc ::tk::IconList_Get {w item} {
    upvar ::tk::$w:fileList fileList
    return [lindex $fileList($item) 0]
}

# ::tk::IconList_Config --
#
#	Configure the widget variables of IconList, according to the command
#	line arguments.
#
proc ::tk::IconList_Config {w argList} {

    # 1: the configuration specs
    #
    set specs {
	{-command "" "" ""}
	{-multiple "" "" "0"}
	{-fg "" "" ""}
    }

    # 2: parse the arguments
    #
    tclParseConfigSpec ::tk::$w $specs "" $argList
}

# ::tk::IconList_Create --
#
#	Creates an IconList widget by assembling a canvas widget and a
#	scrollbar widget. Sets all the bindings necessary for the IconList's
#	operations.
#
proc ::tk::IconList_Create {w} {
    upvar ::tk::$w data

    frame $w -bd 2 -relief sunken -highlightthickness 1 -takefocus 0
    grid propagate $w 0
    set data(hsbar)   [scrollbar $w.hsbar -orient horizontal -highlightthickness 0 -takefocus 0]
    set data(vsbar)   [scrollbar $w.vsbar -orient vertical -highlightthickness 0 -takefocus 0]
    set data(bottomCanvas) [canvas $w.bottomcanvas -bd 0 -highlightthickness 0 -takefocus 0 \
		-width 430 -height 170]
    set data(bottomCanvasFrame) [frame $data(bottomCanvas).frame -bd 0 -highlightthickness 0 -takefocus 0]
    set data(canvasNames) [list name size type modified]
    set col 0
    foreach name $data(canvasNames) {
	set data(${name}Canvas) [canvas $data(bottomCanvasFrame).$name -bd 0 -width 0 \
		-takefocus 0 -selectborderwidth 0 -highlightthickness 0 -background white]
	grid $data(${name}Canvas) -sticky nswe -row 0 -column $col
	incr col
    }
    $data(nameCanvas) configure -takefocus 1
    grid columnconfigure $data(bottomCanvasFrame) 0 -weight 1
    grid rowconfigure $data(bottomCanvasFrame) 0 -weight 1
    $data(bottomCanvas) create window 0 0 -window $data(bottomCanvasFrame) -anchor nw

    set data(viewMethod) List
    set data(detailButtons) [ResizeButs $w.dbuts -resizecommand	[list ::tk::IconList_ResizeColumns $w] \
	-side left -orient horizontal -ordercommand	[list ::tk::IconList_ReArrange $w] -orderbutton [list 0 increasing] \
	-pressrelief ridge -showcommand [list ::tk::IconList_ShowColumns $w]]
    foreach butname $data(canvasNames) {
	$data(detailButtons) add -text [string toupper $butname 0 0]
    }
    $data(detailButtons) itemconfigure 0 -lockshow 1

    grid x $data(vsbar) -sticky nse
    grid $data(bottomCanvas) ^ -sticky nswe
    grid $data(hsbar) -sticky wes
    grid rowconfigure $w 1 -weight 1
    grid columnconfigure $w 0 -weight 1

    $data(hsbar) configure -command [list ::tk::IconList_Hscroll $w]
    $data(detailButtons) configure -scrollcommand [list $data(hsbar) set]
    $data(bottomCanvas) configure -xscrollcommand [list $data(hsbar) set]
    $data(vsbar) configure -command [list $data(bottomCanvas) yview]
    $data(bottomCanvas) configure -yscrollcommand [list $data(vsbar) set]

    # Initializes the max icon/text width and height and other variables
    #
    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(noxScroll) 1
    set data(noyScroll) 1
    set data(selection) {}
    set data(index,anchor) ""
    if {$data(-fg) == ""} {
	set data(-fg) [option get $data(bottomCanvas) foreground Foreground]
    }
    if {$data(-fg) == ""} {set data(-fg) black}

    # Creates the event bindings.
    #
    bind $data(bottomCanvas) <Configure>	[list tk::IconList_Arrange $w -only_resize 1]

    bind $data(nameCanvas) <1>		[list tk::IconList_Btn1 $w %x %y]
    bind $data(nameCanvas) <B1-Motion>	[list tk::IconList_Motion1 $w %x %y]
    bind $data(nameCanvas) <B1-Leave>	[list tk::IconList_Leave1 $w %x %y]
    bind $data(nameCanvas) <Control-1>	[list tk::IconList_CtrlBtn1 $w %x %y]
    bind $data(nameCanvas) <Shift-1>	[list tk::IconList_ShiftBtn1 $w %x %y]
    bind $data(nameCanvas) <B1-Enter>	[list tk::CancelRepeat]
    bind $data(nameCanvas) <ButtonRelease-1> [list tk::IconList_Release1 $w]
    bind $data(nameCanvas) <Double-ButtonRelease-1> [list tk::IconList_Double1 $w %x %y]
    foreach name $data(canvasNames) {
	bind $data(${name}Canvas) <ButtonRelease-3> [list tk::dialog::file::PopUpMenu $w %W %x %y]
    }

    bind $data(nameCanvas) <Up>		[list tk::IconList_UpDown $w -1]
    bind $data(nameCanvas) <Down>		[list tk::IconList_UpDown $w  1]
    bind $data(nameCanvas) <Left>		[list tk::IconList_LeftRight $w -1]
    bind $data(nameCanvas) <Right>		[list tk::IconList_LeftRight $w  1]
    bind $data(nameCanvas) <Return>		[list tk::IconList_ReturnKey $w]
    bind $data(nameCanvas) <KeyPress>	[list tk::IconList_KeyPress $w %A]
    bind $data(nameCanvas) <Control-KeyPress> ";"
    bind $data(nameCanvas) <Alt-KeyPress>	";"

    foreach name $data(canvasNames) {
	bind $data(${name}Canvas) <FocusIn>	[list tk::IconList_FocusIn $w %W]
    }
    bind $data(nameCanvas) <FocusOut>	[list tk::IconList_FocusOut $w]

    set data(editwin) [entry $data(nameCanvas).editwin -bd 0 -highlightthickness 1 -width 0]
    bindtags $data(editwin) [list $data(editwin) Entry]
    bind $data(editwin) <Key-Escape> "set ::tk::${w}(editDone) 0"
    bind $data(editwin) <Key-Return> "set ::tk::${w}(editDone) 1"
    bind EditDone <Button-1> [list tk::IconList_EditTextDone $w %W]

    return $w
}

# ::tk::IconList_AutoScan --
#
# This procedure is invoked when the mouse leaves an entry window
# with button 1 down.  It scrolls the window up, down, left, or
# right, depending on where the mouse left the window, and reschedules
# itself as an "after" command so that the window continues to scroll until
# the mouse moves back into the window or the mouse button is released.
#
# Arguments:
# w -		The IconList window.
#
proc ::tk::IconList_AutoScan {w x y} {
    upvar ::tk::$w data
    variable ::tk::Priv
    global tkPriv

    if {![winfo exists $w]} return

    if {$data(viewMethod) == "List"} {
	if $data(noxScroll) return
	set width [winfo width $data(bottomCanvas)]
	if {[set inc [$data(bottomCanvas) cget -xscrollincrement]] == 0} {
	    set inc [expr {$width / 10}]
	}
	if {$x >= $width} {
	    if {[lindex [$data(bottomCanvas) xview] 1] != 1} {incr Priv(x) $inc} else return
	    $data(bottomCanvas) xview scroll 1 units
	} elseif {$x < 0} {
	    if {[lindex [$data(bottomCanvas) xview] 0] != 0} {incr Priv(x) -$inc} else return
	    $data(bottomCanvas) xview scroll -1 units
	} else return
    } elseif {$data(viewMethod) == "Details"} {
	if $data(noyScroll) return
	set height [winfo height $data(bottomCanvas)]
	if {[set inc [$data(bottomCanvas) cget -yscrollincrement]] == 0} {
	    set inc [expr {$height / 10}]
	}
	if {$y >= $height} {
	    if {[lindex [$data(bottomCanvas) yview] 1] != 1} {incr Priv(y) $inc} else return
	    $data(bottomCanvas) yview scroll 1 units
	} elseif {$y < 0} {
	    if {[lindex [$data(bottomCanvas) yview] 0] != 0} {incr Priv(y) -$inc} else return
	    $data(bottomCanvas) yview scroll -1 units
	} else return
    } else return

    IconList_Motion1 $w $Priv(x) $Priv(y)
    set tkPriv(afterId) [after 50 [list tk::IconList_AutoScan $w $x $y]]
}

# Deletes all the items inside the canvas subwidget and reset the IconList's
# state.
#
proc ::tk::IconList_DeleteAll {w} {
    upvar ::tk::$w data
    upvar ::tk::$w:itemList itemList
    upvar ::tk::$w:fileList fileList

    foreach name $data(canvasNames) {
	$data(${name}Canvas) delete all
    }

    catch {unset data(selected)}
    catch {unset data(rect)}
    catch {unset data(list)}
    catch {unset data(fList)}
    catch {unset data(dList)}
    catch {unset itemList}
    catch {unset fileList}
    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(noxScroll) 1
    set data(noyScroll) 1
    set data(selection) {}
    set data(index,anchor) ""
    set data(index,active) ""
    $data(hsbar) set 0.0 1.0
    $data(vsbar) set 0.0 1.0
    $data(detailButtons) view moveto 0
    $data(bottomCanvas) xview moveto 0
    $data(bottomCanvas) yview moveto 0
}

# Adds an icon into the IconList with the designated image and text
#
proc ::tk::IconList_Add {w image items {addtag ""} {display_when ""}} {
    upvar ::tk::dialog::file::[lindex [split $w .] end-1] dialogData
    upvar ::tk::$w data
    upvar ::tk::$w:itemList itemList
    upvar ::tk::$w:fileList fileList

    foreach name $items {
	set iTag [$data(nameCanvas) create image 0 0 -image $image -anchor nw \
		-tags [list icon item$data(numItems) $addtag]]
	set tTag [$data(nameCanvas) create text  0 0 -text  $name  -anchor nw \
		-font $data(font) -fill $data(-fg) \
		-tags [list text item$data(numItems) $addtag]]
	set rTag [$data(nameCanvas) create rect  0 0 0 0 -fill "" -outline "" \
		-tags [list rect item$data(numItems)]]
	
	foreach {x1 y1 x2 y2} [$data(nameCanvas) bbox $iTag] {
	    break
	}
	set iW [expr {$x2 - $x1}]
	set iH [expr {$y2 - $y1}]
	if {$data(maxIW) < $iW} {
	    set data(maxIW) $iW
	}
	if {$data(maxIH) < $iH} {
	    set data(maxIH) $iH
	}
    
	foreach {x1 y1 x2 y2} [$data(nameCanvas) bbox $tTag] {
	    break
	}
	set tW [expr {$x2 - $x1}]
	set tH [expr {$y2 - $y1}]
	if {$data(maxTW) < $tW} {
	    set data(maxTW) $tW
	}
	if {$data(maxTH) < $tH} {
	    set data(maxTH) $tH
	}

	set full_path [::tk::dialog::file::JoinFile $dialogData(selectPath) $name]
	set type [file type $full_path]
	if [catch {file mtime $full_path} mtime] {
	    set mtime 0
	    if {$type == "link"} {set type "link (broken)"}
	}
	if {$addtag == "dir"} {
	    set size ""
	    lappend data(dList) $data(numItems)
	} elseif {$addtag == "dir_leaf"} {
	    if {$type != "link (broken)"} {set type project}
	    set size 0
	    lappend data(fList) $data(numItems)
	} else {
	    if [catch {file size $full_path} size] {
		set size 0
		if {$type == "link"} {set type "link (broken)"}
	    }
	    if {$type == "file"} {set type [string trimleft [file extension $name] .]}
	    lappend data(fList) $data(numItems)
	}
	set fileList($data(numItems)) [list $name $size $type $mtime]
	set itemList($data(numItems)) [list $iTag $tTag $rTag $iH $tH]

	if {$data(viewMethod) == "Details"} {
	    if {$type != "link (broken)"} {
		set modified [clock format $mtime -format "%m/%d/%Y %I:%M:%S %p"]
		set size [::tk::dialog::file::FormatSize $size]
	    } else {set modified ""; set size ""}
	    foreach win [lrange $data(canvasNames) 1 end] {
		set text [set $win]
		if {$text == ""} continue
		$data(${win}Canvas) create text  0 0 -text $text -anchor nw \
			-font $data(font) -fill $data(-fg) -tags item$data(numItems)
	    }
	}

	if {$display_when == "now"} {
	    ::tk::IconList_Arrange $w -just_one $data(numItems)
	    ::tk::IconList_See $w $data(numItems)
	}
	incr data(numItems)
	if {[llength $items] == 1} {return [expr {$data(numItems) - 1}]}
    }
}

# Places the icons in a column-major arrangement.
#
proc ::tk::IconList_Arrange {w args} {
    upvar ::tk::$w data
    upvar ::tk::$w:itemList itemList

    set only_resize 0
    set just_one ""
    foreach {var val} $args {set [string trimleft $var -] $val}

    set W [winfo width $data(bottomCanvas)]
    set H [winfo height $data(bottomCanvas)]

    if {$data(viewMethod) == "List" || !$only_resize} {
	set dx [expr {$data(maxIW) + $data(maxTW) + 8}]
	set dy [expr {$data(maxTH) > $data(maxIH) ? $data(maxTH) : $data(maxIH)}]
	incr dy 2
	set shift [expr {$data(maxIW) + 4}]

	set usedColumn 0
	if {![info exists data(dList)]} {set data(dList) {}}
	if {![info exists data(fList)]} {set data(fList) {}}
	if {![info exists data(list)]} {set data(list) {}}
	if {$just_one != ""} {
	    set data_list $just_one
	    lappend data(list) $just_one
	    if {[llength $data(list)] == 1} {
		set data(x) 4
		set data(y) 2
	    }
	} else {
	    if {$data(viewMethod) == "List"} {set data(listOrder) increasing}
	    ::tk::IconList_ListSort $w
	    set data(x) 4
	    set data(y) 2
	    set data_list $data(list)
	}

	foreach item $data_list {
	    set usedColumn 1
	    foreach {iTag tTag rTag iH tH} $itemList($item) break

	    set i_dy [expr {($dy - $iH)/2}]
	    set t_dy [expr {($dy - $tH)/2}]

	    $data(nameCanvas) coords $iTag $data(x)                    [expr {$data(y) + $i_dy}]
	    $data(nameCanvas) coords $tTag [expr {$data(x) + $shift}]  [expr {$data(y) + $t_dy}]
	    $data(nameCanvas) coords $rTag $data(x) $data(y) [expr {$data(x)+$dx}] [expr {$data(y)+$dy}]
	    if {$data(viewMethod) == "Details"} {
		foreach win [lrange $data(canvasNames) 1 end] {
		    if {$win == "size"} {set x [expr {$data(x) + 10}]} else {set x $data(x)}
	    	    $data(${win}Canvas) coords item$item $x [expr {$data(y) + $t_dy}]
		}
	    }

	    incr data(y) $dy
	    if {$data(viewMethod) == "List" && ($data(y) + $dy) > $H} {
		set data(y) 2
		incr data(x) $dx
		set usedColumn 0
	    }
	}
	if {$data(selection) != ""} {::tk::IconList_DrawSelection $w}
    }

    if {$data(viewMethod) == "List"} {
	set sW [expr {$usedColumn ? $data(x) + $dx : $data(x)}]
	set data(noyScroll) 1
	$data(bottomCanvas) yview moveto 0
	$data(vsbar) configure -command ""
	$data(bottomCanvas) itemconfigure all -height $H
	$data(bottomCanvas) configure -scrollregion [list 0 0 $sW $H]
	set data(itemsPerColumn) [expr {$H/$dy}]
	if {$data(itemsPerColumn) < 1} {set data(itemsPerColumn) 1}
	if {$sW < $W} {
	    $data(bottomCanvas) itemconfigure all -width $W
	    $data(hsbar) configure -command ""
	    $data(bottomCanvas) xview moveto 0
	    set data(noxScroll) 1
	} else {
	    $data(bottomCanvas) itemconfigure all -width $sW
	    $data(hsbar) configure -command [list ::tk::IconList_Hscroll $w]
	    set data(noxScroll) 0
	}
    } elseif {$data(viewMethod) == "Details"} {
	set width 0
	foreach win $data(canvasNames) {
	    incr width [$data(${win}Canvas) cget -width]
	}
	$data(bottomCanvas) configure -scrollregion [list 0 0 $width $data(y)]
	if {$width <= $W} {
	    $data(bottomCanvas) itemconfigure all -width $W
	    $data(hsbar) configure -command ""
	    $data(bottomCanvas) xview moveto 0
	    set data(noxScroll) 1
	} else {
	    $data(bottomCanvas) itemconfigure all -width $width
	    $data(hsbar) configure -command [list ::tk::IconList_Hscroll $w]
	    set data(noxScroll) 0
	}
	if {$data(y) < $H} {
	    $data(bottomCanvas) itemconfigure all -height $H
	    $data(vsbar) configure -command ""
	    $data(bottomCanvas) yview moveto 0
	    set data(noyScroll) 1
	} else {
	    $data(bottomCanvas) itemconfigure all -height $data(y)
	    $data(vsbar) configure -command [list $data(bottomCanvas) yview]
	    set data(noyScroll) 0
	}
    }
}

# Gets called when the user invokes the IconList (usually by double-clicking
# or pressing the Return key).
#
proc ::tk::IconList_Invoke {w} {
    upvar ::tk::$w data

    if {$data(-command) != "" && [llength $data(selection)]} {
	uplevel #0 $data(-command)
    }
}

# ::tk::IconList_See --
#
#	If the item is not (completely) visible, scroll the canvas so that
#	it becomes visible.
proc ::tk::IconList_See {w i} {
    upvar ::tk::$w data

    if {$data(noxScroll) && $data(viewMethod) == "List"} return
    if {$data(noyScroll) && $data(noxScroll)} return
    set sRegion [$data(bottomCanvas) cget -scrollregion]
    if {[string equal $sRegion {}]} return

    if { $i < 0 || $i >= [llength $data(list)] } return
    set item [lindex $data(list) $i]
    set bbox [$data(nameCanvas) bbox "item$item && rect"]

    foreach {x1 y1 x2 y2} $bbox break
#    incr x1 -3
#    incr x2 -2
#    incr y1 -2
#    incr y2 -2

    set cW [winfo width $data(bottomCanvas)]
    set cH [winfo height $data(bottomCanvas)]

    set scrollW [expr {[lindex $sRegion 2]-[lindex $sRegion 0]+1}]
    set scrollH [expr {[lindex $sRegion 3]-[lindex $sRegion 1]+1}]
    set dispX [expr {int([lindex [$data(bottomCanvas) xview] 0]*$scrollW)}]
    set dispY [expr {int([lindex [$data(bottomCanvas) yview] 0]*$scrollH)}]
    set oldDispX $dispX
    set oldDispY $dispY

    # check if out of the right edge
    if {($x2 - $dispX) >= $cW} {
	set dispX [expr {$x2 - $cW}]
    }
    # check if out of the bottom edge
    if {($y2 - $dispY) >= $cH} {
	set dispY [expr {$y2 - $cH}]
    }
    # check if out of the left edge
    if {($x1 - $dispX) < 0} {
	set dispX $x1
    }
    # check if out of the top edge
    if {($y1 - $dispY) < 0} {
	set dispY $y1
    }

    if {$oldDispX != $dispX} {
	set fraction [expr {double($dispX)/double($scrollW)}]
	::tk::IconList_Hscroll $w moveto $fraction
#	$data(bottomCanvas) xview moveto $fraction
    }
    if {$data(viewMethod) == "Details" && $oldDispY != $dispY} {
	set fraction [expr {double($dispY)/double($scrollH)}]
	$data(bottomCanvas) yview moveto $fraction
    }
}

proc ::tk::IconList_Btn1 {w x y} {
    upvar ::tk::$w data

    focus $data(nameCanvas)
    set x [expr {int([$data(nameCanvas) canvasx $x])}]
    set y [expr {int([$data(nameCanvas) canvasy $y])}]
    set items [$data(nameCanvas) find overlapping $x $y $x $y]
    IconList_Selection $w clear 0 end
    if {[llength $items] > 1} {
	set i [IconList_Index $w @${x},${y}]
	if {$i<0} return
	IconList_Selection $w set $i
	IconList_Selection $w anchor $i
	catch {unset data(selboxstart)}
    } elseif $data(-multiple) {
	set data(selboxstart) "$x $y"
	$data(nameCanvas) create rectangle $x $y $x $y -fill "" -outline black -tags selbox -dash {1 1}
    }
}

proc ::tk::IconList_CtrlBtn1 {w x y} {
    upvar ::tk::$w data
    
    if { $data(-multiple) } {
	focus $data(nameCanvas)
	set x [expr {int([$data(nameCanvas) canvasx $x])}]
	set y [expr {int([$data(nameCanvas) canvasy $y])}]
	set i [IconList_Index $w @${x},${y}]
	if {$i<0} return
	if { [IconList_Selection $w includes $i] } {
	    IconList_Selection $w clear $i
	} else {
	    IconList_Selection $w set $i
	    IconList_Selection $w anchor $i
	    catch {unset data(selboxstart)}
	}
    }
}

proc ::tk::IconList_ShiftBtn1 {w x y} {
    upvar ::tk::$w data
    
    if { $data(-multiple) } {
	focus $data(nameCanvas)
	set x [expr {int([$data(nameCanvas) canvasx $x])}]
	set y [expr {int([$data(nameCanvas) canvasy $y])}]
	set i [IconList_Index $w @${x},${y}]
	if {$i<0} return
	set a [IconList_Index $w anchor]
	if {[info exists data(selboxstart)] && $a<0 && [set cur [IconList_Curselection $w]] != ""} {
	    # set the anchor to the opposite side of the selection
	    set curl [llength $cur]
	    foreach {minx miny} [$data(nameCanvas) coords "item[lindex $cur 0] && icon"] break
	    set maxx $minx; set maxy $miny
	    for {set j 1} {$j < $curl} {incr j} {
		foreach {xi yi} [$data(nameCanvas) coords "item[lindex $cur $j] && icon"] break
		if {$xi < $minx} {set minx $xi; set miny $yi} \
		elseif {$xi > $maxx} {set maxx $xi; set maxy $yi} \
		elseif {$xi == $minx && $yi < $miny} {set minx $xi; set miny $yi} \
		elseif {$xi == $maxx && $yi > $maxy} {set maxx $xi; set maxy $yi}
	    }
	    set minx [expr {int($minx)}]; set miny [expr {int($miny)}]
	    set maxx [expr {int($maxx)}]; set maxy [expr {int($maxy)}]
	    set mini [IconList_Index $w @${minx},${miny}]
	    set maxi [IconList_Index $w @${maxx},${maxy}]
	    if {$i <= $mini} {set a $maxi} \
	    elseif {$i >= $maxi} {set a $mini} \
	    else {set a $mini}
	    IconList_Selection $w anchor $a
	    unset data(selboxstart)
	}
	IconList_Selection $w clear 0 end
	if {$a<0} {
	    set a $i
	    catch {unset data(selboxstart)}
	}
	IconList_Selection $w set $a $i
	IconList_Selection $w anchor $a
    }
}

# Gets called on button-1 motions
#
proc ::tk::IconList_Motion1 {w x y} {
    upvar ::tk::$w data

    set x [expr {int([$data(nameCanvas) canvasx $x])}]
    set y [expr {int([$data(nameCanvas) canvasy $y])}]
    if [info exists data(selboxstart)] {
	foreach {x1 y1} $data(selboxstart) break
	$data(nameCanvas) coords selbox $x1 $y1 $x $y
	set is [::tk::IconList_Index $w "$x1,$y1 to $x,$y"]
	set cur [::tk::IconList_Curselection $w]
	if {$is == $cur} return
	set data(selection) $is
	event generate $w <<ListboxSelect>>
	IconList_DrawSelection $w
    } else {
	set i [IconList_Index $w @${x},${y}]
	if {$i<0} return
	IconList_Selection $w clear 0 end
	IconList_Selection $w set $i
	IconList_Selection $w anchor $i
    }
}

proc ::tk::IconList_Double1 {w x y} {
    upvar ::tk::$w data

    if {[llength $data(selection)]} {
	IconList_Invoke $w
    }
}

proc ::tk::IconList_ReturnKey {w} {
    IconList_Invoke $w
}

proc ::tk::IconList_Leave1 {w x y} {
    upvar ::tk::$w data
    variable ::tk::Priv

    set Priv(x) $x
    set Priv(y) $y
    set sRegion [$data(bottomCanvas) cget -scrollregion]
    if {[string equal $sRegion {}]} return
    set scrollW [expr {[lindex $sRegion 2]-[lindex $sRegion 0]+1}]
    set scrollH [expr {[lindex $sRegion 3]-[lindex $sRegion 1]+1}]
    set dispX [expr {int([lindex [$data(bottomCanvas) xview] 0]*$scrollW)}]
    set dispY [expr {int([lindex [$data(bottomCanvas) yview] 0]*$scrollH)}]
    set x [expr {$x - $dispX}]
    set y [expr {$y - $dispY}]

    IconList_AutoScan $w $x $y
}

proc ::tk::IconList_FocusIn {w W} {
    upvar ::tk::$w data
    set tw [winfo parent $w]
    upvar ::tk::dialog::file::[winfo name $tw] dialogData

    if ![::tk::dialog::file::IsDirectoryToUs $dialogData(selectPath)] {
	::tk::dialog::file::SetPathSilently $tw [lindex $dialogData(selectPathHistory) end]
    }

    if {$W == $data(nameCanvas) && [info exists data(list)] && [llength $data(selection)]} {
	IconList_DrawSelection $w
    }
}

proc ::tk::IconList_FocusOut {w} {
    upvar ::tk::$w data

    set cf [focus]
    if {([info exists data(selectionPopUp)] && $cf == $data(selectionPopUp)) || \
	([info exists data(noSelectionPopUp)] && $cf == $data(noSelectionPopUp))} return
    IconList_Selection $w clear 0 end
}

# ::tk::IconList_UpDown --
#
# Moves the active element up or down by one element
#
# Arguments:
# w -		The IconList widget.
# amount -	+1 to move down one item, -1 to move back one item.
#
proc ::tk::IconList_UpDown {w amount} {
    upvar ::tk::$w data

    if {![info exists data(list)]} return

    set curr [tk::IconList_Curselection $w]
    if { [llength $curr] == 0 } {
	set i 0
    } else {
	set i [tk::IconList_Index $w anchor]
	if {$i<0} return
	incr i $amount
    }
    IconList_Selection $w clear 0 end
    IconList_Selection $w set $i
    IconList_Selection $w anchor $i
    IconList_See $w $i
}

# ::tk::IconList_LeftRight --
#
# Moves the active element left or right by one column
#
# Arguments:
# w -		The IconList widget.
# amount -	+1 to move right one column, -1 to move left one column.
#
proc ::tk::IconList_LeftRight {w amount} {
    upvar ::tk::$w data

    if {![info exists data(list)] || $data(viewMethod) != "List"} return

    set curr [IconList_Curselection $w]
    if { [llength $curr] == 0 } {
	set i 0
    } else {
	set i [IconList_Index $w anchor]
	if {$i<0} return
	incr i [expr {$amount*$data(itemsPerColumn)}]
    }
    IconList_Selection $w clear 0 end
    IconList_Selection $w set $i
    IconList_Selection $w anchor $i
    IconList_See $w $i
}

#----------------------------------------------------------------------
#		Accelerator key bindings
#----------------------------------------------------------------------

# ::tk::IconList_KeyPress --
#
#	Gets called when user enters an arbitrary key in the listbox.
#
proc ::tk::IconList_KeyPress {w key} {
    variable ::tk::Priv

    append Priv(ILAccel,$w) $key
    IconList_Goto $w $Priv(ILAccel,$w)
    catch {
	after cancel $Priv(ILAccel,$w,afterId)
    }
    set Priv(ILAccel,$w,afterId) [after 500 [list tk::IconList_Reset $w]]
}

proc ::tk::IconList_Goto {w text} {
    upvar ::tk::$w data
    upvar ::tk::$w:fileList fileList
    
    if {![info exists data(list)]} return
    if {[string equal {} $text]} return

    if {$data(curItem) == ""} {
	set start  0
    } else {
	set start $data(curItem)
    }

    set theIndex -1
    set len [string length $text]
    set i $start

    # Search forward until we find a filename whose prefix is an exact match
    # with $text
    while {1} {
	set item [lindex $data(list) $i]
	set itemName [lindex $fileList($item) 0]
	if {[string equal -nocase -length $len $text $itemName]} {
	    set theIndex $i
	    break
	}
	incr i
	if {$i == $data(numItems)} {
	    set i 0
	}
	if {$i == $start} {
	    break
	}
    }

    if {$theIndex > -1} {
	IconList_Selection $w clear 0 end
	IconList_Selection $w set $theIndex
	IconList_Selection $w anchor $theIndex
	IconList_See $w $theIndex
    }
}

proc ::tk::IconList_Reset {w} {
    variable ::tk::Priv

    catch {unset Priv(ILAccel,$w)}
}

#----------------------------------------------------------------------
#
#		      F I L E   D I A L O G
#
#----------------------------------------------------------------------

namespace eval ::tk::dialog {}
namespace eval ::tk::dialog::file {
    namespace import -force ::tk::msgcat::*
}
if {![info exists ::tk::dialog::file::showHiddenBtn] || ![string is boolean -strict $::tk::dialog::file::showHiddenBtn]} {
    set ::tk::dialog::file::showHiddenBtn 0
}
if {![info exists ::tk::dialog::file::showHiddenVar] || ![string is boolean -strict $::tk::dialog::file::showHiddenVar]} {
    set ::tk::dialog::file::showHiddenVar 1
}

# ::tk::dialog::file:: --
#
#	Implements the TK file selection dialog. This dialog is used when
#	the tk_strictMotif flag is set to false. This procedure shouldn't
#	be called directly. Call tk_getOpenFile or tk_getSaveFile instead.
#
# Arguments:
#	type		"open" or "save"
#	args		Options parsed by the procedure.
#

proc ::tk::dialog::file:: {type args} {
    variable ::tk::Priv
    set dataName __tk_filedialog
    upvar ::tk::dialog::file::$dataName data

    ::tk::dialog::file::Config $dataName $type $args

    if {[string equal $data(-parent) .]} {
        set w .$dataName
    } else {
        set w $data(-parent).$dataName
    }

    # (re)create the dialog box if necessary
    #
    if {![winfo exists $w]} {
	::tk::dialog::file::Create $w TkFDialog
    } elseif {[string compare [winfo class $w] TkFDialog]} {
	top_destroy $w
	::tk::dialog::file::Create $w TkFDialog
    } else {
	set data(dirMenuBtn) $w.f1.menu
	set data(dirMenu) $w.f1.menu.menu
	set data(upBtn) $w.f1.up
	set data(icons) $w.icons
	set data(ent) $w.f2.ent
	set data(typeMenuLab) $w.f2.lab
	set data(typeMenuBtn) $w.f2.menu
	set data(typeMenu) $data(typeMenuBtn).m
	set data(okBtn) $w.f2.ok
	set data(cancelBtn) $w.f2.cancel
	set data(hiddenBtn) $w.f2.hidden
	::tk::dialog::file::SetSelectMode $w $data(-multiple)
    }
    if {$::tk::dialog::file::showHiddenBtn} {
	$data(hiddenBtn) configure -state normal
	grid $data(hiddenBtn)
    } else {
	$data(hiddenBtn) configure -state disabled
	grid remove $data(hiddenBtn)
    }
    # Make sure subseqent uses of this dialog are independent [Bug 845189]
    catch {unset data(extUsed)}

    # Dialog boxes should be transient with respect to their parent,
    # so that they will always stay on top of their parent window.  However,
    # some window managers will create the window as withdrawn if the parent
    # window is withdrawn or iconified.  Combined with the grab we put on the
    # window, this can hang the entire application.  Therefore we only make
    # the dialog transient if the parent is viewable.

    if !$data(-guibase_toplevel) {
	if {[winfo viewable [winfo toplevel $data(-parent)]] } {
	    wm transient $w $data(-parent)
	}
    }

    # Add traces on the selectPath variable
    #
    trace variable data(selectPath) w "::tk::dialog::file::SetPath $w"
    $data(dirMenuBtn) configure -textvariable ::tk::dialog::file::${dataName}(selectPath)

    set ::tk::${data(icons)}(viewMethod) List
    set data(ClipboardFiles) {}
    set data(selectPathHistory) {}
    bindtags $data(backdirBtn) all

    # Initialize the file types menu
    #
    if {[llength $data(-filetypes)]} {
	if {$data(typeMenu) != ""} { $data(typeMenu) delete 0 end }
	set values ""
	foreach type $data(-filetypes) {
	    set title  [lindex $type 0]

	    if $data(BWidget) {
		lappend values $title
	    } else {
		$data(typeMenu) add command -label $title \
		    -command [list ::tk::dialog::file::SetFilter $w $type]
	    }
	}
	if {$values != ""} {
	    $data(typeMenuBtn) configure -values $values
	}
	set ok 0
	if {$data(-defaultextension) != ""} {
	    foreach ft $data(-filetypes) {
		if {[lsearch -exact $data(-defaultextension) [lindex $ft 1]] >= 0} {
		    ::tk::dialog::file::SetFilter $w $ft no_update
		    set ok 1
		}
	    }
	}
	if !$ok {
	    ::tk::dialog::file::SetFilter $w [lindex $data(-filetypes) 0] no_update
	}
	$data(typeMenuBtn) configure -state normal -takefocus 1
	$data(typeMenuLab) configure -text [::tk::RemoveAmpFromText $data(fTypeCaption)]
	catch {form_label_settext $data(typeMenuLab) [::tk::RemoveAmpFromText $data(fTypeCaption)]}
    } else {
	set data(filter) "*"
	if {[info exists data(typeMenuBtn)] && [winfo exists $data(typeMenuBtn)]} {
	    $data(typeMenuBtn) configure -state disabled -takefocus 0
	    $data(typeMenuLab) configure -text ""
	}
    }
    ::tk::dialog::file::UpdateWhenIdle $w

    # Withdraw the window, then update all the geometry information
    # so we know how big it wants to be, then center the window in the
    # display and de-iconify it.

    if !$data(-guibase_toplevel) {
	::tk::PlaceWindow $w widget $data(-parent)
	wm title $w $data(-title)
    } else {
	top_geometry $w +100+300
    }

    if $data(BWidget) {
	$data(ent) configure -text $data(selectFile)
    } else {
	$data(ent) delete 0 end
	$data(ent) insert 0 $data(selectFile)
	$data(ent) selection range 0 end
	$data(ent) icursor end
    }
    # Set a grab and claim the focus too.
    if !$data(-guibase_toplevel) {
	::tk::SetFocusGrab $w $data(ent)
    } else {
	set oldfocus [focus]
	focus $data(ent)
    }

    # Wait for the user to respond, then restore the focus and
    # return the index of the selected button.  Restore the focus
    # before deleting the window, since otherwise the window manager
    # may take the focus away so we can't redirect it.  Finally,
    # restore any grab that was in effect.

    tkwait variable ::tk::Priv(selectFilePath)

    if !$data(-guibase_toplevel) {
	::tk::RestoreFocusGrab $w $data(ent) withdraw
    } else {
	focus $oldfocus
    }

    # Cleanup traces on selectPath variable
    #

    foreach trace [trace vinfo data(selectPath)] {
	trace vdelete data(selectPath) [lindex $trace 0] [lindex $trace 1]
    }
    # $data(dirMenuBtn) configure -textvariable {}

    # We might have done something wierd here
    # top_destroy clears out ::tk::Priv
    set selectFilePath $Priv(selectFilePath)
    top_destroy $w

    return $selectFilePath
}

# ::tk::dialog::file::Config --
#
#	Configures the TK filedialog according to the argument list
#
proc ::tk::dialog::file::Config {dataName type argList} {
    upvar ::tk::dialog::file::$dataName data

    set data(type) $type

    # 0: Delete all variable that were set on data(selectPath) the
    # last time the file dialog is used. The traces may cause troubles
    # if the dialog is now used with a different -parent option.

    foreach trace [trace vinfo data(selectPath)] {
	trace vdelete data(selectPath) [lindex $trace 0] [lindex $trace 1]
    }

    # 1: the configuration specs
    #
    set specs {
	{-defaultextension "" "" ""}
	{-filetypes "" "" ""}
	{-initialdir "" "" ""}
	{-initialfile "" "" ""}
	{-parent "" "" "."}
	{-title "" "" ""}

	{-dir_leaf_check "" "" ""}
	{-dir_leaf_image "" "" ""}
	{-dir_leaf_label "" "" ""}
	{-extra_widgets_bottom "" "" ""}
	{-extra_widgets_side "" "" ""}
	{-pick_func "" "" ""}
	{-allow_nonexistent "" "" "0"}
	{-guibase_toplevel "" "" "0"}
	{-open_button_name "" "" ""}
    }

    # The "-multiple" option is only available for the "open" file dialog.
    #
    if { [string equal $type "open"] } {
	lappend specs {-multiple "" "" "0"}
    }

    # 2: default values depending on the type of the dialog
    #
    if {![info exists data(selectPath)]} {
	# first time the dialog has been popped up
	set data(selectPath) [pwd]
	set data(selectFile) ""
    }

    # 3: parse the arguments
    #
    tclParseConfigSpec ::tk::dialog::file::$dataName $specs "" $argList

    if {$data(-title) == ""} {
	if {[string equal $type "open"]} {
	    set data(-title) "[mc "Open"]"
	} else {
	    set data(-title) "[mc "Save As"]"
	}
    }

    set data(dir_leaf) [expr {$data(-dir_leaf_check) != ""}]

    # 4: set the default directory and selection according to the -initial
    #    settings
    #
    if {$data(-initialdir) != ""} {
	# Ensure that initialdir is an absolute path name.
	if {[::tk::dialog::file::IsDirectoryToUs $data(-initialdir)]} {
	    set old [pwd]
	    cd $data(-initialdir)
	    set data(selectPath) [pwd]
	    cd $old
	} else {
	    set data(selectPath) [pwd]
	}
    }
    if {[string equal $data(-initialfile) \{\}] || [string equal $data(-initialfile) \"\"]} {
	set data(-initialfile) ""
    }
    set data(selectFile) $data(-initialfile)

    # 5. Parse the -filetypes option
    #
    set data(-filetypes) [::tk::FDGetFileTypes $data(-filetypes)]

    if {![winfo exists $data(-parent)]} {
	error "bad window path name \"$data(-parent)\""
    }

    # Set -multiple to a one or zero value (not other boolean types
    # like "yes") so we can use it in tests more easily.
    if {![string compare $type save]} {
	set data(-multiple) 0
    } elseif {$data(-multiple)} { 
	set data(-multiple) 1 
    } else {
	set data(-multiple) 0
    }
}

proc ::tk::dialog::file::Create {w class} {
    set dataName [lindex [split $w .] end]
    upvar ::tk::dialog::file::$dataName data
    variable ::tk::Priv
    variable busyWidget
    global env

    if $data(-guibase_toplevel) {
	top_window $w 1 $data(-title) [list ::tk::dialog::file::CancelCmd $w] "" 1 1 $class
    } else {
	toplevel $w -class $class
	wm minsize $w 450 290
	if {![info exists Priv(dragBorderImage)]} {
	    set Priv(dragBorderImage) [image create photo -data {
		R0lGODlhDwAPAJEAANnZ2fz8/ICAgP///yH5BAEAAAAALAAAAAAPAA8AAAJUhI8YmUcR4aOF
		SCaQSELwMUQE0UgkgSD4FiICFBE+hIgARSL4ISIQJBN2iAgEyYQdIgJBMgIAwoQQiUAIECIR
		CBESIgIhQkJEBEJIiohACEkIEYECADs=}]
	}
	set drag [label $w.drag -bd 0 -image $Priv(dragBorderImage)]
	place $drag -in $w -relx 1.0 -rely 1.0 -anchor se
    }

    variable recentSelections
    if {[info exists env(HOME)] && ![info exists recentSelections(file)]} {
	# I've had a weird error sometimes on SGI where "info exists" retruns 1,
	# but using $env(HOME) gives an error that it doesn't exist.
	if {![catch {set env(HOME)}] && [file exists $env(HOME)]} {
	    set recentSelections(file) [file join $env(HOME) .tk_recent_files]
	}
    }

    # f1: the frame with the directory option menu
    #
    set f1 [frame $w.f1]
    bind [::tk::AmpWidget label $f1.lab -text "[mc "&Look in:"]" -anchor w -padx 0] <<AltUnderlined>> [list focus $f1.menu]
    # Since the label has no pointer bindings, we can use it later in a grab to block events
    set busyWidget $f1.lab
    catch {form_label_settext $f1.lab "[mc "Look in:"]"}
    set vtext [format %s(selectPath) ::tk::dialog::file::$dataName]
#    set data(BWidget) [expr {[package version BWidget] != ""}]
    set data(BWidget) [expr {![catch {ComboBox $f1.menu -textvariable $vtext -height 10 -justify left} res]}]
    if $data(BWidget) {
	set data(dirMenuBtn) $res
	set cmd Button
	set options {-relief link -bd 1}
    } else {
	set data(dirMenu) [tk_optionMenu $f1.menu $vtext ""]
	set data(dirMenuBtn) $f1.menu
	set cmd button
	set options ""
    }
    set fg [$data(dirMenuBtn) cget -fg]
    switch [string toupper $fg] {
	{} - WHITE - #FFF - #FFFFFF - #FFFFFFFFF - #FFFFFFFFFFFF - #A0A0FF {set fg black}
    }
    if $data(BWidget) {
	$data(dirMenuBtn) configure -fg $fg -postcommand "
	    ::tk::dialog::file::GetDrives $w
	    after idle \{if \[winfo exists $data(dirMenuBtn).shell.listb\] \{
		$data(dirMenuBtn).shell.listb configure -fg $fg\}\}"
    }

    if {![info exists Priv(backdirOffImage)]} {
	set Priv(backdirOffImage) [image create photo -data {
		R0lGODlhEwASAJEAANnZ2YCAgPz8/P///yH5BAEAAAAALAAAAAATABIAAAI/hI+py+0PEwnh
		Y1qEEHzMiBCCj0jxMQg+UHw0IfgUH00IPlB8DCH4FhEk3wj+RQgiIiAR4WOeqKoqpZRSCpAC
		ADs=}]
    }
    if {![info exists Priv(updirImage)]} {
	set Priv(updirImage) [image create photo -data {
		R0lGODlhEwASAJEAANnZ2QAAAP/ykv///yH5BAEAAAAALAAAAAATABIAAAJbhI+py0qxCT5e
		kOwg+AgUH5FgB8nHCwAgRCISJN8CAIAiSUSQfAkAAIpEsUl+AAAEyYo7CyAAISISJN8CAIAi
		iVB8EQkAAkLy8QIACKF8vAAAAuNjEnxMXW5HUgA7}]
    }
    if {![info exists Priv(mkdirImage)]} {
	set Priv(mkdirImage) [image create photo -data {
		R0lGODlhEwASAJEAANnZ2QAA/wAAAP//kiH5BAEAAAAALAAAAAATABIAAAJihI+pi0HwEePi
		KIRNsiEAAgghbKHZAgEBFMIm+QYQBN+E5kdETFASABCabzExQbCF5k9YWBAMoflxYRAEi+bj
		CQAQxPl4AgAEcT6eAABBnI8nAEAQ5+MJABAoH5PgY+oyUgEAOw==}]
    }
    if {![info exists Priv(viewImage)]} {
	set Priv(viewImage) [image create photo -data {
		R0lGODlhHgASALMAANnZ2QQEBAwkbPz8/ISEhAAAgAQEhICAgNTUzP//////////////////
		/////////yH5BAEAAAAALAAAAAAeABIAAAStEMhJq704awuDnLQGCOSkNEAhJ6UBAjkphUFO
		WgMEclIa4JCT0gCBnJSGQcoIYQxIyghhBABgkHMCAMIwBg4pjZkjAABgkDMAAECAQ05KAwAA
		wCAlBFKGccwIYYxj4AhhBAikDCHMGYYxcEhpzBwBAjnDnCDAISelAQI5KQ2DlBHCGBCVEcII
		EMhJaRjFwCGlMXMECOSkNMAhJ6UBAjkphUFOWgMEctJqL8563wgAOw==}]
    }
    if {![info exists Priv(deleteImage)]} {
	set Priv(deleteImage) [image create photo -data {
		R0lGODlhEwASAKIAANnZ2ZxkZMwEBPycNPwEBJwEBMw0NPxkBCH5BAEAAAAALAAAAAATABIA
		AANhCLrc/jDKhkICQXeFFclQIehK7SokRAWAAFIIugyCVABSCLq8glRSCLrcglQIutyCVFQI
		uryCVABUCLoMglQAAEiFoLt2KAi6tKvIhgpBF4gXGRWCLrdiIegyIehy+8OGEgA7}]
    }

    set data(backdirBtn) [eval $cmd $f1.back -image $Priv(backdirOffImage) $options]
    set data(upBtn) [eval $cmd $f1.up -image $Priv(updirImage) $options]
    set data(mkdirBtn) [eval $cmd $f1.mkdir -image $Priv(mkdirImage) $options]
    set data(viewBtn) [eval $cmd $f1.view -image $Priv(viewImage) $options]
    set data(deleteBtn) [eval $cmd $f1.delete -image $Priv(deleteImage) $options]
    if $data(BWidget) {
	DynamicHelp::register $data(backdirBtn) balloon "Go To Last Folder Visited"
	DynamicHelp::register $data(upBtn) balloon "Up One Level"
	DynamicHelp::register $data(mkdirBtn) balloon "Create New Folder"
	DynamicHelp::register $data(viewBtn) balloon "View Menu"
	DynamicHelp::register $data(deleteBtn) balloon "Delete"
    }
    # This is so we can later clear the bindtags on this button and set back again
    # It looks better this way than using -state disabled
    set data(backdirBtnTags) [bindtags $data(backdirBtn)]

    $f1.menu configure -takefocus 1 -highlightthickness 0
    pack $data(deleteBtn) $data(viewBtn) $data(mkdirBtn) $data(upBtn) $data(backdirBtn) \
	-side right -padx 0
    pack $f1.lab -side left -padx 0 -fill both
    pack $f1.menu -expand yes -fill x -padx 7 -pady 2 -ipady 1

    # data(icons): the IconList that list the files and directories.
    #
    if { [string equal $class TkFDialog] } {
	if $data(dir_leaf) {
	    set fNameCaption $data(-dir_leaf_label)
	} elseif {$data(-multiple)} {
	    set fNameCaption "[mc "File &names:"]"
	} else {
	    set fNameCaption "[mc "File &name:"]"
	}
	set data(fTypeCaption) "[mc "Files of &type:"]"
	set iconListCommand [list ::tk::dialog::file::ActivateEnt $w]
    } else {
	set fNameCaption [mc "&Selection:"]
	set iconListCommand [list ::tk::dialog::file::chooseDir::DblClick $w]
    }
    set data(icons) [::tk::IconList $w.icons \
	    -command	$iconListCommand \
	    -multiple	$data(-multiple) -fg $fg]
    bind $data(icons) <<ListboxSelect>> [list ::tk::dialog::file::ListBrowse $w]

    # f2: the frame with the OK button, cancel button, "file name" field
    #     and file types field.
    #
    set f2 [frame $w.f2 -bd 0]
    bind [::tk::AmpWidget label $f2.lab -text $fNameCaption -anchor w -pady 0 -width 12 -padx 0]\
	    <<AltUnderlined>> [list focus $f2.ent]
    catch {form_label_settext $f2.lab [::tk::RemoveAmpFromText $fNameCaption]}
    if $data(BWidget) {
	set data(ent) [ComboBox $f2.ent -justify left -fg $fg \
				-modifycmd [list ::tk::dialog::file::PickRecentSelection $w] \
				-takefocus 1 -highlightthickness 0 -postcommand "
					::tk::dialog::file::GetRecentSelections $w
					after idle \{if \[winfo exists $f2.ent.shell.listb\] \{
						$f2.ent.shell.listb configure -fg $fg\}\}"]
    } else {
	set data(ent) [entry $f2.ent -bd 2]
    }

    # The font to use for the icons. The default Canvas font on Unix
    # is just deviant.
    set ::tk::$w.icons(font) [$data(ent) cget -font]

    # Make the file types bits only if this is a File Dialog
    set data(typeMenuLab) ""; set data(typeMenuBtn) ""; 
    if { [string equal $class TkFDialog] && !$data(dir_leaf) && ($data(-filetypes) != "")} {
	set data(typeMenuLab) [::tk::AmpWidget label $f2.lab2 \
		-text $data(fTypeCaption) -anchor w -bd [$f2.lab cget -bd] \
		-highlightthickness [$f2.lab cget -highlightthickness] \
		-relief [$f2.lab cget -relief] \
		-padx [$f2.lab cget -padx] \
		-pady [$f2.lab cget -pady] \
		-width [$f2.lab cget -width]]
	catch {form_label_settext $f2.lab2 [::tk::RemoveAmpFromText $data(fTypeCaption)]}

	if $data(BWidget) {
	    set cmd [list ::tk::dialog::file::SetFilterName $w]
	    set data(typeMenuBtn) [ComboBox $f2.menu -textvariable \
					::tk::dialog::file::[winfo name $w](filter-name) \
					-takefocus 1 -highlightthickness 0 -fg $fg \
					-justify left -modifycmd $cmd -height 0 -editable 0 \
					-postcommand "after idle \{if \[winfo exists $f2.menu.shell.listb\] \{
						$f2.menu.shell.listb configure -fg $fg\}\}"]
	    set data(typeMenu) ""
	} else {
	    set data(typeMenuBtn) [menubutton $f2.menu -indicatoron 1 \
				       -menu $f2.menu.m -textvariable ::tk::dialog::file::[winfo name $w](filter-name)]
	    set data(typeMenu) [menu $data(typeMenuBtn).m -tearoff 0]
	    $data(typeMenuBtn) configure -takefocus 1 -highlightthickness 2 \
		-relief raised -bd 2 -anchor w
	}
  	bind $data(typeMenuLab) <<AltUnderlined>> [list \
		focus $data(typeMenuBtn)]

    }

    # The hidden button is displayed when ::tk::dialog::file::showHiddenBtn
    # is true.  Create it disabled so the binding doesn't trigger if it
    # isn't shown.
    if {[string equal $class TkFDialog]} {
	set text "[mc "Show &Dot Files/Directories"]"
    } else {
	set text "[mc "Show &Dot Directories"]"
    }
    set data(hiddenBtn) [::tk::AmpWidget checkbutton $f2.hidden \
	    -text $text -anchor w -padx 3 -pady 0 -state disabled \
	    -variable ::tk::dialog::file::showHiddenVar \
	    -command [list ::tk::dialog::file::UpdateWhenIdle $w]]

    # the okBtn is created after the typeMenu so that the keyboard traversal
    # is in the right order

    set data(okBtn)     [::tk::AmpWidget button $f2.ok \
	    -text [mc "&OK"] -default active -padx 15 -pady 0]
    bind $data(okBtn) <Destroy> [list ::tk::dialog::file::Destroyed $w]
    set data(cancelBtn) [::tk::AmpWidget button $f2.cancel \
	    -text [mc "&Cancel"] -default normal -padx 15 -pady 0]
    catch {form_label_settext $f2.ok [mc "OK"]}
    catch {form_label_settext $f2.cancel [mc "Cancel"]}

    # grid the widgets in f2
    #
    grid $f2.lab $f2.ent $data(okBtn) -padx 0 -sticky nsew -pady 0
    grid configure $f2.ent -padx 4 -ipady 1 -sticky ew
    grid [frame $f2.filler -bd 0 -height 4] - -
    if {$data(typeMenuLab) != ""} {
	grid $data(typeMenuLab) $data(typeMenuBtn) $data(cancelBtn) \
		-padx 0 -sticky nsew -pady 0
	grid configure $data(typeMenuBtn) -padx 4 -ipady 1 -sticky ew
	grid $data(hiddenBtn) -columnspan 2 -padx 4 -sticky ew -pady 0
    } else {
	grid $data(hiddenBtn) - $data(cancelBtn) -padx 0 -sticky nsew -pady 0
	grid configure $data(hiddenBtn) -padx 4
    }
    grid columnconfigure $f2 1 -weight 1
    grid columnconfigure $f2 2 -minsize 100
    if {$::tcl_platform(platform) == "unix"} {
	grid rowconfigure $f2 [list 0 2] -minsize 39
	grid configure $f2.ent -ipady 2
	if {$data(typeMenuBtn) != ""} {grid configure $data(typeMenuBtn) -ipady 2}
    } else {
	grid rowconfigure $f2 [list 0 2] -minsize 29
    }

    # grid the widgets in f3
    #
    if {$data(-extra_widgets_bottom) != ""} {
	set f3 [frame $w.f3 -bd 0]
	set bw [eval $data(-extra_widgets_bottom) $f3]
	if ![llength [winfo children $f3]] {
	    destroy $f3
	    set f3 ""
	} elseif {$bw != ""} {
	    $data(okBtn) configure -width $bw
	    $data(cancelBtn) configure -width $bw
	}
    } else {
	set f3 ""
    }

    if {$data(-extra_widgets_side) != ""} {
	set fxs $w.fxs
	frame $fxs -bd 2 -relief ridge
	eval $data(-extra_widgets_side) $fxs
	pack $fxs -side right -fill y
	
    }

    # Pack all the frames together. We are done with widget construction.
    #
    pack $f1 -side top -fill x -pady 6 -padx 8
    if {$f3 != ""} { pack $f3 -side bottom -pady 2}
    pack $f2 -side bottom -fill x -pady 8 -padx 8
    pack $data(icons) -expand yes -fill both -padx 7 -pady 2

    # Set up the event handlers that are common to Directory and File Dialogs
    #

    if !$data(-guibase_toplevel) {
	wm protocol $w WM_DELETE_WINDOW [list ::tk::dialog::file::CancelCmd $w]
    }
    $data(backdirBtn) configure -command [list ::tk::dialog::file::BackDirCmd $w]
    $data(upBtn)     configure -command [list ::tk::dialog::file::UpDirCmd $w]
    $data(mkdirBtn)  configure -command [list ::tk::dialog::file::MkDirCmd $w]
    $data(viewBtn) configure -command [list ::tk::dialog::file::ViewDropdown $w]
    $data(deleteBtn) configure -command [list ::tk::dialog::file::DeleteCmd $w]
    $data(cancelBtn) configure -command [list ::tk::dialog::file::CancelCmd $w]
    bind $w <KeyPress-Escape> [list tkButtonInvoke $data(cancelBtn)]
    bind $w <Alt-Key> [list tk::AltKeyInDialog $w %A]
    bind [set ::tk::${data(icons)}(nameCanvas)] <Delete> [list ::tk::dialog::file::DeleteCmd $w]


    # Set up event handlers specific to File or Directory Dialogs
    #

    if { [string equal $class TkFDialog] } {
	if $data(BWidget) {$data(ent) bind <Return> [list ::tk::dialog::file::ActivateEnt $w]} \
	else {bind $data(ent) <Return> [list ::tk::dialog::file::ActivateEnt $w]}
	$data(okBtn)     configure -command [list ::tk::dialog::file::ActivateEnt $w]
	if !$data(dir_leaf) {
	    bind $w <Alt-t> [format {
		if {[string equal [%s cget -state] "normal"]} {
		    focus %s
		}
	    } $data(typeMenuBtn) $data(typeMenuBtn)]
	}
    } else {
	set okCmd [list ::tk::dialog::file::chooseDir::OkCmd $w]
	if $data(BWidget) {$data(ent) bind <Return> $okCmd} \
	else {bind $data(ent) <Return> $okCmd}
	$data(okBtn) configure -command $okCmd
	bind $w <Alt-s> [list focus $data(ent)]
	bind $w <Alt-o> [list tkButtonInvoke $data(okBtn)]
    }
    bind $w <Alt-h> [list $data(hiddenBtn) invoke]

    # Prepend the EditDone bindtag to all the windows so we can finish the edit text operation
    set new_children $w
    while {$new_children != ""} {
	set children $new_children
	set new_children {}
	foreach child $children {
	    bindtags $child [eval list EditDone [bindtags $child]]
	    eval lappend new_children [winfo children $child]
	}
    }

    if !$data(-guibase_toplevel) {
	set topl $w
    } else {
	set topl .
    }

    # Build the focus group for all the entries
    #
    ::tk::FocusGroup_Create $topl
    ::tk::FocusGroup_BindIn $topl  $data(ent) [list ::tk::dialog::file::EntFocusIn $w]
    ::tk::FocusGroup_BindOut $topl $data(ent) [list ::tk::dialog::file::EntFocusOut $w]

    after 1 "::tk::dialog::file::AdjustViewer $w"
}

# ::tk::dialog::file::SetSelectMode --
#
#	Set the select mode of the dialog to single select or multi-select.
#
# Arguments:
#	w		The dialog path.
#	multi		1 if the dialog is multi-select; 0 otherwise.
#
# Results:
#	None.

proc ::tk::dialog::file::SetSelectMode {w multi} {
    set dataName __tk_filedialog
    upvar ::tk::dialog::file::$dataName data
    if $data(dir_leaf) {
	set fNameCaption $data(-dir_leaf_label)
    } elseif {$multi} {
	set fNameCaption "[mc {File &names:}]"
    } else {
	set fNameCaption "[mc {File &name:}]"
    }

    set iconListCommand [list ::tk::dialog::file::ActivateEnt $w]
    ::tk::SetAmpText $w.f2.lab $fNameCaption
    catch {form_label_settext $w.f2.lab [::tk::RemoveAmpFromText $fNameCaption]}
    ::tk::IconList_Config $data(icons) \
	    [list -multiple $multi -command $iconListCommand]
    return
}

# ::tk::dialog::file::UpdateWhenIdle --
#
#	Creates an idle event handler which updates the dialog in idle
#	time. This is important because loading the directory may take a long
#	time and we don't want to load the same directory for multiple times
#	due to multiple concurrent events.
#
proc ::tk::dialog::file::UpdateWhenIdle {w {arrange_method name} {append_hist 1}} {
    upvar ::tk::dialog::file::[winfo name $w] data

    if {[info exists data(updateId)]} {
	return 0
    } else {
	if {$arrange_method != "no_arrange" && $arrange_method != ""} {
	    set ::tk::${data(icons)}(arrangeMethod) $arrange_method
	}
	set data(updateId) [after idle [list ::tk::dialog::file::Update $w $append_hist]]
	return 1
    }
}

# ::tk::dialog::file::Update --
#
#	Loads the files and directories into the IconList widget. Also
#	sets up the directory option menu for quick access to parent
#	directories.
#	This procedure should not be called directly. Use ::tk::dialog::file::UpdateWhenIdle
#
proc ::tk::dialog::file::Update {w {append_hist 1}} {

    # This proc may be called within an idle handler. Make sure that the
    # window has not been destroyed before this proc is called
    if {![winfo exists $w]} {
	return
    }
    set class [winfo class $w]
    if { [string compare $class TkFDialog] && \
	    [string compare $class TkChooseDir] } {
	return
    }

    set dataName [winfo name $w]
    upvar ::tk::dialog::file::$dataName data
    variable ::tk::Priv
    catch {unset data(updateId)}

    set win [string match *win* [string tolower $::tcl_platform(os)]]
    set appPWD [pwd]
    # Turn on the busy cursor
    SetBusy 1
    # Maybe the user is just typing into the field
    if ![file exists $data(selectPath)] {
	SetBusy 0
	if $win	{
	    set matched_dr 0
	    set p [string trimright $data(selectPath) /]
	    foreach dr [file volume] {
		if [string match -nocase [string trimright $dr /] $p] {set matched_dr 1; break}
	    }
	    if $matched_dr {
		tk_messageBox -type ok -parent $w -icon warning -title "[mc "Can't access drive"]" \
			-message "[mc "Can't connect to the drive \"%1\$s\"." $data(selectPath)]"
		SetPathSilently $w [lindex $data(selectPathHistory) end]
		if $data(BWidget) {
		    $data(dirMenuBtn).e selection range 0 end
		    $data(dirMenuBtn).e icursor end
		}
	    }
	}
	return
    }

    if {![info exists Priv(folderImage)]} {
	set Priv(folderImage) [image create photo -data {
		R0lGODlhDwANAKIAANnZ2ZycBAQEBPz8/Pz8zPz8nMzMZPzMnCH5BAEAAAAALAAAAAAPAA0A
		AANUCIChKgi6GoNEVSEIuoGmaxi6EEi6TIUmQVi6fIYShKVbV3hlEoSlq1d4JkFYqleHdWUS
		SFi6V4d1JkFYenWFV3cmGHR1hVdXd3gmgabLKwgouswJADs=}]
	set Priv(folderCutImage) [::tk::AlterImage $Priv(folderImage) cut]
	set Priv(folderSelectImage) [::tk::AlterImage $Priv(folderImage) select]
    }
    if {![info exists Priv(fileImage)]} {
	set Priv(fileImage) [image create photo -data {
		R0lGODlhDwANAKIAANnZ2YSEhPz8/AQEBMTExP///////////yH5BAEAAAAALAAAAAAPAA0A
		AANWCIChqwi6ECi6MQi6gaIbMgiqIYMzIzM4AwCAgaKrNAgKIYMzIiJIAwCAgaKrNAgKITiq
		IoQDABAoukqDoBCCoypCOAAAgaKrNAgKgaS7AwgAOLo8gJAAOw==}]
	set Priv(fileCutImage) [::tk::AlterImage $Priv(fileImage) cut]
	set Priv(fileSelectImage) [::tk::AlterImage $Priv(fileImage) select]
    }
    if {$data(dir_leaf) && $data(-dir_leaf_image) != ""} {
	set data(dir_leaf_CutImage) [::tk::AlterImage $data(-dir_leaf_image) cut]
	set data(dir_leaf_SelectImage) [::tk::AlterImage $data(-dir_leaf_image) select]
    }

    set folder $Priv(folderImage)
    set file   $Priv(fileImage)

    if {[catch {
	cd $data(selectPath)
    }]} {
	# We cannot change directory to $data(selectPath). $data(selectPath)
	# should have been checked before ::tk::dialog::file::Update is called, so
	# we normally won't come to here. Anyways, give an error and abort
	# action.
	SetBusy 0
	tk_messageBox -type ok -parent $w -icon warning -title "[mc "Permission denied"]" \
	    -message "[mc "Cannot change to the directory \"%1\$s\".\nPermission denied." $data(selectPath)]"
	cd $appPWD
	return
    }
    if $append_hist {
	if {[lindex $data(selectPathHistory) end] != $data(selectPath)} {
	    lappend data(selectPathHistory) $data(selectPath)
	}
	if {![info exists Priv(backdirOnImage)]} {
	    set Priv(backdirOnImage) [image create photo -data {
		R0lGODlhEwASAJEAANnZ2QQEBAT8/P///yH5BAEAAAAALAAAAAATABIAAAI5hI+py+0PEwnh
		Y1qEKpIoBB8zRCi+EXwIko9B8CFIPgbBtxCh+EbwLyQQEQFJCB/zguBj6nL7w0YKADs=}]
	}
	if {[llength $data(selectPathHistory)] > 1} {
	    $data(backdirBtn) configure -image $Priv(backdirOnImage)
	    bindtags $data(backdirBtn) $data(backdirBtnTags)
	}
    }

    ::tk::IconList_DeleteAll $data(icons)
    set showHidden $::tk::dialog::file::showHiddenVar

    # Make the dir list
    #
    set dirs ""
    set opt1 ""
    set opt2 ""
    if {$showHidden} {
	set opt1 .*
	set opt2 -a
    }
    foreach path [eval {glob -directory [pwd] -type d -nocomplain *} $opt1] {
	lappend dirs [file tail $path]
    }
    # This is for a "glob" bug on Linux
    global tcl_platform
    if {$dirs == "" && !$win} {
	foreach path [split [eval {exec ls} $opt2] \n] {
	    if [file isdirectory $path] {lappend dirs $path}
	}
    }
    set dirList {}
    set dir_leaf_list {}
    foreach d $dirs {
	if {[string equal $d .] || [string equal $d ..]} {
	    continue
	}
	if {$win && !$showHidden && [string index $d 0] == "."} continue
	if {($data(-dir_leaf_check) != "") && \
		[eval $data(-dir_leaf_check) [list $d]]} {
	    lappend dir_leaf_list $d
	    continue
	}
	lappend dirList $d
    }
    set dirList [lsort -dictionary -unique $dirList]
    ::tk::IconList_Add $data(icons) $folder $dirList dir

    if $data(dir_leaf) {
	if {$data(-dir_leaf_image) == ""} {
	    set leafim $file
	    set tag file
	} else {
	    set leafim $data(-dir_leaf_image)
	    set tag dir_leaf
	}
	set dir_leaf_list [lsort -dictionary -unique $dir_leaf_list]
	::tk::IconList_Add $data(icons) $leafim $dir_leaf_list $tag
    } elseif { [string equal $class TkFDialog] } {
	# Make the file list if this is a File Dialog, selecting all
	# but 'd'irectory type files.
	#
	set cmd [list glob -directory [pwd] -type {f b c l p s} -nocomplain]
	if {[string equal $data(filter) *]} {
	    eval lappend cmd * $opt1
	} else {
	    eval [list lappend cmd] $data(filter)
	}
	set fileList ""
	foreach subfile [eval $cmd] {
	    set subfile [file tail $subfile]
	    if {!$win || $showHidden || [string index $subfile 0] != "."} {
		lappend fileList $subfile
	    }
	}
	# This is for a "glob" bug on Linux
	if {$fileList == "" && !$win} {
	    foreach path [split [eval {exec ls} $opt2] \n] {
		if [file isfile $path] {
		    foreach pattern $data(filter) {
			if [string match $pattern $path] {lappend fileList $path; break}
		    }
		}
	    }
	}	
	set fileList [lsort -dictionary -unique $fileList]
	::tk::IconList_Add $data(icons) $file $fileList file
    }

    ::tk::IconList_Arrange $data(icons)

    # Update the Directory: option menu
    ::tk::dialog::file::UpdateSelectPathList $w

    # Restore the PWD to the application's PWD
    #
    cd $appPWD

    if { [string equal $class TkFDialog] } {
	# Restore the Open/Save Button if this is a File Dialog
	#
	if {$data(-open_button_name) != ""} {
	    set btext $data(-open_button_name)
	} elseif {[string equal $data(type) open]} {
	    set btext [mc "&Open"]
	} else {
	    set btext [mc "&Save"]
	}
	::tk::SetAmpText $data(okBtn) $btext
	catch {form_label_settext $data(okBtn) [::tk::RemoveAmpFromText $btext]}
    }

    # turn off the busy cursor.
    #
    SetBusy 0
}

# ::tk::dialog::file::SetPathSilently --
#
# 	Sets data(selectPath) without invoking the trace procedure
#
proc ::tk::dialog::file::SetPathSilently {w path} {
    upvar ::tk::dialog::file::[winfo name $w] data
    
    trace vdelete  data(selectPath) w [list ::tk::dialog::file::SetPath $w]
    set data(selectPath) $path
    trace variable data(selectPath) w [list ::tk::dialog::file::SetPath $w]
}


# This proc gets called whenever data(selectPath) is set
#
proc ::tk::dialog::file::SetPath {w name1 name2 op} {
    if {[winfo exists $w]} {
	upvar ::tk::dialog::file::[winfo name $w] data
	
	# This is here so that if you select Desktop it will give you the
	# correct thing.
	if {[info exists data(drive_name_maps_to,$data(selectPath))] &&
		($data(drive_name_maps_to,$data(selectPath)) != $data(selectPath))} {
	    after idle "set ::tk::dialog::file::[winfo name $w](selectPath) \{$data(drive_name_maps_to,$data(selectPath))\}
		if $data(BWidget) \{
		    $data(dirMenuBtn).e selection range 0 end
		    $data(dirMenuBtn).e icursor end
		\}"
	    return
	}
	
	::tk::dialog::file::UpdateWhenIdle $w
	# On directory dialogs, we keep the entry in sync with the currentdir.
	if { [string equal [winfo class $w] TkChooseDir] } {
	    if $data(BWidget) {
		$data(ent) configure -text $data(selectPath)
	    } else {
		$data(ent) delete 0 end
		$data(ent) insert end $data(selectPath)
	    }
	}
    }
    ::tk::dialog::file::AdjustViewer $w
}

# This proc gets called whenever data(filter) is set
#
proc ::tk::dialog::file::SetFilter {w type {update update}} {
    upvar ::tk::dialog::file::[winfo name $w] data
    upvar ::tk::$data(icons) icons

    set data(filter-name) [lindex $type 0]
    set data(filter) [lindex $type 1]

    # If we aren't using a default extension, use the one supplied
    # by the filter.
    if {![info exists data(extUsed)]} {
	if {[string length $data(-defaultextension)]} {
	    set data(extUsed) 1
	} else {
	    set data(extUsed) 0
	}
    }

    if {!$data(extUsed)} {
	# Get the first extension in the list that matches {^\*\.\w+$}
	# and remove all * from the filter.
	set index [lsearch -regexp $data(filter) {^\*\.\w+$}]
	if {$index >= 0} {
	    set data(-defaultextension) \
		    [string trimleft [lindex $data(filter) $index] "*"]
	} else {
	    # Couldn't find anything!  Reset to a safe default...
	    set data(-defaultextension) ""
	}
    }

    $icons(hsbar) set 0.0 0.0
    $icons(vsbar) set 0.0 0.0
    if {$update == "update"} {
	::tk::dialog::file::UpdateWhenIdle $w no_arrange
    }
}

# tk::dialog::file::ResolveFile --
#
#	Interpret the user's text input in a file selection dialog.
#	Performs:
#
#	(1) ~ substitution
#	(2) resolve all instances of . and ..
#	(3) check for non-existent files/directories
#	(4) check for chdir permissions
#
# Arguments:
#	context:  the current directory you are in
#	text:	  the text entered by the user
#	defaultext: the default extension to add to files with no extension
#
# Return vaue:
#	[list $flag $directory $file]
#
#	 flag = OK	: valid input
#	      = PATTERN	: valid directory/pattern
#	      = PATH	: the directory does not exist
#	      = FILE	: the directory exists by the file doesn't
#			  exist
#	      = CHDIR	: Cannot change to the directory
#	      = ERROR	: Invalid entry
#
#	 directory      : valid only if flag = OK or PATTERN or FILE
#	 file           : valid only if flag = OK or PATTERN
#
#	directory may not be the same as context, because text may contain
#	a subdirectory name
#
proc ::tk::dialog::file::ResolveFile {w context text defaultext} {
    upvar ::tk::dialog::file::[winfo name $w] data

    set appPWD [pwd]
    set path [::tk::dialog::file::JoinFile $context $text]
    set class [winfo class $w]

    # If the file has no extension, append the default.  Be careful not
    # to do this for directories, otherwise typing a dirname in the box
    # will give back "dirname.extension" instead of trying to change dir.
    # Also only do it when selecting files to save to or selecting files to open with -allow_nonexistent defined
    if {[string equal $class TkFDialog] && ![file isdirectory $path] && (($data(type) == "save") || ($data(-allow_nonexistent) && ![file exists $path]))} {
	set ext [file ext $path]
	set ok 0
	if {$ext == ""} {
	    if {($data(filter) != "*") && ($data(filter) != "*.*")} {
		set ext [file extension [lindex $data(filter) 0]]
		set path "$path$ext"
	    } else {
		set path "$path$defaultext"
	    }
	} else {
	    if {($data(filter) != "*") && ($data(filter) != "*.*")} {
		foreach type $data(-filetypes) {
		    foreach ff [lindex $type 1] {
			if {($ff != "*") && ($ff != "*.*")} {
			    set x1 [file extension $ff]
			    if {[string match -nocase $x1 $ext]} {set ok 1; break}
			}
		    }
		}
		if !$ok {
		    if {$defaultext != ""} {
			set path "[file rootname $path]$defaultext"
		    }
		}
	    } else {
		# do nothing
		set ok 1
	    }
	}

	if !$ok {
	    set file [file tail $path]
	    if $data(BWidget) {
		$data(ent) configure -text $file
	    } else {
		$data(ent) delete 0 end
		$data(ent) insert 0 $file
	    }
	    update idle; after 500
	}
    }

    if {[catch {file exists $path}]} {
	# This "if" block can be safely removed if the following code
	# stop generating errors.
	#
	#	file exists ~nonsuchuser
	#
	return [list ERROR $path ""]
    }

    if {[file exists $path]} {
	if {[::tk::dialog::file::IsDirectoryToUs $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]
}


# Gets called when the entry box gets keyboard focus. We clear the selection
# from the icon list . This way the user can be certain that the input in the 
# entry box is the selection.
#
proc ::tk::dialog::file::EntFocusIn {w} {
    upvar ::tk::dialog::file::[winfo name $w] data

    if $data(BWidget) {
	if {[string compare [$data(ent) cget -text] ""]} {focus $data(ent)}
    } elseif {[string compare [$data(ent) get] ""]} {
	$data(ent) selection range 0 end
	$data(ent) icursor end
    }

    if { [string equal [winfo class $w] TkFDialog] } {
	# If this is a File Dialog, make sure the buttons are labeled right.
	if {$data(-open_button_name) != ""} {
	    set btext $data(-open_button_name)
	} elseif {[string equal $data(type) open]} {
	    set btext [mc "&Open"]
	} else {
	    set btext [mc "&Save"]
	}
	::tk::SetAmpText $data(okBtn) $btext
	catch {form_label_settext $data(okBtn) [::tk::RemoveAmpFromText $btext]}
    }
}

proc ::tk::dialog::file::EntFocusOut {w} {
    upvar ::tk::dialog::file::[winfo name $w] data

    if !$data(BWidget) {$data(ent) selection clear}
}

# Gets called when user presses Return in the "File name" entry.
#
proc ::tk::dialog::file::ActivateEnt {w} {
    upvar ::tk::dialog::file::[winfo name $w] data

    if $data(BWidget) {
	set text [$data(ent) cget -text]
    } else {
	set text [$data(ent) get]
    }
    set data(selectFile) ""
    set selIcos [::tk::IconList_Curselection $data(icons)]
    if {[llength $selIcos] == 0} {
	if {$text != ""} {
	    # This assumes the user typed something in without selecting
	    # files - so assume they only type in a single filename.
	    ::tk::dialog::file::VerifyFileName $w $text
	}
    } else {
	foreach item $selIcos {
	    ::tk::dialog::file::VerifyFileName $w [::tk::IconList_Get $data(icons) $item]
	}
    }
    ::tk::dialog::file::Done $w
}

# Verification procedure
#
proc ::tk::dialog::file::VerifyFileName {w filename} {
    upvar ::tk::dialog::file::[winfo name $w] data

    set list [::tk::dialog::file::ResolveFile $w $data(selectPath) $filename \
	    $data(-defaultextension)]
    foreach {flag path file} $list break
    set highlight_entry 0
    set class [winfo class $w]

    switch -- $flag {
	OK {
	    if {[string equal $file ""]} {
		# user has entered an existing (sub)directory
		set data(selectPath) $path
	    } else {
		::tk::dialog::file::SetPathSilently $w $path
		if {$data(-multiple)} {
		    lappend data(selectFile) $file
		} else {
		    set data(selectFile) $file
		}
	    }
	}
	PATTERN {
	    set data(selectPath) $path
	    set data(filter) $file
	}
	FILE {
	    set fullfile [JoinFile $data(selectPath) $file]
	    if {[string equal $class TkChooseDir] || ([string equal $data(type) open] &&
			!$data(-allow_nonexistent))} {
		tk_messageBox -icon warning -type ok -parent $w -title "[mc "File doesn't exist"]" \
		    -message "[mc "File \"%1\$s\" does not exist." $fullfile]"
		set highlight_entry 1
	    } elseif {[string equal $data(type) open] && $data(-allow_nonexistent)} {
		set answer [tk_messageBox -icon warning -type yesno -parent $w -title "[mc "File doesn't exist"]" \
		    -message "[mc "File \"%1\$s\" does not exist.\nDo you want to create the file?" $fullfile]"]
		if {$answer == "yes"} {
		    if {$data(-multiple)} {set data(selectFile) [list $file]} \
		    else {set data(selectFile) $file}
		} else {set highlight_entry 1}
	    } else {
		::tk::dialog::file::SetPathSilently $w $path
		if {$data(-multiple)} {
		    lappend data(selectFile) $file
		} else {
		    set data(selectFile) $file
		}
	    }
	}
	PATH {
	    tk_messageBox -icon warning -type ok -parent $w -title "[mc "Directory doesn't exist"]" \
		-message "[mc "Directory \"%1\$s\" does not exist." $path]"
	    set highlight_entry 1
	}
	CHDIR {
	    tk_messageBox -type ok -parent $w -title "[mc "Permission denied"]" \
	       -message "[mc "Cannot change to the directory \"%1\$s\".\nPermission denied." $path]" -icon warning
	    set highlight_entry 1
	}
	ERROR {
	    tk_messageBox -type ok -parent $w -title "[mc "Invalid file name"]" \
	       -message "[mc "Invalid file name \"%1\$s\"." $path]"	-icon warning
	    set highlight_entry 1
	}
    }
    if $highlight_entry {
	set ent $data(ent)
	if $data(BWidget) {append ent ".e"}
	$ent selection range 0 end
	$ent icursor end
    }
}

# Gets called when user presses the Alt-s or Alt-o keys.
#
proc ::tk::dialog::file::InvokeBtn {w key} {
    upvar ::tk::dialog::file::[winfo name $w] data

    if {[string equal [$data(okBtn) cget -text] $key]} {
	::tk::tkButtonInvoke $data(okBtn)
    }
}

# Gets called when user presses the "parent directory" button
#
proc ::tk::dialog::file::UpDirCmd {w} {
    upvar ::tk::dialog::file::[winfo name $w] data

    if {[string compare $data(selectPath) "/"]} {
	set data(selectPath) [file dirname $data(selectPath)]
    }
}

# Join a file name to a path name. The "file join" command will break
# if the filename begins with ~
#
proc ::tk::dialog::file::JoinFile {path file} {
    if {[string match {~*} $file] && [file exists $path/$file]} {
	return [file join $path ./$file]
    } else {
	return [file join $path $file]
    }
}

# Gets called when user presses the "Cancel" button
#
proc ::tk::dialog::file::CancelCmd {w} {
    upvar ::tk::dialog::file::[winfo name $w] data
    variable ::tk::Priv

    bind $data(okBtn) <Destroy> {}
    set Priv(selectFilePath) ""
    return 1
}

# Gets called when user destroys the dialog directly [Bug 987169]
#
proc ::tk::dialog::file::Destroyed {w} {
    upvar ::tk::dialog::file::[winfo name $w] data
    variable ::tk::Priv

    set Priv(selectFilePath) ""
}

# Gets called when user browses the IconList widget (dragging mouse, arrow
# keys, etc)
#
proc ::tk::dialog::file::ListBrowse {w} {
    upvar ::tk::dialog::file::[winfo name $w] data

    set text {}
    foreach item [::tk::IconList_Curselection $data(icons)] {
	lappend text [::tk::IconList_Get $data(icons) $item]
    }
    if {[llength $text] == 0} {
	return
    }
    if { [llength $text] > 1 } {
	set newtext {}
	foreach file $text {
	    set fullfile [::tk::dialog::file::JoinFile $data(selectPath) $file]
	    if { ![::tk::dialog::file::IsDirectoryToUs $fullfile]} {
		lappend newtext $file
	    }
	}
	set text $newtext
	set isDir 0
    } else {
	set text [lindex $text 0]
	if {[string equal $text ""]} return
	set file [::tk::dialog::file::JoinFile $data(selectPath) $text]
	if { [string equal [winfo class $w] TkChooseDir] } {
	    if $data(BWidget) {
		$data(ent) configure -text $file
	    } else {
		$data(ent) delete 0 end
		$data(ent) insert 0 $file
	    }
	    return
	}
	set isDir [::tk::dialog::file::IsDirectoryToUs $file]
    }
    if {!$isDir} {
	if $data(BWidget) {
	    $data(ent) configure -text $text
	} else {
	    $data(ent) delete 0 end
	    $data(ent) insert 0 $text
	}

	if { [string equal [winfo class $w] TkFDialog] } {
	    if {$data(-open_button_name) != ""} {
		set btext $data(-open_button_name)
	    } elseif {[string equal $data(type) open]} {
		set btext [mc "&Open"]
	    } else {
		set btext [mc "&Save"]
	    }
	    ::tk::SetAmpText $data(okBtn) $btext
	    catch {form_label_settext $data(okBtn) [::tk::RemoveAmpFromText $btext]}
	}
	if {$data(-pick_func) != ""} {
	    foreach file $text {
		eval $data(-pick_func) [list [::tk::dialog::file::JoinFile $data(selectPath) $file]]
	    }
	}
    } else {
	if { [string equal [winfo class $w] TkFDialog] } {
	    ::tk::SetAmpText $data(okBtn) [mc "&Open"]
	    catch {form_label_settext $data(okBtn) [mc "Open"]}
	}
    }
}

# ::tk::dialog::file::Done --
#
#	Gets called when user has input a valid filename.  Pops up a
#	dialog box to confirm selection when necessary. Sets the
#	tk::Priv(selectFilePath) variable, which will break the "vwait"
#	loop in ::tk::dialog::file:: and return the selected filename to the
#	script that calls tk_getOpenFile or tk_getSaveFile
#
proc ::tk::dialog::file::Done {w {selectFilePath ""}} {
    upvar ::tk::dialog::file::[winfo name $w] data
    variable ::tk::Priv

    if {[llength $data(selectFile)] == 0 && $selectFilePath == ""} return

    if {[string equal $selectFilePath ""]} {
	if {$data(-multiple)} {
	    set selectFilePath {}
	    foreach f $data(selectFile) {
		lappend selectFilePath [::tk::dialog::file::JoinFile $data(selectPath) $f]
	    }
	} else {
	    set selectFilePath [::tk::dialog::file::JoinFile $data(selectPath) $data(selectFile)]
	}
	
	set Priv(selectFile)     $data(selectFile)
	set Priv(selectPath)     $data(selectPath)

	if {[string equal $data(type) save]} {
	    if {[file exists $selectFilePath]} {
		set reply [tk_messageBox -icon warning -type yesno -title [mc "Overwrite"] \
		    -parent $w -message "[mc "File \"%1\$s\" already exists.\nDo you want to overwrite it?" $selectFilePath]"]
		if {[string equal $reply "no"]} return
	    }
	}
    }

    bind $data(okBtn) <Destroy> {}
    set Priv(selectFilePath) $selectFilePath
    if $data(BWidget) {SaveRecentSelections $w $selectFilePath}
}

################################################
#                                                                                                               #
#    The following are new procedures                                                         #
#                                                                                                               #
################################################

# These procedures were removed
# ::tk::dialog::file::OkCmd
# ::tk::dialog::file::ListInvoke

# ::tk::dialog::file::IsDirectoryToUs --
#
# 	Do we consider this a directory?
#
proc ::tk::dialog::file::IsDirectoryToUs {f} {
    upvar ::tk::dialog::file::__tk_filedialog data
    
    if {![info exists data(dir_leaf)] || !$data(dir_leaf)} {
	return [file isdirectory $f]
    } elseif ![file isdirectory $f] {
	return 0
    } else {
	return [expr ![eval $data(-dir_leaf_check) [list $f]]]
    }
}

proc ::tk::dialog::file::SetFilterName {w} {
    upvar ::tk::dialog::file::[winfo name $w] data

    set ind [$data(typeMenuBtn) getvalue]
    set which [lindex $data(-filetypes) $ind]
    ::tk::dialog::file::SetFilter $w $which
}

# Gets called when user presses the "refresh" button
#
proc ::tk::dialog::file::RefreshCmd {w} {
    ::tk::dialog::file::UpdateWhenIdle $w no_arrange 0
}

# Gets called when user presses the "create directory" button
#
proc ::tk::dialog::file::MkDirCmd {w} {
    upvar ::tk::dialog::file::[winfo name $w] dialogData
    variable ::tk::Priv

    set wd $dialogData(selectPath)
    set dir [file join $wd NewFolder]
    if [file exists $dir] {
	for {set i 2} {[file exists [set dir [file join $wd NewFolder$i]]]} {incr i} {}
    }
    file mkdir $dir
    set i [::tk::IconList_Add $dialogData(icons) $Priv(folderImage) [file tail $dir] dir now]
    ::tk::IconList_Index $dialogData(icons) active $i
    ::tk::dialog::file::RenameCmd $dialogData(icons)
}

# Gets called when user presses the "back directory" button
#
proc ::tk::dialog::file::BackDirCmd {w} {
    upvar ::tk::dialog::file::[winfo name $w] data
    variable ::tk::Priv

    set disable 1
    if {[llength $data(selectPathHistory)] > 1} {
	while {[llength $data(selectPathHistory)] > 1 && ![IsDirectoryToUs [lindex $data(selectPathHistory) end-1]]} {
	    tk_messageBox -type ok -parent $w -icon warning -title "[mc "Folder doesn't exist"]" \
		-message "[mc "The folder \"%1\$s\" has been renamed or deleted." [file tail [lindex $data(selectPathHistory) end-1]]]"
	    set data(selectPathHistory) [lreplace $data(selectPathHistory) end-1 end-1]
	}
	if {[llength $data(selectPathHistory)] > 1} {
	    SetPathSilently $w [lindex $data(selectPathHistory) end-1]
	    if {![::tk::dialog::file::UpdateWhenIdle $w name 0]} {
		SetPathSilently $w [lindex $data(selectPathHistory) end]
		return
	    }
	    set data(selectPathHistory) [lrange $data(selectPathHistory) 0 end-1]
	}
	if {[llength $data(selectPathHistory)] > 1} {set disable 0}
    }
    if $disable {
	$data(backdirBtn) configure -image $Priv(backdirOffImage)
	event generate $data(backdirBtn) <Leave>
	bindtags $data(backdirBtn) all
    }
}

# Gets called when user presses the "delete" button
#
proc ::tk::dialog::file::DeleteCmd {w} {
    upvar ::tk::dialog::file::[winfo name $w] data
    
    set filenames {}
    foreach item [::tk::IconList_Curselection $data(icons)] {
	lappend filenames [::tk::IconList_Get $data(icons) $item]
    }
    set n_files [llength $filenames]
    if !$n_files return
    
    if {$n_files == 1} {
	set mes "\"[lindex $filenames 0]\""
    } else {set mes "[mc "$n_files files"]"}
    if {[tk_messageBox -icon warning -type yesno -parent $w -message "[mc "Delete %1\$s?" $mes]" \
		-title "[mc "Delete files"]"] == "no"} return
    
    foreach file $filenames {file delete -force $data(selectPath)/$file}
    ::tk::dialog::file::UpdateWhenIdle $w no_arrange 0
    if $data(BWidget) {
	after idle [list $data(ent) configure -text ""]
    } else {
	after idle [list $data(ent) delete 0 end]
    }
}

proc ::tk::dialog::file::AdjustViewer {w} {
    if {[winfo exists $w]} {
	upvar ::tk::dialog::file::[winfo name $w] data
	if !$data(BWidget) return
	set ee $data(dirMenuBtn).e
	if [winfo exists $ee] {
	    set xv [$ee xview]
	    if {$xv != "0 1"} {
		$ee xview moveto [expr [lindex $xv 1] - [lindex $xv 0]]
	    }
	}
    }
}

proc ::tk::RemoveAmpFromText {text} {
    regsub -all -- {&([^&])} $text {\1} text
    return $text
}

proc ::tk::dialog::file::PopUpMenu {w W x y} {
    set tw [winfo parent $w]
    upvar ::tk::$w data

    set X [expr {[winfo rootx $W] + $x}]
    set Y [expr {[winfo rooty $W] + $y}]
    set in_w [winfo containing $X $Y]
    if {$in_w != $W} return

    focus $data(nameCanvas)
    if {$W == $data(nameCanvas)} {
	set x [expr {int([$W canvasx $x])}]
	set y [expr {int([$W canvasy $y])}]
	set items [$W find overlapping $x $y $x $y]
    }

    if {$W == $data(nameCanvas) && [llength $items] > 1} {
	if {![info exists data(selectionPopUp)] || ![winfo exists $data(selectionPopUp)]} {
	    set data(selectionPopUp) [menu $data(nameCanvas).selmenu -tearoff 0 -relief raised -bd 2 -takefocus 0]
	    $data(selectionPopUp) add command -label [mc Cut] -command [list ::tk::dialog::file::CopyCutCmd $tw cut]
	    $data(selectionPopUp) add command -label [mc Copy] -command [list ::tk::dialog::file::CopyCutCmd $tw copy]
	    $data(selectionPopUp) add separator
	    $data(selectionPopUp) add command -label [mc Delete] -command [list ::tk::dialog::file::DeleteCmd $tw]
	    $data(selectionPopUp) add command -label [mc Rename] -command [list ::tk::dialog::file::RenameCmd $w]
	    $data(selectionPopUp) add separator
	    $data(selectionPopUp) add command -label [mc Properties] -command [list ::tk::dialog::file::Properties $tw active]
	}

	set i [::tk::IconList_Index $w @${x},${y}]
	if {$i<0} return
	::tk::IconList_Index $w active $i
	if ![::tk::IconList_Selection $w includes $i] {
	    ::tk::IconList_Selection $w clear 0 end
	    ::tk::IconList_Selection $w set $i
	    ::tk::IconList_Selection $w anchor $i
	}
	tk_popup $data(selectionPopUp) $X $Y
    } else {
	if {![info exists data(noSelectionPopUp)] || ![winfo exists $data(noSelectionPopUp)]} {
	    set data(noSelectionPopUp) [menu $data(nameCanvas).noselmenu -tearoff 0 -relief raised -bd 2 -takefocus 0]
	    $data(noSelectionPopUp) add cascade -label [mc View] -menu $data(noSelectionPopUp).view
	    $data(noSelectionPopUp) add separator
	    $data(noSelectionPopUp) add cascade -label "[mc "Arrange Icons"]" -menu $data(noSelectionPopUp).arrange
	    $data(noSelectionPopUp) add command -label [mc Refresh] -command [list ::tk::dialog::file::RefreshCmd $tw]
	    $data(noSelectionPopUp) add separator
	    $data(noSelectionPopUp) add command -label [mc Paste] -command [list ::tk::dialog::file::PasteCmd $tw]
	    $data(noSelectionPopUp) add separator   
	    $data(noSelectionPopUp) add command -label "[mc "New Folder"]" -command [list ::tk::dialog::file::MkDirCmd $tw]
	    $data(noSelectionPopUp) add separator
	    $data(noSelectionPopUp) add command -label [mc Properties] -command [list ::tk::dialog::file::Properties $tw]

	    menu $data(noSelectionPopUp).view -tearoff 0 -relief raised -bd 2 -takefocus 0
	    $data(noSelectionPopUp).view add radiobutton -label [mc List] -variable ::tk::${w}(viewMethod) -value List \
		-command [list ::tk::dialog::file::ViewMethod $w]
	    $data(noSelectionPopUp).view add radiobutton -label [mc Details] -variable ::tk::${w}(viewMethod) -value Details \
		-command [list ::tk::dialog::file::ViewMethod $w]

	    menu $data(noSelectionPopUp).arrange -tearoff 0 -relief raised -bd 2 -takefocus 0
	    $data(noSelectionPopUp).arrange add command -label "[mc "by Name"]" -command \
			[list ::tk::IconList_ReArrange $w [lsearch $data(canvasNames) name] increasing setbutton]
	    $data(noSelectionPopUp).arrange add command -label "[mc "by Size"]" -command \
			[list ::tk::IconList_ReArrange $w [lsearch $data(canvasNames) size] increasing setbutton]
	    $data(noSelectionPopUp).arrange add command -label "[mc "by Type"]" -command \
			[list ::tk::IconList_ReArrange $w [lsearch $data(canvasNames) type] increasing setbutton]
	    $data(noSelectionPopUp).arrange add command -label "[mc "by Date"]" -command \
			[list ::tk::IconList_ReArrange $w [lsearch $data(canvasNames) modified] increasing setbutton]
	}

	::tk::IconList_Selection $w clear 0 end
	if {[CheckFileClipboard $tw] != ""} {
	    $data(noSelectionPopUp) entryconfigure 5 -state normal
	} else {
	    $data(noSelectionPopUp) entryconfigure 5 -state disabled
	}

	tk_popup $data(noSelectionPopUp) $X $Y
    }
}

proc ::tk::IconList_EditTextDone {w W} {
    upvar ::tk::$w data

    if {($W != [winfo toplevel $W]) && ($W != [lindex [split $w .] end-1]) && ($W != $data(editwin))} {
	set data(editDone) 1
    }
}

proc ::tk::dialog::file::RenameCmd {w} {
    upvar ::tk::dialog::file::[lindex [split $w .] end-1] dialogData
    upvar ::tk::$w data
    upvar ::tk::$w:fileList fileList

    set i [::tk::IconList_Index $w active]
    if {$i<0} return
    set item [lindex $data(list) $i]
    set tTag "item$item && text"

    set tmptags [bindtags $data(nameCanvas)]
    bindtags $data(nameCanvas) EditDone

    $data(editwin) configure -font $data(font)
    foreach {x1 y1 x2 y2} [$data(nameCanvas) bbox $tTag] break
    set h [expr {$y2 - $y1 + 1}]
    set x1 [expr {$x1 - 1}]
    set editTag [$data(nameCanvas) create window $x1 $y1 -window $data(editwin) -anchor nw -height $h]
    $data(editwin) delete 0 end
    set prev_name [$data(nameCanvas) itemcget $tTag -text]
    ::tk::IconList_Selection $w clear 0 end
    $data(nameCanvas) itemconfigure $tTag -text ""
    $data(editwin) insert 0 $prev_name
    $data(editwin) icursor end
    $data(editwin) selection range 0 end
    focus $data(editwin)
    vwait ::tk::${w}(editDone)

    set name [$data(editwin) get]
    $data(nameCanvas) delete $editTag
    if {!$data(editDone) || $name == $prev_name} {
	    $data(nameCanvas) itemconfigure $tTag -text $prev_name
    } else {
	# Do rename
	set badname 1
	set full_path [::tk::dialog::file::JoinFile $dialogData(selectPath) $name]
	switch -regexp -- $name {
	    {^()$} {
		set title [mc Rename]
		set mess "[mc "You must type a name."]"
	    }
	    {^[.]{1,2}$} {
		set title "[mc "Invalid name"]"
		set mess "[mc "\"%1\$s\" is invalid.  You must type a valid name." $name]"
	    }
	    {[\\/:*?"<>|]} {
		set title "[mc "Invalid characters"]"
		set mess "[mc "A filename cannot contain any of the following characters:\n\\/:*?\"<>|"]"
	    }
	    default {
		if [file exists $full_path] {
		    set title "[mc "File or folder already exists"]"
		    set mess "[mc "Cannot rename \"%1\$s\" to \"%2\$s.\"\nThe file or folder already exists.  Please specify a different name." $prev_name $name]"
		} else {set badname 0}
	    }
	}

	if !$badname {
	    if [catch {file rename -force -- [::tk::dialog::file::JoinFile $dialogData(selectPath) $prev_name] $full_path} res] {
		set badname 1
		set title [mc Error]
		set mess [mc $res]
	    }
	}
	if !$badname {
	    $data(nameCanvas) itemconfigure $tTag -text $name
	    ::tk::IconList_See $w $i
	    foreach {text size type mtime} $fileList($item) break
	    if {[file type $full_path] == "file"} {set type [string trimleft [file extension $name] .]}	    
	    set fileList($item) [list $name $size $type $mtime]
	    if {$data(viewMethod) == "Details"} {
		$data(typeCanvas) itemconfigure item$item -text $type
	    }
	} else {
	    $data(nameCanvas) itemconfigure $tTag -text $prev_name
	    ::tk::IconList_Selection $w set $i
	    tk_messageBox -type ok -parent $w -icon warning -title $title -message $mess
	    bindtags $data(nameCanvas) $tmptags
	    ::tk::dialog::file::RenameCmd $w
	    return
	}
    }
    ::tk::IconList_Selection $w set $i
    ::tk::IconList_Selection $w anchor $i
    bindtags $data(nameCanvas) $tmptags
}

proc ::tk::dialog::file::ViewDropdown {w} {
    upvar ::tk::dialog::file::[winfo name $w] dialogData

    if {![info exists dialogData(viewDropdown)] || ![winfo exists $dialogData(viewDropdown)]} {
	set dialogData(viewDropdown) [menu $dialogData(viewBtn).vdrop -tearoff 0 -relief raised -bd 2]
	$dialogData(viewDropdown) add radiobutton -label [mc List] -variable ::tk::${dialogData(icons)}(viewMethod) -value List \
		-command [list ::tk::dialog::file::ViewMethod $dialogData(icons)]
	$dialogData(viewDropdown) add radiobutton -label [mc Details] -variable ::tk::${dialogData(icons)}(viewMethod) -value Details \
		-command [list ::tk::dialog::file::ViewMethod $dialogData(icons)]
    }

    set X [winfo rootx $dialogData(viewBtn)]
    set Y [winfo rooty $dialogData(viewBtn)]
    set h [winfo height $dialogData(viewBtn)]
    set Y [expr {$Y + $h}]
    $dialogData(viewBtn) configure -relief sunken
    tk_popup $dialogData(viewDropdown) $X $Y
    if $dialogData(BWidget) {
	$dialogData(viewBtn) configure -relief link
    } else {$dialogData(viewBtn) configure -relief raised}

}

proc ::tk::dialog::file::CopyCutCmd {w method} {
    upvar ::tk::dialog::file::[winfo name $w] dialogData
    upvar ::tk::$dialogData(icons) data

    set filenames {}
    $data(nameCanvas) dtag cut cut
    foreach item [::tk::IconList_Curselection $dialogData(icons)] {
	if {$method == "cut"} {$data(nameCanvas) addtag cut withtag "item$item && icon"}
	lappend filenames [::tk::IconList_Get $dialogData(icons) $item]
    }
    set dialogData(ClipboardFiles) [list $method $dialogData(selectPath) $filenames]
    ::tk::IconList_UpdateIcons $dialogData(icons)
}

proc ::tk::dialog::file::CheckFileClipboard {w} {
    upvar ::tk::dialog::file::[winfo name $w] dialogData

    if {![info exists dialogData(ClipboardFiles)] || ([llength $dialogData(ClipboardFiles)] != 3) ||
		([set method [lindex $dialogData(ClipboardFiles) 0]] != "cut" &&
		$method != "copy")} {
	set dialogData(ClipboardFiles) {}
	return {}
    }
    return $method
}

proc ::tk::dialog::file::PasteCmd {w} {
    upvar ::tk::dialog::file::[winfo name $w] dialogData
    upvar ::tk::$dialogData(icons) data
    variable ::tk::Priv

    set method [CheckFileClipboard $w]
    if {$method == ""} return
    set dir [lindex $dialogData(ClipboardFiles) 1]
    set wd $dialogData(selectPath)
    if {$method == "cut" && $dir == $wd} {
	set dialogData(ClipboardFiles) {}
	$data(nameCanvas) dtag cut cut
	::tk::IconList_UpdateIcons $dialogData(icons)
	return
    }

    SetBusy 1

    ::tk::IconList_Selection $dialogData(icons) clear 0 end
    foreach file [lindex $dialogData(ClipboardFiles) 2] {
	set f [::tk::dialog::file::JoinFile $wd $file]
	if [file exists $f] {
	    for {set i 1} {[file exists [set f [::tk::dialog::file::JoinFile $wd Copy${i}of_$file]]]} {incr i} {}
	}
	if [catch {file copy -- [::tk::dialog::file::JoinFile $dir $file] $f} res] {
	    tk_messageBox -type ok -parent $dialogData(icons) -icon warning -title [mc Error] -message [mc $res]
	} else {
	    if {$method == "cut"} {file delete -force -- [::tk::dialog::file::JoinFile $dir $file]}
	    if [::tk::dialog::file::IsDirectoryToUs $f] {
		set i [::tk::IconList_Add $dialogData(icons) $Priv(folderImage) [file tail $f] dir now]
	    } elseif {[file isdirectory $f] && $dialogData(-dir_leaf_image) != ""} {
		set i [::tk::IconList_Add $dialogData(icons) $dialogData(-dir_leaf_image) [file tail $f] dir_leaf now]
	    } else {
		set i [::tk::IconList_Add $dialogData(icons) $Priv(fileImage) [file tail $f] file now]
	    }
	    ::tk::IconList_Selection $dialogData(icons) set $i
	    if ![info exists j] {::tk::IconList_Selection $dialogData(icons) anchor $i; set j 1}
	    update idletasks
	}
    }
    if {$method == "cut"} {set dialogData(ClipboardFiles) {}}

    # turn off the busy cursor.
    #
    SetBusy 0
}

proc ::tk::AlterImage {im type} {

    switch -exact $type {
	cut {set r 120; set g 120; set b 120}
	select {set r 0; set g 16; set b 48}
	default {return {}}
    }
    set h [image height $im]
    set w [image width $im]
    set im2 [image create photo -height $h -width $w]
    for {set y 0} {$y < $h} {incr y} {
	for {set x 0} {$x < $w} {incr x} {
	    set rgb [$im get $x $y]
	    # We must use "0 0 0" for blank. Use "4 4 4" for black in the input image
	    # It would be better if "rgb" returned "" or "-1 -1 -1" for blank pixels
	    if {[string equal $rgb "0 0 0"]} continue
	    set color #
	    append color [format %02X [expr {int(0.5 * [lindex $rgb 0] + $r)}]]
	    append color [format %02X [expr {int(0.5 * [lindex $rgb 1] + $g)}]]
	    append color [format %02X [expr {int(0.5 * [lindex $rgb 2] + $b)}]]
	    $im2 put $color -to $x $y
	}
    }
    return $im2
}

proc ::tk::IconList_UpdateIcons {w} {
    upvar ::tk::dialog::file::[lindex [split $w .] end-1] dialogData
    upvar ::tk::$w data
    variable ::tk::Priv

    $data(nameCanvas) dtag sel sel
    foreach item $data(selection) {
	$data(nameCanvas) addtag sel withtag "item$item && icon"
    }
    $data(nameCanvas) itemconfigure "icon && dir && !sel && !cut" -image $Priv(folderImage)
    $data(nameCanvas) itemconfigure "icon && file && !sel && !cut" -image $Priv(fileImage)
    $data(nameCanvas) itemconfigure "cut && dir" -image $Priv(folderCutImage)
    $data(nameCanvas) itemconfigure "cut && file" -image $Priv(fileCutImage)
    $data(nameCanvas) itemconfigure "sel && dir && !cut" -image $Priv(folderSelectImage)
    $data(nameCanvas) itemconfigure "sel && file && !cut" -image $Priv(fileSelectImage)

    if {$dialogData(dir_leaf) && $dialogData(-dir_leaf_image) != ""} {
	$data(nameCanvas) itemconfigure "icon && dir_leaf && !sel && !cut" -image $dialogData(-dir_leaf_image)
	$data(nameCanvas) itemconfigure "cut && dir_leaf" -image $dialogData(dir_leaf_CutImage)
	$data(nameCanvas) itemconfigure "sel && dir_leaf && !cut" -image $dialogData(dir_leaf_SelectImage)
    }
}

proc ::tk::dialog::file::GetDrives {w} {
    upvar ::tk::dialog::file::[winfo name $w] data
    global env tcl_platform

#    if [info exists data(drives)] return
    set data(drives) {}
    if {[info exists env(USERPROFILE)] && [file exists $env(USERPROFILE)/Desktop]} { 
	regsub -all {\\} $env(USERPROFILE) / profile
	lappend data(drives) [list Desktop $profile/Desktop]
    }
    if [string match *win* [string tolower $tcl_platform(os)]]	{
	eval lappend data(drives) [file volume]
    }
    ::tk::dialog::file::UpdateSelectPathList $w
}

proc ::tk::dialog::file::UpdateSelectPathList {w} {
    set dataName [winfo name $w]
    upvar ::tk::dialog::file::$dataName data

    set list ""
    set dir ""
    foreach subdir [file split $data(selectPath)] {
	set dir [::tk::dialog::file::JoinFile $dir $subdir]
	lappend list $dir
    }

    if [info exists data(drives)] {
	foreach drname $data(drives) {
	    if {[llength $drname] > 1} {
		set drdir [lindex $drname 1]
		set drname [lindex $drname 0]
		set data(drive_name_maps_to,$drname) $drdir
	    }
	    lappend list $drname
	}
	if {[set i [lsearch [lrange $list 1 end] [string toupper [lindex $list 0]]]] >= 0} {
	    incr i
	    set list [lreplace $list $i $i]
	}
    }

    if $data(BWidget) {
	$data(dirMenuBtn) configure -values $list
    } else {
	$data(dirMenu) delete 0 end
	set var [format %s(selectPath) ::tk::dialog::file::$dataName]
	foreach path $list {
	    set where $path
	    if [info exists data(drive_name_maps_to,$path)] {
		set where $data(drive_name_maps_to,$path)
	    }
	    $data(dirMenu) add command -label $path -command [list set $var $where]
	}
    }
}

proc ::tk::dialog::file::SetBusy {value} {
    variable busyWidget

    # Set the grab on a bottom-level widget that has no pointer bindings (a label widget)
    # This will block all pointer events
    # Also configure the cursor on that widget as the "watch"
    if $value {set value grab} else {set value release}
    ::tk::SafeGlobalGrab $value $busyWidget watch
}

#  This manages the grab and release to return the grab to the last widget that had it
#  It also allows you to set a cursor for the whole screen
proc ::tk::SafeGlobalGrab {action w {cursor ""}} {
    upvar ::tk::Grab($w) data

    if {$action == "grab" && [grab status $w] == "none"} {
	set data {}
	set oldGrab [grab current $w]
	lappend data $oldGrab
	if [winfo exists $oldGrab] {
	    lappend data [grab status $oldGrab]
	} else {lappend data {}}
	set cur [$w cget -cursor]
	lappend data $cur
	if {$cursor == ""} {set cursor $cur}
	if ![catch {grab -global $w}] {
	    $w configure -cursor $cursor
	    update idletasks
	} else {
	    unset data
	}
    } elseif {$action == "release" && [grab status $w] != "none"} {
	if ![info exists data] {
	    grab release $w
	    return
	}
	foreach {oldGrab oldStatus oldCursor} $data break
	unset data
	if {[winfo exists $oldGrab] && [winfo ismapped $oldGrab]} {
	    catch {
		if {[string equal $oldStatus "global"]} {
		    grab -global $oldGrab
		} else {
		    grab $oldGrab
		}
	    }
	} else {grab release $w}
	$w configure -cursor $oldCursor
	update idletasks
    }
}

proc ::tk::dialog::file::GetRecentSelections {w {just_read 0}} {
    upvar ::tk::dialog::file::[winfo name $w] data
    variable recentSelections

    if {[info exists recentSelections(file)] && [file readable $recentSelections(file)]} {
	set recentSelections(list) {}
	set fp [open $recentSelections(file) r]
	while {![eof $fp]} {
	    set f [string trim [gets $fp]]
	    if {$f != ""} {lappend recentSelections(list) $f}
	}
	close $fp
    }

    if {$just_read || ![info exists recentSelections(list)]} return

    switch [winfo class $w] {
	TkChooseDir {set type dir}
	TkFDialog {set type file}
	default {return}
    }

    set max_type 10
    set values {}
    set num 0
    foreach f $recentSelections(list) {
	switch $type {
	    dir {if ![IsDirectoryToUs $f] continue}
	    file {
		if [IsDirectoryToUs $f] continue
		if {[info exists data(dir_leaf)] && $data(dir_leaf) && [file isfile $f]} continue
		set found 0
		set tail [file tail $f]
		foreach pattern $data(filter) {
		    if [string match $pattern $tail] {set found 1; break}
		}
		if {$data(filter) != "" && !$found} continue
	    }
	}
	lappend values $f
	if {[incr num] >= $max_type} break
    }
    $data(ent) configure -values $values -height [expr {$num + 1}]
}

proc ::tk::dialog::file::PickRecentSelection {w} {
    upvar ::tk::dialog::file::[winfo name $w] data

    set path [$data(ent) cget -text]
    if {$data(-pick_func) != ""} {
	eval $data(-pick_func) [list $path]
    }    
    $data(ent).e xview end
}

proc ::tk::dialog::file::SaveRecentSelections {w addfiles} {
    variable recentSelections

    set max_type 10
    GetRecentSelections $w 1

    if ![info exists recentSelections(list)] {set recentSelections(list) ""}
    set i [expr {[llength $addfiles] - 1}]
    set pass1_done 0
    for {} {$i >= 0} {incr i -1} {
	set new_file [lindex $addfiles $i]
	set n_ext [file extension $new_file]
	if [regexp {^.[0-9]+$} $n_ext] {set n_ext __dig_}
	set nd [file isdirectory $new_file]
	if {$n_ext != ""} {set $n_ext 0} else {set folder 0; set file 0}
	set tmp_file_list [list $new_file]
	foreach old_file $recentSelections(list) {
	    if {[string equal $new_file $old_file]} continue
	    if {!$pass1_done && ![file exists $old_file]} continue
	    set od [file isdirectory $old_file]
	    if {($nd && $od) && ([incr folder] >= $max_type)} continue
	    set o_ext [file extension $old_file]
	    if [regexp {^.[0-9]+$} $o_ext] {set o_ext __dig_}
	    if {$n_ext == $o_ext} {
		if {$n_ext == ""} {
		    if {(!$nd && !$od) && ([incr file] >= $max_type)} continue
		} elseif {[incr $n_ext] >= $max_type} continue
	    }
	    lappend tmp_file_list $old_file
	}
	set recentSelections(list) $tmp_file_list
	set pass1_done 1
    }
    if {![info exists recentSelections(file)] || ([file exists $recentSelections(file)] &&
		![file writable $recentSelections(file)])} return
    if [catch {open $recentSelections(file) w} fp] return
    foreach file $recentSelections(list) {puts $fp $file}
    close $fp
}

proc ::tk::dialog::file::ViewMethod {w} {
    upvar ::tk::$w data
    upvar ::tk::$w:fileList fileList
    variable ::tk::Priv

    set end [expr {[lindex [grid size $data(bottomCanvasFrame)] 0] - 1}]
    if {$data(viewMethod) == "List"} {
	grid forget $data(detailButtons)
	grid columnconfigure $data(bottomCanvasFrame) 0 -weight 1
	grid columnconfigure $data(bottomCanvasFrame) $end -weight 0
	foreach win [lreplace $data(canvasNames) 0 0] {
	    $data(${win}Canvas) configure -width 0
	}

	::tk::IconList_Arrange $w
    } elseif {$data(viewMethod) == "Details"} {
	set incrwidth [expr {2 * [$data(detailButtons) cget -bd] + \
			2 * [$data(detailButtons) cget -highlightthickness]}]
	set widths [list 200 100 100 150]
	foreach i [$data(detailButtons) visible] {
	    set win [lindex $data(canvasNames) $i]
	    set width [lindex $widths $i]
	    $data(detailButtons) itemconfigure $i -width $width
	    incr width $incrwidth
	    $data(${win}Canvas) configure -width $width
	}

	grid columnconfigure $data(bottomCanvasFrame) 0 -weight 0
	grid columnconfigure $data(bottomCanvasFrame) $end -weight 1
	::tk::IconList_Hscroll $w moveto 0.0
	grid $data(detailButtons) -row 0 -sticky wen

	foreach item $data(list) {
	    foreach {name size type mtime} $fileList($item) break
	    if {$type != "link (broken)"} {
		set modified [clock format $mtime -format "%m/%d/%Y %I:%M:%S %p"]
		set size [::tk::dialog::file::FormatSize $size]
	    } else {set modified ""; set size ""}
	    foreach win [lrange $data(canvasNames) 1 end] {
		if {[$data(${win}Canvas) find withtag item$item] != ""} continue
		set text [set $win]
		if {$text == ""} continue
		$data(${win}Canvas) create text  0 0 -text $text -anchor nw \
			-font $data(font) -fill $data(-fg) -tags item$item
	    }
	}
	set order [::tk::IconList_GetOrderButton $w]
	eval ::tk::IconList_ReArrange $w $order
    }
}

proc ::tk::IconList_Hscroll {w args} {
    upvar ::tk::$w data

    if {$data(viewMethod) == "Details"} {
	eval $data(detailButtons) view $args
    }
    eval $data(bottomCanvas) xview $args
}

proc ::tk::IconList_ResizeColumns {w args} {
    upvar ::tk::$w data

    foreach {i width} $args break
    set win [lindex $data(canvasNames) $i]
    $data(${win}Canvas) configure -width $width

    ::tk::IconList_Arrange $w -only_resize 1
}

proc ::tk::IconList_ShowColumns {w args} {
    upvar ::tk::$w data

    foreach {i width} $args break
    set win [lindex $data(canvasNames) $i]
    $data(${win}Canvas) configure -width $width

    ::tk::IconList_Arrange $w -only_resize 1
}

proc ::tk::IconList_ReArrange {w arrange_method {order increasing} {arg ""}} {
    upvar ::tk::$w data

    if {$order == ""} {
	if {![info exists data(listOrder)] || $data(listOrder) == ""} {set data(listOrder) increasing}
    } else {set data(listOrder) $order}
    set data(arrangeMethod) [lindex $data(canvasNames) $arrange_method]
    if {$arg == "setbutton"} {$data(detailButtons) configure -orderbutton [list $arrange_method $data(listOrder)]} \
    else {::tk::IconList_Arrange $w}
}

proc ::tk::IconList_ListSort {w} {
    upvar ::tk::$w data

    switch $data(arrangeMethod) {
	name {set dMeth dictionary; set fMeth dictionary; set dInd 0; set fInd 0}
	size {set dMeth dictionary; set fMeth integer; set dInd 0; set fInd 1}
	type {set dMeth dictionary; set fMeth dictionary; set dInd 0; set fInd 2}
	modified {set dMeth integer; set fMeth integer; set dInd 3; set fInd 3}
	default {set data(list) [concat $data(dList) $data(fList)]; return}
    }

    set data(dList) [lsort -command "::tk::IconList_ListSortCommand $w $dMeth $dInd $data(listOrder)" $data(dList)]
    set data(fList) [lsort -command "::tk::IconList_ListSortCommand $w $fMeth $fInd $data(listOrder)" $data(fList)]

    if {$data(listOrder) == "increasing"} {
	set data(list) [concat $data(dList) $data(fList)]
    } else {
	set data(list) [concat $data(fList) $data(dList)]
    }
}

proc ::tk::IconList_ListSortCommand {w method index order a b} {
    upvar ::tk::$w:fileList fileList

    set a [lindex $fileList($a) $index]
    set b [lindex $fileList($b) $index]
    if {$order == "decreasing"} {set t $a;	set a $b;	set b $t}
    switch $method {
	dictionary {return [string compare -nocase $a $b]}
	integer {return [expr {$a<$b ? -1 : $a>$b}]}
    }
}

proc ::tk::dialog::file::FormatSize {size} {
    if {$size == ""} return
    set size [expr {double($size)}]
    set units [list bytes Kb Mb Gb Tb Pb Eb Zb Yb]
    set len [expr {[string length $size] -2}]
    set triples [expr {$len/3}]
    if {$triples*3 == $len} {incr triples -1}
    set units [lindex $units $triples]
    set size [expr {round($size/pow(10,$triples*3))}]
    return "$size $units"
}

proc ::tk::IconList_GetOrderButton {w} {
    upvar ::tk::$w data
    return [$data(detailButtons) cget -orderbutton]
}

proc ::tk::dialog::file::Properties {w {method current_dir}} {
    upvar ::tk::dialog::file::[winfo name $w] dialogData
    upvar ::tk::$dialogData(icons) data
    upvar ::tk::$dialogData(icons):fileList fileList

#    if {[string equal [info commands tk_fileProperties] ""]} return
    if {$method == "active"} {
	set i [::tk::IconList_Index $dialogData(icons) active]
	if {$i<0} return
	set item [lindex $data(list) $i]
	set file [::tk::IconList_Get $dialogData(icons) $item]
	set full_file [::tk::dialog::file::JoinFile $dialogData(selectPath) $file]
	set new_file [tk_fileProperties $full_file -parent $w]
	if {$full_file != $new_file && $new_file != ""} {
	    set name [file tail $new_file]
	    $data(nameCanvas) itemconfigure "item$item && text" -text $name
	    foreach {text size type mtime} $fileList($item) break
	    if {[file type $new_file] == "file"} {set type [string trimleft [file extension $name] .]}	    
	    set fileList($item) [list $name $size $type $mtime]
	    if {$data(viewMethod) == "Details"} {
		$data(typeCanvas) itemconfigure item$item -text $type
	    }
	}
    } elseif {$method == "current_dir"} {
	set path [tk_fileProperties $dialogData(selectPath) -parent $w]
	if {$path != $dialogData(selectPath) && $path != ""} {
	    ::tk::dialog::file::SetPathSilently $w $path
	    set dialogData(selectPathHistory) [lreplace $dialogData(selectPathHistory) end end $path]
	}
    }
}

proc ::tk::IconList_Release1 {w} {
    upvar ::tk::$w data

    if [info exists data(selboxstart)] {
#	unset data(selboxstart)
	$data(nameCanvas) delete selbox
    }
    ::tk::CancelRepeat
}

