#################################
# The Miscellaneous Module
#
# Part of the SharpeSound Editor
# by Paul D. Sharpe
# A 3rd Year Project at the University of Leeds;
# Department of Electronic and Electrical Engineering.
# Date: 8/3/95

# A collection of procedures and functions that are
# (generally) used in more than one module 


###################################################################
# bindScale
# A procedure to do the binding work for the combined scale widget.
# This consists of a scale with an attatched entry to show the value
# of the scale and allows keyboard entry when pointer is in the 
# entry area. 
# Used in mixer.tk and effect.tk
# The two parameters are:
# path : the path of the combined scale widget.
# oldfocus : the path of the widget to have the focus, when not in
# the entry area.
# Revision:0
# Date 8/3/95
proc bindScale { path {oldfocus none} } {
 		# Bind the return to adjust the scale
   		bind $path.label <Return> \
			"set  number \[$path.label get\];
			if {\[regexp {^\[0-9\]+$} \$number\]} {
	   			$path.scale set \$number;
			} else {
	   			$path.label delete 0 end;
	   			$path.label insert 0\
		 	\[ $path.scale get\];
			}"

 		bind $path.label <Any-Leave> \
			"
			 $path.label select clear
 			eval \[bind $path.label <Return>\]"
		
		bind $path.label <Any-Enter> \
			"focus $path.label 
			 $path.label select from 0
			 $path.label select to end"
		bind $path.label <Any-Key> \
		 "catch {$path.label delete sel.first sel.last}"
	
}

###################################################################
# WaitPlease
# This procedure gives the user notice that a process is going to take
# a little while. 
# The start parameter is a boolean value which switches the notice
# on and off.
# Currently this notice is simply changing the cursor pointer to be a
# watch. 
# BUGS: This doesn't change the cursor of entry widgets in a combined
# scale widget. 
# by Paul D. Sharpe 3/95
proc WaitPlease { {start 1} } {

   if {$start} {
	# Fix the window size.
	HoldWindow .

	# Set the cursor to be a watch.
	. config -cursor watch
	# Need to set canvas separately, since it doesn't use default cursor.
	.plotbox.cs.canvas config -cursor  watch
	update idletasks
   } else {
	# Set the cursor to default.
	. config -cursor {}
	# Reset the canvas cursor.
	.plotbox.cs.canvas config -cursor crosshair
	update idletasks
   }
}


###################################################################
# HoldWindow
# This procedure fixes the main window to its current size to 
# avoid shrinking when reconfiguring it. (For example, changing
# colours or the cursor)
# by Paul D. Sharpe 3/95
proc HoldWindow {w} {
	. config -width [winfo width $w] -height [winfo height $w]
	update idletasks
}

###################################################################
# Sec2Time
# This function takes seconds and 
# returns minutes: seconds : milliseconds in a string.
# by Paul D. Sharpe 3/95
proc Sec2Time { secs } {
   set sec2 [expr int(floor($secs))]
   set minutes [expr $sec2/60]
   set msec [expr round(1000*($secs-$sec2))]
   set sec2 [expr $sec2%60]
   return "$minutes : $sec2 : $msec"
}

###################################################################
# CARDSetter
# This procedure sets the CARD array - information about sound card
# by Paul D. Sharpe 3/95
proc CARDSetter {} {
   global CARD FILE

   # Get sound card information.
   set info [exec $FILE(Tool) diagnostics]

   # info contains 4 lists; allowable bit resolution, channels
   # and sampling rate ranges in both mono and stereo modes.
   # Store these in the CARD array.
   set CARD(Bits) 		[lindex $info 0]
   set CARD(Chnnls) 	[lindex $info 1]
   set CARD(Maxrates)\
	[list [lindex [lindex $info 2] 1] [lindex [lindex $info 3] 1]]
   set CARD(Minrates)\
	[list [lindex [lindex $info 2] 0] [lindex [lindex $info 3] 0]]

   # Get some information from the driver's SndStat.
   set f [open {|cat /dev/sndstat}]
   set unique 0
   while {![eof $f]} {	
	set line [gets $f]
	switch [lindex $line 0] {
		Sound { set CARD(Driver) [lindex [split [lindex $line 1] :] 1] }
		Type  { set CARD(HW$unique) [lrange $line 2 end];incr unique }
	}
   }
   close $f
}

###################################################################
# dialog
# This procedure is a general dialog box creator.
# Taken from te book, Tcl and the Tk Toolkit by J.K.Ousterhout (1994).
# Modified to allow flexibiltiy in colours and fonts
# and also to make the window behave as a child window to the root window.

# The parameters are as follows:
# w	: path name of the toplevel window to be created
# title	: title to be placed in the window's frame.
# text	: the dialog message.
# colours: a list containing color infomation. An empty list is allowed.
#	  the order of the list is { backgrnd foregrnd activebg activefg font }
# bitmap: name of the bitmap to be used. An empty string is allowed.
# default: the index of the arg list (next) which is to be default button
# arg	: the list of buttons to be displayed.

# Returns: an index to the arg list corresponding to the button pressed.
# Bindings: <Return> invokes the default button.

# Modified: P.D.Sharpe 1/3/1995 
# 3rd Year Project - Sound Studio in TCL/TK for Linux.
proc dialog {w title text colours bitmap default args } {
    global button

    # 0. Organise Colour and font settings.
    set ColVars [list BG FG ABG AFG FNT ]
    set i 0
    if {$colours ==""} { 
	set colours {grey blue LightGrey MediumBlue "" } 
    }
    foreach Var $ColVars {
	set $Var [lindex $colours $i]
	incr i 
    }
    if {$FNT=="" | ![catch {exec xlsfonts $FNT}]} { 
	set FNT  -adobe-helvetica-medium-r-normal-*-140-*
    }

    # 1. Create th top-level window and divide it into top and
    # bottom parts.

    toplevel $w -class Dialog
    wm title $w $title
    # Set window as a pop-up child of the root window.
    wm transient $w .
     
    frame $w.top -relief raised -bd 1 -bg $BG
    pack $w.top -side top -fill both
    frame $w.bot -relief raised -bd 1 -bg $BG
    pack $w.bot  -side bottom -fill both


    # 2. Fill the top part with the bitmap and message.

    message $w.top.msg  -text $text\
			-font $FNT -bg $BG -fg $FG
    pack $w.top.msg -side right -expand 1 -fill both\
			-padx 3m -pady 3m
    if {$bitmap != ""} {
	label $w.top.bitmap -bitmap $bitmap -bg $BG -fg $FG
	pack $w.top.bitmap -side left -padx 3m -pady 3m
    }


    # 3. Create a row of buttons at the bottom of the dialog
	
    set i 0
    foreach but $args {
	button $w.bot.button$i -text $but -command\
		"set button $i" -bg $BG\
		-fg $FG -activeforeground $AFG \
		-activebackground $ABG
	if {$i==$default} {
		frame $w.bot.default -relief sunken -bd 1 -bg $BG
		raise $w.bot.button$i
		pack $w.bot.default -side left -expand 1\
			-padx 3m -pady 2m
		pack $w.bot.button$i -in $w.bot.default\
			-side left -padx 2m -pady 2m\
			-ipadx 2m -ipady 1m
	} else {
		pack $w.bot.button$i -side left -expand 1\
			-padx 2m -pady 2m\
			-ipadx 2m -ipady 1m
 	}
	incr i
    }


    # 4. Set up a binding for <Return>, if there's a default,
    # set a grab and claim a focus.
    if ($default>=0) {
	bind $w <Return> "$w.bot.button$default flash; \
		set button $default"
    }
    set oldFocus [focus]
    grab set $w
    focus $w


    # 5. Wait for the user to respond, then restore the focus 
    # and return the index of the selected button.
    
    tkwait variable button
    destroy $w
    focus $oldFocus
    return $button
}


###################################################################
# OrderPacking
# This procedure sets the PACK array to give the packing order.
# by P.D.Sharpe 3/95
proc OrderPacking {} {
	global PACK FLAG
	set i 0
	set next 1
	foreach item $PACK(list) {
		# if the item is to be shown set after the previous
		if {$FLAG(Vw_$item)} {
			set PACK($item) [lindex $PACK(path) $i]
			set i $next
			incr next
		} else {
			set PACK($item)	""
			set next [expr [lsearch $PACK(list) $item]+2]
		}
	}

}

###################################################################
# FileBrowser; a file selection browser for TCL/Tk
#
# This Creates a toplevel .filebrowser, with an environment for 
# selecting a single file.
# There are a few globals, all beginning with the prefix FB_ .
# The selected filename (with path) is stored in the global, FB_Return.
#
# All arguments are optional, (you may have to supply an empty string though)
# Summary of Arguments:
#   1. Title : The string to be contained in the toplevel widget.
#   2. Colors : A list containing color settings; the order is as follows
# 		[ BackGround ForeGround ActiveBG ActiveFG FontName ]
# 		Note that font name is not the full path, just eg. Times, Helvetica etc.
#   3. SearchLists : A list containing a list of preset glob type searches. The user is
#		able to apply this search by use of a radiobutton.
#		For example, the list of files most likely to be viewed are say, files 
#		with the extentions ".c" and ".h", also a view of all files is also 
#		to be used frequently then SearchLists will be a list of 2 lists;
#				{ { *.h *.c } { * } }
#		If no list is given no presets will be created.
#		These patterns can currently only contain * and ? (see proc CheckGlob)
#  4. SearchLabels : A list of strings that are to be used for the preset-radiobuttons
#		discussed in 3. 
#		If no list is given or there are less labels than search patterns, 
#		the search pattern will be used as the label
#
# If the arguments are given correctly then you have a good file selection widget
#
# Written By Paul D. Sharpe
# Revision: 3
# Date: 17/2/95
#############################
# FileBrowser Procedure START  
proc FileBrowser { {Title "Load File"} \
		   {Colors {grey blue LightGrey MediumBlue helvetica }} \
		   { SearchLists {} } { SearchLabels {}} } {
#Globals	
global FB_Glob
global FB_CWD
global FB_Return
set FB_Glob "*"

  #!!!!!!!!!!!!!!!!!!!!!!!
  # Local procedures START

  # ----------------------
  # CheckGlob
  # To check whether a string is a glob pattern or not. 
  # Return a boolean where a string that is glob is true. 
  proc CheckGlob { pattern } {
  return [expr [string match *\\** $pattern] || [string match *\\?* $pattern]]
  }

  # -----------------------
  # FB_Exit 
  # Sort out the return value and return.
  proc FB_Exit { value } {
  global FB_Return
	set FB_Return $value
	destroy .filebrowse

  }


  # -----------------------
  # FB_Select
  # Callback to the OK button
  proc FB_Select { } {
	global FB_Glob

	set selection [.filebrowse.main.entry get]
	# Is the entry ...
	if {[CheckGlob $selection] } {
	# ...a glob pattern? (* & ? only)
			set FB_Glob $selection
		 	FB_RefreshList
	}\
	elseif {[file isdirectory $selection] } {
	# ... a directory ?
		cd $selection
		FB_RefreshList
	}\
 	else  {
	# ... a file ?
		if {$selection !=""} {
			FB_Exit "[pwd]/$selection"
		}
	}
	
  }

  # -----------------------
  # FB_Cancel
  # Callback to the cancel button
  proc FB_Cancel {} {
	FB_Exit ""
  }

  # -----------------------
  # FB_RefreshList
  # This fill the listbox with the files in a directory.
  proc FB_RefreshList { } {
	global FB_CWD
	global FB_Glob

	#fill the list box with the directory
	#directories
	.filebrowse.main.list delete 0 end
	.filebrowse.main.entry delete 0 end
	if {[pwd] != "/"} {
		.filebrowse.main.list insert end "../"
	}
	if {[catch { glob */}]==0 } { 
		foreach dir [lsort [glob */]] { 
		.filebrowse.main.list insert end $dir
		}
	}

	# Retrieve file names according to patterns in FB_Glob 
	foreach glob $FB_Glob {
     		if {[catch { glob $glob}]==0 } {        
			foreach file [lsort [glob $glob ]] {
				if {[file isfile $file]} { 
				.filebrowse.main.list insert end $file
				}
			}
     		}
  	}
  	# Set the Variable containing the (truncated) search path. (eg. ../dir/*.*)
  	set pathlist [split [pwd] /]
  	set end [expr [llength $pathlist] -1]
  	if {$end != -1} { set pre "../" }
  	if {[llength $FB_Glob] >1} {
		set globshow "[lindex $FB_Glob 0],..." 
  	}\
  	else {
		set globshow $FB_Glob
  	}
	# Truncate for display and add the search pattern.
  	set FB_CWD [format "%s%s/%s" $pre [lindex $pathlist $end ] $globshow]

  }

  # Local Procedures END
  #!!!!!!!!!!!!!!!!!!!!!!!
  global FB_Glob

  # Set color variables from the argument list.
  set ColVars [list BG FG ABG AFG FNT ]
  set i 0
  if {$Colors ==""} { 
	set Colors {grey blue LightGrey MediumBlue helvetica } 
  }
  foreach Var $ColVars {
	set $Var [lindex $Colors $i]
	incr i 
  }

  # Check that the desired font exists, if not replace by another.

  # Larger Font.
  if {[catch {set Font_L "-*-$FNT-Medium-R-Normal--*-120-*" }] !=0 } { 
	set Font_L -Adobe-Helvetica-Medium-R-Normal--*-120-* 
  }

  # Smaller Font
  if {[catch {set Font_S -*-$FNT-Medium-R-Normal--*-100-*}] !=0 } {
	set Font_S -Adobe-Helvetica-Medium-R-Normal--*-100-* 
  }

  # ==============================
  # Create toplevel .filebrowser .
  toplevel .filebrowse -bg $BG
  wm title .filebrowse $Title
  # Link to master toplevel as a servant.
  wm transient .filebrowse .
  # Stop entry from the main window. (grab).
  catch { grab .filebrowse }


  # ===============================
  # Create and Pack Widgets.
  # There a two frames into which the widgets are packed. 
  # 1. .main contains the entry, scrollbar and listbox.
  # 2. .button contains the cancel and OK buttons.
  # The Radio Buttons are packed straight into the toplevel.
  
  # ------------------------------
  # 1. .main  

  # The frame.
  frame .filebrowse.main -bg $BG

  # The Instruction label.
  label .filebrowse.main.label -bg $BG -fg $FG \
				-font $Font_S \
				-text "Enter a File Name" \
				-anchor w 

  # The Entry area.
  entry .filebrowse.main.entry -relief sunken -bg $BG -fg $FG 

  # The Listbox.
  listbox .filebrowse.main.list -relief sunken -bg $BG -fg $FG \
				-selectbackground $ABG \
				-selectforeground $AFG\
				-font $Font_L \
				-yscrollcommand ".filebrowse.main.scroll set"\
				-selectmode single
 
  # Fill the list box with the directory
  FB_RefreshList

  # The ScrollBar.
  scrollbar .filebrowse.main.scroll \
				-bg $BG  \
				-activebackground $ABG\
				-command ".filebrowse.main.list yview"\
				-relief sunken

  # Pack the .main widgets.
  pack .filebrowse.main.label .filebrowse.main.entry -fill x -expand 1
  pack .filebrowse.main.list  	-fill both -expand 1 -side left
  pack  .filebrowse.main.scroll -fill both -expand 1 -side right

  
  # The Preset RadioButtons.
 
  if { $SearchLists != "" } {
	set count 0
	set flag 1
	foreach list $SearchLists {
		set itemX 0
		set newlist $list
		# Check for valid patterns, delete invalid ones.
		foreach item $list {
			if {![CheckGlob $item]} {
				set newlist [lreplace $newlist $itemX $itemX]
			} else { incr itemX }
		}
		set list $newlist
		if { $flag && $list!=""} { 
			set FB_Glob $list
			incr flag -1
			# Fill the list box with the directory
  			FB_RefreshList 
		}
		# Determine what the label of the button should be,
		# a) a corresponding item in the SearchLabels list is exists or
		# b) the Search pattern	
		if {[lindex $SearchLabels $count] != ""} {
			set label [lindex $SearchLabels $count] 
		}\
		else {
			set label $list
		}
		# Create the RadioButton. 
		radiobutton .filebrowse.radio$count \
			-variable FB_Glob -value $list \
			-text $label \
			-relief flat \
			-bg $BG -font $Font_L \
			-fg $FG \
			-activebackground $BG \
			-activeforeground $FG \
			-anchor w \
			-selectcolor $AFG \
			-command { FB_RefreshList }

		# Pack the button into ..main
		pack .filebrowse.radio$count -expand 1 -fill x -side bottom -anchor w
		incr count
	}
  }


  # 2. .button

  # The frame.
  frame .filebrowse.button -bg $BG

  # The OK button and surrounding border.
  frame .filebrowse.button.okfr -relief sunken -bd 1 -bg $BG
  button .filebrowse.button.ok  -text OK -command FB_Select \
				-bg $BG -fg $FG \
				-activebackground $ABG \
				-activeforeground $AFG \
				-font $Font_L
  # The Cancel Button.
  button .filebrowse.button.cancel \
				-text Cancel \
				-command {FB_Cancel}\
				-bg $BG -fg $FG \
				-activebackground $ABG \
				-activeforeground $AFG \
				-font $Font_L
  
  # The Labels showing the current directory.
  frame .filebrowse.button.pwd -bg $BG
  label .filebrowse.button.pwd.dirlabel \
				-bg $BG -fg $FG \
				-font $Font_S \
				-textvariable FB_CWD \
				-anchor w

  label .filebrowse.button.pwd.label \
				-bg $BG -fg $FG \
				-font $Font_S \
				-text "Current Directory:"\
				-anchor w

  # Packing .button widgets.
  pack .filebrowse.button.okfr .filebrowse.button.cancel \
				-side top -expand 1 \
				-padx 3m -pady 2m 
  pack .filebrowse.button.ok 	-in .filebrowse.button.okfr \
				-side left -padx 3m -pady 2m \
				-ipadx 2m -ipady 1m 
  pack .filebrowse.button.pwd.dirlabel .filebrowse.button.pwd.label \
				-anchor sw -fill x \
				-side bottom
  pack .filebrowse.button.pwd 	-side top -expand 1 \
				-padx 3m -pady 2m

  #------------------------
  # Packing the Frames
  pack .filebrowse.main  -side left -fill both -expand 1
  pack .filebrowse.button -side left -anchor n -fill y

  # -----------------------
  # Bindings

  # Put the selection into the entry area.
  bind .filebrowse.main.list <Button-1> {
	.filebrowse.main.entry delete 0 end
	.filebrowse.main.entry insert 0 [%W get [%W nearest %y]]
  }

  # Link listbox and entry events to the OK button
  bind .filebrowse.main.list <Double-Button-1> {
	.filebrowse.button.ok invoke
	break
  }
  bind .filebrowse.main.entry <Return> {
	.filebrowse.button.ok invoke
  }

  # Link entry event to the Cancel button.
  bind .filebrowse.main.entry <Escape> {
	.filebrowse.button.cancel invoke
  }
  bind .filebrowse.main.entry <Control-Key-c>  { 
	FB_Exit {}
  }
  # Set the focus on the entry area.
  focus .filebrowse.main.entry
  #tkwait variable FB_Return
  tkwait window .filebrowse
  set temp $FB_Return
  unset FB_Return
  unset FB_Glob
  unset FB_CWD
  return $temp

# End of FileBrowser Procedure
}



###################################################################
# FileBrowser2; a file selection browser for TCL/Tk USEFUL FOR SAVING
#
# This Creates a toplevel .filebrowser, with an environment for 
# entering a new filename.

#
# All arguments are optional, (you may have to supply an empty string though)
# Summary of Arguments:
#   1. Title : The string to be contained in the toplevel widget.
#   2. Colors : A list containing color settings; the order is as follows
# 		[ BackGround ForeGround ActiveBG ActiveFG FontName ]
# 		Note that font name is not the full path, just eg. Times, Helvetica etc.
#   3. Search : A glob pattern for the file list to be displayed.
#   4. Filename : and Initial filename to be displayed in entry.
#   5. RadioList : A list of items to form radio buttons. This allows additional
#		  information to be added. Empty list means no buttons.
#		  first item in list is a title indicateing what the buttons are for.
# Returns: The filename and the selected radio button
#
# Written By Paul D. Sharpe
# Revision: 1
# Date: 17/3/95
#############################
# FileBrowser2 Procedure START  
proc FileBrowser2 { {Title "Save File"} \
		   {Colors {}} { Search {*} }\
		   {Filename {}} { RadioList {}} } {
#Globals	
global FB_Glob
global FB_CWD
global FB_Return
global FB_Radio
set FB_Radio ""
set FB_Glob "*"

  #!!!!!!!!!!!!!!!!!!!!!!!
  # Local procedures START

  # ----------------------
  # CheckGlob
  # To check whether a string is a glob pattern or not. 
  # Return a boolean where a string that is glob is true. 
  proc CheckGlob { pattern } {
  return [expr [string match *\\** $pattern] || [string match *\\?* $pattern]]
  }

  # -----------------------
  # FB_Exit 
  # Sort out the return value and return.
  proc FB_Exit { value } {
  global FB_Return
	set FB_Return $value
	destroy .filebrowse
  }


  # -----------------------
  # FB_Select
  # Callback to the OK button
  proc FB_Select { } {
	global FB_Glob

	set selection [.filebrowse.main.entry get]
	# Is the entry ...
	if {[CheckGlob $selection] } {
	# ...a glob pattern? (* & ? only)
			set FB_Glob $selection
		 	FB_RefreshList
	}\
	elseif {[file isdirectory $selection] } {
	# ... a directory ?
		cd $selection
		FB_RefreshList
	}\
 	else  {
	# ... a file ?
		if {$selection !=""} {
			FB_Exit "[pwd]/$selection"
		}
	}
	
  }

  # -----------------------
  # FB_Cancel
  # Callback to the cancel button
  proc FB_Cancel {} {
	FB_Exit ""
  }

  # -----------------------
  # FB_RefreshList
  # This fill the listbox with the files in a directory.
  proc FB_RefreshList { } {
	global FB_CWD
	global FB_Glob

	#fill the list box with the directory
	#directories
	.filebrowse.main.list delete 0 end
	.filebrowse.main.entry delete 0 end
	if {[pwd] != "/"} {
		.filebrowse.main.list insert end "../"
	}
	if {[catch { glob */}]==0 } { 
		foreach dir [lsort [glob */]] { 
		.filebrowse.main.list insert end $dir
		}
	}

	# Retrieve file names according to patterns in FB_Glob 
	foreach glob $FB_Glob {
     		if {[catch { glob $glob}]==0 } {        
			foreach file [lsort [glob $glob ]] {
				if {[file isfile $file]} { 
				.filebrowse.main.list insert end $file
				}
			}
     		}
  	}
  	# Set the Variable containing the (truncated) search path. (eg. ../dir/*.*)
  	set pathlist [split [pwd] /]
  	set end [expr [llength $pathlist] -1]
  	if {$end != -1} { set pre "../" }
  	if {[llength $FB_Glob] >1} {
		set globshow "[lindex $FB_Glob 0],..." 
  	}\
  	else {
		set globshow $FB_Glob
  	}
	# Truncate for display and add the search pattern.
  	set FB_CWD [format "%s%s/%s" $pre [lindex $pathlist $end ] $globshow]

  }

  # Local Procedures END
  #!!!!!!!!!!!!!!!!!!!!!!!
  global FB_Glob

  # Set color variables from the argument list.
  set ColVars [list BG FG ABG AFG FNT ]
  set i 0
  if {$Colors ==""} { 
	set Colors {grey blue LightGrey MediumBlue helvetica } 
  }
  foreach Var $ColVars {
	set $Var [lindex $Colors $i]
	incr i 
  }

  # Check that the desired font exists, if not replace by another.

  # Larger Font.
  if {[catch {set Font_L "-*-$FNT-Medium-R-Normal--*-120-*" }] !=0 } { 
	set Font_L -Adobe-Helvetica-Medium-R-Normal--*-120-* 
  }

  # Smaller Font
  if {[catch {set Font_S -*-$FNT-Medium-R-Normal--*-100-*}] !=0 } {
	set Font_S -Adobe-Helvetica-Medium-R-Normal--*-100-* 
  }

  # ==============================
  # Create toplevel .filebrowser .
  toplevel .filebrowse -bg $BG
  wm title .filebrowse $Title
  # Link to master toplevel as a servant.
  wm transient .filebrowse .
  # Stop entry from the main window. (grab).
  catch { grab .filebrowse }


  # ===============================
  # Create and Pack Widgets.
  # There a two frames into which the widgets are packed. 
  # 1. .main contains the entry, scrollbar and listbox.
  # 2. .button contains the cancel and OK buttons.
  # The Radio Buttons are packed straight into the toplevel.
  
  # ------------------------------
  # 1. .main  

  # The frame.
  frame .filebrowse.main -bg $BG

  # The Instruction label.
  label .filebrowse.main.label -bg $BG -fg $FG \
				-font $Font_S \
				-text "Enter a File Name" \
				-anchor w 

  # The Entry area.
  entry .filebrowse.main.entry -relief sunken -bg $BG -fg $FG 
  # Set inital value of enrty area

  # The Listbox.
  listbox .filebrowse.main.list -relief sunken -bg $BG -fg $FG \
				-selectbackground $ABG \
				-selectforeground $AFG\
				-font $Font_L \
				-yscrollcommand ".filebrowse.main.scroll set"\
				-selectmode single

  # Fill the list box with the directory
  FB_RefreshList

  # The ScrollBar.
  scrollbar .filebrowse.main.scroll \
				-bg $BG   \
				-activebackground $ABG\
				-command ".filebrowse.main.list yview"\
				-relief sunken

  # Pack the .main widgets.
  pack .filebrowse.main.label .filebrowse.main.entry -fill x -expand 1
  pack .filebrowse.main.list  	-fill both -expand 1 -side left
  pack  .filebrowse.main.scroll -fill y -side right

  
  # The RadioButtons.
 
  if { $RadioList != "" } {
	#Create Frame
	frame .filebrowse.radiofr -bg $BG -bd 2 -relief groove
	#Create the Label
	label .filebrowse.radiofr.label -bg $BG -fg $FG \
				-font $Font_S \
				-text [lindex $RadioList 0] \
				-anchor w
	pack .filebrowse.radiofr.label -fill x -expand 1

	# Retrieve # Buttons to be in a row and width of buttons
	set ButtonsPerRow [lindex $RadioList 1]
	set ButtWidth [lindex $RadioList 2]
	# Remove the retrived data from  list
	set RadioList [lrange $RadioList 3 end]

	set line 0
	set count 0
	set length [llength $RadioList] 
	while {$count<$length} {

	   set i $ButtonsPerRow
	   # Create Frame
	   frame .filebrowse.radiofr.$line -bg $BG -bd 2

	   while {$i>0 && $count< $length} {
		# Get item from list			
		set item [lindex $RadioList $count]
		# Create the RadioButton. 
		radiobutton .filebrowse.radiofr.$line.$i \
			-variable FB_Radio -value $item \
			-text $item \
			-relief sunken \
			-bg $BG -font $Font_L \
			-fg $FG \
			-activebackground $BG \
			-activeforeground $FG \
			-anchor w \
			-selectcolor $AFG 
		if {$ButtWidth !=""} {
			.filebrowse.radiofr.$line.$i config -width $ButtWidth	
		}
		# Pack the button into frame
		pack .filebrowse.radiofr.$line.$i -expand 1 -fill x -side left -anchor w

		# Decrement i
		incr i -1
		# Increment Count (to get next item)
		incr count
	   }
		# Pack the line
		pack .filebrowse.radiofr.$line -fill x -expand 1
		# Increment the line number
		incr line
	}

	# Pack the RadioButtons into main
	pack .filebrowse.radiofr -side bottom -fill x -expand 1 -pady 4


  }


  # 2. .button

  # The frame.
  frame .filebrowse.button -bg $BG

  # The OK button and surrounding border.
  frame .filebrowse.button.okfr -relief sunken -bd 1 -bg $BG
  button .filebrowse.button.ok  -text OK -command FB_Select \
				-bg $BG -fg $FG \
				-activebackground $ABG \
				-activeforeground $AFG \
				-font $Font_L
  # The Cancel Button.
  button .filebrowse.button.cancel \
				-text Cancel \
				-command {FB_Cancel}\
				-bg $BG -fg $FG \
				-activebackground $ABG \
				-activeforeground $AFG \
				-font $Font_L
  
  # The Labels showing the current directory.
  frame .filebrowse.button.pwd -bg $BG
  label .filebrowse.button.pwd.dirlabel \
				-bg $BG -fg $FG \
				-font $Font_S \
				-textvariable FB_CWD \
				-anchor w

  label .filebrowse.button.pwd.label \
				-bg $BG -fg $FG \
				-font $Font_S \
				-text "Current Directory:"\
				-anchor w

  # Packing .button widgets.
  pack .filebrowse.button.okfr .filebrowse.button.cancel \
				-side top -expand 1 \
				-padx 3m -pady 2m 
  pack .filebrowse.button.ok 	-in .filebrowse.button.okfr \
				-side left -padx 3m -pady 2m \
				-ipadx 2m -ipady 1m 
  pack .filebrowse.button.pwd.dirlabel .filebrowse.button.pwd.label \
				-anchor sw -fill x \
				-side bottom
  pack .filebrowse.button.pwd 	-side top -expand 1 \
				-padx 3m -pady 2m

  #------------------------
  # Packing the Frames
  pack .filebrowse.main  -side left -fill both -expand 1
  pack .filebrowse.button -side left -anchor n -fill y

  # -----------------------
  # Bindings

  # Put the selection into the entry area.
  bind .filebrowse.main.list <Button-1> {
	.filebrowse.main.entry delete 0 end
	.filebrowse.main.entry insert 0 [%W get [%W nearest %y]]
  }

  # Link listbox and entry events to the OK button
  bind .filebrowse.main.list <Double-Button-1> {
	.filebrowse.button.ok invoke
	break
  }
  bind .filebrowse.main.entry <Return> {
	.filebrowse.button.ok invoke
  }

  # Link entry event to the Cancel button.
  bind .filebrowse.main.entry <Escape> {
	.filebrowse.button.cancel invoke
  }
  bind .filebrowse.main.entry <Control-Key-c>  { 
	FB_Exit {}
  }
  # Set the focus on the entry area.
  focus .filebrowse.main.entry
  .filebrowse.main.entry insert 0 $Filename
  tkwait variable FB_Return
  set temp [list $FB_Return $FB_Radio]
  unset FB_Return
  unset FB_Glob
  unset FB_CWD
  unset FB_Radio
  return $temp

# End of FileBrowser2 Procedure
}  
 
