home *** CD-ROM | disk | FTP | other *** search
- #############################################################################
- #############################################################################
- #
- # latexEngine.tcl (called from latex.tcl)
- #
- # The LaTeX engine
- #
- #############################################################################
- #
- # Author: Tom Scavo (trscavo@syr.edu)
- #
- #############################################################################
- #############################################################################
-
-
- #--------------------------------------------------------------------------
- # Mark Menu:
- #--------------------------------------------------------------------------
-
- proc TeXMarkFile {} {
- set end [maxPos]
- set pos 0
- set l {}
-
- # Remove all previous marks in this file?
- set exp {\\((sub)*section|chapter)(\[.*\]|\*)?{([^{}]*)}}
- while {![catch {search -s -f 1 -r 1 -m 0 -i 0 $exp $pos} res]} {
- set start [lindex $res 0]
- set end [lindex $res 1]
- set text [getText $start $end]
- if {[regexp {\{(.*)\}} $text dummy mtch]} {
- set lab ""
- if {[regexp {(sub)*section} $text title]} then {
- append lab $l [format "%[expr [string length $title] - 7]\s" ""]
- } else {
- set l { }
- }
- # WTP
- regsub -all "\[\ \r\t\]\+" $mtch { } mtch
- if {[string length $mtch] > 30} { set mtch "[string range $mtch 0 26]..." }
- #
- append lab $mtch
- regsub -all {[<(]} $lab {} lab
- regsub -all {[)>]} $lab {╚} lab
- regsub -all {[!^/]} $lab {|} lab
- setNamedMark $lab [lineStart [expr $start - 1]] $start $start
- }
- set pos [expr $end+1]
- }
- }
-
- #--------------------------------------------------------------------------
- # Command-double-clicking:
- #--------------------------------------------------------------------------
- # In TeX mode, use Cmd-double-clicks to follow references and citations,
- # or open input files.
- #
- # (written by Tom Pollard and Andreas Amann)
- #
- # Remaining bugs:
- # - searches are successful even if the pattern is commented out
-
- proc TeXDblClick {from to} {
- global TeXmodeVars TeXSearchPath
-
- # Reset the search path list, forcing it to be rebuilt.
- # (It would improve responsiveness if the searchPath were only
- # rebuilt as needed, perhaps at startup and when requested by the user.)
- #
- set TeXSearchPath {}
-
- set bibPat "\\bibliography\{"
- set theBibPat "\\begin\{thebibliography"
- set bibitemPat {\bibitem(\[[^\]*\])?\{}
- set labelPat "\\label\{"
- set bibTopPat {@([a-zA-Z]+)[\{\(][ ]*}
-
- # Extend selection to largest string delimited by commas or curly-braces
- set text [string trim [eval getText [TeXExtendArg $from $to]]]
-
- # Quote regexp-active characters in case we use $text in a regexp search
- set qtext [quoteExpr $text]
-
- # Set $cmd to TeX command for which the selection is an argument, but
- # only if user clicked on a valid command argument.
- set cmd {}
- if {[set mtch [findCommandWithParts $from 0]] != ""} {
- set beg [lindex $mtch 0]
- set arg [lindex $mtch 2]
- set end [lindex $mtch 3]
- # Make sure the user clicked within a TeX argument and not
- # on the command name itself
- if {$from > $arg && $to < $end} {
- set cmd [extractCommandName [getText $beg $arg]]
- }
- }
-
- # \cite, \nocite, etc.
- #
- if {[lsearch -exact $TeXmodeVars(citeCommands) $cmd] >= 0} {
-
- # Check first for a \thebibliography environment...
- if {![catch {search -f 0 -r 0 -m 0 -s $theBibPat [maxPos]} mtch]} {
- set bibPos [lindex $mtch 1]
- if {![catch {search -f 1 -r 1 -m 0 -s "$bibitemPat$qtext\}" $bibPos} mtch]} {
- pushMark
- eval select $mtch
- message "press <Ctl .> to return to original cursor position"
- return
- }
- }
-
- # ...otherwise get the bib file name(s) from a \bibliography command
- if {![catch {search -f 0 -r 0 -s -m 0 $bibPat [maxPos]} mtch]} {
- # Get ALL the bib file names
- set beg [lindex $mtch 1]
- set end [matchIt "\{" $beg]
- set fnames "[split [getText $beg $end] ,]"
- # Check every file
- foreach fname $fnames {
- set filename [absolutePath "$fname.bib"]
- if {[set pos [searchInFile $filename $bibTopPat$qtext]] >= 0} {
- openFileQuietly $filename
- goto $pos
- return
- }
- }
- if {[llength $TeXSearchPath] == 0} {
- set TeXSearchPath [buildTeXSearchPath]
- }
- foreach fname $fnames {
- foreach folder $TeXSearchPath {
- set filename "$folder$fname.bib"
- if {[set pos [searchInFile $filename $bibTopPat$qtext]] >= 0} {
- openFileQuietly $filename
- goto $pos
- return
- }
- }
- }
- beep
- message "can't find \"$text\" in the .bib file(s)"
-
- } else {
- beep
- message "can't find a \\bibliography"
- }
-
- # \ref, \pageref, etc.
- } elseif {[lsearch -exact $TeXmodeVars(refCommands) $cmd] >= 0} {
- if {![catch {search -f 1 -r 0 -m 0 -s "$labelPat$text\}" 0} mtch]} {
- pushMark
- eval select $mtch
- message "press <Ctl .> to return to original cursor position"
- } else {
- message {No matching \label found}
- }
-
- # \input
- } elseif { $cmd == "input" } {
- openTeXFile $text ".tex"
-
- # \include
- } elseif { $cmd == "include" } {
- openTeXFile "${text}.tex"
-
- # \documentclass or \LoadClass
- } elseif { $cmd == "documentclass" || $cmd == "LoadClass" } {
- openTeXFile "${text}.cls"
-
- # \usepackage or \RequirePackage
- } elseif { $cmd == "usepackage" || $cmd == "RequirePackage" } {
- openTeXFile "${text}.sty"
-
- # \bibliography
- } elseif {$cmd == "bibliography"} {
- openTeXFile "${text}.bib"
-
- # \bibliographystyle
- } elseif {$cmd == "bibliographystyle"} {
- openTeXFile "${text}.bst"
-
- # box-making macro ($boxMacroName)
- } elseif {$cmd == $TeXmodeVars(boxMacroName)} {
- openTeXFile $text
-
- # Other
- } else {
- select $from $to
- message {Command-double-click on the required argument of an underlined LaTeX command}
- }
- }
-
- # Open a TeX source file.
- #
- proc openTeXFile {file {ext ""}} {
- global TeXSearchPath
- # Determine absolute file specification
- # Ignore $ext if $file already has an extension
- if {[string length [file extension $file]] == 0} {
- set file $file$ext
- }
- set filename [absolutePath $file]
- if {![catch {openFileQuietly $filename}]} {
- message $filename
- return
- }
- if {[llength $TeXSearchPath] == 0} {
- set TeXSearchPath [buildTeXSearchPath]
- }
- foreach folder $TeXSearchPath {
- set filename "$folder$file$ext"
- if {![catch {openFileQuietly $filename}]} {
- message $filename
- return
- }
- }
- beep
- message "can't find TeX input file \"$file\""
- }
-
- # Return a list of folders in which to search for TeX input files,
- # including the TeXInputs folder (if it exists) and any folders of
- # the form "*input*" in the TeX application directory. The current
- # folder is not included in the list.
- #
- # (The TeXInputs folder is assigned from the AppPaths submenu.)
- #
- proc buildTeXSearchPath {} {
- global TeXInputs texPath
- message "building TeX search path..."
- set folders {}
-
- # The local 'TeXInputs' folder:
- if {[info exists TeXInputs] && [string length $TeXInputs] > 0} {
- set folders [concat $folders [list $TeXInputs]]
- # Search subfolders one level deep:
- set folders [concat $folders [listSubfolders $TeXInputs 1]]
- }
-
- # Any "*inputs*" folders in the TeX application folder:
- if {[info exists texPath] && [string length $texPath] > 0} {
- set TeXDir [file dirname $texPath]
- set folders [concat $folders [list $TeXDir]]
- # Bug: 'glob' is case sensitive!
- foreach folder [glob "$TeXDir:*\[Ii\]nputs*"] {
- set folders [concat $folders [list $folder]]
- # Search subfolders one level deep:
- set folders [concat $folders [listSubfolders $folder 1]]
- }
- }
-
- # Make sure each folder ends with a colon
- set result {}
- foreach folder $folders {
- set folder "[string trimright $folder {:}]:"
- set result [concat $result [list $folder]]
- }
- return $result
- }
-
-
- # Extend the argument around the position $from.
- # (Args are delimited by commas or curly-braces.)
- proc TeXExtendArg {from {to 0}} {
- if {$to == 0} { set to $from }
- set result [list $from $to]
- if {![catch {search -f 0 -r 1 -s -m 0 "\[,\{\]" $from} mtch0]} {
- if {![catch {search -f 1 -r 1 -s -m 0 "\[,\}\]" $to} mtch1]} {
- set from [lindex $mtch0 1]
- set to [lindex $mtch1 0]
- ## Embedded braces in the arg probably mean that the user
- ## clicked outside a valid command argument
- if {[regexp "\[\{\}\]" [getText $from $to]] == 0} {
- set result [list $from $to]
- }
- }
- }
- return $result
- }
-
- # Find a LaTeX command with arguments in either direction.
- # (see findCommandWithArgs in latexMacros.tcl)
- # This version returns the positions at which the command options
- # and arguments start, as well.
- proc findCommandWithParts {pos direction} {
- set searchString {\\([^a-zA-Z\t\r]|[a-zA-Z]+\*?)(\[.*\])*({[^{}]*})?}
- if {![catch {search -s -f $direction -r 1 $searchString $pos} mtch]} {
- set beg [lindex $mtch 0]
- set end [lindex $mtch 1]
- regexp -indices $searchString [getText $beg $end] all cmd opt arg
- set opt [expr $beg + [lindex $opt 0]]
- set arg [expr $beg + [lindex $arg 0]]
- return [list $beg $opt $arg $end]
- } else {
- return ""
- }
- }
-
- #--------------------------------------------------------------------------
- # Insertion routines:
- #--------------------------------------------------------------------------
-
- # Returns a modified text string if the string $text is non-null,
- # and the null string otherwise. The argument 'operation' is a
- # string directing 'doPrefixText' to either "insert" or "remove"
- # $prefixString to/from each line of $text. (This routine is
- # adapted from strings.tcl.)
- proc doPrefixText {operation prefixString text} {
- if {$text == ""} {return ""}
- set pref [quoteExpr $prefixString]
- if {$operation == "insert"} then {
- set trailChar ""
- set textLen [string length $text]
- if {[string index $text [expr $textLen-1]] == "\r"} then {
- set text [string range $text 0 [expr $textLen-2]]
- set trailChar "\r"
- }
- set str \r$prefixString
- regsub -all \r $text $str text
- return $prefixString$text$trailChar
- } elseif {$operation == "remove"} then {
- regsub -all \r$pref $text \r text
- regsub ^$pref $text "" text
- return $text
- }
- }
-
- # Shift each line of $text to the right by inserting a string of
- # $whitespace characters at the beginning of each line, returning
- # the resulting string.
- proc shiftTextRight {text whitespace} {
- return [doPrefixText "insert" $whitespace $text]
- }
-
- # Return a string of whitespace characters from the beginning
- # of the line containing $pos up to the first non-whitespace
- # character.
- proc getIndentation {pos} {
- set text [getText [lineStart $pos] [nextLineStart $pos]]
- regexp {^[ \t]*} $text theIndentation
- return $theIndentation
- }
-
- # Return an "indented carriage return" if any character preceding
- # the insertion point (on the same line) is a non-whitespace
- # character. Otherwise, return the null string.
- proc openingCarriageReturn {} {
- set pos [getPos]
- set end $pos
- set start [lineStart $pos]
- set text [getText $start $end]
- if {[isWhitespace $text]} then {
- if {$start == $end} {return [getIndentation $pos]} {return ""}
- } else {
- return "\r[getIndentation $pos]"
- }
- }
- # Return an "indented carriage return" if any character following
- # the insertion point (on the same line) is a non-whitespace
- # character. Otherwise, return the null string.
- proc closingCarriageReturn {} {
- set pos [selEnd]
- if {[isSelection] && ($pos == [lineStart $pos])} then {
- return "\r"
- } else {
- set start $pos
- set end [nextLineStart $start]
- set text [getText $start $end]
- if {[isWhitespace $text]} then {
- return ""
- } else {
- return "\r[getIndentation $pos]"
- }
- }
- }
-
- # Insert an object at the insertion point. If there is a selection and the
- # global variable 'deleteObjectNoisily' is false, quietly delete the selection
- # (like 'paste'). Otherwise, prompt the user for the appropriate action.
- # Returns true if the object is ultimately inserted, and false if the
- # user cancels the operation.
- proc insertObject {objectName} {
- global TeXmodeVars
- # if {$TeXmodeVars(expertMode) == 0} then {
- # if {![isInDocument]} then {
- # if {$TeXmodeVars(searchNoisily)} {beep}
- # case [askyesno "The cursor is not in the document environment.\
- # \rContinue the operation?"] in {
- # "yes" {}
- # "no" {error "insertObject: out of context"}
- # }
- # }
- # }
- if {[isSelection]} then {
- if {$TeXmodeVars(deleteObjectNoisily)} then {
- case [askyesno -c "Delete selection?"] in {
- "yes" {deleteText [getPos] [selEnd]}
- "no" {backwardChar}
- "cancel" {return 0}
- }
- } else {
- deleteText [getPos] [selEnd]
- }
- }
- insertText $objectName
- return 1
- }
-
- # Insert an object at the insertion point. If there is a selection, wrap
- # it inside the parameters $left and $right. Returns true if there is a
- # selection (in which case it will wrap), and false otherwise.
- proc wrapObject {left right} {
- # global TeXmodeVars
- # if {$TeXmodeVars(expertMode) == 0} then {
- # if {![isInDocument]} then {
- # if {$TeXmodeVars(searchNoisily)} {beep}
- # case [askyesno "The cursor is not in the document environment.\
- # \rContinue the operation?"] in {
- # "yes" {}
- # "no" {error "wrapObject: out of context"}
- # }
- # }
- # }
- set currentPos [getPos]
- set selected [isSelection]
- if {$selected} then {
- replaceText $currentPos [selEnd] $left [getSelect] $right
- } else {
- insertText $left "Ñ" $right
- }
- goto $currentPos
- nextTabStop
- return $selected
- }
-
- # Builds and returns a LaTeX environment, that is, a \begin...\end
- # pair, given the name of the environment, an argument string,
- # and the environment body. The body should be passed to this
- # procedure fully formatted, including indentation.
- proc buildEnvironment {envName envArg envBody trailingComment} {
- set indent [getIndentation [getPos]]
- set envStr [openingCarriageReturn]
- append envStr "\\begin{" $envName "}"
- append envStr $envArg "\r"
- append envStr $envBody
- append envStr $indent "\\end{" $envName "}$trailingComment"
- append envStr [closingCarriageReturn]
- return $envStr
- }
-
- # Inserts a LaTeX environment with the specified name, argument,
- # and body at the insertion point. Positions the cursor at the
- # beginning of the environment, leaving any subsequent action to the
- # calling procedure. Deletes the current selection quietly if the
- # global variable 'deleteEnvironmentNoisily' is false; otherwise
- # the user is prompted for directions. Returns true if the
- # environment is ultimately inserted, and false if the user cancels
- # the operation.
- proc insertEnvironment {envName envArg envBody} {
- global TeXmodeVars
- # if {$TeXmodeVars(expertMode) == 0} then {
- # if {![isInDocument]} then {
- # if {$TeXmodeVars(searchNoisily)} {beep}
- # case [askyesno "The cursor is not in the document environment.\
- # \rContinue the operation?"] in {
- # "yes" {}
- # "no" {error "insertEnvironment: out of context"}
- # }
- # }
- # }
- if {[isSelection]} then {
- if {$TeXmodeVars(deleteEnvironmentNoisily)} then {
- case [askyesno -c "Delete selection?"] in {
- "yes" {}
- "no" {backwardChar}
- "cancel" {return 0}
- }
- }
- }
- set start [getPos]
- set end [selEnd]
- set body [shiftTextRight $envBody [getIndentation $start]]
- replaceText $start $end [buildEnvironment $envName $envArg $body "Ñ"]
- goto $start
- return 1
- }
-
- # Inserts an environment with the given name, argument, and body at
- # the insertion point. Positions the cursor at the beginning of
- # the environment, leaving any subsequent action to the calling
- # procedure. If there is currently a selection, cut and paste it
- # into the body of the new environment, maintaining proper
- # indentation; otherwise, insert a tab stop into the body of the
- # environment. Returns true if there is a selection, and false
- # otherwise.
- proc wrapEnvironment {envName envArg envBody} {
- # global TeXmodeVars
- # if {$TeXmodeVars(expertMode) == 0} then {
- # if {![isInDocument]} then {
- # if {$TeXmodeVars(searchNoisily)} {beep}
- # case [askyesno "The cursor is not in the document environment.\
- # \rContinue the operation?"] in {
- # "yes" {}
- # "no" {error "wrapEnvironment: out of context"}
- # }
- # }
- # }
- set start [getPos]
- set end [selEnd]
- set indent [getIndentation $start]
- if {[isSelection]} then {
- set text [getSelect]
- set textLen [string length $text]
- if {[string index $text [expr $textLen-1]] != "\r"} then {
- append text "\r"
- }
- if {$start == [lineStart $start]} then {
- set body [shiftTextRight $text \t]
- } else {
- set body "$indent[shiftTextRight $text \t]"
- }
- append body [shiftTextRight $envBody $indent]
- set environment [buildEnvironment $envName $envArg $body "Ñ"]
- set returnFlag 1
- } else {
- append body "$indent\tÑ\r" [shiftTextRight $envBody $indent]
- set environment [buildEnvironment $envName $envArg $body "Ñ"]
- set returnFlag 0
- }
- replaceText $start $end $environment
- goto $start
- return $returnFlag
- }
-
- # A generic call to 'wrapEnvironment' used throughout latex.tcl:
- proc doWrapEnvironment {envName} {
- if {[wrapEnvironment $envName "" ""]} then {
- set msgText "selection wrapped"
- } else {
- set msgText "enter body of $envName environment"
- }
- nextTabStop
- message $msgText
- }
-
- # Inserts a structured document template at the insertion point.
- # Three arguments are required: the class name of the document, a
- # preamble string, and a string containing the body of the document.
- # If the preamble is null, a generic \usepackage statement is
- # inserted; otherwise, the preamble is inserted as is. This routine
- # does absolutely no error-checking (this is totally left up to the
- # calling procedure) and returns nothing.
- proc insertDocument {className preamble docBody} {
- set docStr "\\documentclass\[Ñ\]{$className}\r"
- if {$preamble == ""} then {
- append docStr "\\usepackage\[Ñ\]{Ñ}\r\rÑ\r\r"
- } else {
- append docStr $preamble
- }
- append docStr [buildEnvironment "document" "" $docBody "\r"]
- set start [getPos]
- set end [selEnd]
- replaceText $start $end $docStr
- goto $start
- return
- }
-
- # Inserts a document template at the insertion point given the
- # class name of the document to be inserted. If ALL of the current
- # document is selected, then the routine wraps the text inside a
- # generic document template. If the file is empty, a bullet is
- # inserted in place of the document body. If neither of these
- # conditions is true, an alert is displayed, and no action is taken.
- # Returns true if wrapping occurs, and false otherwise.
- proc wrapDocument {className} {
- if {[isEmptyFile]} then {
- append body "\rÑ\r\r"
- set returnFlag 0
- } else {
- if {[isDocumentSelected]} then {
- set text [getSelect]
- append body "\r$text\r"
- set returnFlag 1
- } else {
- alertnote "nonempty file: delete text or \'Select All\'\
- from the Edit menu"
- return 0
- }
- }
- set docStr "\\documentclass\[Ñ\]{$className}\r"
- append docStr "\\usepackage\[Ñ\]{Ñ}\r\rÑ\r\r"
- append docStr [buildEnvironment "document" "" $body "\r"]
- set start [getPos]
- set end [selEnd]
- replaceText $start $end $docStr
- goto $start
- nextTabStop
- message "enter style (or leave blank)"
- return $returnFlag
- }
-
- #--------------------------------------------------------------------------
- # Booleans to determine the location of the insertion point
- #--------------------------------------------------------------------------
-
- # Return true if the insertion point is before the preamble, and
- # false otherwise. Define "before the preamble" to be all text to
- # the left of "\" in "\documentclass".
- proc isBeforePreamble {} {
- set searchString "\\documentclass"
- set searchResult [search -s -f 1 -r 0 -n $searchString [getPos]]
- if {[llength $searchResult]} {
- return 1
- } else {
- return 0
- }
- }
-
- # Return true if the insertion point is in the preamble, and false
- # otherwise. Define "preamble" to be all text to the left of "\"
- # in "\begin{document}", but not before the "\" in "\documentclass".
- proc isInPreamble {} {
- set searchString "\\begin\{document\}"
- set searchResult [search -s -f 1 -r 0 -n $searchString [getPos]]
- if {[llength $searchResult]} {
- return 1
- } else {
- return 0
- }
- }
-
- # Return true if the insertion point is in the document environment,
- # and false otherwise. Define "document" to be all text between
- # "\begin{document}" and "\end{document}", inclusive.
- proc isInDocument {} {
- set pos [getPos]
- if {$pos == 0} then {return 0}
- set searchString "\\begin\{document\}"
- set searchResult [search -s -f 0 -r 0 -n $searchString [expr $pos - 1]]
- if {[llength $searchResult]} then {
- set searchString "\\end\{document\}"
- # adjust for the length of the search string:
- set len [string length $searchString]
- set searchResult [search -s -f 1 -r 0 -n $searchString [expr $pos - $len + 1]]
- if {[llength $searchResult]} then {
- return 1
- } else {
- return 0
- }
- } else {
- return 0
- }
- }
-
- # Return true if the insertion point is after the document
- # environment, and false otherwise. Define "after the document
- # environment" to be all text to the right of "}" in "\end{document}".
- proc isAfterDocument {} {
- set pos [getPos]
- set searchString "\\end\{document\}"
- set searchResult [search -s -f 0 -r 0 -n $searchString $pos]
- if {[llength $searchResult]} {
- set pos1 [lindex $searchResult 0]
- set pos2 [lindex $searchResult 1]
- if {$pos1 <= $pos && $pos < $pos2} then {
- return 0
- } else {
- return 1
- }
- } else {
- return 0
- }
- }
-
- proc isInMathMode {} {
- set pos [getPos]
- # Check to see if in LaTeX math mode:
- set searchString {\\[()]}
- set searchResult1 [search -s -f 0 -r 1 -n $searchString [expr $pos - 1]]
- if {[llength $searchResult1]} then {
- set delim1 [eval getText $searchResult1]
- } else {
- set delim1 "none"
- }
- set searchResult2 [search -s -f 1 -r 1 -n $searchString $pos]
- if {[llength $searchResult2]} then {
- set delim2 [eval getText $searchResult2]
- } else {
- set delim2 "none"
- }
- set flag1 [expr [string match {none} $delim1] && [string match {\\)} $delim2]]
- set flag2 [expr [string match {\\(} $delim1] && [string match {none} $delim2]]
- set flag3 [expr [string match {\\(} $delim1] && [string match {\\)} $delim2]]
- set flag4 [expr [string match {\\(} $delim1] && [string match {\\(} $delim2]]
- set flag5 [expr [string match {\\)} $delim1] && [string match {\\)} $delim2]]
- if {$flag3} then {
- return 1
- } elseif {$flag1 || $flag2 || $flag4 || $flag5} then {
- set messageString "unbalanced math mode delimiters"
- beep
- alertnote $messageString
- error "isInMathMode: $messageString"
- }
- # Check to see if in LaTeX displaymath mode:
- set searchString {[^\\]\\\[|\\\]}
- set searchResult1 [search -s -f 0 -r 1 -n $searchString [expr $pos - 1]]
- if {[llength $searchResult1]} then {
- set begPos [lindex $searchResult1 0]
- set endPos [lindex $searchResult1 1]
- if {[lookAt [expr $endPos - 1]] == "\["} then {
- set delim1 [getText [expr $begPos + 1] $endPos]
- } else {
- set delim1 [eval getText $searchResult1]
- }
- } else {
- set delim1 "none"
- }
- set searchResult2 [search -s -f 1 -r 1 -n $searchString $pos]
- if {[llength $searchResult2]} then {
- set begPos [lindex $searchResult2 0]
- set endPos [lindex $searchResult2 1]
- if {[lookAt [expr $endPos - 1]] == "\["} then {
- set delim2 [getText [expr $begPos + 1] $endPos]
- } else {
- set delim2 [eval getText $searchResult2]
- }
- } else {
- set delim2 "none"
- }
- set flag1 [expr [string match {none} $delim1] && [string match {\\\]} $delim2]]
- set flag2 [expr [string match {\\\[} $delim1] && [string match {none} $delim2]]
- set flag3 [expr [string match {\\\[} $delim1] && [string match {\\\]} $delim2]]
- set flag4 [expr [string match {\\\[} $delim1] && [string match {\\\[} $delim2]]
- set flag5 [expr [string match {\\\]} $delim1] && [string match {\\\]} $delim2]]
- if {$flag3} then {
- return 1
- } elseif {$flag1 || $flag2 || $flag4 || $flag5} then {
- set messageString "unbalanced math mode delimiters"
- beep
- alertnote $messageString
- error "isInMathMode: $messageString"
- }
- # Check to see if in math environment:
- set envName [extractCommandArg [eval getText [searchEnvironment]]]
- set envList [list "math" "displaymath" "equation" "eqnarray" "eqnarray*" "array"]
- if {[lsearch -exact $envList $envName] == -1} {return 0} {return 1}
- }
-
- #--------------------------------------------------------------------------
- # Routines to dissect LaTeX commands
- #--------------------------------------------------------------------------
-
- # Given a LaTeX command string, extract and return the command name.
- proc extractCommandName {commandStr} {
- if {[regexp {\\([^a-zA-Z\t\r]|[a-zA-Z]+\*?)} $commandStr dummy commandName]} then {
- return $commandName
- } else {
- return ""
- }
- }
-
- # Given a LaTeX command string with at most one required argument and
- # no embedded carriage returns, extract and return the argument.
- # (Note: this proc needs more testing.)
- proc extractCommandArg {commandStr} {
- if {[regexp {\{(.*)\}} $commandStr dummy arg]} then {
- return $arg
- } else {
- return ""
- }
- }
-
- #--------------------------------------------------------------------------
- # An environment search routine
- #--------------------------------------------------------------------------
-
- # Search for the closest surrounding environment and return a list
- # of two positions if the environment is found; otherwise return the
- # empty list. Assumes the LaTeX document is syntactically correct.
- # The command 'eval select [searchEnvironment]' selects the "\begin"
- # statement (with argument) of the surrounding environment.
- proc searchEnvironment {} {
- watchCursor
- set pos [getPos]
- if {$pos == 0} {
- return [list]
- }
- # adjust position if insertion point is contained in "\end{...}"
- set searchPos [expr $pos - 1]
- set searchString {\\end\{[^\{\}]*\}}
- set searchResult [search -s -f 0 -r 1 -n $searchString $searchPos]
- if {[llength $searchResult]} {
- set pos1 [lindex $searchResult 0]
- set pos2 [lindex $searchResult 1]
- if {$pos1 < $pos && $pos < $pos2} then {
- set searchPos [expr $pos1 - 1]
- }
- }
- # begin reverse search:
- set searchString {\\(begin|end)\{[^\{\}]*\}}
- set searchResult [search -s -f 0 -r 1 -n $searchString $searchPos]
- if {[llength $searchResult]} {
- # set text [getText [lindex $searchResult 0] [lindex $searchResult 1]]
- set text [eval getText $searchResult]
- } else {
- return [list]
- }
- set depthCounter 0
- set commandName [extractCommandName $text]
- while {$commandName == "end" || $depthCounter > 0} {
- if {$commandName == "end"} {
- set depthCounter [expr $depthCounter + 1]
- } else {
- set depthCounter [expr $depthCounter - 1]
- }
- set searchPos [expr [lindex $searchResult 0] - 1]
- set searchResult [search -s -f 0 -r 1 -n $searchString $searchPos]
- if {[llength $searchResult]} {
- # set text [getText [lindex $searchResult 0] [lindex $searchResult 1]]
- set text [eval getText $searchResult]
- } else {
- return [list]
- }
- set commandName [extractCommandName $text]
- }
- return $searchResult
- }
-
- #--------------------------------------------------------------------------
- # Misc:
- #--------------------------------------------------------------------------
-
- proc isInteger {str1} {
- if { [regexp {(\+|-)?[0-9]+} $str1 str2] } then {
- if {![string compare $str1 $str2]} {return 1} {return 0}
- } else {
- return 0
- }
- }
-
- proc isUnsignedInteger {str1} {
- if { [regexp {[0-9]+} $str1 str2] } then {
- if {![string compare $str1 $str2]} {return 1} {return 0}
- } else {
- return 0
- }
- }
-
- # Checks to see if there is a current selection.
- proc isSelection {} {
- return [string length [getSelect]]
- }
- # proc isSelection {} {
- # return [string length [getSelect]]
- # }
-
- # Checks to see if the current window is empty, sans whitespace.
- proc isEmptyFile {} {
- return [isWhitespace [getText 0 [maxPos]]]
- }
-
- # If there is a selection, make sure it's uppercase. Otherwise,
- # check to see if the character after the insertion point is uppercase.
- proc isUppercase {} {
- if {[isSelection]} then {
- set text [getSelect]
- } else {
- set text [lookAt [getPos]]
- }
- return [expr {[string toupper $text] == $text}]
- }
-
- # Returns true if the entire window is selected, and false otherwise.
- proc isDocumentSelected {} {
- return [expr {([getPos] == 0) && ([selEnd] == [maxPos])}]
- }
-
- # Takes any string and tests whether or not that string contains all
- # whitespace characters. Carriage returns are considered whitespace,
- # as are spaces and tabs. Also returns true for the null string.
- proc isWhitespace {anyString} {
- set len [string length $anyString]
- for {set i 0} {$i < $len} {incr i} {
- set c [string index $anyString $i]
- if {($c != "\ ") && ($c != "\t") && ($c != "\r")} then {return 0}
- }
- return 1
- }
-
- # Select the line containing the insertion point.
- proc lineSelect {} {
- goto [lineStart [getPos]]
- nextLineSelect
- }
-
- proc checkMathMode {procName mathModeFlag} {
- # global TeXmodeVars
- # if {$TeXmodeVars(expertMode) == 0} then {
- # if {[isInDocument] && [isInMathMode] != $mathModeFlag} then {
- # if {$TeXmodeVars(searchNoisily)} {beep}
- # if {$mathModeFlag} then {
- # set messageString "You are not in math mode"
- # } else {
- # set messageString "You are already in math mode"
- # }
- # case [askyesno "$messageString.\rContinue the operation?"] in {
- # "yes" {}
- # "no" {error "$procName: out of context"}
- # }
- # }
- # }
- }
-
- # Check to see if the LaTeX symbol package has been loaded; if not, ask
- # the user for directions. Returns false if the package is not loaded
- # AND the user cancels the operation; otherwise, returns true.
- proc isSymbolPackageLoaded {} {
- global searchNoisily
- set begPos [getPos]
- set endPos [selEnd]
- set searchString {\\usepackage\{.*latexsym.*\}}
- set searchResult [search -s -n -f 0 -m 0 -i 1 -r 1 $searchString $begPos]
- if {[llength $searchResult] == 0} then {
- case [askyesno -c "Insert the LaTeX symbol package?"] in {
- "yes" {
- set searchString {\\documentclass(\[.*\])?\{.*\}}
- set searchResult [search -s -n -f 0 -m 0 -i 1 -r 1 $searchString $begPos]
- if {[llength $searchResult] == 0} then {
- set returnVal 0
- if {$searchNoisily} {beep}
- message "can't find \\documentclass"
- } else {
- goto [lindex $searchResult 1]
- set txt "\r\\usepackage\{latexsym\}"
- set offset [string length $txt]
- set begPos [expr $begPos + $offset]
- set endPos [expr $endPos + $offset]
- insertText $txt
- set returnVal 1
- }
- }
- "no" {set returnVal 1}
- "cancel" {set returnVal 0}
- }
- } else {
- set returnVal 1
- }
- select $begPos $endPos
- return $returnVal
- }
-
-
-