#!/afs/ece/usr/tcl/bin/wish -f
# The next line is executed by most shells, but not Tcl \
wish $0 $*


#
# Elsbeth startup file
#

# If you move this file, you should change the value of the following varialbe
# to the TH source directory. (something like ~/src/th)
if {[string index [set TH_Dir "[file dirname [info script]]/.."] 0] != "/"} {
  set TH_Dir "[pwd]/$TH_Dir"
}


# This file does not have the text widget, or the startup procedures; those
# are in els. Other than those, this file contains only the functions necessary
# upon startup.

set Els "$TH_Dir/bin/els"
set Elsbeth_Help_File "$TH_Dir/aux/elsbeth.help"
set Elsbeth_Bindings "$TH_Dir/aux/elsbeth.bindings.tcl"

# Only add bindings if elsbeth.bindings.tcl exists, otherwise just do els.
if {![file exists $Elsbeth_Bindings]} {
  source $Els
} else {

set TH(Completions,File,Commands) [list "ls -lFa" "make |& cat" "grep -n" "egrep -n" "fgrep -n"]

proc elsbeth_new_text {tl} {
  global TH

  # Create inactive entry with interpreter name in it.
  entry $tl.t_fm.interp -relief sunken -width 7
  $tl.t_fm.interp insert end [winfo name .]
  $tl.t_fm.interp xview [expr [string length [winfo name .]] -7]
  $tl.t_fm.interp configure -state disabled
  foreach binding {B1-Motion A-ButtonPress-1} {
    bind $tl.t_fm.interp $binding {%W select from 0 ; %W select to end}}
  pack $tl.t_fm.interp -side left

  # Create quit button
  button $tl.t_fm.quit -text "Quit" -command "elsbeth_destroy_text $tl.t"
  pack $tl.t_fm.quit -side right -expand yes -fill x
  update
  bindtags $tl.t "Text $tl.t . all"
  elsbeth_Text_instance $tl.t

  # Create scrollbar
  th_toggle_scrollbar $tl.t y left

  # Bring up file/path names
  th_file_update_widgets $tl.t
  elsbeth_recall_marks $tl.t
  elsbeth_ensure_no_duplicates $tl.t
  if {![winfo exists $tl.t]} {return}

  th_toggle_incremental_search $tl.t

  if {[lindex [tk appname] 0] == "elsbeth"} {
    th_add_module elsbeth $tl.t
  }

  if {[string first "makefile" [string tolower [file tail $TH(File,$tl.t)]]] >= 0} {th_add_module tclth $tl.t}
  switch [string tolower [file extension $TH(File,$tl.t)]] {
    ".txt" {th_add_module paragrath $tl.t
  } ".tcl" - ".t" - ".tk" - ".pl" - ".pm" - "p" {th_add_module tclth $tl.t
  } ".c" - ".h" - ".cc" {th_add_module cth $tl.t
  } ".lisp" - ".lsp" - ".l" - ".scm" {th_add_module lispth $tl.t
  } ".html" - ".htm" {th_add_module htmlth $tl.t
}}
  if {[lindex [tk appname] 0] == "elsbeth"} {
    th_flash_label $tl.t -relief ridge -text "Press [lindex $TH(Binding,Help) 0] for help, or [lindex $TH(Binding,Toggle_Menus) 0] for menus."
}}

# Ensures no other interp is editing the same file I am editing.
proc elsbeth_ensure_no_duplicates {w} {
  global TH
  # If we're looking at a pipe output, or no file, don't bother.
  if {[catch "set TH(File,$w)"] || ($TH(File,$w) == "") ||
      [string match \|* $TH(File,$w)]} {return}

  foreach tl [winfo children .] {
    set w2 "$tl.t"
    if {![winfo exists $w2]} {continue}
    # Oh...it's just me.
    if {($w2 == $w)} {continue}
    # Maybe he's looking at a different file.
    if {[catch "set TH(File,$w2)"]} {continue}
    if {($TH(File,$w) != $TH(File,$w2))} {continue}
    # Oh well...gotta resolve it.
    elsbeth_resolve_mutual_edit_conflict $w $w2
}}

proc elsbeth_resolve_mutual_edit_conflict {w w2} {
  global TH
  set msg "$TH(File,$w) is being editied in another window. What should I do?"
  set choice [tk_dialog .conf "Conflict Dialog" $msg warning \
          0 "Quit" "Read another file" "Kill other window" "Nothing"]
  switch $choice {
    0 {elsbeth_destroy_text $w
  } 1 {th_read_file_prompt $w
  } 2 {elsbeth_destroy_text $w2
}}}


# New window w is up. Add the marks to it (if any)
# If all is 0, then only the marks, view and insert is remembered.
proc elsbeth_recall_marks {w {all 1}} {
  global TH Elsbeth_Configs Elsbeth_Geom Elsbeth_Info
  if {[string match "*| *" $TH(File,$w)]} {return}
  set file "[file tail [file dirname $TH(File,$w)]]/[file tail $TH(File,$w)]"

# Now parse marks file, see what changes are specified.
  if {![catch "set Elsbeth_Info($file)" info]} {
    set i 1 ; set l [llength $info]
    while {$i < $l} {switch [lindex $info $i] {
	"insert" {incr i ; $w mark set insert [lindex $info $i] ; incr i}
	"view" {incr i ; scan [lindex $info $i] "%d.%d" y x ; incr y -1 ; incr i
	  update ; $w yview scroll $y units ; $w xview scroll $x units}
	"paint" {incr i ; set paints [lindex $info $i] ; incr i
	  foreach paint $paints {eval th_Misc_paint_add $w $paint}}
	"marks" {incr i ; set marks [lindex $info $i] ; incr i
	  set lm [llength $marks]
	  eval $w tag configure mark $TH(Mark,Tag)
	  for {set m 0} {$m < $lm} {incr m 2} {
	    eval $w tag add mark [lrange $marks $m [expr $m+1]]}}
	default {incr i
}}}}}

# Read the elsbeth.info file, and load the marks
proc elsbeth_load_marks {} {
  global env Elsbeth_Info
  if {[llength [tk appname]] > 1} {return}

  if {[file exists $env(HOME)/.th/[tk appname].info]} {
    uplevel #0 source $env(HOME)/.th/[tk appname].info
  }

  foreach tl [winfo children .] {
    if {[string match ".sym*" $tl]} {
      elsbeth_recall_marks $tl.t
  }}

  foreach file [array names Elsbeth_Info] {
    if {![file exists "[lindex $Elsbeth_Info($file) 0]/$file"]} {
      unset Elsbeth_Info($file)
}}}
elsbeth_load_marks

# Window w is about to go. Save its marks.
proc elsbeth_remember_marks {w} {
  global TH Elsbeth_Info Elsbeth_Configs Elsbeth_Geom Elsbeth_Remember
  if {[catch "set Elsbeth_Remember"]} {set Elsbeth_Remember 1}

  if {[string match "*| *" $TH(File,$w)]} {return}
  set info ""

# Now check for cursor location and view
  if $Elsbeth_Remember {
    if {[$w index insert] != "1.0"} {lappend info insert [$w index insert]}
    if {[$w index "@0,0"] != "1.0"} {lappend info view [$w index "@0,0"]}
  }

# Now check for custom paints
  if {![catch "set TH(Paint,$w)"]} {
    set paint_info ""
    foreach paint $TH(Paint,$w) {
      if {[lsearch -exact $TH(Module,Paint,$w) $paint] >= 0} {continue}
      set painting $paint
      foreach config [$w tag configure [lindex $paint 0]] {
        if {[lindex $config 4] != ""} {
          lappend painting [lindex $config 0] [lindex $config 4]
      }}
      lappend paint_info $painting
    }
    if {$paint_info != ""} {lappend info paint $paint_info}
  }

# Now check for marks
  if {[set marks [$w tag ranges mark]] != ""} {
    lappend info marks $marks
  }
  set file "[file tail [file dirname $TH(File,$w)]]/[file tail $TH(File,$w)]"
  if {$info != ""} {set Elsbeth_Info($file) [concat [file dirname [file dirname $TH(File,$w)]] $info]} else {catch {unset Elsbeth_Info($file)}}
}

# Save the elsbeth.info file, iff this is the last window.
proc elsbeth_save_marks {} {
  global env Elsbeth_Info
  if {![file isdir $env(HOME)/.th]} {return}
  if {[llength [tk appname]] > 1} {return}

  set f [open $env(HOME)/.th/[tk appname].info "w"]

  if {[catch {array names Elsbeth_Info} files]} {set files ""}
  puts $f "foreach item \{"
  foreach file $files {puts $f "\{$file $Elsbeth_Info($file)\}"}
  puts $f "\} {set Elsbeth_Info(\[lindex \$item 0\]) \[lrange \$item 1 end\]}"

  close $f
}

proc elsbeth_destroy_text {w {remember 0}} {
  global Elsbeth_Remember ; set Elsbeth_Remember $remember
  th_confirm_save $w "catch \"elsbeth_save_marks\" ; els_destroy_text $w"
}


source $Elsbeth_Bindings
set arg0 $Els ; set argv "$arg0 $argv" ; incr argc
source "[file dirname [info script]]/thbind"

wm title . Elsbeth
wm iconname . Elsbeth

# This forces the window module to load, so we can overwrite some of its procs.
auto_load th_iconify_window

# Don't iconify w if it is in toplevel window, unless its alone.
proc th_iconify_window {w} {
  set p [winfo parent $w]
  if {([winfo class $p] == "Toplevel")} {
    wm iconify $p
  } else {
    if {([llength [pack slaves .]] == 1)} {
      wm iconify .
    } else {
      pack forget $p
  }}
  th_circle_focus_next $w
}

proc th_raise_window {w} {
  set p [winfo parent $w]
  if {([winfo class $p] == "Toplevel")} {
    wm deiconify $p ; raise $p
  } else {
    wm deiconify . ; raise .
    pack $p -side top -expand yes -fill both
    if {[set s [lindex [pack slaves .] 0]] != ""} {
      pack $p -before $s
}}}

set TH(Gradual) 1 ; set TH(Pipe,Enabled) 1

# Extend th_load_file to do a handful of elsbeth-type goodies.
set code [info body th_load_file]
proc th_load_file {w {insert_flag 0}} [concat $code { ;
  if {!$insert_flag} {    elsbeth_recall_marks $w 0 }
  th_file_update_titles $w
  elsbeth_ensure_no_duplicates $w
}]

# Extend th's write_file to change window titles, and check for duplicates.
set code [info body th_write_file]
proc th_write_file {w} [concat $code { ; 
  th_file_update_titles $w
  elsbeth_ensure_no_duplicates $w
  elsbeth_remember_marks $w
}]


# Extend th's confirm-save to remember the marks, whether or not file is saved.
set code [info body th_confirm_save]
proc th_confirm_save {w cmd} [concat { ;
  global TH
  if {!$TH(Modified,$w)} {elsbeth_remember_marks $w}
; } $code]



### Extra procedures to clear Elsbeth info

proc elsbeth_clear_locations {} {elsbeth_clear view ; elsbeth_clear insert}

proc elsbeth_clear_marks {} {elsbeth_clear marks}

proc elsbeth_clear {{kind "all"}} {
  global Elsbeth_Info
  if {$kind == "all"} {elsbeth_clear_locations ; elsbeth_clear_marks}

  foreach index [array names Elsbeth_Info] {
    if {[set l [lsearch $Elsbeth_Info($index) $kind]] == -1} {continue}
    set Elsbeth_Info($index) [lreplace $Elsbeth_Info($index) $l [expr $l + 1]]
    if {[llength $Elsbeth_Info($index)] == 1} {
      unset Elsbeth_Info($index)
}}}

proc elsbeth_info_visit {} {
  global Elsbeth_Info
  set paths ""
  foreach index [array names Elsbeth_Info] {
    lappend paths "[lindex $Elsbeth_Info($index) 0]/$index"
  }
  if {[set file [th_dialog_listbox .conf "Files" "Select a file to visit:" \
		$paths]] == ""} {return ""}
  elsbeth_goto_file [focus] $file
  return ""
}

set TH(Pipe,Enabled) 1

bind Toplevel <Enter> {+catch {cd [th_file_dirname $TH(File,%W.t)]}}
}
