home *** CD-ROM | disk | FTP | other *** search
/ Internet File Formats / InternetFileFormatsCD.bin / text / latex / mac / alpha60.hqx / Tcl / SystemCode / procs.tcl < prev    next >
Encoding:
Text File  |  1995-07-14  |  23.0 KB  |  929 lines

  1.  
  2. #==============================================================================
  3. # Load electric alias, rebind tcl file completion for precedence.
  4. proc loadElectricAlias {} {
  5.     global HOME
  6.     uplevel #0 {
  7.         source "$HOME:Tcl:ElectricAlias:electricAlias.tcl"
  8.     }
  9.     message "ElectricAlias loaded."
  10.     bind '\t' tclFileCompletion "Shel"
  11.     enableMenuItem -m install "Electric Alias" off
  12. }
  13.  
  14. proc debug {} {
  15.     uplevel #0 {
  16.         set debugging 1
  17.     }
  18. }
  19.  
  20.  
  21. proc normalLeftBracket {} {
  22.     insertText "\{"
  23. }
  24. proc normalRightBracket {} {
  25.     insertText "\}"
  26. }
  27. bind '\[' <zs>  normalLeftBracket
  28. bind '\]' <zs>  normalRightBracket
  29.             
  30. # Select the next or current word. If word already selected, will go to next.
  31. proc hiliteWord {} {
  32.     if {[getPos]!=[selEnd]}    forwardChar
  33.     forwardWord
  34.     set start [getPos]
  35.     backwardWord
  36.     select $start [getPos]
  37. }
  38.  
  39. bind 'h' <z> hiliteWord
  40.  
  41. #================================================================================
  42. # Mode variables
  43. #================================================================================
  44. # For mark stack.
  45. set markName 0
  46. set markStack ""
  47.  
  48. # mapping of windows to current modes.
  49. set winModes("") ""
  50.  
  51. # making vars local to windows
  52. # 'incomingVars' used to hold old var values that have been overwritten in current window
  53.  
  54. #================================================================================
  55. # Handle 'flag' and 'var' menu selections.
  56. #================================================================================
  57. proc editFlag {menu item} {
  58.     global $item incomingVars localVars modifiedVars
  59.  
  60.     if {[regexp {\? (.*)} $item dummy var]} {
  61.         alphaHelp
  62.         eval select [search -f 1 -r 1 "^$var"]
  63.         return
  64.     }
  65.     lappend modifiedVars $item
  66.     set val [expr ([set $item]-1)*-1]
  67.     markMenuItem $menu $item [expr ($val)?"on":"off"]
  68.     set $item $val
  69.  
  70. }
  71.  
  72. proc editVar {menu item} {
  73.     global $item incomingVars localVars modifiedVars
  74.  
  75.     if {[regexp {\? (.*)} $item dummy var]} {
  76.         alphaHelp
  77.         eval select [search -f 1 -r 1 "^$var"]
  78.         return
  79.     }
  80.     lappend modifiedVars $item
  81.     append prmpt "New Value of " $item ": "
  82.     if ![catch {prompt $prmpt [set $item]} res] {
  83.         set $item $res
  84.     }
  85. }
  86.  
  87.  
  88.  
  89.  
  90. #================================================================================
  91.  
  92. # Instantiate a global variable to the path of a file (usually an app). As a
  93. # side-effect, make the instantiation permanent.
  94. proc addAppPath {name var} {
  95.     global $var modifiedVars
  96.     
  97.     set $var [getfile "Find '$name' app:"]
  98.     lappend modifiedVars $var
  99. }
  100.  
  101.  
  102. proc getFileSig {f} {
  103.     getFileInfo $f arr
  104.     return $arr(creator)
  105. }
  106.  
  107. proc getFileType {f} {
  108.     getFileInfo $f arr
  109.     return $arr(type)
  110. }
  111.  
  112.  
  113. # Look for given app sig in active processes. If not there, try to 
  114. # launch with 'path' prompting for 'path' if necessary.
  115. # Return the real name of the app. Don't switch.
  116.  
  117. # Slightly modified version of 'checkRunning' that looks for any of a
  118. # list of running apps.  The name of the app is returned. 
  119. proc checkRunning {prompt sigs path {in_front 1}} {
  120.     global $path
  121.  
  122.     # See if a process w/ any of the acceptable sigs already running.
  123.     # If so, use it, whether it's the one specified by $path or not.
  124.     #
  125.     foreach proc [processes] {
  126.         # if a running app has the correct sig, ...
  127.         if {[lsearch -exact $sigs [lindex $proc 1]] >= 0} {
  128.             # ...then return its name.
  129.             return [lindex $proc 0]
  130.         }
  131.     }
  132.  
  133.     # If the path variable or the file it references don't exist,
  134.     # or if its sig isn't one that we expect, then prompt the user 
  135.     # to locate the app.
  136.     #
  137.     if {![info exists $path] || ![file exists [set $path]] 
  138.              || [lsearch -exact $sigs [getFileSig [set $path]]] < 0} {
  139.         if {[catch {addAppPath $prompt $path}]} return
  140.     }
  141.  
  142.     # Check that the user's choice has an acceptable sig
  143.     if {[lsearch -exact $sigs [getFileSig [set $path]]] < 0} {
  144.         unset $path
  145.         message "Inappropriate file chosen"
  146.         return {} 
  147.     }
  148.     
  149.     # Launch the app
  150.     if {$in_front} {
  151.         if {[catch {launch -f [set $path]}]} {
  152.             error "Problem with launching file (out of memory?)"
  153.         }
  154.     } else {
  155.         if {[catch {launch [set $path]}]} {
  156.             error "Problem with launching file (out of memory?)"
  157.         }
  158.     }        
  159.     
  160.     # Return the name of the chosen application
  161.     return [file tail [set $path]]
  162. }
  163.  
  164.  
  165. #================================================================================
  166. # Excalibur is the only Mac spell-checker that I know of which will handle LaTeX as
  167. # well as ordinary text.
  168.  
  169.  
  170. proc spellcheckWindow {} {
  171.     global excaliburPath resumeRevert
  172.  
  173.     catch {checkRunning Excalibur XCLB excaliburPath} name
  174.  
  175.     if {[winDirty]} {
  176.         if {[askyesno "Save '[lindex [winNames] 0]'?"] == "yes"} {
  177.             save
  178.         }
  179.     }
  180.     sendOpenEvent noReply $name [lindex [winNames -f] 0]
  181.     switchTo $name
  182.     set resumeRevert 1
  183. }
  184.  
  185. proc spellcheckSelection {} {
  186.     global excaliburPath 
  187.  
  188.     catch {checkRunning Excalibur XCLB excaliburPath} name
  189.  
  190.     if {[getPos] == [selEnd]} {
  191.         beep
  192.         message "No selection"
  193.         return;
  194.     }
  195.     copy
  196.     switchTo $name
  197. }
  198.  
  199. #================================================================================
  200.  
  201.  
  202. proc alphaHelp {} {
  203.     global HOME
  204.     edit -r "$HOME:Help:Manual"
  205. }
  206.  
  207.  
  208. proc tclHelp {} {
  209.     global HOME
  210.     edit -r "$HOME:Help:Tcl Commands"
  211. }
  212.  
  213.  
  214. proc dividingLine {} {
  215.     insertText "===============================================================================\r"
  216. }
  217. bind 'l' <C> dividingLine
  218.  
  219. proc texDividingLine {} {
  220.     insertText "%===============================================================================\r"
  221. }
  222. bind 'l' <C> texDividingLine TeX
  223.  
  224. proc cDividingLine {} {
  225.     insertText "//===============================================================================\r"
  226. }
  227. bind 'l' <C> cDividingLine C
  228. bind 'l' <C> cDividingLine C++
  229.  
  230. proc tclDividingLine {} {
  231.     insertText "#===============================================================================\r"
  232. }
  233. bind 'l' <C> tclDividingLine Tcl
  234.  
  235.  
  236. #================================================================================
  237.  
  238. if {![string length [info commands oldCd]]} {
  239.     rename cd oldCd
  240. }
  241.  
  242. proc cd args {
  243.     global HOME
  244.     if {[llength $args]} {
  245.         oldCd [string trim [eval list $args] "        \{\}"]
  246.     } else {
  247.         oldCd $HOME
  248.     }
  249. }
  250.  
  251.  
  252.  
  253. #############################################################################
  254. #  List the name and value of each element of the array $arrName.
  255. #  (Convenient to use as a shell command.)
  256. #
  257. #  Note: it's slower to insert the lines one-by-one like this, but 
  258. #  assembling everything in $lines before inserting can seriously crash Alpha
  259. #  if the result is too big.  (Trying to list the contents of $auto_index()
  260. #  will do it.)  This method seems to be more robust.
  261. #
  262. proc listArray {arrName} {
  263.     global $arrName
  264.     set lines {}
  265.     if {![catch {info vars $arrName}]} {
  266.         foreach nm [array names $arrName] {
  267.             set val [expr \$$arrName\($nm\)]
  268.             append lines "\r\"$nm\"\t\{$val\}"
  269.         }
  270.         insertText $lines
  271.     } else {
  272.         alertnote "\"$arrName\" doesn't exist in this context"
  273.     }
  274. }
  275.  
  276.  
  277.  
  278. #================================================================================
  279.     
  280. proc selectParagraph {} {
  281.     set pos [getPos]
  282.     set start [paraStart $pos] 
  283.     set finish [paraFinish $pos]
  284.     goto $start
  285.     select $start $finish
  286. }
  287.  
  288. # wrapText ==  getText ; breakIntoLines ; replaceText
  289. # Remove text from window, transform (join, del-ws), insert back into window.
  290. proc fillTextByPar {from to} {
  291.     set text [getText $from $to]
  292.     regsub -all "\r(\[ \t\]*\r)+" $text "\r\r\r" text
  293.     regsub -all "(\[^\r\])\r" $text "\\1 " text
  294.     regsub -all "\[ \t\]+" $text " " text
  295.     return [breakIntoLines $text]
  296. }
  297.  
  298. proc fillRegionByPar {{start -1} {finish -1}} {
  299. #    # if {[getPos] == [selEnd]} { return}
  300.     if {($start < 0) || ($finish < 0)} {
  301.         set start [lineStart [getPos]]
  302.         set finish [selEnd] }
  303.     if {$start >= $finish} return
  304.     goto $start
  305.     set text [fillTextByPar $start $finish]
  306.     replaceText $start $finish $text "\r"
  307. }
  308.     
  309. #
  310. # join Lines in region -- if no optional args, use selection
  311. #
  312. proc joinRegion {{from -1} {to -1}} {
  313.     if {($from < 0) || ($to < 0)} {    set from [getPos] ; set to [selEnd] }
  314.     if {$from >= $to} return
  315.     set text [getText $from $to]
  316.     regsub -all "\r(\[ \t\]*\r)+" $text "\r\r\r" text
  317.     regsub -all "(\[^\r\])\r" $text "\\1 " text
  318.     replaceText $from $to $text "\r"
  319. }
  320. # WARNING:    regsub ^$ refers to string endpts (not lines)
  321. # FUTURE:    filterLines like perl:
  322. #    replaceText[apply_to_all(cmd,split [getText [getPos] [selEnd]] "\r")]
  323. # OR:    replaceInRegion: dup_\r, $=>\r ??
  324. #
  325.  
  326.  
  327. #
  328. # Remove text from window, transform (delete dup ws), insert back into window.
  329. #
  330. # inputs: message, alertnote, askyesno, listpick, prompt KILLS SELECTION.
  331. # search: bnds = search -forward -regExpr -ignoreCase -matchWords -noabort 
  332. #        -l limit pat pos
  333. proc regsubInRegion {from to srch repl} {
  334.     if {![string length $srch]} return
  335.     if {$from >= $to} return
  336.     set text [getText $from $to]
  337.     regsub -all "$srch" $text "$repl" text
  338.     replaceText $from $to $text
  339. }
  340. #    while {($pos < $to) &&
  341. #          ![catch {search -s -f 1 -r 1 -i 1 -m 0 "$srch" $pos} mtch]} {
  342. #        set mbeg [lindex $mtch 0]
  343. #        set pos [lindex $mtch 1]
  344. #        replaceText $mbeg $pos $repl }
  345.  
  346. #proc backSlashSub {arg} { eval [concat return "\"$arg\""] }
  347.  
  348. proc backSlashSub {arg} {
  349.     regsub -all {\\} $arg {\\\\} arg
  350.     regsub -all {\[} $arg {\\[} arg
  351.     regsub -all {\]} $arg {\\]} arg
  352.     eval [concat return "\"$arg\""]
  353. }
  354.  
  355. proc replaceInRegion {} {
  356.     if [catch {prompt "Search RegExpr:" ""} srch] return
  357.     if [catch {prompt "Replace String:" ""} repl] return
  358.     if {![string length $srch]} return
  359.     regsubInRegion [getPos] [selEnd] \
  360.         [backSlashSub "$srch"] [backSlashSub "$repl"]
  361. }
  362.  
  363. #
  364. # Apply command to each line (or paragraph) in selection ;
  365. #    if no cmd arg then prompts for it
  366. #
  367. proc filterLines {{cmd 0} {parunit 0}} {
  368.     if {$cmd == 0} {
  369.       if {[catch { prompt "Line-filter command: " "" } cmd]} { return } }
  370.     if {![string length $cmd]} return
  371.     set unitStart lineStart
  372.     set unitEnd nextLineStart
  373.     if {$parunit} {
  374.         set unitStart paraStart
  375.         set unitEnd paraFinish }
  376.     set pos [$unitStart [getPos]]
  377.     set finish [selEnd]
  378.     if {$pos >= $finish} return
  379.     goto $pos
  380.     createTMark "filterLend" $finish
  381.     set next [$unitEnd $pos]
  382.     while {(($next > $pos) && ($pos < $finish))} {
  383.         goto [expr $next-1]
  384.         createTMark "filterLnext" $next
  385.         setMark
  386.         goto $pos
  387.         markHilite
  388.         if {[catch [list uplevel #0 "$cmd"] retval]} {
  389.             select $pos $finish
  390.             alertnote $retval
  391.             return
  392.         }
  393.         if {$next==$finish} break
  394.         set ind [lsearch -regexp [lindex [getTMarks] 0] "filterLend.*"]
  395.         set finish [lindex [lindex [lindex [getTMarks] 0] $ind] 2]
  396.         gotoTMark "filterLnext"
  397.         set pos [$unitStart [getPos]]
  398.         set next [$unitEnd $pos]
  399.     }
  400.     removeTMark "filterLend"
  401.     removeTMark "filterLnext"
  402. }
  403.  
  404.  
  405. proc filterParagraphs {{cmd 0}} { filterLines $cmd 1 }
  406.  
  407. # WARNING: deselecting sets the mark to selEnd
  408. proc sortParagraphs {{from -1} {to -1}} {
  409.     if {($from < 0) || ($to < 0)} {    set from [getPos] ; set to [selEnd] }
  410.     if {$from >= $to} return
  411.     joinRegion {$from $to}
  412.     select [getPos] [nextLineStart [getMark]]
  413.     sortLines
  414.     select [getPos] [getPos]
  415.     regsubInRegion [getPos] [getMark] "\r" "\r\r" 
  416.     wrapRegion
  417. }
  418.  
  419. #
  420. # Sample
  421. #
  422. proc filterRegion {{from -1} {to -1} {cmd 0} {newwin 0}} {
  423.     if {$cmd == 0} {
  424.       if {[catch { prompt "Eval command: " "" } cmd]} { return }
  425.     }
  426.     if {![string length $cmd]} return
  427.     if {($from < 0) || ($to < 0)} {    set from [getPos] ; set to [selEnd] }
  428.     if {$from >= $to} return
  429.     set pos [getPos]
  430.     set text [getText $from $to]
  431.     set text [$cmd $text]
  432.     replaceText $from $to $text "\r"
  433.     goto $pos
  434. }
  435.  
  436.  
  437. #
  438. set lastEvaled ""
  439. proc evaluate {} {
  440.     global lastEvaled
  441.     if {[string length $lastEvaled]} {
  442.         set p "M-x ($lastEvaled): "
  443.     } else {
  444.         set p "M-x: "
  445.     }
  446.     if {[catch {statusPrompt $p} text]} {return}
  447.     if {![string length $text]} {set text $lastEvaled}
  448.     $text
  449.     set lastEvaled $text
  450. }
  451.  
  452.  
  453. # First, define macros to bypass the electric braces.
  454. proc ordLeftBrace {} {
  455.     insertText "        \{"
  456. }
  457. bind {'['} <cs> ordLeftBrace
  458.  
  459. proc ordRightBrace {} {
  460.     insertText "\}"
  461.     blink [matchIt "\}" [expr [getPos]-1]]
  462. }
  463. bind {']'} <cs> ordRightBrace
  464.     
  465. proc quoteWord {} {
  466.     backwardWord
  467.     insertText "'"
  468.     forwardWord
  469.     insertText "'"
  470. }
  471. bind ''' <z> quoteWord
  472.  
  473. #================================================================================
  474.  
  475. proc tomac {fname} {
  476.     set fd [open $fname "r"]
  477.     set text [read $fd]
  478.     close $fd
  479.     set fd [open $fname "w"]
  480.     regsub "\n" $text "\r" text
  481.     puts -nonewline $fd $text
  482.     close $fd
  483. }
  484.  
  485. proc tounix {fname} {
  486.     set fd [open $fname "r"]
  487.     set text [read $fd]
  488.     close $fd
  489.     set fd [open $fname "w"]
  490.     regsub "\r" $text "\n" text
  491.     puts -nonewline $fd $text
  492.     close $fd
  493. }
  494.  
  495.  
  496. proc cat args {
  497.     set files ""
  498.     foreach a $args {
  499.         foreach f [glob $a] {
  500.             lappend files $f
  501.         }
  502.     }
  503.     foreach f $files {
  504.         append text "==============<$f>==============\r"
  505.         set fd [open $f "r"]
  506.         append text "[read $fd]\r\r"
  507.         close $fd
  508.     }
  509.     return $text
  510. }
  511.  
  512. proc catto args {
  513.     set len [llength $args]
  514.     set to [lindex $args [expr $len -1]]
  515.     set args [lrange $args 0 [expr $len -2]]
  516.  
  517.     set files ""
  518.     foreach a $args {
  519.         foreach f [glob $a] {
  520.             lappend files $f
  521.         }
  522.     }
  523.     foreach f $files {
  524.         append text "==============<$f>==============\r"
  525.         set fd [open $f "r"]
  526.         append text "[read $fd]\r\r"
  527.         close $fd
  528.     }
  529.  
  530.     set dfile $to
  531.     if {[file exists $dfile]} {
  532.         set fid [open $dfile "a"]
  533.     } else {
  534.         set fid [open $dfile "w"]
  535.     }
  536.     puts $fid $text
  537.     close $fid
  538. }
  539.  
  540.  
  541. ##############################################################################
  542. #  To be used in the windows created by "matchingLines" or by batch searches.
  543. #
  544. #  With the cursor positioned in a line corrsponding to a match, 
  545. #  go back and select the line in the original file that 
  546. #  generated this match.  (Like emacs 'Occur' functionality)
  547. #
  548. proc gotoMatch {} {
  549.     global tileHeight tileWidth tileTop tileLeft errorHeight errorDisp
  550.     set text [getText [lineStart [getPos]] [expr [nextLineStart [getPos]] - 1]]
  551.     set ind1 [string first "░" $text]
  552.     set ind2 [string last "░" $text]
  553.     if {$ind1 == $ind2} {
  554.         set fname [string trim [string range $text $ind1 end] {░}]
  555.         set msg ""
  556.     } else {
  557.         set fname [string trim [string range $text $ind1 $ind2] {░}]
  558.         set msg [string trim [string range $text $ind2 end] {░}]
  559.     }
  560.     
  561.     set top $tileTop
  562.     set geo [getGeometry]
  563.     if {([lindex $geo 0] != $tileLeft) || ([lindex $geo 1] != $top) || ([lindex $geo 2] != $tileWidth) || ([lindex $geo 3] != $errorHeight) } {
  564.         moveWin $tileLeft $top
  565.         sizeWin $tileWidth $errorHeight
  566.     }
  567.     set mar 22
  568.     incr top [expr $errorHeight + $mar]
  569.     if {[expr {[lsearch [winNames -f] "*$fname"] >= 0}]} {
  570.         if {[string match ":*" $fname]} {
  571.             set fname [file tail $fname]
  572.         }
  573.         bringToFront $fname
  574.         set geo [getGeometry]
  575.         if {([lindex $geo 0] != $tileLeft) || ([lindex $geo 1] != $top) || ([lindex $geo 2] != $tileWidth) || ([lindex $geo 3] != $errorDisp) } {
  576.             sizeWin $tileWidth $errorDisp
  577.             moveWin $tileLeft $top
  578.         }
  579.     } elseif {[file exists $fname]} {
  580.         edit -g $tileLeft $top $tileWidth $errorDisp $fname
  581.     } else {
  582.         if {![string match "*Link*" [getText 0 [nextLineStart 0]]]} {
  583.             alertnote "File \" $fname \" not found." 
  584.         }
  585.         return
  586.     }
  587.     if {![regexp {Line ([0-9]+):} $text dummy line]} { error "Garbage" }
  588.     set pos [rowColToPos $line 0]
  589.     select $pos [nextLineStart $pos]
  590.     message $msg
  591. }
  592. bind 'c' <Cz>        gotoMatch
  593.  
  594.  
  595. #================================================================================
  596.  
  597. proc prevIntro {} {
  598.     set res [search -s -f 0 -r 0 {== } [getPos]]
  599.     display [lineStart [expr [lineStart [lindex $res 0]] - 1]]
  600. }
  601.  
  602. proc nextIntro {} {
  603.     set res [search -s -f 1 -r 0 {== } [getPos]]
  604.     set res [lindex $res 1]
  605.     set res [search -s -f 1 -r 0 {== } $res]
  606.     display [lineStart [expr [lineStart [lindex $res 0]] - 1]]
  607. }
  608.  
  609. #================================================================================
  610.  
  611. proc searchStart {} {
  612.     global search_start
  613.     select [getPos]
  614.     setMark
  615.     if {[catch {goto $search_start}]} {message "No previous search"}
  616. }
  617.  
  618. #================================================================================
  619.  
  620.  
  621. proc listBindings {} {
  622.     new -n {* Key Bindings *}
  623.     insertText [bindingList]
  624.  
  625.     global infoWindowsDirty
  626.     if {!$infoWindowsDirty} {setWinInfo dirty 0}
  627. }
  628.  
  629.  
  630. proc listFunctions {} {
  631.     global winModes
  632.     new -n {* Functions *}
  633.     insertText "===\r\tCommand-double-click on a function to see its definition\r===\r\r" [join [lsort -ignore [info commands]] "\r"] "\r"
  634.     goto 0
  635.     setWinInfo dirty 0
  636.     changeMode [set winModes([lindex [winNames] 0]) Tcl]
  637. }
  638.  
  639.  
  640. #================================================================================
  641.  
  642. proc printArray {arr} {
  643.     global $arr
  644.         foreach n [array names $arr] {
  645.         append text "$n '[set ${arr}($n)]'\r"
  646.     }
  647.     return [string trim $text "\r"]
  648. }
  649.  
  650. #================================================================================
  651.  
  652.  
  653. proc doATab {} {
  654.     global mode
  655.     global ${mode}modeVars
  656.     if {[info exists ${mode}modeVars] && ![set ${mode}modeVars(electricTab)] || [regexp {[^ \t]} [getText [lineStart [getPos]] [getPos]]]} {
  657.         if {[getPos] != [selEnd]} {
  658.             replaceText [getPos] [selEnd] "\t"
  659.         } else {
  660.             insertText "\t"
  661.         }
  662.     } else {
  663.         indentLine
  664.     }
  665. }
  666.  
  667. #     set ptext [getText [lindex $lst 0] [nextLineStart [lindex $lst 0]]]
  668. #     regsub -all {[^(]} $ptext {} one
  669. #     regsub -all {[^)]} $ptext {} two
  670. #     if {[string length $one] > [string length $two]} {
  671. #         regexp {[^(]*\(} $ptext blah
  672. #         regsub -all {[^    ]} $blah { } lwhite
  673. #     } elseif {($nextC == "\{")} {
  674. #         append lwhite "\t"
  675. #     }
  676.  
  677. proc indentLine {} {
  678.     global mode
  679.     
  680.     set beg [lineStart [getPos]]
  681.  
  682.     set lst [search -s -f 0 -r 1 -i 0 {^[ \t]*[^ \t\r]} [expr $beg-1]]
  683.     set lwhite [getText [lindex $lst 0] [expr [lindex $lst 1] - 1]]
  684.     set nextC [lookAt [expr [nextLineStart [lindex $lst 1]] - 2]]
  685.  
  686.     if {($nextC == "\{")} {
  687.         append lwhite "\t"
  688.     } elseif {$nextC == ":"} {
  689.         set lwhite "[string range $lwhite 0 [expr [string length $lwhite]-3]]\t"
  690.     }
  691.         
  692.     set text [getText $beg [nextLineStart $beg]]
  693.     regexp {^[ \t]*} $text white
  694.     set len [string length $white]
  695.     set nextC [lookAt [expr $beg + $len]]
  696.     if {$nextC == "\}"} {
  697.         set lwhite [string range $lwhite 0 [expr [string length $lwhite] - 2]]
  698.     }
  699.     
  700.     global ${mode}modeVars
  701.     if {[string match "*:\r" $text] && [info exists ${mode}modeVars(elecColon)] && [set ${mode}modeVars(elecColon)]} {
  702.         if {[string index $lwhite 0] == "\t"} {
  703.             set lwhite "[string range $lwhite 1 [expr [string length $lwhite] - 1]]  "
  704.         }
  705.     }
  706.  
  707.     if {$white != $lwhite} {
  708.         replaceText $beg [expr $beg + $len] $lwhite
  709.     }
  710.     goto [expr $beg + [string length $lwhite]]
  711. }
  712.  
  713.  
  714. proc indentRegion {} {
  715.     set from [lindex [posToRowCol [getPos]] 0]
  716.     set to [lindex [posToRowCol [selEnd]] 0]
  717.     select [getPos]
  718.     while {$from <= $to} {
  719.         goto [rowColToPos $from 0]
  720.         indentLine
  721.         incr from
  722.     }
  723. }
  724.  
  725. #================================================================================
  726.  
  727. proc sPrompt {msg def} {
  728.     global useStatusBar
  729.     if {!$useStatusBar} {return [prompt $msg $def]}
  730.     if {[catch {statusPrompt "$msg ($def): "} ans]} {
  731.         error "cancel"
  732.     }
  733.     if {![string length $ans]} {return $def}
  734.     return $ans
  735. }
  736.  
  737. #================================================================================
  738. proc quoteChar {} {
  739.     message "Literal keystroke to be inserted:"
  740.     insertText [getChar]
  741. }
  742. #===============================================================================
  743.  
  744. proc saveACopyAs {} {
  745.     if {[file exists [set nm [lindex [winNames -f] 0]]]} {
  746.         set nm2 [putfile "Save a copy as:" [file tail $nm]]
  747.         cp $nm $nm2
  748.     }
  749. }
  750. #===============================================================================
  751. proc removeDups {l} {
  752.     foreach f $l {
  753.         set silly($f) 1
  754.     }
  755.     if {[info exists silly]} {
  756.         return [array names silly]
  757.     }
  758. }
  759.             
  760.  
  761. #===============================================================================
  762.  
  763. proc printHeaderProc {} {
  764.     global printHeader printHeaderTime printHeaderFullPath
  765.     
  766.     if {!$printHeader} return ""
  767.     
  768.     if {$printHeaderFullPath} {
  769.         set text [lindex [winNames -f] 0]
  770.     } else {
  771.         set text [lindex [winNames] 0]
  772.     }
  773.     
  774.     if {$printHeaderTime} {
  775.         append text "      [join [mtime [now] short]]"
  776.     }
  777. }
  778.  
  779. #===============================================================================
  780.  
  781. proc toggleNumLock {} {
  782.     global numLock modifiedVars
  783.     
  784.     set numLock [expr -1 * ($numLock - 1)]
  785.     lappend modifiedVars numLock
  786. }
  787.  
  788. #===============================================================================
  789.  
  790. proc register {} {
  791.     global HOME
  792. #    edit -r "$HOME:Help:Registering"
  793.     launch -f "$HOME:Register 1.1.5 Keleher"
  794. }
  795.  
  796. #===============================================================================
  797. # Useful for -command flag of 'lsort'.
  798. proc sortByTail {one two} {
  799.     string compare [file tail $one] [file tail $two]
  800. }
  801.  
  802.  
  803. #===============================================================================
  804.  
  805. proc cmdDoubleClick {{from -1} {to -1}} {
  806.     global  mode
  807.     
  808.     if {$from < 0} {
  809.         set from [getPos]
  810.         set to [selEnd]
  811.         if {$from == $to} {
  812.             message "No selection"
  813.             return
  814.         }
  815.     }
  816.     
  817.     if {[catch {${mode}DblClick $from $to}]} {
  818.         message "No docs"
  819.     }
  820.     
  821. }
  822.  
  823. #===============================================================================
  824.  
  825.  
  826. proc editMark {fname mname args} {
  827.     if {[set pos [lsearch [winNames -f] "*$fname*"]] >= 0}  {
  828.         bringToFront [lindex [winNames -f] $pos]
  829.     } else {
  830.         if {[lsearch $args {-r}] >= 0} {
  831.             edit -r "$fname"
  832.         } else {
  833.             edit "$fname"
  834.         }
  835.     }
  836.     if {[lsearch [getNamedMarks -n] $mname] < 0} {
  837.         global    mode
  838.         ${mode}MarkFile
  839.     } 
  840.     gotoMark $mname
  841. }
  842.  
  843.  
  844. proc winDirty {} {
  845.     getWinInfo arr
  846.     return $arr(dirty)
  847. }
  848.  
  849.  
  850. #===============================================================================
  851.  
  852. proc lreverse {l} {
  853.     if {[llength $l] > 1} {
  854.         set first [lindex $l 0]
  855.         set l [lreverse [lrange $l 1 end]]
  856.         lappend l $first
  857.     }
  858.     return $l
  859. }
  860.  
  861.     
  862. #===============================================================================
  863.  
  864.  
  865. set {patternLibrary(Pascal to C Comments)}      { {\{([^\}]*)\}}    {/* \1 */}     }
  866. set {patternLibrary(C++ to C Comments)}            { {//(.*)}            {/* \1 */}     }
  867. set {patternLibrary(Space Runs to Tabs)}        { { +}                {\t}         }
  868.  
  869.  
  870.  
  871. proc getPatternLibrary {} {
  872.     global patternLibrary
  873.     
  874.     foreach nm [array names patternLibrary] {
  875.         lappend nms [concat [list $nm] $patternLibrary($nm)]
  876.     }
  877.     return $nms
  878. }
  879.  
  880. proc rememberPatternHook {search replace} {
  881.     global patternLibrary
  882.     if {[catch {set name [prompt "New pattern's name?" ""]}]} {
  883.         return ""
  884.     }
  885.     addArrDef patternLibrary $name [list $search $replace]
  886.     set patternLibrary($name) [list $search $replace]
  887.     return $name
  888. }
  889.  
  890. proc deletePatternHook {} {
  891.     global patternLibrary
  892.     
  893.     
  894.     set temp [list prompt "Delete which pattern?" [lindex [array names patternLibrary] 0] "Pats:"]
  895.     set name [eval [concat $temp [array names patternLibrary]]]
  896.     removeArrDef patternLibrary $name
  897.     unset patternLibrary($name)
  898. }
  899.  
  900. #===============================================================================
  901. set htmlEventSuiteIDs(MOSS) {WWW!}
  902. proc sendUrl {} {
  903.         global htmlBrowserPath htmlEventSuiteIDs
  904.         if {![info exists htmlBrowserPath]} {
  905.                 if {[catch {addAppPath "HTML Browser" htmlBrowserPath}]} {
  906.                         alertnote "You must choose an HTML browser"
  907.                         return
  908.                 }
  909.         }
  910.         set sig [getFileSig $htmlBrowserPath] 
  911.         
  912.         set name [checkRunning "HTML Browser" $sig htmlBrowserPath]
  913.         if {![string length $name]} {
  914.                 alertnote "Couldn't run HTML browser"
  915.                 return
  916.         }
  917.  
  918.         if {![info exists htmlEventSuiteIDs($sig)]} {
  919.                 alertnote "Can't send URLs to this HTML browser"
  920.                 return
  921.         }
  922.         set suite $htmlEventSuiteIDs($sig)
  923.  
  924.         AEBuild "'${sig}'" $suite {OURL} {----} "╥[getSelect]╙"
  925.         switchTo $name
  926. }
  927.