# Allgemeine Prozeduren für xtem_texmenu
#
# Copyright (C) 1999  G. Lamprecht, W. Lotz, R. Weibezahn; IWD, Bremen University


proc SigChldB {} {signal block SIGCHLD};#  must be called before exec (yet not exec xterm ...)
proc SigChldU {} {signal unblock SIGCHLD};# must be called after exec (yet not exec xterm ...)


proc delFromUnlockListe {wnam} {global unlockliste; # delete widgetnames from list
 foreach w $wnam \
  {set i [lsearch $unlockliste $w];if {$i>=0} {set unlockliste [lreplace $unlockliste $i $i]}}
}


proc setInUnlockListe {wnam} {global unlockliste; # if not already in: insert widgetnames
 foreach w $wnam \
	{if [lsearch $unlockliste $w]<0 {set unlockliste [linsert $unlockliste end $w]}}
}


proc decr {v} {upvar 1 $v n; incr n -1}; # decrement v by -1


proc datime {} {return [fmtclock [getclock] +%H:%M:%S]; # liefert Uhrzeit als Return-Wert!}


proc catFile {file w args} {# Anlisten der Datei file im Fenster w
#				ggfs. nach vorherigem Löschen des bisherigen Fensterinhalts
 global anl0 vv
 if {[string first clear $args]>=0} {set clear 1} {set clear 0}
 if {[string first pos0 $args]>=0} {set pos 0.0} {set pos insert}
 if {[string first absolutely $args]>=0} {set absolutely 1} {set absolutely 0}
 if {($anl0==1)&&($w==".d.tt")&&($absolutely!=1)} {return}; # derzeit läuft ein Programm
 $w configure -state normal
 if {$clear} {$w delete 0.0 end}
 set fid [open "$file" r]; $w insert end "[read $fid]@\n"; close $fid
 $w mark set insert $pos; $w yview insert
 configureStateDisabled $w
} 


proc putsVerbatim {f t} {puts $f {\begin{verbatim}}; puts $f "$t"; puts $f {\end{verbatim}}}


proc Bind2HF    {W      file w} {BindnHTF 2 $W \"\"      $file $w};### Help-bindings: Button-2
proc Bind3HF    {W      file w} {BindnHTF 3 $W \"\"      $file $w};### Help-bindings: Button-3
proc Bind3HTF   {W text file w} {BindnHTF 3 $W \"$text\" $file $w};### Help-bindings: Button-3
proc BindnHTF {n W text file w} {### bindings for helptext and helpfile via Button-2, Button-3
 global mousebutts bindkeysenab WTB
 if {[string first ".d.tt" $W]<0} {set WT $W} \
 elseif {$W==".d.tt.ins"} {set WT $W} \
 else {set WT [AlphNum CmdXNo$W]; set WTB($WT) $WT}
 TestPut 4 "<$W><$w><$bindkeysenab><[string first ".d.tt" $W]>><WT nach Substitution:<$WT>"
 bind $WT <ButtonPress-$n>                                   "Bend"
 bind $WT <ButtonPress-$n><ButtonRelease-$n>                 "HTxtFile $text $file $w; Bend"
 bind $WT <ButtonPress-$n><Leave><ButtonRelease-$n>	     "Bend"
 bind $WT <ButtonPress-$n><Leave><Enter><ButtonRelease-$n>   "HTxtFile $text $file $w; Bend"
 if {$mousebutts==2} {
  if {$n==3} {set N 2} else {set N 3}
  bind $WT <Control-ButtonPress-$N>			     "Bend"
  bind $WT <Control-ButtonPress-$N><ButtonRelease-$N>        "HTxtFile $text $file $w; Bend"
  bind $WT <Control-ButtonPress-$N><Leave><ButtonRelease-$N> "Bend"
  bind $WT <Control-ButtonPress-$N><Leave><Enter><ButtonRelease-$N> \
							     "HTxtFile $text $file $w; Bend"
 }
}
proc Bind3HTFK {wcn wxx f w} {# help text driver for buttons with shortcuts (Key bindings)
 global vv bindkeysenab bindkeys
 if {$bindkeysenab==1} {
   set t ""
   if	  [info exist bindkeys($wxx)]  {set t "[lindex $bindkeys($wxx) 0]:  $vv(wlmt)\n"} \
   elseif [info exist bindkeys($wcn.$wxx)] \
				       {set t "[lindex $bindkeys($wcn.$wxx) 0]:  $vv(wlmt)\n"}
 } else {set t ""}
 Bind3HTF $wcn.$wxx "$t" $f $w
}

proc HTxtFile {text file w} {
 global sub hlp_dir RequestActive tlaOutLstAct
 if {($sub>0)&&($w==".d.tt")&&($RequestActive!=1)} {return}
 if {$tlaOutLstAct==0} {writescr0 $w ""} else {writescr $w "\n---------------------------\n"}
 writescr $w $text; catFile $hlp_dir$file.hlp $w
}

proc BindS1P  {W ExAllow proc args} {				    # run proc: Shift-Button-1
				 BindnP Shift- 1 $W $ExAllow $proc $args
}
proc Bind1P   {W ExAllow proc args} {BindnP "" 1 $W $ExAllow $proc $args};# run proc: Button-1
proc Bind2P   {W ExAllow proc args} {BindnP "" 2 $W $ExAllow $proc $args};# run proc: Button-2
proc Bind3P   {W ExAllow proc args} {BindnP "" 3 $W $ExAllow $proc $args};# run proc: Button-3
proc BindnP {Md n W ExAllow proc args} {#bindings:proc calls via: Button-1, Button-2, Button-3
 global mousebutts
 bind $W <${Md}ButtonPress-$n>				"Bend"
 bind $W <${Md}ButtonPress-$n><ButtonRelease-$n>	"ProcExec $ExAllow $proc $args; Bend"
 bind $W <${Md}ButtonPress-$n><Leave><ButtonRelease-$n> "Bend"
 bind $W <${Md}ButtonPress-$n><Enter><ButtonRelease-$n> "ProcExec $ExAllow $proc $args; Bend"
 if {$mousebutts==2} {
  if {$n==3} {set N 2} else {set N 3}
  bind $W <Control-ButtonPress-$N>			"Bend"
  bind $W <Control-ButtonPress-$N><ButtonRelease-$N> 	"ProcExec $ExAllow $proc $args; Bend"
  bind $W <Control-ButtonPress-$N><Leave><ButtonRelease-$N>	\
							"Bend"
  bind $W <Control-ButtonPress-$N><Enter><ButtonRelease-$N>	\
							"ProcExec $ExAllow $proc $args; Bend"
 }
}

proc ProcExec {ExAllow proc args} {
 global sub
 TestPut 4 "<$sub><$ExAllow>  <$proc> <$args>"
 if {($sub>0)&&($ExAllow==0)} {return};# when other program runs: run proc only if allowed
 eval $proc [join $args]
}

proc LeftMouseOnly {w} {global vv; writescr0 $w "$vv(xt25)\n"; mybell 1}


proc CallSetMenu {p} {lock; set sub 1; $p; setMenuCalled $p}

proc setMenuCalled {p} {# set SetMenuCalled --> 1 and writes this into personal setting files
 global SetMenuCalled language env main_file
 if {($SetMenuCalled==1)||($p=="xv")} {return}
 TestPut 4 ""
 set SetMenuCalled 1
 if {[file exists "$env(HOME)/.xtem_$language.vst"]} \
	{exec echo "SetMenuCalled $SetMenuCalled" >> $env(HOME)/.xtem_$language.vst}
 if {[file exists "${main_file}_$language.vst"]} \
	{exec echo "SetMenuCalled $SetMenuCalled" >> ${main_file}_$language.vst}
}


proc mybell {level} {global bell_level; if {$level>=$bell_level} {bell}; # significant signal}
####                        bell_level: 1=no_restriction/2=warnings+errors/3=errors/4=no_bell
#### use   mybell 1    for low level messages
#### use   mybell 2    for warnings
#### use   mybell 3    for errors
#### use   mybell 4    for very hard errors: must bell in any case


proc testfilename {fname win suf} {# test filename (only letters, numerals, some others)
  global vv
  set f $fname
  if {$f==""} {mybell 2;  writescr $win "$vv(ut3)\n"; $win yview 0; return 1}
  
  if {[regexp {^[/a-zA-Z0-9_-]+$} $f]&&![regexp {^[-].*$} $f]} {return 0} 
  mybell 2
  set r 1
  writescr $win "$vv(ut4) \"$f\" $vv(ut5)\n         $vv(ut6)"
  if {$suf!=""} {writescr $win "$vv(ut7) \"$suf\""}
  writescr $win "\n"
  if {[string match "* *" $f]} {writescr $win "\n***** $vv(ut8)\n"; mybell 3; set r 2} 
  if {[regexp {^[-].*$} $f]} {writescr $win "\n***** $vv(ut9)\n"; mybell 3} 
  $win yview 0; return $r
}


proc mtest {str var} {# Looks for the Variable $var in the personal .vst-files;
#                       if found: sets it to the assigned value
  upvar 1 $var v
  set pat $var
  if {[string match "$pat*" [string trim $str]]} {
	set z "[string trim $str] "; set p [string first " " $z]
	set v [string trim [string range $z $p end]] 
  }
}


proc progback {prog back} {# Testen, ob Programm $prog im Hintergrund 
#                            aufgerufen werden soll,
#                            Setzen von $back und korrigieren von $prog
  upvar 1 $prog programm
  upvar 1 $back background

  set bpos [string last & "$programm"]
  if {$bpos>0} {
    set programm [string trim [string range $programm 0 [expr {$bpos - 1}]]]
    set background & 
  } else {
    set background ""
  }
  set $programm [string trim $programm]
}


proc Focus {w} {global bindkeysenab RequestActive; #####@@@@@ make this procedure obsolete?! 
 #if {($bindkeysenab==0)} {focus $w}
 #if {($bindkeysenab==0)||($RequestActive==0)} {focus $w}
}


proc configureStateDisabled {w} {global bindkeysenab; # disables text widget if bindkeysenab=0
 # if {$bindkeysenab==0} {$w configure -state disabled}
}

proc writescr  {w args} {# bel. Anzahl von Strings --> $w mit update
 eval writescr2 $w $args; update idletasks
}

proc writescr0 {w args} {# bel. Anzahl von Strings --> $w mit update, nach vorherigem Löschen
 global tlaOutLstAct
 set tlaOutLstAct 0
 $w configure -state normal; $w delete 0.0 end
 eval writescr2 $w $args; update idletasks
}

proc writescr2 {w args} {# bel. Anzahl von Strings --> $w ohne update
 $w configure -state normal
 foreach i $args {$w insert end "$i"}
 $w yview -pickplace end
 configureStateDisabled $w
}


proc getscl {foid e} {# filter for call of gets, but line breaks by "\" allowed
#
  upvar 1 $e ein

  set ret [gets $foid z];  set z [string trimright $z]
  set ein "$z"
  set lm1 [expr [string length $z]-1]
  while {($lm1>=0)&&([string last \\ $z]==$lm1)} { 
    set ein [string range $ein 0 [expr [string length $ein]-2]]
    set ret [gets $foid z];  set z [string trimright $z]
    set lm1 [expr [string length $z]-1]
    set ein "$ein$z"
  }
  if {$ret>=0} {set ret [string length "$ein"]};  return $ret
}


proc getscl0 {foid e} {# like getscl, but blanks at begin-of-continuation-line deleted
#                
  upvar 1 $e ein

  set ret [gets $foid z];  set z [string trimright $z]
  set ein "$z"
  set lm1 [expr [string length $z]-1]
  while {($lm1>=0)&&([string last \\ $z]==$lm1)} { 
    set ein [string range $ein 0 [expr [string length $ein]-2]]
    set ret [gets $foid z];  set z [string trimright $z]
    set lm1 [expr [string length $z]-1]
    set ein "$ein[string trimleft $z]"
  }
  if {$ret>=0} {set ret [string length "$ein"]};  return $ret
}


proc fillbox {w dat} {# fill listbox $w from .vst-file $dat, if file exists
#
  if {$dat!=""} {set f [open_vst $dat]; while {[getscl $f e]>0} {$w insert end $e}; close $f}
}


proc fillboxsep {w dat} {# listbox $w füllen aus .vst-Datei $dat und Separator
#                                     bestimmen (1. Zeichen ungleich Blank)
  set f [open_vst $dat]
  getscl $f e;  set sep [string index [string trim $e] 0]
  while {[getscl $f e]>0} {$w insert end $e}
  close $f
  return $sep
}


proc TestNotEmpty {string message} {# write message if string empty and exit
 if {$string!=""} return
 global Werr;  set Werr .xtemerror
 mybell 4;  puts stdout "\n$message\n"; flush stdout
 toplevel_init $Werr "error" 700 300
 button $Werr.l -text "$message --> exit" -command {destroy $Werr; exit} -height 20
 pack configure $Werr.l; after 2000 raise $Werr
}


proc getlnum {d} {# get number of lines in file $d (open, read-lines, close)
  set f [open_vst $d]; set n 0; while {[getscl $f e]>0} {incr n}; close $f; return $n
}


proc alternative {dv t1 t2} {# Hilfsprozedur für alternative Ausgabe 
#
  if {$dv==""} {return $t1} else {return $t2}
}


proc Request {t text1 text2 textY comY textN comN helpdatei w fd} {# 2 reply buttons: yes/no
 global  vv geom RequestActive
 TestPut 3 "<$t><$text1><$text2>< $textY><$comY> <$textN><$comN> <$helpdatei><$w>"
 set w "$w.d.tt"
 wm title $t "$vv(utvor)";  wm minsize $t 400 200
 if [info exists geom(ut_rp)] {wm geometry $t $geom(ut_rp)}
 label $t.text1 -text "$text1"; pack configure $t.text1 -padx 37 -pady 13
 set RequestActive 1
 if {$text2!=""} {label $t.text2 -text "$text2"; pack configure $t.text2 -padx 37 -pady 13}
 frame $t.r -relief raised -borderwidth 0; pack configure $t.r -pady 16
 button $t.r.yes -text "$textY" -command "set RequestActive 0; $comY"
 button $t.r.no  -text "$textN" -command "set RequestActive 0; $comN"
 bind $t.r.yes <Return> "$t.r.yes invoke; Bend"
 bind $t.r.no  <Return> "$t.r.no  invoke; Bend"
 if {$fd=="y"} {focus $t.r.yes} elseif {$fd=="n"} {focus $t.r.no}
 pack configure $t.r.yes $t.r.no  -side left -padx 13
 if {$helpdatei!=""} {
   Bind3HF $t $helpdatei $w
   Bind3HF $t.text1 $helpdatei $w; if {$text2!=""} {Bind3HF $t.text2 $helpdatei $w}
   Bind3HF $t.r.yes $helpdatei $w; Bind3HF $t.r.no  $helpdatei $w
 }
}


proc destror w {global geom
  set g [wm geometry $w]; set geom(ut_rp) [string range $g [string first + $g] end]
  destroy $w; update
}

proc destros w {global geom; set geom($w) [wm geometry $w];  destroy $w; update}

proc toplevel_init {w wname wmin wmax} {global geom; # initialisations for toplevel window

  if [winfo exists $w] {destros $w};  toplevel $w;  wm title $w $wname
  wm minsize $w $wmin $wmax;  if [info exists geom($w)] {wm geometry $w $geom($w)}
}


proc mdtest {hd stex sdvi aus} {# test for modification dates: $hd$stex / $hd$sdvi
#                         ($hd$sdvi sollte neuere Datei sein, d.h. t2>t1, dann return-Wert 1!)
 upvar 1 $aus a
 global vv
 if {$hd==""}               {mybell 2;set a "\n***** $vv(ea1)\n"; return -1}
 if ![file exists $hd$sdvi] {mybell 2;set a "\n*** $vv(ut10) $hd$sdvi $vv(ut100)\n";return -1}
 if ![file exists $hd$stex] {mybell 2;set a "$vv(ut11) $hd$stex $vv(ut12)\n"; return 1}
 set t1 [file mtime $hd$stex]
 set t2 [file mtime $hd$sdvi]
 if {$t1>$t2} {mybell 2; set a "$vv(ut11) $hd$stex $vv(ut13) $hd$sdvi $vv(ut14)\n"; return 0}
 return 1
}


proc getvalue {strng n separator} {# aus strng den n-ten Wert zurückgeben
 if {$separator==""} {return $strng}
 set count 0
 while {$count<$n} {
   set pos [string first $separator $strng]
   if {$pos>=0} {set strng [string range $strng [expr $pos+1] end]} else {set strng ""}
   incr count
 }
 set pos [string first $separator $strng]
 if {$pos>=0} {set strng [string range $strng 0 [expr $pos-1]]}
 return [string trim $strng]
}


proc checksum {suffix} {# gives checksum for all files with given suffix
# 
  global sub
  set prsum 0
  foreach i [glob -nocomplain -- *] {
    if {[file isfile $i]&&[string match "*$suffix" $i]} {
      if {[file size $i]>0} {
	##############################
	# One of the following alternatives must be chosen for checksum:
	# a) checksum in pure Tcl (simple test only!)
	#   set prsumd [checksumFile $i]
	# b) checksum with Unix command (System V and UCB)
	    SigChldB; set prsumd [string trim [lindex [exec sum $i] 0]]; SigChldU
            lock; set sub 1;
	    set prsumd [string trimleft $prsumd 0]
	##############################
      } else {
	set prsumd 0
      }
      incr prsum $prsumd
    }
  }
  return $prsum
}


proc checksumFile {datei} {# checksum in pure Tcl
#
  set fileid [open $datei r]
  set filesize [file size $datei]
  if {$filesize==0} {# Datei hat Länge 0
    close $fileid; return 0
  } else {# Datei hat Länge > 0
    set chars "abcdefghijklmnopqrstuvwxyzäöüßABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ"
    set chars "${chars}1234567890.':<>|`~!@#%^&*()-_=+\[\]\$\ \;\"\{\}\\\n\b"
    set prs 0
    set bytegel 0
    set faktor 1
    while {"$bytegel"<"$filesize"} {
      set byte [read $fileid 1]; incr bytegel
      set prs [expr "$prs+([string first $byte $chars]*$faktor)"]
      if {$faktor==1} {set faktor 2} else {set faktor 1}
    }
    close $fileid; return $prs
  }
}


proc lpcmdTest {} {# check line printer command (command specified in variable "lpcmd" found?
 global vv lpcmd lpcmdChecked
 if ![info exists lpcmdChecked] {
   TestPut 4 "$lpcmd"
   if {[catch "which $lpcmd" m]!=0} {
     puts stdout  "$vv(xtq01)\nError! Line printer command \"$lpcmd\" not found;"
     puts stdout  "check variable lpcmd in file printing.vst\n$vv(xtq01)"
     mybell 4
   }
   set lpcmdChecked 1
 }
}


proc vstr_install {args} {# read variable values from install.vst
 foreach varname $args {
   global [lindex $varname 0]
   if {[lindex $varname 1]!=""} {set [lindex $varname 0] [lrange $varname 1 end]}
 }
 if {[info exists env(XTEMINSTALL)]} {set f [open "$env(XTEMINSTALL)" r]} \
 else				     {set f [open_vst install.vst]}
 while {[getscl $f z]>0} {set [lindex $z 0] [lrange $z 1 end]}
 close $f
}

proc vstr_exec {exit} {
 global vv mkcommand xvcsel_v xvbsel_v bell_level xvsbsel_v textxscroll xtemTyh xvTyh Wx
 global XiInstallationRuns
 set f [open_vst mkcommand.vst]; set s [GetSep mkcommand.vst $f]; set m ""
 while {$m==""} {getscl $f e;  set m [getvalue $e [MkcmdTclVCol $exit] $s]}
 close $f
 set mkcommand $m
 set xvcsel_v "[string range [getvalue $e [MkcmdTclVCol exit] $s] 0 10] :  [getvalue $e 0 $s]"
 vstr_install {fsmenucols 2} {textxscroll 0} {bell_level 3}
 set xvbsel_v "$vv(xveb$bell_level)";  set xvsbsel_v "$vv(xvesb$textxscroll)"
 if {([info procs winfo]=="winfo")&&[winfo exists .d]&&![info exists XiInstallationRuns]} \
		{destroy .d; InsertTextFrame "" $xtemTyh "" "" ""}
 if {([info procs winfo]=="winfo")&&[winfo exists $Wx.d]} \
		{destroy $Wx.d; InsertTextFrame $Wx $xvTyh "" "" ""}
}

proc vstr_editor {} {
 global We editor edtext esuff edxterm edoptions evesel_v tssk
 set f [open_vst editor.vst]; set s [GetSep editor.vst $f]; getscl $f e; close $f
 set evesel_v "$e"; set edtext [getvalue $e 0 $s]
 set edxterm   [getvalue $e 1 $s]; set editor [getvalue $e 2 $s]
 set edoptions [getvalue $e 3 $s]
 vstr_install {edsyntaxhelp icon}
 if [winfo exists $We.c.f.f.li] {selection clear $We.c.f.f.li}
}

proc vstr_quick {} {
 global	quickprev
 vstr_install	{quicknonstop 1} {quickmultprv 1} {quickdelfile 0} \
		{quickprev "standard_preview"} {quickprevstd "xdvi -hold"} {quickprsstd .dvi}
 if {("$quickprev"!="standard_preview")&&("$quickprev"!="current_preview")} \
	{set quickprev "current_preview"}
}

proc vstr_tex {} {
 global Wt texfmt texfmtt texmem texmtext texmax tvfsel_v tvssel_v tvmsel_v tvHSel_v tvNSel_v
 global texloganalyze tvLSel_v texopttext texopts tlOverfull tlOfull tlHBadness tlHBad
 global vv tlMaxL tlMaxLines quickenable quickverbatim quickprereq quickpreform
 global quicksuffix quickpreamble quickendpre quickenddoc mainfilgrep texedit tvASel_v
 global hyphentext hyphenprog hyphenopts hyphenchk texposthyph texautostrt texautostrtv
 set f [open_vst texfmt.vst]; set s [GetSep texfmt.vst $f]; getscl $f e; close $f
 set tvfsel_v "$e"; set texfmtt [getvalue $e 0 $s]; set texfmt [getvalue $e 1 $s]
 set quickenable [getvalue $e 2 $s]; set quickverbatim [getvalue $e 3 $s]
 set quickprereq [getvalue $e 4 $s]; set quickpreform [getvalue $e 5 $s]
 set quicksuffix [getvalue $e 6 $s]; set quickpreamble [getvalue $e 7 $s]
 set quickendpre [getvalue $e 8 $s]; set quickenddoc [getvalue $e 9 $s]
 set mainfilgrep [getvalue $e 10 $s]
 if {$quickenable==""} {set quickenable 0}
 if {$quickenable} {setInUnlockListe .c.1.qd} {delFromUnlockListe .c.1.qd}
 if [winfo exist $Wt] {lock; unlock_list; update}
 set f [open_vst texsiz.vst]; set s [GetSep texsiz.vst $f]; getscl $f e; close $f
 set tvssel_v "$e"; set texmtext [getvalue $e 0 $s]; set texmem [getvalue $e 1 $s]
 set f [open_vst texopts.vst]; set s [GetSep texopts.vst $f]; getscl $f e; close $f
 set tvNSel_v "$e"; set texopttext [getvalue $e 0 $s]; set texopts [getvalue $e 1 $s]
 set f [open_vst hyphen.vst]; set s [GetSep hyphen.vst $f]; getscl $f e; close $f
 set tvHSel_v "$e"; set hyphentext [getvalue $e 0 $s]; set texposthyph [getvalue $e 1 $s]
 set hyphenprog [getvalue $e 2 $s]; set hyphenopts [getvalue $e 3 $s]
 set hyphenchk [getvalue $e 4 $s]
 if {$hyphenchk==""} {set hyphenchk {$mainfile.hck}}
 if {$hyphenchk=="/dev/null"} {set hyphenchk ""}
 vstr_install {texposttex 1} {texmax 1} texedit {texautostrt 0} {texautostrtv 0} \
		{texloganalyze 1}
 if {$texmax==1} {set tvmsel_v $texmax} else {set tvmsel_v "$vv(max) $texmax"}
 if {$texautostrtv>0} {set tvASel_v $vv(yes)} {set tvASel_v $vv(no)}
 if [winfo exists $Wt.c.f.f.f.li] {selection clear $Wt.c.f.f.f.li}
 if [winfo exists $Wt.c.s.f.f.li] {selection clear $Wt.c.s.f.f.li}
 if [winfo exists $Wt.c.m.f.f.li] {selection clear $Wt.c.m.f.f.li}
 if [winfo exists $Wt.c.l.f.f.li] {selection clear $Wt.c.l.f.f.li}
}

proc vstr_preview {} {
 global Wp vst_dir prtext preview prsuffix proptions prformat prpreopt
 set f [open_vst preview.vst]; set s [GetSep preview.vst $f]; getscl $f e;
 set z [split $e $s]; set prtext   [string trim [lindex $z 0]]
 set preview   [string trim [lindex $z 1]]; set prsuffix [string trim [lindex $z 2]]
 set proptions [string trim [lindex $z 3]]
 set fl [string trim [lindex $z 4]];set p1 [string first \{ $fl];set p2 [string first \} $fl]
   set prformat [string trim [string range $fl 0 [expr $p1-1]]]
   if {[expr $p1+1]<$p2} \
	{set prpreopt [string trim [string range $fl [expr $p1+1] [expr $p2-1]]]} \
   else {set prpreopt ""}
 set fl [string range $fl [expr $p2+1] end];
 set p1 [string first \{ $fl]; set p2 [string first \} $fl]
 if {[expr $p1+1]<$p2} \
    {set proptions "$proptions [string trim [string range $fl [expr $p1+1] [expr $p2-1]]]"}
 while {$e!=""} {
   if {[string trim [lindex $z 4]]==""} {
     puts stdout "Error in file $vst_dir/preview.vst - empty format string in line:\n $e"
     mybell 3
   }
   getscl $f e; set z [split $e $s]
 }
 close $f
 if [winfo exists $Wp.c.1.f.f.li] {selection clear $Wp.c.1.f.f.li}
 if [winfo exists $Wp.c.2.f.f.li] {selection clear $Wp.c.2.f.f.li}
}

proc vstr_logfile {} {
 global Wl logtext logform logxterm logoptions lsuff lvfsel_v lvssel_v
 set f [open_vst logform.vst]; set s [GetSep logform.vst $f]; getscl $f e; close $f
 set lvfsel_v "$e"; set logtext [getvalue $e 0 $s]
 set logxterm   [getvalue $e 1 $s]; set logform [getvalue $e 2 $s]
 set logoptions [getvalue $e 3 $s]
 set f [open_vst logsuffix.vst]; getscl $f e; close $f; set lvssel_v "$e";
 set lsuff [getvalue $e 0 " "]
 if {($logform=="tl")&&($lsuff!=".log")} {set lsuff ".log"}
 if [winfo exists $Wl.c.1.f.f.li] {selection clear $Wl.c.1.f.f.li}
 if [winfo exists $Wl.c.2.f.f.li] {selection clear $Wl.c.2.f.f.li}
}

proc vstr_cleanup {} {
 global aufmax aufsuff auftoggle
 set f [open_vst cleanup.vst]; set s [GetSep cleanup.vst $f]
 set aufsuff ""; set auftoggle ""
 while {[getscl $f e]>0} \
   {set aufsuff "$aufsuff [getvalue $e 0 $s]"; set auftoggle "$auftoggle [getvalue $e 1 $s]"}
 close $f
}

proc vstr_printer {} {
 global vv vst_dir printer lpcmd lpopt prtpresel prtselstr
 global prtoptions prtsuf prtfilperm prtformat prtdriver prtlistsort
 set et1 "Error in file\n  $vst_dir/printing.vst,\n (logical) line"
 set et2 "\n$vv(adm)\n"
 set f [open_vst printing.vst];getscl $f e; set ln 1;set s [string index [string trim $e] 0]
 TestNotEmpty "$s" "$et1 $ln (empty first line!)\n$et2"
 set drselmax 2; while {[getvalue $e [expr $drselmax+9] $s] != ""} {incr drselmax}
 getscl $f e; incr ln; set z [split $e $s]
 if {[string trim [lindex $z 0]]==""} {# first argument is empty: pre-selection settings
   set prtpresel [string trim [lindex $z 1]]
   if {([string trim [lindex $z 2]]=="*")||([string trim [lindex $z 2]]=="")|| \
       ([string trim [lindex $z 3]]=="*")||([string trim [lindex $z 3]]=="")} \
	{set prtpresel "$prtpresel *"} \
   else {set prtpresel "$prtpresel [string trim [lindex $z 2]]:[string trim [lindex $z 3]]"}
   for {set i 2} {$i<=$drselmax} {incr i} \
	{set prtpresel "$prtpresel [string trim [lindex $z [expr $i+9]]]"}
   getscl $f e; incr ln; set z [split $e $s]
 } else {# 1 argument not empty: printer setting line
   for {set i 1; set prtpresel "*"} {$i<=$drselmax} {incr i} {set prtpresel "$prtpresel *"}
 }
 set prtselstr "[string trim [lindex $z 0]], [string trim [lindex $z 1]]"
 set prtselstr "$prtselstr, [string trim [lindex $z 2]]:[string trim [lindex $z 3]]"
 set l [string trim [lindex $z 11]]; set p [string first \{ $l]
 set et3 "format selection specification (11th parameter) incorrect"
 if {$p<=0} {TestNotEmpty "" "$et1 $ln:\n$e\n$et3\n$et2"; return}
 set prtselstr "$prtselstr, [string trim [string range $l 0 [expr $p-1]]]"
 set prtformat [string trim [string range $l 0 [expr $p-1]]]
 for {set i 4} {$i<=$drselmax} {incr i} {
   set l [string trim [lindex $z [expr $i+8]]]; set p [string first \{ $l]
   if {$p>0} {set prtselstr "$prtselstr, [string trim [string range $l 0 [expr $p-1]]]"} \
   else {set prtselstr "$prtselstr, [string trim $l]"}
 }
 prt_select "$prtselstr" ""
 set et4 "(empty last criterion/[expr $drselmax+8].th criterion must be non-blanc!)"
 while {$e!=""} {
   if {[string trim [lindex $z [expr $drselmax+8]]]==""} \
	{puts stdout "$et1 $ln:\n$e\n$et4\n$et2"; mybell 3}
   getscl $f e; incr ln; set z [split $e $s]
 }
 close $f
 vstr_install {prtlistsort 0}
 vstr_driver
}
proc vstr_driver {} {
 global Wdm Wdv prtdriver dmdsel_v prmtext prmrelabs prmsel prtreversed prtcmd prtcmdmax
 set f [open_vst prt_$prtdriver.vst]; set s [GetSep prt_$prtdriver.vst $f]
 getscl $f e; close $f; set z [split $e $s]; set dmdsel_v "$e"
 set prmtext [string trim [lindex $z 0]]; set prmrelabs [string trim  [lindex $z 1]]
 set prmsel [string trim [lindex $z 2]]; set prtreversed [string trim [lindex $z 3]]
 for {set c 1} {$c<=$prtcmdmax} {incr c} {set prtcmd($c) "[getvalue $e [expr $c+3] $s]"}
 if [winfo exists $Wdm.b.f.f.li] {selection clear $Wdm.b.f.f.li}
 if [winfo exists $Wdv.c.f.f.li] {selection clear $Wdv.c.f.f.li}
}

proc vstr_spell {} {
 global Wr sptext spcmd splang spcorr spselect spoptions rvsel_v
 set f [open_vst spellcheck.vst]; set s [GetSep spellcheck.vst $f]; getscl $f e; close $f
 set rvsel_v "$e"; set sptext [getvalue $e 0 $s]
 set spcmd [getvalue $e 1 $s];  set splang [getvalue $e 2 $s]
 set spcorr [getvalue $e 3 $s]; set spselect [getvalue $e 4 $s]
 set spoptions [getvalue $e 5 $s]
 if [winfo exists $Wr.c.f.f.li] {selection clear $Wr.c.f.f.li}
}

proc vstr_index {} {
 global Wi
 set f [open_vst index.vst]; set s [GetSep index.vst $f]; getscl $f e; close $f
 if [winfo exists $Wi.c.ipp.f.f.li] {selection clear $Wi.c.ipp.f.f.li}
 set_index_vars "$s" "$e"
 vstr_install {texpostind 1}
}
proc set_index_vars {s e} {
 global intext index inoptions ivsel_v
 set ivsel_v "$e"; set intext [getvalue $e 0 $s]
 set index [getvalue $e 1 $s]; set inoptions [getvalue $e 2 $s]
}

proc vstr_syntax {} {
 global Ws sytext syntax syoptions svsel_v
 set f [open_vst syntax.vst]; set s [GetSep syntax.vst $f]; getscl $f e; close $f
 set svsel_v "$e"; set sytext [getvalue $e 0 $s]
 set syntax [getvalue $e 1 $s]; set syoptions [getvalue $e 2 $s]
 if [winfo exists $Ws.c.f.f.li] {selection clear $Ws.c.f.f.li}
}

proc vstr_bibtex {} {
 global Wb bibtex bitext bioptions bvsel_v texpostbib
 set f [open_vst bibtex.vst]; set s [GetSep bibtex.vst $f]; getscl $f e; close $f
 set bvsel_v "$e"; set bitext [getvalue $e 0 $s]
 set bibtex [getvalue $e 1 $s]; set bioptions [getvalue $e 2 $s]
 if [winfo exists $Wb.c.f.f.li] {selection clear $Wb.c.f.f.li}
 vstr_install {texpostbib 0}
}

proc vstr_letter {} {
 global Wm 
 set f [open_vst letter.vst]; set s [GetSep letter.vst $f]; getscl $f e; close $f
 if [winfo exists $Wm.c.ipp.f.f.li] {selection clear $Wm.c.ipp.f.f.li}
 set_letter_vars "$s" "$e"
}
proc set_letter_vars {s e} {
 global lettext letter letoptions letbackalw letback mvsel_v
 set mvsel_v "$e"; set lettext [getvalue $e 0 $s]
 set letter [getvalue $e 1 $s]
 set letbackalw [getvalue $e 2 $s]; set letback [getvalue $e 3 $s]
 if {$letbackalw==0} {set letback 0}; mvChkBackWidg
 set letoptions [RegsubHOMEetc [getvalue $e 4 $s]]
}

proc vstReadDriver {} {
  global oldsuff texsuffix main_file
  set oldsuff $texsuffix
  vstRead .d.tt eigene.vst
  if {($oldsuff!="")&&($oldsuff!=$texsuffix)} {set main_file ""}
  MkcmdSource; knoepfe
}

proc vstRead {w vst_file} {# Voreinstellungen lesen: Rahmen für vstGetValues
#
  global  version_vst main_file dir efile env vstdat prvformat prformat opsep
  global  prtoptions olsep lpopt editor edback preview logform logback texsuffix
  global  logxterm edxterm logoptions edoptions version_incompatible language logtext
  global  vst_dir

  set version_vst 0.00
  if {$vst_file=="default.vst"}  {# "Grund-Voreinst."
    set vstdat ""
  } else                            {# "Start/eigene Voreinst."
    if {($main_file=="")&&[file exists .lastxtem]} {
	set f [open ".lastxtem" r]
	while {[getscl $f e]>0} \
		{mtest $e dir; mtest $e main_file; mtest $e texsuffix; mtest $e efile}
	close $f
	if ![file exists $main_file$texsuffix] \
		{unlink -nocomplain .lastxtem; set dir ""; set main_file ""; set efile ""} \
	elseif {$dir!="[pwd]"} \
		{unlink -nocomplain .lastxtem; set dir ""}
	if {$efile==""} {set efile $main_file}
    } elseif {($main_file!="")&&[file exists .lastxtem]} {
	set f [open ".lastxtem" r]
	getscl $f zd; getscl $f zm; getscl $f zms; getscl $f ze; getscl $f zes
	close $f
	if {[lindex $zm 1]=="$main_file"} {set efile [lindex $ze 1]}
    }
    if {($main_file!="")&&[file exists "${main_file}_$language.vst"] \
      &&($vst_file!=".xtem_$language.vst")} {
	set vstdat ${main_file}_$language.vst
    } elseif {[file exists "$env(HOME)/.xtem_$language.vst"]} {
	set vstdat "$env(HOME)/.xtem_$language.vst"
    } else {
	set vstdat ""
    }
  }
  TestPut 3 "vstdat=<$vstdat>"
  vstGetValues $w $vstdat; # eigentliches Lesen der Voreinstellungen!
  update_prtformat
  set prvformat $prformat
  set opsep [string index $prtoptions 0]; set olsep [string index $lpopt 0]
  TestPut 3 "olsep=<$olsep>"
  if {$logform=="\$editor"} {
    set logxterm $edxterm; set logform $editor; set logback $edback; set logoptions $edoptions
    set logtext ""
  }
  if {$w!=""} {disp_prefs1 $w}
  set r 0
  if {[string range $version_vst 0 3]<=$version_incompatible} {
    if {($vstdat!="")&&![file exists $vstdat.bak]} {frename $vstdat $vstdat.bak;set r $vstdat}
  }
  if {$vstdat==""} {set vstdat $vst_dir/*.vst}
  return $r
}


proc update_prtformat {} {
  global  prtselstr prtformat
  set prtformat [string trim [lindex [split $prtselstr ","] 3]]
}


proc GetSep {file FID args} {# read separator for vst-file (read separator line only)
 global vv
 getscl $FID e; set s [string index [string trim $e] 0]
 TestNotEmpty "$s" "Error in file $args $file (empty first line!)\n$vv(adm)"
 TestPut 4 "<$args><$file><$s>"
 return $s
}

proc getsep {file args} {# get separator for vst-file $file (open, read-separator, close)
 set FID [open_vst $file $args]; set s [GetSep $file $FID $args]; close $FID
 return $s
}

proc open_vst {filename args} {# open for a .vst-file
 global xtem_path vst_dir language env 
 set dir [lindex $args 0]
 TestPut 3 "<$filename><$args><$dir>"
 if {"$dir"!=""} {
   set f [open "$dir/$filename" r]
   set vst_dir "$dir"
 } elseif {[info exists env(XTEMVSTDIR)]} {
   if {[file exists $env(XTEMVSTDIR)/$filename]} {
     set f [open "$env(XTEMVSTDIR)/$filename" r]
     set vst_dir "$env(XTEMVSTDIR)"
   } else {
     set f [open "$xtem_path/locals_$language/$filename" r]
     set vst_dir "$xtem_path/locals_$language"
   }
 } else {
   set f [open "$xtem_path/locals_$language/$filename" r]
   set vst_dir "$xtem_path/locals_$language"
 }
 TestPut 4 "<$args><$filename> <$dir> <$vst_dir>"
 return $f
}

proc vst2list {file skip sep text var args} {# read setting file, return as list
  global [set var]
  if ![info exists [set var]] {set [set var] ""}
  set f [open_vst $file $args]
  for {set s 1} {$s<=$skip} {incr s} {getscl $f e}
  set l ""
  while {[getscl $f e]>0} {
    lappend l $e
     if {$text==[getvalue $e 0 $sep]} {eval set [set var] \"\$e\"}
		# do not evaluate $e here (e.g because of $HOME in spell.vst)!
  }
  close $f
  return "$l"
}

proc vstGetValues {w vstdat} {# Voreinstellungen lesen
#
  global vv vst_dir tclversion vstReadSkipSuff

  foreach variable [ListVstVars] {global [set variable]}
  global edback prback logback prtcmdmax prtcmd geom efile

  if {$vstdat==""} {
    vstr_exec exit; vstr_editor; vstr_quick; vstr_tex; vstr_preview; vstr_logfile
    vstr_cleanup; vstr_printer; vstr_spell; vstr_syntax; vstr_index; vstr_bibtex; vstr_letter
  } else {
    if {$w != ""} {writescr0 $w "$vv(xt28) $vstdat\n\n"}
    set prmsel ""; for {set c 1} {$c<=$prtcmdmax} {incr c} {set prtcmd($c) ""}
    if {$vstReadSkipSuff>0} {set ots $texsuffix; set oef $efile; set oes $esuff}
    set f [open $vstdat r]
    while {[getscl0 $f z]>0} {
	TestPut 4 "<$vstdat><$z>"
	set z "[string trim $z] "; set p [string first " " $z]
	set [string range $z 0 [expr $p-1]] [string trim [string range $z $p end]]
    }
    close $f
    if {($vstReadSkipSuff==3)||($vstReadSkipSuff==1)} {set texsuffix $ots}
    if {($vstReadSkipSuff==3)||($vstReadSkipSuff==2)} {
      if {("$efile"!="")&&![file exists $efile$oes]} {
	foreach s [vst2list texsuffix.vst 0 "" "" ""] \
			{if {"$s"=="*"} {set s ""}; if [file exists $efile$s] {set esuff $s}}
      } else {set esuff $oes}
    }
    if {($tclversion>=7.5)&&($mkcommand=="mkcommand.3")} {vstr_exec exit}
  }
  progback  editor  edback; progback  preview prback; progback  logform logback

}


proc lastxtemWrite {} {# writes file .lastxtem
 set l ""; lappend l dir main_file texsuffix efile esuff; writeVarList2File .lastxtem $l ""
}


proc writeVarList2File {file list globl} {# write variable names and values of list into file
 TestPut 3 "<$file><$list><$globl>"
 if {[catch "open $file w" FID]==0} {
   foreach var $globl {global $var}
   foreach var $list {global [set var]; eval puts \$FID \"\$var \$$var\"}
   close $FID
   TestPut 3 "written:<$FID>"
 }
}


proc vstWriteFile {vst_file} {# Voreinstellungen in vst-Datei schreiben
#
 global version_vst version language editor edback preview prback logform logback
 global prtcmdmax prtcmd geom env 

 set geom(xtem) [wm geometry .]
 # save some variable values ...
	set version_Vst $version_vst; set version_vst "$version"
	set editor $editor$edback; set preview $preview$prback; set logform $logform$logback

 set vstWListe ""
 if {"$vst_file"!="$env(HOME)/.xtem_$language.vst"} {lappend vstWListe dir main_file efile}
 set vstWListe "$vstWListe [ListVstVars]"
 if [info exists geom] {foreach k [array names geom] {lappend vstWListe geom($k)}}
 for {set c 1} {$c<=$prtcmdmax} {incr c} {lappend vstWListe prtcmd($c)}
 writeVarList2File $vst_file $vstWListe "geom prtcmd"

 # ... and restore some variable values
	set version_vst $version_Vst
	if {$edback!=""}  {set editor  [string trimright $editor  $edback]}
	if {$prback!=""}  {set preview [string trimright $preview $prback]}
	if {$logback!=""} {set logform [string trimright $logform $logback]}
}

proc vstWriteCom {w} {global vv env main_file language
 vstWriteFile "$env(HOME)/.xtem_$language.vst"
 $w.ins configure -state disabled -text " $vv(ut194) "
}   

proc vstWrite {win} {# Voreinstellungen sichern
#
 global vv Wq env main_file language mkcommand

 if {$mkcommand=="mkcommand.9"} {writescr0 .d.tt "\n*** $vv(ut15)"; mybell 3; return}
 #
 if {[string length $main_file]>0}	{set f "${main_file}_$language.vst"} \
 else					{set f "$env(HOME)/.xtem_$language.vst"}
 #
 if {[file writable $f]||![file exists $f]} \
	{vstWriteFile "$f";  writescr0 $win "$vv(ut16) $f $vv(ut17):\n\n";  disp_prefs1 $win}
 #
 if {[string length $main_file]>0} {
   lastxtemWrite
   if {[file writable $f]||![file exists $f]} \
	{writescr $win "$vv(ut18) `$main_file' $vv(ut17)!\n"}
   set HOMEvst "$env(HOME)/.xtem_$language.vst"
   if {[file writable $HOMEvst]||![file exists $HOMEvst]} {
     writescr $win "$vv(ut19)\n$vv(ut190) `$HOMEvst'\n"
     writescr $win "$vv(ut191)\n$vv(ut192)\n"
     button $win.ins -text " $vv(ut193) " -command " vstWriteCom $win"
     $win window create insert -window $win.ins
   }
 }
}


proc ListVstVars {} {# returns list of variables in *personal* setting files
 lappend vstListe version_vst
 lappend vstListe bibtex bitext bioptions
 lappend vstListe editor edtext edxterm edoptions edsyntaxhelp esuff
 lappend vstListe hyphentext hyphenprog hyphenopts hyphenchk index intext inoptions
 lappend vstListe letter lettext letoptions letback letbackalw
 lappend vstListe logform logtext logxterm logoptions lsuff
 lappend vstListe preview prtext prsuffix proptions prformat prpreopt
 lappend vstListe printer lpcmd lpopt prtdriver prtselstr prtoptions prtnumpag prtlistsort
 lappend vstListe prtreversed prtfilperm prtsuf prtpresel prmtext prmsel prmrelabs
 lappend vstListe quickenable quickverbatim quickprereq quickpreform
 lappend vstListe quickdelfile quicknonstop quickmultprv quickprev quickprevstd quickprsstd
 lappend vstListe quicksuffix quickpreamble quickendpre mainfilgrep quickenddoc
 lappend vstListe spcmd sptext splang spcorr spselect spoptions
 lappend vstListe syntax sytext syoptions
 lappend vstListe texedit texfmt texfmtt texmem
 lappend vstListe texpostbib texposthyph texpostind texpostps texposttex texmtext texautostrtv
 lappend vstListe texmax texsuffix texloganalyze texopttext texopts tlOfull tlHBad tlMaxL
 lappend vstListe aufmax aufsuff auftoggle mkcommand hlp_bmsuppr fsmenucols mdispmainv
 lappend vstListe bell_level textxscroll mousebutts syntaxmark
 lappend vstListe  SetMenuCalled
 return "$vstListe"
}


proc installLesen {} {# following global list variables are taken from locals_*/install.vst
 global vv env InstDir widthl widthr sizeds unlockbutt noWarnTcl shortbutts mousebutts
 global fontdli fontsli fontbl fontstdout fonterr fonterrtag fonted errbgrd errfgrd
 global prtselmaxl prtselmaxc prtfilperm hyphentext hyphenprog hyphenopts hyphenchk
 global texpostbib texposthyph texpostind texpostps texposttex texautostrt texautostrtv
 global texloganalyze
 global maxprintcops vlerg hlp_font xtermcall edsyntaxhelp bell_level syntaxmark
 global texedit texmax whichcheck geom button2end fsmenucols fshistory
 global mdispmain mdispmainv efilesearch filNotExdsp
 global b_quick b_spell b_syntax 1 b_index b_bibliography b_additional b_logfile b_letters
 global bindkeysenab bindkeys prtnumpag prtlistsort
 global tlDirIgnore tlOverfull tlHBadness tlMaxLines quickfile exallowset textxscroll
 global quickverbatim quickdelfile quicknonstop quickmultprv
 global quickprev quickprevstd quickprsstd urlcallexec
 global letter lettext letoptions letback letbackalw

 if [info exists env(XTEMINSTALL)] \
	{set f [open "$env(XTEMINSTALL)" r];  set InstDir "${InstDir} ($vv(xt1))\n"} \
 else  {set f [open_vst install.vst]}

 while {[getscl $f z]>0} {set [string trim [lindex $z 0]] [string trim [lrange $z 1 end]]}
 close $f
}


proc disp_prefs1 {win} {# aktuelle Einstellungen anzeigen (ohne Dateien)
#
  global  vv editor edback edtext esuff texfmt texmtext texmax preview prback
  global  logform logback printer prtdriver prmtext spcmd syntax index bibtex
  global  mkcommand prformat prtformat

  writescr .d.tt " $vv(ut20) $editor$edback  $edtext" \
	[alternative $edback "\n" "   $vv(ut21)\n"] \
	"    $vv(ut200)" [alternative $esuff " *\n" " $esuff\n"] \
	" $vv(ut22) $texfmt\n    $vv(ut23) $texmtext\n    $vv(ut24) $texmax\n" \
	" $vv(ut25) $preview$prback" \
	[alternative $prback "" "   $vv(ut21)"]  ", $prformat\n" \
	" $vv(ut26) $logform$logback\n $vv(ut27) $printer\n" \
	" $vv(ut28) $prtdriver,  $prtformat\n $vv(ut29) $prmtext\n $vv(ut30) $spcmd\n" \
	" $vv(ut31) $syntax\n $vv(ut34) $index\n $vv(ut32) $bibtex\n $vv(ut33) $mkcommand\n\n"
}


proc disp_prefs2 {win} {# aktuelle Einstellungen anzeigen (mit Dateien)
#
  global  vv main_file efile texfmt esuff tsuff

  disp_prefs1 $win
  writescr .d.tt [alternative $efile " $vv(bad1)\n" " $vv(bad2) $efile$esuff\n"] \
	[alternative $main_file " $vv(tvbad1) $texfmt $vv(tvbad3)\n" \
	  " $vv(tvbad2) $texfmt $vv(tvbad3): $main_file$tsuff\n"]
}


proc ConfigText {w t} {if [winfo exists $w] {$w configure -text $t}}


proc LockButtons {args} {foreach but $args {$but configure -state disabled}; update idletasks}


proc UnlockButtons {args} {foreach but $args {$but configure -state normal}; update idletasks}


proc lock {} {global gesliste anl0; # lock all main menu buttons (gesliste), sets anl0 -> 1
 foreach but $gesliste {$but configure -state disabled}; update idletasks; set anl0 1; update
}


proc unlock {liste} {global sub anl0; # unlocks the given buttons, sets -> 0: anl0, sub
 update; foreach button $liste {$button configure -state normal}; set sub 0; set anl0 0
 ### update needed at this position: editor/preview/... call in forground, blocking of
 ### mouse-clicks done during foreground job running!!!
}


proc unlock_list {} {#unlock buttons in unlockliste (sets anl0 -> 0 by call of procedure lock)
 global Wo unlockliste edsubback prsubback letsubback TeXRunActive UnLock
 if {$UnLock==0} {return}
 if {[winfo exists $Wo]||$TeXRunActive} {return};# no unlock if TeX or `additional pr.' active
 if {([processActive edliste]==0)&&($edsubback>0)} {set edsubback 0; setInUnlockListe .c.1.ed}
 if {([processActive prliste]==0)&&($prsubback>0)} {set prsubback 0; setInUnlockListe .c.1.pr}
 if {([processActive letliste]==0)&&($letsubback>0)} \
						  {set letsubback 0; setInUnlockListe .c.2.le}
 unlock $unlockliste
}


proc processActive {liste} {# returns number of processes in liste still active in background
 global [set liste];  set pl [set $liste]
 foreach p $pl {
   if {[process $p]!=0} {set i [lsearch $pl $p]; set pl [lreplace $pl $i $i];# $p not active!}
 }
 set [set liste] $pl;  return [llength $pl]
}


proc DestroyAfterKillEtc {prozessliste} {# kill processes, delete files, destroy xtem
 global quickdelfile fshistory
 TestPut 4 "<$prozessliste>"
 if {[llength $prozessliste]!=0} {
   foreach pi $prozessliste {killprocess $pi}; update;  SigChldB; exec sleep 1; SigChldU
 }
 if {$quickdelfile>=1} {QuickFilDel --all}
 unlink -nocomplain .xtemStamp
 if {$fshistory>0} {writeFsHist}
 signal default SIGCHLD
 destroy .
}


proc getFsHist {} {# read file selection history from file ~/.xtem_history
 global env fsHist
 set fsHist ""
 if [file exists $env(HOME)/.xtem_history] {
   set FID [open "$env(HOME)/.xtem_history" r]
   while {[getscl $FID e]>0} {lappend fsHist "$e"}
   close $FID
 }
 TestPut 4 "fsHistory:\n$fsHist"
}

proc writeFsHist {} {# write file selection history into file ~/.xtem_history
 global env fsHist
 if {$fsHist!=""} {
   set FID [open "$env(HOME)/.xtem_history" w]; foreach fs $fsHist {puts $FID $fs}; close $FID
 }
}

proc insFsHist {mainfile efile} {# insert fileSelection at top of file selection history
 global fsHist fshistory
 TestPut 4 "<[llength $fsHist]><$mainfile><$fshistory>\n$fsHist"
 if {$mainfile==""} {return}
 set dir [file dirname $mainfile]
 if {($dir==".")||([string first "../" "$mainfile"]==0)} {set mainfile "[pwd]/$mainfile"}
 set dir [file dirname $mainfile]; set main [file tail $mainfile]
 set string "$main $dir"
 set p [lsearch $fsHist "$string"]
 TestPut 4 "<$p><$string>"
 if {$p>=0} {set fsHist [lreplace $fsHist $p $p]}
 set fsHist [linsert $fsHist 0 "$string"]
 if {[llength $fsHist]>$fshistory} {set fsHist [lrange $fsHist 0 [expr $fshistory-1]]}
 TestPut 4 "<[llength $fsHist]><$mainfile><$p>\n$fsHist"
}

proc selFsHist {args} {# file selection from history
 global main_file texsuffix efile esuff fsWMenu language
 set main_file "[lindex $args 1]/[file rootname [lindex $args 0]]"
 set texsuffix [file extension [lindex $args 0]]
 dirMainFile
 set efile $main_file; set esuff $texsuffix
 TestPut 4 "<$args> <[pwd]><$main_file><$texsuffix> <$efile><$esuff>"
 destroy $fsWMenu
 writescr0 .d.tt ""; if {[file exists "${main_file}_$language.vst"]} {vstReadDriver}
 knoepfe
}


proc fillString2Length {string length} {# fills string up to length with trailing blanks
 while {[string length $string]<$length} {set string "$string "}
 return "$string"
}


proc format_switch {w fmtneu mod} {# switch format (e.g. portrait/landscape)
                                   # for preview and printing
  global vv Wp Wdv prformat prtext prvformat prvfmtli pvnoend prtselstr prtformat prtfmtli

  set fmtlisten 0

  TestPut 4 "<$prvformat><$prtformat>  <$fmtneu>"
  if {$w=="$Wdv.d.tt"} {if {[winfo exists $Wp]} {writescr0 $Wp.d.tt ""}} \
  else {if {[winfo exists $Wdv]} {writescr0 $Wdv.d.tt ""}}

  set prfmtalt "$prvformat"
  if {($mod==1)||($mod==3)} {
    if {$fmtneu==$prfmtalt} {# no format change necessary (old = new)
      writescr $w "$prvformat $vv(pvfe)\n"
    } else {# format has to be changed (old /= new)
      set prres [prv_select "$prtext, $prformat" "$fmtneu"]
      set prvformat $fmtneu
      if {$prres} {# preview format changed
        if {$w=="$Wdv.d.tt"} {writescr $w "$vv(ut35)\n$vv(ut35a)\n $prtext, $prformat\n\n"}
        if {[winfo exists $Wp]} prvlistfill
      } else {# preview format could not be changed; only update preview list
        writescr $w "$vv(ut37)\n$vv(ut38)\n$vv(ut39)\n\n"
        if {[winfo exists $Wp]} prvlistfill
        mybell 3; set fmtlisten 1; set pvnoend 1
      }
    }
  }

  set prtfmtalt "$prtformat"
  if {$mod>=2} {
    if {$fmtneu=="$prtfmtalt"} {# no format change necessary (old = new)
      writescr $w "$prtformat $vv(dvfe)\n"
    } else {# format has to be changed (old /= new)
      set prtres [prt_select "$prtselstr" "$fmtneu"]
      if {$prtres} {# printer format changed
        if {$w=="$Wp.d.tt"} {writescr $w "$vv(ut36)\n$vv(ut36a)\n $prtselstr\n\n"}
      } else {# printer format could not be changed
        writescr $w "$vv(ut40)\n$vv(ut41)\n$vv(ut42)\n\n"
        mybell 3; set fmtlisten 1; set pvnoend 1
      }
    }
  }

  if {$fmtlisten} {
    writescr $w "$vv(ut43) ($prtext):\n$prvfmtli\n"
    writescr $w "$vv(ut44) ($prtselstr):\n$prtfmtli\n"
  }
  TestPut 4 "<$prvformat><$prtformat>"
}


proc InsertTextFrame {w tyh xx yy zz} {# text frame for help/program output
 global textxscroll bindkeysenab WTB
 TestPut 4 "<$w><$tyh>"
 frame $w.d -relief raised -borderwidth 2
 pack configure $w.d -anchor sw -fill both -expand true
 if {($textxscroll>1)||(($textxscroll>0)&&($w==""))} {
   text $w.d.tt -height $tyh -yscrollcommand [list $w.d.yb set] \
		-wrap none -xscrollcommand [list $w.d.xb set]
   scrollbar $w.d.xb -orient horizontal -command [list $w.d.tt xview]
   pack configure $w.d.xb -side bottom -fill x
   Bind3HF $w.d.xb z_textfeld $w.d.tt
 } else {
   text $w.d.tt -height $tyh -yscrollcommand [list $w.d.yb set]
 }
 scrollbar $w.d.yb -orient vertical -command [list $w.d.tt yview]
 pack configure $w.d.yb -side right -fill y
 pack configure $w.d.tt -side left -fill both -expand true
 Bind3HF $w.d.yb z_textfeld $w.d.tt
 Bind3HF $w.d.tt z_textfeld $w.d.tt
 if {($bindkeysenab==1)&&($w=="")} {set cmdxkb CmdXKB} {set cmdxkb ""}
 bind CmdX$w.d.tt <Key-Up>		"$w.d.tt yview scroll -1 units"
 bind CmdX$w.d.tt <Key-Down>		"$w.d.tt yview scroll  1 units"
 bindtags $w.d.tt "CmdXNo CmdX$w.d.tt $cmdxkb $WTB([AlphNum CmdXNo$w.d.tt]) . all"
 focus $w.d.tt
 TestPut 4 "<$WTB([AlphNum CmdXNo$w.d.tt])>"
}


proc AlphNum {s} {regsub -all {[^0-9a-zA-Z]} $s "" as; return $as};# returns pure alphanum
proc Num {s} {regsub -all {[^0-9]} $s "" as; return $as};# returns pure numerical
proc TestNumGE0 {s} {# tests if s is pure num and >=0 (then return value s, else return -1)
  regsub -all {[^0-9]} $s "" n; if {[string compare $s $n]==0} {return $s} {return -1}
}


proc insertTopButtons {w h endCom args} {# inserts 3 top buttons: exit, help, clear -> $w.a
 global vv hlp_dir

 if {$args==""} {set wh $w.d.tt} {set wh $args}
 frame $w.a -relief raised -borderwidth 1; pack configure $w.a -pady 3 -anchor nw
 
 button $w.a.e -text "$vv(ae)" -command $endCom
 button $w.a.h -text "$vv(ah)" -command "catFile ${hlp_dir}$h.hlp $wh clear"
 button $w.a.l -text "$vv(al)" -command "writescr0 $wh {}"
 pack configure $w.a.e $w.a.h $w.a.l -side left -padx 3 -pady 3
 Bind3HF $w.a.e z_vstquit $wh
 Bind3HF $w.a.h z_help $wh
 Bind3HF $w.a.l z_loeschetf $wh
 wm protocol ".[lindex [split $w "."] 1]" WM_DELETE_WINDOW $endCom
}



proc CreateLSBox {w text s wi he bw hf hw sep list com sel come args} {
# creates frame w.f and title for selection, fills with list
# creates selection box + scrollbar or radiobuttons; width wi, height he; help-text hf in hw
#  sel... --> $sel : select box (no radio butons) in any case (selnoysb:  without scrollbar)
#
  global vv [set com]_v lastclick button2end but2invoked

  set ldist 4
  foreach a $args {set [lindex $a 0] [lindex $a 1]}

  frame $w.f;# -relief raised -borderwidth $bw
  pack configure $w.f -anchor w -padx $ldist -fill x -expand yes
  if {$text!=""} {
    frame $w.f.l; pack configure $w.f.l -side $s -anchor w
    label $w.f.l.t -text $text; pack configure $w.f.l.t -side left -anchor w
    if {$hf!=""} {Bind3HTF $w.f.l.t "$vv(btclk1):\n" $hf $hw}
  }
  frame $w.f.f; pack configure $w.f.f -anchor w -fill x -expand yes
  if {($come!="")&&($button2end==2)} {set hp "$vv(btclk2):\n  $vv(btclk3)\n"} else {set hp ""}
  set hp "${hp}$vv(btclk1):\n"
  if {([string first "sel" "$sel"]>=0)||([llength $list]>$he)} {
    scrollbar $w.f.f.ys -command "$w.f.f.li yview"
    scrollbar $w.f.f.xs -command "$w.f.f.li xview" -orient horiz
    set ysc "$w.f.f.ys set"; set xsc ""; # default settings
    if {$sel=="selnoysb"} {set ysc ""}
    if {$sel=="selxsb"} {set xsc "$w.f.f.xs set"}
    listbox $w.f.f.li -xscrollcommand "$xsc" -yscrollcommand "$ysc" -width $wi -height $he
    if {$sel!="selnoysb"} {pack configure $w.f.f.ys -fill y -side right}
    if {$sel=="selxsb"}   {pack configure $w.f.f.xs -fill x -side bottom}
    pack configure $w.f.f.li -side right -fill x -fill y -expand yes
    if {$list!=""} then {foreach e $list {$w.f.f.li insert end $e}}
    if {$hf!=""} {Bind3HTF $w.f.f.li "$hp" $hf $hw}
    bind $w.f.f.li <Leave> Bend
    bind $w.f.f.li <Double-Button-1> Bend
    bind $w.f.f.li <Triple-Button-1> Bend
    eval bind $w.f.f.li <Button-1> \
	\{set but2invoked 0\; set lastclick $w.f.f.li\; [set com] \[Selektion %W %y\]\; Bend\}
    if {($come!="")&&($button2end==2)} {
      eval bind $w.f.f.li <Button-2> \
	\{set but2invoked 1\; set lastclick $w.f.f.li\; [set com] \[Selektion %W %y\]\; Bend\}
      eval bind $w.f.f.li <ButtonRelease-2> \{after 500\; $come\; Bend\}
    }
    return "-[llength $list]"
  } else {
    set i 0
    foreach e $list {
      incr i; set txt [getvalue $e 0 $sep]
      radiobutton $w.f.f.$i -width $wi -anchor w -text "$txt" \
	-variable [set com]_v -value "$e" -command "set lastclick $w.f.f.$i; [set com] \{$e\}"
      if {($come!="")&&($button2end==2)} \
	      {bind $w.f.f.$i <Button-2> "$w.f.f.$i invoke; after 500; $come"}
      pack configure $w.f.f.$i -anchor nw -expand yes -fill x
      if {$hf!=""} {Bind3HTF $w.f.f.$i $hp $hf $hw}
    }
    return $i
  }
}


proc CreateRBBox {w text wt s wb bw hf hw var coms come list args} {# radio buttons box
# creates frame w.f and title for selection, fills with radiobuttons
# width wt/wb; help-text hf in hw
#
  global vv [set var] lastclick button2end
  if {$list==""} {set list "{1 $vv(yes)} {0 $vv(no)}"}
  if {($come!="")&&($button2end==2)} {set hp "$vv(btclk2):\n  $vv(btclk3)\n"} else {set hp ""}
  set hp "${hp}$vv(btclk1):\n"
  set ldist 4
  foreach a $args {set [lindex $a 0] [lindex $a 1]}
  frame $w.f; pack configure $w.f -anchor w -padx $ldist -fill x -expand yes
  if {$text!=""} {
    if {($wt!="")&&($s=="top")} {label $w.f.l -text $text -width $wt -anchor w} \
    elseif {($wt!="")&&($s=="left")} {label $w.f.l -text $text -width $wt -anchor e} \
    else {label $w.f.l -text $text}
    pack configure $w.f.l -side $s -anchor w
    if {$hf!=""} {Bind3HTF $w.f.l $hp $hf $hw}
  }
  frame $w.f.f -relief ridge -borderwidth $bw
  pack configure $w.f.f -anchor w -fill x -expand yes
  foreach e $list {
    set i [lindex $e 0]
    radiobutton $w.f.f.$i -width $wb -anchor w -text [lrange $e 1 end] \
	-variable [set var] -value "[lindex $e 0]" -command "set lastclick $w.f.f.$i; $coms"
    if {($come!="")&&($button2end==2)} \
	{bind $w.f.f.$i <Button-2> "$w.f.f.$i invoke; update; after 300; $come"}
    pack configure $w.f.f.$i -anchor nw -fill x -expand yes
    if {$hf!=""} {Bind3HTF $w.f.f.$i $hp $hf $hw}
  }
}


proc dirMainFile {} {# if main-filename is prefixed by directory: cd if possible
  global vv Wf Wq main_file efile esuff texsuffix dirprefix dir Wf
  set dirprefix ""; set ret 0; set lastslash [string last / $main_file]
  TestPut 4 "<$lastslash><$main_file>"
  if {$lastslash>=0} {# filename is prefixed by directory
    if {$lastslash==0} {
	set d $main_file; set f ""
    } else {
	set d [string range $main_file 0 [expr $lastslash-1]]
	set f [string range $main_file [expr $lastslash+1] end]
    }
    TestPut 4 "<$d><$f>"
    if {[file isdirectory $d]&&[file readable $d]&&[file writable $d]&&[file executable $d]} {
      cd $d; set dir [pwd]; set ret 1; if [winfo exists $Wf] {dirselected $dir $f}
      set main_file $f; set efile $f; set esuff $texsuffix
      if [winfo exists $Wf] {fsanzeige $Wf}
    } elseif {($d!="")&&![file exists $d]} {
      mkdcdfill "$d" "$f" main; set ret 1
    } else {
      set dirprefix $d
    }
  }
  return $ret
}


proc mkdcdfill {nd nf type} {# aks whether to create nd (and creates it on request)
 global Wf Wq vv mkdcdfill_nd mkdcdfill_nf mkdcdfill_type

 set mkdcdfill_nd "$nd"; set mkdcdfill_nf "$nf"; set mkdcdfill_type "$type"
 if [winfo exists $Wf.d.tt] {set wt $Wf} else {set wt ""}
 if [string match "* *" $nd] {writescr0 $w "$vv(ut45)!"; mybell 3; return}
 regsub -all "//+" "$nd" "/" nd;  set nd [string trimright $nd /]

 if {[winfo exists $Wq]} {destroy $Wq}; toplevel $Wq
 set frage1 "$vv(fs20) \"$nd\" $vv(ea4)   $vv(fs21)?"; set frage2 ""
 proc ReqCDirYes {} {
   global vv Wq Wf mkdcdfill_nd mkdcdfill_type mkdcdfill_nf efile
   destror $Wq
   set res [catch "mkdir -path $mkdcdfill_nd" mes]
   if {$mes!=""} {
     if [winfo exists $Wf.d.tt] {set w $Wf.d.tt} else {set w .d.tt}
     writescr $w "\n*** $vv(ut46):\n $mes\n "; mybell 3
   } elseif {$mkdcdfill_type=="main"} {
     dirselected $mkdcdfill_nd $mkdcdfill_nf
   } elseif {$mkdcdfill_type=="edit"} {
     set efile "[fsdirCheckClear $mkdcdfill_nd]$mkdcdfill_nf"
     if [winfo exists $Wf.c.e.i] {$Wf.c.e.i delete 0 end}
     if {$efile==""} {writescr0 $Wf.d.tt "$vv(fs19) = $vv(fs5)\n"} \
     else {writescr0 $Wf.d.tt "$vv(fs19) $efile\n"}
     fsfuellen edit
     fsanzeige $Wf
   }
 }
 proc ReqCDirNo {} {global Wq; destror $Wq}
 Request $Wq "$frage1" "$frage2" "$vv(yes)" ReqCDirYes "$vv(no)" ReqCDirNo ut_createdir $wt y
}


proc dirselected {d f} {# fills the directory selection box; sets files to f
  global vv env Wf dir main_file efile esuff texsuffix dirprefix

  if {$d=="\$HOME"} {set cdir $env(HOME)} else {set cdir $d}
  if [winfo exists $Wf] {set w $Wf.d.tt} else {set w .d.tt}
  if {[catch {cd $cdir} m]!=0} {
    mybell 2;  set dir [pwd];  writescr0 $w "$vv(tvt2)\n$vv(tvt3)\n$m\n"
    return 0
  } else {
    set dirprefix ""
    writescr0 $w "$vv(tvt4) [pwd]\n\n"
    set dir [pwd]
    if {$f==""} {set main_file ""} else {set main_file $f}
    set efile "$main_file"; set esuff $texsuffix
    knoepfe
    if {[winfo exists $Wf]} {
      fsanzeige $Wf
      setInUnlockListe ".c.1.ed .c.1.pr"
      if [winfo exists $Wf.c.d] {
      $Wf.c.d.f.f.li delete 0 end; $Wf.c.d.f.f.li insert end "\$HOME" ".."
	foreach k [lsort [glob -nocomplain -- *]] \
	  {if [file isdirectory $k] {$Wf.c.d.f.f.li insert end $k}}
      }
      fsfuellen main; fsfuellen edit
    }
    return 1
  }
}


proc which {command} {
  global env whichcheck
  TestPut 3 "whichcheck=$whichcheck:<$command><$env(PATH)>"
  if {$whichcheck=="yes"} {
    if {[file isfile $command]&&[file executable $command]} {return $command}
    foreach dir [split $env(PATH) :] {
      set path ${dir}/${command}
      if {[file isfile $path]&&[file executable $path]} {return $path}
    }
    return -code error \
	-errorinfo "$command not found in [split $env(PATH) :]" "$command not found"
  } else {
    return -code -1 \
	-errorinfo "which check not allowed at this xtem installation" "no which check"
  }
}


proc ButText {w ts tl t} {# normal buttons: $t; shortbuttons: $ts, $tl (if empty: $t --> $tl )
 global shortbutts shortbuttsFNT main_file efile texsuffix esuff
 if {$shortbutts} {
   if {$tl==""} {set tl "$t"}
   if {$main_file==""} {set tsuff ""} else {set tsuff $texsuffix}
   if {[fileName $efile]==""} {set esuffl ""} else {set esuffl $esuff}
   set tfn "$main_file$tsuff $efile$esuffl"
   bind $w <Enter> "ConfigText .buttontext {$tl}"
   bind $w <Leave> "ConfigText .buttontext {$shortbuttsFNT}"
   $w configure -text "[string trimright $ts ":"]"
 } else {
   $w configure -text "$t"
 }
}


proc StripDir {name} {return [file tail $name];# strip dir from name (name may end with "&"!)}


proc RetN0PString {n sN s0 sP} \
			{if {$n<0} {return $sN} elseif {$n==0} {return $s0} else {return $sP}}

proc FileExists {file} {if {"$file"==""} {return -1} {return [file exists $file]}}


proc knoepfe {} {
 global vv BK editor efile esuff texfmt main_file tsuff preview psuff printer asuff
 global logform logback lsuff prtdriver texsuffix prsuffix quickfile quickenable spcmd spsuff
 global syntax ssuff index isuffe bibtex edback prback b_letters shortbutts shortbuttsFNT
 global filNotExdsp letback lettext

 if {$main_file==""} {
   set tsuff "";  set psuff "";  set lsuffd "";  set asuff ""; set quicktext ""
 } else {
   set tsuff $texsuffix;  set psuff $prsuffix;  set lsuffd $lsuff;  set asuff .dvi
   set quicktext "$main_file -> $quickfile$tsuff"
 }
 if {[fileName $efile]==""} {set esuffl ""} else {set esuffl $esuff}
 set spsuff "$esuffl";  set ssuff  "$esuffl"
 set efn "[fileName $efile]";  set efp "[filePrefix $efile]"
 if {$efn==""} {set efilel ""} \
 elseif {($efp=="")||($efp=="/")||($efp=="[pwd]/")} {set efilel "$efn"} \
 else {set efilel "..../$efn"}
 if {$shortbutts} {
   set shortbuttsFNT "$main_file$tsuff"
   if {"$main_file$tsuff"!="$efile$esuffl"} \
		{set shortbuttsFNT "$shortbuttsFNT    $efile$esuffl"}
   if [winfo exists .buttontext] {.buttontext configure -text "$shortbuttsFNT"}
 }
 set FNED [lindex $filNotExdsp 0]; set FNEDS [lindex $filNotExdsp 1]
 if $FNED {set em [RetN0PString [FileExists $main_file$tsuff] "" $FNEDS ""]} {set em ""}
 if $FNED {set ee [RetN0PString [FileExists $efile$esuffl]    "" $FNEDS ""]} {set ee ""}

 ButText .c.1.fs "$vv(xtc1FS)" "" \
	"$BK(fs)$vv(xtc1fs)"
 ButText .c.1.ed "$vv(xtc1ed)" "" \
	"$BK(ed)$vv(xtc1ed) [StripDir $editor$edback] $efilel$esuffl $ee"
 ButText .c.1.qd "$vv(xtc1qd)" "" \
	"$BK(qd)$vv(xtc1qd) [StripDir $texfmt] $quicktext"
 ButText .c.1.la "$vv(xtc1la)" "" \
	"$BK(la)$vv(xtc1la) [StripDir $texfmt] $main_file$tsuff $em"
 ButText .c.1.pr "$vv(xtc1pf)" "" \
	"$BK(pr)$vv(xtc1pf) [StripDir $preview$prback] $main_file$psuff"
 ButText .c.1.as "$vv(xtc1as)" "" \
	"$BK(as)$vv(xtc1as) [StripDir $prtdriver] $main_file$asuff -> $printer"
 ButText .c.1.au "$vv(xtc1au)" "$BK(au)$vv(xtc1Au)" \
	"$BK(au)$vv(xtc1au)"
 ButText .c.2.re "$vv(xtc2re)" "" \
	"$BK(re)$vv(xtc2re) [StripDir $spcmd] $efilel$spsuff"
 ButText .c.2.sy "$vv(xtc2sy)" "" \
	"$BK(sy)$vv(xtc2sy) [StripDir $syntax] $efilel$ssuff"
 ButText .c.2.in "$vv(xtc2in)" "" \
	"$BK(in)$vv(xtc2in) [StripDir $index] $main_file"
 ButText .c.2.bi "$vv(xtc2bi)" "" \
	"$BK(bi)$vv(xtc2bi) [StripDir $bibtex] $main_file"
 ButText .c.2.so "[lindex $vv(xtc2so) 0]" \
	"$BK(so)$vv(xtc2so)" "$BK(so)$vv(xtc2so)"
 ButText .c.2.fl "$vv(xtc1fl)" "" \
	"$BK(fl)$vv(xtc1fl) [StripDir $logform$logback] $main_file$lsuffd"
 if {$letback==1} {set letBack "&"} {set letBack ""}
 set letText [alternative $lettext "" ":  $lettext"]
 ButText .c.2.le "[string trim [string range $b_letters 1 end]]$letBack"  "" \
	"$BK(le)[string trim [string range $b_letters 1 end]]$letBack$letText"
}



proc filePrefix {file} {# returns prefix (=directory) of file
  set p [string last "/" $file]
  if {$p<0} {return ""} else {return "[string range $file 0 $p]"}
}

proc fileName {file} {# returns filename (without directory-prefix) of file
  set p [string last "/" $file]
  if {$p<0} {return "$file"} else {return "[string range $file [expr $p+1] end]"}
}
proc stripdir {file} {return [fileName $file]};#obsolete-->fileName

proc Selektion {W y} {# selection for list boxes (y=B1 (y coordinate) within widget W)
  set i [$W nearest $y]
  $W selection clear 0 end;  $W selection set $i
  return [$W get $i]
}


proc Bend {} {return -code break; # procedure to break resp. nullify bindings}


proc MkcmdTclVCol {notfound args} {# returns column number in mkcommand.vst applying to Tcl version
	# tclversion/tclVersion must start with 3rd word in a column in 1st line of file
 global vv tclversion tclVersion vst_dir MkcmdTclVColNr stt

 if [info exists MkcmdTclVColNr] {return $MkcmdTclVColNr}; # second call

 # first call: set MkcmdTclVColNr
 set f [open_vst mkcommand.vst $args]; getscl $f e; close $f
 set s [string index [string trim $e] 0]
 for {set n 1} {[string trim [getvalue $e $n $s]]!=""} {incr n} {set lastCol $n}
 for {set n 1} {$n<=$lastCol} {incr n} {
   if {"[string trim [getvalue $e $n $s]]"=="Tcl_$tclversion"} \
							{set MkcmdTclVColNr $n; return $n}
   if {"[lindex [getvalue $e $n $s] 0]"=="$tclversion"} {set MkcmdTclVColNr $n; return $n}
   if {"[lindex [getvalue $e $n $s] 1]"=="$tclversion"} {set MkcmdTclVColNr $n; return $n}
   if {"[lindex [getvalue $e $n $s] 2]"=="$tclversion"} {set MkcmdTclVColNr $n; return $n}
   if {[regexp "^Tcl.*${tclversion}$" [getvalue $e $n $s]]} {set MkcmdTclVColNr $n; return $n}
 }
 for {set n 1} {$n<=$lastCol} {incr n} {
   if {[string first $tclversion [getvalue $e $n $s]]>=0} {set MkcmdTclVColNr $n; return $n}
 }
 if {"$notfound"=="exit"} {
   set tl1 "\n$vv(errf) $vst_dir/mkcommand.vst\n"
   set tl2 "    ($vv(ut53) $tclversion)\n    $vv(adm)\n"
   set tl3 "    ($vv(ut54) [getvalue $e $lastCol $s] $vv(ut55)!)\n"
   puts stdout "$tl1$tl2"; set stt "${stt}$tl1$tl2"
   mybell 4
   # don't exit, better to use last column, if existing!
   if {$lastCol>=1} {
     puts stdout "$tl3"; set stt "${stt}$tl3"
     set MkcmdTclVColNr $lastCol; return $lastCol
   } else {
     exit
   }
 } else {
   return 0
 }
}


proc ClickAbbruch {} {# Klick auf Abbruch-Knopf .a.2.a
  global vv sub xtAbbruch p_mkCmd lp_mkCmd wait_mkCmd
  TestPut 4 "<$sub><$xtAbbruch><$p_mkCmd>"
  if {$xtAbbruch==2} {# Abbruch von Prozeduren wie z.B tla (TeX Logfile Analyse)
    set xtAbbruch 1
  } else {
    if {$sub==1} {
      set lp_mkCmd $p_mkCmd; mybell 2
      if {$lp_mkCmd>1} \
	{writescr .d.tt "\n\n[datime] $vv(xt4) $lp_mkCmd $vv(xt5)\n";killprocess $p_mkCmd} \
      elseif {$lp_mkCmd==1} {writescr .d.tt "\n\n[datime] $vv(xt6)\n"} \
      else {destror $Wq; set wait_mkCmd 1}
      unlock_list
    } else {
      writescr .d.tt "\n\n[datime] $vv(xt7)\n\n$vv(xt8)\n";  mybell 2
    }
  }
}

proc MakeAbbruchButton {} {# cancel/Abbruch-button: .a.2.a
  global vv
  button .a.2.a -text "$vv(xta2a)" -command ClickAbbruch; # Klick auf Abbruch-Knopf .a.2.a
  Bind3HF .a.2.a xt_abbruch .d.tt
  pack configure .a.2.a -side left -padx 3 -pady 3
  .a.2.a configure -state disabled; update idletasks
}

proc MkcmdSource {} {# reads mkcommand.*
  global  vv Wq mkcommand xtem_path tclversion
  MkcmdTclVCol exit
  set mkctyp [string range $mkcommand 0 10]
  if [file exists "mkcommand_tst"] {set mkcommand "mkcommand_tst"} \
  else {
    if     [file exists $xtem_path/${mkctyp}_tcl$tclversion] \
		{set mkcommand     ${mkctyp}_tcl$tclversion} \
    elseif [file exists $xtem_path/$mkctyp] \
		{set mkcommand     $mkctyp} \
    else        {set mkcommand mkcommand.9}
  }
  source $xtem_path/$mkcommand
  if {[regexp {^mkcommand\.[0,5]} $mkctyp]} {
    if  [winfo exists .a.2.a] {destroy .a.2.a; update idletasks}
    if  [winfo exists .a.2.x] {.a.2.x invoke; destroy .a.2.x; update idletasks}
  } elseif {$mkctyp=="mkcommand.4"} {
    if ![winfo exists .a.2.a] MakeAbbruchButton
    if ![winfo exists .a.2.x] mkCmd_cw
    XhostTest .d.tt "\n**** "
  } else {
    if ![winfo exists .a.2.a] MakeAbbruchButton
    if  [winfo exists .a.2.x] {.a.2.x invoke; destroy .a.2.x; update idletasks}
  }
}


proc XhostTest {f str} {# procedure to test, whether send command is supposed to work here
  global vv
  TestPut 4 ""
  SigChldB; set xherg [catch "exec xhost" xhostres]; SigChldU
  if "$xherg" {
    if {$f!=""} {writescr $f "\n$str$vv(ut47)!\n\n"; mybell 3};  
    return -1
  } else {
    if {[string first \n $xhostres]>0} {set nl 9999} else {set nl 1}
    set beg [lrange $xhostres 0 7]
    if {([string first enabled $beg]>0)&&($nl>1)} \
	    {writescr $f "\n$str$vv(ut48)\n$vv(ut49)\n$vv(ut50)!\n\n"; mybell 3}
  }
}


proc AnzCharIn {c string} {
 set n 0
 if {$c=="z"} {set s "${string}x"} else {set s "${string}z"}
 while {[string first $c $s]>=0} \
	{incr n; set s [string range $s [expr [string first $c $s]+1] end]}
 return $n
}


proc CheckNumInt {num} {# checks, if num is integer number: return 0 if not; else ...
  set n "x$num"
  if {($n=="x0") ||[regexp {^x[1-9]+[0-9]*$} $n]}     {return  1};# >=0 without sign
  if {($n=="x+0")||[regexp {^x[+]+[1-9]+[0-9]*$} $n]} {return  2};# >=0 with sign
  if {[regexp {^x[-]+[1-9]+[0-9]*$} $n]}              {return -1};# <0
  if {($n=="x-0")}                                    {return -2};# -0 (0 with sign!)
  return 0
}


proc CheckNumReal {num} {# checks, if num is real number: return 0 if not; else ...
 set n $num
 if {([string first + $n]==0)&&([string length $n]>1)} \
	{set s +; set n [string range $n 1 end]} \
 elseif {([string first - $n]==0)&&([string length $n]>1)} \
	{set s -; set n [string range $n 1 end]} \
 elseif {([string length $n]>0)} {set s ""} \
 else {return 0}
 if {(![regexp {^[0-9.]+$} $n])||([AnzCharIn "." $n]>1)} {return 0}
 catch "if {($n==.)} {return 0}"
 # now we know: $num is number, n contains only digits an at most 1 point, $s contains sign
 return ${s}1
}


proc TestPut {level text args} {
  global bell_level testPut
  set s "$text"; if {$args!=""} {set s "${s}<$args>"}
  if {($testPut>0)&&($level>=$bell_level)} \
	{puts stdout "*** [lindex [info level [expr [info level]-1]] 0]: \t<$s>";flush stdout}
}

proc getBefore {str pos} {# returns all characters from string before position or empty string
  if {$pos<=0} {return ""} else {return [string range $str 0 [expr $pos-1]]}
}


proc getAfter {str pos} {# returns all characters from string after position or empty string
  if {$pos>=[string length $str]} {return ""} {return [string range $str [expr $pos+1] end]}
}


proc getPreamble {file} {# set preamble (up to quickendpre) of file and returns 1 if found
  global preamble preamble_found quickpreamble quickendpre quickprereq
  set f [open $file r]; set app ""; set preamble ""; set preamble_found 0
  if {[gets $f zeile]==-1}	{set search 0} \
  else				{set search 1; set app $zeile}
  while {$search} {
    if {[string first "$quickendpre" "$zeile"]>=0} {# quickendpre in this line; comment only?
      set app ""; set rest $zeile
      while {$rest!=""} {
	set p [string first "$quickendpre" "$rest"]
	if {$p>0} {set s1 [string range $rest 0 [expr $p-1]]} else {set s1 ""}
	set s2 [string range $rest $p end]
        if {(![CommentIncl "$s1"])||([string index "$quickendpre" 0]=="%")} {
	  # no comment in line before quickendpre or `ignore comment'
	  set app "$s1"; set rest ""; set search 0; set preamble_found 1
        } else {
	  set app "$s1"
        }
      }
      if {$search} then {if {[gets $f zeile]==-1} then {set search 0}}
    } else {# no quickendpre in this line
      if {[gets $f zeile]==-1} {set search 0}
    }
    set preamble "${preamble}$app\n"; set app  $zeile
  }
  close $f
  if {!$preamble_found} {if {!$quickprereq} {set preamble ""} {set preamble "$quickpreamble"}}
}


proc TopAndTail {String nl} {# returns string: extracted nl lines at start and end of String
  set spl [split "$String" "\n"]
  set ll [llength $spl]
  while {[lindex $spl [expr $ll-1]]==""} {incr ll -1}
  if {$ll>2*$nl} {
    set ll1 [expr $ll-$nl]; set ll2 [expr $ll-1]
    set short "[join "[lrange $spl 0 [expr $nl-1]] ... [lrange $spl $ll1 $ll2]" \n]"
  } else {
    set short "$String"
  }
  return "$short"
}


proc CommentIncl {string} {# returns 1 if comment starts elsewhere in string, 0 otherwise
  set rest "$string"; set commInc 0
  while {$rest!=""} {
    set fbpr [string first {\%} "$rest"]; set fpro [string first {%} "$rest"]
    if {($fbpr>=0)&&($fbpr<$fpro)} {set rest [getAfter "$rest" [expr $fbpr+1]]; # \% first} \
    elseif {$fpro>0} {set rest ""; set commInc 1; # \% first}
  }
  return $commInc
}


proc QuickFilDel {select} {global quickfile
 set liste [glob -nocomplain -- $quickfile.*]
 if {$select!="--all"} \
   {set i [lsearch $liste $select]; if {$i>=0} {set liste [lreplace $liste $i $i]}}
 foreach file $liste {unlink -nocomplain $file}
}


proc CheckSIGCHLDUnblocked {} {# checks whether SIGCHLD is unblocked; unblocks if nexecessary
  if {[lindex [lindex [lindex [signal get SIGCHLD] 0] 1] 1]!=0} {signal unblock SIGCHLD}
}


proc CheckSIGCHLDBlocked {} {# checks whether SIGCHLD is blocked; blocks if necessary
  if {[lindex [lindex [lindex [signal get SIGCHLD] 0] 1] 1]==0} {signal block SIGCHLD}
}


proc CheckSIGCHLDInsecure {w} {# is SIGCHLD insecure? (Tcl7.5 & mkcommand: .1,.2,.3)
  global vv tclversion mkcommand

  if {$tclversion>=7.5} {# SIGCHLD is insecure 
			 # (does'nt come in any case after program termination)!
    writescr $w "\n$vv(xtq01)\n$vv(xtq28): $mkcommand\n" \
		"$vv(xtq29) $tclversion\n**\n$vv(xtq30)\n$vv(xtq31)\n**\n$vv(xtq32)\n" 
    mybell 2
  }
}


proc quickprevstdCheck {} {#if quickprevstd doesn't exist, quickprev is set to current_preview
 global Wqv quickprevstd quickprev
 if {("$quickprevstd"=="")||([catch "which [lindex $quickprevstd 0]" m]!=0)} \
  {set quickprev current_preview;if [winfo exist $Wqv.c.wpv] {$Wqv.a.e invoke;CallSetMenu qv}}
}


proc mvChkBackWidg {} {global Wm letbackalw; # check for widget $Wm.c.ira visibility
 if ![winfo exists $Wm] {return}
 TestPut 3 "<$letbackalw><[winfo exists $Wm.c.ira]>"
 if   {$letbackalw==0}	{pack forget $Wm.c.ira} {pack configure $Wm.c.ira -side left}
}


proc RegsubHOMEetc {string} {global XTEMPATH HOME; # substitute in string: $XTEMPATH, $HOME, ~
 set string [eval concat "$string"]; regsub -all {\~} "$string" $HOME string; return "$string"
}


proc prtRegsub {subString mainfile opt1 opt2 startpage endpage} {
 global prt_file
 regsub -all {\$mainfile} "$subString" $mainfile subString
 regsub -all {\$opt1} "$subString" "$opt1" subString
 regsub -all {\$opt2} "$subString" "$opt2" subString
 regsub -all {\$prt_file} "$subString" $prt_file subString
 regsub -all {\$startpage} "$subString" $startpage subString
 regsub -all {\$endpage} "$subString" $endpage subString
 return $subString
}


proc IncrNumL {var inc min max retifblank} {# increments variable var by inc within limits
 set var [Num $var]
 if {$var==""} {return $retifblank}
 set v [expr $var+$inc]; if {$v<$min} {set v $min}; if {$v>$max} {set v $max}; return $v
}


proc DelFileIfEmpty {f} {if {[file exists $f]&&[file size $f]==0} {unlink -nocomplain $f}}


proc BoxWaitOK {t text lockbut} {# display text, waits for "OK-click", locks/unlocks buttons
 global vv geom RequestActive
 TestPut 3 "<$t><$lockbut><$text>"
 if {$lockbut!=""} {foreach l $lockbut {$l configure -state disabled}}
 if [winfo exists $t] {destror $t}; toplevel $t
 wm title $t "$vv(utvor)";  wm minsize $t 400 200
 if [info exists geom(ut_rp)] {wm geometry $t $geom(ut_rp)}
 text $t.text; pack configure $t.text -padx 10 -pady 10
 $t.text insert insert "$text"
 set RequestActive 1
 button $t.goon -text "$vv(goon)" -command "set RequestActive 0; destror $t"
 bind $t.goon <Return> "$t.goon invoke; Bend"
 focus $t.goon
 pack configure $t.goon -padx 10
 tkwait variable RequestActive
 if {$lockbut!=""} {foreach l $lockbut {$l configure -state normal}}
}


proc FehltNoch {text} {mybell 4; puts stdout "\n\n\n\n@@@@@@@@@@\n$text\n@@@@@@@@@@\n\n\n\n"}


proc Dummy {} {# dummy (empty) procedure,needed e.g. if middle-mouse-button=left-mouse-button}


proc WaitUntilExistsWin {w args} {# waits (bell and puts stdout!!!) unitil window w exists!
 while ![winfo exists $w] {mybell 4; puts "***** window $w doesn't exist ($args)";after 200 }
}


proc fontencTeX {} {# returns font-encoding type (if found in .tex-file) or empty string
 global main_file tsuff
 SigChldB; set res [catch "exec grep \"\\usepackage\" $main_file$tsuff" erg]; SigChldU; lock
 if {$res==1} {return ""}
 set ergl [split "$erg" "\n"]
 set type ""
 foreach l "$ergl" {
   set l [lindex [split $l "%"] 0]
   if {[regexp {.*\\usepackage.*\[.*T1.*\].*\{.*fontenc.*\}} $l]} {set type T1}
   if {[regexp {.*\\usepackage.*\[.*OT1.*\].*\{.*fontenc.*\}} $l]} {set type OT1}
   TestPut 4 "<$l><$type>"
 }
 return $type
}


proc fontencOpt {} {# returns font-encoding type (if not found in option string: default)
 global hyphenopts
 set type "T1"
 for {set i 0} {$i<[llength $hyphenopts]} {incr i} \
	{if {[lindex $hyphenopts $i]=="-c"} {set type [lindex $hyphenopts [expr $i+1]]}}
 return $type
}


proc hyphIns {w} {# add .hyp to .hck, then delete file .hyp; disable add-button
 global vv mainfile hyphenchke HyphListe HyphDeleted
 TestPut 3 "<$HyphDeleted><$HyphListe>"
 if {$HyphDeleted>0} {
   set trimlist {,.;:!?='`+()/"-_\#*&%^$ }
   set FID [open $hyphenchke a+]
   foreach hyph $HyphListe {
     TestPut 3 "?<$hyph>"
     if {[string length $hyph]>0} {
	TestPut 3 "i<$hyph>"
	set hyph [string trimright $hyph $trimlist]
	set len [string length $hyph]
	set hyph [string trimleft $hyph $trimlist]
	while {[string length $hyph]<$len} {set hyph " $hyph"}
	puts $FID $hyph
     }
   }
   close $FID
 } else {
   SigChldB; exec cat $mainfile.hyp >>$hyphenchke; SigChldU
 }
 unlink -nocomplain $mainfile.hyp
 $w.ins configure -state disabled -text " $vv(teh13) "
 if [winfo exists $w.sort] {$w.sort configure -state normal -text " $vv(teh14) "}
}


proc hyphSort {w} {# sort .hck
 global vv xtem_path hyphenchke
 SigChldB; set res [catch "exec $xtem_path/hyphen_show.sort $hyphenchke" erg]; SigChldU
 $w.sort configure -state disabled -text " $vv(teh15) "
 if {$erg!=0} {$w insert insert "$erg"}
}


proc hyphGetStartPos {} {global HyphStartPos; set HyphStartPos [.d.tt index insert]}

proc hyphGetEndPos {} { global HyphEndPos; set HyphEndPos [.d.tt index insert]}

proc hyphDel {ln tagNr zeile} {
 global HyphListe HyphDeleted
 TestPut 4 "<$ln><$tagNr><$zeile>"
 .d.tt tag delete hyph$tagNr
 .d.tt delete $ln.0 "$ln.0 lineend"
 TestPut 3 "<$tagNr><$HyphListe>  <$zeile>"
 set HyphListe [lreplace $HyphListe $tagNr $tagNr ""]
 incr HyphDeleted
 if {[llength $HyphListe]==$HyphDeleted} {.d.tt.ins configure -state disabled}
 TestPut 3 "<$tagNr><$HyphListe>"
}

proc hyphMakeTags {} {
 global HyphStartPos HyphEndPos HyphListe HyphDeleted
 TestPut 3 "<[.d.tt tag names]>"
 foreach tn [.d.tt tag names] {if {[string first hyph $tn]==0} {.d.tt tag delete $tn}};#rm old
 set LNS [lindex [split $HyphStartPos "."] 0]; incr LNS 7
 if {[string trim [.d.tt get $LNS.0 "$LNS.0  lineend"]]==""} {incr LNS 1}
 set LNE [lindex [split $HyphEndPos "."] 0]; incr LNE -4
 if {[string trim [.d.tt get $LNE.0 "$LNE.0  lineend"]]==""} {incr LNE -1}
 TestPut 4 "<$HyphStartPos><$HyphEndPos>  <$LNS><$LNE> <[.d.tt get $LNS.0 "$LNS.0  lineend"]>"
 set HyphListe ""; set ln $LNS; set tn 0; set HyphDeleted 0
 TestPut 4 "<[.d.tt get $LNS.0 "$LNS.0  lineend"]>"
 while {$ln<=$LNE} {
   set zeile [.d.tt get $ln.0 "$ln.0  lineend"]
   if {"[string range [string trim $zeile] 0 0]"!="\["} {
     lappend HyphListe $zeile
     .d.tt tag add hyph$tn $ln.0 "$ln.0  lineend"
     .d.tt tag bind hyph$tn <Button-1> "hyphDel $ln $tn \"$zeile\""
     incr tn
   }
   incr ln
 }
 TestPut 4 "<$HyphListe>"
 TestPut 3 "<[.d.tt tag names]>"
}

proc hyphInitDisplay {f mainfile feType prType} {# displays hyphenations etc.
 global vv main_file tsuff hyphenchke xtem_path HyphDeleted
 TestPut 4 "<[file exists $main_file$tsuff]><[file exists $mainfile.hyp]>"
 hyphMakeTags; set HyphDeleted 0
 if {[file exists $main_file$tsuff]&& \
     [file exists $mainfile.hyp]&&([file size $mainfile.hyp]>0)} {#check type compatibil.
 TestPut 4 "<<$feType>> <<$prType>>"
 if {($feType!="")&&($feType!=$prType)} \
	{mybell 3; writescr $f "\n$vv(teh4) ($feType)\n$vv(teh5) ($prType)\n$vv(teh6)\n"}
 if {($feType=="")} \
	{mybell 1; writescr $f "\n$vv(teh7)\n$vv(teh8) `$prType',\n$vv(teh9)\n"}
 }
 set tlaOutLstAct 1
 TestPut 4 "<$hyphenchke><[file exists $mainfile.hyp]>"
 if {($hyphenchke!="")&&[file exists $mainfile.hyp]&&([file size $mainfile.hyp]>0)} {
   TestPut 4 "<[file size $mainfile.hyp]>"
   writescr $f "$vv(teh10)\n$vv(teh11)\n$vv(teh16)\n`$hyphenchke' $vv(teh17)\n"
   button $f.ins -text " $vv(teh12) " -command "hyphIns $f"
   $f window create insert -window $f.ins -padx 5
   Bind3HF $f.ins te_hyph .d.tt
   if {[file exists $xtem_path/hyphen_show.sort]&& \
       [file executable $xtem_path/hyphen_show.sort]} {
     button $f.sort -text " $vv(teh14) " -command "hyphSort $f"
     $f window create insert -window $f.sort -padx 5
     Bind3HF $f.sort te_hyph .d.tt
     if {(![file exists $hyphenchke])||([file size $hyphenchke]==0)} \
	{$f.sort configure -state disabled; update}
   }
 }
 DelFileIfEmpty $hyphenchke; DelFileIfEmpty $mainfile.hyp
 mybell 1
}

proc NumYesNo {n} {global vv; if {$n==1} {return "$n ($vv(yes))"} {return "$n ($vv(no))"}}

proc BindInvoke {bindTo event button} {global bindAltMeta
 if {$bindAltMeta==1} {
   if {[string first "Alt-" $event]==0} {set event "$event Meta-[string range $event 4 end]"}
   if {[string first "Meta-" $event]==0} {set event "$event Alt-[string range $event 5 end]"}
 }
 foreach ev $event {
   bind $bindTo <$ev> "$button invoke"
   TestPut 3	"bind $bindTo <$ev> \{$button invoke\}"
 }
}

proc subStringFirst {string match sub} {#substitutes first $match in $string by $sub
 set p1 [expr [string first $match $string]-1]; # endpos of pre
 set p2 [expr $p1+1+[string length $match]];# startpos of post
 if {$p1>=-1} {set string "[string range $string  0 $p1]$sub[string range $string $p2 end]"}
 return $string
}

proc subStringAll {string match sub} {#substitutes all $match in $string by $sub
 while {[string first $match $string]>=0} {set string [subStringFirst $string $match $sub]}
 return $string
}

proc getAnzThisCharInString {char string} {# returns number of appearance of this char in string
 set N 0
 while {[string first $char $string]>=0} \
     {incr N; set string [string range $string [expr [string first $char $string]+1] end]}
 return $N
}

proc TouchEFStamp {} {# sets time stamp EFStamp (according to: date, edit file, main file)
 global efile esuff main_file tsuff EFStamp
 set EFStamp [clock seconds]
 set EFT [file mtime $efile$esuff];	if {$EFT>$EFStamp} {set EFStamp $EFT}
 set MFT [file mtime $main_file$tsuff];	if {$MFT>$EFStamp} {set EFStamp $MFT}
}

##############################################################################################
