# letters menu 
#
# Copyright (C) 2004  G. Lamprecht, W. Lotz, R. Weibezahn; IWD, Bremen University


proc leExecPre {block} {# runs execpre commands
 global vv Wq Wle leBCont leBComPre leBDspC leIdTexts email
 TestPut 3 "<$block><$leBComPre($block)><$leBCont($block)>"
 set ind0 [lindex $leBComPre($block) 0]
 set errtxt "\n*** $vv(aerr): `$ind0'\n$vv(leerr1)\n$vv(leerr3) $email\n"
 if		{[string first "remove-comment-framework" $ind0]==0} {
   set ret $leBCont($block)
   foreach i "1 2 3 4 5 6 7 8 9 " {regsub -all "$leIdTexts(grepL)${i}_<" "$ret" "" ret}
   regsub -all ">$leIdTexts(grepR)"  "$ret" "" ret
   regsub -all "\n" "$ret" "$leBDspC(-NewLine)" ret
 } elseif	{$ind0=="remove-2backslashes-at-end-of-line"} {
   set zl [split "$leBCont($block)" "\n"]
   TestPut 1 "$zl"
   set ret ""
   foreach z $zl {
     set zt [string trim $z]; set p [string last {\\} $zt]; set l [string length $zt]
     if {$p==$l-2} {set z [string range $zt 0 [expr $l-3]]}
     if {"x$ret"=="x"} {set ret "$z"} else {set ret "$ret\n$z"}
   }
 } elseif	{$ind0=="remove-newcommand-and-braces"} {
   set ret [string trim $leBCont($block)]; set lg [string length $ret]
   set lc1 [string length [lindex $leBComPre($block) 1]]
   set lc2 [string length [lindex $leBComPre($block) 2]]
   TestPut 4 "<$lg><$lc1><$lc2><$ret>"
   set ret [string range $ret [expr $lc1+$lc2+5] [expr $lg-2]]
 } elseif	{$ind0=="remove-command-and-braces"} {
   set ret [string trim $leBCont($block)]; set lg [string length $ret]
   set lc [string length [lindex $leBComPre($block) 1]]
   TestPut 4 "<$lg><$lc><$ret>"
   set ret [string range $ret [expr $lc+2] [expr $lg-2]]
 } elseif	{$ind0=="comment-if-empty-command"} {
   if {[string first "%" [string trim $leBCont($block)]]==0} {
     set ret ""
   } else {
     set ret [string trim $leBCont($block)]; set lg [string length $ret]
     set lc [string length [lindex $leBComPre($block) 1]]
     TestPut 4 "<$lg><$lc><$ret>"
     set ret [string range $ret [expr $lc+2] [expr $lg-2]]
   }
 } else {mybell 4; BoxWaitOK $Wq "$errtxt" $Wle.a.e; set ret "$leBCont($block)"}
 TestPut 3 "$ret"
 update
 return "$ret"
}

proc leGetListLineCont {block} {
 global Wle leBDspC leBCont leDLen
 set txt [string trim [string range $leBCont($block) 0 $leDLen]]
 if {"x[string trim [string range $leBCont($block) [expr $leDLen+1] 400]]"!="x"} \
	{set txt "$txt..."}
 regsub -all "\n" "$txt" "$leBDspC(-NewLine)" txt
 update
 return " $leBDspC($block)  $block   $txt"
}

proc leUpdListWidget {selected} {# update selected block (or all) in $Wle.c.s.f.f.li
 global Wle leBVarList leBDspC
 TestPut 3 "<$selected>\n<$leBVarList>"
 if {$selected==""} {
   foreach block $leBVarList {$Wle.c.s.f.f.li insert end "[leGetListLineCont $block]"}
 } else {
   set line [lsearch $leBVarList $selected]
   $Wle.c.s.f.f.li delete $line; $Wle.c.s.f.f.li insert $line "[leGetListLineCont $selected]"
 }
 $Wle.a.e configure -state normal
 update
}

proc leSetBDspC {block} {# updates block display character according to leBDspC
 global Wle leBDspC leBVarList leBCont leDLen
 set i [lsearch $leBVarList $block]
 set txt [string trim [string range $leBCont($block) 0 $leDLen]]
 if {"x[string trim [string range $leBCont($block) [expr $leDLen+1] 400]]"!="x"} \
	{set txt "$txt..."}
 regsub -all "\n" "$txt" "$leBDspC(-NewLine)" txt
 TestPut 2 "<$block><$i><$leBDspC($block)><txt>"
 $Wle.c.s.f.f.li delete $i; $Wle.c.s.f.f.li insert $i  " $leBDspC($block)  $block   $txt"
 update
}

proc leBExecSetCont {} {# do execset (after end block edit)
 global vv Wq Wle leBSel leBCont leBSetCont leBVar leBDspC leSelTypeVst lesep
 global HOME XTEMPATH leComDir leGroupDir leFileName
 TestPut 3 "<$leBSel><$leBCont($leBSel)><$leBSetCont($leBSel)>"
 set progcall [lindex $leBSetCont($leBSel) 0]
 set res [catch "exec $progcall $leBCont($leBSel)" mes]
 set errtxt "$vv(acall): $progcall $leBCont($leBSel)\n\n$vv(aerr):\n$mes"
 if {$res!=0} {mybell 3; BoxWaitOK $Wq "$errtxt" ""}
 TestPut 2 "<$res><$mes>"
 if {$res==0} {set values $mes} else {set values ""}
 set bl [lrange $leBSetCont($leBSel) 1 end]
 foreach b $bl {
   TestPut 3 "<$b>[lsearch $bl $b]<[lindex $values [lsearch $bl $b]]>"
   set errt "$vv(errf) letter.vst,\n [getvalue $leSelTypeVst 0 $lesep] : $leBSel : execset\n"
   set errt1 "${errt} $b $vv(leerr4);\n $vv(tsrt2)"
   set errt2 "${errt} $b $vv(leerr5);\n $vv(tsrt2)"
   TestPut 3 "<[info exists leBCont($b)]><[lindex $leBVar($leBSel) 0]>"
   if ![info exists leBCont($b)]		{mybell 3; BoxWaitOK $Wq "$errt1" $Wle.a.e} \
   elseif {[lindex $leBVar($b) 0]=="extern"} 	{mybell 3; BoxWaitOK $Wq "$errt2" $Wle.a.e} \
   else {set leBCont($b) [lindex $values [lsearch $bl $b]]}
   set leBDspC($b) "$leBDspC(-AutoChg)"; leSetBDspC "$b"
 }
 update
}

proc leEndBlockEditNext {save} {TestPut 4 "$save"; leEndBlockEdit $save; leEditBlockSelected}

proc leEndBlockEdit {save} {
 global Wle Wleed leBSel leBCont leModified leBType leBVarList leBSetCont leBDspC leBNonEmpt
 global leSelBufN
 TestPut 4 "<$save><$leBSel> <$leBCont($leBSel)> <$leBSetCont($leBSel)>"
 incr leModified $save
 if {$save==1} {
   if {$leBType=="entry"} {
     set txt [$Wleed.d.tt get]
   } elseif {$leBType=="text"} {
     set l [$Wleed.d.tt get "end -1c" end]
     if {$l=="\n"} {set txt [$Wleed.d.tt get 1.0 end-1c]} {set txt [$Wleed.d.tt get 1.0 end]}
   } elseif {$leBType=="radiobuttons"} {
     set txt "$leBCont($leBSel)"
   }
   TestPut 2 "$txt"
   set leBCont($leBSel) "$txt"
   leUpdListWidget $leBSel
   if {$leBSetCont($leBSel)!=""} {leBExecSetCont}
 }
 leLUTeXPv $leModified; leLUPrint 1
 if [winfo exists $Wleed] {destros $Wleed}
 set bnum [lsearch $leBVarList $leBSel]; set b $leBSel
 $Wle.c.s.f.f.li selection clear $bnum
 if {($leBNonEmpt($b)==1)&&("x[string trim $leBCont($b)]"=="x")} \
     then {set i -Missing} else {set i -NoExcpt}
 set leBDspC($leBSel) "$leBDspC($i)"
 leSetBDspC $leBSel
 leSelIncB $Wle.c.s.f.f.li 1
 TestPut 3 "<$leSelBufN><$leBSel> <$leBCont($leBSel)>"
 TestPut 3 "111"
 update
 TestPut 3 "222"
 focus $Wle
 TestPut 3 "333"
}

proc leEditBlockSelected {} {
 global Wleed vv textxscroll leBindKeyMod
 global leBSel leBVar leBType leBCont leBSetCont leBAlt leEditCFN leBEdited leBText
 TestPut 4 "########<$leBSel><$leBVar($leBSel)>\n\t\t\t<$leBCont($leBSel)>"
 leSelLevel 3
 set editTyp [lindex $leBVar($leBSel) 0]
 lappend leBEdited $leBSel
 if {$editTyp=="extern"} {					    # editor according $editor
   set leBType extern
   set tmpfile $leEditCFN; # don't use another file name here!
   FileDelete $tmpfile
   set ID [open $tmpfile w]; puts -nonewline $ID "$leBCont($leBSel)"; close $ID
   editor letter-edit $tmpfile
   set ID [open $tmpfile r]; set leBCont($leBSel) [read $ID]; close $ID
   FileDelete $tmpfile
   leEndBlockEdit 0
 } elseif {$editTyp=="radiobuttons"} {				    # alternatives
   set leBType radiobuttons
   TestPut 2 "$leBAlt($leBSel)"
   set width [lindex $leBVar($leBSel) 1]
   toplevel_init $Wleed "$vv(ain): $leBSel" 550 400
   # top buttons
   frame $Wleed.a; pack configure $Wleed.a -pady 3 -anchor nw
   TestPut 2 "$leBSetCont($leBSel)"
   button $Wleed.a.e -text "~s $vv(le4are)" -command "leEndBlockEdit 1"
   Bind2P $Wleed.a.e 1 leEndBlockEditNext 1
   button $Wleed.a.q -text "~q $vv(le4arq)" -command "leEndBlockEdit 0"
   Bind2P $Wleed.a.q 1 leEndBlockEditNext 0
   BindInvoke $Wleed $leBindKeyMod-q $Wleed.a.q
   label $Wleed.a.t -text "$vv(le4art)"
   pack configure $Wleed.a.e $Wleed.a.q $Wleed.a.t -side left -padx 3 -pady 3 -anchor w
   frame $Wleed.b;  pack configure $Wleed.b -anchor nw
   label $Wleed.b.t -text "$vv(le4bt): [lrange $leBSetCont($leBSel) 1 end]"
   frame $Wleed.b.d -height 20
   pack configure $Wleed.b.t $Wleed.b.d  -padx 3 -anchor nw
   # radiobutton area
   label $Wleed.ht -text "$leBText($leBSel):"; pack configure $Wleed.ht -pady 3 -anchor nw
   frame $Wleed.d -relief raised -borderwidth 2
   pack configure $Wleed.d -anchor nw -fill both -expand true -side top
   set i 0; set foundi ""
   foreach b $leBAlt($leBSel) {
     TestPut 4 "<$b><$leBCont($leBSel)>"
     radiobutton $Wleed.d.$i -width $width -anchor w -text "$b" -variable leBCont($leBSel) \
	-value "$b" -command {if [winfo exists $Wleed.l] {destroy $Wleed.l}}
     bind $Wleed.d.$i <Button-2> "$Wleed.d.$i invoke; after 300; $Wleed.a.e invoke"
     pack configure $Wleed.d.$i -anchor nw
     if {$leBCont($leBSel)=="$b"} {set foundi $i}
     incr i
   }
   focus $Wleed
   BindInvoke $Wleed $leBindKeyMod-s $Wleed.a.e
   bind $Wleed <Return> "leEndBlockEdit 1"
 } elseif {$editTyp=="intern"}  {				    # free input in $Weed
   set width [lindex $leBVar($leBSel) 1]
   set height [lindex $leBVar($leBSel) 2]
   toplevel_init $Wleed "$vv(asel): $leBSel" 600 400
   # top buttons
   frame $Wleed.a;  pack configure $Wleed.a -pady 3 -anchor nw
   button $Wleed.a.e -text "~s $vv(le4ae)" -command "leEndBlockEdit 1"
   Bind2P $Wleed.a.e 1 leEndBlockEditNext 1
   button $Wleed.a.q -text "~q $vv(le4aq)" -command "leEndBlockEdit 0"
   Bind2P $Wleed.a.q 1 leEndBlockEditNextt 0
   pack configure $Wleed.a.e $Wleed.a.q -side left -padx 3 -pady 3
   label $Wleed.ht -text "$leBText($leBSel):"; pack configure $Wleed.ht -pady 3 -anchor nw
   # edit area
   frame $Wleed.d -relief raised -borderwidth 2
   pack configure $Wleed.d -anchor nw -fill both -expand true
   if {$height==1} {						      # 1 input line
     set leBType entry
     entry $Wleed.d.tt -width $width
     pack configure $Wleed.d.tt -anchor nw -fill x -expand true
     bind $Wleed.d.tt <Return> "leEndBlockEdit 1"
   } else {							      # text-widget+scrollbar
     set leBType text
     if {$textxscroll>1} {
       text $Wleed.d.tt -height $height -width $width -yscrollcommand [list $Wleed.d.yb set] \
		-wrap none -xscrollcommand [list $Wleed.d.xb set]
       scrollbar $Wleed.d.xb -orient horizontal -command [list $Wleed.d.tt xview]
       pack configure $Wleed.d.xb -side bottom -fill x
       Bind3HF $Wleed.d.xb z_textfeld $Wleed.d.tt
     } else {
       text $Wleed.d.tt -height $height -width $width -yscrollcommand [list $Wleed.d.yb set]
     }
     scrollbar $Wleed.d.yb -orient vertical -command [list $Wleed.d.tt yview]
     pack configure $Wleed.d.yb -side right -fill y
     pack configure $Wleed.d.tt -side left -fill both -expand true
     bind $Wleed.d.tt <Key-Up>		"$Wleed.d.tt yview scroll -1 units"
     bind $Wleed.d.tt <Key-Down>	"$Wleed.d.tt yview scroll  1 units"
   }
   $Wleed.d.tt insert insert "$leBCont($leBSel)"
   focus $Wleed.d.tt
   BindInvoke $Wleed.d.tt $leBindKeyMod-s $Wleed.a.e
   BindInvoke $Wleed.d.tt $leBindKeyMod-q $Wleed.a.q
 }
 update
}

proc leBlockSelected {sel} {
 global Wleed Wle leBList leBVarList leBSel leBSetCont leBEdited leSelBufN
 TestPut 3 "<$leSelBufN><$sel><$leBList>"
 set sold [lindex $leBEdited end]
 if {"$sel"==""} {
   set sel [$Wle.c.s.f.f.li get $leSelBufN]
 } else {
   set leSelBufN [lsearch $leBVarList [lindex $sel 0]]
   if {$leSelBufN<0} {set leSelBufN [lsearch $leBVarList [lindex $sel 1]]}
 }
 update
 if {[string trim [string range $sel 0 2]]==""} {set el 0} else {set el 1}
 set leBSel [lindex $sel $el]
 TestPut 3 "<$leSelBufN><$sel><$sold><$leBSel>"
 if {[winfo exists $Wleed]&&($sold!="")&&($leBSetCont($sold)!="")} {set rais 1} {set rais 0}
 if {$rais==1} {raise $Wleed} else {leEditBlockSelected}
 leLUTeXPv 1; leLUPrint 1
 update
}

proc leGetNECont {block cont} {# gets block contents from vst for non-variable block
 global HOME XTEMPATH leComDir leGroupDir leFileName leBCont
 TestPut 3 "<$block><$cont>"
 set contents ""
 foreach conte $cont {
   if {$contents!=""} {set contents "$contents\n"}
     set s0 [lindex $conte 0]; set s1 [string range "$conte" [string length $s0] end]
   if		{$s0=="exececho"}	{set contents "$contents$s1"} \
   elseif	{$s0=="execcat"}	{set contents "$contents[leExec "cat $s1"]"} \
   else					{set contents "$contents$conte"}
 }
 TestPut 3 "$contents"
 regsub -all {\$leComDir} "$contents" "$leComDir" contents
 regsub -all {\$leGroupDir} "$contents" "$leGroupDir" contents
 regsub -all {\$leFileName} "$contents" "$leFileName" contents
 regsub -all {Open_Braces} "$contents" "\{" contents
 regsub -all {Close_Braces} "$contents" "\}" contents
 set leBCont($block) "$contents"
 TestPut 3 "<$leBCont($block)>"
}

proc leReadBlockCont {block eofenc} {# reads block contents from file, execpre if requested
 global vv Wq leFId leFIdEOF leBCont leBDefault leBSetCont leBComPre leIdTexts leBSel
 global leFileName
 TestPut 3 "0<$block><$leFId><$eofenc>"
 set found 0; set contents ""
 set getret [gets $leFId z]
 while {$getret>=0} {# positioning to start ob block (found=1 if really found)
   TestPut 1 "1<$z>"
   if {"x$z"=="x$leIdTexts(nomod) $leIdTexts(start) $block"} {set found 1; break}
   set getret [gets $leFId z]
 }
 if {$getret>=0} {set getret [gets $leFId z]}
 TestPut 1 "<$getret><$found>"
 while {($getret>=0)&&($found==1)} {# if block start found: read until end of block; 
				    # (found=2 if block start *and* block end really 
   TestPut 1 "2<$z>"
   if {"x$z"=="x$leIdTexts(nomod) $leIdTexts(end) $block"}		{set found 2; break} \
   elseif {[string first "$leIdTexts(nomod) $leIdTexts(start)" $z]==0}	{set found 3; break} \
   elseif {[string first "$leIdTexts(nomod) $leIdTexts(end)" $z]==0}	{break} \
   elseif {"x$contents"=="x"}		{set contents "$z"} \
   else					{set contents "$contents\n$z"}
   set getret [gets $leFId z]
 }
 if {$getret<0} {incr eofenc}; # increment "EOF encountered" at EOF (should not happen!)
 TestPut 1 "<$getret> <$found><$eofenc>"
 if {($found==2)} {# OK, block found correctly
   set leBCont($block) "$contents"
   if {$leBComPre($block)!=""} {set leBCont($block) [leExecPre $block]}
 } elseif {($found==1)&&($eofenc==0)} {#block start OK; end found,but wasn't end of this block
   set leBCont($block) "$contents"
   if {$leBComPre($block)!=""} {set leBCont($block) [leExecPre $block]}
   mybell 3
   BoxWaitOK $Wq "$vv(errf) `'\n$vv(leerr6) `$block' $vv(anf)\n$vv(leerr7)\n$vv(leerr8)" ""
 } elseif {($eofenc==1)} {# perhaps block order changed: try one more run from the file start
   set  leBCont($block) ""
   close $leFId; set leFId [open $leFileName]; set leFIdEOF 0
   leReadBlockCont $block 1
 } else {# set to default value
   set leBCont($block) "$leBDefault($block)"
   if {$leBSetCont($block)!=""} {set leBSel "$block"; leBExecSetCont; set leBsel ""}
   mybell 3
   BoxWaitOK $Wq "$vv(errf) `'\n$vv(leerr6) `$block' $vv(anf)\n$vv(leerr7)\n$vv(leerr8)" ""  
 }
 TestPut 2 "4<$leBCont($block)"
}

proc leLoadFile {} {# fills leF...(...): from existing file, or defaults otherwise
 global leFileName leSelTypeVst leFId leFIdRegular leBList leBVar leBVarList leBAlt leBDspC
 global leBName leBNonEmpt leBText leBCont leBDefault leBSetCont leBComPre leBComPost leBRep
 global leBEdited leBSel lesep
 if {$leFileName==""} {return}
 if {[file exists $leFileName]&&([file size $leFileName]>0)} {set exists 1} {set exists 0}
 TestPut 4 "<$leFileName><$exists>"
 if {$exists==1} {set leFId [open $leFileName]; set leFIdEOF 0}
 set leBEdited ""; set execsetcontafter ""
 #
 # set leB...($bn)
 set leBList ""; set leBVarList "";
 set bnum 1; set s [getvalue $leSelTypeVst [expr $bnum+2] $lesep]
 while {$s!=""} {
   set OB [getAnzThisCharInString "\{" $s]; set CB [getAnzThisCharInString "\}" $s]
   if {$OB<$CB} {set s [string range $s 0 [expr [string length $s]-2]]}
   TestPut 3 "-------------------------------------------------\n\t\t$OB $CB <$s>"
   set s0 [lindex $s 0]; set bn [lindex $s0 1]; set leBName($bn) $bn
   if {"[string trim $bn]"!=""} {lappend leBList $bn} else {break}
   set leBCont($bn) ""; set leBRep($bn) ""; set leBDspC($bn) "$leBDspC(-NonTchd)"
   set leBSetCont($bn) ""; set leBNonEmpt($bn) 0
   set leBComPre($bn) ""; set leBComPost($bn) ""
   if {[lindex [lindex $s0 0] 0]=="variable"} {
     set leBVar($bn) "[lrange [lindex $s0 0] 1 end]"
     if {$leBVar($bn)==""} {set leBVar($bn) "intern 40 1"}
   } else {
     set leBVar($bn) ""
   }
   if {$leBVar($bn)!=""} {lappend leBVarList $bn}
   TestPut 2 "$bnum:<$leBName($bn)><$leBVar($bn)>"
   if {$leBVar($bn)==""} {# non-variable block
     if {$exists==1} {leReadBlockCont $bn 0} else {leGetNECont $bn [lrange $s 1 end]}
   } else {# variable block
     set leBText($bn) [lindex $s 1]
     if {[lindex [lindex $s0 2] 0]=="non-empty"} {set leBNonEmpt($bn) 1}
     if {[lindex [lindex $s 2] 0]=="alternatives"} \
		{set leBAlt($bn) [lrange [lindex $s 2] 1 end]} else {set leBAlt($bn) ""}
     set i 3; set ll [llength $s]
     while {$i<$ll} {
	set si [lindex $s $i]
	if {[lindex $si 0]=="execset"}	{set leBSetCont($bn)	[lrange $si 1 end]}
	if {[lindex $si 0]=="execpre"}	{set leBComPre($bn)	[lrange $si 1 end]}
	#if {[lindex $si 0]=="execset"}	{lappend leBSetCont($bn)	[lrange $si 1 end]}
	#if {[lindex $si 0]=="execpre"}	{lappend leBComPre($bn)		[lrange $si 1 end]}
	if {[lindex $si 0]=="execpost"}	{lappend leBComPost($bn)	[lrange $si 1 end]}
	incr i
     }
     set leBDefault($bn) [lindex [lindex $s 2] 1]
     if {$exists==1} {
	 leReadBlockCont $bn 0
     } else {
	 set leBCont($bn) $leBDefault($bn)
	 if {$leBSetCont($bn)!=""} {lappend execsetcontafter "$bn"}
     }
     if {[string first "exec" [lindex $s 3]]!=0} {set leBRep($bn) [lindex $s 3]}
     TestPut 2 "<$leBText($bn)>\n\t\t\t<$leBNonEmpt($bn)><$leBAlt($bn)>"
     TestPut 2 "<$leBRep($bn)>\n\t\t\t<$leBSetCont($bn)><$leBComPre($bn)><$leBComPost($bn)>"
   }
   TestPut 2 "$leBCont($bn)"
   incr bnum; set s [getvalue $leSelTypeVst [expr $bnum+2] $lesep]
   if {($leBNonEmpt($bn)==1)&&("x[string trim $leBCont($bn)]"=="x")} \
	{set leBDspC($bn) "$leBDspC(-Missing)"}
 }
 #
 if {$exists==1} {close $leFId}
 if {$execsetcontafter!=""} \
	 {foreach bn $execsetcontafter {set leBSel "$bn"; leBExecSetCont}; set leBsel ""}
 TestPut 4 "<$leBList>\n\t\t<$leBVarList>"
}

proc leExec {cmd args} {# executes cmd via exec and returns result
 global Wle Wq vv xtem_path HOME XTEMPATH leComDir leGroupDir leFileName
 set res ""; set ret ""
 eval set cmd \"$cmd\"
 TestPut 4 "<$cmd><$args><$ret><$res>"
 if {[string trim $cmd]!=""} {
   if {[string trim $cmd]=="echo"} {
     set res $args
     #catch "exec echo [lrange $cmd 1 end]" res
   } else {
     eval set ret [catch "exec $cmd $args" res]
     set errtxt "$res\n\n$vv(errf): $xtem_path/letter.vst\n$vv(adm)\n\n$vv(lesemp)\n($cmd)"
     if {$ret==1} {mybell 4; BoxWaitOK $Wq "$errtxt" $Wle.a.e; set res ""}
   }
 }
 TestPut 4 "<$cmd><$ret><$res>"
 update
 return "$res"
}

proc leRepCont {block n} {#replacement $leBRep($n)->($n+1) in leBCont;returns 0 after last rp.
 global leBCont leBRep
 set str [lindex $leBRep($block) $n]; set rep [lindex $leBRep($block) [expr $n+1]]
 TestPut 2 "[string first "execrep " $rep] <$block><$n> <$str><$rep> <$leBCont($block)>"
 if {"$str$rep"!=""} {
   if {([string first $str $leBCont($block)]>=0)&&([string first "execrep " $rep]>=0)} \
	{set rep [leExec [lrange $rep 1 end]]}
   if {"x$str"!="x"} {set leBCont($block) [subStringAll $leBCont($block) $str $rep]} \
   elseif {"x[string trim $leBCont($block)]"=="x"} {set leBCont($block) $rep}
   TestPut 2 "$leBCont($block)"
   return 1
 } else {
   return 0
 } 
}

proc leExecPost {block} {# runs execpost commands
 global vv Wq Wle leBCont leBComPost leBDspC leIdTexts email leFileName
 TestPut 4 "\n*****************************************************************************\n"
 TestPut 3 "<$block><$leBComPost($block)><$leBCont($block)>"
 regsub -all "\"`" $leBCont($block) "`" leBCont($block)
 regsub -all "\"'" $leBCont($block) "'" leBCont($block)
 TestPut 3 "<$block><$leBComPost($block)><$leBCont($block)>"
 if {"x[lindex $leBCont($block) 0]"=="xset-equal-to-block-contents"} \
	{set leBCont($block) "$leBCont([lindex $leBCont($block) 1])"}
 set Contents "$leBCont($block)"
 foreach ComPost $leBComPost($block) {
   TestPut 4 "\n\n<$Contents>\n<$ComPost>"
   set ind0 [lindex $ComPost 0]
   set errtxt "\n*** $vv(aerr): `$ind0'\n$vv(leerr2)\n$vv(leerr3) $email\n"
   if		{[string first "insert-comment-framework" $ind0]==0} {
     foreach i "1 2 3 4 5 6 7 8 9 " {
       if {$ind0=="insert-comment-framework$i"} \
	   {set Contents "$leIdTexts(grepL)${i}_<${Contents}>$leIdTexts(grepR)"}
     }
     regsub -all "\n" "$Contents" "$leBDspC(-NewLine)" Contents
   } elseif	{$ind0=="insert-2backslashes-at-end-of-line"} {
     set zl [split "$Contents" "\n"]
     set Contents ""
     foreach z $zl {
       if {$Contents==""} {set Contents "$z"} else {set Contents "$Contents\n$z"}
       if {"x[string trim $z]"!="x"} {set Contents "$Contents\\\\"}
     }
   } elseif	{$ind0=="insert-newcommand-and-braces"} {
     set Contents "\\[lindex $ComPost 1]\{\\[lindex $ComPost 2]\}\{$Contents\}"
   } elseif	{$ind0=="insert-command-and-braces"} {
     set Contents "\\[lindex $ComPost 1]\{$Contents\}"
   } elseif	{$ind0=="comment-if-empty-command"} {
     if {"x[string trim $Contents]"=="x"} {set Contents "%\\[lindex $ComPost 1]\{\}"} \
     else				  {set Contents  "\\[lindex $ComPost 1]\{$Contents\}"}
   } elseif	{$ind0=="call-exec"} {
     set tmpfile1 leFileName-1.tmp; set tmpfile2 leFileName-2.tmp
     FileDelete $tmpfile1 $tmpfile2
     set ID [open $tmpfile1 w]; puts -nonewline $ID "$Contents"; close $ID
     leExec [lrange $ComPost 1 end] $tmpfile1 $tmpfile2
     set ID [open $tmpfile2 r]; set Contents [read $ID]; close $ID
     FileDelete $tmpfile1 $tmpfile2
   } else {mybell 4; BoxWaitOK $Wq "$errtxt" $Wle.a.e; set Contents "$Contents"}
   TestPut 4 "\n<$Contents>"
 }
 update
 return "$Contents"
}

proc leKnoepfe {} {# sets main_file, efile and suffixes, then calls knoepfe
 global leFileName main_file texsuffix tsuff efile esuff dir
 set main_file [string range $leFileName 0 [expr [string length $leFileName]-5]]
 set tsuff $texsuffix; set efile $main_file; set esuff $tsuff; knoepfe
}

proc leWriteFile {} {# writes block contents into file, and does execpost if requested
 global leFileName leSelTypeVst lesep leIdTexts leBList leBCont leBRep leBComPost leModified
 if [file exists $leFileName] {set exists 1} else {set exists 0}
 if {$exists==1} {file rename -force -- $leFileName $leFileName.bak}
 set leFId [open $leFileName w]
 set type "$leIdTexts(nomod) $leIdTexts(type) [getvalue $leSelTypeVst 0 $lesep]"
 TestPut 4 "<exists=$exists><$leFileName><$leBList>\n$type"
 puts $leFId "$type"
 foreach block $leBList {
   if {[info exists leBRep($block)]&&($leBRep($block)!="")} \
	{set n 0; while {[leRepCont $block $n]!=0} {incr n 2}}
   set pre  "%\n$leIdTexts(nomod) $leIdTexts(start) $block\n"
   if {$leBComPost($block)==""} {set text $leBCont($block)}  {set text [leExecPost $block]}
   set post "\n$leIdTexts(nomod) $leIdTexts(end) $block"
   TestPut 2 "<$block>:\n$pre$text$post"
   puts $leFId "$pre$text$post"
 }
 close $leFId
 leLUTeXPv 0; leLUPrint 1; set leModified 0
}

proc leTeXPv {} {global main_file
 file delete -force -- $main_file.dvi; ClickTeX ""; ClickPreview ""; leLUPrint 0
}

proc lePrint {} {ClickDvi2Printer Shift}

proc leLUTeXPv {mode} {# mode:   >=1 lock; =0 unlock, if meaningful
 global Wle leFileName
 if {![winfo exists $Wle.a.t]} {return}
 if {![file exists $leFileName]} {set mode 1}
 if {$mode==0} {$Wle.a.t configure -state normal} \
 else {$Wle.a.t configure -state disabled}
}

proc leLUPrint {mode} {# mode:   >=1 lock; ==0 unlock, if meaningful
 global Wle main_file
 if {![winfo exists $Wle.a.p]} {return}
 if {![file exists $main_file.dvi]} {set mode 1}
 if {$mode==0} {$Wle.a.p configure -state normal} \
 else {$Wle.a.p configure -state disabled}
}

proc leWle2aedit {} {# edit selected file --> create $Wle.c.s.f.f.li
 global vv Wle leModified leFileName leBList leSelLev leBindKeyMod leSelBufN
 leSelLevel 2
 #
 $Wle.a.e configure -state disabled
 foreach w "$Wle.a.edit $Wle.a.delete $Wle.a.copyedit" {if [winfo exists $w] {destroy $w}}
 leKnoepfe
 leLoadFile
 #
 # add top buttons
 button $Wle.a.save -text "~s $vv(le2asv) $leFileName" -command "leWriteFile"
 button $Wle.a.t -text "~x $vv(let)" -command {leTeXPv}
 button $Wle.a.p -text "~p $vv(lep)" -command {lePrint}
 pack configure $Wle.a.save $Wle.a.t $Wle.a.p -side left -padx 3 -pady 3
 leLUTeXPv 0; leLUPrint 1
 #
 if [winfo exists $Wle.c] {destroy $Wle.c}
 #
 # add "edit list block":
 frame $Wle.c; pack $Wle.c -anchor w -fill x -expand yes
 frame $Wle.c.s; pack $Wle.c.s -anchor w -padx 4 -fill x -expand yes
 CreateLSBox $Wle.c.s "$vv(le3c)" top 80 60 2 "" "" "" "" leBlockSelected sel Dummy
 leUpdListWidget ""
 set leSelBufN 0; $Wle.c.s.f.f.li selection set 0
 #
 focus $Wle
 BindInvoke $Wle $leBindKeyMod-q $Wle.a.e
 BindInvoke $Wle $leBindKeyMod-s $Wle.a.save
 BindInvoke $Wle $leBindKeyMod-x $Wle.a.t
 BindInvoke $Wle $leBindKeyMod-p $Wle.a.p
 bind $Wle <Return> {leBlockSelected ""}
 bind $Wle <Down> {leSelIncB $Wle.c.s.f.f.li 1}
 bind $Wle <Up> {leSelIncB $Wle.c.s.f.f.li -1}
 #
 set leModified 0
 update
}

proc leSelIncB {w inc} {global leSelBufN
 incr leSelBufN $inc
 if {$leSelBufN<0} {set leSelBufN 0}
 if {$leSelBufN>=[$w size]} {set leSelBufN [expr [$w size]-1]}
 $w selection clear 0 end; $w selection set $leSelBufN
 TestPut 4 "<$leSelBufN>"
}

proc leFileCopyEdit {} {# copy selected file to "new file", hten edit "new file"
 global leNewFile main_file efile texsuffix leFileName
 TestPut 4 "<$main_file><$texsuffix><$leFileName> <$leNewFile>"
 if {![file exists $main_file$texsuffix]} {return} 
 file copy -force -- $main_file$texsuffix $leNewFile
 set leFileName $leNewFile
 set main_file [file rootname $leNewFile]; set efile $main_file; knoepfe
 leWle2aedit
}

proc leFileDel {} {
 global vv Wq leFileName
 TestPut 4 "<$leFileName>"
 if {![file exists $leFileName]} {return} 
 if {[winfo exists $Wq]==1} {destror $Wq}; toplevel $Wq
 set frage "$vv(ak6): $leFileName ?"
 proc leReqDelYes {} {global Wq; destror $Wq;leFileDelDo};# file delete
 proc leReqDelNo  {} {global Wq; destror $Wq;           };# no file delete
 Request $Wq "$frage " "" "$vv(yes)" leReqDelYes "$vv(no)" leReqDelNo "" "" y
 proc leFileDelDo {} {
   global Wle leFileList leFileName leSelFileN leNewFile main_file efile
   TestPut 4 "<$leFileName><$leNewFile><$leFileList>"
   file delete -- $leFileName; set main_file ""; set efile ""; knoepfe
   leGetFileList
   $Wle.c.s.f.f.li delete 0 end
   foreach FN $leFileList {$Wle.c.s.f.f.li insert end $FN}
   set leSelFileN 0; $Wle.c.s.f.f.li selection set $leSelFileN; set leFileName $leNewFile
 }
}

proc leFileSel {sel} {
 global leFileName main_file efile leSelFileN
 TestPut 4 "<$leSelFileN><$sel>"
 set leFileName [lindex $sel 0]
 set fn [file rootname $leFileName]
 set main_file $fn; set efile $fn; knoepfe
}

proc leGrepFileIdTexts {files} {# grep for file identification texts --> leIdTexts(grepall*)
 global leIdTexts
 foreach i "1 2 3 4 5 6 7 8 9 " {
   set r [catch "exec grep \"$leIdTexts(grepL)$i\" $files" m]
   if {[llength $files]==1} {set m "$files:$m"}
   if {$r==0} {set leIdTexts(grepall$i) "$m"} else {set leIdTexts(grepall$i) ""}
TestPut 3 "<<<$leIdTexts(grepall$i)>>>"
 }
}

proc leFileIdText {file} {# returns file identification text for $file
 global leIdTexts
 set ret ""
 set t2 ">$leIdTexts(grepR)"
 foreach i "1 2 3 4 5 6 7 8 9" {
   set t1 "$file:$leIdTexts(grepL)${i}_<"
   set s "$leIdTexts(grepall$i)"
   set p1 [string first $t1 $s]
   if {$p1>=0} {set s [string range $s [expr $p1+[string length $t1]] end]} else {set s ""}
   set p2 [string first $t2 $s]
   if {$p2>0} {set ret "$ret  [string range $s 0 [expr $p2-1]]"}
 }
 return "$ret"
}

proc leGetFileList {} {
 global vv leFileList leGroupName texsuffix leNewFile
 # looks for old file list:
 set res [catch "glob ${leGroupName}????????-*$texsuffix" erg]
 if {$res==1} {set fold ""} else {set fold [lsort $erg]}
 TestPut 3 "<$fold>"
 #
 # grep file ident texts form old files:
 if {$fold!=""} {leGrepFileIdTexts "$fold"}
 #
 # set new file name
 set fn "$leGroupName[clock format [clock seconds] -format %Y%m%d]-"
 for {set n 1} {$n<100} {incr n} {
   if {$n<10} {set leNewFile ${fn}0$n$texsuffix} else {set leNewFile ${fn}$n$texsuffix}
   if ![file exists $leNewFile] break
 }
 TestPut 3 "<$leNewFile>";
 #
 # sets file list including ident texts
 set leFileList ""; set leFileList [linsert $leFileList 0 "$leNewFile   $vv(le2cn)"]
 foreach fn $fold {set leFileList [linsert $leFileList 1 "$fn [leFileIdText $fn]"]}
 TestPut 3 "<$leFileList>";
}

proc leSelectFile {} {# create top window, fill first filename selection window
 global vv Wle Wq geom env leSelTypeVst lesep leSelLev b_letters leModified
 global leGroupDir leFileName leGroupName vst_dir leBindKeyMod leSelFileN leNewFile leFileList
 leSelLevel 1
 TestPut 3 "[pwd] $leGroupDir [file writable $leGroupDir]"
 set errtxt "$vv(fs20) $leGroupDir\n$vv(ledne)\n"
 if [file isdirectory $leGroupDir]&&[file writable $leGroupDir] {cd $leGroupDir} \
     else {mybell 3; BoxWaitOK $Wq "$errtxt" ""; set leFileName ""; leEnd; return}
 set vstfile "$leGroupName.vst"
 if {[file exists $vstfile]} {set lesep [getsep $vstfile $leGroupDir]} \
 else \
     {puts stdout "$vv(errf) $vst_dir/letter.vst\n$vv(aus5) $vstfile $vv(ea4)\n$vv(adm)";exit}
 set leSelTypeVst [vst2list $vstfile 1 $lesep dummy dummy $leGroupDir]
 TestPut 3 "<$lesep>\n$leSelTypeVst\n"
 #
 leGetFileList
 #
 toplevel_init $Wle "$vv(amen) [string range $b_letters 1 end]" 600 800
 wm protocol $Wle WM_DELETE_WINDOW leWleae
 # top buttons
 frame $Wle.a;  pack configure $Wle.a -pady 3 -anchor nw
 button $Wle.a.e -text "~q $vv(ae)" -command "leWleae"
 pack configure $Wle.a.e -side left -padx 3 -pady 3
 # display area
 # add "edit selected file" button and selection list:
 button $Wle.a.edit -text "~e $vv(le2aed)" -command "leWle2aedit"
 button $Wle.a.copyedit -text "$vv(le2aced1)" -command "leFileCopyEdit"
 button $Wle.a.delete -text "$vv(le2ad)" -command "leFileDel"
 pack configure $Wle.a.edit $Wle.a.copyedit $Wle.a.delete -side left -padx 3 -pady 3
 frame $Wle.c; pack $Wle.c -anchor w -fill both -expand yes
 frame $Wle.c.s; pack $Wle.c.s -anchor w -padx 4 -fill both -expand yes
 CreateLSBox $Wle.c.s "$vv(le2c)" top 80 60 2 "" "" "" "$leFileList" leFileSel sel leWle2aedit
 set leSelFileN 0; $Wle.c.s.f.f.li selection set $leSelFileN; set leFileName $leNewFile
 bind $Wle.c.s.f.f.li <Return> {$Wle.a.edit invoke}
 #
 focus $Wle.c.s.f.f.li
 BindInvoke $Wle.c.s.f.f.li $leBindKeyMod-q $Wle.a.e
 BindInvoke $Wle.c.s.f.f.li $leBindKeyMod-e $Wle.a.edit
 bind $Wle.c.s.f.f.li <Down> {leSelIncF $Wle.c.s.f.f.li 1}
 bind $Wle.c.s.f.f.li <Up> {leSelIncF $Wle.c.s.f.f.li -1}
 #
 set leModified 0
 update
}

proc leSelIncF {w inc} {global leSelFileN
 incr leSelFileN $inc
 if {$leSelFileN<0} {set leSelFileN 0}
 if {$leSelFileN>=[$w size]} {set leSelFileN [expr [$w size]-1]}
 leFileSel [$w get $leSelFileN]
}

proc leSelLevel {lev} {global leSelLev; set leSelLev $lev; TestPut 3 "@@@@@@@@@@<$leSelLev>"}

proc leWleae {} {# ends letter window
 global vv Wq leModified leFileName
 if {$leModified==0} {leEnd} \
 else {
   if {[winfo exists $Wq]==1} {destror $Wq}; toplevel $Wq
   set frage "$vv(tlsrq2): $leFileName ?"
   proc leReqEditYes {} {global Wq; destror $Wq;leWriteFile; leEnd};# file save
   proc leReqEditNo  {} {global Wq; destror $Wq;             leEnd};# no file save
   Request $Wq "$frage " "" "$vv(yes)" leReqEditYes "$vv(no)" leReqEditNo "" "" y
 }
}
proc leEnd {} {# ends letter window
 global Wle lePreDir UnLock
 global main_file leOldMF texsuffix leOldTS1 tsuff leOldTS2 efile leOldEF esuff leOldES
 if {[winfo exists $Wle]} {destros $Wle}
 setInUnlockListe .c.2.le
 unlock_list; if {$lePreDir!=[pwd]} {cd $lePreDir}; TestPut 4 "pwd=[pwd]"
 set main_file $leOldMF; set texsuffix $leOldTS1; set tsuff $leOldTS2
 set efile $leOldEF; set esuff $leOldES
 knoepfe; set UnLock 1; unlock_list; update
}


proc xtem_letter {options} {
 global vv env HOME lePreDir leIdTexts leBDspC leUnlockEtc leComDir leGroupDir leGroupName
 global main_file leOldMF texsuffix leOldTS1 tsuff leOldTS2 efile leOldEF esuff leOldES UnLock
 global leBindKeyMod leDLen

 TestPut 3 "<$options>\npwd=[pwd]"

 set leComDir [lindex $options 0]
 set leGroupDir [lindex $options 1]
 set leGroupName [lindex $options 2]

 CheckCreateXtemlettersDemo $leGroupDir 

 set leDLen 90; # length of display string in block select list $Wle.c.s.f.f.li
 set leOldMF $main_file; set leOldTS1 $texsuffix; set leOldTS2 $tsuff
 set leOldEF $efile; set leOldES $esuff
 set texsuffix .tex; set tsuff $texsuffix
 set UnLock 0

 set leBindKeyMod "Alt-Key"


 set leIdTexts(grepL) "%%%%%%%%%%_identification_text_"
 set leIdTexts(grepR)					"_don't_modify_in_general_%%%%%%%%%%"
 set leIdTexts(nomod) "%%%%%%%%%%_don't modify this line"
 set leIdTexts(start) "start:"
 set leIdTexts(end)   "end:  "
 set leIdTexts(type)  "letter type:"
 set leBDspC(-Missing) "M" ; # non-blank contents requested (`missing contents')
 set leBDspC(-AutoChg) "*" ; # block contents changed automatically by `execset'
 set leBDspC(-NonTchd) "." ; # other non-toched blocks
 set leBDspC(-NoExcpt) " " ; # no exception (after `touch') --> display `blank'
 set leBDspC(-NewLine) { \\\\ } ; # no exception (after `touch') --> display `blank'

 leSelectFile; set leUnlockEtc 0
}
