1# e93 base startup file 2# This is the top of the startup script tree for e93 3# it finds this file, which in turn includes all other 4# files which are executed at startup time. 5 6# NOTE: normally, this file requires no modifications, 7# since all of its functionality can be overridden in 8# other files. 9 10# WARNING: be careful when editing this file, 11# e93 will stop processing this file at the FIRST error! 12 13# Globals/Defaults 14 15set tcl_precision 16; # increase precision 16 17set sysPrefsDir "[file dirname $SCRIPTPATH]"; # place where system preferences are stored 18set userPrefsDir "~/.e93"; # place where user's preferences are stored 19 20set mapsDir "syntaxmaps"; # place inside prefs directory where syntaxmaps are stored 21set auxMapsDir "syntaxmaps_aux"; # user can add additional maps in here 22set highlightDir "highlightschemes"; # place inside prefs directory where highlighting schemes are stored 23set auxHighlightDir "highlightschemes_aux"; # user can add additional highlight schemes in here 24set modulesDir "modules"; # place inside prefs directory where modules are stored 25set auxModulesDir "modules_aux"; # user can add additional modules in here 26set imagesDir "images"; # all images the editor uses are read from here 27set prefsDir "prefs"; # place where user's preferences can be written 28 29set untitledCounter 0; # used to give each new untitled window a unique name 30set lineWrap 0; # no line wrapping currently 31set lineWrapColumn 70; # column where lines should be wrapped 32 33set windowWidthLimit 1400; # width in pixels that we hold new windows to on really large screens 34 35set grepFilesChoice ""; # initialize the data in the grep files dialog 36set replaceSelectionsChoice ""; # initialize the data in the replace selections dialog 37set pipeSelectionsChoice ""; # initialize the data in the pipe selections dialog 38set mailRecipientChoice ""; # initialize the data in the mail recipient dialog 39set mailSubjectChoice ""; # initialize the data in the mail subject dialog 40set refillLimitChoice "70"; # initialize the data in the refill limit dialog 41 42#scrollbarplacement left; # X-specific command to set default placement for vertical scroll bars (defaults to right) 43 44# Set the default fonts to use 45setdefaultviewfont {-*-lucidatypewriter-medium-r-normal-sans-12-*-*-*-*-*-*-*}; # font for viewing text 46setdefaultmenufont {-*-new century schoolbook-bold-r-normal--14-*-*-*-*-*-*-*}; # font for the menus 47setdefaultdialogbuttonfont {-*-new century schoolbook-bold-r-normal--14-*-*-*-*-*-*-*}; # font for dialog buttons 48setdefaultdialogtextfont {-*-new century schoolbook-bold-r-normal--14-*-*-*-*-*-*-*}; # font for dialog items 49setdefaultstatusbarfont {-*-lucidatypewriter-medium-r-normal-sans-12-*-*-*-*-*-*-*}; # font for the status bar 50 51# Set the characters considered parts of words when double clicking. 52setwordchars {ABCDEFGHJIKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789@_} 53 54# Set checkboxes in the search dialog to default values. 55# Change these to have them default whatever way you would like when e93 starts. 56set sd_backwards 0; # do not search backwards by default at startup 57set sd_wrapAround 0; # do not wrap around by default at startup 58set sd_selectionExpression 0; # do not use selection expressions by default at startup 59set sd_ignoreCase 0; # do not ignore case by default 60set sd_limitScope 0; # do not limit scope by default 61set sd_replaceProc 0; # do not treat replace text as procedure 62 63# set up default command used to print text in "buffer" 64#set defaultPrintCommand "a2ps -Pps18 --stdin=\$buffer -T\[gettabsize \$buffer\]" 65#set defaultPrintCommand "lpr -#1 -J=\$buffer" 66set defaultPrintCommand "enscript -B -h -c -T\[gettabsize \$buffer\] -f Courier7" 67 68 69# if e93 is unable to match a document name, these will be used as the defaults 70set defaultTabSize 4 71set defaultColorScheme "e93"; # these must exist, or e93 will complain 72set defaultSyntaxMap "unknown"; # by default, we don't know what kind of document it is 73 74 75# Styles enumerations for syntax coloring rules 76# These style numbers are arbitrary (except for style_default) 77set style_default 0; # define some standard styles to make life easier 78set style_comment 1; 79set style_string 2; 80set style_char 3; 81set style_digit 4; 82set style_operator 5; 83set style_variable 6; 84set style_value 7; 85set style_delimiter 8; 86set style_keyword 9; 87set style_type 10; 88set style_directive 11; 89set style_function 12; 90set style_label 13; 91set style_local_label 14; 92set style_bold 15; 93set style_indent0 16; 94set style_indent1 17; 95set style_indent2 18; 96set style_indent3 19; 97set style_indent4 20; 98set lastStyle $style_indent4; # set this to allow others to add more styles at the end 99 100# define coloring rules for various languages 101 102# see if the user has his own set of maps specified, if so, skip including the defaults, and get only his 103if {[file exists [file join $userPrefsDir $mapsDir]]} \ 104{ 105 foreach file [lsort [glob -nocomplain [file join $userPrefsDir $mapsDir *.tcl]]] \ 106 { 107 source $file; 108 } 109} \ 110else \ 111{ 112 # use all system defined syntax maps 113 foreach file [lsort [glob -nocomplain [file join $sysPrefsDir $mapsDir *.tcl]]] \ 114 { 115 source $file; 116 } 117} 118 119# get user's additional syntax maps (if any) 120if {[file exists [file join $userPrefsDir $auxMapsDir]]} \ 121{ 122 foreach file [lsort [glob -nocomplain [file join $userPrefsDir $auxMapsDir *.tcl]]] \ 123 { 124 source $file; 125 } 126} 127 128# see if the user has his own set of highlight schemes specified, if so, skip including the defaults, and get only his 129if {[file exists [file join $userPrefsDir $highlightDir]]} \ 130{ 131 foreach file [lsort [glob -nocomplain [file join $userPrefsDir $highlightDir *.tcl]]] \ 132 { 133 source $file; 134 } 135} \ 136else \ 137{ 138 # use all system defined schemes 139 foreach file [lsort [glob -nocomplain [file join $sysPrefsDir $highlightDir *.tcl]]] \ 140 { 141 source $file; 142 } 143} 144 145# get user's additional highlighting schemes (if any) 146if {[file exists [file join $userPrefsDir $auxHighlightDir]]} \ 147{ 148 foreach file [lsort [glob -nocomplain [file join $userPrefsDir $auxHighlightDir *.tcl]]] \ 149 { 150 source $file; 151 } 152} 153 154# Tcl console 155newbuffer tclConsole; setbuffervariable tclConsole lowpriority ""; # create a buffer for Tcl's stdout 156#settclstdout tclConsole; # direct the messages there 157#settclstderr tclConsole; # do not direct errors here by default, since they override the editor's stderr and cause it not to output 158 159# Clipboard buffers 160newbuffer clip0; setbuffervariable clip0 lowpriority ""; # set the lowpriority variable which tells us to treat windows on this buffer specially 161newbuffer clip1; setbuffervariable clip1 lowpriority ""; 162newbuffer clip2; setbuffervariable clip2 lowpriority ""; 163newbuffer clip3; setbuffervariable clip3 lowpriority ""; 164newbuffer clip4; setbuffervariable clip4 lowpriority ""; 165newbuffer clip5; setbuffervariable clip5 lowpriority ""; 166newbuffer clip6; setbuffervariable clip6 lowpriority ""; 167newbuffer clip7; setbuffervariable clip7 lowpriority ""; 168newbuffer clip8; setbuffervariable clip8 lowpriority ""; 169newbuffer clip9; setbuffervariable clip9 lowpriority ""; 170 171setclipboard clip0; # set this as the current clipboard 172 173# Search buffers 174newbuffer findBuffer; setbuffervariable findBuffer lowpriority ""; # create default buffer to use for "find" 175newbuffer replaceBuffer; setbuffervariable replaceBuffer lowpriority ""; # create default buffer to use for "replace" 176newbuffer tempFindBuffer; setbuffervariable tempFindBuffer lowpriority ""; # these buffers are for commands which are implemented with search/replace, but do not want to overwrite the find/replaceBuffers 177newbuffer tempReplaceBuffer; setbuffervariable tempReplaceBuffer lowpriority ""; 178 179 180# --------------------------------------------------------------------------------------------------------------------------------- 181 182# Determine screen and window sizes. 183set screenWidth [lindex [screensize] 0] 184set screenHeight [lindex [screensize] 1] 185set windowHeight [expr $screenHeight*3/4]; # set the initial default height for new windows 186set windowWidth [expr $windowHeight*4/3]; # set the initial default width for new windows (make 4:3 based on width) 187 188# Limit the width on really large screens, since at some point, extra width isn't 189# getting you much. 190if {$windowWidth>$windowWidthLimit} \ 191{ 192 set windowWidth $windowWidthLimit; 193} 194 195# Determine how windows stagger when they are opened. 196set staggerInitialX [expr $screenWidth/24]; # set the initial default X position for new windows 197set staggerInitialY [expr $screenHeight/16]; # set the initial default Y position for new windows 198set staggerIncrementX [expr $screenWidth/160]; # amount to increment by 199set staggerIncrementY [expr $screenHeight/160]; 200set staggerMaxX [expr $screenWidth*3/24] 201set staggerOpenX $staggerInitialX; # set the current X position for new windows 202set staggerOpenY $staggerInitialY; # set the current Y position for new windows 203 204# --------------------------------------------------------------------------------------------------------------------------------- 205# Procedures 206 207# Convenience function for setting marks in buffers 208# this will reset the mark if it already exists, and create it if 209# it does not already exist 210proc setmark {buffer mark} \ 211{ 212 catch {newmark $buffer $mark}; # create new mark if none existed already 213 copyselection $buffer -destmark $mark; # copy selection into it 214} 215 216# Convenience function for locating marks in buffers 217# this will reset the mark if it already exists, and create it if 218# it does not already exist 219proc gotomark {buffer mark} \ 220{ 221 copyselection $buffer -sourcemark $mark; # copy the mark over the buffer's selection 222} 223 224# Home a window to the start of selection (with arguments) 225proc HomeWindowToSelectionStart {window args} \ 226{ 227 set position [lindex [getselectionends $window] 0]; # get selection start position 228 eval [list homewindow $window] $position $position $args; # home to start 229} 230 231# Return true if the passed window name is one of the low-priority windows. 232# A low priority window is one that e93 should not ask to save, even if it 233# has been modified... 234proc LowPriority {window} \ 235{ 236 expr {[catch {getbuffervariable $window lowpriority}]==0} 237} 238 239# When the interpreter does not understand a given command, send it to a shell. 240# NOTE: no interactive commands can be executed this way, because Tcl would 241# be suspended (waiting for the interactive command to finish). If Tcl is 242# suspended, then e93 is also suspended (waiting for the Tcl command to finish) 243# So there is no way that e93 could provide input to an interactive command. 244# Interactive commands should be run as tasks. 245#proc unknown args \ 246#{ 247# return [uplevel exec $args] 248#} 249 250# NOTE: the code above has been replaced by this: 251proc console {} {} 252set tcl_interactive 1 253# those 2 lines tell the tcl built-in unknown routine to behave as 254# desired, and also get us auto loading and other useful features 255 256 257# If there is no selection, select the current line 258proc SelectLineWhenNoSelection {buffer} \ 259{ 260 set ends [getselectionends $buffer] 261 set start [lindex $ends 0] 262 set end [lindex $ends 1] 263 if {$start==$end} \ 264 { 265 selectline $buffer [lindex [positiontolineoffset $buffer $start] 0]; # select the line the cursor is on 266 } 267} 268 269# Copy the selection in buffer to the clipboard passed. 270# If there is no selection in buffer, then select the line the cursor is on. 271proc SmartCopy {buffer clipboard} \ 272{ 273 SelectLineWhenNoSelection $buffer 274 copy $buffer $clipboard 275} 276 277# Cut the selection in buffer to the clipboard passed. 278# If there is no selection in buffer, then select the line the cursor is on. 279proc SmartCut {buffer clipboard} \ 280{ 281 SelectLineWhenNoSelection $buffer 282 cut $buffer $clipboard 283} 284 285# Replace the entire contents of a buffer with the passed text, and clear undos on the buffer. 286# NOTE: it would be bad if this were called on a document that had been edited for hours and not 287# saved! -- It would blow away the entire contents. 288proc TextToBuffer {buffer text} \ 289{ 290 selectall $buffer; # select everything, so insert will remove it 291 insert $buffer $text; # write over everything in buffer 292 flushundos $buffer; # get rid of any undo information for this buffer 293} 294 295# Move the stagger position to the next spot for a new staggered window. 296proc UpdateStaggerPosition {} \ 297{ 298 uplevel #0 \ 299 { 300 incr staggerOpenX $staggerIncrementX; 301 incr staggerOpenY $staggerIncrementY; 302 if {$staggerOpenX>$staggerMaxX} \ 303 { 304 set staggerOpenX $staggerInitialX; 305 set staggerOpenY $staggerInitialY 306 } 307 } 308} 309 310# Tile the windows on the display. 311proc TileWindows {} \ 312{ 313 set horizontalNumber 4; # number of windows we want across 314 set verticalNumber 4; # number we want down 315 set horizontalBorder 30; # number of pixels to leave around edges of screen 316 set verticalBorder 30; 317 set screendimensions [screensize] 318 set width [lindex $screendimensions 0] 319 set height [lindex $screendimensions 1] 320 set windowWidth [expr ($width-($horizontalBorder*2))/$horizontalNumber]; # get the width of each individual window 321 set windowHeight [expr ($height-($verticalBorder*2))/$verticalNumber]; # get the height of each individual window 322 set horizontalIndex 0; set verticalIndex 0; # init counters that tell us where we are 323 foreach window [windowlist] \ 324 { 325 if {![LowPriority $window]} \ 326 { 327 setrect $window [expr $horizontalBorder+$horizontalIndex*$windowWidth] [expr $verticalBorder+$verticalIndex*$windowHeight] $windowWidth $windowHeight 328 incr horizontalIndex 329 if {$horizontalIndex>=$horizontalNumber} \ 330 { 331 set horizontalIndex 0; 332 incr verticalIndex; 333 if {$verticalIndex>=$verticalNumber} \ 334 { 335 set verticalIndex 0; 336 } 337 } 338 } 339 } 340} 341 342# Stack the windows on the display. 343proc StackWindows {} \ 344{ 345 global staggerInitialX staggerInitialY staggerOpenX staggerOpenY windowWidth windowHeight 346 347 set staggerOpenX $staggerInitialX; # set the initial default X 348 set staggerOpenY $staggerInitialY; # set the initial default Y 349 foreach window [windowlist] \ 350 { 351 if {![LowPriority $window]} \ 352 { 353 setrect $window $staggerOpenX $staggerOpenY $windowWidth $windowHeight 354 UpdateStaggerPosition 355 } 356 } 357} 358 359# return the foreground color for the given index of the given color scheme 360proc HighlightSchemeForegroundColor {schemeName styleIndex} \ 361{ 362 global HighlightSchemes 363 set schemeArray $HighlightSchemes($schemeName); # get the name of the array which holds the scheme information 364 global $schemeArray 365 366 set elementValue [lindex [array get $schemeArray $styleIndex] 1] 367 return [lindex $elementValue 0] 368} 369 370# return the background color for the given index of the given color scheme 371proc HighlightSchemeBackgroundColor {schemeName styleIndex} \ 372{ 373 global HighlightSchemes 374 set schemeArray $HighlightSchemes($schemeName); 375 global $schemeArray 376 377 set elementValue [lindex [array get $schemeArray $styleIndex] 1] 378 return [lindex $elementValue 1] 379} 380 381# return the font name for the given index of the given color scheme 382proc HighlightSchemeFont {schemeName styleIndex} \ 383{ 384 global HighlightSchemes 385 set schemeArray $HighlightSchemes($schemeName); 386 global $schemeArray 387 388 set elementValue [lindex [array get $schemeArray $styleIndex] 1] 389 return [lindex $elementValue 2] 390} 391 392# Given a window, set the highlight scheme (which colors and fonts to use) 393proc SetHighlightScheme {window schemeName} \ 394{ 395 global HighlightSchemes 396 set schemeArray $HighlightSchemes($schemeName); # get the name of the array which holds the scheme information 397 global $schemeArray 398 foreach element [array names $schemeArray] \ 399 { 400 set elementValue [lindex [array get $schemeArray $element] 1] 401 if {$element=="selection"} \ 402 { 403 setselectioncolors $window [lindex $elementValue 0] [lindex $elementValue 1] 404 } \ 405 else \ 406 { 407 setcolors $window [lindex $elementValue 0] [lindex $elementValue 1] $element 408 setfont $window [lindex $elementValue 2] $element 409 } 410 } 411} 412 413# Given a buffer, set the highlight mode (which syntax to parse) 414proc SetHighlightMode {buffer highlightModeName} \ 415{ 416 setsyntaxmap $buffer $highlightModeName 417} 418 419# work out the default color scheme, highlight mode, and tab size for buffer 420# return a list which contains a boolean that tells if something other than the 421# default is being returned, the tab size, the color scheme name, and the syntax map name 422proc GetDefaultStyleInfo {buffer} \ 423{ 424 global extensionHuntExpression extensionTabSize extensionColorScheme extensionMapName defaultTabSize defaultColorScheme defaultSyntaxMap 425 426 set hadMatch 0 427 428 # set up defaults 429 set tabSize $defaultTabSize 430 set schemeName $defaultColorScheme 431 set mapName $defaultSyntaxMap 432 433 foreach extensionAttrName [array names extensionHuntExpression] \ 434 { 435 if {[regexp $extensionHuntExpression($extensionAttrName) [file tail $buffer]]} \ 436 { 437 set tabSize $extensionTabSize($extensionAttrName) 438 set schemeName $extensionColorScheme($extensionAttrName) 439 set mapName $extensionMapName($extensionAttrName) 440 set hadMatch 1 441 break 442 } 443 } 444 lappend temp $hadMatch $tabSize $schemeName $mapName; # return the 3 items 445} 446 447# when a window's name has been changed, this is called to update the 448# styles in use for the window 449# if the name is recognized, this will change the style, otherwise it 450# does nothing 451proc UpdateStyle {window} \ 452{ 453 set temp [GetDefaultStyleInfo $window] 454 if {[lindex $temp 0]} \ 455 { 456 settabsize $window [lindex $temp 1] 457 SetHighlightScheme $window [lindex $temp 2] 458 SetHighlightMode $window [lindex $temp 3] 459 } 460} 461 462# Create a window onto buffer, using given values for position, size, font, tabSize, color, and highlighting. 463proc OpenWindow {buffer x y width height tabSize schemeName mapName} \ 464{ 465 global style_default 466 467 if {[haswindow $buffer]} \ 468 { 469 settopwindow $buffer; # if it was already open, then just put it to the top, change nothing 470 } \ 471 else \ 472 { 473 openwindow $buffer $x $y $width $height [HighlightSchemeFont $schemeName $style_default] $tabSize [HighlightSchemeForegroundColor $schemeName $style_default] [HighlightSchemeBackgroundColor $schemeName $style_default] 474 SetHighlightScheme $buffer $schemeName 475 SetHighlightMode $buffer $mapName 476 HomeWindowToSelectionStart $buffer; # go to the cursor/selection 477 } 478} 479 480# Create a window onto buffer, using default values for position and size 481# and given values for, font, tabSize, color, and highlighting. 482proc OpenStaggeredWindow {buffer tabSize schemeName mapName} \ 483{ 484 global staggerOpenX staggerOpenY screenWidth screenHeight windowWidth windowHeight 485 486 if {[haswindow $buffer]} \ 487 { 488 settopwindow $buffer; # if it was already open, then just put it to the top 489 } \ 490 else \ 491 { 492 if {[LowPriority $buffer]} \ 493 { 494 set width [expr $screenWidth*3/4] 495 set height [expr $screenHeight*1/8] 496 set x [expr ($screenWidth-$width)/2] 497 set y [expr $screenHeight-$height] 498 } \ 499 else \ 500 { 501 set width $windowWidth 502 set height $windowHeight 503 set x $staggerOpenX 504 set y $staggerOpenY 505 UpdateStaggerPosition; 506 } 507 OpenWindow $buffer $x $y $width $height $tabSize $schemeName $mapName 508 } 509} 510 511# Create a window onto buffer, using default values for position, size, font, tabSize, color, and highlighting. 512proc OpenDefaultWindow {buffer} \ 513{ 514 if {[haswindow $buffer]} \ 515 { 516 settopwindow $buffer; # if it was already open, then just put it to the top 517 } \ 518 else \ 519 { 520 if {[LowPriority $buffer]} \ 521 { 522 set tabSize 4 523 set schemeName "Low Priority" 524 set mapName "" 525 } \ 526 else \ 527 { 528 set temp [GetDefaultStyleInfo $buffer] 529 set tabSize [lindex $temp 1] 530 set schemeName [lindex $temp 2] 531 set mapName [lindex $temp 3] 532 } 533 OpenStaggeredWindow $buffer $tabSize $schemeName $mapName 534 } 535} 536 537# Return a good name for a new window. 538proc NewWindowName {} \ 539{ 540 global untitledCounter; # reference the global 541 set name "Untitled-$untitledCounter"; # get new name 542 incr untitledCounter; # next time, make the count one larger 543 return $name; # return the name of the new window 544} 545 546# Create a new window with a default name, return the name. 547proc NewWindow {} \ 548{ 549 OpenDefaultWindow [set name [newbuffer [NewWindowName]]]; # open a new window with new name 550 return $name; # return the name of the new window 551} 552 553# Open the passed file name into a buffer, and record the modification time 554# of the file into the variable "mtime" attached to the buffer 555# if there is a problem, fail just like openbuffer would 556proc OpenBufferRecordMtime {file} \ 557{ 558 if {[catch {openbuffer $file} message]==0} \ 559 { 560 # see if there is ALREADY a modification time tag associated with this file, if so, check against current mtime and complain if they differ 561 # NOTE: there could already be a variable assigned if the file was open already 562 if {[catch {getbuffervariable $message mtime} oldmtime]==0} \ 563 { 564 if {[catch {file mtime $message} newmtime]==0} \ 565 { 566 if {$oldmtime!=$newmtime} \ 567 { 568 okdialog "WARNING!\n\nIt looks like another application modified:\n$message\nwhile it was open for editing.\n" 569 } 570 } \ 571 else \ 572 { 573 okdialog "WARNING!\n\nA buffer exists for the requested file:\n$message\nBut could not read mtime.\n" 574 } 575 } \ 576 else \ 577 { 578 catch {setbuffervariable $message mtime [file mtime $message]}; 579 } 580 return $message; 581 } \ 582 else \ 583 { 584 return -code error $message; 585 } 586} 587 588# Attempt to open a list of files one at a time. 589# If any fails to open, report why, and give the user a chance to cancel. 590proc OpenList {list} \ 591{ 592 set numItems [llength $list] 593 set item 0 594 while {$item<$numItems} \ 595 { 596 set file [lindex $list $item] 597 incr item 598 if {[catch {OpenDefaultWindow [OpenBufferRecordMtime $file]} errorMessage]!=0} \ 599 { 600 if {$item==$numItems} \ 601 { 602 okdialog "Failed to open '$file'\n$errorMessage" 603 } \ 604 else \ 605 { 606 okcanceldialog "Failed to open '$file'\n$errorMessage\n\nContinue?" 607 } 608 } 609 } 610} 611 612# Given an "filename" from a list, try to interpret it as the output from 613# an GNU tool: 614# filename:nnnn 615# If it looks like that, then extract the filename and line number 616# and return them in a list, otherwise return an error 617proc SmartOpenListGNU {listItem} \ 618{ 619 if {[regexp {^([^:]+):([0-9]+)} $listItem whole tempFile tempLine]} \ 620 { 621 if {[file exists $tempFile]} \ 622 { 623 lappend temp $tempFile $tempLine; # make a list of 2 elements (filename and line number) 624 lappend temp2 $temp; # return list of lists 625 return $temp2; 626 } 627 } 628 return -code error; 629} 630 631# Given an "filename" from a list, try to interpret it as the output from 632# an MPW tool: 633# File filename;Line nnnn 634# If it looks like that, then extract the filename and line number 635# and return them in a list, otherwise return an error 636proc SmartOpenListMPW {listItem} \ 637{ 638 if {[regexp {^File *'?([^' ]+)'? *; *Line *([0-9]+)} $listItem whole tempFile tempLine]} \ 639 { 640 if {[file exists $tempFile]} \ 641 { 642 lappend temp $tempFile $tempLine; # make a list of 2 elements (filename and line number) 643 lappend temp2 $temp; # return list of lists 644 return $temp2; 645 } 646 } 647 return -code error; 648} 649 650# Given an "filename" from a list, try to interpret it as the output from 651# a Visual Studio tool: 652# filename(nnnn) 653# If it looks like that, then extract the filename and line number 654# and return them in a list, otherwise return an error 655proc SmartOpenListVisualStudio {listItem} \ 656{ 657 if {[regexp {^([^ (]+) *\(([0-9]+)\)} $listItem whole tempFile tempLine]} \ 658 { 659 if {[file exists $tempFile]} \ 660 { 661 lappend temp $tempFile $tempLine; # make a list of 2 elements (filename and line number) 662 lappend temp2 $temp; # return list of lists 663 return $temp2; 664 } 665 } 666 return -code error; 667} 668 669# Given an "filename" from a list, try to interpret it as a 'C' include 670# statement: 671# #include <filename> (looks in /usr/include) 672# #include "filename" (looks in current directory) 673# If it looks like that, then extract the filename 674# and return it, otherwise return an error 675proc SmartOpenListInclude {listItem} \ 676{ 677 if {[regexp "^\[ \t\]*#\[ \t\]*include\[ \t\]+\\<(\[^>\]+)\\>" $listItem whole tempFile]} \ 678 { 679 lappend temp "/usr/include/$tempFile" 680 lappend temp2 $temp; # return list of lists 681 return $temp2; 682 } \ 683 else \ 684 { 685 if {[regexp "^\[ \t\]*#\[ \t\]*include\[ \t\]+\"(\[^\"\]+)\"" $listItem whole tempFile]} \ 686 { 687 lappend temp $tempFile; 688 lappend temp2 $temp; # return list of lists 689 return $temp2; 690 } 691 } 692 return -code error; 693} 694 695# Given an "filename" from a list, try to interpret it as a globbed list 696# of names. 697# If it looks like that, then extract the filename 698# and return it, otherwise return an error 699proc SmartOpenListGlob {listItem} \ 700{ 701 if {[catch {glob $listItem} globList]==0} \ 702 { 703 return $globList; 704 } 705 return -code error; 706} 707 708# Just like OpenList, but uses an array of functions to try to identify filenames 709# with line numbers that might appear in various forms. 710# If it can find a line number, then it opens the file to that line. 711proc SmartOpenList {list} \ 712{ 713 set numItems [llength $list] 714 set item 0 715 while {$item<$numItems} \ 716 { 717 set listItem [lindex $list $item] 718 incr item 719 set claimed 0 720 721 # strip off newline if it exists 722 regexp "^(\[^\n\]+)" $listItem whole listItem; 723 724 foreach procListElement {SmartOpenListGNU SmartOpenListMPW SmartOpenListVisualStudio SmartOpenListInclude SmartOpenListGlob} \ 725 { 726 # see if one of the functions will claim this item as its own 727 if {[catch {set results [$procListElement $listItem]} errorMessage]==0} \ 728 { 729 set numResults [llength $results] 730 set resultIndex 0 731 while {$resultIndex<$numResults} \ 732 { 733 set result [lindex $results $resultIndex]; # pick out one of the file/line pairs from the return result 734 incr resultIndex; 735 set file [lindex $result 0]; # get the pieces 736 set line [lindex $result 1] 737 738 if {[catch {OpenDefaultWindow [set newBuffer [OpenBufferRecordMtime $file]]} errorMessage]==0} \ 739 { 740 if {[string length $line]!=0} \ 741 { 742 selectline $newBuffer $line; 743 HomeWindowToSelectionStart $newBuffer; 744 } 745 } \ 746 else \ 747 { 748 if {$item==$numItems&&$resultIndex==$numResults} \ 749 { 750 okdialog "Failed to open '$file'\n$errorMessage" 751 } \ 752 else \ 753 { 754 okcanceldialog "Failed to open '$file'\n$errorMessage\n\nContinue?" 755 } 756 } 757 } 758 set claimed 1; 759 break; # had a function claim the list element, so stop searching 760 } 761 } 762 if {$claimed==0} \ 763 { 764 if {[catch {OpenDefaultWindow [set newBuffer [OpenBufferRecordMtime $listItem]]} errorMessage]!=0} \ 765 { 766 if {$item==$numItems} \ 767 { 768 okdialog "Failed to open '$listItem'\n$errorMessage" 769 } \ 770 else \ 771 { 772 okcanceldialog "Failed to open '$listItem'\n$errorMessage\n\nContinue?" 773 } 774 } 775 } 776 } 777} 778 779# Attempt to include a list of files one at a time, into the given buffer. 780# If any fails to include, report why, and give the user a chance to cancel. 781proc IncludeList {buffer list} \ 782{ 783 set numItems [llength $list] 784 set item 0 785 786 while {$item<$numItems} \ 787 { 788 set file [lindex $list $item] 789 incr item 790 if {[catch {insertfile $buffer $file} errorMessage]!=0} \ 791 { 792 if {$item==$numItems} \ 793 { 794 okdialog "Failed to include '$file'\n$errorMessage" 795 } \ 796 else \ 797 { 798 okcanceldialog "Failed to include '$file'\n$errorMessage\n\nContinue?" 799 } 800 } 801 } 802} 803 804# Swap the top two windows on the screen. 805proc SwapWindows {} \ 806{ 807 set windowList [windowlist] 808 if {[llength $windowList]>1} \ 809 { 810 settopwindow [lindex $windowList 1] 811 } \ 812 elseif {[llength $windowList]>0} \ 813 { 814 settopwindow [lindex $windowList 0] 815 } \ 816 else \ 817 { 818 beep 819 } 820} 821 822# Bring the bottom window to the top. 823proc RotateWindows {} \ 824{ 825 set windowList [windowlist] 826 set numWindows [llength $windowList] 827 if {$numWindows>1} \ 828 { 829 incr numWindows -1 830 settopwindow [lindex $windowList $numWindows] 831 } \ 832 elseif {$numWindows>0} \ 833 { 834 settopwindow [lindex $windowList 0] 835 } \ 836 else \ 837 { 838 beep 839 } 840} 841 842# Choose a window to be top-most (this places a * next to windows which have 843# been modified) 844proc ChooseWindow {} \ 845{ 846 set newList ""; 847 foreach window [windowlist]\ 848 { 849 if {[isdirty $window]} \ 850 { 851 lappend newList "* $window"; 852 } \ 853 else \ 854 { 855 lappend newList " $window"; 856 } 857 } 858 foreach window [listdialog "Choose a Window:" $newList] \ 859 { 860 settopwindow [string range $window 2 end]; # select the window (removing the modified indication) 861 } 862} 863 864# Return the active window if there is one, otherwise 865# just beep, and return an error. 866proc ActiveWindowOrBeep {} \ 867{ 868 if {[catch {activewindow} message]==0} \ 869 { 870 return $message 871 } 872 beep 873 return -code error 874} 875 876# Return the current clipboard if there is one, otherwise 877# just beep, and return an error. 878proc CurrentClipboardOrBeep {} \ 879{ 880 if {[catch {getclipboard} message]==0} \ 881 { 882 return $message 883 } 884 beep 885 return -code error 886} 887 888# Report the current clipboard, or a message that indicates that 889# there is none 890proc ShowCurrentClipboard {} \ 891{ 892 if {[catch {getclipboard} message]==0} \ 893 { 894 okdialog "Current clipboard:\n\n$message" 895 } \ 896 else \ 897 { 898 okdialog "There is no current clipboard" 899 } 900} 901 902# Quiz user to find out if he really wants to "revert". 903proc AskRevert {buffer} \ 904{ 905 if {[isdirty $buffer]} \ 906 { 907 okcanceldialog "Do you really want to discard changes to:\n'$buffer'" 908 revertbuffer $buffer 909 if {[fromfile $buffer]} \ 910 { 911 catch {setbuffervariable $buffer mtime [file mtime $buffer]}; # update the modification time so we can look at it when saving 912 } 913 } \ 914 else \ 915 { 916 revertbuffer $buffer; # may be reverting because the file was changed, so just do it without asking 917 if {[fromfile $buffer]} \ 918 { 919 catch {setbuffervariable $buffer mtime [file mtime $buffer]}; # update the modification time so we can look at it when saving 920 } 921 } 922} 923 924# Get name of file to "save as", then do it for the given buffer. 925# NOTE: this returns the new name of the buffer if it completes successfully. 926proc AskSaveAs {buffer} \ 927{ 928 set newPath [savedialog "Save File:" $buffer] 929 if {[file exists $newPath]} \ 930 { 931 okcanceldialog "File:\n'$newPath'\nalready exists. Overwrite?" 932 } 933 if {[catch {savebufferas $buffer $newPath} message]==0} \ 934 { 935 catch {setbuffervariable $message mtime [file mtime $message]}; # update the modification time so we can look at it when saving 936 } \ 937 else \ 938 { 939 okdialog "Failed to save:\n'$newPath'\n$message" 940 return -code error 941 } 942 UpdateStyle $message; # update the styles of this window 943 return $message; # return the new name 944} 945 946# Get name of file to "save to", then do it for the given buffer. 947proc AskSaveTo {buffer} \ 948{ 949 set newPath [savedialog "Save Copy To:" $buffer] 950 if {[file exists $newPath]} \ 951 { 952 okcanceldialog "File:\n'$newPath'\nalready exists. Overwrite?" 953 } 954 if {[catch {savebufferto $buffer $newPath} errorMessage]!=0} \ 955 { 956 okdialog "Failed to save:\n'$newPath'\n$errorMessage" 957 return -code error 958 } 959} 960 961# See if buffer is not linked to a file, and if not, ask for 962# a file name to save it to, else just save it. 963# Either way, return the name of the buffer after it is saved, 964# as it may have changed during the save process. 965proc AskSave {buffer} \ 966{ 967 if {[fromfile $buffer]} \ 968 { 969 # see if there is a modification time tag associated with this file, if so, check against current mtime and complain if they differ 970 if {[catch {getbuffervariable $buffer mtime} oldmtime]==0} \ 971 { 972 if {[catch {file mtime $buffer} newmtime]==0} \ 973 { 974 if {$oldmtime!=$newmtime} \ 975 { 976 okcanceldialog "WARNING!\n\nIt looks like another application modified:\n$buffer\nwhile it was open for editing.\n\nWould you like to save anyway?" 977 } 978 } \ 979 else \ 980 { 981 okcanceldialog "WARNING!\n\nIt looks like another application deleted:\n$buffer\nwhile it was open for editing.\n\nWould you like to save anyway?" 982 } 983 } 984 985 if {[catch {savebuffer $buffer} message]==0} \ 986 { 987 catch {setbuffervariable $buffer mtime [file mtime $buffer]}; # update the modification time so we can look at it next time we save 988 } \ 989 else \ 990 { 991 okdialog "Failed to save:\n'$buffer'\n$message" 992 return -code error 993 } 994 } \ 995 else \ 996 { 997 set buffer [AskSaveAs $buffer]; # pick up the new name of the buffer 998 } 999 return $buffer 1000} 1001 1002# Ask the user if he really wants to save all the dirty windows, if so, do it. 1003proc AskSaveAll {} \ 1004{ 1005 ActiveWindowOrBeep; # make sure there is a window, if not, just beep and leave 1006 okcanceldialog "Really save all modified windows?" 1007 foreach window [windowlist] \ 1008 { 1009 if {[isdirty $window]} \ 1010 { 1011 if {[catch {AskSave $window}]!=0} \ 1012 { 1013 okdialog "Save All aborted\n" 1014 return -code error 1015 } 1016 } 1017 } 1018} 1019 1020# See if buffer is dirty before closing. 1021# If it is, give user a chance to save. 1022proc AskClose {buffer} \ 1023{ 1024 # See if buffer points to a something low-priority, we just close the windows on them, not the buffer 1025 if {[LowPriority $buffer]} \ 1026 { 1027 closewindow $buffer 1028 } \ 1029 else \ 1030 { 1031 if {[isdirty $buffer]} \ 1032 { 1033 settopwindow $buffer; # pop it to the top of the window stack 1034 1035 if {[yesnodialog "Save Changes To:\n'$buffer'\nBefore Closing?"]} \ 1036 { 1037 set buffer [AskSave $buffer]; # if it is saved, get the new name so we can close it 1038 } 1039 } 1040 closebuffer $buffer 1041 } 1042} 1043 1044# Ask for a list of windows which should be printed 1045proc PrintWindows {} \ 1046{ 1047 global defaultPrintCommand; 1048 1049 foreach buffer [listdialog "Choose Window(s) to Print:" [windowlist]] \ 1050 { 1051 set command [textdialog "If needed, modify the print command below:" "[eval format "%s" \"$defaultPrintCommand\"]"] 1052 setmark $buffer temp; # remember what was selected, we will not disturb it 1053 selectall $buffer; # make a selection of all of the text in the passed buffer 1054 if {[catch {eval exec $command << {[lindex [selectedtextlist $buffer] 0]}} result]!=0} \ 1055 { 1056 okdialog "Print status:\n\n$result\n" 1057 } 1058 gotomark $buffer temp; # put selection back 1059 closemark $buffer temp; # get rid of temp selection 1060 } 1061} 1062 1063# Attempt to get lpr to output this document to the local printer 1064proc PrintBuffer {buffer} \ 1065{ 1066 global defaultPrintCommand; 1067 1068 set command [textdialog "If needed, modify the print command below:" "[eval format "%s" \"$defaultPrintCommand\"]"] 1069 setmark $buffer temp; # remember what was selected, we will not disturb it 1070 selectall $buffer; # make a selection of all of the text in the passed buffer 1071 if {[catch {eval exec $command << {[lindex [selectedtextlist $buffer] 0]}} result]!=0} \ 1072 { 1073 okdialog "Print status:\n\n$result\n" 1074 } 1075 gotomark $buffer temp; # put selection back 1076 closemark $buffer temp; # get rid of temp selection 1077} 1078 1079# print the first selection to the local printer 1080proc PrintSelection {buffer} \ 1081{ 1082 global defaultPrintCommand; 1083 1084 if {[lindex [selectioninfo $buffer] 6]} \ 1085 { 1086 set command [textdialog "If needed, modify the print command below:" "[eval format "%s" \"$defaultPrintCommand\"]"] 1087 if {[catch {eval exec $command << {[lindex [selectedtextlist $buffer] 0]}} result]!=0} \ 1088 { 1089 okdialog "Print status:\n\n$result\n" 1090 } 1091 } \ 1092 else \ 1093 { 1094 beep 1095 } 1096} 1097 1098# Attempt to close all open windows, asking to save any that are dirty. 1099# If the user cancels, then back out, otherwise, quit. 1100proc TryToQuit {} \ 1101{ 1102 foreach window [windowlist] \ 1103 { 1104 AskClose $window 1105 } 1106 forceQUIT 1107} 1108 1109# Just like find, but will place the result in a dialog if it fails, and home if it succeeds, or beep if it finds nothing. 1110proc FindBeep {window buffer args} \ 1111{ 1112 if {[catch {eval [list find $window $buffer] $args} message]==0} \ 1113 { 1114 if {[llength $message]} {homewindow $window [lindex $message 0] [lindex $message 1]} else {beep} 1115 } \ 1116 else \ 1117 { 1118 okdialog $message 1119 } 1120} 1121 1122# Just like findall, but will place the result in a dialog if it fails, and home if it succeeds, or beep if it finds nothing. 1123proc FindAllBeep {window buffer args} \ 1124{ 1125 if {[catch {eval [list findall $window $buffer] $args} message]==0} \ 1126 { 1127 if {[llength $message]} {homewindow $window [lindex $message 0] [lindex $message 1]} else {beep} 1128 } \ 1129 else \ 1130 { 1131 okdialog $message 1132 } 1133} 1134 1135# Just like replace, but will place the result in a dialog if it fails, and home if it succeeds, or beep if it finds nothing. 1136proc ReplaceBeep {window findBuffer replaceBuffer args} \ 1137{ 1138 if {[catch {eval [list replace $window $findBuffer $replaceBuffer] $args} message]==0} \ 1139 { 1140 if {[llength $message]} {homewindow $window [lindex $message 0] [lindex $message 1]} else {beep} 1141 } \ 1142 else \ 1143 { 1144 okdialog $message 1145 } 1146} 1147 1148# Just like replaceall, but will place the result in a dialog if it fails, and home if it succeeds, or beep if it finds nothing. 1149proc ReplaceAllBeep {window findBuffer replaceBuffer args} \ 1150{ 1151 if {[catch {eval [list replaceall $window $findBuffer $replaceBuffer] $args} message]==0} \ 1152 { 1153 if {[llength $message]} {homewindow $window [lindex $message 0] [lindex $message 1]} else {beep} 1154 } \ 1155 else \ 1156 { 1157 okdialog $message 1158 } 1159} 1160 1161# Turn the booleans that come back from the search dialog into flags which can be passed 1162# to the search functions 1163proc CreateSearchOptions {} \ 1164{ 1165 global sd_backwards sd_wrapAround sd_selectionExpression sd_ignoreCase sd_limitScope sd_replaceProc 1166 1167 set result "" 1168 if {$sd_backwards!=0} \ 1169 { 1170 lappend result "-backward"; 1171 } 1172 if {$sd_wrapAround!=0} \ 1173 { 1174 lappend result "-wrap"; 1175 } 1176 if {$sd_selectionExpression!=0} \ 1177 { 1178 lappend result "-regex"; 1179 } 1180 if {$sd_ignoreCase!=0} \ 1181 { 1182 lappend result "-ignorecase"; 1183 } 1184 if {$sd_limitScope!=0} \ 1185 { 1186 lappend result "-limitscope"; 1187 } 1188 if {$sd_replaceProc!=0} \ 1189 { 1190 lappend result "-replacescript"; 1191 } 1192 return $result 1193} 1194 1195# Ask the user just what he wishes to search for, and how, then do it in all open windows if he does not cancel. 1196proc AskSearchAll {} \ 1197{ 1198 global sd_backwards sd_wrapAround sd_selectionExpression sd_ignoreCase sd_limitScope sd_replaceProc 1199 1200 set searchType [searchdialog "" findBuffer replaceBuffer sd_backwards sd_wrapAround sd_selectionExpression sd_ignoreCase sd_limitScope sd_replaceProc] 1201 foreach window [windowlist] \ 1202 { 1203 switch $searchType \ 1204 { 1205 find 1206 { 1207 eval [list FindBeep $window findBuffer] [CreateSearchOptions] 1208 } 1209 findall 1210 { 1211 eval [list FindAllBeep $window findBuffer] [CreateSearchOptions] 1212 } 1213 replace 1214 { 1215 eval [list ReplaceBeep $window findBuffer replaceBuffer] [CreateSearchOptions] 1216 } 1217 replaceall 1218 { 1219 eval [list ReplaceAllBeep $window findBuffer replaceBuffer] [CreateSearchOptions] 1220 } 1221 } 1222 } 1223 okdialog "All windows completed" 1224} 1225 1226# Ask the user just what he wishes to search for, and how, then do it if he does not cancel. 1227proc AskSearch {window} \ 1228{ 1229 global sd_backwards sd_wrapAround sd_selectionExpression sd_ignoreCase sd_limitScope sd_replaceProc 1230 1231 set searchType [searchdialog "" findBuffer replaceBuffer sd_backwards sd_wrapAround sd_selectionExpression sd_ignoreCase sd_limitScope sd_replaceProc] 1232 switch $searchType \ 1233 { 1234 find 1235 { 1236 eval [list FindBeep $window findBuffer] [CreateSearchOptions] 1237 } 1238 findall 1239 { 1240 eval [list FindAllBeep $window findBuffer] [CreateSearchOptions] 1241 } 1242 replace 1243 { 1244 eval [list ReplaceBeep $window findBuffer replaceBuffer] [CreateSearchOptions] 1245 } 1246 replaceall 1247 { 1248 eval [list ReplaceAllBeep $window findBuffer replaceBuffer] [CreateSearchOptions] 1249 } 1250 } 1251} 1252 1253# Used for find same backwards/forwards. 1254proc FindNext {window backward} \ 1255{ 1256 set flags [CreateSearchOptions] 1257 # if asked to search backwards, then add this flag to the list 1258 if {$backward!=0} \ 1259 { 1260 lappend flags "-backward" 1261 } \ 1262 else \ 1263 { 1264 lappend flags "-forward" 1265 } 1266 eval [list FindBeep $window findBuffer] $flags 1267} 1268 1269# if selection then first copy the selection and then do FindAllBeep 1270# if no selection then try to find what is in the findBuffer 1271proc FindSelectionNext {window backward} \ 1272{ 1273 set ends [getselectionends $window] 1274 set start [lindex $ends 0] 1275 set end [lindex $ends 1] 1276 if {$start!=$end} \ 1277 { 1278 copy $window findBuffer 1279 } 1280 FindNext $window $backward 1281} 1282 1283# Used for replace same backwards/forwards. 1284proc ReplaceNext {window backward} \ 1285{ 1286 set flags [CreateSearchOptions] 1287 # if asked to search backwards, then add this flag to the list 1288 if {$backward!=0} \ 1289 { 1290 lappend flags "-backward" 1291 } \ 1292 else \ 1293 { 1294 lappend flags "-forward" 1295 } 1296 eval [list ReplaceBeep $window findBuffer replaceBuffer] $flags 1297} 1298 1299# Replace all selections with some given text. 1300proc ReplaceSelections {window} \ 1301{ 1302 global replaceSelectionsChoice; 1303 1304 TextToBuffer tempFindBuffer {([^]+)}; # load up the expression (find anything, mark as \0) 1305 TextToBuffer tempReplaceBuffer [set replaceSelectionsChoice [textdialog "Replacement string?" $replaceSelectionsChoice]]; # load up the replacement 1306 ReplaceAllBeep $window tempFindBuffer tempReplaceBuffer -regex -limitscope; # do the replacement 1307} 1308 1309# Shift the text but attempt to leave the selection as little disturbed as possible 1310proc HandleShifts {buffer} \ 1311{ 1312 set numSelections [lindex [selectioninfo $buffer] 6] 1313 1314 if {$numSelections>0} \ 1315 { 1316 # if one selection, try not to "columnarize" it 1317 if {$numSelections==1} \ 1318 { 1319 catch {closebuffer tempBuffer}; # get rid of any lingering tempBuffer 1320 newbuffer tempBuffer; # create a place to do some messing around in 1321 copy $buffer tempBuffer; # move text in question to temp buffer 1322 setselectionends tempBuffer 0 0; # move to top for replace 1323 1324 set start [lindex [getselectionends $buffer] 0]; # get start of selection 1325 1326 if {[catch {replaceall tempBuffer tempFindBuffer tempReplaceBuffer -regex} message]==0} \ 1327 { 1328 if {[llength $message]} \ 1329 { 1330 setselectionends tempBuffer 0 0; # get rid of selections in temp buffer so paste does what we want 1331 paste $buffer tempBuffer; # place results back, write over old selection 1332 set length [lindex [textinfo tempBuffer] 1] 1333 setselectionends $buffer $start [expr $start+$length] ; # re-select the block 1334 } \ 1335 else \ 1336 { 1337 beep 1338 } 1339 } \ 1340 else \ 1341 { 1342 okdialog $message 1343 } 1344 closebuffer tempBuffer; 1345 } \ 1346 else \ 1347 { 1348 if {[catch {replaceall $buffer tempFindBuffer tempReplaceBuffer -regex -limitscope} message]==0} \ 1349 { 1350 if {[llength $message]==0} {beep} 1351 } \ 1352 else \ 1353 { 1354 okdialog $message 1355 } 1356 } 1357 } \ 1358 else \ 1359 { 1360 beep 1361 } 1362} 1363 1364# Align text left, removing all tabs or spaces at the start of lines in the selection. 1365proc AlignLeft {buffer} \ 1366{ 1367 TextToBuffer tempFindBuffer {^[\t ]+(.*)|(.+)}; # load up the expression 1368 TextToBuffer tempReplaceBuffer {\0\1}; # load up the replacement 1369 HandleShifts $buffer; 1370} 1371 1372# Shift text left, removing tabs or spaces at the start of lines in the selection. 1373proc ShiftLeft {buffer} \ 1374{ 1375 TextToBuffer tempFindBuffer {^[\t ](.*)|(.+)}; # load up the expression (expression is slightly strange, so that lines which are not altered are not deselected) 1376 TextToBuffer tempReplaceBuffer {\0\1}; # load up the replacement 1377 HandleShifts $buffer; 1378} 1379 1380# Shift text right, adding tabs at the start of lines in the selection. 1381proc ShiftRight {buffer} \ 1382{ 1383 TextToBuffer tempFindBuffer {^(.+)}; # load up the expression 1384 TextToBuffer tempReplaceBuffer { \0}; # load up the replacement 1385 HandleShifts $buffer; 1386} 1387 1388# Unselect any whitspace which is currently selected. 1389# This is sometimes useful during columnar select when tabs or spaces 1390# get in the way 1391proc UnselectWhitespace {buffer} \ 1392{ 1393 TextToBuffer tempFindBuffer {[^ \t\n]+}; # load up the expression to match any non-white characters 1394 if {[catch {findall $buffer tempFindBuffer -regex -limitscope} message]==0} \ 1395 { 1396 if {[llength $message]==0} \ 1397 { 1398 # no non-white characters were located, so selection is ALL white, just eliminate the selection 1399 set start [lindex [getselectionends $buffer] 0]; # get start of selection 1400 setselectionends $buffer $start $start; # reduce selection to nothing 1401 } 1402 } \ 1403 else \ 1404 { 1405 okdialog $message 1406 } 1407} 1408 1409# Report interesting information about the passed buffer 1410proc BufferInfo {buffer} \ 1411{ 1412 set textInfo [textinfo $buffer] 1413 set textLines [lindex $textInfo 0] 1414 set textChars [lindex $textInfo 1] 1415 1416 set selectionInfo [selectioninfo $buffer] 1417 set startPosition [lindex $selectionInfo 0] 1418 set endPosition [lindex $selectionInfo 1] 1419 set startLine [lindex $selectionInfo 2] 1420 set endLine [lindex $selectionInfo 3] 1421 set startLinePosition [lindex $selectionInfo 4] 1422 set endLinePosition [lindex $selectionInfo 5] 1423 set totalSegments [lindex $selectionInfo 6] 1424 set totalSpan [lindex $selectionInfo 7] 1425 1426 if {$endLinePosition&&$totalSpan} \ 1427 { 1428 set totalLines [expr $endLine-$startLine+1]; # this is kind of screwy, but it gives the results that are easiest for the user to understand 1429 } \ 1430 else \ 1431 { 1432 set totalLines [expr $endLine-$startLine] 1433 } 1434 1435 okdialog "\ 1436$buffer\n\n\ 1437Tab stops [gettabsize $buffer]\n\ 1438Total lines $textLines\n\ 1439Total bytes $textChars\n\ 1440Selection start position $startPosition ($startLine:$startLinePosition)\n\ 1441Selection end position $endPosition ($endLine:$endLinePosition)\n\ 1442Total selection segments $totalSegments\n\ 1443Total selected chars $totalSpan\n\ 1444Total lines spanned $totalLines\n" 1445} 1446 1447# Pipe the selections through a unix command, collect output, and replace selections. 1448proc PipeSelection {window} \ 1449{ 1450 global pipeSelectionsChoice; 1451 1452 set command [set pipeSelectionsChoice [textdialog "Enter command to pipe selections through:" $pipeSelectionsChoice]] 1453 TextToBuffer tempFindBuffer {[^]+}; # load up the expression (find absolutely anything) 1454 TextToBuffer tempReplaceBuffer "catch \{exec -keepnewline $command <<\$found\} message; set message"; # load up the replacement, return results of command 1455 ReplaceAllBeep $window tempFindBuffer tempReplaceBuffer -regex -limitscope -replacescript; # do the replacement 1456} 1457 1458# Convert all letters of the given selection to upper case. 1459proc UppercaseSelection window \ 1460{ 1461 TextToBuffer tempFindBuffer {[^]+}; # load up the expression (find anything) 1462 TextToBuffer tempReplaceBuffer "string toupper \$found"; # load up the replacement 1463 ReplaceAllBeep $window tempFindBuffer tempReplaceBuffer -regex -limitscope -replacescript; # do the replacement 1464} 1465 1466# Convert all letters of the given selection to lower case. 1467proc LowercaseSelection window \ 1468{ 1469 TextToBuffer tempFindBuffer {[^]+}; # load up the expression (find anything) 1470 TextToBuffer tempReplaceBuffer "string tolower \$found"; # load up the replacement 1471 ReplaceAllBeep $window tempFindBuffer tempReplaceBuffer -regex -limitscope -replacescript; # do the replacement 1472} 1473 1474# Locate all the numbers in the current selection, and increment them by the given amount. 1475proc IncrementSelection {window amount} \ 1476{ 1477 TextToBuffer tempFindBuffer {-?(([0-9]+(\.[0-9]+)?)|(\.[0-9]+))}; # load up the expression (find any (possibly floating point) number including negative ones) 1478 TextToBuffer tempReplaceBuffer "expr [string trimleft \$found 0] + $amount"; # load up the replacement, return the result of adding amount 1479 ReplaceAllBeep $window tempFindBuffer tempReplaceBuffer -regex -limitscope -replacescript; # do the replacement 1480} 1481 1482# Replace each selection by an incrementing number. 1483proc EnumerateSelection {window startAt amount} \ 1484{ 1485 global enumStart 1486 set enumStart $startAt 1487 TextToBuffer tempFindBuffer {.+}; # load up the expression (find anything) 1488 TextToBuffer tempReplaceBuffer "global enumStart;set temp \$enumStart;incr enumStart $amount;format %d \$temp"; # load up the replacement, return an incremented number 1489 ReplaceAllBeep $window tempFindBuffer tempReplaceBuffer -regex -limitscope -replacescript; # do the replacement 1490} 1491 1492# Report the sum of all selected numbers. 1493proc SumSelection {window} \ 1494{ 1495 setmark $window temp; # remember what was selected, we will not disturb it 1496 TextToBuffer tempFindBuffer {-?(([0-9]+(\.[0-9]+)?)|(\.[0-9]+))}; # load up the expression (find any (possibly floating point) number including negative ones) 1497 if {[catch {findall $window tempFindBuffer -regex -limitscope} message]==0} \ 1498 { 1499 if {[llength $message]} \ 1500 { 1501 set total 0 1502 foreach number [selectedtextlist $window] \ 1503 { 1504 set total [expr [string trimleft $number 0]+$total]; # convert number with leading 0's to DECIMAL, not octal! 1505 } 1506 okdialog "Sum = $total" 1507 } \ 1508 else \ 1509 { 1510 beep 1511 } 1512 } \ 1513 else \ 1514 { 1515 okdialog $message 1516 } 1517 gotomark $window temp; # put back the user's selection 1518 closemark $window temp; # get rid of temp selection 1519} 1520 1521# Sort the selections, and replace them in sorted order. 1522proc SortSelection {window} \ 1523{ 1524 global sortedArray sortedIndex 1525 catch {unset sortedArray} 1526 set sortedIndex 0 1527 foreach element [lsort [selectedtextlist $window]] \ 1528 { 1529 set sortedArray($sortedIndex) $element; # copy elements into an array to speed things up 1530 incr sortedIndex 1531 } 1532 set sortedIndex 0 1533 TextToBuffer tempFindBuffer {[^]+}; # load up the expression (find absolutely anything) 1534 TextToBuffer tempReplaceBuffer {global sortedArray sortedIndex;incr sortedIndex;set sortedArray([expr $sortedIndex-1])}; # load up the replacement, return an entry from the array 1535 ReplaceAllBeep $window tempFindBuffer tempReplaceBuffer -regex -limitscope -replacescript; # do the replacement 1536 catch {unset sortedArray} 1537 unset sortedIndex 1538} 1539 1540# Replace the selections in reverse order. 1541proc ReverseSelection {window} \ 1542{ 1543 global reverseArray reverseIndex 1544 catch {unset reverseArray} 1545 set reverseIndex 0 1546 foreach element [selectedtextlist $window] \ 1547 { 1548 set reverseArray($reverseIndex) $element; # copy elements into an array to speed things up 1549 incr reverseIndex 1550 } 1551 TextToBuffer tempFindBuffer {[^]+}; # load up the expression (find absolutely anything) 1552 TextToBuffer tempReplaceBuffer {global reverseArray reverseIndex;incr reverseIndex -1;set reverseArray($reverseIndex)}; # load up the replacement, return an entry from the array 1553 ReplaceAllBeep $window tempFindBuffer tempReplaceBuffer -regex -limitscope -replacescript; # do the replacement 1554 catch {unset reverseArray} 1555 unset reverseIndex 1556} 1557 1558# Get a manual page, and dump it into a window. 1559proc ManPage params \ 1560{ 1561 global staggerOpenX staggerOpenY windowHeight style_keyword style_string 1562 1563 set name [newbuffer [NewWindowName]]; # make a buffer to hold the man page 1564 # move stdin to /dev/null so that man won't look at current terminal width 1565 execute $name "catch \{exec man -Tascii $params </dev/null\} result; set result"; 1566 1567# man thinks it is outputing to a printer where it can backspace over stuff to get effects 1568# like BOLD, or dot points. The replace strips out the mess 1569 1570# first, go through and make keywords out of anything man was trying to make bold 1571 setselectionends $name 0 0; # move to the top of the man page buffer 1572 TextToBuffer tempFindBuffer {((.)\x08\1)+}; # load up the expression 1573 catch {findall $name tempFindBuffer -regex}; # do this, ignore any errors 1574 selectiontostyle $name $style_keyword; # set what we found to style_keyword 1575 1576# now, go through and make strings out of anything man was trying to make underlines 1577 setselectionends $name 0 0; # move to the top of the man page buffer 1578 TextToBuffer tempFindBuffer {(_\x08[^\n_])+}; # load up the expression 1579 catch {findall $name tempFindBuffer -regex}; # do this, ignore any errors 1580 selectiontostyle $name $style_string; # set what we found to style_string 1581 1582# remove all the backspace characters 1583 setselectionends $name 0 0; # move to the top of the man page buffer 1584 TextToBuffer tempFindBuffer {.\x08}; # load up the expression 1585 TextToBuffer tempReplaceBuffer {}; # replace with nothing 1586 catch {replaceall $name tempFindBuffer tempReplaceBuffer -regex}; # do this, ignore any errors 1587 1588# replace special double-quote chars 1589 setselectionends $name 0 0; # move to the top of the man page buffer 1590 TextToBuffer tempFindBuffer {(\xE2\x80[\x98,\x99]){2}}; # load up the expression 1591 TextToBuffer tempReplaceBuffer {"}; # replace with nothing 1592 catch {replaceall $name tempFindBuffer tempReplaceBuffer -regex}; # do this, ignore any errors 1593 1594# replace special single-quote chars 1595 setselectionends $name 0 0; # move to the top of the man page buffer 1596 TextToBuffer tempFindBuffer {\xE2\x80[\x98,\x99]}; # load up the expression 1597 TextToBuffer tempReplaceBuffer {'}; # replace with nothing 1598 catch {replaceall $name tempFindBuffer tempReplaceBuffer -regex}; # do this, ignore any errors 1599 1600# get rid of any huge page gaps 1601 setselectionends $name 0 0; # move to the top of the buffer again 1602 TextToBuffer tempFindBuffer {^\n{2,}}; # load up the expression 1603 TextToBuffer tempReplaceBuffer "\n"; # replace with nothing 1604 catch {replaceall $name tempFindBuffer tempReplaceBuffer -regex}; # do this, ignore any errors 1605 setselectionends $name 0 0; # move to the top of the buffer again 1606 1607 flushundos $name; # get rid of any undos we made here, just to be nice 1608 cleardirty $name; # make it non-modified 1609 1610 OpenWindow $name $staggerOpenX $staggerOpenY [expr 8*80] $windowHeight 8 "Man Page" "" 1611 UpdateStaggerPosition; 1612} 1613 1614# Refill a selected paragraph(s), so that the lines of text do not extend past the given 1615# column. This is a little ugly, but it does the job quite nicely. This also works if the 1616# selection is columnar (can be used to refill comments) 1617proc RefillSelection buffer \ 1618{ 1619 global refillLimitChoice; 1620 1621 set limit [expr [set refillLimitChoice [textdialog "Max length:" $refillLimitChoice]]]; # get length limit from user 1622 1623 set ends [getselectionends $buffer] 1624 set start [lindex $ends 0] 1625 set end [lindex $ends 1] 1626 if {$start!=$end} \ 1627 { 1628 catch {closebuffer tempBuffer}; # get rid of any lingering tempBuffer 1629 newbuffer tempBuffer; # create a place to do some messing around in 1630 copy $buffer tempBuffer; # move text in question to temp buffer 1631 1632 TextToBuffer tempFindBuffer "(^\[ \\t\]+)|(\[ \t\]+$)"; # remove white space at starts and ends of lines 1633 TextToBuffer tempReplaceBuffer {}; 1634 setselectionends tempBuffer 0 0; # move to top for replace 1635 catch {replaceall tempBuffer tempFindBuffer tempReplaceBuffer -regex}; # do this, ignore any errors 1636 1637 TextToBuffer tempFindBuffer "\[ \\t\]+"; # make tabs, or multiple spaces into single spaces 1638 TextToBuffer tempReplaceBuffer { }; 1639 setselectionends tempBuffer 0 0; # move to top for replace 1640 catch {replaceall tempBuffer tempFindBuffer tempReplaceBuffer -regex}; # do this, ignore any errors 1641 1642 TextToBuffer tempFindBuffer "(^\\n)|(\\n)"; # make all newlines at the ends of lines into spaces 1643 TextToBuffer tempReplaceBuffer {if {[string length $1] > 0} {set found { }}; set found}; 1644 selectall tempBuffer; # select all so replace will start at the bottom (replacing backwards) 1645 catch {replaceall tempBuffer tempFindBuffer tempReplaceBuffer -backward -regex -replacescript}; # do this, ignore any errors 1646 1647 TextToBuffer tempFindBuffer "(.\{1,$limit\})((\[ \\t\]+)|(.$))"; # cut lines to length at whitespace 1648 TextToBuffer tempReplaceBuffer {if {[string length $2] > 0} {format "%s\n" $0} else {format "%s%s" $0 $3}}; 1649 setselectionends tempBuffer 0 0; # move to top for replace 1650 catch {replaceall tempBuffer tempFindBuffer tempReplaceBuffer -regex -replacescript}; # do this, ignore any errors 1651 1652 setselectionends tempBuffer 0 0; # move to top of temp buffer 1653 1654 set startNumSelections [lindex [selectioninfo $buffer] 6]; 1655 if {$startNumSelections>1} \ 1656 { 1657 TextToBuffer tempFindBuffer "^.*$"; # select all the lines individually 1658 catch {findall tempBuffer tempFindBuffer -regex}; # do this, ignore any errors 1659 1660 set endNumSelections [lindex [selectioninfo tempBuffer] 6]; 1661 if {$endNumSelections>$startNumSelections} \ 1662 { 1663 addselectionendlist tempBuffer [list [list [lineoffsettoposition tempBuffer $startNumSelections 0] [lineoffsettoposition tempBuffer [expr $endNumSelections+1] 0]]] 1664 } 1665 } 1666 1667 paste $buffer tempBuffer; # place results back, write over old selection(s) 1668 1669 closebuffer tempBuffer; 1670 } \ 1671 else \ 1672 { 1673 beep; 1674 } 1675} 1676 1677# Check spelling in buffer, make a new window containing the misspelled words. 1678proc SpellDocument buffer \ 1679{ 1680 global staggerOpenX staggerOpenY windowHeight 1681 1682 set name [newbuffer [NewWindowName]]; # make a buffer to hold the output of the spell command 1683 setmark $buffer temp; # remember what was selected, we will not disturb it 1684 selectall $buffer; # make a selection of all of the text in the passed buffer 1685 execute $name {catch {exec aspell list << [lindex [selectedtextlist $buffer] 0] | sort -u} result; set result}; 1686 gotomark $buffer temp; # put selection back 1687 setselectionends $name 0 0; # move to the top of the output buffer 1688 1689 flushundos $name; # get rid of any undos we made here, just to be nice 1690 cleardirty $name; # make it non-modified 1691 openwindow $name $staggerOpenX $staggerOpenY [expr 7*50] $windowHeight "" 8 black lightyellow; # make a new window, set width to roughly 50 columns of an 7 pixel wide font 1692 UpdateStaggerPosition; 1693 closemark $buffer temp; # get rid of temp selection 1694} 1695 1696# Get an address, and mail the contents of buffer 1697# to that address. 1698# NOTE: this would be much better handled with a Tk dialog 1699proc MailDocument buffer \ 1700{ 1701 global mailRecipientChoice; 1702 global mailSubjectChoice; 1703 1704 # get recipient 1705 set recipient [set mailRecipientChoice [textdialog "Mail $buffer To:" $mailRecipientChoice]] 1706 # get subject 1707 set subject [set mailSubjectChoice [textdialog "Subject:" $mailSubjectChoice]] 1708 1709 catch {closebuffer tempBuffer}; # get rid of any lingering tempBuffer 1710 newbuffer tempBuffer; # create temp buffer 1711 setmark $buffer temp; # remember what was selected, we will not disturb it 1712 selectall $buffer; # make a selection of all of the text in the passed buffer 1713 copy $buffer tempBuffer; # copy selection to temp buffer 1714 gotomark $buffer temp; # put selection back 1715 closemark $buffer temp; # get rid of temp selection 1716 setselectionends tempBuffer 0 0; # move to the top of the temp buffer 1717 insert tempBuffer "To: $recipient\nSubject: $subject\n\n"; # insert recipient and subject to buffer 1718 set result 0; # predefine no error happend 1719 selectall tempBuffer; # select what to mail 1720 1721 if {[catch {exec /usr/lib/sendmail -t << [lindex [selectedtextlist tempBuffer] 0]} result]!=0} \ 1722 { 1723 okdialog "Mail status:\n\n$result\n" 1724 } 1725 closebuffer tempBuffer; # get rid of temp buffer 1726} 1727 1728# mail contents of chosen windows to chosen recipients 1729proc MailWindows {} \ 1730{ 1731 foreach buffer [listdialog "Choose Window(s) to Mail:" [windowlist]] \ 1732 { 1733 MailDocument $buffer 1734 } 1735} 1736 1737# Strip the white space at the ends of lines, attempt to leave the selection as it was. 1738# return the number of characters removed 1739proc StripWhite {window} \ 1740{ 1741 set initialChars [lindex [textinfo $window] 1]; # find out how many characters we have at the start 1742 set numRemoved 0; 1743 setmark $window temp; # remember what was selected, we will not disturb it 1744 TextToBuffer tempFindBuffer {[ \t]+$}; # load up the expression 1745 TextToBuffer tempReplaceBuffer {}; # replace with nothing 1746 setselectionends $window 0 0; # move to the top of the buffer to perform the search 1747 if {[catch {replaceall $window tempFindBuffer tempReplaceBuffer -regex} message]==0} \ 1748 { 1749 set finalChars [lindex [textinfo $window] 1]; # find out how many characters we have now that we are done 1750 set numRemoved [expr $initialChars-$finalChars]; 1751 } \ 1752 else \ 1753 { 1754 okdialog $message 1755 } 1756 gotomark $window temp; # put back the user's selection 1757 closemark $window temp; # get rid of temp selection 1758 return $numRemoved 1759} 1760 1761# Set line termination to the given sequence 1762proc SetLineTermination {window termination} \ 1763{ 1764 setmark $window temp; # remember what was selected, we will not disturb it 1765 TextToBuffer tempFindBuffer {\r\n|\r|\n}; # load up the expression 1766 TextToBuffer tempReplaceBuffer $termination; # replace with given characters 1767 setselectionends $window 0 0; # move to the top of the buffer to perform the search 1768 catch {replaceall $window tempFindBuffer tempReplaceBuffer -regex} 1769 gotomark $window temp; # put back the user's selection 1770 closemark $window temp; # get rid of temp selection 1771} 1772 1773# insert a character into window, and then home the window so that 1774# the character is visible 1775proc InsertAndHome {window character} \ 1776{ 1777 insert $window $character; # insert the character 1778 HomeWindowToSelectionStart $window -lenient; # make sure it is visible 1779} 1780 1781# Inserts newline if the cursor position is above a given value 1782# This is a simple way to implement wrapping lines at word boundaries 1783# Thanks to Juergen Reiss 1784proc WrapLine buffer \ 1785{ 1786 global lineWrap; 1787 global lineWrapColumn; 1788 set ends [getselectionends $buffer]; # get end of selection 1789 set start [lindex $ends 0]; # line number 1790 set pos [lindex [positiontolineoffset $buffer $start] 1];# get column number 1791 if {$pos>$lineWrapColumn} \ 1792 { 1793 InsertAndHome $buffer "\n"; # insert newline 1794 } \ 1795 else \ 1796 { 1797 InsertAndHome $buffer " "; # insert space 1798 } 1799} 1800 1801# Changes the status of line-wrapping 1802proc WrapOnOff {} \ 1803{ 1804 global lineWrap; 1805 set temp "off"; 1806 if {$lineWrap} \ 1807 { 1808 set temp "on"; 1809 } 1810 set lineWrap [yesnodialog "Line wrapping is currently '$temp'\nDo you want to have line wrapping on?"]; 1811 if {$lineWrap} \ 1812 { 1813 bindkey space {x0000000000} {WrapLine [ActiveWindowOrBeep]}; # when space is hit, see if above the given column and insert newline if needed 1814 } \ 1815 else \ 1816 { 1817 unbindkey space {x0000000000} 1818 } 1819} 1820 1821# Changes the column at which lines wrap 1822proc WrapNewColumn {} \ 1823{ 1824 global lineWrapColumn; 1825 set lineWrapColumn [expr [textdialog "New line wrap column:" $lineWrapColumn]]; # get new column limit from user 1826} 1827 1828# Get text to evaluate from window, then stick in a newline. 1829proc EvalText {window} \ 1830{ 1831 set ends [getselectionends $window] 1832 set start [lindex $ends 0] 1833 set end [lindex $ends 1] 1834 if {$start==$end} \ 1835 { 1836 set line [lindex [positiontolineoffset $window $start] 0]; # get line we want to select 1837 set start [lineoffsettoposition $window $line 0]; # point to the start 1838 set end [lineoffsettoposition $window [expr $line+1] 0]; # point to the end 1839 } 1840 if {[lindex [positiontolineoffset $window $end] 1]==0} \ 1841 { 1842 if {$start!=$end} \ 1843 { 1844 incr end -1; # move back past last newline 1845 } 1846 } 1847 setselectionends $window $start $end; # make only one selection, even if more than one 1848 set result [lindex [selectedtextlist $window] 0]\n; # get contents of selection to return (add in new line) 1849 setselectionends $window $end $end; # move to the end 1850 breakundo $window; # force a break in the undo stream for this window 1851 InsertAndHome $window "\n"; # add newline 1852 set result; # return this 1853} 1854 1855# When a shell command arrives, this handles it 1856# NOTE: ShellCommand is a procedure that the editor expects to be defined. 1857# The editor calls this procedure in response to certain events. 1858# The following is a list of the commands that are currently defined: 1859# initialargs -- sent when the editor begins, args is the list of command line arguments 1860# open -- editor is asked to open documents, args is path name list 1861# close -- editor is asked to close documents, args is buffer list 1862# quit -- editor is asked to quit, args is not used 1863proc ShellCommand {command args} \ 1864{ 1865 switch $command \ 1866 { 1867 "initialargs" 1868 { 1869 OpenList $args; # later, if we want, we can interpret this for command line switches, or whatever 1870 } 1871 "open" 1872 { 1873 OpenList $args 1874 } 1875 "close" 1876 { 1877 foreach window $args \ 1878 { 1879 AskClose $window 1880 } 1881 } 1882 "quit" 1883 { 1884 TryToQuit 1885 } 1886 } 1887} 1888 1889# display the e93 about box 1890proc AboutBox {} \ 1891{ 1892 global SCRIPTPATH; 1893 1894 okdialog "[version]\nTcl: [info tclversion]\nStartup Script: $SCRIPTPATH\n\n$::tcl_platform(os) $::tcl_platform(osVersion) $::tcl_platform(machine)\nProcess ID: [pid]\n\nNumber of open windows: [llength [windowlist]]\nNumber of open buffers: [llength [bufferlist]]\n\nFor the latest version, visit www.e93.org" 1895} 1896 1897# Add another directory path to the directory menu. 1898proc AddDirectoryMenu {path} \ 1899{ 1900 addmenu {Directory} LASTCHILD 1 "$path" {} "cd \{$path\}" 1901} 1902 1903# Define the menus. 1904addmenu {} LASTCHILD 1 "e93" "" "" 1905 addmenu {e93} LASTCHILD 1 "About..." {} {AboutBox} 1906 addmenu {e93} LASTCHILD 0 "space0" {\\S} {} 1907 1908 addmenu {e93} LASTCHILD 1 "Help for e93" {} {OpenList [file join $sysPrefsDir README.e93]} 1909 addmenu {e93} LASTCHILD 1 "Help for regular expressions" {} {OpenList [file join $sysPrefsDir README.regex]} 1910 addmenu {e93} LASTCHILD 1 "Help for syntax maps" {} {OpenList [file join $sysPrefsDir README.syntaxmaps]} 1911 1912addmenu {} LASTCHILD 0 "space0" {\\S} {} 1913 1914addmenu {} LASTCHILD 1 "File" "" "" 1915 addmenu {File} LASTCHILD 1 "New" {\\Kn} {NewWindow} 1916 addmenu {File} LASTCHILD 1 "Open..." {\\Ko} {OpenList [opendialog "Open File:"]} 1917 addmenu {File} LASTCHILD 1 "Open Selection" {\\Kd} {SmartOpenList [SelectLineWhenNoSelection [set window [ActiveWindowOrBeep]]; selectedtextlist $window]} 1918 addmenu {File} LASTCHILD 1 "Include..." {} {IncludeList [set window [ActiveWindowOrBeep]] [opendialog "Include:"];HomeWindowToSelectionStart $window} 1919 addmenu {File} LASTCHILD 0 "space0" {\\S} {} 1920 addmenu {File} LASTCHILD 1 "Close" {\\Kw} {AskClose [ActiveWindowOrBeep]} 1921 addmenu {File} LASTCHILD 1 "Close All" {\\KW} {foreach window [windowlist] {AskClose $window}} 1922 addmenu {File} LASTCHILD 1 "Save" {\\Ks} {AskSave [ActiveWindowOrBeep]} 1923 addmenu {File} LASTCHILD 1 "Save As..." {\\KS} {AskSaveAs [ActiveWindowOrBeep]} 1924 addmenu {File} LASTCHILD 1 "Save To..." {} {AskSaveTo [ActiveWindowOrBeep]} 1925 addmenu {File} LASTCHILD 1 "Save All" {} {AskSaveAll} 1926 addmenu {File} LASTCHILD 1 "Revert To Saved" {} {AskRevert [ActiveWindowOrBeep]} 1927 addmenu {File} LASTCHILD 0 "space1" {\\S} {} 1928 addmenu {File} LASTCHILD 1 "Print..." {\\Kp} {PrintBuffer [ActiveWindowOrBeep]} 1929 addmenu {File} LASTCHILD 1 "Print Selection..." {\\KP} {PrintSelection [ActiveWindowOrBeep]} 1930 addmenu {File} LASTCHILD 1 "Print Windows..." {} {PrintWindows} 1931 addmenu {File} LASTCHILD 0 "space2" {\\S} {} 1932 addmenu {File} LASTCHILD 1 "Quit" {\\Kq} {TryToQuit} 1933 1934addmenu {} LASTCHILD 1 "Edit" "" "" 1935 addmenu {Edit} LASTCHILD 1 "Undo/Redo Toggle" {\\Kz} {if {[undotoggle [set window [ActiveWindowOrBeep]]]!=0} {HomeWindowToSelectionStart $window} else {beep}} 1936 addmenu {Edit} LASTCHILD 1 "Undo" {\\Ku} {if {[undo [set window [ActiveWindowOrBeep]]]!=0} {HomeWindowToSelectionStart $window} else {beep}} 1937 addmenu {Edit} LASTCHILD 1 "Redo" {\\Ky} {if {[redo [set window [ActiveWindowOrBeep]]]!=0} {HomeWindowToSelectionStart $window} else {beep}} 1938 addmenu {Edit} LASTCHILD 1 "Flush Undo/Redo Buffer" {} {okcanceldialog "Really flush undos for:\n'[set window [ActiveWindowOrBeep]]'?";flushundos $window} 1939 addmenu {Edit} LASTCHILD 0 "space0" {\\S} {} 1940 addmenu {Edit} LASTCHILD 1 "Cut" {\\Kx} {SmartCut [set window [ActiveWindowOrBeep]] [CurrentClipboardOrBeep];HomeWindowToSelectionStart $window;flushundos [getclipboard]} 1941 addmenu {Edit} LASTCHILD 1 "Copy" {\\Kc} {SmartCopy [ActiveWindowOrBeep] [CurrentClipboardOrBeep];flushundos [getclipboard]} 1942 addmenu {Edit} LASTCHILD 1 "Paste" {\\Kv} {HomeWindowToSelectionStart [set window [ActiveWindowOrBeep]];paste $window [CurrentClipboardOrBeep];HomeWindowToSelectionStart $window -lenient} 1943 addmenu {Edit} LASTCHILD 1 "Clear" {} {clear [set window [ActiveWindowOrBeep]];HomeWindowToSelectionStart $window} 1944 addmenu {Edit} LASTCHILD 0 "space1" {\\S} {} 1945 addmenu {Edit} LASTCHILD 1 "Clipboards" {} {} 1946 addmenu {Edit Clipboards} LASTCHILD 1 "Show Current Clipboard..." {} {ShowCurrentClipboard} 1947 addmenu {Edit Clipboards} LASTCHILD 1 "Open Current Clipboard..." {} {OpenDefaultWindow [CurrentClipboardOrBeep]} 1948 addmenu {Edit Clipboards} LASTCHILD 0 "space0" {\\S} {} 1949 addmenu {Edit Clipboards} LASTCHILD 1 "Clipboard 0" {\\K0} {setclipboard clip0} 1950 addmenu {Edit Clipboards} LASTCHILD 1 "Clipboard 1" {\\K1} {setclipboard clip1} 1951 addmenu {Edit Clipboards} LASTCHILD 1 "Clipboard 2" {\\K2} {setclipboard clip2} 1952 addmenu {Edit Clipboards} LASTCHILD 1 "Clipboard 3" {\\K3} {setclipboard clip3} 1953 addmenu {Edit Clipboards} LASTCHILD 1 "Clipboard 4" {\\K4} {setclipboard clip4} 1954 addmenu {Edit Clipboards} LASTCHILD 1 "Clipboard 5" {\\K5} {setclipboard clip5} 1955 addmenu {Edit Clipboards} LASTCHILD 1 "Clipboard 6" {\\K6} {setclipboard clip6} 1956 addmenu {Edit Clipboards} LASTCHILD 1 "Clipboard 7" {\\K7} {setclipboard clip7} 1957 addmenu {Edit Clipboards} LASTCHILD 1 "Clipboard 8" {\\K8} {setclipboard clip8} 1958 addmenu {Edit Clipboards} LASTCHILD 1 "Clipboard 9" {\\K9} {setclipboard clip9} 1959 addmenu {Edit} LASTCHILD 0 "space2" {\\S} {} 1960 addmenu {Edit} LASTCHILD 1 "Select All" {\\Ka} {selectall [ActiveWindowOrBeep]} 1961 addmenu {Edit} LASTCHILD 1 "Unselect Whitespace" {\\Kb} {UnselectWhitespace [ActiveWindowOrBeep]} 1962 addmenu {Edit} LASTCHILD 0 "space3" {\\S} {} 1963 addmenu {Edit} LASTCHILD 1 "Align Left" {\\Kbraceleft} {AlignLeft [ActiveWindowOrBeep]} 1964 addmenu {Edit} LASTCHILD 1 "Shift Left" {\\Kbracketleft} {ShiftLeft [ActiveWindowOrBeep]} 1965 addmenu {Edit} LASTCHILD 1 "Shift Right" {\\Kbracketright} {ShiftRight [ActiveWindowOrBeep]} 1966 1967addmenu {} LASTCHILD 1 "Find" "" "" 1968 addmenu {Find} LASTCHILD 1 "Find/Replace..." {\\Kf} {AskSearch [ActiveWindowOrBeep]} 1969 addmenu {Find} LASTCHILD 1 "Find/Replace in All..." {} {ActiveWindowOrBeep;AskSearchAll} 1970 addmenu {Find} LASTCHILD 1 "Find Same Backwards" {\\KG} {FindNext [ActiveWindowOrBeep] 1} 1971 addmenu {Find} LASTCHILD 1 "Find Same" {\\Kg} {FindNext [ActiveWindowOrBeep] 0} 1972 addmenu {Find} LASTCHILD 1 "Find Selection Backwards" {\\KH} {FindSelectionNext [ActiveWindowOrBeep] 1} 1973 addmenu {Find} LASTCHILD 1 "Find Selection" {\\Kh} {FindSelectionNext [ActiveWindowOrBeep] 0} 1974 addmenu {Find} LASTCHILD 0 "space0" {\\S} {} 1975 addmenu {Find} LASTCHILD 1 "Replace Same Backwards" {\\KT} {ReplaceNext [ActiveWindowOrBeep] 1} 1976 addmenu {Find} LASTCHILD 1 "Replace Same" {\\Kt} {ReplaceNext [ActiveWindowOrBeep] 0} 1977 addmenu {Find} LASTCHILD 0 "space1" {\\S} {} 1978 addmenu {Find} LASTCHILD 1 "Replace Selections With..." {\\KR} {ReplaceSelections [ActiveWindowOrBeep]} 1979 addmenu {Find} LASTCHILD 0 "space2" {\\S} {} 1980 addmenu {Find} LASTCHILD 1 "Go To Line..." {\\Kl} {selectline [set window [ActiveWindowOrBeep]] [expr [textdialog "Go to line:"]];HomeWindowToSelectionStart $window} 1981 addmenu {Find} LASTCHILD 1 "Locate Selection" {\\KL} {HomeWindowToSelectionStart [ActiveWindowOrBeep] -strict} 1982 addmenu {Find} LASTCHILD 0 "space3" {\\S} {} 1983 addmenu {Find} LASTCHILD 1 "Grep -n For..." {\\KF} {set data "grep -E -n -s --line-buffered -D skip [set grepFilesChoice [textdialog "Enter pattern, and file list: (eg. void *.c)" $grepFilesChoice]]"; set window [NewWindow]; task $window $data} 1984 1985addmenu {} LASTCHILD 1 "Window" "" "" 1986 addmenu {Window} LASTCHILD 1 "Tcl console" {} {OpenDefaultWindow tclConsole} 1987 addmenu {Window} LASTCHILD 0 "space0" {\\S} {} 1988 addmenu {Window} LASTCHILD 1 "Get Information" {\\Ki} {BufferInfo [ActiveWindowOrBeep]} 1989 addmenu {Window} LASTCHILD 1 "Set Font..." {\\KE} {setfont [set window [ActiveWindowOrBeep]] [fontdialog "Choose Font:" [getfont $window]]} 1990 addmenu {Window} LASTCHILD 1 "Set Tab Size..." {\\Ke} {settabsize [set window [ActiveWindowOrBeep]] [expr [textdialog "New tab size:" [gettabsize $window]]]} 1991 addmenu {Window} LASTCHILD 0 "space1" {\\S} {} 1992 addmenu {Window} LASTCHILD 1 "Swap Top Windows" {\\Kspace} {SwapWindows} 1993 addmenu {Window} LASTCHILD 1 "Rotate Windows" {\\Kgrave} {RotateWindows} 1994 addmenu {Window} LASTCHILD 1 "Choose Window..." {\\KO} {ChooseWindow} 1995 addmenu {Window} LASTCHILD 0 "space2" {\\S} {} 1996 addmenu {Window} LASTCHILD 1 "Stack Windows" {} {StackWindows} 1997 addmenu {Window} LASTCHILD 1 "Tile Windows" {} {TileWindows} 1998 addmenu {Window} LASTCHILD 0 "space3" {\\S} {} 1999 addmenu {Window} LASTCHILD 1 "Language Mode" {} {} 2000 addmenu {Window "Language Mode"} LASTCHILD 1 "<none>" {} {SetHighlightMode [ActiveWindowOrBeep] ""} 2001 foreach element [lsort -dictionary [syntaxmaps]] \ 2002 { 2003 addmenu {Window "Language Mode"} LASTCHILD 1 $element {} "SetHighlightMode \[ActiveWindowOrBeep\] $element" 2004 } 2005 addmenu {Window} LASTCHILD 1 "Color Scheme" {} {} 2006 foreach element [lsort -dictionary [array names HighlightSchemes]] \ 2007 { 2008 addmenu {Window "Color Scheme"} LASTCHILD 1 $element {} "SetHighlightScheme \[ActiveWindowOrBeep\] \"$element\"" 2009 } 2010 2011addmenu {} LASTCHILD 1 "Mark" "" "" 2012 addmenu {Mark} LASTCHILD 1 "Mark..." {} {setmark [ActiveWindowOrBeep] [textdialog "Mark selection with what name?"]} 2013 addmenu {Mark} LASTCHILD 1 "Unmark..." {} {foreach mark [listdialog "Delete which mark(s):" [marklist [set window [ActiveWindowOrBeep]]]] {closemark $window $mark}} 2014 addmenu {Mark} LASTCHILD 1 "Goto Mark..." {} {foreach mark [listdialog "Go to which mark:" [marklist [set window [ActiveWindowOrBeep]]]] {gotomark $window $mark; HomeWindowToSelectionStart $window -strict}} 2015 2016addmenu {} LASTCHILD 1 "Directory" "" "" 2017 addmenu {Directory} LASTCHILD 1 "Show Current Directory" {} {okdialog "Current directory:\n\n[pwd]"} 2018 addmenu {Directory} LASTCHILD 1 "Set Directory..." {} {set path [pathdialog "Choose directory:"]; cd "$path"; AddDirectoryMenu "$path"} 2019 addmenu {Directory} LASTCHILD 1 "space0" {\\S} {} 2020 2021addmenu {} LASTCHILD 1 "Misc" "" "" 2022 addmenu {Misc} LASTCHILD 1 "Strip EOL Whitespace" {} {set numRemoved [StripWhite [set window [ActiveWindowOrBeep]]];okdialog "$window\n\nCharacters removed: $numRemoved"} 2023 addmenu {Misc} LASTCHILD 1 "Set Unix LF Line Termination" {} {SetLineTermination [ActiveWindowOrBeep] "\n"} 2024 addmenu {Misc} LASTCHILD 1 "Set Mac CR Line Termination" {} {SetLineTermination [ActiveWindowOrBeep] "\r"} 2025 addmenu {Misc} LASTCHILD 1 "Set PC CRLF Line Termination" {} {SetLineTermination [ActiveWindowOrBeep] "\r\n"} 2026 2027 addmenu {Misc} LASTCHILD 1 "In All Open Windows ..." {} {} 2028 addmenu {Misc "In All Open Windows ..."} LASTCHILD 1 "Strip EOL Whitespace" {} {ActiveWindowOrBeep;set numRemoved 0;foreach window [windowlist] {incr numRemoved [StripWhite $window]};okdialog "Total characters removed: $numRemoved"} 2029 addmenu {Misc "In All Open Windows ..."} LASTCHILD 1 "Set Unix Line Termination" {} {ActiveWindowOrBeep;foreach window [windowlist] {SetLineTermination $window "\n"};okdialog "All windows completed"} 2030 addmenu {Misc "In All Open Windows ..."} LASTCHILD 1 "Set Mac Line Termination" {} {ActiveWindowOrBeep;foreach window [windowlist] {SetLineTermination $window "\r"};okdialog "All windows completed"} 2031 addmenu {Misc "In All Open Windows ..."} LASTCHILD 1 "Set PC Line Termination" {} {ActiveWindowOrBeep;foreach window [windowlist] {SetLineTermination $window "\r\n"};okdialog "All windows completed"} 2032 2033 addmenu {Misc} LASTCHILD 1 "Uppercase Selection" {} {UppercaseSelection [ActiveWindowOrBeep]} 2034 addmenu {Misc} LASTCHILD 1 "Lowercase Selection" {} {LowercaseSelection [ActiveWindowOrBeep]} 2035 addmenu {Misc} LASTCHILD 1 "Increment Selected Numbers..." {} {IncrementSelection [ActiveWindowOrBeep] [textdialog "How much to increment:" 1]} 2036 addmenu {Misc} LASTCHILD 1 "Enumerate Selections..." {} {EnumerateSelection [ActiveWindowOrBeep] [textdialog "Starting value:" 1] [textdialog "How much to increment:" 1]} 2037 addmenu {Misc} LASTCHILD 1 "Sum of Selected Numbers" {} {SumSelection [ActiveWindowOrBeep]} 2038 addmenu {Misc} LASTCHILD 1 "Sort Selection Segments" {} {SortSelection [ActiveWindowOrBeep]} 2039 addmenu {Misc} LASTCHILD 1 "Reverse Selection Segments" {} {ReverseSelection [ActiveWindowOrBeep]} 2040 addmenu {Misc} LASTCHILD 1 "Refill Selection..." {\\Kr} {RefillSelection [ActiveWindowOrBeep]} 2041 addmenu {Misc} LASTCHILD 1 "Line Wrapping..." {} {WrapOnOff} 2042 addmenu {Misc} LASTCHILD 1 "Get man Page..." {\\Kslash} {ManPage [textdialog "Enter man page subject:"]} 2043 addmenu {Misc} LASTCHILD 1 "Spell" {} {SpellDocument [ActiveWindowOrBeep]} 2044 addmenu {Misc} LASTCHILD 1 "Mail To..." {} {MailDocument [ActiveWindowOrBeep]} 2045 addmenu {Misc} LASTCHILD 1 "Mail Windows To..." {} {MailWindows} 2046 2047addmenu {} LASTCHILD 1 "Tasks" "" "" 2048 addmenu {Tasks} LASTCHILD 1 "Execute Shell Task" {\\KKP_Enter} {task [set window [ActiveWindowOrBeep]] [EvalText $window]} 2049 addmenu {Tasks} LASTCHILD 1 "Send EOF To Task" {\\Kk} {eoftask [ActiveWindowOrBeep]} 2050 addmenu {Tasks} LASTCHILD 1 "Kill Task" {\\KK} {killtask [ActiveWindowOrBeep]} 2051 addmenu {Tasks} LASTCHILD 0 "space0" {\\S} {} 2052 addmenu {Tasks} LASTCHILD 1 "Pipe Selections Through..." {} {PipeSelection [ActiveWindowOrBeep]} 2053 2054addmenu {} LASTCHILD 1 "Build" "" "" 2055 addmenu {Build} LASTCHILD 1 "make" {\\Km} {HomeWindowToSelectionStart [set window [ActiveWindowOrBeep]];breakundo $window;task $window make} 2056 2057# Bind keys to various useful things. 2058# l=caps lock, s=shift, c=control, 0-7 are additional modifiers such as command, alt, option, command, etc... 2059# Bind flags lsc01234567 (x means don't care, 0 means not pressed, 1 means pressed) 2060 2061bindkey F1 {x0010000000} {setmark [set window [ActiveWindowOrBeep]] F1;markvisible $window F1 008000} 2062bindkey F1 {x1010000000} {orselection [ActiveWindowOrBeep] -destmark F1} 2063bindkey F1 {x0000000000} {gotomark [set window [ActiveWindowOrBeep]] F1;HomeWindowToSelectionStart $window -semistrict} 2064bindkey F2 {x0010000000} {setmark [set window [ActiveWindowOrBeep]] F2;markvisible $window F2 800000} 2065bindkey F2 {x1010000000} {orselection [ActiveWindowOrBeep] -destmark F2} 2066bindkey F2 {x0000000000} {gotomark [set window [ActiveWindowOrBeep]] F2;HomeWindowToSelectionStart $window -semistrict} 2067bindkey F3 {x0010000000} {setmark [set window [ActiveWindowOrBeep]] F3;markvisible $window F3 6060A0} 2068bindkey F3 {x1010000000} {orselection [ActiveWindowOrBeep] -destmark F3} 2069bindkey F3 {x0000000000} {gotomark [set window [ActiveWindowOrBeep]] F3;HomeWindowToSelectionStart $window -semistrict} 2070bindkey F4 {x0010000000} {setmark [set window [ActiveWindowOrBeep]] F4;markvisible $window F4 007070} 2071bindkey F4 {x1010000000} {orselection [ActiveWindowOrBeep] -destmark F4} 2072bindkey F4 {x0000000000} {gotomark [set window [ActiveWindowOrBeep]] F4;HomeWindowToSelectionStart $window -semistrict} 2073 2074bindkey F5 {x0000000000} {WrapOnOff}; 2075bindkey F5 {x0010000000} {WrapNewColumn}; 2076 2077bindkey KP_Enter {x0000000000} {execute [set window [ActiveWindowOrBeep]] [EvalText $window];catch {HomeWindowToSelectionStart $window -lenient}} 2078bindkey Return {x0010000000} {task [set window [ActiveWindowOrBeep]] [EvalText $window]}; # this is for laptop machines without a keypad 2079bindkey Help {x0000000000} {ManPage [textdialog "Enter man page subject:"]} 2080 2081# Specify initial paths to be placed into the directory menu. 2082 2083AddDirectoryMenu / 2084catch {AddDirectoryMenu [glob ~]}; # this can fail if user has no home directory 2085AddDirectoryMenu [pwd] 2086 2087 2088# see if the user has his own set of modules specified, if so, skip including the defaults, and get only his 2089if {[file exists [file join $userPrefsDir $modulesDir]]} \ 2090{ 2091 foreach file [lsort [glob -nocomplain [file join $userPrefsDir $modulesDir *.tcl]]] \ 2092 { 2093 source $file; 2094 } 2095} \ 2096else \ 2097{ 2098 # use all system defined modules 2099 foreach file [lsort [glob -nocomplain [file join $sysPrefsDir $modulesDir *.tcl]]] \ 2100 { 2101 source $file; 2102 } 2103} 2104 2105# get user's additional modules (if any) 2106if {[file exists [file join $userPrefsDir $auxModulesDir]]} \ 2107{ 2108 foreach file [lsort [glob -nocomplain [file join $userPrefsDir $auxModulesDir *.tcl]]] \ 2109 { 2110 source $file; 2111 } 2112} 2113 2114# get user's preferences (if any) 2115if {[file exists [file join $userPrefsDir $prefsDir]]} \ 2116{ 2117 foreach file [lsort [glob -nocomplain [file join $userPrefsDir $prefsDir *.tcl]]] \ 2118 { 2119 source $file; 2120 } 2121} 2122