########################################
# ts.tcl
########################################

# Procedures

proc debug {s} {
  global params

  if $params(debug) { puts $s }
}

proc shortdir {path} {
  global env

  if {[string first $env(HOME) $path] == 0} {
    return "~[string range $path [string length $env(HOME)] end]"
  } else {
    return $path
  }
}

proc cutdir {path} {
  global params

  if {[string first $params(Primary_dir) $path] == 0} {
    return [string range $path [expr [string length $params(Primary_dir)]+1] \
      end]
  } else {
    return [shortdir $path]
  }
}

proc FirstCall {} {
  global env TS_BASE TS_VERSION params
  
  if {[file exists $env(HOME)/.ts]} {
    if {![file isdir $env(HOME)/.ts]} {
      puts "Error: found file '~/.ts'. Please rename it and restart ts."
      exit 1
    }
  } else {
    file mkdir $env(HOME)/.ts
    if {[file exists $env(HOME)/.texshell]} {
      puts "Copying ~/.texshell to ~/.ts/ts.cfg."
      puts "You can delete ~/.texshell now."
      file copy $env(HOME)/.texshell $env(HOME)/.ts/ts.cfg
    }
  }
  if [file exists $env(HOME)/.ts/$TS_VERSION] {return}
  # check includes.cfg format
  if [file exists $env(HOME)/.ts/includes.cfg] {
    set fd [open $env(HOME)/.ts/includes.cfg r]
    gets $fd line
    close $fd
    if {![regexp {^#} $line]} {
      file rename -force $env(HOME)/.ts/includes.cfg \
        $env(HOME)/.ts/includes.cfg.old
      puts "includes.cfg has new format"
    }
  }
  foreach f {"includes.cfg"} {
    if {![file exists $env(HOME)/.ts/$f]} {
      file copy "$TS_BASE/$f" "$env(HOME)/.ts"
    } 
  }
  scan_templates
  set fd [open $env(HOME)/.ts/$TS_VERSION w]
  close $fd
}

proc filetest {f1 {f2 ""}} {
  if ![file exist $f1] {
    return 1
  }
  if {$f2 == ""} {return 0}
  if ![file exist $f2] {
    return 2
  }
  if {[file mtime $f1] > [file mtime $f2]} {
    return 3
  }
  return 0
}

# proc scanopt replaces  %-parameters
#  %p - Primary file 
#  %d - Primary dir
#  %r - Rootname of Primary file
#  %e - Editfile -> Filedialog
#  %o - Other file -> Filedialog
#  %g - Geometry 
# Print options !... ! cleared

proc scanopt {s {geom ""}} {
  global params prd

  debug "scanopt: $s"
  set t ""
  if [regexp -- {%p} $s] {
    if {$params(Primary_file) != ""} { 
      set t $params(Primary_file)
    } elseif {$params(Edit_file) != ""} {
      set t [cutdir $params(Edit_file)]
    } else {
      Warning $params(dlg_geom) \
        "No Primary file is specified.\nNo Edit file was found."
      return ""
    }
    regsub -all -- {%p} $s $t s
    debug $s
  }
  if [regexp -- {%r} $s] {
    if {$params(Primary_file) != ""} { 
      set t [file rootname $params(Primary_file)]
    } elseif {$params(Edit_file) != ""} {
      set t [file rootname [cutdir $params(Edit_file)]]
    } else {
      Warning $params(dlg_geom) \
        "No Primary file is specified.\nNo Edit file was found."
      return ""
    }
    regsub -all -- {%r} $s $t s
    debug $s
  }
  if [regexp -- {%d} $s] {
    if {$params(Primary_dir) != ""} { 
      set dir $params(Primary_dir)
    } else {
      set dir [pwd]
    }
    regsub -all -- {%d} $s $dir s
  }
  regsub -all -- {%e} $s $params(Edit_file) s
  debug $s
  if [regexp -- {%o([^ ]*)} $s sub ext] {
    set f ""
    if {![FileDialog $params(dlg_geom) "Select File" $ext f]} {
      return ""
    }
    if {[file tail $f] != ""} {
      set t [cutdir $f]
    }
    regsub -all -- {%o[^ ]*} $s $t s
    debug $s
  }
  if [regexp -- {%g([^ ]*)} $s sub sgeo] {
    if {$sgeo != ""} {
      set geom $sgeo
    }
    if {$geom == ""} {
      set geom $params(default_geom)
    }
    regsub -all -- {%g[^ ]*} $s $geom s
    debug $s
  }
  regsub -all -- {![^!]*!} $s {} s
  debug "scanopt ready: $s"
  return $s
}

# setprintopt s opt
# sets printeroption opt in s
# Options:
#   landscape -> !l..!
#
proc setprintopt {str opt {value ""}} {
  upvar $str s

  debug "Setprintopt ($opt $value): $s"
  switch $opt {
    landscape {
      regsub {!l([^!%]*)!} $s "\\1" s
    }
    first {
      regsub {!0([^!%]*)%([^!]*)!} $s "\\1$value\\2" s
    }
    last {
      regsub {!9([^!%]*)%([^!]*)!} $s "\\1$value\\2" s
    }
    copies {
      regsub {!c([^!%]*)%([^!]*)!} $s "\\1$value\\2" s
    }
    odd {
      regsub {!o([^!%]*)!} $s "\\1" s
    }
    even {
      regsub {!e([^!%]*)!} $s "\\1" s
    }
    xopt {
      regsub {!x([^!%]*)%([^!]*)!} $s "\\1$value\\2" s
    }
    default {return 0}
  }
  debug "Setprintopt ready: $s"
  return 1
}

proc EvalCmd {cmdline {geom ""}} {
  global params sigchld

  debug "EvalCmd: $cmdline"
  set cmd [lindex $cmdline 1]
  set opt [lindex $cmdline 2]
  if {[set opt [scanopt $opt $geom]] == ""} {
    return
  }
  debug "Work directory: $params(Primary_dir)"
  debug "Cmd: $cmd Opt: $opt"
  switch $cmd {
    exwin {
      OutMsg "$opt\n"
      set oldfocus [focus]
      debug "exwin: oldfocus = $oldfocus"
      xfocus .term
      set sigchld 0
      ExecCmd $opt
      tkwait variable sigchld
      debug "exwin: process died"
      debug "exwin: oldfocus $oldfocus"
      xfocus $oldfocus
      update idletasks
    }
    exbg {
      ExecBg $opt
    }
    exec {
      OutMsg $opt
      catch {eval exec $opt} out
      OutMsg $out
    }
    xterm {
      OutMsg "$opt\n"
      ExecTerm $opt
    }
    xtermbg {
      OutMsg "$opt\n"
      ExecTermBg $opt
    }
    default {
      OutMsg "$cmd $opt"
      eval $cmd $opt
    }
  }
}

proc OutMsg {s} {
#  Out .t.text "+ [CurTime] $s"
  Out .term "* $s"
}

proc OutErr {s} {
  Out .t.text  "??? $s ???\n"
}

proc OutClr {} {
  Out .t.text \012
}

proc xfocus {w} {
  global params ted

  set old_focus [focus]
  if {$old_focus == ".term"} {
    catch {$old_focus configure -foreground #000000}
  }
  if {[string compare $w ""] == 0} {set w .}
  focus $w
  raise [set wt [winfo toplevel $w]]
  if {$w == ".term"} {
    catch {$w configure -foreground #0000ff}
  }
  catch {set params(Edit_file) $ted($wt,file)}
}

proc Exit {} {
  global params env

  set ex_ok 1
  for {set i 0} {$i < 10} {incr i} {
    if [winfo exists .t$i] {
      if ![TedExit .t$i] {set ex_ok 0}
    }
  }
  if {!$ex_ok} {
    return
  }
  #CleanShutdown
#  destroy .
  exit
}

proc Primary {} {
  global params

  if {$params(Primary_file) != ""} {
    set f $params(Primary_file)
  } else {
    set f ""
  }
  if {![FileDialog $params(dlg_geom) "Select Primary File" .tex f]} {return 0}
  set params(Primary_dir) [file dirname $f]
  set params(Short_dir) [shortdir $params(Primary_dir)]
  cd $params(Primary_dir)
  set f [file tail $f]
#  set params(Primary_file) [file rootname $f]
  set params(Primary_file) $f
  readparams
  catch {prjrescan}
  OutMsg "Primary file was changed to $params(Primary_file)"
  OutMsg "Working directory is now    $params(Primary_dir)"
  return 1
}

proc EditFile {file {line 1}} {
  global params ted

  set lcmd [lindex $params(Edit) $params(Edit_default)]
  set cmd [lindex $lcmd 1]
  if {$cmd == "intern"} {
    for {set i 0} {$i < 10} {incr i} {
      if [winfo exists .t$i] {
        if {$ted(.t$i,file) == $file} {
          raise .t$i
          xfocus .t$i.text
          .t$i.text mark set insert $line.0
          .t$i.text yview -pickplace insert
          return
        }
      }
    }
    set i 1
    while {[winfo exists .t$i]} {incr i}
    if {$i >= 10} {
      Warning $params(dlg_default) "Too many editors (max. 9)."
      return
    }
    set geom +[expr $params(x0)+50+30*$i]+[expr $params(y0)+50+30*$i]
    tedit .t$i $geom "Edit - $i" $file $line
  } else {
    set opt [lindex $lcmd 2]
    regsub -- {!i([^!%]*)%([^!]*)!} $opt "\\1$line\\2" opt
    debug "Insert line: $opt"
    set params(Edit_file) $file
#    if {[set i [string first "%e" $opt]] >= 0} {
#      set s [string range $opt 0 [expr $i - 1]]$file
#      set l [string length $opt]
#      for {incr i 2} {$i < $l && [cindex $opt $i] != " "} {incr i} { }
#      set opt $s[string range $opt [expr $i + 1] end]
#    } else {
#      Warning $params(dlg_geom) \
#        "Error in Editor file parameter.\nMust be `%e'."
#      return
#    }
    EvalCmd [list Edit $cmd $opt]
  } 
}
      
proc Edit {{i ""}} {
  global params

  set lcmd [lindex $params(Edit) $params(Edit_default)]
  set cmd [lindex $lcmd 1]
  # eval geometry for external Editor
  if {$cmd != "intern"} {
    set ext [file extension $params(Edit_file)]
    if {$ext == ""} {set ext .tex}
    if {![FileDialog $params(dlg_geom) "Select File" $ext \
      params(Edit_file)]} {return ""}
    set params(Edit_file) [cutdir $params(Edit_file)]
    EvalCmd $lcmd
    return
  }
  if {$i != ""} {
    if {[winfo exists .t$i]} {
      raise .t$i
      xfocus .t${i}.text
      return
    }
  } else {
    set i 1
    while {[winfo exists .t$i]} {incr i}
    if {$i >= 10} {
      Warning $params(dlg_default) "Too many editors (max. 9)."
      return
    }
  }
  set geom +[expr $params(x0)+50+30*$i]+[expr $params(y0)+50+30*$i]
  if {![FileDialog $params(dlg_geom) "Select File" .tex \
    params(Edit_file)]} {return ""}
  set opt ".t$i $geom \"Edit - $i\" $params(Edit_file)"
  if {$opt != ""} {eval tedit $opt} 
}

proc NewPrim {} {
  global params

  set templatefile [templatedlg]
  if {$templatefile != ""} {
    set fd [open $templatefile r]
    set fprim [open $params(Primary_file) w]
    gets $fd cont
    gets $fd sline
    debug "sline: $sline"
    set line 1
    regexp {%! *([0-9]+)} $sline dummy line
    while {![eof $fd]} {
      gets $fd s
      puts $fprim $s
    }
    close $fd
    close $fprim
    if {$line < 1} {set line 1}
    debug "$line"
    return $line
  }
  return 1
}

proc EditPrim {} {
  global params
  
  set lcmd [lindex $params(Edit) $params(Edit_default)]
  set cmd [lindex $lcmd 1]
  if {$params(Primary_file) == ""} {
    if {![Primary]} return
    if {$params(Primary_file) == ""} {
      Warning $params(dlg_geom) "No primary file is specified."
      return
    }
  }
  if {[file extension $params(Primary_file)] != ""} {
    set params(Edit_File) $params(Primary_file)
  } else {
    set params(Edit_File) $params(Primary_file).tex
  }
  if {![file exists $params(Primary_file)]} {
    set line [NewPrim]
  } else {
    set line 1
  }
  if {$cmd == "intern"} {
    if {[winfo exists .t0]} {
      raise .t0
      xfocus .t0.text
    } else {
      set x [expr $params(x0)+50]
      set y [expr $params(y0)+30]
      tedit .t0 +$x+$y "Edit - 0" \
        $params(Primary_dir)/$params(Primary_file) $line
    }
  } else {
    EditFile $params(Primary_file) $line
  }
}

proc Compose {} {
  global params

  # Save last edit file, because Saving will change this
  set edfile $params(Edit_file)
  for {set i 0} {$i < 10} {incr i} {
    if [winfo exists .t$i] {
      if {![TedAskSave .t$i]} {return}
    }
  }
  set params(Edit_file) $edfile
  set l [lindex $params(Compose) $params(Compose_default)]
  file delete compose.err
  EvalCmd $l
  if {[file exists compose.err]} { ;# Error occured, Edit was called
    set fd [open compose.err r]
    gets $fd s
    debug "compose.err: $s"
    close $fd
    regexp -- {([^ ]*)[ ]*([^ ]*)} $s sub line file
    file delete compose.err
    if {[string first "/" $file] != 0} {
      set file $params(Primary_dir)/$file
    }
    debug "Compose: $file $line"
    EditFile $file $line
  }
}

proc Reference {} {
  global params

  set l [lindex $params(Reference) $params(Reference_default)]
  EvalCmd $l
}

proc Filter {} {
  global params

  set l [lindex $params(Filter) $params(Filter_default)]
  set opt [lindex $l 3]
  EvalCmd [list Filter exwin $opt]
}

proc ApplyFilter {pattern} {
  global params
 
  set prim [file rootname $params(Primary_file)]
  set i -1
  foreach l $params(Filter) {
    incr i
    foreach {name source target cmd} $l { break }
    if {$pattern == $target} {
      EvalCmd [list Filter exwin $cmd]
      return $i
    }
  }
  return -1
}

proc View {} {
  Output View
}

proc Print {} {
  Output Print
}

proc Output {{device View}} {
  global params prd

  if {$params(Primary_file) != ""} {
    set f [file rootname $params(Primary_file)]
  } elseif {$params(Edit_file) != ""} {
    set f [file rootname $params(Edit_file)]
  } else {
    Warning $params(dlg_geom) "No Primary file is specified."
    return
  }

  switch [filetest ${f}.tex ${f}.dvi] {
    1 {
      Warning $params(dlg_geom) "TeX file ${f}.tex not found"
      return
    }
    2 {
      if {[Dialog .dlg $params(dlg_geom) "" \
        "DVI file $f.dvi not found.\n Run compose?" question \
        0 1 {Yes <Any-y>} {No <Any-n>}] == 0} {
        Compose
      } else {
        return
      }
    }
    3 {
      if {[Dialog .dlg $params(dlg_geom) "" \
        "Primary file $f has been changed.\nRun compose?" question \
        0 1 {Yes <Any-y>} {No <Any-n>}] == 0} {
        Compose
        debug "View weiter"
      }
    }
  }
  set l [lindex $params($device) $params(${device}_default)]
  # Filter test
  set cmd [lindex $l 1]
  set opt [lindex $l 2]
  if [regexp {%r[^ ]*} $opt fpattern] {
    regsub -all {%r} $fpattern $f file
    switch [filetest ${f}.tex $file] {
      1 {
        Warning $params(dlg_geom) "Could not compose DVI file ${f}.dvi."
        return
      }
      2 - 3 {
        OutMsg "Apply Filter for $file."
        ApplyFilter $fpattern
      }
    }
  } 
  if {$device == "View"} {
    update
    EvalCmd $l
    return
  }
  # Printing
  if {![PrintDlg $params(dlg_geom) [cutdir $file] params $opt]} {
    return
  }
  if {$params(pr_first) != "" && $params(pr_first) > 1} {
    setprintopt opt first $params(pr_first)
  }
  if {$params(pr_last) != "" && $params(pr_last) < 9999} {
    setprintopt opt last $params(pr_last)
  }
  if {$params(pr_copies) != "" && $params(pr_copies) > 1} {
    setprintopt opt copies $params(pr_copies)
  }
  if {$params(pr_xopt) != ""} {
    setprintopt opt xopt $params(pr_xopt)
  }
  if {$params(pr_orientation) == "landscape"} {
    if {![setprintopt opt landscape]} {
      Warning $params(dlg_geom) \
        "DVI Driver can't print in landscape mode.\nAbort."
      return
    }
  }
  switch $params(pr_pages) {
    all { }
    odd {setprintopt opt odd}
    even {setprintopt opt even}
  }
  set l [list Print $cmd $opt]
  EvalCmd $l
}

proc Graphic {} {
  global params

  set l [lindex $params(Graphic) $params(Graphic_default)]
  EvalCmd $l
}

proc Util {{i -1}} {
  global params

  if {$i == -1} {
    set i $params(Util_default)
  }
  set l [lindex $params(Util) $i]
  EvalCmd $l
}

proc setparam {cmd entry} {
 global params

 set params(${cmd}_cmd) [lindex $entry 1]
}

#proc ShowOut {} {
#  global params
#
#  if {$params(ShowOut)} {
#    wm deiconify .term
#  } else {
#    wm withdraw .term
#  }
#}

# Main
proc main {} {
  global params pid argc argv env hlp

  FirstCall
  if $argc>0 {
    set f [lindex $argv end]
    set params(Primary_dir) [file dirname $f]
    cd $params(Primary_dir)
    set f [file tail $f]
    if {[file extension $f] == ""} {
      set params(Primary_file) ${f}.tex
    } else {
      set params(Primary_file) $f
    }
  }
  if {$params(Primary_dir) == "."} {
    set params(Primary_dir) [pwd]
  }
  readparams
  read_templatelist
  ide 
  # Extent standard action for Button 1 (set focus)
  set textbind "[bind Text <1>]\nxfocus %W"
  bind Text <1> $textbind
  debug [bind Text <1>]
  #bind .c.lprimary <2> {set params(Primary_file) [selection get]}

  set env(TEXEDIT) "ts_err %d %s"
  foreach P {Edit Compose View Print Util Graphic} {
    set params(${P}_pid) 1
  }
  set params(Short_dir) [shortdir $params(Primary_dir)]
  prjreadpatterns
  debug "Start Help"
#  ref_tell [glob -nocomplain $hlp(dir)/*.hlp]
#  ref_read
  debug "Help Ready"
  exec xlsfonts *Courier* >$env(HOME)/.ts_fontlist
  OutMsg "TeXShell Version $params(version)" 
  OutMsg "(poenisch@wirtschaft.tu-chemnitz.de)"
  OutMsg "\xa9 1994-1998 Jens Pönisch"
  OutMsg "Redistribution and modification is restricted"
  OutMsg "by GNU General Public License Version 2"
  OutMsg ""
  OutMsg "  Primary file:"
  OutMsg "    $params(Primary_file)"
  OutMsg "  Working directory:"
  OutMsg "     $params(Primary_dir)"
  OutMsg ""
  OutMsg "  Help: Press F1"
  update idletasks
  focus .
  update
} 
