

proc AddConf { fid var_var setto expl } {
  global glob config 
  upvar $var_var var
  puts -nonewline $fid {#-----------------------------------------------------------------------}
#-----------------------------------------------------------------------
  #puts -nonewline $fid "# Variable: $var_var"
  puts $fid "$expl"
  if { $setto == "" } {
    puts $fid "set $var_var \{$var\}"
  } else {
    puts -nonewline $fid "set $var_var $setto"
  }
  puts $fid ""
}

proc SaveConfig {}  {
  global glob config env
  set r [catch {open $glob(conf_dir)/config w} fid]
  if {$r != 0} { PopError "Saving config: $fid"; return "" }

puts $fid "# Generated by FileRunner $glob(version) on [clock format [clock seconds]]"
  
  puts $fid {
# This is the configuration file for FileRunner. It is read every time
# FileRunner starts up. It is saved in your home directory as
# "~/.fr/config" (~ is short for the path to your home directory). Make
# sure to only edit values for variables that are listed. Do not add or
# delete anything, since this file will be automatically regenerated
# when you do a "Edit Configuration->Save Configuration" in the menu and those
# changes will be lost.
#
# This config file is saved to disk and reread into FileRunner when you
# press the OK button in the config browser. You can also edit this file
# with a regular text editor and re-read it into FileRunner with
# "Configuration->Reread Configuration"
}

  AddConf $fid config(hotlist) "{" {
# This list is what will show up in your HotList menu. (Like "bookmarks"
# in Netscape). Feel free to edit this list.
}
  foreach k $glob(hotlist) {
    if { [lindex $k 1] != "" } {
      puts $fid "    {$k}"
    } else {
      puts $fid "    $k"
    }
  }
  puts $fid "  }\n"

  puts $fid {
#****** COMMAND CONFIGURATION ******************************************
}

  AddConf $fid config(editor) "" {
# This variable should be set to the name of your favourite text
# editor. This editor will be invoked when you select files and press
# the "Edit" button. The text editor you choose should be an
# X-application, not a text-terminal application. You can start
# text-terminal edtiors for example by launching them from inside an
# xterm. E.g: "xterm -e vi %s". The editor you choose should be able to
# load multiple files specified as arguments to the editor (e.g: 
# "emacs /tmp/foo /home/joe/bar"). The editor will be launched in the
# background.
}

  AddConf $fid config(view,extensions) "" {
# This parameter contains a list of commands and the file patterns that
# are used when finding the right viewer for various files. The commands
# will receive a list of selected files. The first file in the selected
# list are used when deciding which viewer should be used. (Don't try
# and view a couple of text files and images simultaneously by selecting
# and pressing the view button). If you add a the option "-viewtext"
# last in the rule that means the command outputs a listing/view and it
# should be viewed in the internal text viewer. The viewing commands
# will be executed in the background.
}

  AddConf $fid config(cmd,print) "" {
# The print command you want to use to print files.
}

  AddConf $fid config(cmd,term) "" {
# The name of your favourite terminal program.
# This is the program that will be launched when you press the button
# with the image of the terminal window (upper right of the file list
# panels). It will be launched in the background.
}

  AddConf $fid config(cmd,diff) "" {
# Your favourite diff command. Should be able to diff directories also.
# Used in the "Diff" button command. This program will run
# synchronously, i.e. FileRunner will wait until it's done.
}

  puts $fid {
#****** ARCHIVER/PACKER CONFIGURATION **********************************
}

  AddConf $fid config(cmd,unarc,extensions) "" {
# Extensions and bindings for unarchive rules. This is a list of
# commands and file name extensions. FileRunner will use this variable
# when deciding which command should be used to unarchive the file when
# you press the UnArc button.
}

  AddConf $fid config(cmd,unpack,extensions) "" {
# Extensions and bindings for unpacking rules. This is a list of
# commands and file name extensions. FileRunner will use this variable
# when deciding which command should be used to unpack the file when you
# press the UnPack button.
}

  AddConf $fid config(cmd,pack) "" {
# The name of your favourite packer command. 
# Used in the "Arc" button command to pack files. Run synchronously
# or in the background.
}

  AddConf $fid config(cmd,archive) "" {
# This is the name of your archiver program. The archiver program is
# passed the name of the directory selected and is executed in the
# current directory. The archive created is supposed to contain the
# contents of the directory. The default builtin "tar+gz {%s}" creates
# an archive named <directory>.tar.gz packed with tar and gzip. This
# command is used in the "Arc" button command to pack/archive
# directories. Can be run synchronously or in the background.
}

  puts $fid {
#****** FTP CONFIGURATION **********************************************
}

  AddConf $fid config(ftp,login) "" {
# Rule based login information. Allows automatic determination
# if the login should use a proxy and what username/password it
# should use etc.
# See the online guide, chapter 8.8.
}

  AddConf $fid config(ftp,fastlink) "" {
# Set this to 1 if you feel your FTP connections are fast, to 0
# otherwise. If you set it to 1, soft-links in FTP listings are
# correctly identified either as links to directories or to files,
# otherwise it will always think links are links to directories.
}

  AddConf $fid config(ftp,proxy) "" {
# If you have to go through a firewall via an FTP proxy, set this
# variable to the hostname of your FTP proxy. Set it to "" if you don't
# have an FTP proxy.
}

#  AddConf $fid config(ftp,user) "" {
# Set username for FTP sessions. If you are doing anonymous FTP, set
# this to "anonymous".
#}

  AddConf $fid config(ftp,password) "" {
# Set password for anonymous FTP sessions. This should be your 
# email address.
}

  AddConf $fid config(ftp,timeout) "" {
# Set timeout in seconds for FTP communication. 
}

  AddConf $fid config(ftp,anonymous) "" {
# 1 -> Do anonymous FTP
# 0 -> Log in to FTP with username and password.
}

  AddConf $fid config(ftp,useproxy) "" {
# 1 -> Use defined ftp proxy
# 0 -> Don't use proxy (to access hosts inside the proxy/firewall)
}

  AddConf $fid config(ftp,cache,maxentries) "" {
# Maximum number of directory listings the cache should hold.
}

  AddConf $fid config(ftp,cd_pwd) "" {
# If true (non-zero): When doing a cd to a new directory, FileRunner
# will run pwd to check where it ended up (which makes a difference
# if you cd to a link which points to a directory).
}

  puts $fid {
#****** HTTP CONFIGURATION *********************************************
}

  AddConf $fid config(http,proxy) "" {
# HTTP proxy. Format: host:port (for example: proxy.foo.com:80). 
# Leave empty if you have a direct connection to the net.
}

  puts $fid {
#****** APPEARANCE CONFIGURATION ***************************************
}

  AddConf $fid config(gui,color_bg) "" {
# Background color of listboxes etc.
# You can edit this easier from the configuration menu.
}

  AddConf $fid config(gui,color_fg) "" {
# Foreground color of listboxes etc.
# You can edit this easier from the configuration menu.
}

  AddConf $fid config(gui,color_cmd) "" {
# Color for commands in the command window.
# You can edit this easier from the configuration menu.
}

  AddConf $fid config(gui,color_select_bg) "" {
# Selection background color.
# You can edit this easier from the configuration menu.
}

  AddConf $fid config(gui,color_select_fg) "" {
# Selection foreground color.
# You can edit this easier from the configuration menu.
}

  AddConf $fid config(gui,color_scheme) "" {
# Scheme color.
# Default Tk seems to be "grey85".
# You can edit this easier from the configuration menu.
}

  AddConf $fid config(gui,color_cursor) "" {
# Cursor color.
# You can edit this easier from the configuration menu.
}

  AddConf $fid config(gui,font) "" {
# Font for listboxes etc. Must be fixed-width.
# Some good choices:
#  screen-bold-12
#  *-lucidatypewriter-bold-r-normal-*-12-*
#  *-lucidatypewriter-bold-r-normal-*-14-*
#  *-courier-bold-r-normal-*-14-*
}

  AddConf $fid config(gui,font_scheme) "" {
# Font for default Tcl/Tk stuff (menus, buttons etc.)
# Set this to "" in order to not change from what it already is.
# Default Tk seems to be "-Adobe-Helvetica-Bold-R-Normal--*-120-*-*-*-*-*-*"
}

  AddConf $fid config(geometry,main) "" {
# The X11 geometry string deciding where and how big the FileRunner
# main window should be at startup.
}

  AddConf $fid config(geometry,textviewer) "" {
# The X11 geometry string deciding where and how big the FileRunner
# text viewer window should be.
}

  AddConf $fid config(geometry,qedit) "" {
# The X11 geometry string deciding where and how big the FileRunner
# quick-editor window should be.
}

  AddConf $fid config(middle_button_colors) "" {
# This contains a list of background colors for the middle row command
# buttons. The syntax is:
#  set config(middle_button_colors) {
#    { ButtonName [-]Color }
#    ...
#  }
# An example:
#  set config(middle_button_colors) {
#    { Copy #0000ff }
#    { Delete red }
#    { Move -red }
#  }
# The Copy button will be blue and the Delete button will be red.
# The Move button will turn red only when the mouse moves over it.
# Buttons not mentioned will get the default scheme color.
# You need to restart FileRunner for this to have effect.
}

  puts $fid {
#****** SHELL CONFIGURATION ********************************************
}

  AddConf $fid config(shell,height,left) "" {
# Height in lines of text of the left shell text window.
}

  AddConf $fid config(shell,height,right) "" {
# Height in lines of text of the right shell text window.
}

  AddConf $fid config(shell,buffer) "" {
# Size of shell buffer, in lines of text.
}

  AddConf $fid config(shell,aliases) "{" {
# Shell aliases, in the form of a list of tuples: " { alias, command } .. "
# If there are arguments to the command line they are just tagged onto the
# alias. (I.e, aliases can take arguments)
}
  foreach k $config(shell,aliases) {
    if { [lindex $k 1] != "" } {
      puts $fid "    {$k}"
    } else {
      puts $fid "    $k"
    }
  }
  puts $fid "  }\n"

  puts $fid {
#****** MISC CONFIGURATION *********************************************
}

  AddConf $fid config(startpwd,left) "" {
# At startup, show this directory in the left panel.
# If you set it to "", FileRunner will show the directory from where 
# it was invoked.
}

  AddConf $fid config(startpwd,right) "" {
# At startup, show this directory in the right panel
# If you set it to "", FileRunner will show the directory from where 
# it was invoked.
}

  AddConf $fid config(fileshow,all) "" {
# 1 -> Will show files beginning with a dot ".".
# 0 -> Won't.
}

  AddConf $fid config(fileshow,sort) "" {
# This variable determines how file listings are sorted. Possible values
# are "nameonly", "dirsfirst", "dirslast", "time" and "size"
}

  AddConf $fid config(dateformat) "" {
# Sets date format. Possible values "yymmdd" and "ddmmyy".
# (yy=year mm=month dd=day)
}

  AddConf $fid config(autoupdate) "" {
# Sets how often FileRunner checks to see if it needs to update its 
# windows.
# Set this to 0 to disable. Value is in seconds.
}

  AddConf $fid config(logsize) "" {
# Size of log in bytes. Don't set this too high, or FileRunner might 
# slow down a little. When the log exceeds this size, it will be 
# truncated.  
}

  AddConf $fid config(check_ownership) "" {
# If this is "1", FileRunner will check as best as it can if you are
# about to overwrite or delete a file you do not own and warn you about
# it. This can be handy when working in groups with other people and you
# want an extra check that you don't accidentally erase someone elses
# files.  This will slow some operations down slightly.
}

  AddConf $fid config(keyb_support) "" {
# If this is 1, you will make the file listbox take focus when clicked
# and this will let you use the keyboard for traversing the list (using
# arrows and PgUp/PgDown) and issuing commands.
# You'll have to restart FileRunner to get this setting to have effect.
}

  AddConf $fid config(ask,dir_delete) "" {
# If 1, FileRunner will ask you if you are sure when you delete 
# directories. If 0, it will go ahead and delete without asking.
}

  AddConf $fid config(ask,file_delete) "" {
# If 1, FileRunner will ask you if you are sure when you delete 
# files. If 0, it will go ahead and delete without asking.
}

  AddConf $fid config(mwheel,delta) "" {
# For "wheel"-mice (MS Intellimouse or Logitech MouseMan+), set
# number of lines to scroll when turning mouse wheel.
}

  AddConf $fid config(mwheel,neg) "" {
# For "wheel"-mice (MS Intellimouse or Logitech MouseMan+), set
# mouse button to use for negative scroll movement.
}

  AddConf $fid config(mwheel,pos) "" {
# For "wheel"-mice (MS Intellimouse or Logitech MouseMan+), set
# mouse button to use for positive scroll movement.
}

  AddConf $fid config(save_conf_at_exit) "" {
# If true (non-zero): FileRunner will automatically save configuration and
# hotlist at exit.
}

  AddConf $fid config(create_relative_links) "" {
# If true (non-zero): FileRunner will create relative links
# instead of absolute links. (e.g ../../foo instead of /a/b/c/foo)
}

  AddConf $fid config(cd_pwd) "" {
# If true (non-zero): When doing a cd to a new directory, FileRunner
# will run pwd to check where it ended up (which makes a difference
# if you cd to a link which points to a directory).
}


  puts $fid {
#****** DANGEROUS CONFIGURATION ****************************************
# Below this point you can change some of the stuff that is used
# internally by FileRunner. This should almost never be necessary if the
# platform is standard Unix or close to standard Unix. If you change any
# of this below, make very very sure you get it right. If you are
# unsure, don't touch it. If you get it wrong, very bad things can
# happen...
# 
# A note on having the full path to the commands below, like using
# "/bin/cp" and not just "cp": Lets say you have a dot "." in your path
# and someone really mean has created a command called "cp" in his home
# directory that does a "rm" instead. Then you cd to his home directory
# and type cp <something>, you will invoke his evil manipulated version
# of cp that removes whatever you inteded to copy. The morale of this is
# to always use full path to critical commands and hope your sysop is
# not so mean he will rename "/bin/rm" to "/bin/mkdir"...
# A few commands below do not have specified full path, that's because
# they aren't very critical and seem to move around between different
# versions of Unix.
}

  AddConf $fid config(cmd,sh) "" {
# The bourne-shell command. This should almost always be /bin/sh.
}

  AddConf $fid config(cmd,rm) "" {
# The rm (remove-files) command. This should almost always be /bin/rm.
}

  AddConf $fid config(cmd,cp) "" {
# The cp (copy-files) command. This should almost always be /bin/cp.
}

  AddConf $fid config(cmd,ln) "" {
# The ln (link) command. This should almost always be /bin/ln.
}

  AddConf $fid config(cmd,chmod) "" {
# The change mode (chmod) command. This should almost always be /bin/chmod.
}

  AddConf $fid config(cmd,touch) "" {
# The touch command.
}

  AddConf $fid config(cmd,du) "" {
# The "du" command. Should return size in kilobytes. On many
# systems other than BSD (?) you need to add a -k argument
# to this command to get it in kilobytes.
}

  AddConf $fid config(cmd,find) "" {
# The find command.
}

  close $fid
  Log "Configuration saved to $glob(conf_dir)/config"
}

proc InitConfig {} {
  global glob config env argv

  set config(hotlist) ""
  if {[info exists env(EDITOR)]} {
    set config(editor) "$env(EDITOR) {%s}"
  } else {
    set config(editor) "xterm -e vi {%s}"
  }
  set config(fileshow,all) 0
  set config(fileshow,sort) "dirsfirst"

  set config(cmd,print) "lpr {%s}"
  set config(cmd,term) "xterm"
  set config(cmd,diff) "diff -r {%s} {%s}"
  set config(cmd,pack) "gzip {%s}"
  set config(cmd,archive) "tar+gz {%s}"

  set config(cmd,unarc,extensions) {
  { {gzip -cd {%s} | tar xfBp -}
    {*.tgz *.taz *.tar.z *.tar.gz} }
  { {tar xfBp {%s}}
    {*.tar} }
  { {unzip -oqq {%s}}
    {*.zip} }
  { {lha -x {%s}}
    {*.lha} }
}

  set config(cmd,unpack,extensions) {
  { {gzip -d {%s}}
    {*.gz} }
}

  set config(startpwd,left) ""
  set config(startpwd,right) ""
  set config(ask,dir_delete) "1"
  set config(ask,file_delete) "0"
  set config(ftp,fastlink) 0
  set config(ftp,proxy) ""
  set config(ftp,user) anonymous
  set config(ftp,password) ""
  set config(ftp,timeout) "120"
  set config(ftp,anonymous) 1
  set config(ftp,useproxy) 1
  set config(ftp,login) {}
  set config(ftp,cache,maxentries) 15
  set config(ftp,cd_pwd) 1
  set config(http,proxy) {}
  #set config(gui,color_bg) FloralWhite
  set config(gui,color_bg) {#e8b3e570deed}
  set config(gui,color_fg) Black
  set config(gui,color_cmd) "#ffffe4e679db"
  set config(gui,color_select_bg) "#f1a9ec43aa9d"
  set config(gui,color_select_fg) black
  set config(gui,color_scheme) "grey85"
  #set config(gui,color_scheme) {#bfeed0add9da}
  set config(gui,color_cursor) black
  set config(gui,font_scheme) ""

  foreach testfont { 
      *-lucidatypewriter-bold-r-normal-*-12-*
      screen-bold-12 
      *-lucidatypewriter-bold-r-normal-*-14-*
      *-courier-bold-r-normal-*-14-* 
      fixed 
      } {
    set config(gui,font) $testfont
    set r [catch { label .foo -font $testfont } out]
    catch {destroy .foo}
    #puts "$r $out"
    if {$r == 0} {
      break
    }
  }

  set config(middle_button_colors) {
  { Delete -#ff4d4d }
}

  set config(keyb_support) 0
  set config(dateformat) "yymmdd"
  set config(autoupdate) 20
  set config(logsize) 5000
  set config(check_ownership) 0
  set config(geometry,main) "840x720+31+0"
  set config(geometry,textviewer) "80x30"
  set config(geometry,qedit) "80x30"
  set config(shell,height,left) 10
  set config(shell,height,right) 10
  set config(shell,buffer) 1000
  set config(shell,aliases) {{.. {cd ..}} {md mkdir} {m view} {more view} {less view}}
  set config(view,extensions) {
  { {xmikmod {%s}}
    {*.mod.gz *.s3m *.mtm *.stm *.xm *.uni *.mod} }
  { {timidity {%s}}
    {*.midi.gz *.midi *.mid.gz *.mid} }
  { {xv -gamma 2.0 {%s}}
    { *.bmp *.iff *.jpg *.pbm *.pgm *.png *.ppm *.tga *.tif *.tiff *.xbm *.xpm *.gif} }
  { {gzip -dc {%s} | ghostview -}
    { *.ps.gz } }
  { {ghostview {%s}}
    { *.ps } }
  { {xanim {%s}}
    {*.avi *.fli *.flc *.mpg} }
  { {gzip -cd {%s} | tar tvf -} 
    { *.tgz *.taz *.tar.z *.tar.gz }
    -viewtext }
  { {tar tvf {%s}}
    {*.tar}
    -viewtext }
  { {unzip -lv {%s}}
    {*.zip}
    -viewtext }
  { {lha -v {%s}}
    {*.lha}
    -viewtext }
  { {gzip -cd {%s}}
    {*.gz}
    -viewtext }
  { {rpm -qilp {%s}}
    {*.rpm}
    -viewtext }
}

  set config(cmd,sh) "/bin/sh"
  set config(cmd,rm) "/bin/rm"
  set config(cmd,cp) "/bin/cp"
  set config(cmd,ln) "/bin/ln"
  set config(cmd,chmod) "/bin/chmod"
  set config(cmd,touch) "touch"
  set config(cmd,du) "du -s"
  set config(cmd,find) find

  set config(mwheel,delta) 6
  set config(mwheel,neg) <4>
  set config(mwheel,pos) <5>

  set config(save_conf_at_exit) 1

  set config(create_relative_links) 1
  set config(cd_pwd) 1

  set glob(searchstring) ""
  set glob(log) ""
  set glob(left,pwd)  [Pwd]
  set glob(right,pwd) [Pwd]
  set glob(left,update_oldpwd) $glob(left,pwd)
  set glob(right,update_oldpwd) $glob(right,pwd)
  set glob(left,newpwd_oldpwd) $glob(left,pwd)
  set glob(right,newpwd_oldpwd) $glob(right,pwd)
  set glob(left,filelist) {}
  set glob(right,filelist) {}
  set glob(hotlist) {}
  set glob(toplevelidx) 0
  set glob(entry_dialog_return) {}
  set glob(ftp_entry_dialog_return) {}
  set glob(ftp,serverport,start) 5000
  set glob(ftp,serverport,end) 65000
  # This is an ugly hack to avoid reusing ports too fast, but it's because of a limitiation in the tcl socket
  # command. (You can't make the socket -server command choose a port by itself...)
  set glob(ftp,serverport,last) [expr 5000 + (([pid] * 100) % (65000 - 5000))]
  set glob(ftp,serversocket,acceptlist) {}
  set glob(forceupdate) 0
  set glob(havedoneftp) 0
  set glob(enableautoupdate) 1
  set glob(left,df) ?
  set glob(right,df) ?
  set glob(abortcmd) 0
  set glob(left,dirstack) ""
  set glob(right,dirstack) ""
  set glob(left,shell,packed) 0
  set glob(right,shell,packed) 0
  set glob(shell,maxed) 0
  set glob(left,shell,history) {}
  set glob(right,shell,history) {}
  set glob(left,shell,complete,flipping) 0
  set glob(right,shell,complete,flipping) 0
  set glob(left,shell,history,flipping) 0
  set glob(right,shell,history,flipping) 0
  set glob(left,shell,history,flipping,index) 0
  set glob(right,shell,history,flipping,index) 0
  set glob(batchlist) {}
  set glob(tmpdir) $glob(conf_dir)/tmp

  set glob(win,top) .fupper.ftop
  set glob(win,left) .fupper.fleft
  set glob(win,right) .fupper.fright
  set glob(win,middle) .fupper.fmiddle
  set glob(win,bottom) .flower

  set glob(gui,color_xx,winlist) ""
  set glob(gui,color_cmd,winlist) ""
  set glob(gui,color_scheme,winlist) ""
  set glob(gui,tablist) ""

  # These configuration have already been incorporated, since they are used when creating
  # new widgets. (No widgets have been created yet)
  set glob(gui,color_bg)      $config(gui,color_bg)
  set glob(gui,color_fg)      $config(gui,color_fg)
  set glob(gui,color_cmd)     $config(gui,color_cmd)
  set glob(gui,color_select_bg)  $config(gui,color_select_bg)
  set glob(gui,color_select_fg)  $config(gui,color_select_fg)
  # These configuration have not been set yet, must be done in ReConfigColors
  set glob(gui,color_scheme) ""
  set glob(gui,font_scheme) ""
  set glob(gui,color_cursor) ""

  set glob(gui,font) $config(gui,font)
  set glob(gui,font_scheme) ""

  set glob(async) 0
  set glob(left,shellcount) 0
  set glob(right,shellcount) 0

  if {![info exists env(USER)]} {
    if {![info exists env(LOGNAME)]} {
      PopError "Cannot read \$USER or \$LOGNAME environment variable. FileRunner cannot work without this correctly set."
      CleanUp 1
    }
    set env(USER) $env(LOGNAME)
  }
  if {![info exists env(HOME)]} {
    PopError "Cannot read \$HOME environment variable. FileRunner cannot work without this correctly set."
    CleanUp 1
  }
  if {![info exists env(HOST)]} {
    set env(HOST) unknown
  }
  if {$env(HOST) == "unknown"} {
    set r [catch { exec uname -n } out]
    if {!$r} {
      set env(HOST) $out
    }
  }

  set glob(history) ""
  # read history from disk
  if { [file exists $glob(conf_dir)/history ] } {
    set r [catch {set fid [open $glob(conf_dir)/history r];gets $fid glob(history);close $fid} out]
    if {$r} {
      puts "FileRunner: Can't read directory history from disk: $out"
    }
  }

  # set up a few default options
#  option add *HighlightThickness 1 widgetDefault
  option add *InsertWidth 2 widgetDefault
  option add *Scrollbar.Width 11 widgetDefault
  option add *Button.BorderWidth 1 widgetDefault
  option add *Scrollbar.BorderWidth 2 widgetDefault
#  option add *Listbox.BorderWidth 2 widgetDefault # makes the spacing between list elements too large...
  option add *Frame.BorderWidth 2 widgetDefault
  option add *Entry.BorderWidth 2 widgetDefault
#  option add *.Text.InsertBackground red widgetDefault
#  option add *insertBorderWidth 2 widgetDefault
#  option add *BorderWidth 1 widgetDefault
}

proc ReadConfig {} {
  global glob config env argv argv0
  if {[file readable $glob(lib_fr)/config]} {
    set r [catch {source $glob(lib_fr)/config} out]
    if {$r} {
      tk_dialog .error_dialog "Init error" "Reading system wide configuration from $glob(lib_fr)/config:\n$out" error 0 "OK"
    }
  }
  if {[file readable $glob(conf_dir)/config]} {
    set r [catch {source $glob(conf_dir)/config} out]
    if {$r} {
      tk_dialog .error_dialog "Init error" "Reading user configuration $glob(conf_dir)/config:\n$out" error 0 "OK"
    }
  }
  set glob(hotlist) $config(hotlist)
  if {$config(ftp,password) == "" } {
    set r [catch {set config(ftp,password) "$env(USER)@[exec domainname]"}]
  }
  foreach k { left right } {
    if { $config(startpwd,$k) != "" && !$glob(init_done)} {
      catch { cd $config(startpwd,$k); set glob($k,pwd) [Pwd] } out
    }
  }
  if { $config(ftp,proxy) == "" } {
    set config(ftp,useproxy) 0
  }
  if { $config(dateformat) == "ddmmyy" } {
    GetTimeFromSecsSetFormat 1
  }
  if { $config(dateformat) == "yymmdd" } {
    GetTimeFromSecsSetFormat 0
  }
  ReConfigColors
  ReConfigFont
}

proc ConfigPwd {} {
  global glob config env argv argv0
  set pwd(left) [lindex $argv 1]
  set pwd(right) [lindex $argv 2]
  foreach k { left right } {
    if { $pwd($k) != "" && $glob($k,pwd) != $pwd($k) } {
      NewPwd $k $pwd($k)
      UpdateWindow $k
    } else {
      if { $config(startpwd,$k) != "" && $glob($k,pwd) != $config(startpwd,$k)} {
        NewPwd $k $config(startpwd,$k) 
        UpdateWindow $k
      }
    }
  }
  AppendToDirHistory $glob(left,pwd)
  AppendToDirHistory $glob(right,pwd)
  set glob(left,dirstack) $glob(left,pwd)
  set glob(right,dirstack) $glob(right,pwd)
}

proc CheckConfigDir {} {
  global env glob

  if {[file isdirectory $glob(conf_dir)]} {
    return
  }
  if {$glob(os) != "WIN32" && [file exists $env(HOME)/.fr]} {
    set button [tk_dialog .questDialog "Question" \
        "The configuration files have moved for this version of FileRunner. Is it OK to move the config files to \
the new directory $env(HOME)/.fr? (The old .fr file will be called .fr/config, the .fr_cmds file will be called .fr/cmds \
and the .fr_history file will be called .fr/history)" \
        question 0 "Yes" "No(Exit)"]
    if {$button == 1} {
      exit 0
    }
    set cmds { 
      "file rename $env(HOME)/.fr $env(HOME)/.fr_tmp" 
      "file mkdir $env(HOME)/.fr"
      "file rename $env(HOME)/.fr_tmp $env(HOME)/.fr/config" 
    }
    foreach cmd $cmds {
      set r [catch $cmd out]
      if {$r} {
        PopErrorSimple "$cmd : $out"
        exit 1
      }
    }
    set cmds { 
      "file rename $env(HOME)/.fr_cmds $env(HOME)/.fr/cmds" 
      "file rename $env(HOME)/.fr_history $env(HOME)/.fr/history" 
      "file rename $env(HOME)/.fr_ver $env(HOME)/.fr/version" }
    foreach cmd $cmds {
      set r [catch $cmd out]
    }
    return
  }
  set button [tk_dialog .questDialog "Question" \
      "The FileRunner configuration directory $glob(conf_dir) does not exist. Ok to create it?" \
      error 0 "Yes" "No"]
  if {$button == 1} {
    return
  }
  set r [catch "file mkdir $glob(conf_dir)" out]
  if {$r} {
    PopErrorSimple "$out"
    exit 1
  }
}

proc ConfigBrowser {} {
  global glob config

  if {![file exists $glob(conf_dir)/config]} { SaveConfig }

  set glob(edit_configuration_configlist) {
    {Hotlist {---------------------------}}
    hotlist
    {Commands {COMMAND CONFIGURATION}}
    editor
    view,extensions
    cmd,print
    cmd,term
    cmd,diff
    {Archiver/Packer {ARCHIVER/PACKER}}
    cmd,unarc,extensions
    cmd,unpack,extensions
    cmd,pack
    cmd,archive
    {FTP {FTP CONFIGURATION}}
    ftp,login
    ftp,fastlink
    ftp,proxy
    ftp,password
    ftp,timeout
    ftp,anonymous
    ftp,useproxy
    ftp,cache,maxentries
    ftp,cd_pwd
    {HTTP {HTTP}}
    http,proxy
    {Appearance {APPEARANCE}}
    gui,color_bg
    gui,color_fg
    gui,color_cmd
    gui,color_select_bg
    gui,color_select_fg
    gui,color_scheme
    gui,color_cursor
    gui,font
    gui,font_scheme
    geometry,main
    geometry,textviewer
    geometry,qedit
    middle_button_colors
    {Shell {SHELL}}
    shell,height,left
    shell,height,right
    shell,buffer
    shell,aliases
    {Miscellaneous {MISC}}
    startpwd,left
    startpwd,right
    fileshow,all
    fileshow,sort
    dateformat
    autoupdate
    logsize
    check_ownership
    keyb_support
    ask,dir_delete
    ask,file_delete
    mwheel,delta
    mwheel,neg
    mwheel,pos
    save_conf_at_exit
    create_relative_links
    cd_pwd
    {{Dangerous stuff} {DANGEROUS}}
    cmd,sh
    cmd,rm
    cmd,cp
    cmd,ln
    cmd,chmod
    cmd,touch
    cmd,du
    cmd,find
  }

  set w .config_dialog
  toplevel $w -class Dialog
  wm title $w "Configuration Browser"
  wm iconname $w "FR config browser"
  wm resizable $w true true
  wm transient $w [winfo toplevel [winfo parent $w]]

  frame $w.left
  frame $w.right
  frame $w.bot

  # Create left frame containing the list of config options
  scrollbar $w.left.scrollvert -command "$w.left.list yview" -orient vertical 
  listbox $w.left.list \
    -yscrollcommand "$w.left.scrollvert set" \
    -font $config(gui,font) \
    -background $config(gui,color_bg) -foreground $config(gui,color_fg) \
    -selectbackground $config(gui,color_select_bg) -selectforeground $config(gui,color_select_fg) \
    -width 25 \
    -height 35 
  pack $w.left.list -side left -fill both
  pack $w.left.scrollvert -side right -fill y

  # Create right frame containing the config text and a scrollbar
  text $w.right.text -relief sunken -bd 2 -yscrollcommand "$w.right.scroll set" -setgrid 1 \
      -height 35 -font $config(gui,font) -background $config(gui,color_bg) \
      -foreground $config(gui,color_fg) -selectbackground $config(gui,color_select_bg) -selectforeground $config(gui,color_select_fg) -highlightthickness 0 
  scrollbar $w.right.scroll -command "$w.right.text yview" 
  pack $w.right.scroll -side right -fill y
  pack $w.right.text -expand 1 -fill both

  # Create bottom frame containing the OK/Cancel buttons
  button $w.bot.regen -text {Regenerate Configuration} -command "ConfigBrowserRegenerate $w.right.text"
  button $w.bot.ok -text OK -command "ConfigBrowserOK $w.right.text; destroy $w"
  button $w.bot.cancel -text Cancel -command "set glob(config_dialog_return) {}; destroy $w"
  pack $w.bot.cancel -side right -padx 3
  pack $w.bot.ok -side right -padx 3
  pack $w.bot.regen -side right -padx 3

  # Fill left frame with contents
  #set glob(font_dialog,fl) [split $glob(font_dialog,fl) "\n"]
  set cdl {}
  foreach k $glob(edit_configuration_configlist) {
    if {[lindex $k 1] != {}} {
      lappend cdl [lindex $k 0]
    } else {
      set tmp [split $k ,_]
      set tmp2 {}
      foreach t $tmp {
        lappend tmp2 "[string toupper [string index $t 0]][string range $t 1 end]"
      }
      lappend cdl "  $tmp2"
    }
  }

  eval $w.left.list insert end $cdl

  # Create popup menu
  menu $w.right.text.p
  $w.right.text.p add command -label Search... -command "SearchView $w.right.text 0"
  $w.right.text.p add command -label {Search Again} -command "SearchView $w.right.text 1"

  # Pack the top frames
  pack $w.bot -side bottom
  pack $w.left -side left -fill both
  pack $w.right -side right -fill both -expand 1

  # Assign bindings
  bind $w.right.text $config(mwheel,neg) "$w.right.text yview scroll -$config(mwheel,delta) units"
  bind $w.right.text $config(mwheel,pos) "$w.right.text yview scroll $config(mwheel,delta) units"
  bind $w.left.list $config(mwheel,neg) "$w.left.list yview scroll -$config(mwheel,delta) units"
  bind $w.left.list $config(mwheel,pos) "$w.left.list yview scroll $config(mwheel,delta) units"
  bind $w <Next> "$w.right.text yview scroll 1 pages"
  bind $w <Prior> "$w.right.text yview scroll -1 pages"
  bind $w <Home> "$w.right.text see 0.0"
  bind $w <End> "$w.right.text see end"
  bind $w <Escape> "destroy $w"
  bind $w.right.text <3> "tk_popup $w.right.text.p %X %Y"
  bind $w.left.list <1> "ConfigBrowserJumpToLoc $w.right.text \[$w.left.list nearest %y\]"
  wm withdraw $w
  update idletasks
  set x [expr [winfo screenwidth $w]/2 - [winfo reqwidth $w]/2 \
          - [winfo vrootx [winfo parent $w]]]
  set y [expr [winfo screenheight $w]/2 - [winfo reqheight $w]/2 \
          - [winfo vrooty [winfo parent $w]]]
  wm geom $w +$x+$y
  wm deiconify $w

  # Fill right frame with contents
  set filename $glob(conf_dir)/config
  set r [catch {set fid [open $filename r]} out]
  if {$r} {
    PopError "Can't open $filename for editing"
    destroy $w
    return
  }
  $w.right.text insert 0.0 [read -nonewline $fid]
  close $fid
  $w.right.text mark set insert 0.0
}

proc ConfigBrowserJumpToLoc { w index } {
  global glob config
  set tmp [lindex $glob(edit_configuration_configlist) $index]
  if {[lindex $tmp 1] != {}} {
    set searchfor [lindex $tmp 1]
    set heading 1
  } else {
    set searchfor config($tmp)
    set heading 0
  }

  set tag select
  $w tag configure $tag -background $config(gui,color_select_bg) -foreground $config(gui,color_select_fg) 
  $w tag remove $tag 0.0 end

  set idx [$w search -count len -backwards -- $searchfor 0.0]
  if {$idx == ""} {
    PopWarn "Can't find that location in config file. Try to regenerate configuration and try again."
    return
  }
  $w mark set insert "$idx + $len chars"
  $w see end
  $w see insert
  set line [lindex [split $idx .] 0]
  if {$heading} {
    $w mark set insert $line.0
  } else {
    # search backwards for ------------ and make sure it's visible
    set idx [$w search -count len -backwards -- "-----------" insert]
    if {$idx != {}} {
      $w see $idx
    }
  }
  $w tag add $tag $line.0 [expr $line+1].0
}

proc ConfigBrowserOK { w } {
  global glob config
  set filename $glob(conf_dir)/config
  Log "Configuration Browser: Saving $filename"
  Try { set fid [open $filename w]
        puts -nonewline $fid [$w get 0.0 end]
        close $fid} "" 1
  ReadConfig
  ForceUpdate
}

proc ConfigBrowserRegenerate { w } {
  global glob
  SaveConfig
  set filename $glob(conf_dir)/config
  set r [catch {set fid [open $filename r]} out]
  if {$r} {
    PopError "Can't open $filename for editing"
    return
  }
  $w delete 0.0 end
  $w insert 0.0 [read -nonewline $fid]
  close $fid
  $w mark set insert 0.0
}
