#******************************************************************************
#***
#*** 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 ""
        }
}







