#
# Module for file browsing
#


# Some useful variables:
set TH(File,Browse,Shortcommand) [lindex [string trim $TH(File,Browse,Command) "| "] 0]
set TH(File,Browse,Dir) ""
set TH(File,Browse,Listing) ""
set TH(File,Browse,Length) 0
set TH(File,Browse,Index) 0

# Tries to figure out a file and line number pointed at by w and index.
# Returns file, or "" if unsuccessful. If a line and column were found, and
# line_var and column_var are specified, fills one or both.
# line_var and column_var.
proc th_file_parse {w index {line_var ""} {column_var ""}} {
  if {$line_var != ""} {upvar $line_var line}
  if {$column_var != ""} {upvar $column_var column}
  set file ""

  if {[set start [$w search -backwards -regexp -- {[^A-Za-z0-9_/~\.]} $index "$index linestart"]] == ""} {
    set start [$w index "$index linestart"]
  }
  if {[set answer [th_file_parse_aux $w $start]] == ""} {
    if {[set answer [th_file_parse_aux $w "$index linestart"]] == ""} {
      return ""
  }}
  if {[llength $answer] > 0} {set file [lindex $answer 0]}
  if {[llength $answer] > 1} {set line [lindex $answer 1]}
  if {[llength $answer] > 2} {set column [lindex $answer 2]}
  return $file
}

proc th_file_parse_aux {w index} {
  global TH
  set list [split [$w get $index "$index lineend"] "\=\@\*\<\>\{\}\(\)\[\]\"':, \t"]
  set l [llength $list]
  set found 0
  for {set i 0} {$i < $l} {incr i} {
    set name [lindex $list $i]
    if {($name == "") || ($name == ".")} {continue}
    if {[string first [string index [lindex $list $i] 0] "~/."] == -1} {
      set name "[th_file_dirname $TH(File,$w)]/[lindex $list $i]"}
    if {[file exists $name]} {
      set file $name
      set found 1
      break
  }}
  if {!$found} {return ""}

  set found 0
  for {incr i} {$i < $l} {incr i} {
    if {[regexp {^[0-9]+$} [lindex $list $i]]} {
      set line [lindex $list $i]
      set found 1
      break
  }}
  if {!$found} {return $file}

  set found 0
  for {incr i} {$i < $l} {incr i} {
    if {[regexp {^[0-9]+$} [lindex $list $i]]} {
      set column [lindex $list $i]
      set found 1
      break
  }}
  if {!$found} {return [list $file $line]}

  return [list $file $line $column]
}


# Finds instance of file in w (which contains directory listing)
proc th_file_find {w file} {
  set index 1.0
  while {[set index [$w search -forward -- $file "$index+1c" end]] != ""} {
    set find [th_file_parse $w $index]
    if {[th_file_tail $find] == ""} {set find [th_file_tail [th_file_dirname $find]]
    } else {set find [th_file_tail $find]}
    if {($find == $file)} {
      return $index
}}}

# Gets the current file (or directory)'s parent directory listing.
proc th_file_raise {w} {
  global TH ; if {[catch "set TH(File,$w)"]} {set TH(File,$w) "[pwd]/a"}
  set dir [th_file_dirname $TH(File,$w)]
  if {[string match "*/$TH(File,Browse,Command)" $TH(File,$w)]} {
    set dir [th_file_dirname $dir]
    set oldfile [th_file_tail [th_file_dirname $TH(File,$w)]]
  } else {set oldfile [th_file_tail $TH(File,$w)]}
  set TH(File,New,$w) "$dir/$TH(File,Browse,Command)"
  return $oldfile
}

# Goes up in the directory hierarchy one level.
proc th_file_up {w} {
  set oldfile [th_file_raise $w]
  th_load_file $w
  th_Text_goto $w [th_file_find $w $oldfile]
}

# Goes down in the directory hierarchy one level.
proc th_file_down {w} {
  global TH ; if {[catch "set TH(File,$w)"]} {set TH(File,$w) "[pwd]/a"}
  if {![string match "*/$TH(File,Browse,Command)" $TH(File,$w)]} {bell ; return}
  set file [th_file_parse $w insert]
  if {![file readable $file]} {bell ; return}
  set dir [th_file_dirname $TH(File,$w)]
  if {[file isdirectory $file]} {
    if {([string index $file [expr [string length $file] - 1]] != "/")} {
      set TH(File,New,$w) "$file/$TH(File,Browse,Command)"
    } else {
      set TH(File,New,$w) "$file$TH(File,Browse,Command)"
  }} else {set TH(File,New,$w) $file}
  th_load_file $w
}

# Goes forward or backward by inc files in the current directory level.
proc th_file_move {w inc} {
  global TH ; if {[catch "set TH(File,$w)"]} {set TH(File,$w) "[pwd]/a"}
  set of $TH(File,$w)
  set oldfile [th_file_raise $w]
  set dir [th_file_dirname $TH(File,New,$w)]
  if {$dir != $TH(File,Browse,Dir)} {
    set TH(File,Browse,Dir) $dir
    set TH(File,Browse,Listing) [exec $TH(File,Browse,Shortcommand) $dir]
    set TH(File,Browse,Length) [llength $TH(File,Browse,Listing)]
    set TH(File,Browse,Index) [lsearch $TH(File,Browse,Listing) $oldfile]
  }
  incr TH(File,Browse,Index) $inc
  if {($TH(File,Browse,Index) < 0) || 
	($TH(File,Browse,Index) >= $TH(File,Browse,Length))} {
    set TH(File,New,$w) $of
    if {$TH(File,Browse,Index) < 0} {set TH(File,Browse,Index) 0
    } else {set TH(File,Browse,Index) [expr $TH(File,Browse,Length) -1]}
    bell ; return}
  set file [lindex $TH(File,Browse,Listing) $TH(File,Browse,Index)]
  if {[file isdirectory $dir/$file]} {
    set TH(File,New,$w) "$dir/$file/$TH(File,Browse,Command)"
  } else {set TH(File,New,$w) "$dir/$file"}
  th_load_file $w
}
