# 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 Win95(TM). The user can navigate
#	the directories by clicking on the folder icons or by
#	selecting the "Directory" 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.64 2004/01/21 19:03:37 escolano 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.
#

if { ![llength [info command .central.s]] } {
    set ::GIDDEFAULT $::env(GIDDEFAULT)
}

# done already in tclfile-opengl.tcl
# if { $::tcl_platform(platform) eq "windows" } {
#     load [file join $::GIDDEFAULT tclreg11.dll] registry
# }

proc font:reqwidth {font text {w ""}} {
     for {set i 1} {[winfo exists $w.label-$i]} {incr i} {}
     set l $w.label-$i
     label $l -bd 0 -padx 0 -pady 0 -highlightthickness 0 \
	 -font $font \
	 -text $text
     set width  [winfo reqwidth  $l]
     set height [winfo reqheight $l]
     destroy $l
     return $width
 }

proc ::tk::shellfolder { name } {
    variable folders

    if {[info exists folders($name)]} {
	set folders($name)
    } else {
	set folders($name) [registry get \
				{HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders} \
				$name]
    }
}

#----------------------------------------------------------------------
#
#		      I C O N   L I S T
#
# This is a pseudo-widget that implements the icon list inside the 
# ::tk::dialog::file:: dialog box.
#
#----------------------------------------------------------------------

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

proc ::tk::IconList_Index {w i} {
    upvar #0 ::tk::$w data
    upvar #0 ::tk::$w:itemList itemList
    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$" {
	    return $data(index,active)
	}
	"^anchor$" {
	    return $data(index,anchor)
	}
	"^end$" {
	    return [llength $data(list)]
	}
	"@-?[0-9]+,-?[0-9]+" {
	    foreach {x y} [scan $i "@%d,%d"] {
		break
	    }
	    set item [$data(canvas) find closest $x $y]
	    return [lindex [$data(canvas) itemcget $item -tags] 1]
	}
    }
}

proc ::tk::IconList_Selection {w op args} {
    upvar ::tk::$w data
    switch -exact -- $op {
	"anchor" {
	    if { [llength $args] == 1 } {
		set data(index,anchor) [tk::IconList_Index $w [lindex $args 0]]
	    } else {
		return $data(index,anchor)
	    }
	}
	"clear" {
	    if { [llength $args] == 2 } {
		foreach {first last} $args {
		    break
		}
	    } elseif { [llength $args] == 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 ind 0
	    foreach item $data(selection) {
		if { $item >= $first } {
		    set first $ind
		    break
		}
	    }
	    set ind [expr {[llength $data(selection)] - 1}]
	    for {} {$ind >= 0} {incr ind -1} {
		set item [lindex $data(selection) $ind]
		if { $item <= $last } {
		    set last $ind
		    break
		}
	    }

	    if { $first > $last } {
		return
	    }
	    set data(selection) [lreplace $data(selection) $first $last]
	    event generate $w <<ListboxSelect>>
	    IconList_DrawSelection $w
	}
	"includes" {
	    set index [lsearch -exact $data(selection) [lindex $args 0]]
	    return [expr {$index != -1}]
	}
	"set" {
	    if { [llength $args] == 2 } {
		foreach {first last} $args {
		    break
		}
	    } elseif { [llength $args] == 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
	    }
	    for {set i $first} {$i <= $last} {incr i} {
		lappend data(selection) $i
	    }
	    set data(selection) [lsort -integer -unique $data(selection)]
	    event generate $w <<ListboxSelect>>
	    IconList_DrawSelection $w
	}
    }
}

proc ::tk::IconList_Curselection {w} {
    upvar ::tk::$w data
    return $data(selection)
}

proc ::tk::IconList_DrawSelection {w} {
    upvar ::tk::$w data
    upvar ::tk::$w:itemList itemList

    $data(canvas) delete selection
    foreach item $data(selection) {
	set rTag [lindex [lindex $data(list) $item] 2]
	foreach {iTag tTag text serial} $itemList($rTag) {
	    break
	}
	
	set bbox [$data(canvas) bbox $tTag]
        $data(canvas) create rect $bbox -fill \#a0a0ff -outline \#a0a0ff \
		-tags selection
    }
    $data(canvas) lower selection
    return
}

proc ::tk::IconList_Get {w item} {
    upvar ::tk::$w data
    upvar ::tk::$w:itemList itemList
    set rTag [lindex [lindex $data(list) $item] 2]
    foreach {iTag tTag text serial} $itemList($rTag) {
	break
    }
    return $text
}

# ::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"}
	{-checkrenamecmd "" "" ""}
	{-menucontext "" "" ""}
    }

    # 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
    set data(sbar)   [scrollbar $w.sbar -orient horizontal \
	-highlightthickness 0 -takefocus 0]
    set data(canvas) [canvas $w.canvas -bd 1 -relief sunken \
	-width 400 -height 120 -takefocus 1]

    if { [llength $data(-menucontext)] } {
	set data(menu_context) [menu $data(canvas).mc -tearoff 0 -bd 1 -activeborder 0]
	foreach i $data(-menucontext) {
	    if {([llength $i] == 1) && ($i eq "---") } {
		$data(menu_context) add separator
		continue
	    }
	    array set entry_info {
		-cmd ""
		-label ""
		-image ""
		-bitmap ""
		-bind ""
	    }
	    array set entry_info $i
	    $data(menu_context) add command -command $entry_info(-cmd)  -hidemargin true
	    foreach opt {image label bitmap} {
		set has_${opt} 0
		if { $entry_info(-$opt) ne "" } {
		    set has_${opt} 1
		    $data(menu_context) entryconf end -$opt $entry_info(-$opt)
		}
	    }
	    if { $has_label && ($has_image || $has_bitmap) } {
		$data(menu_context) entryconf end -compound left
	    }
	    if {$entry_info(-bind) ne "" && $entry_info(-cmd) ne ""} {
		bind $data(canvas) $entry_info(-bind) +$entry_info(-cmd)
	    }
	}
	bind $data(canvas) <3>              [list tk::IconList_Btn3 $w %X %Y %x %y]
    }
    
    pack $data(sbar) -side bottom -fill x -padx 2
    pack $data(canvas) -expand yes -fill both

    $data(sbar) config -command [list $data(canvas) xview]
    $data(canvas) config -xscrollcommand [list $data(sbar) set]
#	-background [ $w cget -background]
#	-background {white smoke}

    set data(edit) [entry $data(canvas).edit -selectbackground \#a0a0ff \
			-bg [$data(canvas) cget -bg] \
			-relief solid -bd 1 -highlightthickness 0 \
			-textvariable ::tk::${w}(edit,textvar)]
    set data(edit,undo) ""
    set data(edit,isactive) 0
    bind $data(edit) <KeyPress-Return> "[list ::tk::IconList_TextAccept $w] ; break"
    bind $data(edit) <KeyPress-Escape> "[list ::tk::IconList_TextEscape $w] ; break"
    bind $data(edit) <FocusOut>        "[list ::tk::IconList_TextAccept $w] ; break"

    # 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(noScroll) 1
    set data(selection) {}
    set data(index,anchor) ""

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

    bind $data(canvas) <1>		[list tk::IconList_Btn1 $w %x %y]
    bind $data(canvas) <B1-Motion>	[list tk::IconList_Motion1 $w %x %y]
    bind $data(canvas) <B1-Leave>	[list tk::IconList_Leave1 $w %x %y]
    bind $data(canvas) <Control-1>	[list tk::IconList_CtrlBtn1 $w %x %y]
    bind $data(canvas) <Shift-1>	[list tk::IconList_ShiftBtn1 $w %x %y]
    bind $data(canvas) <B1-Enter>	[list tk::CancelRepeat]
    bind $data(canvas) <ButtonRelease-1> [list tk::CancelRepeat]
    #bind $data(canvas) <Double-ButtonRelease-1>
    bind $data(canvas) <Double-1> \
	    [list tk::IconList_Double1 $w %x %y]

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

    bind $data(canvas) <FocusIn>	[list tk::IconList_FocusIn $w]
    bind $data(canvas) <FocusOut>	[list tk::IconList_FocusOut $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} {
    upvar ::tk::$w data
    variable ::tk::Priv

    if {![winfo exists $w]} return
    set x $Priv(x)
    set y $Priv(y)

    if {$data(noScroll)} {
	return
    }
    if {$x >= [winfo width $data(canvas)]} {
	$data(canvas) xview scroll 1 units
    } elseif {$x < 0} {
	$data(canvas) xview scroll -1 units
    } elseif {$y >= [winfo height $data(canvas)]} {
	# do nothing
    } elseif {$y < 0} {
	# do nothing
    } else {
	return
    }

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

# 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:textList textList

    $data(canvas) delete all
    catch {unset data(selected)}
    catch {unset data(rect)}
    catch {unset data(list)}
    catch {array unset itemList}
    catch {array unset textList}
    set data(maxIW) 1
    set data(maxIH) 1
    set data(maxTW) 1
    set data(maxTH) 1
    set data(numItems) 0
    set data(curItem)  {}
    set data(noScroll) 1
    set data(selection) {}
    set data(index,anchor) ""
    $data(sbar) set 0.0 1.0
    $data(canvas) xview moveto 0

    # remake the edit item

    $data(canvas) create window -100 -100 -anchor "nw" -window $data(edit) -tags edit
    set data(edit,request) 0
}


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

    if { $x < 0 || $x > [winfo width $data(edit)] ||
	 $y < 0 || $y > [winfo height $data(edit)] } {
	IconList_UnmapRename $w
    }
}

# Invoked when changing an item's text and one of the events occur:
# <KeyPress-Return> or <FocusOut>

proc ::tk::IconList_TextAccept {w} {
    upvar ::tk::$w data
    upvar ::tk::$w:itemList itemList
    upvar ::tk::$w:textList textList

    # verify if this is a valid text

    if { !$data(edit,isactive) } {
	return
    }

    set item $data(item_edited)
    if { [string compare $data(edit,textvar) $data(edit,undo)] } {
	set status_rename [eval $data(-checkrenamecmd) [list $data(edit,undo)] [list $data(edit,textvar)]]

	if { ![lindex $status_rename 0] } {
	    # show the message returned
	    tk_messageBox -type ok -parent $w -message [lindex $status_rename 1]  \
		-icon warning -title [_ "Error"]
	    focus -force $data(edit)
	    return
	} else {
	    set item $data(item_edited)
	    # change the text info
	    set item_info [lindex $data(list) $item]
	    if { [llength $status_rename] > 1 } {
		set iTag [lindex $item_info 0]
		$data(canvas) itemconfigure $iTag -image [lindex $status_rename 1]
		foreach {x1 y1 x2 y2} [$data(canvas) 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
		}
	    }
	    set tTag [lindex $item_info 1]
	    $data(canvas) itemconfigure $tTag -text $data(edit,textvar)
	    foreach {x1 y1 x2 y2} [$data(canvas) 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 rTag [lindex $item_info 2]
	    set itemList($rTag) [lreplace $itemList($rTag) 2 2 $data(edit,textvar)]
	    set textList($item) [string tolower $data(edit,textvar)]
	    set data(edit,undo) ""
	}
    }	    
 
   # hide the edit box
    IconList_UnmapRename $w

    tk::IconList_Arrange $w
    ::tk::IconList_Selection $w clear 0 end
    ::tk::IconList_Selection $w set $item
    ::tk::IconList_Selection $w anchor $item
    ::tk::IconList_DrawSelection $w 
}

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

    bind $data(edit) <Any> ""
    grab release $data(edit)

    #place forget $data(edit)
    $data(canvas) coords edit -100 -100

    set data(edit,isactive) 0
    focus -force $data(edit,oldfocus)
    catch {grab $data(edit,oldgrab)}
    bind $data(edit) <Any-Button> $data(edit,oldbind)
}

# Invoked when changing an item's text and <KeyPress-Escape> occur:
#

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

    set data(edit,undo) ""
    IconList_UnmapRename $w
    tk::IconList_Arrange $w
    ::tk::IconList_Selection $w clear 0 end
    set item $data(item_edited)
    ::tk::IconList_Selection $w set $item
    ::tk::IconList_Selection $w anchor $item
    ::tk::IconList_DrawSelection $w 
}

proc ::tk::IconList_GetText {w item} {
    upvar ::tk::$w data
    upvar ::tk::$w:itemList itemList
    upvar ::tk::$w:textList textList

    if {$item == -1} {
	set item $data(sim,id)
    }
    set rTag [lindex [lindex $data(list) $item] 2]
    foreach {iTag tTag text serial} $itemList($rTag) {
	break
    }
    return $text
}

# Change the text of an item
#

proc ::tk::IconList_RenameText {w item} {
    upvar ::tk::$w data
    upvar ::tk::$w:itemList itemList
    upvar ::tk::$w:textList textList

    if {$item == -1} {
	set item $data(sim,id)
    }
    set rTag [lindex [lindex $data(list) $item] 2]
    set data(item_edited) $item
    foreach {iTag tTag text serial} $itemList($rTag) {
	break
    }
    foreach {x1 y1 x2 y2} [$data(canvas) bbox $tTag] {
	break
    }
    set data(edit,textvar) $text
    set data(edit,undo) $text
    set lstr [string length $text]
    $data(edit) configure -font $data(font) -width $lstr
     set lbbox [expr $x2-$x1]
     while { [winfo reqwidth $data(edit)] < $lbbox } {
 	incr lstr
 	$data(edit) configure -width $lstr
     }
    $data(edit) selection range 0 end

    #place $data(edit) -in $data(canvas) -x [$data(canvas) canvasx $x1] -y [$data(canvas) canvasy $y1]
    IconList_See $w $item

    $data(canvas) coords edit $x1 $y1

    set data(edit,isactive) 1
    set data(edit,oldgrab) [grab current]
    grab $data(edit)
    set data(edit,oldfocus) [focus -force $data(edit)]
    set data(edit,oldbind) [bind $data(edit) <Any-Button>]
    bind $data(edit) <Any-Button> +[list ::tk::IconList_RenameAnyHandler $w %x %y]
}

# Adds an icon into the IconList with the designated image and text
#
proc ::tk::IconList_Add {w image items} {
    upvar ::tk::$w data
    upvar ::tk::$w:itemList itemList
    upvar ::tk::$w:textList textList

    foreach text $items {
	set iTag [$data(canvas) create image 0 0 -image $image -anchor nw \
		-tags [list icon $data(numItems) item$data(numItems)]]
	set tTag [$data(canvas) create text  0 0 -text  $text  -anchor nw \
		-font $data(font) \
		-tags [list text $data(numItems) item$data(numItems)]]
	set rTag [$data(canvas) create rect  0 0 0 0 -fill "" -outline "" \
		-tags [list rect $data(numItems) item$data(numItems)]]
	
	foreach {x1 y1 x2 y2} [$data(canvas) 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(canvas) 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
	}
    
	lappend data(list) [list $iTag $tTag $rTag $iW $iH $tW \
		$tH $data(numItems)]
	set itemList($rTag) [list $iTag $tTag $text $data(numItems)]
#	set textList($data(numItems)) [string tolower $text]
	set textList($data(numItems)) $text
	incr data(numItems)
    }
}

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

    if {![info exists data(list)]} {
	if {[info exists data(canvas)] && [winfo exists $data(canvas)]} {
	    set data(noScroll) 1
	    $data(sbar) config -command ""
	}
	return
    }

    set W [winfo width  $data(canvas)]
    set H [winfo height $data(canvas)]
    set pad [expr {[$data(canvas) cget -highlightthickness] + \
	    [$data(canvas) cget -bd]}]
    if {$pad < 2} {
	set pad 2
    }

    incr W -[expr {$pad*2}]
    incr H -[expr {$pad*2}]

    set dx [expr {$data(maxIW) + $data(maxTW) + 8}]
    if {$data(maxTH) > $data(maxIH)} {
	set dy $data(maxTH)
    } else {
	set dy $data(maxIH)
    }
    incr dy 2
    set shift [expr {$data(maxIW) + 4}]

    set x [expr {$pad * 2}]
    set y [expr {$pad * 1}] ; # Why * 1 ?
    set usedColumn 0
    foreach sublist $data(list) {
	set usedColumn 1
	foreach {iTag tTag rTag iW iH tW tH} $sublist {
	    break
	}

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

	$data(canvas) coords $iTag $x                    [expr {$y + $i_dy}]
	$data(canvas) coords $tTag [expr {$x + $shift}]  [expr {$y + $t_dy}]
	$data(canvas) coords $rTag $x $y [expr {$x+$dx}] [expr {$y+$dy}]

	incr y $dy
	if {($y + $dy) > $H} {
	    set y [expr {$pad * 1}] ; # *1 ?
	    incr x $dx
	    set usedColumn 0
	}
    }

    if {$usedColumn} {
	set sW [expr {$x + $dx}]
    } else {
	set sW $x
    }

    if {$sW < $W} {
	$data(canvas) config -scrollregion [list $pad $pad $sW $H]
	$data(sbar) config -command ""
	$data(canvas) xview moveto 0
	set data(noScroll) 1
    } else {
	$data(canvas) config -scrollregion [list $pad $pad $sW $H]
	$data(sbar) config -command [list $data(canvas) xview]
	set data(noScroll) 0
    }

    set data(itemsPerColumn) [expr {($H-$pad)/$dy}]
    if {$data(itemsPerColumn) < 1} {
	set data(itemsPerColumn) 1
    }

    if {$data(curItem) != ""} {
	IconList_Select $w [lindex [lindex $data(list) $data(curItem)] 2] 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 rTag} {
    upvar ::tk::$w data
    upvar ::tk::$w:itemList itemList

    if {$data(noScroll)} {
	return
    }
    set sRegion [$data(canvas) cget -scrollregion]
    if {[string equal $sRegion {}]} {
	return
    }

    if { $rTag < 0 || $rTag >= [llength $data(list)] } {
	return
    }

    set bbox [$data(canvas) bbox item$rTag]
    set pad [expr {[$data(canvas) cget -highlightthickness] + \
	    [$data(canvas) cget -bd]}]

    set x1 [lindex $bbox 0]
    set x2 [lindex $bbox 2]
    incr x1 -[expr {$pad * 2}]
    incr x2 -[expr {$pad * 1}] ; # *1 ?

    set cW [expr {[winfo width $data(canvas)] - $pad*2}]

    set scrollW [expr {[lindex $sRegion 2]-[lindex $sRegion 0]+1}]
    set dispX [expr {int([lindex [$data(canvas) xview] 0]*$scrollW)}]
    set oldDispX $dispX

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

    if {$oldDispX != $dispX} {
	set fraction [expr {double($dispX)/double($scrollW)}]
	$data(canvas) xview moveto $fraction
    }
}

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

    focus $data(canvas)
    set x [expr {int([$data(canvas) canvasx $x])}]
    set y [expr {int([$data(canvas) canvasy $y])}]
    set i [IconList_Index $w @${x},${y}]
    if {$i==""} return
    # verify if there is only one selected
    if { !$sim && [llength $data(selection)] == 1 && [lindex $data(selection) 0] == $i } {
	# enter in rename mode
	set data(edit,request) 1
	set data(edit,afterId) [after 300 ::tk::IconList_RenameText $w $i]
    } else {
	IconList_Selection $w clear 0 end
	IconList_Selection $w set $i
	IconList_Selection $w anchor $i
	# this is only needed when the WM is configure to change the
	# focus as the mouse move
#	if {$sim} {
	    set data(sim,id) $i
#	}
    }
}

proc ::tk::IconList_CtrlBtn1 {w x y} {
    upvar ::tk::$w data
    
    if { $data(-multiple) } {
	focus $data(canvas)
	set x [expr {int([$data(canvas) canvasx $x])}]
	set y [expr {int([$data(canvas) canvasy $y])}]
	set i [IconList_Index $w @${x},${y}]
	if {$i==""} return
	if { [IconList_Selection $w includes $i] } {
	    IconList_Selection $w clear $i
	} else {
	    IconList_Selection $w set $i
	    IconList_Selection $w anchor $i
	}
    }
}

proc ::tk::IconList_ShiftBtn1 {w x y} {
    upvar ::tk::$w data
    
    if { $data(-multiple) } {
	focus $data(canvas)
	set x [expr {int([$data(canvas) canvasx $x])}]
	set y [expr {int([$data(canvas) canvasy $y])}]
	set i [IconList_Index $w @${x},${y}]
	if {$i==""} return
	set a [IconList_Index $w anchor]
	if { [string equal $a ""] } {
	    set a $i
	}
	IconList_Selection $w clear 0 end
	IconList_Selection $w set $a $i
    }
}

# Gets called on button-1 motions
#
proc ::tk::IconList_Motion1 {w x y} {
    upvar ::tk::$w data
    variable ::tk::Priv
    set Priv(x) $x
    set Priv(y) $y
    set x [expr {int([$data(canvas) canvasx $x])}]
    set y [expr {int([$data(canvas) canvasy $y])}]
    set i [IconList_Index $w @${x},${y}]
    if {$i==""} return
    IconList_Selection $w clear 0 end
    IconList_Selection $w set $i
}

proc ::tk::IconList_Btn3 {w X Y x y} {
    upvar ::tk::$w data
    
    IconList_Btn1 $w $x $y 1
    tk_popup $data(menu_context) $X $Y 
}

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

    if {$data(edit,request)} {
	# avoid mapping
	set data(edit,request) 0
	after cancel $data(edit,afterId)
    }
    if {[llength $data(selection)]} {
	IconList_Invoke $w
    }
}

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

proc ::tk::IconList_Leave1 {w x y} {
    variable ::tk::Priv

    set Priv(x) $x
    set Priv(y) $y
    IconList_AutoScan $w
}

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

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

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

proc ::tk::IconList_FocusOut {w} {
    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==""} 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)]} {
	return
    }

    set curr [IconList_Curselection $w]
    if { [llength $curr] == 0 } {
	set i 0
    } else {
	set i [IconList_Index $w anchor]
	if {$i==""} 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:textList textList
    
    if {![info exists data(list)]} {
	return
    }

    if {[string equal {} $text]} {
	return
    }

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

    set text [string tolower $text]
    set theIndex -1
    set less 0
    set len [string length $text]
    set len0 [expr {$len-1}]
    set i $start

    # Search forward until we find a filename whose prefix is an exact match
    # with $text
    while {1} {
	# RAMSAN
	set sub [string tolower [string range $textList($i) 0 $len0]]
	if {[string equal $text $sub]} {
	    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 {
    catch {
	namespace import ::tk::msgcat::*
    }
}

# ::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]} {
	destroy $w
	::tk::dialog::file::Create $w TkFDialog
    } else {
	#set data(dirMenuBtn) $w.f1.menu
	#set data(dirMenu) $w.f1.menu.menu
	set data(dirCombo) $w.f1.hcb

	set data(upBtn) $w.f1.up
	set data(icons) $w.icons
	set data(ent) $w.f2.ent
	set data(typeMenuLab) $w.f3.lab
	#set data(typeMenuBtn) $w.f3.menu
	#set data(typeMenu) $data(typeMenuBtn).m
	set data(typeCombo) $w.f3.tcb
	set data(okBtn) $w.f2.ok
	set data(cancelBtn) $w.f3.cancel
	::tk::dialog::file::SetSelectMode $w $data(-multiple)
    }

    # 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 {[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"
    #trace variable data(selectPathCombo) w "::tk::dialog::file::SetPathCombo $w"
    #$data(dirMenuBtn) configure -textvariable ::tk::dialog::file::${dataName}(selectPath)
    #$data(dirCombo) configure -textvariable ::tk::dialog::file::${dataName}(selectPathCombo)

    # Initialize the file types menu
    #
    if {[llength $data(-filetypes)]} {
	#$data(typeMenu) delete 0 end
	set data(typeCombo,filters) {}
	set data(typeCombo,labels) {}
	foreach type $data(-filetypes) {
	    set title  [lindex $type 0]
	    set filter [lindex $type 1]
	    lappend data(typeCombo,labels) $title
	    lappend data(typeCombo,filters) $filter
	    #$data(typeMenu) add command -label $title -command [list ::tk::dialog::file::SetFilter $w $type]
	}
	#$data(typeCombo) configure -values $values

	::tk::dialog::file::SetFilter $w [lindex $data(-filetypes) 0]
	set data(typeCombo,textvar) [lindex $data(typeCombo,labels) 0]
	#$data(typeMenuBtn) config -state normal
	set len_labels [llength $data(typeCombo,labels)]
	$data(typeCombo) configure -state readonly -height [expr $len_labels>5?5:$len_labels]
	$data(typeMenuLab) config -state normal
    } else {
	set data(filter) "*"
	#$data(typeMenuBtn) config -state disabled -takefocus 0
	$data(typeCombo) configure -state disabled -takefocus 0
	$data(typeMenuLab) config -state disabled
    }
    ::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.

    ::tk::PlaceWindow $w widget $data(-parent)
    wm title $w $data(-title)

    # Set a grab and claim the focus too.

    ::tk::SetFocusGrab $w $data(ent)
    $data(ent) delete 0 end
    $data(ent) insert 0 $data(selectFile)
    $data(ent) selection range 0 end
    $data(ent) icursor end

    # 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.

    vwait ::tk::Priv(selectFilePath)

    ::tk::RestoreFocusGrab $w $data(ent) withdraw

    # Cleanup traces on selectPath variable
    #

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

    return $Priv(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 idx {selectPath selectPathCombo} {
	foreach trace [trace vinfo data($idx)] {
	    trace vdelete data($idx) [lindex $trace 0] [lindex $trace 1]
	}
    }

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

    # 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) [_ "Open"]
	} else {
	    set data(-title) [_ "Save As"]
	}
    }

    # 4: set the default directory and selection according to the -initial
    #    settings
    #
    if {$data(-initialdir) != ""} {
	# Ensure that initialdir is an absolute path name.
	if {[file isdirectory $data(-initialdir)]} {
	    set old [pwd]
	    cd $data(-initialdir)
	    set data(selectPath) [pwd]
	    cd $old
	} else {
	    set data(selectPath) [pwd]
	}
    }
    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
    }
}

#RAMSAN adding. Text is beginning of a filename. Tries to find longer

proc ::tk::IconList_ReturnUniqueChar {w text} {
    global tcl_platform
    upvar ::tk::$w data
    upvar ::tk::$w:textList textList
    
    if {![info exists data(list)] || ![info exists textList]} {
	return ""
    }

    if {[string length $text] == 0} {
	return ""
    }

    set start  0

    if { $tcl_platform(platform) == "windows" } {
	set text [string tolower $text]
    }
    set theIndex -1
    set theIndexLast -1
    set less 0
    set len [string length $text]
    set len0 [expr $len-1]
    set i $start

    # Search forward until we find a filename whose prefix is an exact match
    # with $text
    while 1 {
	if { $tcl_platform(platform) == "windows" } {
	    set sub [string tolower [string range $textList($i) 0 $len0]]
	} else {
	    set sub [string range $textList($i) 0 $len0]
	}
	if {[string compare $text $sub] == 0} {
	    if { $theIndex == -1 } {
		set theIndex $i
	    } else { set theIndexLast $i }
	} elseif { $theIndex != -1 } { break }
	incr i
	if {$i == $data(numItems)} {
	    set i 0
	}
	if {$i == $start} {
	    break
	}
    }

    if { $theIndex == -1 } { return "" }
    if { $theIndexLast == -1 } {
	return [string range $textList($theIndex) $len end]
    }
    set leni [string length $textList($theIndex)]
    for { set i $len } { $i < $leni } { incr i } {
	set a [string index $textList($theIndex) $i]
	for { set j [expr $theIndex+1] } { $j <= $theIndexLast } { incr j } {
	    if { $tcl_platform(platform) == "windows" } {
		if { [string comp [string tolower $a]  \
			[string tolower [string index $textList($j) $i]]] != 0 } { 
		    break
		}
	    } else {
		if { [string comp $a  [string index $textList($j) $i]] != 0 } { 
		    break
		}
	    }
	}
	if { $j <= $theIndexLast } { break }
    }
    return [string range $textList($theIndex) $len [expr $i -1]]
}

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

    toplevel $w -class $class
    wm withdraw $w

    # f1: the frame with the directory option menu
    #
    set f1 [frame $w.f1]
    #bind [::tk::AmpWidget label $f1.lab -text "[mc "&Directory:"]" ] <<AltUnderlined>> [list focus $f1.menu]
    bind [::tk::AmpWidget label $f1.lab -text [_ "&Directory"]: ] <<AltUnderlined>> [list focus $f1.hcb]
    
    #set data(dirMenuBtn) $f1.menu
    #set data(dirMenu) [tk_optionMenu $f1.menu [format %s(selectPath) ::tk::dialog::file::$dataName] ""]
    set data(dirList) [list]
    set data(dirFullList) [list]
    set data(dirCombo) [::hugecombo::hugecombo $f1.hcb \
			    -list [format "%s(dirList)" ::tk::dialog::file::$dataName] \
			    -compund 1 -height 7 -rowheight 18 \
			    -state picklist \
			    -bd 1]
    #$data(dirCombo) configure -readonlybackground [$data(dirCombo) cget -bg]
  set entry_cb [$data(dirCombo) component entry]
  $entry_cb conf -bd 1 -insertbackground [$entry_cb cget -bg]
  bind $entry_cb <1> "$data(dirCombo) list open"

  $f1.hcb.t.f configure -bd 1 -relief solid
  $f1.hcb.t.f.vs configure -bd 1 -relief ridge

  bind [$data(dirCombo) component list] <<ListboxSelect>> +[namespace code "SetPathCombo $w"]
  bind [$data(dirCombo) component entry] <Return> +[namespace code "SetPathCombo $w"]
  set data(upBtn) [button $f1.up]
  foreach {fimg idximg} {folder.gif folderImage \
			     folder_h.gif folderhImage \
			     file.gif fileImage \
			     file_h.gif filehImage \
			     upfolder.gif updirImage \
			     newfolder.gif newfolderImage \
			     openfold.gif  openfolderImage \
			     openfold_h.gif openfolderImage \
			     trash.gif trashImage \
			     rename.gif renImage \
			     disk.gif diskImage \
			     home.gif homeImage} {
    if {![info exists Priv($idximg)]} {
      set Priv($idximg) [image create photo -file \
			     [file join $::GIDDEFAULT bitmaps $fimg]]
    }
  }
    if { 0 } {
    if {![info exists Priv(updirImage)]} {
	set Priv(updirImage) [image create bitmap -data {
	    #define updir_width 28
	    #define updir_height 16
	    static char updir_bits[] = {
		0x00, 0x00, 0x00, 0x00, 0x80, 0x1f, 0x00, 0x00, 0x40, 0x20, 0x00, 0x00,
		0x20, 0x40, 0x00, 0x00, 0xf0, 0xff, 0xff, 0x01, 0x10, 0x00, 0x00, 0x01,
		0x10, 0x02, 0x00, 0x01, 0x10, 0x07, 0x00, 0x01, 0x90, 0x0f, 0x00, 0x01,
		0x10, 0x02, 0x00, 0x01, 0x10, 0x02, 0x00, 0x01, 0x10, 0x02, 0x00, 0x01,
		0x10, 0xfe, 0x07, 0x01, 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x01,
		0xf0, 0xff, 0xff, 0x01};}]
    }
    }
    set parent_bg [[winfo parent $data(upBtn)] cget -bg]
    
    $data(upBtn) config -image $Priv(updirImage) \
	-relief flat -overrelief raised -bg $parent_bg
    set data(newBtn) [button $f1.new -image $Priv(newfolderImage) \
			  -relief flat -overrelief raised -bg $parent_bg]
    DynamicHelp::configure -bg white
    DynamicHelp::register $data(upBtn) balloon [_ "Go up to parent directory"]
    DynamicHelp::register $data(newBtn) balloon [_ "Create a new directory"]
    #$f1.menu config -takefocus 1 -highlightthickness 2
 
    pack $data(newBtn) $data(upBtn) -side right -fill both

    pack $f1.lab -side left -padx 4 -fill both
    #pack $f1.menu -expand yes -fill both -padx 4
    pack $f1.hcb -expand yes -fill x -padx 4


    proc setbwidth { w } {
	set dataName [lindex [split $w .] end]
	upvar ::tk::dialog::file::$dataName data
	#set newwidth [winfo reqheight $data(dirMenu)]
	set newwidth [winfo reqheight $data(dirCombo)]
	$data(newBtn) configure -width $newwidth
	$data(upBtn) configure -width $newwidth
    }
    after idle ::tk::dialog::file::setbwidth $w

    # data(icons): the IconList that list the files and directories.
    #
  if { [string equal $class TkFDialog] } {
    if { $data(-multiple) } {
      set fNameCaption [_ "File &names"]:
    } else {
      set fNameCaption [_ "File &name"]:
    }
    set fTypeCaption [_ "Files of &type"]:
    set fCaptionWidth [::tk::mcmaxamp $fNameCaption $fTypeCaption]
    set fCaptionWidth [expr {$fCaptionWidth<14?14:$fCaptionWidth}]
    set iconListCommand [list ::tk::dialog::file::OkCmd $w]
  } else {
    set fNameCaption [_ "&Selection"]:
    set fCaptionWidth [string length $fNameCaption]
    set iconListCommand [list ::tk::dialog::file::chooseDir::DblClick $w]
  }
    set data(icons) [::tk::IconList $w.icons \
			 -command	$iconListCommand \
			 -multiple	$data(-multiple) \
			 -checkrenamecmd "::tk::dialog::file::OnRename $w" \
			 -menucontext [list \
					   [list -label "Up directory" \
						-cmd  [list ::tk::dialog::file::UpDirCmd $w] \
						-image $Priv(updirImage) \
						-bind <KeyPress-BackSpace>] \
					   [list -label "New directory" \
						-cmd  [list ::tk::dialog::file::NewDirCmd $w] \
						-image $Priv(newfolderImage)] \
					   --- \
					   [list -label "Rename" \
						-cmd [list ::tk::dialog::file::RenameFile $w] \
						-image $Priv(renImage)] \
					   [list -label "Delete" \
						-cmd [list ::tk::dialog::file::RemoveFile $w] \
						-image $Priv(trashImage) \
					        -bind <KeyPress-Delete>]]]
    bind $data(icons) <<ListboxSelect>> \
	    [list ::tk::dialog::file::ListBrowse $w]

    # f2: the frame with the OK button and the "file name" field
    #
    set CCBG [CCColorActivo [$w cget -background]]
    set f2 [frame $w.f2 -bd 0 -bg $CCBG]
    bind [::tk::AmpWidget label $f2.lab -text $fNameCaption -anchor e -width $fCaptionWidth \
	    -pady 0 -bg $CCBG] <<AltUnderlined>> [list focus $f2.ent]
    set data(ent) [entry $f2.ent -bd 1 -highlightthickness 0]

    # RAMSAN adding
    proc ImproveEntry { wentry w dataName a } {
	upvar #0 $dataName data
	#if { [string compare $data(type) "open"] != 0} { return -1 }
	if { [regexp {^[a-zA-Z0-9_.-]+$} $a] } {
	    tk::EntryInsert $wentry $a
	    set text [::tk::IconList_ReturnUniqueChar $w [$wentry get]]
	    if { $text != ""  && \
		    [$wentry index insert] == [$wentry index end] } {
		$wentry sel from end
		$wentry ins end $text
		$wentry sel to end
	    }
	    return 0
	} else { return -1 }
    }
    # RAMSAN adding
      bind $data(ent) <KeyPress> " \
  	    if { \[::tk::dialog::file::ImproveEntry %W $data(icons) $dataName %A] ==0 } { break }"

    # 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]

    # f3: the frame with the cancel button and the file types field
    #
    set f3 [frame $w.f3 -bd 0 -bg $CCBG]

    # Make the file types bits only if this is a File Dialog
    if { [string equal $class TkFDialog] } {
	# The "File of types:" label needs to be grayed-out when
	# -filetypes are not specified. The label widget does not support
	# grayed-out text on monochrome displays. Therefore, we have to
	# use a button widget to emulate a label widget (by setting its
	# bindtags)
	
	set data(typeMenuLab) [::tk::AmpWidget button $f3.lab -text $fTypeCaption \
		-anchor e -width $fCaptionWidth \
		-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] -bg $CCBG]
	bindtags $data(typeMenuLab) [list $data(typeMenuLab) Label \
		[winfo toplevel $data(typeMenuLab)] all]

	#set data(typeMenuBtn) [menubutton $f3.menu -indicatoron 1 -menu $f3.menu.m]
	#set data(typeMenu) [menu $data(typeMenuBtn).m -tearoff 0]
	#$data(typeMenuBtn) config -takefocus 1 -highlightthickness 2 -relief raised -bd 2 -anchor w

	set data(typeCombo) [::tinycombo::tinycombo $f3.tcb -takefocus 1 -bd 1 \
				 -textvariable ::tk::dialog::file::${dataName}(typeCombo,textvar) \
				 -listvariable ::tk::dialog::file::${dataName}(typeCombo,labels)]
	$data(typeCombo) configure -readonlybackground [$data(typeCombo) cget -bg]
	::tinycombo::top:create $f3.tcb
	$f3.tcb.t.f configure -bd 1 -relief solid
	$f3.tcb.t.f.vs configure -bd 1 -relief ridge

	[$f3.tcb component entry] conf -borderwidth 1

	bind [$f3.tcb component list] <<ListboxSelect>> +[namespace code "SetFilterCombo $w"]
	[$f3.tcb component list] configure -selectforeground white

        #bind $data(typeMenuLab) <<AltUnderlined>> [list focus $data(typeMenuBtn)]
        bind $data(typeMenuLab) <<AltUnderlined>> [list focus $data(typeCombo)]
    }
    
    # the okBtn is created after the typeMenu so that the keyboard traversal
    # is in the right order
    set maxWidth [::tk::mcmaxamp &OK &Cancel]
    set maxWidth [expr {$maxWidth<6?6:$maxWidth}]
    set data(okBtn)     [::tk::AmpWidget button $f2.ok     -text [_ "&OK"] \
	-width $maxWidth -default active -pady 3]
    set data(cancelBtn) [::tk::AmpWidget button $f3.cancel -text [_ "&Cancel"] \
	-width $maxWidth -default normal -pady 3]

    # pack the widgets in f2 and f3
    #
    pack $data(okBtn) -side right -padx 4 -anchor e
    pack $f2.lab -side left -padx 4
    pack $f2.ent -expand yes -fill x -padx 2 -pady 0
    
    pack $data(cancelBtn) -side right -padx 4 -anchor w
    if { [string equal $class TkFDialog] } {
	pack $data(typeMenuLab) -side left -padx 4
	#pack $data(typeMenuBtn) -expand yes -fill x -side right
	pack $data(typeCombo) -expand yes -fill x -side right
    }

    # Pack all the frames together. We are done with widget construction.
    #
    pack $f1 -side top -fill x -pady 4
    pack $f3 -side bottom -fill x
    pack $f2 -side bottom -fill x
    pack $data(icons) -expand yes -fill both -padx 4 -pady 1

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

    wm protocol $w WM_DELETE_WINDOW [list ::tk::dialog::file::CancelCmd $w]
    $data(upBtn)     config -command [list ::tk::dialog::file::UpDirCmd $w]
    $data(newBtn)     config -command [list ::tk::dialog::file::NewDirCmd $w]
    $data(cancelBtn) config -command [list ::tk::dialog::file::CancelCmd $w]
    bind $w <KeyPress-Escape> [list tk::ButtonInvoke $data(cancelBtn)]
    bind $w <Alt-Key> [list tk::AltKeyInDialog $w %A]
    # Set up event handlers specific to File or Directory Dialogs
    #

    if { [string equal $class TkFDialog] } {
	bind $data(ent) <Return> [list ::tk::dialog::file::ActivateEnt $w]
	$data(okBtn)     config -command [list ::tk::dialog::file::OkCmd $w]
	bind $w <Alt-t> [format {
	    if {[string equal [%s cget -state] "normal"]} {
		focus %s
	    }
	}	 $data(typeCombo) $data(typeCombo)]
 #       $data(typeMenuBtn) $data(typeMenuBtn)]
    } else {
	set okCmd [list ::tk::dialog::file::chooseDir::OkCmd $w]
	bind $data(ent) <Return> $okCmd
	$data(okBtn) config -command $okCmd
	bind $w <Alt-s> [list focus $data(ent)]
	bind $w <Alt-o> [list tk::ButtonInvoke $data(okBtn)]
    }

    # Build the focus group for all the entries
    #
    ::tk::FocusGroup_Create $w
    ::tk::FocusGroup_BindIn $w  $data(ent) [list ::tk::dialog::file::EntFocusIn $w]
    ::tk::FocusGroup_BindOut $w $data(ent) [list ::tk::dialog::file::EntFocusOut $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 { $multi } {
	set fNameCaption [_ "File &names"]:
    } else {
	set fNameCaption [_ "File &name"]:
    }
    set iconListCommand [list ::tk::dialog::file::OkCmd $w]
    ::tk::SetAmpText $w.f2.lab $fNameCaption 
    ::tk::IconList_Config $data(icons) \
	    [list -multiple $multi -command $iconListCommand \
		-checkrenamecmd "::tk::dialog::file::OnRename $w"]
    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} {
    upvar ::tk::dialog::file::[winfo name $w] data

    if {[info exists data(updateId)]} {
	return
    } else {
	set data(updateId) [after idle [list ::tk::dialog::file::Update $w]]
    }
}


# ::tk::dialog::file::InsertNames --
#
#       Insert into the iconlist the names given in allList, if a name is 
#       in the list hiddenList the it is inserted with the icon iconList[1]
#       otherwise it is inserted with the icon iconList[0].
#

proc ::tk::dialog::file::InsertNames {w_iconlist allList hiddenList icons} {
    set tmpList [list]
    set g_ishidden -1
    foreach name $allList {
	set att_hidden [expr [lsearch -exact $hiddenList $name]!=-1]
	if {$g_ishidden == -1} {
	    set g_ishidden $att_hidden
	    lappend tmpList $name
	} else {
	    if {[expr {!($att_hidden ^ $g_ishidden)}]} {
		lappend tmpList $name
	    } else {
		::tk::IconList_Add $w_iconlist [lindex $icons $g_ishidden] $tmpList
		set g_ishidden $att_hidden
		set tmpList [list $name]
	    }
	}
    }
    if {[llength $tmpList]} {
	::tk::IconList_Add $w_iconlist [lindex $icons $g_ishidden] $tmpList
    }
}

# ::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.
#

set ::nocache 0

proc ::tk::dialog::file::Update {w} {

    # 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
    global tk_library
    catch {unset data(updateId)}

    if {![info exists Priv(folderImage)]} {
	set Priv(folderImage) [image create photo -data {
R0lGODlhEAAMAKEAAAD//wAAAPD/gAAAACH5BAEAAAAALAAAAAAQAAwAAAIghINhyycvVFsB
QtmS3rjaH1Hg141WaT5ouprt2HHcUgAAOw==}]
    }
    if {![info exists Priv(fileImage)]} {
	set Priv(fileImage)   [image create photo -data {
R0lGODlhDAAMAKEAALLA3AAAAP//8wAAACH5BAEAAAAALAAAAAAMAAwAAAIgRI4Ha+IfWHsO
rSASvJTGhnhcV3EJlo3kh53ltF5nAhQAOw==}]
    }
    if {![info exists ::GiDPriv(image_GiDdirectory)]} {
	set ::GidPriv(image_GiDdirectory) [image create photo -file \
					       [file join $::GIDDEFAULT bitmaps GiDdirectory.gif]]
    }
    if {![info exists ::GiDPriv(image_GiDdirectoryH)]} {
	set ::GidPriv(image_GiDdirectoryH) [image create photo -file \
					       [file join $::GIDDEFAULT bitmaps GiDdirectory_h.gif]]
    }
    set folder $Priv(folderImage)
    set file   $Priv(fileImage)
    set prjdir $::GidPriv(image_GiDdirectory)
    set prjdirh $::GidPriv(image_GiDdirectoryH)
    set appPWD [pwd]
    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.
	tk_messageBox -type ok -parent $w -message \
	    [_ "Cannot change to the directory '%s'. Permission denied." $data(selectPath)]\
	    -icon warning -title [_ "Error"]
	cd $appPWD
	return
    }

    ::DynamicHelp::register $data(dirCombo) balloon $data(selectPath)

    # Turn on the busy cursor. BUG?? We haven't disabled X events, though,
    # so the user may still click and cause havoc ...
    #
    set entCursor [$data(ent) cget -cursor]
    set dlgCursor [$w         cget -cursor]
    $data(ent) config -cursor watch
    $w         config -cursor watch
    update
    
    # Update the Directory: option menu
    #
    set list ""
    set dir ""
    set index -1
    set curdir_idx -1
    set left 15
    global tcl_platform

    if {![info exists data(dirCombo,index)]} {
	set data(dirCombo,index) -1
	set data(dirCombo,indexbase) -1
    }

    set selnative [file native $data(selectPath)]

    if { $::nocache || ![info exists data(cache,items_conf)] ||
	![info exists data(cache,dirList)] ||
	![info exists data(cache,dirFullList)]} {
	set items_conf [list]
	set data(dirList) [list]
	set data(dirFullList) [list]
	if { $tcl_platform(platform) == "windows" } {
	    # specials folders in windows
	    foreach winfolder {Personal Desktop} {
		set pfolder [::tk::shellfolder $winfolder]
		lappend data(dirList) [file tail $pfolder]
		lappend data(dirFullList) $pfolder
		incr index
		if {($curdir_idx == -1) && ($pfolder eq $selnative)
		    && ($data(dirCombo,index) <= $data(dirCombo,indexbase))} {
		    set curdir_idx $index		
		}
		# iterar tambien por los indices de las imagenes
		# cuando las tengas, por ahora le ponemos el de folder
		lappend items_conf [list $index $left $Priv(folderImage)]
	    }
	} else {
	    # specials folder in unix
	    set pfolder [file normalize ~]
	    lappend data(dirList) [file tail $pfolder]
	    lappend data(dirFullList) $pfolder
	    incr index
	    if {($curdir_idx == -1) && ($pfolder eq $data(selectPath))
		&& ($data(dirCombo,index) <= $data(dirCombo,indexbase))} {
		set curdir_idx $index		
	    }
	    lappend items_conf [list $index $left $Priv(homeImage)]
	}
	# GiD special folder
	set pfolder [file nativename $::GIDDEFAULT]
	lappend data(dirList) [file tail $pfolder]
	lappend data(dirFullList) $pfolder
	incr index
	if {($curdir_idx == -1) && ($pfolder eq $selnative)
	    && ($data(dirCombo,index) <= $data(dirCombo,indexbase))} {
	    set curdir_idx $index		
	}
	# proponer quizas una imagen mejor para el icono del directorio de GiD
	lappend items_conf [list $index $left $::GidPriv(image_GiDdirectory)]
	set data(dirCombo,indexbase) $index
	
	if { $tcl_platform(platform) == "windows" } {
	    set volumes [list]
	    foreach i [lindex [givewinvolumes] 0] {
		lappend volumes "$i\\"
	    }
	} else {
	    set volumes /
	}
	set data(cache,items_conf) $items_conf
	set data(cache,dirList) $data(dirList)
	set data(cache,dirFullList) $data(dirFullList)
	set data(cache,volumes) $volumes
    } else {
	[$data(dirCombo) component list] selection clear 0 end
	set items_conf $data(cache,items_conf)
	set data(dirList) $data(cache,dirList)
	set data(dirFullList) $data(cache,dirFullList)
	set volumes $data(cache,volumes)
	
	foreach i $data(dirFullList) {
	    incr index
	    if {$curdir_idx == -1 && ($i eq $selnative) &&
		($data(dirCombo,index) <= $data(dirCombo,indexbase))} {
		set curdir_idx $index
		break
	    }
	}
	set index $data(dirCombo,indexbase)
    }

    set subdirs [file split $data(selectPath)]
    set volpath [file native [lindex $subdirs 0]]
    foreach vol $volumes {
	lappend data(dirList) $vol
	lappend data(dirFullList) $vol
	incr index
	lappend items_conf [list $index $left $Priv(diskImage)]
	if {($curdir_idx == -1) && ($vol eq $selnative)} {
	    set curdir_idx $index		
	} elseif {($curdir_idx == -1) && ($volpath eq $vol)} {
	    # unroll the path
	    set dir $vol
	    foreach subdir [lrange $subdirs 1 end] {
		set dir [file nativename [file join $dir $subdir]]
		lappend data(dirList) $subdir
		lappend data(dirFullList) $dir
		incr index
		incr left 15
		lappend items_conf [list $index $left $Priv(folderImage)]
		if {($curdir_idx == -1) && ($selnative eq $dir)} {
		    set curdir_idx $index
		    lappend items_conf [list $index $left $Priv(openfolderImage)]
		} else {
		    lappend items_conf [list $index $left $Priv(folderImage)]
		}
	    }
	    set left 15
	}
    }
    
    # now configure the elements of the hugelist

    foreach conf $items_conf {
	foreach {index left image} $conf break
	$data(dirCombo) itemconf $index -left $left -image $image
    }

    $data(dirCombo) list select $curdir_idx
    $data(dirCombo) load
    set len_dirlist [llength $data(dirList)]
    $data(dirCombo) configure -height [expr $len_dirlist>7?7:$len_dirlist]

#    $data(dirMenu) delete 0 end

    #set var [format %s(selectPath) ::tk::dialog::file::$dataName]
    #foreach path $list {
    #	$data(dirMenu) add command -label $path -command [list set $var $path]
    #}

    ::tk::IconList_DeleteAll $data(icons)

    # Make the dir list
    #
    #set completeFileList [lsort -dictionary -unique [glob -nocomplain .* *]]
    set hiddenDirs [glob -nocomplain -type {hidden d} *]
    set normalDirs [glob -nocomplain -type d *]
    set completeDirList [lsort -dictionary -unique [concat \
							$hiddenDirs\
							$normalDirs]]
    set dirList {}
    set prjdirList {}
#     foreach f $completeFileList {
# 	if {[string equal $f .]} {
# 	    continue
# 	}
# 	if {[string equal $f ..]} {
# 	    continue
# 	}
# 	if {[file isdir ./$f]} {
# 	    if {($data(-dirprojectext) eq "" || 
# 		 [file extension $f] ne $data(-dirprojectext))} {
# 		lappend dirList $f
# 	    } else {
# 		lappend prjdirList $f
# 	    }
# 	}
#     }
    foreach f $completeDirList {
	if {[string equal $f .]} {
	    continue
	}
	if {[string equal $f ..]} {
	    continue
	}
      if {($data(-dirprojectext) eq "" || 
	   [file extension $f] ne $data(-dirprojectext))} {
	lappend dirList $f
      } else {
	lappend prjdirList $f
      }
    }

    #::tk::IconList_Add $data(icons) $folder $dirList
    InsertNames $data(icons) $dirList $hiddenDirs \
	[list $Priv(folderImage) $Priv(folderhImage)]
    if { [string equal $class TkFDialog] } {
	# Make the file list if this is a File Dialog
	#
	set hiddenFiles [glob -nocomplain -type {f hidden} *]
	set normalFiles [glob -nocomplain -type f *]
	set completeFileList [lsort -dictionary -unique [concat \
							     $hiddenFiles \
							     $normalFiles]]
	if {[string equal $data(filter) *]} {
	    #set files $completeFileList
	    set fileList $completeFileList
	} else {
# 	    set files {}
	    set fileList {}
	    foreach f $completeFileList {
		foreach pat $data(filter) {
		    if { [string match -nocase $pat $f] } {
			#lappend files $f
		        lappend fileList $f
			break
		    }
		}
	    }
	}
#	set fileList {}
# 	foreach f $files {
# 	    if {![file isdir ./$f]} {
# 		lappend fileList $f
# 	    }
#       }
	if {[llength $prjdirList]} {
	    #::tk::IconList_Add $data(icons) $prjdir $prjdirList
	    InsertNames $data(icons) $prjdirList $hiddenDirs \
		[list $prjdir $prjdirh]
	}
	if {[llength $fileList]} {
	    #::tk::IconList_Add $data(icons) $file $fileList
	    InsertNames $data(icons) $fileList $hiddenFiles \
		[list $file $Priv(filehImage)]
	}
    }

    ::tk::IconList_Arrange $data(icons)


    # 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 {[string equal $data(type) open]} {
	    ::tk::SetAmpText $data(okBtn) [_ "&Open"]
	    set maxWidth [::tk::mcmaxamp [_ "&Open"]]
	    if {$maxWidth>[$data(okBtn) cget -width]} {
		    $data(okBtn) config -width $maxWidth
		    $data(cancelBtn) config -width $maxWidth
	    }
	} else {
	    ::tk::SetAmpText $data(okBtn) [_ "&Save"]
	    set maxWidth [::tk::mcmaxamp [_ "&Save"]]
	    if {$maxWidth>[$data(okBtn) cget -width]} {
		    $data(okBtn) config -width $maxWidth
		    $data(cancelBtn) config -width $maxWidth
	    }
	}
    }

    # turn off the busy cursor.
    #
    $data(ent) config -cursor $entCursor
    $w         config -cursor $dlgCursor
}

# ::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(selectPathCombo) is set
#
proc ::tk::dialog::file::SetPathCombo {w} {
    if {[winfo exists $w]} {
	upvar ::tk::dialog::file::[winfo name $w] data
	set data(dirCombo,index) [$data(dirCombo) list cursel]
	set data(selectPath) [lindex $data(dirFullList) $data(dirCombo,index)]
    }
}

# 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
	::tk::dialog::file::UpdateWhenIdle $w
	# On directory dialogs, we keep the entry in sync with the currentdir.
	if { [string equal [winfo class $w] TkChooseDir] } {
	    $data(ent) delete 0 end
	    $data(ent) insert end $data(selectPath)
	}
    }
}

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

    set idx [eval [$data(typeCombo) comp list] curselection]
    ::tk::dialog::file::SetFilter $w [list "" \
					  [lindex $data(typeCombo,filters) $idx]] 
}

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

    set data(filter) [lindex $type 1]
    #$data(typeMenuBtn) config -text [lindex $type 0] -indicatoron 1
    #set data(typeCombo,textvar) [lindex $type 0]
    # If we aren't using a default extension, use the one suppled
    # 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) ""
	}
    }

    if {$needsupdate} {
	$icons(sbar) set 0.0 0.0
    
	::tk::dialog::file::UpdateWhenIdle $w
    }
}

# 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]

    # 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.

    if {![file isdirectory $path]} {
	set ext [file ext $path]
	set append_ext 1
	foreach _ext $data(filter) {
	    if {[string equal -nocase [string trimleft $_ext *] $ext]} {
		set append_ext 0
		break
	    }
	}
	if { $append_ext } {
	    set path "$path$defaultext"	
	}
    }

#     if {(![file isdirectory $path] || ($data(-dirprojectext) ne "")) && \
# 	    [string equal [file ext $path] ""]} {
# 	set path "$path$defaultext"
#     }


    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 {[file isdirectory $path] && ($data(-dirprojectext) eq "" ||
					 [file extension $path] ne $data(-dirprojectext))} {
	    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 {[string compare [$data(ent) get] ""]} {
	$data(ent) selection range 0 end
	$data(ent) icursor end
    } else {
	$data(ent) selection clear
    }

    if { [string equal [winfo class $w] TkFDialog] } {
	# If this is a File Dialog, make sure the buttons are labeled right.
	if {[string equal $data(type) open]} {
	    ::tk::SetAmpText $data(okBtn) [_ "&Open"]
	} else {
	    ::tk::SetAmpText $data(okBtn) [_ "&Save"]
	}
    }
}

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

    $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

    set text [$data(ent) get]
    if {$data(-multiple)} {
	# For the multiple case we have to be careful to get the file
	# names as a true list, watching out for a single file with a
	# space in the name.  Thus we query the IconList directly.

	set data(selectFile) ""
	foreach item [::tk::IconList_Curselection $data(icons)] {
	    ::tk::dialog::file::VerifyFileName $w \
		    [::tk::IconList_Get $data(icons) $item]
	}
    } else {
	::tk::dialog::file::VerifyFileName $w $text
    }
}

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

    if {[regexp {[*]|[?]} $filename]} {
	set flag PATTERN
	set path $data(selectPath)
	SetFilter $w [list "" [list $filename]] 0
	set file $data(filter)
	
    } else {
	set list [::tk::dialog::file::ResolveFile $w $data(selectPath) $filename \
		      $data(-defaultextension)]
	foreach {flag path file} $list {
	    break
	}
    }
 
#    foreach {flag path file} $list {
# 	break
#     }

    switch -- $flag {
	OK {
	    if {[string equal $file ""]} {
		# user has entered an existing (sub)directory
		set data(selectPath) $path
		$data(ent) delete 0 end
	    } else {
		::tk::dialog::file::SetPathSilently $w $path
		if {$data(-multiple)} {
		    lappend data(selectFile) $file
		} else {
		    set data(selectFile) $file
		}
		::tk::dialog::file::Done $w
	    }
	}
	PATTERN {
	    set data(filter) $file

	    set data(selectPath) $path
	    #set data(filter) $file
	}
	FILE {
	    if {[string equal $data(type) open]} {
		tk_messageBox -icon warning -type ok -parent $w \
		    -message [_ "File '%s' does not exist." [file join $path $file]] \
		    -title [_ "Error"]
		$data(ent) selection range 0 end
		$data(ent) icursor end
	    } else {
		::tk::dialog::file::SetPathSilently $w $path
		if {$data(-multiple)} {
		    lappend data(selectFile) $file
		} else {
		    set data(selectFile) $file
		}
		::tk::dialog::file::Done $w
	    }
	}
	PATH {
	    tk_messageBox -icon warning -type ok -parent $w \
		-message [_ "Directory '%s' does not exist." $path] \
		-title [_ "Error"]
	    $data(ent) selection range 0 end
	    $data(ent) icursor end
	}
	CHDIR {
	    tk_messageBox -type ok -parent $w -message \
	       [_ "Cannot change to the directory '%s'. Permission denied." $path]\
		-icon warning -title [_ "Error"]
	    $data(ent) selection range 0 end
	    $data(ent) icursor end
	}
	ERROR {
	    tk_messageBox -type ok -parent $w -message \
	       [_ "Invalid file name '%s'." $path]\
		-icon warning  -title [_ "Error"]
	    $data(ent) selection range 0 end
	    $data(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::ButtonInvoke $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)]
    }
}

# called when a rename is about to be done
# return empty if its a valid newname, and perform the renaming
# return an message error when renaming can not be done
#

proc ::tk::dialog::file::OnRename {w oldname newname} {
    upvar ::tk::dialog::file::[winfo name $w] data
    variable ::tk::Priv
    
    set _newname [::tk::dialog::file::JoinFile $data(selectPath) $newname]
    if { [file exists $_newname] } {
	return [list 0 [_ "File '%s' already exists.Can not rename." $newname]] 
    }
    # rename if it does not exist
    if { ![file writable $data(selectPath)] } {
	return [list 0 \
		    [_ "You have not write permision on the directory '%s'. Permission denied." $data(selectPath)]] 
    } else {
	# catch it for possible error not considered
	if { [catch {file rename [::tk::dialog::file::JoinFile $data(selectPath) $oldname] $_newname} msgcatch] } {
	    return [list 0 [_ $msgcatch]] 
	}
	if { [file isdirectory $_newname] && $data(-dirprojectext) != "" } {
	    if { [file extension $newname] == $data(-dirprojectext) } {
		# change the files names inside project directory
		set prjname [file rootname $newname]
		set old_prjname [file rootname $oldname]
		foreach f [glob -nocomplain [::tk::dialog::file::JoinFile $_newname *]] {
		    if {[string equal $old_prjname [file rootname [file tail $f]]]} {
			file rename $f [::tk::dialog::file::JoinFile $_newname ${prjname}[file extension $f]]
		    }
		}
		if { [file extension $oldname] != $data(-dirprojectext) } {
		    return [list 1 $::GidPriv(image_GiDdirectory)]
		}
	    } else {
		if { [file extension $oldname] == $data(-dirprojectext) } {
		    return [list 1 $Priv(folderImage)]		
		}
	    }
	}
    }
    return [list 1]
} 

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

    set fname [file nativename [file join $data(selectPath) \
	         [::tk::IconList_GetText $data(icons) -1]]]
    if {$::tcl_platform(platform) eq "windows"} {
	trash $fname
    } else {
	# doit in unix
    }
    UpdateWhenIdle $w
}

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

    ::tk::IconList_RenameText $data(icons) -1
}

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

    # verify first if we can create a new folder
    
    if { ![file writable $data(selectPath)] } {
	tk_messageBox -type ok -parent $w -message \
	    [_ "You have not write permision on the directory '%s'. Permission denied." $data(selectPath)] \
	    -icon warning  -title [_ "Error"]
	return
    }
    # create a unique new folder name
    set mcprefix [_ "New Folder "]
    set lpath [string length $data(selectPath)]
    set nf_list [glob -nocomplain [::tk::dialog::file::JoinFile $data(selectPath) ${mcprefix}*]]
    set nf_id_list [list]
    foreach nf $nf_list {
	regexp "${mcprefix}(.*)" [string range $nf $lpath end] {} _id
	if { [string is integer $_id] } {
	    lappend nf_id_list $_id
	}
    }
    set nf_id_list [lsort -integer $nf_id_list] 
    set id 1
    foreach _id $nf_id_list {
	if { $_id <= 0 } continue
	if { $id < $_id } break
	incr id
    }
    set FolderName ${mcprefix}$id
    # create the new folder
    file mkdir [::tk::dialog::file::JoinFile $data(selectPath) $FolderName]
    # add to the icon list
    ::tk::IconList_Add $data(icons) $::tk::Priv(folderImage) [list $FolderName]
    ::tk::IconList_Arrange $data(icons)

    #::tk::IconList_See $w.icons [expr [::tk::IconList_Index $w.icons end]-1]
    
    # move to the end
    $icons(canvas) xview moveto 1
    # set the selection to the end
    # don't know why should I compute this index that way?
    set idx_end [expr [::tk::IconList_Index $data(icons) end]-1]
 
    ::tk::IconList_Selection $data(icons) clear 0 end
    #::tk::IconList_Selection $data(icons) set $idx_end
    #::tk::IconList_Selection $data(icons) anchor $idx_end

    # and allow changing the name    

    ::tk::IconList_RenameText $data(icons) $idx_end

    # crear una entry encima del rectangulo y enviar todos los eventos de teclado
    # al terminar craer la carpeta.

    #{::tk::.__tk_filedialog.icons (list)}
}

# 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 "OK" button
#
proc ::tk::dialog::file::OkCmd {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]
    }

    if {([llength $filenames] && !$data(-multiple)) || \
	    ($data(-multiple) && ([llength $filenames] == 1))} {
	set filename [lindex $filenames 0]
	set file [::tk::dialog::file::JoinFile $data(selectPath) $filename]
	if {[file isdirectory $file] && ($data(-dirprojectext) eq "" ||
					 [file extension $file] ne $data(-dirprojectext)) } {
	    ::tk::dialog::file::ListInvoke $w [list $filename]
	    return
	}
    }

    ::tk::dialog::file::ActivateEnt $w
}

# 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

    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 { ![file isdirectory $fullfile] || ($data(-dirprojectext) ne "" && 
						   [file extension $fullfile] eq $data(-dirprojectext)) } {
		lappend newtext $file
	    }
	}
	set text $newtext
	set isDir 0
    } else {
	set text [lindex $text 0]
	set file [::tk::dialog::file::JoinFile $data(selectPath) $text]
	set isDir [expr [file isdirectory $file] && \
		       ([string equal $data(-dirprojectext) ""] || \
			    [string compare [file extension $file] $data(-dirprojectext)])]
    }
    if {!$isDir} {
	$data(ent) delete 0 end
	$data(ent) insert 0 $text

	if { [string equal [winfo class $w] TkFDialog] } {
	    if {[string equal $data(type) open]} {
		::tk::SetAmpText $data(okBtn) [_ "&Open"]
	    } else {
		::tk::SetAmpText $data(okBtn) [_ "&Save"]
	    }
	}
    } else {
	if { [string equal [winfo class $w] TkFDialog] } {
	    ::tk::SetAmpText $data(okBtn) [_ "&Open"]
	}
    }
}

# Gets called when user invokes the IconList widget (double-click, 
# Return key, etc)
#
proc ::tk::dialog::file::ListInvoke {w filenames} {
    upvar ::tk::dialog::file::[winfo name $w] data

    if {[llength $filenames] == 0} {
	return
    }

    set file [::tk::dialog::file::JoinFile $data(selectPath) \
	    [lindex $filenames 0]]
    
    set class [winfo class $w]
    if {[string equal $class TkChooseDir] || [file isdirectory $file] &&
	($data(-dirprojectext) eq "" || [file extension $file] ne $data(-dirprojectext))} {
	set appPWD [pwd]
	if {[catch {cd $file}]} {
	    tk_messageBox -type ok -parent $w -message \
	       [_ "Cannot change to the directory '%s'.Permission denied." $file] \
		-icon warning  -title [_ "Error"]
	} else {
	    cd $appPWD
	    set data(selectPath) $file
	}
    } else {
	if {$data(-multiple)} {
	    set data(selectFile) $filenames
	} else {
	    set data(selectFile) $file
	}
	::tk::dialog::file::Done $w
    }
}

# ::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 {[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\
			   -parent $w \
			   -message [_ "File '%s' already exists. Do you want to overwrite it?" $selectFilePath] \
			   -title [_ "Error"]]
	    if {[string equal $reply "no"]} {
		return
		}
	    }
	}
    }
    set Priv(selectFilePath) $selectFilePath
}
