# TeX logfile analyzing (errors, warnings)
#
# Copyright (C) 2000  G. Lamprecht, W. Lotz, R. Weibezahn; IWD, Bremen University

#####@@@@@ Wie sicherstellen, daß .aux-Dateien etc. seit Erstellen des Logfiles
#####@@@@@ nicht gelöscht wurden (sonst Fehler bei tlParLev!)

proc tlWtlae {} {# ends logfile editing
 global vv Wq tlFileChanged tlLastFilLoaded
 if {$tlFileChanged==0} {
   tlDestroy
 } else {
   if {[winfo exists $Wq]==1} {destror $Wq}; toplevel $Wq
   set frage "$vv(tlsrq2): $tlLastFilLoaded ?"
   proc tlReqEditYes {} {global Wq;  destror $Wq; tlSaveFile; tlDestroy};# file save
   proc tlReqEditNo  {} {global Wq;  destror $Wq;             tlDestroy};# no file save
   Request $Wq "$frage " "" "$vv(yes)" tlReqEditYes "$vv(no)" tlReqEditNo "" "" y
 }
}

proc tlCreateWindow {} {

 global vv Wtl tlLastFilLoaded tlBgr tlFgr

 toplevel_init $Wtl "$vv(tlvor)" 100 20; set tyh 20; set txw 80


 # End Button, File and Line Display

 frame $Wtl.a; pack configure $Wtl.a -anchor w -side top
 button $Wtl.a.e -text $vv(ae) -command {tlWtlae};      Bind3P $Wtl.a.e 1 tlHelpText tlhae
 button $Wtl.a.s -text $vv(tlas) -command {tlSaveFile}; Bind3P $Wtl.a.s 1 tlHelpText tlhas
 label  $Wtl.a.l1 -anchor w -text "";			Bind3P $Wtl.a.l1 1 tlHelpText tlhal
 label  $Wtl.a.l2 -anchor w -text "";			Bind3P $Wtl.a.l2 1 tlHelpText tlhal
 pack configure $Wtl.a.e $Wtl.a.s -side left -padx 3 -pady 3
 pack configure $Wtl.a.l1 $Wtl.a.l2 -side left -fill x -expand yes


 # Next/Previous Tag

 frame $Wtl.b; pack configure $Wtl.b -anchor w -side top
 button $Wtl.b.p -text $vv(tlbp) -command {tlIncrTag -1}; Bind3P $Wtl.b.p 1 tlHelpText tlhbp
 button $Wtl.b.n -text $vv(tlbn) -command {tlIncrTag 1};  Bind3P $Wtl.b.n 1 tlHelpText tlhbn
 pack configure $Wtl.b.p $Wtl.b.n -side left -padx 3 -pady 3


 # Editing Widget
 frame $Wtl.c -relief raised -borderwidth 2
 pack configure $Wtl.c -pady 3 -anchor sw -fill both -expand yes -side top
 scrollbar $Wtl.c.s -command "$Wtl.c.t yview";		Bind3P $Wtl.c.s 1 tlHelpText tlhct
 text $Wtl.c.t -yscrollcommand "$Wtl.c.s set" -height $tyh -width $txw
 bindtags $Wtl.c.t {Wtl_c_t1 Text Wtl_c_t2 Wtl_c_th $Wtl all Wtl_c_t3}
 bind Wtl_c_t1 <Home> \
	{$Wtl.c.t mark set insert 0.0; $Wtl.c.t yview -pickplace insert; tlColDsp; break}
 bind Wtl_c_t1 <End> \
	{$Wtl.c.t mark set insert end; $Wtl.c.t yview -pickplace insert; tlColDsp; break}
 bind Wtl_c_t1 <Any-Key> {
   if {"%A"!="{}"} {set tlFileChanged 1; $Wtl.c.t tag remove CurErr 0.0 end}
   if {("%K"=="Return")||("%K"=="BackSpace")||("%K"=="Delete")} {set tlEndLast [tlSavEnd]}
 }
 bind Wtl_c_t3 <Return> tlEditNL
 bind Wtl_c_t3 <BackSpace> tlEditBS
 bind Wtl_c_t3 <Delete> tlEditDel
 bind Wtl_c_t2 <Any-Key> {tlColDsp}
 bind Wtl_c_t2 <Button-1> {tlColDsp}
 Bind3P Wtl_c_th 1 tlHelpText tlhct
 pack configure $Wtl.c.s -side right -fill y
 pack configure $Wtl.c.t -side right -fill both -expand yes
 text $Wtl.error
 set tlerrBgr [lindex [$Wtl.error configure -background] 4]
 set tlerrFgr [lindex [$Wtl.error configure -foreground] 4]
 if {[option get $Wtl.error background text]==""} {set tlerrBgr red}
 if {[option get $Wtl.error foreground text]==""} {set tlerrFgr $tlBgr}
 $Wtl.c.t tag configure CurErr -foreground $tlerrFgr -background $tlerrBgr
 TestPut 4 "Errors: Foreground:<$tlerrFgr> Background:<$tlerrBgr>"


 # Error Text Display

 frame $Wtl.e; pack configure $Wtl.e -anchor w -fill x -side bottom
 label $Wtl.e.errortag -anchor w -text "" -width $txw
 Bind3P $Wtl.e.errortag 1 tlHelpText tlhel
 pack configure $Wtl.e.errortag -fill x
}

proc tlSavPos {} {global Wtl; return [$Wtl.c.t index insert]};# save insert position
proc tlSavEnd {} {global Wtl; return [$Wtl.c.t index end]};# save end position

proc tlEditNL {} {# Newline entered in text editing
 global Wtl
 TestPut 4 "Newline entered ([expr [$Wtl.c.t index insert]-1])"
 set l [lindex [split [$Wtl.c.t index insert] .] 0]; tlIncrLN $l [expr $l-1] 1
}

proc tlEditBS {} {# BackSpace entered in text editing
 global Wtl tlEndLast
 TestPut 4 "BackSpace entered ([expr [$Wtl.c.t index insert]+1])"
 if {[$Wtl.c.t index end]!=$tlEndLast} \
     {set l [lindex [split [$Wtl.c.t index insert] .] 0]; tlIncrLN [expr $l+1] [expr $l+1] -1}
}

proc tlEditDel {} {# Delete entered in text editing
 global Wtl tlEndLast
 TestPut 4 "Delete entered ([$Wtl.c.t index insert])"
 if {[$Wtl.c.t index end]!=$tlEndLast} \
     {set l [lindex [split [$Wtl.c.t index insert] .] 0]; tlIncrLN [expr $l+1] [expr $l+1] -1}
}

proc tlIncrLN {ln2 ln3 incr} {# increment line numbers in tlErrStack (parameters 2 and 3)
 global Wtl tlEndLast tlLastFilLoaded tlErrStack
 TestPut 4 "tlErrStackold ($ln2,$ln3:$incr/$tlEndLast,[$Wtl.c.t index end]):\n\n$tlErrStack\n"
 for {set tn 0} {$tn<[lindex [lindex $tlErrStack 0] 0]} {incr tn} {
   set tt [lindex $tlErrStack $tn] 
   TestPut 4 "<$tn>  <$tt>"
   if {"[lindex $tt 1]"=="$tlLastFilLoaded"} {
     set tln2 [lindex $tt 2]; set tln3 [lindex $tt 3]
     if {($ln2<=$tln2)||($ln3<=$tln3)} {
       if {$ln2<=$tln2} {set tt [lreplace "$tt" 2 2 [incr tln2 $incr]]}
       if {$ln3<=$tln3} {set tt [lreplace "$tt" 3 3 [incr tln3 $incr]]}
       TestPut 4 "<$tn>**<$tt>"
       set tlErrStack [lreplace "$tlErrStack" $tn $tn $tt]
     }
   }
 }
  TestPut 4 "tlErrStacknew:\n\n$tlErrStack\n"
}

proc tlIncrTag {increment} {# next/previous error (increment= +1/-1)
 global vv Wtl Wq tlTAnz tlErrStack tlLastFilLoaded tlTag tlTNr tlFileChanged

 set tagnr [expr $tlTNr+$increment]
 if {($tagnr<1)||($tagnr>$tlTAnz)} return

 set tlTNr $tagnr;  set tlTag "[lindex $tlErrStack [expr $tlTAnz-$tagnr]]"
 if {[lindex $tlTag 1]==$tlLastFilLoaded} {
   TestPut 3 "\n*****<$tlTNr> = <$tlTag>"
   $Wtl.c.t tag remove CurErr 0.0 end;  tlPositEtc
 } else {
   TestPut 3 "\n*****<$tlTNr> != <$tlTag>"
   if {$tlFileChanged==0} {
     tlChangeFile
   } else {
     if {[winfo exists $Wq]==1} {destror $Wq}; toplevel $Wq
     set frage1 "$vv(tlsrq1)"
     set frage2 "$vv(tlsrq2): $tlLastFilLoaded ?"
     proc tlReqSaveYes {} {global Wq; destror $Wq; tlSaveFile; tlChangeFile}
     proc tlReqSaveNo  {} {global Wq; destror $Wq;             tlChangeFile}
     Request $Wq "$frage1" "$frage2" "$vv(yes)" tlReqSaveYes "$vv(no)" tlReqSaveNo "" "" y
   }
 }
}

proc tlChangeFile {} {# file change in consequence of next/previous error
 global vv Wtl tlTag
 $Wtl.c.t delete 0.0 end
 set file [lindex $tlTag 1]
 if [file exists $file] {tlFillFile $file} \
 else {$Wtl.c.t insert insert "$vv(aus5) $file $vv(ea4)"; mybell 3}
}

proc tlFillFile {file} {# fills file into text widget (file must exist!)
 global vv Wtl tlLastFilLoaded tlFileChanged sub

 lock; set sub 1
 set f [open "$file" r];  set tlLastFilLoaded $file;  set tlFileChanged 0
 $Wtl.c.t delete 0.0 end;  $Wtl.c.t insert end "[read $f]";  $Wtl.c.t yview 0
 close $f
 $Wtl.c.t configure -state normal
 tlPositEtc
}

proc tlDestroy {} {
  global Wtl tlLastFilLoaded
  destros $Wtl; unset tlLastFilLoaded; unlock_list; Focus .
}

proc tlSaveFile {} {# save text widget into file tlLastFilLoaded, reset tlFileChanged to 0
  global Wtl tlLastFilLoaded tlFileChanged

  exec mv $tlLastFilLoaded $tlLastFilLoaded.bak
  lock
  set f [open $tlLastFilLoaded w]
  set lc [$Wtl.c.t get "end -1c" end]
  if {($lc=="\n")} {puts -nonewline $f [$Wtl.c.t get 1.0 "end-1c"]} \
  else             {puts -nonewline $f [$Wtl.c.t get 1.0 end]}
  flush $f
  close $f
  set tlFileChanged 0
}

proc tlColDsp {} {# refresh edit line/column and error text
 global Wtl tlLastErr
 set pos [split [$Wtl.c.t index insert] .]
 $Wtl.a.l2 configure -text "[lindex $pos 0].[expr [lindex $pos 1]+1]"
 $Wtl.e.errortag configure -text "$tlLastErr"
 set f [option get .font.errortag font text];if {$f!=""} {$Wtl.e.errortag configure -font $f}
}

proc tlPositEtc {} {# refresh all: filename, position, file text, errror mark, error text
  global vv Wtl tlLastFilLoaded tlTag tlTAnz tlTNr tlLastErr
  set l1 [lindex $tlTag 2];   set l2 [lindex $tlTag 3];  set col [lindex $tlTag 4]
  $Wtl.a.l1 configure -text "$vv(aus5): $tlLastFilLoaded  / $vv(tlal): "
  if {$l1!=""} {
    $Wtl.a.l2 configure -text $l1
    $Wtl.c.t yview -pickplace [expr $l1-2]
    $Wtl.c.t mark set insert $l1.$col
    $Wtl.c.t tag add CurErr $l1.0 [expr $l2+1].0
    $Wtl.c.t configure -insertofftime 500 -insertontime 500 -insertwidth 4
  }
  set tlLastErr "[lindex $tlTag 5]  [lindex $tlTag 6] [lindex $tlTag 7]"
  tlColDsp;  if {$l1==""} {$Wtl.a.l2 configure -text "?"}
  focus $Wtl.c.t
  if {$tlTNr==1} {$Wtl.b.p configure -state disabled} {$Wtl.b.p configure -state normal}
  if {$tlTNr==$tlTAnz} {$Wtl.b.n configure -state disabled} {$Wtl.b.n configure -state normal}
  update
}

proc tlEditFile {tagnr} {# switch to file as specified in Tag tagnr (if file exists)
 global Wtl vv tlErrStack tlTAnz tlTag tlTNr tlFileCheck tlA Wq tlFile edliste
 TestPut 4 "Clicked at tagnr=<$tagnr>"
 if ![info exists tlTAnz] {return}
 set tlFile [lindex [lindex $tlErrStack [expr $tlTAnz-$tagnr]] 1]
 if {[file exists $tlFile]} {
  if [winfo exists $Wtl] {
   if {[wm state $Wtl]=="normal"} {raise $Wtl} else {wm deiconify $Wtl}
   tlIncrTag [expr $tagnr-$tlTNr]
  } else {
   set tlTNr $tagnr;  set tlTag "[lindex $tlErrStack [expr $tlTAnz-$tagnr]]"
   TestPut 3 "\n*****<$tagnr>   <$tlTag>"
   if {[llength $edliste]!=0} {
    if {[winfo exists $Wq]==1} {destror $Wq}; toplevel $Wq  
    set frage1 "$vv(xt34)";	set frage2 "$vv(xt35) $vv(xt351)"
    proc tlReqKflYes {} {global Wq tlFile; destror $Wq;tlCreateWindow;tlFillFile $tlFile}
    proc tlReqKflNo  {} {global Wq;	       destror $Wq}
    Request $Wq "$frage1" "$frage2" "$vv(yes)" tlReqKflYes $vv(no) tlReqKflNo tl_konflikt "" n
   } else {
    tlCreateWindow; tlFillFile $tlFile
   }
  }
 } else {
  writescr .d.tt "\n$vv(aus5) $tlFile $vv(ea4)"
  TestPut 4 "<$tlTAnz>-<$tagnr> tlErrStack:\n$tlErrStack\n"
  tlErrorMail 2 "$tlFile:$tagnr";#####@@@@@Nur Testphase;später:diese Zeile weg,dafür nächste!
  #if {$tlFileCheck==1} {tlErrorMail 2 "$tlFile:$tagnr";# file not found whilst clicking tag}
 }
}

proc tlHelpText {t} {# display a help text in the bottom line of $Wtl
 global vv Wtl
 $Wtl.e.errortag configure -text $vv($t)
 set f [option get .font.normal font text];if {$f!=""} {$Wtl.e.errortag configure -font $f}
}

proc tlErrorMail {errorNr text} {
  global email version tlA tlLog tlFileCheck tlLN
  TestPut 4 ""
  mybell 4
  set emailaddr [lindex $email 1]
  if [info exists tlLN] {set line "($tlLN)"} else {set line "(-)"}
  set l [string length $text]; if {$l>20} {set text [string range $text [expr $l-20] end]}
  set tla ""
  set tla "${tla}\n\n**********************************************************\n"
  set tla "${tla}Error $errorNr in xtem_TeXMenu-logfile-analyzing; please e-mail the \n"
  set tla "${tla}logfile $tlLog to us, e.g. using command\n"
  set tla "${tla} mailx -s 'xtem($version):LogAnalyzeErr:$errorNr:$tlFileCheck$line:$text'"
  set tla "${tla} $emailaddr < $tlLog \n"
  set tla "${tla}**********************************************************\n"
  if {$errorNr!=1} {writescr .d.tt $tla; .d.tt yview -pickplace insert}
  set tlA "${tlA}$tla"
}

proc tlCheckFilename {file} {
 TestPut 3 "<$file>"
 regsub -all "\\^\\^." "$file" "?" sf
 if {"$sf"!="$file"} \
	{set r [glob -nocomplain -- $sf]; if {("$r"!="")&&[file exists "$r"]} {set file $r}} 
 TestPut 3 "<$file><$sf>"
 return $file
}
   
proc tlInsertTag {w text1 text2 Insert col file lines} {# inserts a new error tag

  global vv tlTNr tlNl tlCP tlDirIgnore tlFgr tlBgr tlErrStack tlMessStack tlParLev
  global main_file tsuff tlInErr testPut tlLN

  TestPut 3 "<$text1><$text2><$Insert><$col><$file><$lines>"
  if {"$lines"==""} {set lines 0}
  if {$file==""} {set file $main_file$tsuff}
  set file [tlCheckFilename $file]
  if {[string first $tlDirIgnore $file]>=0} {return};#####@@@@@ später weg: in procedure tla !

  incr tlTNr; set tlInErr 0
  $w configure -state normal
  $w insert insert "${tlNl}"
  set linestart [lindex [split $lines "-"] 0]
  set lineend [lindex [split $lines "-"] 2]; if {$lineend==""} {set lineend $linestart}
  LvarPushtlErrStack [list $tlTNr $file $linestart $lineend $col $text1 $text2]
  set p0 [$w index insert];		$w insert insert "$text1"
  if {($Insert)&&($text2!="")} {
    label $w.tsep$tlTNr -bitmap error;	$w window create insert -window $w.tsep$tlTNr
					$w insert insert "$text2"
  }
  set p1 [$w index insert]
					$w insert insert "  ($file: $linestart)"
  if {$testPut>0} {			$w insert insert " \[$tlTNr ($tlLN) $tlParLev\]"}
  set p2 [$w index insert];		$w insert insert "\n"
  $w tag add errortag $p0 $p1
  $w tag add filename $p1 $p2
  $w tag add $tlTNr $p0 $p2
  $w tag bind $tlTNr <Button-1> "tlEditFile $tlTNr"
  $w tag bind $tlTNr <Enter> "$w tag configure $tlTNr -foreground $tlBgr -background $tlFgr"
  $w tag bind $tlTNr <Leave> "$w tag configure $tlTNr -foreground $tlFgr -background $tlBgr"
  $w yview -pickplace end
  update
  configureStateDisabled $w
  TestPut 3 "<$tlTNr><$p0><$p1><$p2><[$w tag names]>"

  set tlNl ""; set tlCP 0; set tlMessStack ""
}

proc tlMessStackOut {w file} {
  global tlMessStack tlInErr
  set tlInErr 0
  TestPut 1 "\t\t<$tlMessStack><$tlInErr>"
  if {"$tlMessStack"!=""} {tlInsertTag $w "$tlMessStack" "" 0 "" "$file" ""}
}

proc lrest1 {string} {# returns "rest after first blank of trimmed string"
  set s [string trim "$string"]; set p1 [string first " " $s]; set l [string length $s]
  if {$p1<0} {return ""} else {return [string trimleft [string range $s $p1 end]]}
}

proc tlClosePars {s} {# returns -1 if s contains at least one non-")", otherwise # of ")"
  if {[string length [string trim $s "\)"]]==0} {return [string length $s]} else {return -1}
}

proc tlAnalyzeLineRest0 {w cont e} {# transform "(" -> " (" and  ")" -> ") "
  regsub -all {\(} "$e" { (} s; regsub -all {\)} "$s" {) } t
  tlAnalyzeLineRest $w $cont [string trim $t]
}

proc lind0 {s} {# returns "first list element"
  set s [string trim $s]; set b [string first " " $s]
  if {$b>0} {return [string range $s 0 [expr $b-1]]} else {return $s}
}

proc tlGetscl {e} {
 upvar 1 $e ein
 global tlFId tlLN tlParLev
 set ret [getscl $tlFId zeile]; set zeile [string trim $zeile]; incr tlLN
 set p1 [string first "\[" $zeile]; set p2 [string first "\]" $zeile]
 TestPut 2 "***<$tlLN><$tlParLev>\t\t<$zeile> <$p1><$p2>"
 if {($p1<0)&&($p2<0)} {
   set ein "$zeile"
 } else {
   set ein ""
   while {($p1>=0)||($p2>=0)} {
     set subst 0
     if {$p2<0} {set p2 [string length $zeile]}
     if {($p1<0)||($p1>$p2)} {set p1 0}
     set ein "$ein [string range $zeile 0 [expr $p1-1]]"
     set str [string trim [string range $zeile $p1 $p2]]
     set zeile [string trim [string range $zeile [expr $p2+1] end]]
     if {"x[string trim $str "\[-0123456789\]"]"!="x"} {set subst 1}
     if {$subst==1} {regsub -all "\\\[" $str "<" str; regsub -all "\\\]" $str ">" str}
     set ein "$ein $str"
     set p1 [string first "\[" $zeile]; set p2 [string first "\]" $zeile]
   }
   set ein [string trim "${ein} $zeile"]
   TestPut 2 "***<$tlLN><$tlParLev>\t\t<$ein> <$p1><$p2>"
 }
 return $ret
}

proc tlWritescr2 {w str} {
 global tlCP tlNl
 writescr2 $w "$str"
 incr tlCP [string length $str]
 if {$tlCP>80} {writescr $w "\n"; set tlNl ""; set tlCP 0; update} else {set tlNl "\n"}
}

proc tlLookForPages {w string} {
 set p1 [string first "\[" $string]; set p2 [string first "\]" $string]
 TestPut 3 "$p1,$p2<$string>"
 while {($p1>=0)&&($p2>$p1)} {
   set s [string range $string [expr $p1+1] [expr $p2-1]]
   if {("x[string trim $s "-0123456789"]"=="x")&&("$s"!="")} {tlWritescr2 $w "\[$s\] "}
   set string [string range $string [expr $p2+1] end]
   set p1 [string first "\[" $string]; set p2 [string first "\]" $string]

 }
}

proc tlRunaway {w} {
 global tlRunAway
 writescr $w "\nRunaway argument?"
 set n 1
 while {([tlGetscl e]>=0)&&($n<20)} {
   if {$n==1} {writescr $w "\n$e"} \
   elseif {[string first "x! " "x$e"]==0} {writescr $w "\n$e"} \
   elseif {[string first "x<*> " "x$e"]==0} {writescr $w "\n$e"} \
   elseif {[string first "x*** " "x$e"]==0} {writescr $w "\n$e"}
   incr n
 }
 writescr $w "\n"
 incr tlRunAway
}

proc tlAnalyzeLineRest {w cont e} {# analyzes a line or (recursively) the remaining rest

  global vv email tlA tlFNF tlPL tlParLev tlFileStack tlOfull tlLN texlogwarning
  global tlHBad tlFileCheck tlMessStack xtAbbruch tlRec tlInErr tlTWrn

  if {"x[string trim $w]"=="x"} {return}

  TestPut 2 "<$tlLN><$cont><$tlInErr> ---<$e>"
  incr tlRec; if {$tlRec>50} {writescr $w "\n$vv(tlrec)\n"; set xtAbbruch 1; return}
  if {$xtAbbruch==1} then {return}

  set frag [lind0 $e]; set xfrag "x$frag"; # insert "x"; otherwise "integer too large"
  set frTrimPN [string trimleft [string trimleft [string trim $frag "\[\]"] "-"] "0123456789"]
  if {[string range $e 0 0]==" "} {set cont 1}

  # use lrest instead of lindex in the following (problem: \ { } etc.)

  TestPut 2 "<$tlLN><$cont>    ...<$frag><$frTrimPN>"

  if {("$xfrag"=="xOverfull")&&($cont==0)} {# overfull boxes

    set excess [string range [lindex $e 2] 1 [expr [string length [lindex $e 2]]-3]]
    set type [lrest1 $e]
    set text1 $e
    while {([string first "line" [lindex $e 0]]!=0)&&($e!="")} {set e [lrest1 $e]}
    set lines [lindex $e 1]
    set text2 "";        tlGetscl e2;  set text2 "$text2$e2"
    while {"x$e2"!="x"} {tlGetscl e2;  set text2 "$text2$e2"}
    if {$excess>=$tlOfull} {
      tlMessStackOut $w [lindex $tlFileStack 0]
      tlInsertTag $w "$text1" "$text2" 0 0 [lindex $tlFileStack 0] $lines
    }

  } elseif {("$xfrag"=="xUnderfull")&&($cont==0)} {# underfull boxes

    set bad [string range [lindex $e 3] 0 [expr [string length [lindex $e 3]]-2]]
    set type [lrange $e 1 1]
    set text1 $e
    while {([string first "line" [lindex $e 0]]!=0)&&($e!="")} {set e [lrest1 $e]}
    set lines [lindex $e 1]
    set text2 "";        tlGetscl e2;  set text2 "$text2$e2"
    while {"x$e2"!="x"} {tlGetscl e2;  set text2 "$text2$e2"}
    if {$bad>=$tlHBad} {
      tlMessStackOut $w [lindex $tlFileStack 0]
      tlInsertTag $w "$text1" "$text2" 0 0 [lindex $tlFileStack 0] $lines
    }

  } elseif {("$xfrag"=="xMissing")&&([string first " character" $e]>6) \
				  &&([string first " character" $e]<9)&&($cont==0)} {# Miss...

  } elseif {("$xfrag"=="x!")&&($cont==0)&&([string range $e 0 0]=="!")} {# probably error text
    TestPut 1 "!             <$frag><$e><$tlInErr>"

    if {$tlMessStack==""} {set tlMessStack "$e"} {set tlMessStack "${tlMessStack}\n$e"}
    set text1 [lrest1 $e];  set lines "";  set col ""; set text2 ""
    if {([string first "LaTeX" $e]>0)&&([string first "LaTeX" $e]<5)} {
      TestPut 1 "! LaTeX        <$frag><$e><$tlInErr>"
      if {[string last ")" "$e"]<[string first "(" "$e"]} {set tlInErr $tlLN}
    } else {
      TestPut 1 "! non-LaTeX    <$frag><$e><$tlInErr>"
      set tlInErr $tlLN
    }

  } elseif {("$xfrag"=="xLaTeX")&&([lindex $e 1]=="Warning:")} {# LaTeX Warning:
    TestPut 1 "LaTeX Warning:  <$texlogwarning><$frag><$e>"
    incr tlTWrn
    if {$texlogwarning==1} {
      set lines ""; set p [string first "input line" $e]
      set text $e
      if {$p>0} {
	set lines [string trim [string range $e [expr $p+10] end] " ."]
	if {"$lines"==""} {if {[tlGetscl e]>=0} {set lines $e}; set text "$text $e"}
	set lines [string trim $lines " ."]
 	if {"[Num $lines]"!="$lines"} {set lines ""}
      }
      tlInsertTag $w "$text" "" 0 0 [lindex $tlFileStack 0] $lines
    }

  } elseif {[regexp {xl\.[0-9]+$} $xfrag]&&($cont==0)} {# l.nnn --> error message?
    TestPut 1 "l.nnn ?       <$frag><$e><$cont><$tlMessStack>"

    if {($tlMessStack!="")&&($cont==0)} {# line number: !nnn
      set text1 "$tlMessStack  [lrest1 $e]"
      set lines [lindex [split $xfrag "."] 1]
      set col [string length [lrest1 $e]]
      tlGetscl e2;  set text2 "[string trim $e2] "
      TestPut 1 "l.nnn OK       <$frag><$e><$text1><$text2>"
      tlInsertTag $w "$text1" "$text2" 1 $col [lindex $tlFileStack 0] $lines
    }

  } elseif {"$xfrag"=="x\[\]"} {# []
    TestPut 1 "\[\]  <$frag>"
    if {($cont==0)&&([lrest1 $e]!="")} {tlAnalyzeLineRest $w 1 [lrest1 $e]}

  } elseif {("$xfrag"!="x")&&("$frTrimPN"=="")} {# output page number?
    TestPut 1 "\[nnn ?      :  <$frag>"

    set p1 [string first \[ $frag]; set p2 [string first \] $frag]; set r ""
    if     {$p1==0} {tlWritescr2 $w "\[[string trim $frag "\[\]"]\] "} \
    elseif {$p2>=1} {set r [string range $frag [expr $p2+1] end]}
    set line "$r [lrest1 $e]";  if {"x$line"!="x"} {tlAnalyzeLineRest $w 1 $line}

  } elseif {[string index $xfrag 1]=="\]"} {# closing ] (balancing output page number?!)
    TestPut 1 "\] ?         :   <$frag>"

    if {[string length $xfrag]>2} {set rf "[string range $xfrag 2 end] "} else {set rf ""}
    set line $rf[lrest1 $e];  if {"x$line"!="x"} {tlAnalyzeLineRest $w 1 $line}

  } elseif {([string range $xfrag 0 1]=="x\(")&&($tlFNF)&&($tlInErr==0)} {
						# string starts with "(" -> file opening?

    set frg [string range $xfrag 2 end]
    set l [string length $frg];  set p1 [string first ")" $frg]
    TestPut 1 "( ?         :  <$frg><$l><$p1><$tlInErr>"
    if {($tlRec==1)&&($l>=77)&&([string first " " $frg]<0)&& \
	([string index $frg [expr $l-1]]!=")")&&(![file exists $frg])} {
      if {[tlGetscl e]>=0} {set frg "${frg}$e"}
      tlAnalyzeLineRest0 $w 0 "($frg"
    } else {
      set name ""; set close 0
      if {$p1<0} {set name $frg; set close 0} \
      else	 {set name [string range $frg 0 [expr $p1-1]]; set close 1}
      if {($name!="")||("x[string trim $e]"=="x(")} {
	  tlMessStackOut $w [lindex $tlFileStack 0]; LvarPush tlFileStack $name
	  set tlParLev [expr $tlParLev+1-$close]
	  for {set i 1} {$i<=$close} {incr i} {LvarPop tlFileStack}
	  TestPut 1 "( OK +1-$close $tlParLev :  <$tlFileStack>"
      }
      set line [lrest1 $e];  if {"x$line"!="x"} {tlAnalyzeLineRest $w 1 $line}
    }

  } elseif {[regexp {^x\)+$} $xfrag]&&($tlFNF)&&($tlInErr==0)} {# file closing?

    TestPut 1 ") ?         :  <$frag><$tlInErr>"
    tlMessStackOut $w [lindex $tlFileStack 0]
    for {set n 1} {$n<[string length $xfrag]} {incr n} {LvarPop tlFileStack; incr tlParLev -1}
    if {$tlParLev<0} {tlErrorMail 1 "";# parentheses level error}
    TestPut 1 ") OK   -[expr $n-1] $tlParLev : <$tlFileStack><$tlInErr>"
    set line [lrest1 $e];  if {"x$line"!="x"} {tlAnalyzeLineRest $w 1 $line}

  } elseif {($tlInErr!=0)} {TestPut 1 "in error text --> do nothing!"

  } else {# "(filename", ")", "[pagenumber", "]" can follow!
    TestPut 1 "else-clause"

    set p1 [string first "(" $e]; set p2 [string first ")" $e]

    if {($p1==-1)&&($p2==-1)} {# no "(", ")" can follow
      tlLookForPages $w $e
      set tlFNF 0
    } else {
      TestPut 1 "()-Spezial"
      if {$p1<0} {set p $p2} else {if {($p2>0)&&($p2<$p1)} {set p $p2} else {set p $p1}}
      tlLookForPages $w [string range $e 0 [expr $p1-1]]
      set line [string range $e $p end];  if {"x$line"!="x"} {tlAnalyzeLineRest $w 1 $line}
    }
  }

}

proc tlAnalyzeIndexLog {w zeile} {
  global tlIErr tlIWrn
  set posE [string first {!! Input index error} $zeile]; if {$posE>=0} {incr tlIErr; set p 6}
  set posW [string first {## Warning} $zeile];		 if {$posW>=0} {incr tlIWrn; set p 4}
  TestPut 4 "<$posE><$posW>\t<$zeile>"
  if {($posE>=0)||($posW>=0)} {
    tlGetscl folgez
    set p1 [$w index insert]
    writescr $w "$zeile $folgez\n"
    set fnam [lindex $zeile $p];set fnam [string range $fnam 0 [expr [string length $fnam]-2]]
    set ln [lindex [split [lindex $zeile [expr $p+3]] "():;,="] 0]
    if [file exists $fnam] {
	set rsed [ catch "exec sed -n \"$ln,${ln}p\" $fnam" txt]
	TestPut 4 "<$fnam><$ln><$rsed><$txt>"
	if {($rsed==0)&&("$txt"!="")} {writescr $w "\t$txt\n"}
    }
    set p2 [$w index insert]
    $w tag add errortag $p1 $p2
  }
}

proc tla {w} {
  global vv tlCP tlNl tlFNF tlPL tlParLev tlFileStack tlTNr tlTAnz tlTWrn tlMaxL tlLN
  global tlLog tlFId tlFgr tlBgr tlOfull tlHBad email tlErrStack tlMessStack xtAbbruch tlRec
  global tlDirIgnore texlogwarning tlInErr tlRunAway tlaOutLstAct main_file tlIErr tlIWrn

  foreach tn [$w tag names] {
	if {[regexp {^[0-9]+$} $tn]||($tn=="filename")||($tn=="errortag")} {$w tag delete $tn}
  }
  $w tag configure errortag -font [option get .font.errortag font text]
  $w tag configure filename -font [option get .font.normal font text]
  if [info exists tlTAnz] {unset tlTAnz}
  set tlFgr [lindex [$w configure -foreground] 4]
  set tlBgr [lindex [$w configure -background] 4]

  set tlParLev 0; set tlFileStack ""; set tlErrStack ""; set tlTNr 0; set tlInErr 0
  set tlNl ""; set tlPL ""; set tlMessStack ""; set xtAbbruch 2; set tlRunAway 0

  writescr $w "\n*** "
  eval writescr $w "$vv(tlstrt0)"
  writescr $w " ***\n$vv(tlstrt3) $tlDirIgnore\n$vv(tlstrt4)\n\n"
  if [winfo exists .a.2.a] {.a.2.a configure -state normal; update}

  set tlFId [open $tlLog r]; set tlLN 0; set tlCP 0; set tlTWrn 0
  while {([tlGetscl e]>=0)&&($tlParLev>=0)} {
    set tlFNF 1; set tlRec 0
    if {($xtAbbruch==1)||($tlLN>$tlMaxL)} then {break}
    if {"x$e"=="xRunaway argument?"} {tlRunaway $w; break}
    tlAnalyzeLineRest0 $w 0 $e; set tlPL "$e"
  }
  close $tlFId
  tlMessStackOut $w [lindex $tlFileStack 0]
  if [winfo exists .a.2.a] {.a.2.a configure -state disabled; update idletasks}
  set tlTAnz $tlTNr
  TestPut 3 "+++++++++++++ ParLevel:<$tlParLev> \#Tags:<$tlTAnz> <$xtAbbruch>"
  writescr $w "$tlNl"
  if {($tlLN>$tlMaxL)} {# logfile analyze terminated: max. # of lines in logfile exceeded
    writescr $w "\n$vv(tlend5) $tlMaxL $vv(tlend6)"
  } else {
    if {$tlRunAway!=0} {writescr $w "\n$vv(tlend8)"} \
    elseif {($xtAbbruch!=1)} {
      if     {($tlTAnz==0)&&($tlTWrn==0)} {writescr $w "\n$vv(tlend10)"} \
      elseif {($tlTAnz==0)&&($tlTWrn!=0)} {writescr $w "\n$vv(tlend11)"} \
      elseif {($texlogwarning==1)&&($tlTWrn==$tlTAnz)} {writescr $w "\n$vv(tlend12)"} \
    }
    if {($texlogwarning==0)&&($tlTAnz>0)&&($tlTWrn>0)} {writescr $w "\n$vv(tlend13)"}
    if {($tlParLev!=0)} {writescr $w "\n*** tlParLev=$tlParLev $vv(tlend4)\n";mybell 4}
  }
  if {$tlTAnz>0} {writescr $w "\n$vv(tlend7)"; set tlaOutLstAct 1}
  update idletasks

  set tlLog $main_file.ilg
  TestPut 4 "[file exists $tlLog] $tlLog"
  if [file exists $tlLog] {
    set tlFId [open $tlLog r]; set tlLN 0; set tlIErr 0; set tlIWrn 0
    writescr $w "\n\n$vv(tlilg1) ($tlLog):\n"
    while {([tlGetscl e]>=0)&&($tlParLev>=0)} {
      if {($xtAbbruch==1)||($tlLN>$tlMaxL)} then {break}
      set IErrExp [tlAnalyzeIndexLog $w $e]
    }
    close $tlFId
    if {($tlIErr==0)&&($xtAbbruch!=1)} {writescr $w "$vv(tlend10)"}
  }
  update idletasks

  set xtAbbruch 0

  return
}

proc LvarPushtlErrStack {string} {#replacing TclX command lvarpush (argument only!)
 global tlErrStack
 TestPut 3 "<$string>"
 set tlErrStack [linsert $tlErrStack 0 "$string"]
}
