#******************************************************************************
#***
#*** This file is part of XTeXShell; see file xtexsh for details
#*** Version 0.91 (21.2.94)
#***
#******************************************************************************

proc XTeXEdit {} {

#******************************************************************************
#*** Editor
#***
#*** Open a new window
#*** Load and edit the file $editfname. If $editfname == "", edit new file
#***
#*** Mode of editor is determined by variable editmode (TURBO, E2)
#***
#******************************************************************************

       global  col line
       global  editwin textbuf
       global  edit_font  bold_font  boldl_font  fixboldl_font  helvbold_font
       global  editfname  editinfname
       global  editmod goto_command
       global  editins
       global  CMode trailing_spaces
       global  isColorX

       set     editwin   ".mainwin.frame"
       set     editins   "Insert"
       set     textbuf   $editwin.txt
       set     editinfname [expr {[cequal "" $editfname] ? "(unnamed)" : $editfname} ]
       set     trailing_spaces 0

#*** Check if there is already a XTeXEdit window

       if {[winfo exists $textbuf]} {
               DisplayInfo  "There is already a XTeX-Edit window!\nPlease end other XTeX-Edit session first" "$boldl_font"
               return
       }

#*** Check if file exists

       if {![cequal "" $editfname] && ![file exists $editfname]} {
               DisplayInfo "File: $editfname does not exist" "$boldl_font"
               return
       }

#*** Generate frame

       frame     $editwin
       pack      $editwin              -fill both -padx 3m -pady 2m

#*** Generate text window with scrollbars

       text      $textbuf              -relief raised -bd 2 -setgrid true -yscrollcommand "$editwin.sy set" \
                                       -wrap none -font $edit_font -height 26 -width 85
       scrollbar $editwin.sy           -relief flat -orient vertical   -command "$textbuf yview"

       pack      $editwin.sy           -side right  -fill y
       pack      $textbuf              -expand yes  -fill both

#*** Generate menu bar

       frame     $editwin.menu         -relief raised -borderwidth 1
       pack      $editwin.menu         -side bottom -fill x

       button    $editwin.menu.file    -text "Save&Quit" -command {SaveFile ""; EndXTeXEdit}
       button    $editwin.menu.save    -text "Save"      -command {SaveFile "" }
       button    $editwin.menu.saveas  -text "Save As"   -command {SaveFile "AS"}
       button    $editwin.menu.reread  -text "Reload"    -command {ReLoadFile}
       button    $editwin.menu.include -text "Include"   -command {ReadFile ""}
       button    $editwin.menu.quit    -text "Quit"      -command {EndXTeXEdit}
       pack      $editwin.menu.file $editwin.menu.save $editwin.menu.saveas $editwin.menu.reread \
                 $editwin.menu.include -side left  -padx 3m -pady 1m -ipadx 0.6m
       pack      $editwin.menu.quit -side right -padx 3m -pady 1m -ipadx 0.6m

#*** Generate Info Line

       set col 0
       set line 0
       set CMode ""
       resetmodflag

       frame     $editwin.info         -relief raised -borderwidth 1
       pack      $editwin.info         -side bottom -fill x

       label     $editwin.info.lab1    -text "Position: "
       entry     $editwin.info.col     -relief sunken -textvariable col   -width 5 -font $helvbold_font
       entry     $editwin.info.line    -relief sunken -textvariable line  -width 5 -font $helvbold_font

       label     $editwin.info.lab2    -textvariable CMode        -width 3  -font $helvbold_font -relief flat
       label     $editwin.info.lab3    -text "File:"              -width 3  -font $helvbold_font
       label     $editwin.info.fname   -textvariable editinfname            -font $helvbold_font
       label     $editwin.info.ins     -textvariable editins      -width 7  -font $helvbold_font
       label     $editwin.info.mod     -textvariable editmod      -width 3  -font $helvbold_font

       pack      $editwin.info.lab1 $editwin.info.line $editwin.info.col $editwin.info.lab2 -side left -padx 3m -pady 1m
       pack      $editwin.info.fname $editwin.info.lab3 $editwin.info.ins $editwin.info.mod -side right -padx 1m -pady 1m

       if {$isColorX} {
               $textbuf tag configure srchfound -font $edit_font -underline 1 \
                        -foreground red
       } else {
               $textbuf tag configure srchfound -font $edit_font \
                        -background black -foreground white
       }

       set       goto_command ""

#*** Read file

       if {![cequal "" $editfname]} {
               ReadFile $editfname
               resetmodflag
       }

       update
       GotoXY $textbuf "1.0"

#*** Handle Key Events

       bind $textbuf <Any-Enter>       {focus  $textbuf}
       bind $textbuf <Control-KeyPress> {ControlKey "%K"}
       bind $textbuf <KeyPress>        {if {[clength $CMode]} {ControlKey %K} else {InsChar $textbuf %A}}
       bind $textbuf <Return>          {set CMode ""; InsChar $textbuf "\n"}
       bind $textbuf <BackSpace>       {BsChar  $textbuf}
       bind $textbuf <Delete>          {DelChar $textbuf}
       bind $textbuf <Tab>             {TabChar $textbuf}
       bind $textbuf <Shift-Tab>       {ShiftTab $textbuf}
       bind $textbuf <Insert>          {toginsmode}
       bind $textbuf <Home>            {GotoXY  $textbuf [$textbuf index "insert linestart"]}
       bind $textbuf <Up>              {GotoXY  $textbuf [$textbuf index insert-1l] $col}
       bind $textbuf <Left>            {GotoXY  $textbuf [$textbuf index insert-1c]}
       bind $textbuf <Right>           {GotoXY  $textbuf [$textbuf index insert+1c]}
       bind $textbuf <Down>            {GotoXY  $textbuf [$textbuf index insert+1l] $col}
       bind $textbuf <End>             {EatSpaces $textbuf $line.$col; GotoXY  $textbuf [$textbuf index "insert lineend"]}
       bind $textbuf <Control-Home>    {setmodflag; $textbuf delete "insert linestart" insert; GotoXY $textbuf [$textbuf index insert]}
       bind $textbuf <Control-End>     {setmodflag; $textbuf delete insert "insert lineend";   GotoXY $textbuf [$textbuf index insert]}
       bind $textbuf <Prior>           {GotoXY  $textbuf [$textbuf index insert-25l] $col}
       bind $textbuf <Next>            {GotoXY  $textbuf [$textbuf index insert+25l] $col}
       bind $textbuf <Control-Prior>   {GotoXY  $textbuf [$textbuf index insert-100000l] $col}
       bind $textbuf <Control-Next>    {GotoXY  $textbuf [$textbuf index insert+100000l] $col}

       bind $textbuf <Control-F1>      {set word [%W get "insert wordstart" "insert wordend"]
                                        HyperHelp $word
                                       }

#*** New Column / Line Request

       bind $editwin.info.col  <Return>      {GotoXY  $textbuf $line.$col $col}
       bind $editwin.info.line <Return>      {GotoXY  $textbuf $line.$col $col}

#*** Handle Mouse Events

       bind $textbuf <1>               {But11 %W %x %y}
       bind $textbuf <Double-1>        {But12 %W %x %y}
       bind $textbuf <Triple-1>        {But13 %W %x %y}
       bind $textbuf <B1-Motion>       {tk_textSelectTo %W @%x,%y}
       bind $textbuf <Shift-1>         {ButS11  %W %x %y}
       bind $textbuf <Shift-B1-Motion> {tk_textSelectTo %W @%x,%y}
       bind $textbuf <2>               {%W scan mark -%y}
       bind $textbuf <Double-2>        {InsSelection %W}
       bind $textbuf <B2-Motion>       {%W scan dragto -%y}
       bind $textbuf <3>               {%W index @%X,%Y
                                        set word [%W get "@%x,%y wordstart" "@%x,%y wordend"]
                                        HyperHelp $word
                                       }

       tk_bindForTraversal Text
}


proc ControlKey {char} {

#*** This function handles Control-Key Sequences

       global ch CMode
       set ch [string tolower "$char"]

       uplevel 1 {

#*** Normal Control-Events

               if {[cequal $CMode ""]} {
                       switch "$ch" {
                               "k" {set CMode "^K"}
                               "q" {set CMode "^Q"}
                               "h" {BsChar  $textbuf}
                               "y" {setmodflag; $textbuf delete "insert linestart" "insert lineend+1c"; GotoXY $textbuf [$textbuf index "insert"]}
                               "l" -
                               "f" {EditSrch "CONTINUE"}
                       }
                       return
               }

#*** We are in a Ctrl-K or Ctrl-Q state

               if {[cequal $CMode "^K"]} {
                       switch "$ch" {
                               "b" {$textbuf mark set anchor insert}
                               "k" {tk_textSelectTo $textbuf "insert-1c"}
                               "c" {InsSelection $textbuf}
                               "m" -
                               "v" {MoveSelection $textbuf}
                               "y" {DelSelection $textbuf}
                               "r" {ReadFile ""}
                               "w" {WriteFile {[selection get]} ""}
                               "s" {$editwin.menu.save invoke}
                               "d" {$editwin.menu.file invoke}
                               "f" {EditSrch ""}
                               "a" {EditSrch "REPLACE"}
                       }
               }
               if {[cequal $CMode "^Q"]} {
                       switch "$ch" {
                               "f" {EditSrch ""}
                               "a" {EditSrch "REPLACE"}
                       }
               }
               set CMode ""
       }
}

#*****************************************************************************
#****** Functions to enter Text or characters into editor ********************
#*****************************************************************************

proc InsChar {textbuf char} {

       global col line
       global editwrap editwrapcol edittrans edittrlist
       global editins

       if {[ctype ord $char] > 0} {
               setmodflag

#*** Character Translation

               if {$edittrans} {
                       set pos [lsearch -exact $edittrlist "\_$char\_"]
                       if {$pos > -1} {
                               set char [lindex $edittrlist [expr $pos+1]]
                       }
               }


#*** Delete Mode ?

               if {[cequal $editins "Delete"]} {
                       set len  [clength "$char"]
                       set rlen [clength [$textbuf get $line.$col "$line.$col lineend"]]
                       if {$rlen < $len} {
                               set len $rlen
                       }

                       $textbuf delete $line.$col "$line.$col+$len c"
                       $textbuf insert $line.$col "$char"
               } else {

#*** Insert character in text. Check for Wrap-Mode

                       $textbuf insert $line.$col "$char"

                       if {$col > $editwrapcol && $editwrap && [string first $char " \n"]<0} {
                               set col [string last " " [$textbuf get "insert linestart" "insert"]]
                               incr col
                               if {$col>0} {$textbuf insert $line.$col "\n"}
                       }
               }

#*** Set cursor

               GotoXY $textbuf [$textbuf index insert]
       }
}

proc InsertText {textbuf text} {

#*** Insert text into editor. Move cursor to end of text

       global col line

       setmodflag
       $textbuf insert $line.$col "$text"
       GotoXY $textbuf [$textbuf index insert]
}

proc InsertEditor {text} {

#*** Insert text into editor, but only if editor exists.
#*** Remove all tabs and replace by spaces. Do not move cursor

       global edittab textbuf boldl_font

       if {![EditChkOpen]} {return}
       set pos [$textbuf index insert]
       InsertText $textbuf "$text"

#*** Now search through text in 512 byte blocks for tabs and replace them
#*** This routine must be very fast !!!!!

       if {[string first "\t" $text] >= 0} {
               DisplayMsg "Text contains Tabs.\n Replacing Tabs.\n Please Wait..." $boldl_font
               for {set sblock 0} {1 < [clength [$textbuf get "0.0 + $sblock c" "0.0 + $sblock c + 2c"]]} {incr sblock 512} {
                       while {1} {
                               set tpos [string first "\t" [$textbuf get "0.0 + $sblock c" "0.0 + $sblock c + 512 c"]]
                               if {$tpos < 0} {break}

                               incr sblock $tpos
                               $textbuf mark set insert "0.0 + $sblock c"
                               $textbuf delete insert

                               set col [lindex [split [$textbuf index insert] "."] 1]
                               $textbuf insert insert [replicate " " [expr [expr $edittab * ($col / $edittab + 1)] - $col]]
                       }
               }
       }

#*** Set Cursor position

       GotoXY $textbuf $pos
}

#*****************************************************************************
#****** Functions to change cursor position **********************************
#*****************************************************************************

proc GotoXY {textbuf pos {wcol -1}} {

#*** Move Cursor to position pos.
#*** If wcol>=0, goto column wcol. If column wcol does not exist
#*** because the line is shorter, insert spaces at end of line
#*** until wcol is reached. Remove extra spaces when cursor is moved to
#*** the next line.

       global col line
       global goto_command

#*** Calculate new position

       set npos  [$textbuf index "$pos"]
       set nline [lindex [split $npos "."] 0]
       set ncol  [lindex [split $npos "."] 1]

#*** Execute goto_command command

       eval $goto_command
       set goto_command ""

#*** before the line changes, eat up ending spaces (if any)

       if {$line != $nline} {
               EatSpaces $textbuf $line.$col
       }

#*** Set Cursor

       while {1} {
               $textbuf insert $npos ""
               $textbuf mark set insert $npos

#*** Get Cursor position

               set col  [lindex [split [$textbuf index insert] "."] 1]
               set line [lindex [split [$textbuf index insert] "."] 0]

#*** If wcol >=0, check if new column=wcol. If not, insert spaces until
#*** column==wcol. This is important for cursor up/down if line length
#*** is smaller than the requested column

               if {$wcol >= 0 && $col < $wcol} {
                       set xpos [$textbuf index "$nline.0 lineend"]
                       $textbuf mark set insert $xpos

                       set len [expr $wcol - [lindex [split $xpos "."] 1]]
                       $textbuf insert insert [replicate " " $len]
                       set npos "$nline.$wcol"
                       set wcol -1
                       continue
               }

#*** Redisplay text window if neccessary

               $textbuf yview -pickplace insert
               focus $textbuf
               break
       }
}

proc EatSpaces {textbuf pos} {

#*** Eat all spaces at the end of line pos (YUMM, YUMM)

       set line  [$textbuf get "$pos linestart" "$pos lineend"]
       set len   [expr [clength $line] - [clength [string trimright $line]]]

       if {$len>0} {
               $textbuf delete "$pos lineend -$len c" "$pos lineend"
       }
}

#*****************************************************************************
#****** Handle key events ****************************************************
#*****************************************************************************

proc TabChar {textbuf} {

       global edittab editins line col

       set    newcol [expr $edittab * ($col / $edittab + 1)]

       if {[cequal "Insert" $editins]} {
               InsertText $textbuf [replicate " " [expr $newcol - $col]]
       } else {
               GotoXY  $textbuf $line.$newcol $newcol
       }
}

proc ShiftTab {textbuf} {

       global edittab line col

       set    newcol [expr $edittab * (($col-1) / $edittab)]
       GotoXY  $textbuf $line.$newcol
}


proc DelChar {textbuf} {

       global col line

       setmodflag
       $textbuf delete $line.$col
}

proc BsChar {textbuf} {

       if {![cequal "1.0" [$textbuf index insert]]} {
               setmodflag
               GotoXY $textbuf [$textbuf index insert-1c]
               $textbuf delete insert
       }
}

proc DelSelection {textbuf} {

       setmodflag
       $textbuf delete sel.first sel.last
}

proc InsSelection {textbuf} {


       setmodflag
       $textbuf insert insert [selection get]
       GotoXY $textbuf [$textbuf index insert]
}

proc MoveSelection {textbuf} {

       setmodflag
       InsSelection $textbuf
       DelSelection $textbuf
}

proc But11 {textbuf x y} {
       set tk_priv(selectMode) char
       $textbuf mark set insert @$x,$y
       $textbuf mark set anchor insert
       if {[lindex [$textbuf config -state] 4] == "normal"} {focus $textbuf}
       GotoXY $textbuf [$textbuf index insert]
}

proc But12 {textbuf x y} {
       set tk_priv(selectMode) word
       $textbuf mark set anchor "@$x,$y wordstart"
       tk_textSelectTo $textbuf "@$x,$y wordend-1c"
}

proc But13 {textbuf x y} {
       set tk_priv(selectMode) line
       $textbuf mark set anchor "@$x,$y linestart"
       tk_textSelectTo $textbuf "@$x,$y lineend"
}

proc ButS11 {textbuf x y} {
       tk_textResetAnchor $textbuf @$x,$y
       tk_textSelectTo $textbuf @$x,$y
}


#*****************************************************************************
#****** Check editor status **************************************************
#*****************************************************************************

proc EditChkOpen {{mode 1}} {

#*** Check if editor open.
#*** If not, (if mode=1 display warning message) and return false

       global textbuf boldl_font

       if {![info exists textbuf] || ![winfo exists $textbuf]} {
               if {$mode == 1} {
                       DisplayInfo "Function does not work because you haven't startet the XTeX-editor yet" $boldl_font
               }
               return 0
       }
       return 1
}

#******************************************************************************
#*** Flags for modification of editor window **********************************
#******************************************************************************

proc setmodflag {} {

#*** Set Flag for modification

       global editmod
       if {[cequal $editmod ""]} {
               set editmod "Mod"
       }
}

proc resetmodflag {} {

#*** Reset Modification flag

       global editmod
       set editmod ""
}

proc Qmodflag {} {

#*** Is modification flag set ?

       global editmod

       if {![EditChkOpen 0]} {return 0}
       return [string compare $editmod ""]
}

proc toginsmode {} {

#*** Toggle Insert Flag and

       global editins

       if {[cequal "Insert" $editins]} {
               set editins "Delete"
       } else {
               set editins "Insert"
       }
}

#******************************************************************************
#*** File I/O *****************************************************************
#******************************************************************************

proc ReadFile {fname} {

#*** Include a file at current cursor position
#*** if fname == "", then ask for file name

       global boldl_font textbuf

#*** Do we have an open edit window ?

       if {![EditChkOpen]} {return}

#*** Yes. Do we have a valid filename? if fname="" then ask for filename

       if {[cequal $fname ""]} {
               set fname [FileSelBox OPEN]
               if {[cequal $fname ""]} {return}
       }

#*** Now read file

       set fd [open $fname "r"]
       InsertEditor [read $fd]
       close $fd
}

proc ReLoadFile {} {

#*** Quit current File view and Re-Read file

       global boldl_font
       global editfname textbuf

#*** Do we have an open edit window and did we load a file or was it a new file?

       if {![EditChkOpen] || [cequal "" $editfname]} {return}

#*** Ask user if he wants the file reload and load file

       set retval [DisplayQuest "Re-Read file:\n\nCancel current editor window and Re-Read file?" \
                                $boldl_font "Yes" "No"]
       if {$retval==1} {
               $textbuf delete 0.0 end
               ReadFile $editfname
               resetmodflag
       }
}

proc WriteFile {range fname} {

#*** Rename fname to fname~. Write range to file fname
#*** If fname == "", than ask for FileName
#*** return filename if operation successful, "" if error

       global textbuf boldl_font
       global line col

       if {[cequal $fname ""]} {
               set fname [FileSelBox CREATE]
               if {[cequal $fname ""]} {return ""}
       }

       if {[file exists "$fname"]} {
               catch {frename "$fname" "$fname~"}
       }

       set fd [open $fname "w"]
       if {$fd <= 0} {
               DisplayInfo "Can't open file\n$fname\nfor writing!\nOperation aborted!" $boldl_font
               return ""
       }

       DisplayMsg "Writing to file\n $fname.\n Please wait..." $boldl_font

       eval puts $fd $range
       close $fd

       sleep 1;                                #*** Wait and remove message in GotoXY function
       GotoXY $textbuf $line.$col

       return "$fname"
}

proc SaveFile {Mode} {

#*** Save file in editor. Mode="": Use editfname. Mode=="AS": Ask for filename

       global textbuf editfname editinfname

#*** Do we have an open edit window ?

       if {![EditChkOpen]} {return}

#*** Get filename

       if {[cequal $Mode ""]} {
               set retval [WriteFile {[$textbuf get 0.0 end]} "$editfname"]
       } else {
               set retval [WriteFile {[$textbuf get 0.0 end]} ""]
       }

#*** Write file

       if {![cequal $retval ""]} {
               resetmodflag
               set editfname   "$retval"
               set editinfname "$retval"
       }
}

#******************************************************************************
#*** Search / Replace**********************************************************
#******************************************************************************

proc EditSrch {func} {

#*** Search/Replace Text
#***   func== ""         : Display Search mask and search
#***   func== "REPLACE"  : Display Replace mask and replace
#***   func== "CONTINUE" : Continue previous operation

       global srch_win
       global srch_mode srch_str srch_rep srch_case srch_prompt srch_dir srch_mode srch_pos
       global srch_act srch_scope textbuf
       global textbuf

       if {![EditChkOpen]} {return}

       if {![cequal $func "CONTINUE"] || ![info exists srch_pos]} {
               set srch_mode [expr ![cequal $func "REPLACE"]]

#*** Create Search / Replace Window

               set srch_win [CreateTopWin search "CREATE"]
               if {$srch_mode}  {set title "Search"}
               if {!$srch_mode} {set title "Replace"}
               wm title    $srch_win $title
               wm iconname $srch_win $title

#*** Create Frames which are used to place the entries on the screen

               frame   $srch_win.srch     -relief flat -border 1
               frame   $srch_win.bot      -relief raised -border 1
               frame   $srch_win.opt1     -relief flat -border 1
               frame   $srch_win.opt2     -relief flat -border 1
               frame   $srch_win.opt3     -relief flat -border 1
               pack    $srch_win.bot      -side bottom -expand yes -fill both

#*** Search / Replace text entry

               pack    $srch_win.srch     -anchor w -side top -expand yes
               label   $srch_win.srch.txt -text "Text to find  "
               entry   $srch_win.srch.var -relief sunken -textvariable srch_str -width 40
               pack    $srch_win.srch.txt $srch_win.srch.var -side left -anchor w -expand yes -fill x -padx 3m -pady 1m
               bind    $srch_win.srch.var <Return> {$srch_win.bot.ok invoke}
               bind    $srch_win.srch.var <Tab>    { }

               if {!$srch_mode} {
                       frame   $srch_win.rep      -relief flat -border 1
                       pack    $srch_win.rep      -anchor w -side top -expand yes
                       label   $srch_win.rep.txt  -text "Replace with"
                       entry   $srch_win.rep.var  -relief sunken -textvariable srch_rep -width 40
                       pack    $srch_win.rep.txt  $srch_win.rep.var -side left -anchor w -expand yes -fill x -padx 3m -pady 1m
                       bind    $srch_win.srch.var <Return> {focus $srch_win.rep.var}
                       bind    $srch_win.srch.var <Tab>    {focus $srch_win.rep.var}
                       bind    $srch_win.rep.var  <Return> {$srch_win.bot.ok invoke}
                       bind    $srch_win.rep.var  <Tab>    { }
               }

#*** Options entry

               pack        $srch_win.opt1 $srch_win.opt2 $srch_win.opt3  -side left -expand yes -padx 3m -pady 2m

               label       $srch_win.opt1.txt    -text "Options"
               checkbutton $srch_win.opt1.case   -relief flat  -text "Case-sensitive"    -variable srch_case
               if {!$srch_mode} {
                       checkbutton $srch_win.opt1.prompt -relief flat  -text "Prompt on Replace" -variable srch_prompt
                       $srch_win.opt1.prompt select
               } else {
                       label       $srch_win.opt1.prompt -text " "
               }
               pack        $srch_win.opt1.txt $srch_win.opt1.case $srch_win.opt1.prompt -side top -anchor w

               label       $srch_win.opt2.txt    -text "Direction"
               radiobutton $srch_win.opt2.forw   -relief flat  -text "Forward"           -variable srch_dir -value "FORWARD"
               radiobutton $srch_win.opt2.back   -relief flat  -text "Backward"          -variable srch_dir -value "BACKWARD"
               pack        $srch_win.opt2.txt $srch_win.opt2.forw $srch_win.opt2.back -side top -anchor w
               $srch_win.opt2.forw invoke

               label       $srch_win.opt3.txt    -text "Scope"
               radiobutton $srch_win.opt3.cur    -relief flat  -text "From Cursor"       -variable srch_scope -value "CURSOR"
               radiobutton $srch_win.opt3.scop   -relief flat  -text "Entire File"       -variable srch_scope -value "FILE"
               pack        $srch_win.opt3.txt $srch_win.opt3.cur $srch_win.opt3.scop -side top -anchor w
               $srch_win.opt3.cur invoke

#*** Menu Buttons at the top of the window

               button  $srch_win.bot.ok          -text "OK"         -command  {set srch_act "1";    destroy $srch_win}
               button  $srch_win.bot.all         -text "Change All" -command  {set srch_act "ALL";  destroy $srch_win}
               button  $srch_win.bot.cancel      -text "Cancel"     -command  {set srch_act "";     destroy $srch_win; return}
               button  $srch_win.bot.help        -text "Help"       -command  {}
               pack    $srch_win.bot.ok -padx 3m -pady 3m -side left -expand yes -fill x
               if {!$srch_mode} {
                       pack    $srch_win.bot.all -padx 3m -pady 3m -side left -expand yes -fill x
               }
               pack    $srch_win.bot.cancel $srch_win.bot.help -padx 3m -pady 3m -side left -expand yes -fill x

#*** Wait until user selected action

               focus   $srch_win.srch.var
               tkwait visibility $srch_win
               grab -global $srch_win
               tkwait window $srch_win
               focus $textbuf

               if {[cequal $srch_act ""]} {return}

#*** Initialize some variables

               set srch_dir [cequal "FORWARD" $srch_dir]

#*** Search / Replace from Top / End of file ? Set srch_pos

               if {[cequal $srch_scope "FILE"]} {
                       if {$srch_dir} {
                               set srch_pos 0
                       } else {
                               set srch_pos [string length [$textbuf get 0.0 end]]
                       }
                       SrchRep
                       focus $textbuf
                       return
               }

       }

#*** Srch / Replace from Cursor ? Set srch_pos to current cursor

       set srch_pos [string length [$textbuf get 0.0 insert]]
       if {$srch_dir} {
               incr srch_pos
       }

       SrchRep
       focus $textbuf
}


proc SrchRep {} {

#*** Search / Replace
#***    srch_mode:   true: Search, false: Replace
#***    srch_str:    String to search
#***    srch_rep:    String to replace
#***    srch_case:   Case sensitive ?
#***    srch_prompt: Prompt on replace ?
#***    srch_dir:    true = forward, false = backward
#***    srch_act:   "1" Search next  "ALL" Replace all
#***    srch_pos:    Position (in chars) where to start with search

       global     srch_mode srch_str srch_rep srch_case srch_prompt srch_dir srch_mode srch_pos srch_act
       global     textbuf line col goto_command
       global     boldl_font

       set        rep_num 0;                           #*** Number of replacements

#*** Get Search-String to str. If case independant search, convert to upper

       set str    "$srch_str"
       if {!$srch_case} {set str  [string toupper "$str"]}
       set str_len [clength $str]

       while (1) {

#*** Copy Text-Range to search to text... If case independant, convert to upper case...
#*** Search entry. If found, set pos to position in textbuf, srch_pos to position for
#*** next search / replace

               if {$srch_dir} {
                       set text  [$textbuf get "0.0 + $srch_pos chars" end]
               } else {
                       set text  [$textbuf get "0.0" "0.0 + $srch_pos chars"]
               }

               if {!$srch_case} {set text [string toupper "$text"]}

               if {$srch_dir} {
                       set pos [string first "$str" "$text"]
                       set curpos [expr $srch_pos+$pos]
               } else {
                       set pos [string last  "$str" "$text"]
                       set curpos $pos
               }


#*** No entry found ? Tell User if Search-Mode. If Replace-Mode, everything is fine...

               if {$pos < 0} {
                       if {$rep_num == 0} {
                               DisplayInfo "Search:\n$str\n not found" $boldl_font
                       } else {
                               DisplayMsg "Replace:\n$rep_num\nreplacements made" $boldl_font
                               sleep 1
                       }
                       set srch_pos 1000000
                       focus $textbuf
                       GotoXY $textbuf $line.$col
                       return
               }

#*** Entry found, set cursor to word and highlight

               GotoXY $textbuf "0.0 + $curpos chars"
               $textbuf tag add srchfound insert "insert+$str_len c"
               update
               lvarcat goto_command "$textbuf tag remove srchfound 0.0 end;"

#*** Return if Search-Mode

               if {$srch_mode} {return}

#*** Next Srch / Replace from Cursor! Set srch_pos to current cursor

               set srch_pos [string length [$textbuf get 0.0 insert]]
               if {$srch_dir} {
                       incr srch_pos
               }

#*** Prompt before replace ? ...

               if {$srch_prompt} {
                       set retval [DisplayQuest "Search String found! Replace?" $boldl_font "Yes" "No" "Go" "Quit"]
                       if {$retval == 4} {return}
                       if {$retval == 3} {set srch_prompt 0}
                       if {$retval == 2} {continue}
               }

#*** Now replace String

               $textbuf delete insert "insert + $str_len chars"
               InsertEditor "$srch_rep"
               setmodflag
               incr rep_num
               if {![cequal "ALL" $srch_act]} {
                       return
               }
       }
}


#******************************************************************************
#*** Edit: Select editor and edit file ****************************************
#******************************************************************************

proc Edit fname {

#*** Call Editor
#*** fname = "\n"  : Display file selector box and let user choose a file to edit
#*** fname = ""    : Create a new file
#*** default       : Edit file fname

       global editfname editinfname editor editwin
       global editfilelist
       global boldl_font

#*** The XTeX built-in editor can handle only one file at a time.
#*** Check if XTeX editor is selected and if there is already a modified file in the editor

       set editor [string tolower $editor]

       if {[cequal $editor "xtex"]  && [info exists editwin] && [winfo exists $editwin]} {
               while {[Qmodflag]} {
                       set retval [DisplayQuest "Warning!!!\n\nData in editor window\nhas not been saved!\n\nDo you want to save it now?\nFile:\n $editinfname" \
                                                        "$boldl_font" "Save" "Save As" "Don't save" "Return to editor"]
                       switch $retval {
                               1 { SaveFile ""   }
                               2 { SaveFile "AS" }
                               3 { break }
                               4 { return }
                       }
               }
               destroy $editwin
       }

#*** Check if filename makes sense

       switch $fname {
          "\n"    { set fname [FileSelBox OPENCREATE]
                    if {[cequal $fname ""]} {return}
                  }
          default {}
       }

#*** Append filename to ReOpen menu if filename is not there yet

       if {![info exists editfilelist]} {set editfilelist ""}

       if {![cequal "" $fname] && [lsearch $editfilelist $fname]==-1} {
               .menu.file.m.reopen add command -label "$fname" -underline 0 -command "Edit $fname"
               lappend editfilelist "$fname"
       }

       set editfname $fname

       if {$editor=="xtex"} {
               XTeXEdit
       } else {
               global command_editor_$editor
               eval set command \$command_editor_$editor
               while {1} {
                       set pos [string first ":" "$command"]
                       if {$pos==-1} {break}

                       set sstr [expr {$pos ? [crange "$command" 0 "$pos-1" ] : ""}]
                       set estr [crange "$command" "$pos+1" end]
                       set mstr [string tolower [ctoken estr " .,:"]]

                       if {[cequal "$mstr" "fnamewoext"]} {
                               set mstr [strip_extension $fname]
                               set filenameneeded 1
                       }
                       if {[cequal "$mstr" "fname"]} {
                               set mstr $fname
                               set filenameneeded 1
                       }
                       set command [format "%s%s%s" "$sstr" "$mstr" "$estr"]
               }
               eval exec $command &
       }
}

#******************************************************************************
#*** Quit was selected. Are the files saved ? *********************************
#******************************************************************************

proc EndXTeXEdit {} {

       global boldl_font
       global editwin editfname editinfname editmdfied

       if {[info exists editwin] && [winfo exists $editwin]} {
               while {[Qmodflag]} {
                       set retval [DisplayQuest "Warning!!!\n\nData in editor window\nhas not been saved!\n\nDo you want to save it now?\nFile:\n $editinfname" \
                                                "$boldl_font" "Save" "Save As" "Really Quit"]
                       switch $retval {
                               1 { SaveFile ""   }
                               2 { SaveFile "AS" }
                               3 { break;}
                       }
               }
               destroy $editwin
               set editfname ""
       }
}