######################################################### # TkTeXeditor # Distributed under GNU Public License # Author: Sergey Kalinin (BanZaj) banzaj@lrn.ru # Copyright (c) "CONERO lrn", 2000, http//conero.lrn.ru ######################################################### ## FILE EDITOR WINDOW ## proc EditFile {file} { global dir font tree nb files color files index status activeFile treeStruct ver global editor backup status replace sysenc release wm title . "TkLaTeXEditor $ver$release - $file" if {[file exists $file] == 0} { set answer [tk_messageBox -message "$f [::msgcat::mc "File not found"]"\ -type ok -icon warning -title [::msgcat::mc "Warning"]] case $answer { ok {return} } } set fileName [file tail $file] set fileDir [file dirname $file] set dir(current) $fileDir puts "============ $fileName $fileDir" set node [InsertTreeNode $fileName $fileDir] #set node [NodeInsert $fileName $fileDir ""] set activeFile $node set replace 0 ;# for Overwrite procedure# execute external editor # if {$editor(extern)=="Yes"} { set pipe [open "|$editor(prog) $file" "r"] fileevent $pipe readable fconfigure $pipe -buffering none -blocking no return } ## check active file and if them don't exists return 0 if {[info exists files($node)] != 1} { set files($node) [list $file 0] set w [$nb insert end $node -text "$fileName"] } else { # puts "$file - already opened" return } ## update statusbar info $status(fileAttr) configure -text "[FileAttr $file]" $status(fileSize) configure -text "[file size $file] b." $status(encode) configure -text "[lindex $files($node) 2]" ## create frames and text widget # frame $w.f -borderwidth 2 -relief ridge pack $w.f -side top -fill both -expand true #supertext::text supertext::text $w.f.text -yscrollcommand "$w.f.yscroll set" \ -relief sunken -wrap $editor(wrap) -highlightthickness 0 -font $font(editNormal)\ -background $color(editBg) -foreground $color(editFg)\ -selectborderwidth 0 -selectbackground $color(selectbg) -width 10 # lines numbering #set txtLineNumber [text $w.f.text_lines -yscrollcommand "$w.f.yscroll set" \ #-relief sunken -wrap $editor(wrap) -highlightthickness 0 -font $font(editNormal)\ #-background $color(lineNumberBg) -foreground $color(lineNumberFg)\ #-selectborderwidth 0 -selectbackground $color(selectbg) -width 5] scrollbar $w.f.yscroll -relief sunken -borderwidth {1} -width {10} -takefocus 0 \ -command "$w.f.text yview" #pack $w.f.text_lines -side left -fill y pack $w.f.text -side left -fill both -expand true pack $w.f.yscroll -side left -fill y $nb raise $node ## loadig tags for highlight procedure LoadTag $w.f.text #puts $w.f.text ## BACKUP FILE CREATED ## if {$backup(create) == "Yes"} { file copy -force -- $file [file join $dir(tmp) $fileName~] } ## OPENED FILE ## set fHandle [open "$file" r] set sourceEnc [DocRecode $fHandle] if {$sourceEnc == ""} { set sourceEnc [encoding system] } lappend files($node) "$sourceEnc" ;# added encoding information $status(encode) configure -text "[lindex $files($node) 2]" set lineNumber 1 $treeStruct delete [$treeStruct nodes root] ;# delete all info about old structure while {[gets $fHandle line]>=0} { set line [encoding convertfrom $sourceEnc $line] $w.f.text insert end "[string trimright $line]\n" InsertStruct $node $line $lineNumber $fileDir HighLightTEX $w.f.text $line $lineNumber $node #$txtLineNumber insert end "$lineNumber\n" incr lineNumber } close $fHandle # key bindings # set text $w.f.text bind $text GoToLine bind $text GoToLine bind $text Find bind $text Find #bind $text SplitWindow #bind $text {ConvertDialog ps} #bind $text {ConvertDialog pdf} bind $text ReplaceDialog bind $text ReplaceDialog #bind $text {ReplaceCommand $w.frame.text 1} bind $text {FileDialog save} bind $text {FileDialog save} bind $text {FileDialog save_as} bind $text {FileDialog save_as} bind $text {FileDialog close} bind $text {FileDialog close} bind $text "tk_textCut $w.f.text;break" bind $text "tk_textCut $w.f.text;break" bind $text "tk_textCopy $w.f.text;break" bind $text "tk_textCopy $w.f.text;break" bind $text "tk_textPaste $w.f.text;break" bind $text "tk_textPaste $w.f.text;break" bind $text exit bind $text exit bind $text "$text undo" bind $text "$text undo" bind $text AutoComplit bind $text AutoComplit bind $text "GenerateFormula math" bind $text "GenerateFormula math" bind $text "GenerateFormula text" bind $text "GenerateFormula text" bind $text {$status(pos) configure -text [%W index insert]} bind $text {OverWrite} bind $text {catch [PopupMenu %W %X %Y]} bind $text { AddText item set pos [%W index insert] set line [lindex [split $pos "."] 0] set editLine [%W get $line.0 $pos] HighLightTEX %W $editLine $line [$nb raise] set node [$nb raise] if {$node == "" || $node == "debug" || $node == "settings" || $node == "about"} {return 1} if {[lindex $files($node) 1] == 0} { set files($node) [list [lindex $files($node) 0] 1 [lindex $files($node) 2]] $status(active) configure -text [::msgcat::mc "File modify"] $nb itemconfigure $node -foreground $color(editTitleModify) } } bind $text { set node [$nb raise] if {$node == "" || $node == "debug" || $node == "settings" || $node == "about"} {return 1} set text "$nb.f$node.f.text" set pos [$text index insert] set line [lindex [split $pos "."] 0] set symbol [lindex [split $pos "."] 1] set editLine [$text get $line.0 $pos] HighLightTEX $text $editLine $line $node $status(pos) configure -text [$text index insert];# cursor position if {$symbol >= $editor(strLen)} { if {[Key %k] == "true"} { if {$editor(strWrap) == "Yes"} { #$text insert $line.end "\n" set p [$text search -backward -regexp -- {\s} $pos $line.0] if {$p !=""} { $text insert "$p + 1 chars" "\n" } } } } if {[Key %k] == "true"} { if {[lindex $files($node) 1] == 0} { set files($node) [list [lindex $files($node) 0] 1 [lindex $files($node) 2]] $status(active) configure -text [::msgcat::mc "File modify"] $nb itemconfigure $node -foreground $color(editTitleModify) } } } bind $text { if {[Key %k] == "true"} { ReplaceChar %W } set node [$nb raise] if {$node == "" || $node == "debug" || $node == "settings" || $node == "about"} {return 1} set text "$nb.f$node.f.text" set pos [$text index insert] set line [lindex [split $pos "."] 0] set symbol [lindex [split $pos "."] 1] set editLine [$text get $line.0 $pos] HighLightTEX $text $editLine $line $node $status(pos) configure -text [$text index insert];# cursor position if {$symbol >= $editor(strLen)} { if {[Key %k] == "true"} { if {$editor(strWrap) == "Yes"} { #$text insert $line.end "\n" set p [$text search -backward -regexp -- {\s} $pos $line.0] if {$p !=""} { $text insert "$p + 1 chars" "\n" } } } } } bind $text { if {[Key %k] == "true"} { ReplaceChar %W } } bind $text { set node [$nb raise] if {$node == "" || $node == "debug" || $node == "settings" || $node == "about"} {return 1} if {[lindex $files($node) 1] == 0} { set files($node) [list [lindex $files($node) 0] 1 [lindex $files($node) 2]] $status(active) configure -text [::msgcat::mc "File modify"] $nb itemconfigure $node -foreground $color(editTitleModify) } } bind $text { set i -1 switch -- [%W get "insert - 1 chars"] { \{ {set i [_searchCloseBracket %W \{ \} insert end]} \[ {set i [_searchCloseBracket %W \[ \] insert end]} ( {set i [_searchCloseBracket %W ( ) insert end]} \} {set i [_searchOpenBracket %W \{ \} insert 1.0]} \] {set i [_searchOpenBracket %W \[ \] insert 1.0]} ) {set i [_searchOpenBracket %W ( ) insert 1.0]} } ;# switch if { $i != -1 } { %W mark set insert $i %W see insert } } ;# bind bindtags $text [list [winfo toplevel $text] $text Text sysAfter all] bind sysAfter {+ set i -1 catch { switch -- [%W get "insert - 1 chars"] { \{ {set i [_searchCloseBracket %W \{ \} insert end]} \[ {set i [_searchCloseBracket %W \[ \] insert end]} ( {set i [_searchCloseBracket %W ( ) insert end]} \} {set i [_searchOpenBracket %W \{ \} insert 1.0]} \] {set i [_searchOpenBracket %W \[ \] insert 1.0]} ) {set i [_searchOpenBracket %W ( ) insert 1.0]} } ;# switch catch { %W tag remove lightBracket 1.0 end } if { $i != -1 } {%W tag add lightBracket "$i - 1 chars" $i} } } ;# bind sysAfter bind sysAfter [bind sysAfter ] focus -force $w.f.text Timer $file "refresh" if {$backup(autosave) == "Yes"} { Timer $file "autosave" } };# proc EditFile proc _searchCloseBracket { widget o_bracket c_bracket start_pos end_pos } { set o_count 1 set c_count 0 set found 0 set pattern "\[\\$o_bracket\\$c_bracket\]" set pos [$widget search -regexp -- $pattern $start_pos $end_pos] while { ! [string equal $pos {}] } { set char [$widget get $pos] #tk_messageBox -title $pattern -message "char: $char; $pos; o_count=$o_count; c_count=$c_count" if {[string equal $char $o_bracket]} {incr o_count ; set found 1} if {[string equal $char $c_bracket]} {incr c_count ; set found 1} if {($found == 1) && ($o_count == $c_count) } { return [$widget index "$pos + 1 chars"] } set found 0 set start_pos "$pos + 1 chars" set pos [$widget search -regexp -- $pattern $start_pos $end_pos] } ;# while search return -1 } ;# proc _searchCloseBracket # DEDERER ## Search open bracket in editor widget proc _searchOpenBracket { widget o_bracket c_bracket start_pos end_pos } { set o_count 0 set c_count 1 set found 0 set pattern "\[\\$o_bracket\\$c_bracket\]" set pos [$widget search -backward -regexp -- $pattern "$start_pos - 1 chars" $end_pos] while { ! [string equal $pos {}] } { set char [$widget get $pos] #tk_messageBox -title $pattern -message "char: $char; $pos; o_count=$o_count; c_count=$c_count" if {[string equal $char $o_bracket]} {incr o_count ; set found 1} if {[string equal $char $c_bracket]} {incr c_count ; set found 1} if {($found == 1) && ($o_count == $c_count) } { return [$widget index "$pos + 1 chars"] } set found 0 set start_pos "$pos - 0 chars" set pos [$widget search -backward -regexp -- $pattern $start_pos $end_pos] } ;# while search return -1 } ;# proc _searchOpenBracket proc GoToLine {} { global nb files font color set node [$nb raise] if {$node == "newproj" || $node == "settings" || $node == "about" || $node == ""} { return } set file $files($node) set w $nb.f$node.goto set text "$nb.f$node.f.text" # destroy the find window if it already exists if {[winfo exists $w]} { destroy $w } # create the new "goto" window toplevel $w wm title $w [::msgcat::mc "Goto line"] wm resizable $w 0 0 wm transient $w $nb.f$node label $w.text -text [::msgcat::mc "Line number"] -font $font(normal) -background $color(bg) entry $w.entGoTo -width 6 -validate key -validatecommand "ValidNumber %W %P" pack $w.text $w.entGoTo -side left -anchor nw -padx 2 -pady 2 set line [$w.entGoTo get] bind $w.entGoTo "+GoToLineNumber $text $nb.f$node" bind $w.entGoTo "destroy $w" focus -force $w.entGoTo } ## Check input number ## proc ValidNumber {w value} { if [string is integer $value] { return 1 } else { bell return 0 } } ## GOTO LINE ## proc GoToLineNumber {text w} { global status set lineNumber [$w.goto.entGoTo get] destroy $w.goto catch { $text mark set insert $lineNumber.0 $text see insert } $status(pos) configure -text [$text index insert];# cursor position } ## SEARCH DIALOG FORM ## set findHistory "" set findString "" set replaceString "" proc Find {} { global nb files font findHistory findString color set node [$nb raise] if {$node == "newproj" || $node == "settings" || $node == "about" || $node == ""} { return } set file $files($node) set w $nb.f$node.find set text "$nb.f$node.f.text" set findString "" # destroy the find window if it already exists if {[winfo exists $w]} { destroy $w } toplevel $w wm title $w [::msgcat::mc "Find"] wm resizable $w 0 0 wm transient $w $nb.f$node frame $w.frmCombo -borderwidth 1 -background $color(bg) frame $w.frmBtn -borderwidth 1 -background $color(bg) pack $w.frmCombo $w.frmBtn -side top -fill x # set combo [entry $w.frmCombo.entFind] set combo [ComboBox $w.frmCombo.txtLocale\ -textvariable findString -background $color(bg)\ -selectbackground "#55c4d1" -selectborderwidth 0\ -values $findHistory] pack $combo -fill x -padx 2 -pady 2 button $w.frmBtn.btnFind -text "[::msgcat::mc "Find"] - F3"\ -font $font(normal) -width 12 -relief groove -background $color(bg)\ -command "FindCommand $text $w" button $w.frmBtn.btnCancel -text "[::msgcat::mc "Close"] - Esc"\ -relief groove -width 12 -font $font(normal) -background $color(bg)\ -command "destroy $w" pack $w.frmBtn.btnFind $w.frmBtn.btnCancel -fill x -padx 2 -pady 2 -side left bind $w "FindCommand $text $w" bind $w "FindCommand $text $w" bind $w "destroy $w" focus -force $combo # set findIndex [lsearch -exact $findHistory "$findString"] $combo setvalue @0 } proc FindCommand {text w} { global findString findHistory # set findString [$entry get] destroy $w # if null string? do nothing if {$findString == ""} { return } # search "again" (starting from current position) FindNext $text 0 } proc FindNext {text {incr 1}} { global findString findHistory set t $text # append find string into find history list # if {[lsearch -exact $findHistory $findString] == -1} { set findHistory [linsert $findHistory 0 $findString] } set pos [$t index insert] set line [lindex [split $pos "."] 0] set x [lindex [split $pos "."] 1] incr x $incr set pos [$t search -nocase $findString $line.$x end] # if found then move the insert cursor to that position, otherwise beep if {$pos != ""} { $t mark set insert $pos $t see $pos # highlight the found word set line [lindex [split $pos "."] 0] set x [lindex [split $pos "."] 1] set x [expr {$x + [string length $findString]}] $t tag remove sel 1.0 end $t tag add sel $pos $line.$x focus -force $t return 1 } else { bell return 0 } catch [$status(pos) configure -text [%W index insert]] ;# cursor position } ## FIND FUNCTION PROCEDURE ## proc FindProc {text findString node} { global nb status set pos "0.0" $text see $pos set line [lindex [split $pos "."] 0] set x [lindex [split $pos "."] 1] set pos [$text search -nocase $findString $line.$x end] $text mark set insert $pos $text see $pos # highlight the found word set line [lindex [split $pos "."] 0] set x [lindex [split $pos "."] 1] set x [expr {$x + [string length $findString]}] $text tag remove sel 1.0 end $text tag add sel $pos $line.$x focus -force $text catch [$status(pos) configure -text [$text index insert]] ;# cursor position return 1 } #3 REPLACE DIALOG FORM ## proc ReplaceDialog {} { global nb font files findString replaceString text color set node [$nb raise] if {$node == "newproj" || $node == "settings" || $node == "about" || $node == ""} { return } #set file $files($node) set w .replace set text "$nb.f$node.f.text" # set findString "" # destroy the find window if it already exists if {[winfo exists $w]} { destroy $w } # create the new "find" window toplevel $w wm transient $w $nb.f$node wm title $w [::msgcat::mc "Replace"] wm resizable $w 0 0 set f1 [frame $w.frmFind -background $color(bg)] set f2 [frame $w.frmReplace -background $color(bg)] set f3 [frame $w.frmBtn -borderwidth 1 -background $color(bg)] pack $f1 $f2 $f3 -side top -fill x -expand true label $f1.lblFind -text [::msgcat::mc "Find"] -font $font(normal) -width 15 -anchor w -background $color(bg) entry $f1.entFind -width 30 pack $f1.lblFind $f1.entFind -side left -padx 2 -pady 2 pack $f1.entFind -side left -fill x -expand true -padx 2 -pady 2 label $f2.lblReplace -text [::msgcat::mc "Replace with"] -font $font(normal) -width 15 -anchor w -background $color(bg) entry $f2.entReplace -width 30 pack $f2.lblReplace $f2.entReplace -side left -padx 2 -pady 2 pack $f2.entReplace -side left -fill x -expand true -padx 2 -pady 2 button $f3.btnFind -text "[::msgcat::mc "Find"] - Enter" -width 12 -pady 0 -font $font(normal) -relief groove -background $color(bg)\ -command "ReplaceCommand $text $w $f1.entFind $f2.entReplace find" button $f3.btnReplace -text "[::msgcat::mc "Replace"] - F4" -width 12 -pady 0\ -font $font(normal) -relief groove -background $color(bg)\ -command { ReplaceCommand $text $w .replace.frmFind.entFind .replace.frmReplace.entReplace replace focus -force .replace } button $f3.btnReplaceAll -text [::msgcat::mc "Replace all"] -width 12 -pady 0\ -font $font(normal) -relief groove -background $color(bg)\ -command "ReplaceCommand $text $w $f1.entFind $f2.entReplace replace_all" button $f3.btnCancel -text "[::msgcat::mc "Cancel"] - Esc" -command "destroy $w"\ -width 12 -pady 0 -font $font(normal) -relief groove -background $color(bg) pack $f3.btnFind $f3.btnReplace $f3.btnReplaceAll $f3.btnCancel\ -side left -padx 2 -pady 2 -fill x bind $w "ReplaceCommand $text $w $f1.entFind $f2.entReplace find" bind $w "ReplaceCommand $text $w $f1.entFind $f2.entReplace replace" bind $w "destroy $w" focus -force $f1.entFind if {$findString != ""} { $f1.entFind insert end $findString } if {$replaceString != ""} { $f2.entReplace insert end $replaceString } } ## REPLACE COMMAND ## proc ReplaceCommand {text w entFind entReplace command} { global nb font files findString replaceString set node [$nb raise] set findString [$entFind get] set replaceString [$entReplace get] switch -- $command { "find" { FindNext $text 1 focus -force .replace } "replace" { if {[Replace $text 0]} { FindNext $text 1 if {[lindex $files($node) 1] == 0} { set files($node) [list [lindex $files($node) 0] 1 [lindex $files($node) 2]] } focus -force .replace } } "replace_all" { set stringsReplace 0 if {[Replace $text 0]} { if {[lindex $files($node) 1] == 0} { set files($node) [list [lindex $files($node) 0] 1 [lindex $files($node) 2]] } incr stringsReplace while {[Replace $text 1]} { incr stringsReplace } } tk_messageBox -icon info -title [::msgcat::mc "Replace"]\ -parent $text -message\ "[::msgcat::mc "Was replacement"] $stringsReplace." destroy $w } } } ## REPLACE ONE WORD PROCEDURE ## proc Replace {text incr} { global nb font files findString replaceString if {[FindNext $text $incr]} { set selected [$text tag ranges sel] set start [lindex $selected 0] set end [lindex $selected 1] $text delete $start $end $text insert [$text index insert] $replaceString return 1 } else { return 0 } # focus -force .replace } ## OVERWRITE SYMBOL PROCEDURE ## proc OverWrite {} { global replace fontNormal status if {$replace == 1} { set replace 0 $status(ovwrt) configure -text [::msgcat::mc "Insert"] -foreground black } else { set replace 1 $status(ovwrt) configure -text [::msgcat::mc "Overwrite"] -foreground red } } proc ReplaceChar {text} { global replace set pos [$text index insert] set posY [lindex [split $pos "."] 0] set posX [lindex [split $pos "."] 1] if {$replace == 1} { $text delete $posY.$posX $posY.[expr $posX + 1] } } ## GET KEYS CODE ## proc Key {key} { #puts $key ;#debug if {$key >= 10 && $key <= 22} {return "true"} if {$key >= 24 && $key <= 36} {return "true"} if {$key >= 38 && $key <= 50} {return "true"} if {$key >= 51 && $key <= 61 && $key != 58} {return "true"} if {$key >= 79 && $key <= 91} {return "true"} if {$key == 63 || $key == 107 || $key == 108 || $key == 112} {return "true"} if {$key == 98 || $key == 100 || $key == 102 || $key == 104} {return "false"} } ## SPLIT EDITOR WINDOW PROCEDURE ## set split 0 proc SplitWindow {} { global color font editor nb activeFile split if [info exists activeFile] { set w $nb.f$activeFile } else { return } if {$split == 0} { frame $w.f1 -borderwidth 2 -relief ridge pack $w.f1 -side top -fill both -expand true #supertext::text supertext::text $w.f1.text -yscrollcommand "$w.f1.yscroll set" \ -relief sunken -wrap $editor(wrap) -highlightthickness 0 -font $font(editNormal)\ -background $color(editBg) -foreground $color(editFg)\ -selectborderwidth 0 -selectbackground $color(selectbg) -width 10 scrollbar $w.f1.yscroll -relief sunken -borderwidth {1} -width {10} -takefocus 0 \ -command "$w.f1.text yview" pack $w.f1.text -side left -fill both -expand true pack $w.f1.yscroll -side left -fill y ############################################## pane::create $w.f $w.f1 -orient horizontal -percent 0.5 set split 1 } elseif {$split == 1} { destroy $w.f1 } }