home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast2.iso / sprint / texmac.zip / NOTHER.SPM < prev    next >
Text File  |  1991-11-26  |  62KB  |  2,189 lines

  1. ; NOTHER.UIM -- SP.SPM replacement
  2. ; Last Update: 1/6/91, RDT
  3. ;    CONTENTS:
  4. ;;    SECTION:  Routines whose definitions are to be removed.
  5. ;    SECTION:    General and command macros sub-grouped by function
  6. ;    subsection:    miscellaneous semi primitives
  7. ;    subsection:    object/unit movements, jumps
  8. ;    subsection:    text manipulation, word wrap, newlines, etc
  9. ;    subsection:    columns
  10. ;    subsection:    regions, selection, deletions
  11. ;    subsection:    locate, search & replace
  12. ;    subsection:    macro management
  13. ;    subsection:    file management
  14. ;    subsection:    window management
  15. ;    subsection:    direction / unit control
  16. ;
  17. ;    SECTION:    Automatically-called macro definitions (Main, Init,
  18. ;            EditKey, MenuKey, etc.)
  19.  
  20. ;----------------------------------------------
  21. ;;    SECTION:    Forward declarations -- Things I don't use but
  22. ;                have kept in the macros for easier modification by others
  23. ;            These have no space before : to distinguish from real defs.
  24. ;----------------------------------------------
  25. ;Restart:    ; needed for prmenu.uim but defined in Auto. macros later.
  26. DefaultRuler:    ; just cause sometime someone might want it again
  27. CheckLastWord:
  28. NeedDisk:    ; see UnloadEngine
  29. SetQDDiskName:    ; get it from core.spm if you have floppy system
  30. regionupper:
  31. regionlower:    ; see region section
  32.  
  33. ;----------------------------------------------
  34. ;    SECTION:    General and command macros sub grouped by function
  35. ;----------------------------------------------
  36. ;    subsection:    miscellaneous semi primitives
  37. ; --- Replacements for old unnumbered mark commands:
  38.  
  39. aftermark : after themark
  40. beforemark : before themark
  41. setmark : set themark
  42. swapmark : if (inbuff themark) swap themark
  43. tomark : to prevmark
  44. togmark : to gmark
  45. Unselect : 0->select
  46. MarkSelect : setmark 1->select
  47. IsNotSelect : (!select || (select && !inbuff themark))    
  48. ; True if nothing is selected or selection is in another buffer
  49. IsSelect : (select && inbuff themark)    ; could use to protect against
  50. ; Can't copy, mark not in buffer error.
  51. MaybeSelect : if !select (setmark 1->select) 0->ColMode    ; force columns off
  52.  
  53. BlockCursor :    ; my preference
  54.     hardware "0fh int 10h" & 0ffh =7 ? {hardware "14>cx 1 int 10h"} : {hardware "8>cx 1 int 10h"} 
  55.  
  56. ; Normal keystroke input, converts IBM function keys into 256+'scan code':
  57. ;KeyGet : key || key + 256
  58. KeyGet :
  59.     int ktmp
  60.     key || key + 256
  61.         ->ktmp
  62.     if  ((ktmp > 1afh)&&(ktmp <1bah)) (ktmp - 180h)
  63.     else ktmp
  64. GetKey: KeyGet    ; old name
  65.  
  66. Arg :                ; QD = prompt
  67.     ->n
  68.     message "\n"
  69.     message QD
  70.     n status ": %d"
  71.     key->x
  72.     if (x >= '0' && x <= '9') {
  73.         x - '0'->n
  74.         do    {
  75.             message "\n"
  76.             message QD
  77.             n status ": %d"
  78.             key->x
  79.             if (x >= '0' && x <= '9') (n * 10 + x - '0'->n)
  80.             else break
  81.             }
  82.         }
  83.     x keypushback
  84.     n
  85.  
  86. AtPara :        ; Return TRUE if point is at a real paragraph to be filled
  87.     mark (ispara && ((f c ispara) || iswhite || isend || (current = '^L') || (current = '^K')))
  88.  
  89. IsAlpha : (
  90.     current >= 'a' && current <= 'z') || (current >= 'A' && current <= 'Z')
  91.  
  92. IsBlankLine : ispara && column = 0
  93.  
  94. IsLower : current >= 'a' && current <= 'z'
  95.  
  96. IsOnlyRuler : (length ==0) || (mark (r to isend inruler && (toeol c isend)))
  97.  
  98. IsParaEnd :            ; check for end of paragraph (after a NL)
  99.     isgray || (3 match "[@./\\\\)}\\]]")    ; added tex esc. char \\\\
  100.  
  101. IsShift : 0->peekseg isibm && (peek 417H) & 3
  102.  
  103. IsSol : mark (!(r c) || isnl)
  104.  
  105. IsUnnamed : length fname = 0
  106.  
  107. IsUpper : current >= 'A' && current <= 'Z'
  108.  
  109. Null :    ; do nothing macro
  110.  
  111. NoBlock : error "You must mark a block first."
  112.  
  113. ToLower : if IsUpper (current + 20H->current) else c
  114.  
  115. ToUpper : if IsLower (current - 20H->current) else c
  116.  
  117. RateChange :
  118.     if !keypressed 0
  119.     else {
  120.         KeyGet - 30h->x        ; convert numbers '0'-'9' to 0-9
  121.         if (x < 0 || x > 9) 1
  122.         else {
  123.             if x (x * 50 ->RepeatRate)    ; 0 is super fast, other in 50mS increments
  124.             else 1->RepeatRate
  125.             0
  126.             }
  127.         }
  128.  
  129. CharToAlpha : 
  130.     ; why bother when there's x,y,n ?
  131.     if (x >= 188h && x <= 193h) (x - 180h -> x)
  132.     if (x >=  'a' && x <=  'x') (x - 32->x)
  133.     if (x >= '^A' && x <= '^X') (x + 64->x)
  134.     x
  135.  
  136. CharToUpper : int z
  137.     z >= 'a' && z <= 'z' ? z - 20h : z
  138.  
  139. Quote :
  140.     (if !inagain {
  141.         if (!menudelay || !(menudelay wait)) {
  142.             status "\nControl character to insert: "
  143.             }
  144.         KeyGet & 9fh ->Quoted
  145.         }
  146.     $)
  147.     if inruler (toeol c)
  148.     repeat {
  149.         Quoted case {
  150.         32    '^\' insert,
  151.         '-'    '^^' insert,
  152.         '^[' if ask "Insert [ESC] character? " ('^[' insert),
  153.         '^K'    '^K' insert readruler,
  154.         188h    '^H' insert,
  155.         189h    '^I' insert,
  156.         18ah    '^J' insert,
  157.         18dh    '^M' insert,
  158.         $    Quoted insert
  159.             }
  160.         }
  161.  
  162. QuoteHack :        ; This is a hook called by all the search-type
  163.                 ; functions so that you can hack escape/wild card/
  164.                 ; quote characters
  165.  
  166. CountRepeat :
  167.     set QD "Repeat" 1 Arg->RepCount
  168.     key -> RepChar
  169.     if (RepChar >= 32) {
  170.         RepCount repeat (RepChar keypushback dokey)
  171.         }
  172.     else    {
  173.         RepChar keypushback
  174.         RepCount dokey
  175.         }
  176.  
  177. KeyRepeat :
  178.     if !InRepChar {
  179.         ++InRepChar
  180.         status "\nKey to repeat: "
  181.         KeyGet->RepChar
  182.         stopped while !RateChange {
  183.             RepChar keyexec
  184.             message "\nRepeating key. Press 0-9 to adjust rate, any other key to stop"
  185.             draw RepeatRate wait
  186.             }
  187.         }
  188.     else error "You can't repeat repeat."
  189.     0 ->InRepChar
  190.     status ""
  191.  
  192. RightEdge :    ; returns rightmost column number
  193.     mark (toeol column)
  194.  
  195. Showpos :    offset message "point=%u " length message "of %d"
  196.  
  197. TimeMonth :               ; Insert the month
  198.     time 4 - 1 put "%[January%;February%;March%;April%;May%;June%;July%;August%;September%;October%;November%;December%]"
  199.  
  200. TimeWeekDay :            ; Insert the day of week
  201.     time 6 put "%[Sunday%;Monday%;Tuesday%;Wednesday%;Thursday%;Friday%;Saturday%]"
  202.  
  203. TimeDateLong :            ; Insert the date as 'January 1, 1988'
  204.     TimeMonth
  205.     time 3 put " %d, "
  206.     time 5 + 1900 put "%d"
  207.  
  208. TimeDateShort :            ; Insert the date as '1/1/88'
  209.     time 4 put "%d/"
  210.     time 3 put "%d/"
  211.     time 5 put "%d"
  212.  
  213. TimeDayDate :
  214.     TimeWeekDay insert ", " TimeDateLong
  215.  
  216. TimeTime :            ; Insert time as HR:MIN:SEC AM/PM
  217.     0->x                ; AM/PM flag
  218.     time 2->y            ; hours
  219.     if (y > 11) (1->x y - 12->y)
  220.     if !y (12->y)
  221.     y put "%d:"
  222.     time 1 put "%02d:"
  223.     time 0 put "%02d"
  224.     x put " %[am%;pm%]"
  225.  
  226. ToggleIns : ++overwrite
  227.  
  228. Zap : Unselect 1 Bell abort
  229.  
  230. ;----------------------------------------------
  231. ;    subsection:    unit (object) movements, jumps
  232. CharFind :    ; case insensitive move to char, maps ^M to NL.
  233.             ; returns 1 if found, 2 if illegal key, else false
  234.     key->x
  235.     if (x < ' ') {
  236.         x case {
  237.         '^M' '^J' ->x,        ; map return to NL
  238.         '^I',
  239.         '^J',
  240.         '^L',
  241.         $ if !x keypushback 2 return    ; function keys are returned
  242.         }
  243.     }
  244.     x CharToUpper ->x
  245.         direction ? {    ; Forward Search
  246.             if ((x < 'A') || ((x > 'Z') && (x < 'a')))
  247.                 (x csearch)     ; literal search for non-alpha chars
  248.             else {
  249.                 to (current = x) || (current = (x + 20h))
  250.                 }
  251.             }
  252.         : {        ; Reverse Search
  253.             if (x < ' ') (x r csearch)    ; literal search for control chars
  254.             else {
  255.                 r to (current = x) || (current = (x + 20h))
  256.                 }
  257.             }
  258.  
  259. CharFindBack : 
  260.     status "\nFind <- "
  261.     mark {
  262.         r CharFind case {
  263.             1    r c setmark,
  264.             2    return,
  265.             $ message "\nNot found"
  266.             }
  267.         }
  268.  
  269. CharFindFwd : 
  270.     status "\nFind -> "
  271.     mark {
  272.         CharFind case {
  273.             1    setmark,
  274.             2    return,
  275.             $ message "\nNot found"
  276.             }
  277.         }
  278.  
  279. Up : (if action (tosol setmark) $)
  280.     repeat (tosol r c)
  281.     if action tosol
  282.     else (dcolumn->dcolumn)
  283.     $
  284.  
  285. Down :     (if action (tosol setmark) $)
  286.     repeat (toeol c)
  287.     if !action (dcolumn->dcolumn)
  288.     $
  289.  
  290. FileEnd :     if !(IsSelect || isend || r isend) setmark
  291.     f toend
  292.  
  293. FileStart : (if !(IsSelect || isend || r isend) setmark $)->line
  294.  
  295. LineJump :     if !IsSelect setmark
  296.     LastLine get "Line number" -> LastLine -> line
  297.     if (line < LastLine) message "\nLine was out of range.  At end of file"
  298.     if (LastLine < line) { 1->LastLine message "\nAt beginning of file"}
  299.  
  300. LineFwd : repeat (past isnl to isnl)    ; end of line, down
  301. ;(RightEdge > column) ? toeol : Down   toeol)
  302.  
  303. LineBack : repeat r (past isnl to isnl)    ; start of line, up
  304. ; column = 0 ? Up : tosol)
  305.  
  306. LineNext : repeat (to isnl past isnl)    ; start of line, down
  307.  
  308. LinePrevious : r LineNext        ; end of line, up
  309.  
  310. Left : repeat r c
  311.  
  312. MarkerBack :    ;apologies to hch, goes to previous mark in jump ring
  313.  ; while (!inbuff marknumber NextMnum) (NextMnum+9)%10->NextMnum ; stay in current buffer
  314.         if !IsSelect setmark
  315.     to marknumber NextMnum
  316.     NextMnum message "Back to Mark %x"
  317.     (NextMnum+9)%10->NextMnum
  318.  ; it seems more functional & intuitive to decrement nextmnum AFTER
  319.  ; cuz I probably want to go to the mark I just set.
  320.  
  321. MarkerFwd :        ;rdt goes to next mark in jump ring
  322.  ; while !(inbuff marknumber NextMnum) (NextMnum+1)%10->NextMnum
  323.     (NextMnum+1)%10->NextMnum
  324.         if !IsSelect setmark
  325.     to marknumber NextMnum
  326.     NextMnum message "Forward to Mark %x"
  327.  
  328. MarkerMark :   ;apologies to hch    sets a mark and puts it in mark stack
  329.     ++Mnum%10->Mnum
  330.     set marknumber Mnum
  331.     Mnum message "Mark %x set"
  332.     Mnum->NextMnum      ;sets mark in jump ring
  333.  
  334. MarkerJump :
  335.     status "\nGo to marker (0-9): "
  336.     KeyGet - 30h -> x
  337.     (x< 10 && x >= 0)? {
  338.         x ismarkset ? (if !IsSelect setmark to marknumber x)
  339.         else message "\nMarker not set." } else abort
  340. ; goes to previous position in file if no marker entered
  341.  
  342. MarkerSet :
  343.     status "\nSet marker (0-9): "
  344.     KeyGet - 30h -> x
  345.     (x < 10 && x >= 0)? (set marknumber x message "\nMarker set") else abort
  346.  
  347. ParagraphBack : repeat {if !WordWrap {
  348. ;    r past isgray r to ispara f past isgray
  349.     r past isgray r to IsBlankLine
  350.     }
  351.     else {    r past isgray
  352.         while ('^J' r csearch) {
  353.             c
  354.             if (IsParaEnd) break    ; 
  355.             r c
  356.             }
  357.         past isnl    ; stays at sol
  358.         }
  359.     }
  360.  
  361. ParagraphFwd : repeat {if !WordWrap {
  362. ;    past isgray action ? setmark        ; ??
  363. ;    to ispara past isgray    ;clings to text
  364.     past isgray to IsBlankLine past isgray
  365.     }
  366.     else {    past isgray
  367.         while ('^J' csearch) {
  368.             c
  369.             if (IsParaEnd) break
  370.             }
  371.         past isnl    ; get's to start of next
  372.         }
  373.     }
  374.  
  375. Right : repeat c
  376.  
  377. ScreenBack :
  378.     || wlines-scrollborder -> x if x<=0 (1->x)
  379.     x repeat (tosol r c)
  380.     if r isend return
  381.     x r scroll
  382.     dcolumn->dcolumn
  383.  
  384. ScreenFwd :
  385.     || wlines-scrollborder -> x if x<=0 (1->x)
  386.     x repeat (toeol c)
  387.     if isend return
  388.     x scroll
  389.     dcolumn->dcolumn
  390.  
  391. SentenceBack : 
  392.   repeat {
  393. ;    if !WordWrap {     3 r search "[{(\[<]" r c    ; \"    }
  394. ;    else  {     ; look for programming fences
  395.        r to istoken
  396.         do    {
  397.             r to (issent || current = ';')
  398.             r c
  399.             if (current != '^J') {
  400.                 c
  401.                 past isgray
  402.                 break
  403.                 }
  404.             }
  405. ;        }
  406.     if inruler (toeol c)
  407.     }
  408.  
  409. SentenceFwd : 
  410.    repeat { 
  411. ;    if !WordWrap (    3 search "[}\\])>]" c    ;\"    )
  412. ;    else {  ; look for programming fences
  413.         do    {
  414.             past isgray
  415.             to (issent || current = ';') ; include semicolons in sentence punc. set.
  416.             if (current = '^J') c
  417.             else    {
  418.                 to isgray
  419.                 break
  420.                 }
  421.             }
  422. ;        }
  423.     }
  424.  
  425. WordBack : repeat (r to istoken r past istoken)
  426.  
  427. WordFwd : repeat (to istoken past istoken)
  428.  
  429. WordSelect :
  430.     repeat (WordFwd WordBack MaybeSelect repeat WordFwd)
  431.  
  432. ;======================= HOME ========================
  433. ; Date:            7 April 90
  434. ; Author:        Herman Kuun (70741,1044)
  435. ; Keyboard Function 
  436. ;------------------
  437. ;
  438. ; HOME            => To start of line
  439. ; HOME HOME    => To start of file
  440. ;
  441.  
  442. newHOME :   SentenceBack    ; put into ^Home 167h
  443.     draw
  444. ;    if (300 wait)    {    ; 400 is too slow
  445. ;        if (KeyGet = 147h) (ScreenTop)
  446. ;        draw
  447. ; HOME HOME        => To top of screen
  448.         if (250 wait)    {
  449.             if (KeyGet = 167h) (FileStart)
  450.             draw
  451.         }
  452. ;    }
  453.  
  454. newEND  :   SentenceFwd
  455.     draw
  456. ;    if (300 wait )    {    ; 400 is too slow
  457. ;        if (KeyGet = 14fh) (ScreenBottom)
  458. ;        draw
  459.         if (250 wait)    {
  460.             if (KeyGet = 16fh) (FileEnd)
  461.             draw
  462.         }
  463. ;    }
  464.  
  465. ;----------------------------------------------
  466. ;    subsection:    text manipulation, word wrap, newlines, etc
  467.  
  468. EraseWhite : erase past iswhite r erase past iswhite
  469.  
  470. CaseChange :
  471.     mark {
  472.         if !istoken (r to istoken past istoken)
  473.         if IsLower ToUpper            ; uppercase first letter
  474.         else if (c && istoken && IsLower)
  475.             (r c while (istoken) ToUpper) ; to uppercase
  476.         else (r c while (istoken) ToLower) ; to lowercase
  477.         }
  478.  
  479. FWCaseRotate :
  480.     mark {
  481.         to isvisible
  482.         if !istoken WordBack
  483.         CaseChange
  484.         }
  485.  
  486. CaseRotate :        ; rotate case To->TO->to->To...
  487.     mark {
  488.         int type
  489.         if !select WordSelect else if beforemark swapmark
  490.         regionfwd {
  491.             mark {
  492.                 past istoken r (to IsAlpha c)    ; check what end of word is
  493.                 IsLower ->type        ; save case in type
  494.                 }
  495.             if (type && IsLower) (ToUpper r c)     ; word all lc so just set initial cap
  496.             else if (type && IsUpper) RegionUpper ; convert to all UC
  497.             else RegionLower
  498.             }
  499.         Unselect
  500.     }
  501.  
  502. CaseSwitch :
  503.     if select
  504.         (regionfwd IsUpper ? RegionLower : RegionUpper Unselect)
  505.     else NoBlock
  506.  
  507. CaseInitCap :    ; macro to convert a region such as a heading to initial caps
  508.         ; For use in macros, where you want consistent results
  509. ;    if !select {tosol setmark toeol}    ; define current line
  510.     RegionLower    ; init to lowercase
  511.     markregion {         ; get to start
  512.         while beforemark {
  513.             ToUpper
  514.             to isgray to istoken
  515.             }
  516.         }
  517.     Unselect
  518.  
  519. CaseInit :    ; macro to cycle through a region's initial capitalization
  520.         ; this will be an INTERACTIVE macro since results vary depending on current capitalization
  521.     markregion (
  522.         while beforemark {
  523.             (CaseChange $)
  524.             to isgray past isgray 
  525.             }     ; single letters A are problem cause they change more often that multi letter words
  526.         )    ; leave it in select for cycling
  527.  
  528. TabIndent :
  529.     ->x $
  530.     r erase past iswhite
  531.     if (column < x) {
  532.         while (column < x) ('^I' insert)
  533.         if (column > x) {
  534.             r del
  535.             x - column repeat (insert " ")
  536.             }
  537.         }
  538.  
  539. TabIndent : ; x is tab stop to go to. column nexttab produces next column # to go to
  540.     ->x $     ; adjusted to use spaces, not ^I
  541.     r erase past iswhite  ; remove all previous whitespace
  542.     if (column < x) {
  543.         while (column < x) (' ' insert)
  544.         }
  545.  
  546. ; substitute this for tabindent if you want spaces instead of tab characters
  547. ; see regiontab and detab in column to convert to spaces
  548. TabAction :    
  549.   do {
  550.        insert " "
  551.      }
  552.    while ( (column+1)  % tabsize )
  553.  
  554. TabBack :      ; remove tabs and spaces around cursor
  555.      EraseWhite
  556. ;     column->x 1 r erase past iswhite
  557. ;    while (x>column && !(x nexttab < dcolumn)) --x
  558. ;    x>column ? (x nexttab TabIndent)
  559.  
  560. ALineFill :    ; returns true if line was filled.
  561.     0-> int filled
  562.     if (!rightmargin && ALineLength && column > ALineLength) {
  563.         mark {
  564.             while (r past iswhite column > ALineLength) (r to isgray)
  565.             if (column && (past iswhite beforemark))
  566.                 (r c '^J'->current ++filled)
  567.             if AutoIndent {        ; if indent is on, do it.
  568.                 r c tosol 
  569.                 past iswhite
  570.                 column (isnl ? erase tosol toeol c $) TabIndent
  571.                 }
  572.             }
  573.         }
  574.     filled
  575.  
  576. ; This reformats in ascii wrap mode, and fixes corrupted screens.
  577. Reformat :
  578.     0 redraw draw    ; So the command also fixes corrupt screens...
  579.     mark    {
  580.         if (ALineLength && !rightmargin) {
  581.             status "\nFilling..."            ; filling ASCII text, no rulers
  582.             r to AtPara                ; go to top of current paragraph
  583.             c
  584.             do    {
  585.                 toeol
  586.                 if !AtPara {
  587.                     32->current            ; replace NL's with spaces
  588.                     }
  589.                 } while !AtPara
  590.             ALineLength->column            ; go to first wrap position
  591.             while (column = ALineLength && !AtPara) { 
  592.                 if !iswhite (r (to (iswhite || AtPara) c))
  593.                 '^J'->current
  594.                 ALineLength->column        ; next wrap position
  595.                 }
  596.             }
  597.         else message "\nScreen refreshed."            ; for files w/rulers
  598.         }
  599.  
  600. QuickFill :    ; skips preceding part of paragraph to save time.
  601.     ; calling routine must decide to call this based on WordWrap flag
  602.    mark { if (ALineLength && !rightmargin) {
  603.             do    {
  604.             toeol
  605.             if !AtPara {
  606.                 32->current        ; replace NL's with spaces
  607.                 }
  608.             } while !AtPara
  609.         ALineLength->column            ; go to first wrap position
  610.         while (column = ALineLength && !AtPara) { 
  611.             if !iswhite (r (to (iswhite || AtPara) c))     ; screws up if no wordspaces in line, ie row of -------
  612.             '^J'->current
  613.             ALineLength->column        ; next wrap position
  614.             }
  615.         } ; end alinelength test, if not, do nothing to current paragraph
  616.     } 
  617.     redraw
  618.  
  619. EditFill : QuickFill
  620.  ; point of this is only to have easy way to control when qfill happens
  621. EditFill: ; I want this to do nothing now
  622.  
  623. FileFill :     ; reformat all paragraphs in file
  624.     if !AlineLength message "\nNo line length set"
  625.     else (
  626.         status "\Filling file"
  627.         r toend
  628.         while !isend {Reformat ParagraphFwd}
  629.         )
  630.  
  631. RegionFill :  ; reformat all paragraphs in region
  632.     if IsSelect {
  633.     status "\Filling region"
  634.     markregion (
  635.         while beforemark {Reformat ParagraphFwd}
  636.         )
  637.     Unselect}
  638.     else Reformat    ; just do the paragraph
  639.  
  640. BreakTest :    ; decides whether to wrap at screen edge plus puncbreak
  641.     if (column > ALineLength) (ALineFill $)        ; if at line end, move to next
  642.     else if (RightEdge > ALineLength)        ; but if in line
  643.         (EraseWhite "^J" left)    ; do LineOpen
  644.  
  645. ASpace : if (overwrite && current != '^J') del 
  646.     insert " "   ; actually inserts space char
  647.  
  648. SpaceInsert :
  649.      (if AutoCorrect CheckLastWord $)
  650.     WordWrap case {
  651.     0       ASpace,     ; do on wrapping
  652.     1          QuickFill   ; normal type of word wrap
  653.             ASpace,
  654.     2         previous case {  '.', '?', '!', ';', ':' "^J",  ; break after punc. mark
  655.             $ BreakTest ASpace} ; or does it need wrapping + space char?
  656.     }
  657.  
  658. TabInsert :      ; fwii.spm
  659.     if AutoCorrect CheckLastWord
  660.     column nexttab
  661.     TabIndent
  662.     if WordWrap = 1 QuickFill
  663.  
  664. NewLineInsert :    
  665.     '^J' insert
  666.  ;    if (!WordWrap) ('^J' insert)  ; : (' ' insert)
  667.  
  668. NewLineIndent : NewLineInsert r c tosol past iswhite column
  669.     (isnl ? erase tosol toeol c $)
  670.     TabIndent
  671.  
  672. NewLinePressed : (if AutoCorrect CheckLastWord $) 
  673.     AutoIndent ? NewLineIndent : NewLineInsert
  674.  
  675. LineOpen : repeat ('^J' insert r c)
  676. ;LineOpen : (NewLineInsert $) r c
  677.  
  678. LineIndent : mark (tosol TabInsert)    ;sp.spm
  679.  
  680. CharTranspose : r c r c current (1 del c $) insert
  681.  
  682. ;LineTranspose : mark(tosol delete (toeol c) QD toeol c insert QD)
  683. LineTranspose :
  684.     tosol
  685.     if (r isend) Down
  686.     delete (f toeol c) QD
  687.     Up tosol
  688.     insert QD
  689.  
  690. WordTranspose : ; to preserve kill buffer, this uses QC, though it shouldn't
  691.     if (f isend) WordBack
  692.     if (r isend) WordFwd
  693.     f to istoken
  694.     delete (past istoken) QD
  695.     delete (r to istoken) QC
  696.     r past istoken
  697.     insert QD
  698.     insert QC
  699.     set QC ""
  700.  
  701. CharFindDelete :
  702.     status "\nDelete to: "
  703.     mark {
  704.         if (CharFind = 1) (delete tomark 1->AppendNext set markF)    ; use top of mark list first
  705.         }
  706.  
  707. WordBackDelete : 
  708.     r delete (repeat WordBack) 1->AppendNext set markF
  709.     EditFill
  710.  
  711. DelFwd : del EditFill
  712.  
  713. DelBack : if overwrite r c else r del
  714.     EditFill
  715.  
  716. ;----------------------------------------------
  717. ;    subsection:    columns
  718. ; maybe otta just fwd declare stuff.
  719. ;#include "column"
  720. Coltab:
  721. ColDeTab:
  722. ColCopy:
  723. ColDelete:
  724. ColInsert:
  725. ColErase:
  726. ColSetOneEnd:
  727.  
  728. ;----------------------------------------------
  729. ;    subsection:    regions, selection, deletion
  730.  
  731. FileSelect : r toend MarkSelect toend
  732.  
  733. UndeleteN : ; changed so I can reselect an inserted block, this leaves the mark BEFORE the insertion point.
  734.     if (r !isend) { ; if not at start of file, clumsy fix
  735.         r c setmark f c ; adjust point for bad mark placement, so it doesn't get "pushed down" by the insertion
  736.         } else setmark $ ; so it won't save mark correctly at start of file
  737.     repeat undelete
  738.     swapmark f c  ; this should "fix" location of top mark
  739.     swapmark
  740.     EditFill
  741.  
  742. ; RegionFix - changes the region so it contains balanced delimiters
  743. ;    It is important to do a RegionFix before any region manipulations.
  744. ;    Deleting an unfixed region can really mess up the attributes after it!
  745. ;    Don't call this for a copy, because it might modify the source buffer!
  746.  
  747. RegionFix:     ; I don't need this, fwd declare for other spm/uim files
  748.  
  749.     ; I don't need this, fwd declare for other spm/uim files
  750. RegionFixNoMod:    ; do as good as you can without changing text for copy
  751.  
  752. AppendCopy : swapmark 1->append copy togmark
  753.     swapmark Unselect 1->AppendNext set markF
  754.  
  755. AppendDelete : swapmark 1->append delete togmark
  756.     Unselect 1->AppendNext set markF
  757.     EditFill
  758.  
  759. RegionCopy :     if select {
  760.         copy togmark
  761.         Unselect
  762.         1->AppendNext
  763.         }
  764.  
  765. RegionDelete :     if select {
  766.         delete togmark
  767.         Unselect
  768.         1->AppendNext
  769.         set markF            ; Save position of deletion. Why?
  770.         EditFill
  771.         }
  772.     else    DelFwd
  773.  
  774. RegionErase :     if select {
  775.         erase togmark
  776.         Unselect
  777.         0->AppendNext
  778.         EditFill
  779.         }
  780.     else NoBlock
  781.  
  782. RegionIndent : || tabsize->y    ; if no argument, use tabsize
  783.     markregion {
  784.         while (beforemark) {
  785.             if (!isnl) {
  786.                 tosol past iswhite
  787.                 column+y TabIndent
  788.                 }
  789.             toeol c
  790.             }
  791.         }
  792.     0->select
  793.  
  794. RegionOutdent : || tabsize -> x *-1 RegionIndent
  795.  
  796. RegionEntab : ColTab    ; defined in column.uim
  797.  
  798. RegionDetab : ColDetab
  799.  
  800. RegionLower :
  801.     markregion while beforemark ToLower
  802.  
  803. RegionUpper :
  804.     markregion while beforemark ToUpper
  805.  
  806. BlockDelete : ColMode ? (if select (ColDelete (aftermark ? swapmark) 0->select) else DelFwd) : RegionDelete
  807.  
  808. BlockErase : ColMode ? ColErase : RegionErase
  809.  
  810. BlockCopy : ColMode ? (ColCopy (aftermark ? swapmark) 0->select) : RegionCopy
  811.  
  812. BlockPaste : ColMode ? ColInsert : UndeleteN
  813.  
  814. CopyNext : mark (dokey swapmark copy tomark)
  815.  
  816. DeleteNext : ; delete by next movement command
  817.     set markF
  818.     delete (dokey if before markF (0->direction))
  819.     255->direction
  820.     1->AppendNext
  821.     EditFill    ; repair ASCII paragraph
  822.  
  823. ; This main loop replacement is called when select is turned on.  Then
  824. ; characters are used to extend the selection:
  825.  
  826. SelectLoop :    ; change to accomodate SearchDirection flag
  827.     if (select || ColMode) return        ; to prevent recursion and col extend
  828.     1->select
  829.     while (select=1) {
  830.         if stopped {
  831.             if (inbuff themark) {
  832.                 draw key -> int x
  833.                 if (x = '^M') ('^J'->x)
  834.                 if (x < ' ' && x!='^J' && x!='^I') {x keypushback dokey}
  835.                 else if (x>='a' && x<='z' || x>='A' && x<='Z') {
  836.                     x CharToUpper -> x + 20H -> y
  837.                     if SearchDirection {
  838.                         to (current = x || current = y)
  839.                         c }
  840.                         else { r to (current = x || current = y) r c }  ; added directional sensing
  841.                     }
  842.                     else if SearchDirection {x csearch c}  ; added directional sensing
  843.                         else {x r csearch }
  844.                 }
  845.             else dokey
  846.             }
  847.         else {
  848.             AppendNext->append
  849.             0->AppendNext
  850.             }
  851.         }
  852.  
  853. ToggleColMode :
  854.     ColMode ? {
  855.         0->ColMode ->flag3
  856.         if select (0->select SelectLoop)    ;  switch to block select mode
  857.         }
  858.     else { 
  859.         1->ColMode ->flag3
  860.         if select (2->select)    ; switch to column select mode
  861.         }
  862.  
  863. ReSelect : 
  864.     if select (0->select) 
  865.     else  (ColMode ? (2-> select) : SelectLoop)    ;toggles select, but with old region
  866.  
  867. ToggleSelect :
  868.     if (!select || (select && !inbuff themark)) {
  869.         if !ColMode {        ; regular select mode
  870.             0->select        ; just if mark isn't in buffer
  871.             setmark
  872.             SelectLoop
  873.             }
  874.         else ColSetOneEnd    ; column select mode
  875.         }
  876.     else {
  877.             0->select draw
  878.         }
  879.  
  880. UndoDelete : to markF BlockPaste    ; puts it back in original pos.
  881.  
  882. #define Thischar        ; from Match.spm
  883. #define Matchchar
  884. #define NestLevel
  885. #define OpenDelim
  886.  
  887. MatchShow :
  888.     if beforemark (swapmark c swapmark) ; fix end pos.
  889.     else c
  890.     1 -> select draw
  891.  
  892. MatchFind : if (OpenDelim) {  ; search forwards
  893.             while (NestLevel && !isend) {
  894.                 c if (current == Thischar) ++NestLevel
  895.                 if (current == Matchchar) --NestLevel
  896.             }
  897.         }
  898.         else  { ; search backwards
  899.             while (NestLevel && !(r isend)) {
  900.                 r c if (current == Thischar) ++NestLevel
  901.                 if (current == Matchchar) --NestLevel
  902.             }
  903.         }
  904.  
  905. MatchSelect : 
  906. ;    Unselect
  907.     current case (
  908.         '{' 1->OpenDelim '}',
  909.         '}' 0->OpenDelim '{',
  910.         '(' 1->OpenDelim ')',
  911.         ')' 0->OpenDelim '(',
  912.         '[' 1->OpenDelim ']',
  913.         ']' 0->OpenDelim '[',
  914.         '<' 1->OpenDelim '>',
  915.         '>' 0->OpenDelim '<',
  916.         $ 0)
  917.     -> Matchchar current ->Thischar 1->NestLevel
  918.     if (Matchchar) (  
  919.                 if !select (setmark)  ; if something's not already lit up, like @foot
  920.                 MatchFind
  921.         if (!isend && !(r isend)) MatchShow
  922.         else message "Mis-matched or missing delimiter"
  923.     )
  924.     else message "\nNot a delimiter"
  925.  
  926. ;----------------------------------------------
  927. ;    subsection:    deletions
  928. ;----------------------------------------------
  929. ;    subsection:    Locate, Search & Replace
  930. HiLiteFound : mark (found 1->select draw 0 wait Unselect swapmark)
  931.  
  932. Locate :     set QD Q2            ; extra level of MARK to get around SETMARK
  933. ;    if (SearchOpt & 1) (mark (to QD mark (toend RegionLower)))
  934.     SearchDirection message "\n%[Rev%: Fwd%] Seeking: " QD
  935.     mark {
  936.         if SearchDirection
  937.             (SearchOpt f search QD)
  938.         else (SearchOpt r search QD)
  939.         ? (setmark 1) : (1 Bell message "\n" QD ": not found." 0)
  940.         }
  941.  
  942. LocateNext :     Locate -> StrFound
  943.     (StrFound && !select) ? {
  944.         if !SearchDirection found    ; so it works more than once
  945.         HiLiteFound
  946.         }
  947.     : (select && SearchDirection ? found)
  948.  
  949. LocateFwd :     message "\nForward search: " set Q2
  950.     if !IsSelect setmark
  951.     2 QuoteHack
  952.     1->SearchDirection
  953.     Locate && !select ? HiLiteFound : (select ? found)
  954.  
  955. LocateBack :
  956.     if !IsSelect setmark
  957.     message "\nBackward search: " set Q2    ; used to be Q2
  958.     2 QuoteHack
  959.     0->SearchDirection
  960.     Locate && !select ? (found HiLiteFound)
  961.  
  962. Find : SearchDirection ? LocateFwd : LocateBack
  963. ; didn't want to mess with name for Locate but needed someting
  964. ; that responded to rather than set the SearchDir variable.
  965.  
  966. LocateAuto : if !IsSelect WordSelect
  967.         (copy togmark Q2) 
  968.         if (SearchDirection && beforemark) (swapmark)    ; so it skips current word
  969.         if (!SearchDirection && aftermark) (swapmark)
  970.         Unselect
  971.         LocateNext
  972.  
  973. LocateInc :     ; incremental locate macro
  974.         set Q2  ""      ; use Q2 for CORE compat.
  975.         SearchDirection message "\n%[Rev%: Fwd%] Incr. search: " Q2
  976.         if !IsSelect set themark        ; save start as anchor for LocateNext, except if already selecting something.
  977.     infobox "Incremental Locate" {
  978.         " As you type, Sprint searches for matching text. ",
  979.         " Alt-F, Alt-R change search direction. ^Enter = CR ",
  980.         " Esc breaks search at current point. Alt-^H erases. ",
  981.         " All other command keys break the search and perform ",
  982.         " their expected actions."}
  983.         do  {
  984.                 KeyGet ->x 
  985.                 x case {    ; how bout ^Q quoting?
  986.                         1C6h 1->SearchDirection,    ; Alt F
  987.                         1D2h 0->SearchDirection,    ; Alt R
  988.                         18Ah,    ; '~^J' CtrlEnter
  989.                         '^M' '^J'->x mark (to Q2 toend x insert),   ; clumsy way to insert some special control Chars
  990.                         '^J',
  991.                         '^I' mark (to Q2 toend x insert),
  992.                         '^A' LocateNext break,                  ; ^key that normally does LocateNext falls through CASE and gets executed too
  993.                         188h mark (to Q2 toend r c del),        ; remove char. from Q2 was ^H, now Alt Bspace
  994.                         abortkey,
  995.                         '^[' break,
  996. ;                        (to themark draw break ),
  997.                         $ if (x >= 256 || x < 32) (x keyexec break)
  998.               else (mark (to Q2 toend x insert))     ; add char. to Q2 search string
  999.             }
  1000.                 to themark      ; go back to starting point
  1001.                 LocateNext      ; and search again
  1002.                 draw            ; to show hilite when select =1 
  1003.                 } 
  1004.         message "\n"
  1005.  
  1006. FWConvert :     mark {
  1007.     if (255 csearch) {
  1008.         r toend
  1009.         while (255 csearch) (10 -> current $)
  1010.         }
  1011.     else if (r toend '@' csearch) {
  1012.         r toend
  1013.         insert "@Style(fill yes)"
  1014.         10 insert
  1015.         }
  1016.     }
  1017.     $ Bell message "\nDone."
  1018.  
  1019. DoRepMenu :
  1020.     qmenu "Replace this?" {
  1021.     "Yes"            1,
  1022.     "No"                0,
  1023.     "And the rest"        1->GlobalReplace
  1024.     "Stop"            2,
  1025.     "Replace and stop"    3
  1026.         }
  1027.  
  1028. ReplaceFwd :
  1029.     while (SearchOpt search QD) {
  1030.         1->StrFound    ; set to display message
  1031.         if GlobalReplace {
  1032.             replace found Q3
  1033.             ++x                ; incr number changed
  1034.             }
  1035.         else {
  1036.             mark (1->select found draw setmark)
  1037.             0->select
  1038.             DoRepMenu
  1039.             case {
  1040.                 1    replace found Q3 draw ++x,
  1041.                 2    2->StrFound break,
  1042.                 3    3->StrFound $ replace found Q3 break
  1043.                 }
  1044.             }
  1045.              x status "\nReplaced so far: %d..."
  1046.         }
  1047.  
  1048. ReplaceBack :
  1049.     while (SearchOpt r search QD) {
  1050.         1->StrFound    ; set to display message
  1051.         if GlobalReplace {
  1052.             replace found Q3
  1053.             ++x                ; incr number changed
  1054.             }
  1055.         else {
  1056.             found mark (1->select found draw setmark)
  1057.             0->select
  1058.             DoRepMenu
  1059.             case {
  1060.             1    replace found Q3 draw ++x found,
  1061.             2    2->StrFound break,
  1062.             3    3->StrFound $ replace found Q3 break
  1063.                 }
  1064.             }
  1065.              x status "\nReplaced so far: %d..."
  1066.     }
  1067.  
  1068. doreptest :    ; set marks D and E to make unreplace easy
  1069.        set markD found set markE found
  1070.        copy (to markE) Q4 $ found r c SearchOpt search QD
  1071.        replace found Q3
  1072.        draw
  1073.        ask "Replace?" ? 2 : 3 
  1074.    
  1075. DoReplace :
  1076.        0->StrFound
  1077.        0->x                ; number found
  1078.        set QD Q2           ; extra level of MARK to get around SETMARK
  1079.        ; ensure that case independant really is, without changing string
  1080.        if (SearchOpt & 1) (mark (to QD mark (toend RegionLower)))
  1081.        mark    {
  1082.            if GlobalSearch (r toend f)
  1083.            status "\nSearching..."
  1084.            while (SearchOpt search QD) {
  1085.                1->StrFound ; set to display message
  1086.                if GlobalReplace {
  1087.                    replace found Q3
  1088.                    ++x             ; incr number changed
  1089.                    }
  1090.                else {
  1091.                    mark (1->select found draw setmark)
  1092.                    0->select
  1093.                    qmenu "Replace this?" {
  1094.                    "Test"  doreptest,
  1095.                    "Yes"   1,
  1096.                    "No"    0,
  1097.                    "All"   1->GlobalReplace,
  1098.                    "Exit"  setmark break    ;abort
  1099.                        }
  1100.                    case {
  1101.                    1   replace found Q3 draw ++x,
  1102.                    2   ++x, ; tstrep has done replace, just need to ++x   ;; tstrep has done replace; undo it and go on
  1103.                    3   to markD $ replace (to markE) Q4
  1104.                        }
  1105.                    }
  1106.                x status "\nReplaced so far: %d..."
  1107.                }    ; end while
  1108.            StrFound
  1109.            case {
  1110.            0   message "Not found." 1 Bell,
  1111.            1   x message "%d replaced.",
  1112.            2   message "Cancelled."
  1113.                }
  1114.            } ; end mark
  1115.  
  1116. QueryReplace : ; same as core set, but better messages
  1117.     if select copy to gmark Q2 
  1118.     else {
  1119.     do {
  1120.         message "\nQuery replace search for: " set Q2
  1121.         if !length Q2 {
  1122.             error "You must enter a search string."
  1123.             }
  1124.         else break
  1125.     }}
  1126.     2 QuoteHack
  1127.     message "\nQuery replace with: " set Q3
  1128.     3 QuoteHack
  1129.     0->GlobalReplace
  1130.     DoReplace
  1131. ;    swapmark    ; to fix exit problem
  1132.  
  1133. ReplaceAll :
  1134. ;    if NeedSave WantSave
  1135.     message "\nReplace All search for: " set Q2 $ 
  1136.     2 QuoteHack
  1137.     message "\nReplace All with: " set Q3
  1138.     3 QuoteHack
  1139.     1->GlobalReplace
  1140.     DoReplace
  1141.  
  1142. WantSave: ; fwd declare, see Files management
  1143. NeedSave:
  1144. ReplaceRegion :        ; run Quick replace on file region
  1145.     if IsSelect {
  1146.         if ColMode (message "\nNot setup for Column replace" break)
  1147.         if NeedSave WantSave
  1148.         delete to gmark
  1149.         ;--- now call search and replace
  1150.         open ""         ; put it in unnamed buffer, bigger capacity than Q reg.
  1151.         clear
  1152.         undelete
  1153.         r toend
  1154.         ReplaceAll    ; don't forget, if doing ^J stuff to get 1st ^J
  1155.         r toend
  1156.     delete toend
  1157.         close           ; close buffer and return
  1158.     r c set markF f c ; save position
  1159.     undelete Unselect
  1160.     to markF f c    ; reposition to save gmark. swapmark?
  1161.     }
  1162.  
  1163. ;----------------------------------------------
  1164. ;    subsection:    file management
  1165. BackUpAndSave : 0 fdelete "%.BAK" 0 fmove "%" "%.BAK" write "%"
  1166.  
  1167. QCap :            ; uppercase Qx
  1168.     mark {qswitch while !isend ToUpper}
  1169. AllCaps: QCap    ; old name
  1170.  
  1171. QLow :            ; Lowercase Qx
  1172.     mark {qswitch while !isend ToLower}
  1173.  
  1174. QSlash :  ; change \\ to / for Tex
  1175.       -> int x
  1176.        mark{x qswitch while ('\\' csearch) ( '/'-> current)
  1177.           }
  1178.  
  1179. QMSS :    ; add .MSS to filename in Qx if no extension
  1180.      -> int x
  1181.     mark {
  1182.           x qswitch toend
  1183.         ; we must skip past directories, which might have . or .. in them
  1184.         3 r search "[/\\\\:]"
  1185.         if !('.' csearch) {insert ".MSS"
  1186.                }
  1187.         r toend while !isend ToUpper    ; convert name to uppercase
  1188.         }
  1189.  
  1190. QTrim :        ; remove leading and trailing blanks, put this in FIle routine
  1191.      mark {qswitch erase past isgray 
  1192.         toend erase r past isgray }
  1193.  
  1194. QWild : mark (qswitch ('*' csearch || ('?' r csearch)))
  1195. CheckWild: QWild
  1196.  
  1197. QExt : -> int x         ; D is 13
  1198.         set qnumber x fname
  1199.         mark (x qswitch erase (to current = '.' c)     ; remove up to and past '.'
  1200.         toend insert "   " )    ; pad with spaces for testing .c , .p type files
  1201.         ; returns Qreg with spaces if no extension 
  1202.  
  1203. QStripExt : -> int x         ; D is 13
  1204.         set qnumber x fname
  1205.         mark{x qswitch to current = '.' erase toend}   ; remove extension
  1206.     ; cause fchange "%." doesn't remove period
  1207.  
  1208. QTMP : ->x    ; creates temp file in home directory, if home is SET
  1209.         ; else temp file will be in current dir. Use with piped, sort, paginate
  1210.     set qnumber x home    ; put home direc. prefix into Q reg. if it exists, requires some care with DOS SET Home=X:\
  1211.     mark(x qswitch toend insert "TMP.$$$")  ; glossqdname handles home var. better
  1212.  
  1213. WPConfig :    ; word processing assumptions, suppose I don't WANT fill on? 
  1214.         1->WordWrap
  1215.         0->AutoIndent
  1216.  
  1217. TeXConfig :    ; TeX assumptions
  1218.         2->WordWrap
  1219.     1->AutoIndent  ; ?
  1220.  
  1221. TEdConfig :    ; Text Editing
  1222.     0->WordWrap
  1223.     1->AutoIndent
  1224.  
  1225. ExtConfig : ; test extension and make some assumptions about editor settings
  1226.        13 QExt   ; returns just extension in QD
  1227.     if mark(to QD match "MSS") (WPConfig)
  1228.     else if mark(to QD match "TEX") (TeXConfig)
  1229.     else if mark(to QD match "   ") (WPConfig)
  1230.     else if mark(to QD match "DOC") (WPConfig)
  1231.     else if mark(to QD match "SPM") (TEdConfig)      ; and so on 
  1232.     else TEdConfig                           ; default for now
  1233. ; use this after pickfile and FileOpen, anything that gets to another buffer/file
  1234. ExtConfig: ; define as nothing to prevent it from happening. I don't like it now
  1235.  
  1236. SetCurrentDir : ; cool
  1237. ;    Set current directory to directory of file in current window
  1238.     set QD fname
  1239.     mark {
  1240.         to QD
  1241.         toeol
  1242.         3 r search "[/\\\\]"
  1243.         if (previous = ':') (f c)    ; deal with root dir. by saving slash
  1244.         erase toeol
  1245.         }
  1246.     set cd QD
  1247.     message "\nCurrent directory set to: "
  1248.     message cd
  1249.  
  1250. FileBack : r bufswitch ExtConfig
  1251.  
  1252. FileFwd : bufswitch ExtConfig
  1253.  
  1254. FilePick : ; replacement for pickfile primitive
  1255.     pickfile ExtConfig
  1256.  
  1257. FileSave :
  1258.     0 ->int NoConfirm 
  1259.     if IsUnnamed {        ; get a name from the user
  1260.         do    {
  1261.             set Q0 "" message "\nSave file as: " set Q0
  1262.             0 QCap 0 QTrim    ; added
  1263.             if (!length Q0)
  1264.                 stopped error "You must give the file a name."
  1265.             else {
  1266.                 0 QMSS
  1267.                 set Q0 flist Q0        ; force file name validity check
  1268.                 if !(exist Q0) break    ; file doesn't exist
  1269.                 else if ask "Overwrite existing file?" {
  1270.                     1-> NoConfirm    ; all set, so just do it.
  1271.                     break
  1272.                     }
  1273.                 }
  1274.             }
  1275.         0 QMSS
  1276.         if (NoConfirm || (!(32 exist Q0) || ask "Overwrite existing file?")) {
  1277.             bufnum->x
  1278.             if (buffind Q0 && (bufnum != x)) 
  1279.                 close    ;throw away copy if in buffer, and not current file
  1280.             if !(stopped (write Q0)) {
  1281.                 set fname Q0  ;change file name only if write successful
  1282.                 }
  1283.             }
  1284.         }
  1285.     else {        ; to prevent network users from overwriting each other
  1286.             ; check the copy on disk and make sure it has not been
  1287.             ; written by someone else since last saved by user
  1288.         if (datecheck fname == 1) {
  1289.             1 Bell
  1290.             infobox "NETWORK CONFLICT!" {
  1291.                 "\>The file has been written by someone\>",
  1292.                 "\>else on the network.  Writing the file\>",
  1293.                 "\>now will overwrite ALL changes made\>",
  1294.                 "\>by the other user.\>",
  1295.                 "_",
  1296.                 "\>To prevent overwriting, CANCEL, then\>",
  1297.                 "\>use 'Write As' to save this to a file\>",
  1298.                 "\>under another name.\>"
  1299.                 }{
  1300.                     if !ask "PRESS ESC or N to CANCEL, Y to SAVE: "
  1301.                     return
  1302.                     }
  1303.                 }
  1304.         write "%"
  1305.         }
  1306.  
  1307. NeedSave : ; to replace simple modf test
  1308.     modf
  1309.         ; || (length fname > 0 && !exist fname) )    
  1310.      ; modified or named file that's not on disk somehow
  1311.     ; (length fname = 0 && length != 0) ) ; unnamed with something in it
  1312.     ; this test may be TOO thorough
  1313.  
  1314. WantSave :  ; Used for ExitEditor, FileClose, etc. If modf call this
  1315.     draw while keypressed (key draw)
  1316.     if length fname {
  1317.         message "\nThe file "
  1318.         message fname
  1319.         }
  1320.     else message "\nThis Unnamed file"
  1321.     if (ask " has not been saved; save it (Y,N,ESC)? ") FileSave
  1322.  
  1323. FileTest :      ; Q9 normally, preserves FileOpen spec. Returns status code and Q0 with filename in it
  1324.         -> int x        ; takes any register, generalized to maintain Q9 for FileOpen only, and let Q8 be used for FileDelete, etc.
  1325.     int fstatus 0
  1326.     x QCap x QTrim                     ; tex slash, cap the spec, & trim
  1327.     if (!mark(x qswitch toend 3 match "[\*\?]")) {x QMSS set Q0 qnumber x} ;   try to add .mss if it's not a wildcard
  1328.     if (x QWild) {16 set Q0 flist qnumber x}    ; tries to convert wcard to spec, and shows dirs
  1329. ;    result is filename in Q0
  1330.     if (exist Q0) (1->fstatus)
  1331.     else {
  1332.         if (length Q0) 2->fstatus    ; flist returned legal spec
  1333.         else 0->fstatus        ; flist returned blank, no wild match
  1334.         } ; has to be tested with buffind still
  1335.     fstatus    ; returns 1 exist, 2 spec, no file, or 0 no wild spec match
  1336. ; change all file handling AGAIN to use Q9, not Q0
  1337.  
  1338. FWTest : mark {
  1339.     if (255 csearch) (Bell message "\nFW soft NLs. Run FWConvert")
  1340.     }
  1341.  
  1342. FileGet : -> int fstatus ;ExtConfig is currently disabled, cuz I don't like it
  1343.     if (buffind Q0) (ExtConfig)
  1344.     else {
  1345.     fstatus case (
  1346.         0  set QD "Can't find " mark(to QD toend insert Q9) error QD,
  1347.         1  open Q0 ExtConfig FWTest,
  1348.         2  open Q0 ExtConfig message "\nNew file: " Q0
  1349.         )
  1350.     }
  1351.  
  1352. FileOpen : 
  1353.     message "\nFile to open: " set Q9
  1354.      if (!length Q9) open "" else {
  1355.         SetCurrentDir   ;a dubious convenience, that assumes you usually want to open files associated with the current one.
  1356.     9 FileTest
  1357.     FileGet
  1358.         }
  1359.  
  1360. FileClose : 
  1361.     if NeedSave WantSave
  1362.     if (inbuff themark) (0->select)    ; turn off select
  1363.     close 
  1364. ;    if !files DefaultRuler
  1365.     if files ExtConfig
  1366.  
  1367. FileConvert : message "\nFile conversion software not installed."
  1368.  
  1369. FileDelete :     
  1370.         set QD cdstrip fname
  1371.     message "\nFile to delete (backspace = " fname "): " set Q8
  1372.         if !length(Q8) set Q8 fname     ; if user hits backspace, use current file
  1373.     8 FileTest ; returns 1 exist, 2 spec, no file, or 0 no spec, filename in Q0
  1374.     case (
  1375.         0  message "\nCan't find " Q8,    ; where wild flist returns nothing
  1376.         2  message "\nCan't find " Q0,
  1377.         1 {message "\nAre you sure you want to erase " Q0
  1378.             if (ask "? ") fdelete Q0
  1379.             if buffind Q0 close
  1380.             }
  1381.         )
  1382.  
  1383. FileCopy :      
  1384.         set QD cdstrip fname
  1385.     message "\nFile to copy (backspace = " QD "): " set Q8
  1386.         if !length(Q8) set Q8 fname     ; if user hits backspace, use current file
  1387.     8 FileTest  ; returns 1 exist, 2 spec, no file, or 0 no spec and filename in Q0
  1388.     case (
  1389.         0  message "\nCan't find " Q8,
  1390.         2  message "\nCan't find " Q0,
  1391.         1 { ; set Q1 "" 
  1392.         message "\nCopy " Q0 
  1393.         message " to: " set Q1
  1394.         1 QCap 1 QTrim
  1395.         if (!length Q1) error "You must specify a name."
  1396.         status "\nCopying..."
  1397.         fcopy Q0 Q1
  1398.         message "\nCopy complete."
  1399.         }
  1400.         )
  1401.  
  1402. FileInsert :    ; improved handling of inserted material, makes it easy to delete it.
  1403.         message "\nFile to insert: " set Q8
  1404.         8 FileTest  ; returns 1 exist, 2 spec, no file, or 0 no spec
  1405.         case (
  1406.                 0  message "\nCan't find " Q8,
  1407.         2  message "\nCan't find " Q0,
  1408.                 1  ( if (r !isend) { ; if not at start of file, clumsy fix
  1409.                         r c setmark f c ; adjust point for bad mark placement, so it doesn't get "pushed down" by the insertion
  1410.                         } else setmark ; so it won't save mark correctly at start of file
  1411.                         read Q0 
  1412.                         swapmark f c  ; this should "fix" location of top mark
  1413.                         swapmark
  1414.                    )                      ; allow easy removal of insert
  1415.                 )
  1416.  
  1417. FileRename :   set QD cdstrip fname
  1418.     message "\nFile to rename or move (backspace = " QD "): " set Q8 ; uses current spec in Q8
  1419.         if !length(Q8) set Q8 fname     ; if user hits backspace, use current file
  1420.     8 FileTest  ; returns 1 exist, 2 spec, no file, or 0 no spec
  1421.     case (
  1422.                 0  message "\nCan't find " Q8,
  1423.         2  message "\nCan't find " Q0,
  1424.         1 { ; set Q1 "" 
  1425.         message "\nRename/move " Q0 
  1426.         message " to: " set Q1
  1427.         1 QCap 1 QTrim
  1428.         if (!length Q1) error "You must specify a name."
  1429.         set Q1 flist Q1
  1430.         if exist Q1 {    ; if file already exists...
  1431.             message "\nReplace existing " Q1
  1432.             if !(ask "? ") (message "\nCanceled" abort)
  1433.             else fdelete Q1
  1434.             }
  1435.         fmove Q0 Q1
  1436.         mark { ; doesn't deal with just the dir name
  1437.             if buffind Q0 {set fname Q1}    ; rename in buffer too
  1438.             }  ; doesn't yet check for same name file in swap file
  1439.         message "\nRename complete."
  1440.         }
  1441.         )
  1442.  
  1443. FileCloseAll :     bufnum->x
  1444.     do    {
  1445.         draw
  1446.         FileClose
  1447.         } while (bufswitch && bufnum != x)
  1448.     draw
  1449.     FileClose
  1450.  
  1451. FileSaveAll :
  1452.     bufnum->x
  1453.     do    {
  1454.         draw
  1455.         if NeedSave FileSave
  1456.         } while (bufswitch && bufnum != x)
  1457.     draw
  1458.     if NeedSave FileSave
  1459.  
  1460. FileReRead :
  1461.     if (exist fname) {
  1462.         line->x
  1463.         dline->y
  1464.         clear
  1465.         $ read fname
  1466.         x->line
  1467.         y redraw    ; force back to same line
  1468.         0->select    ; make sure select is off
  1469.         }
  1470.     else (error "File not on disk (yet).")
  1471.  
  1472. RevertToSaved :
  1473.     if (!modf || ask "Discard changes (Y,N,ESC)? ")
  1474.         FileReRead
  1475.  
  1476. FileWrite :
  1477.     set Q0 cdstrip fname
  1478.     message "\nWrite file as: " set Q0
  1479.     0 QMSS 0 QTrim
  1480.     if (!(32 exist Q0) || ask "Overwrite existing file?") {
  1481.         bufnum->x
  1482.         if (buffind Q0 && (bufnum != x)) 
  1483.             close    ;throw away copy if in buffer, and not current file
  1484.         if !(stopped (write Q0)) {
  1485.             set fname Q0  ;change file name only if write successful
  1486.             }
  1487.         }
  1488.  
  1489. RegionWrite :        ; otta see about appending
  1490.     if !select (NoBlock return)
  1491.     set Q0 ""
  1492.     message "\nName of file to write block to: " set Q0 
  1493.     0 QCap 0 QTrim 
  1494.     if !(mark(to Q0 match "LPT" || match "PRN"))
  1495.         (0 QMSS)    ; if it's not a port .MSS it
  1496.     if (!(32 exist Q0) || ask "Overwrite existing file? ") {
  1497.         if !ColMode {
  1498.             writeregion togmark Q0
  1499.             mark {
  1500.                 if (buffind Q0) FileReRead    ; if file was open, reread
  1501.                 }
  1502.             }
  1503.         else {
  1504.             ColCopy        ; get column to QH
  1505.             mark {
  1506.                 to QH                ; get into column buffer
  1507.                 if length (write Q0)        ; and write it
  1508.                 if (buffind Q0) FileReRead    ; if file was open, re-read
  1509.                 }
  1510.             }
  1511.         }
  1512.  
  1513. DirectoryNew :     set QD cd
  1514.     if stopped { message "\nChange directory to: " set cd }
  1515.     set cd QD    ; does this save old dir? Push/Pop capability?
  1516.  
  1517. DirectoryGoTo :  DirectoryNew 
  1518.  
  1519. PickDirFile :
  1520. ;    Point and shoot open file and set current directory
  1521.         set Q0 "*.*"
  1522.     message "\nInsert optional Drive & Dir spec: " set Q0
  1523.     16 set Q0 flist Q0
  1524.     open Q0
  1525.     SetCurrentDir
  1526.  
  1527. SetColors :
  1528. ;    set Q0 "spedit.exe" NeedDisk
  1529.     if (ovlmodf) (ovlwrite "%")
  1530.     if (2 exist "colors.ovl") (ovlread "colors")
  1531.     else if (2 exist "colors.uim") (mread "colors")    ; change ext.
  1532.     else (error "Unable to find colors overlay or macros.")
  1533.  
  1534. UIWriteAs :
  1535.     do    {
  1536.         set Q0 "" message "\nSave Editor setup in file: " set Q0
  1537.         if (!length Q0)
  1538.             stopped error "You must give the setup file a name."
  1539.         else if (0 QWild)
  1540.             stopped error "Wildcards are not allowed."
  1541.         else {
  1542.             set Q0 fchange "%.UI" Q0
  1543.             if (!(32 exist Q0) || ask "Overwrite existing file?") {
  1544.                 ovlwrite Q0
  1545.                 break
  1546.                 }
  1547.             }
  1548.         }
  1549.  
  1550. UIOpen :
  1551.     status "\nGetting user interfaces..."
  1552.     10 set Q0 flist "*.UI"
  1553.     if (!length Q0) error "No alternate user interfaces found."
  1554.     if ovlmodf UISave
  1555.     set Q0 fchange "%.UI" Q0
  1556.     -1 ovlread Q0
  1557. SetEmulation: UIOpen    ; compatibility
  1558.  
  1559. SetOvlModf : 1->ovlmodf ; force save of changes
  1560.  
  1561. SystemCommand :
  1562.     message "\nDOS command: " set Q5
  1563.     mark{ to Q5 erase past isgray}    ; get rid of any leading spaces
  1564.     set Q0 "spedit.exe" NeedDisk
  1565.     draw
  1566.     if (0 subchar Q5)
  1567. ;        (1+8 call "%comspec% " Q5)        ; 4dos
  1568.         (1 call "command /c" Q5)        ;+BIGDOS
  1569.     else {
  1570.         exitmessage "--Type EXIT to return to Sprint--\r\n"
  1571.                 SetOvlModf         ; save the damn variables
  1572.         BIGDOS call "command"        ; try removing 8, runs restart
  1573.         }
  1574.  
  1575. PipedCommand :    ; uEMACS style feature to get redir. output into temp buffer
  1576.         message "\nPiped command: " set Q5
  1577.         5 QTrim ; remove blanks
  1578. ;       set Q0 "spedit.exe" NeedDisk draw
  1579.         if (0 subchar Q5) (
  1580.                 0 QTMP          ; create temp file in home dir
  1581.         status "\nPlease wait..."
  1582.                 call "command /c " Q5 "> " Q0    ; 32 preserves screen
  1583.                 open ""
  1584.                 read Q0 r toend
  1585.                 fdelete Q0
  1586.                 )
  1587.  
  1588. FilterCommand :        ; uEMACS feature to run filter on current file, beware
  1589.     if NeedSave WantSave    ; strongly recommended
  1590.         message "\nFilter command: " set Q5
  1591.         5 QTrim ; remove blanks
  1592. ;       set Q0 "spedit.exe" NeedDisk        draw
  1593.         if (0 subchar Q5) (
  1594.                 0 QTMP          ; create temp file in home dir
  1595.         status "\nPlease wait..."
  1596.                 call "command /c " Q5 "< " fname "> " Q0    ; some redirection, hope it works most of the time
  1597.         clear        ; empty current buffer
  1598. ;        open ""        ; open unnamed instead
  1599.           read Q0        ; put results back in
  1600.         r toend        ; get to start
  1601.           fdelete Q0    ; kill temp file
  1602.          )
  1603.  
  1604. ;----------------------------------------------
  1605. ;    subsection:    macro management
  1606.  
  1607. ; core stuff
  1608. ; -----------------------------------------------------------------
  1609. ; Deletions
  1610. ; -----------------------------------------------------------------
  1611. ; Variables
  1612. ; -----------------------------------------------------------------
  1613. ; Forward Declarations
  1614. ; -----------------------------------------------------------------
  1615. ; General Macros
  1616.  
  1617. ASCIITable : 
  1618.     call "list  f:ascii.txt"        ; use list.com to display
  1619.  
  1620. CharValue : current ->x message "Char. (%c): " x = "%d " x = "%xh"
  1621.  
  1622. ; Remarks by Andrew Morrow
  1623. ; The original EscapeKey would call KeyRecordEnd (who would call
  1624. ; MacroCollEnd _only_ when recording was ON.  Thus, when the keyrecord
  1625. ; was replayed, the ESC that was the last char in the keyrecord would
  1626. ; never invoke MacroCollEnd who could decide to replay the keyrecord again.
  1627. ;
  1628. ; The fix is to have a unique key to do Macro/Finish and to remove the
  1629. ; call to KeyRecordEnd from EscapeKey.    --I don't understand this at all
  1630.  
  1631. ; This assumes that the calling macros put a message for display using 'mode'
  1632. ; Sample : 'Keyboard recording on.  Press ESC to end recording.'
  1633.  
  1634. MacroCollBegin :
  1635.     set QF ""    ; conflict here with what Gloss does with QF prior to storage, inserting 254s and desc.
  1636.     if record {
  1637.         1 Bell message "\nKey recording canceled."
  1638.         0->record
  1639.         OldStatLine->statline
  1640.         }
  1641.     else    {
  1642.         15->record
  1643.         statline ->OldStatLine
  1644.         2->statline
  1645.         }
  1646.  
  1647. MacroCollDo :    ; where's this from? What's the point of macrorepcnt
  1648.     || 1 -> MacroRepCnt
  1649.     if record (1 Bell message "\nCurrently recording keys.")
  1650.     else MacroRepCnt repeat (keypushback QF)
  1651.     0 -> MacroRepCnt
  1652.  
  1653. MacroCollEnd :
  1654.     if record {
  1655.         0->record
  1656.         OldStatLine->statline
  1657.         draw
  1658.         }
  1659.     else if (!MacroRepCnt) MacroCollDo    ; don't get what this does.
  1660.     else {
  1661.         --MacroRepCnt
  1662.         if (MacroRepCnt > 0) (keypushback QF)
  1663.         }
  1664.  
  1665. MacroCollHalt : if record MacroCollEnd ; ???
  1666.  
  1667. ;; Note that .MAC files can be read with 'sp <foo.mac' to redirect input!
  1668. MacroCollLoad :
  1669.     set QD ""
  1670.     message "\nFile to get recording from: "
  1671.     set QD
  1672.     if (!length QD) (set QD "*.MAC")        ; to force a list if no entry
  1673.     set QD cdstrip fchange "%.MAC" QD
  1674.     13 QCap
  1675.     if (2 exist QD) {
  1676.         mark {
  1677.             to QF
  1678.             clear
  1679.             read QD
  1680.             message "\nRecording loaded."
  1681.             }
  1682.         }
  1683.  
  1684. MacroCollSave :
  1685.     set QD flist "%.MAC"
  1686.     message "\nIn which file should the recording be saved? " set QD
  1687.     mark    {
  1688.         to QF
  1689.         write QD
  1690.         message "\nRecording saved."
  1691.         }
  1692.  
  1693. MacroCollRepeat :
  1694.     get "How many times" MacroCollDo
  1695.  
  1696. MacroLoad : 10 mread flist "*.spm" 
  1697.  
  1698. MacroRunFile :
  1699.     set Q0 fname
  1700.     if (mark (to Q0 1 search ".spm")) {
  1701.         if (modf=1 || !exist Q0) FileSave
  1702.         mread fname
  1703.         }
  1704.     else    (message "\nFile does not have .spm extension.")
  1705.  
  1706. ; Key macros are mostly dependent on Macro macros
  1707. KeyAssignError : stopped error "That key may not be re-assigned."
  1708.  
  1709. KeyCanAssign :    ; check if the passed key is OK to bind
  1710.         ->int keyin
  1711.     if (keyin < 20h || keyin > 0ffh)
  1712.         case {
  1713.         '^I'    0,
  1714.         18ah    0,
  1715.         18dh 0,
  1716.         '^M'    0,
  1717.         abortkey 0,
  1718. ;        10ah    0,        ; F10
  1719.         $    1
  1720.             }
  1721.     else 0        ; Printable Ascii is unassignable
  1722.  
  1723. KeyAssign : message "Press key to reassign: "
  1724.     KeyGet->x if (x == '^[' || x==abortkey) {message "\n" abort}
  1725.     message "\nEnter macro: "
  1726.     x macro
  1727.  
  1728. KeyAssignMacro : 
  1729.     status "\nTo which key should the macro be assigned: " KeyGet macro
  1730.  
  1731. KeyReMap :
  1732.     draw
  1733.     infobox "" {
  1734.     "You may shift commands from one Function",
  1735.     "or Command key (Alt, Ctrl), to another.",
  1736.     "_",
  1737.     "If you press the wrong key as the",
  1738.     "key to be defined, press it again",
  1739.     "to cancel the change."
  1740.         }
  1741.     do    {
  1742.         status "\nKey to be defined: "
  1743.         KeyGet->x
  1744.         if (x KeyCanAssign) {
  1745.             status "\nWhich key currently performs this command? "
  1746.             KeyGet keyhelp        ; get macro to Q0
  1747.             if (mark (to Q0 match "text"))
  1748.                 (message "\nSorry, only command keys may be reassigned")
  1749.             else (x macro Q0)        ; make assignment
  1750.             }
  1751.         else KeyAssignError
  1752.         } while (ask "\nReassign another? ")
  1753.  
  1754. Meta_ize :  -> int ktmp
  1755.     set QD ""    ; clean it from last time
  1756.     mark { to QD    ; dump results in QD
  1757.         if ktmp < 20h {    (ktmp+40h) put " ^%c " }
  1758.     ; Function keys
  1759.         else if ktmp < 180h { (ktmp-100h) put " F%d "}
  1760.     ; Meta Control keys, shifted by 40h out of control codes
  1761.         else if ktmp < 1A0h { (ktmp-180h)+40h put " ~^%c "}
  1762.     ; Meta Keys
  1763.         else { (ktmp-180h) put " ~%c "}
  1764.         ktmp keyhelp    ; keyhelp puts macro name into Q0
  1765.         TabAction ktmp put "f%xh : " 
  1766.         TabAction insert Q0
  1767.         }
  1768.  
  1769. KeyReport : ; use this to write complete mapping report
  1770.     int ktmp
  1771.     message "\nPress a command key "
  1772.         KeyGet -> ktmp 
  1773. ;        if (ktmp < 20h || ktmp > 0ffh) {
  1774.             ktmp Meta_ize
  1775.             message "\n" QD 
  1776. ;            }
  1777.  
  1778. KeyReportAll : ; use this to write complete mapping report
  1779.     int ktmp 0
  1780.     set Q8 "KEYBIND.MSS"
  1781.     8 FileTest FileGet
  1782.     clear
  1783.     status "Working ...."
  1784.     while (ktmp < 200h) {
  1785.     ; use QD scratch reg. and test for Q0 unknown skip
  1786.         if ktmp = 20h insert "\n"
  1787.         if ktmp = 180h insert "\n"
  1788.         if ktmp = 1A0h insert "\n"
  1789.         if (ktmp <= 20h || ktmp > 0ffh) {
  1790.             ktmp Meta_ize
  1791.             insert QD insert "\n"
  1792.             }
  1793.         ++ktmp
  1794.         }
  1795.  
  1796. KeyRecordMsg :
  1797.     mode "Keyboard recording on. Use Glossary/Halt to end recording."
  1798. ; KeyRecordEnd is in Gloss I guess. I think Esc. really doesn't work
  1799.  
  1800. MacroExecute :
  1801.     message "\nEnter macro: " set QG
  1802.     $ macro QG
  1803.  
  1804. KeyAssignMacro :    ; in core
  1805.     message "\nEnter macro: " set QG
  1806.     status "\nTo which key should the macro be assigned: "
  1807.     KeyGet->x
  1808.     if (x = '^[')
  1809.         abort
  1810.     if (x KeyCanAssign)
  1811.         { x macro QG }
  1812.     else
  1813.         KeyAssignError
  1814.  
  1815. ;#include "gloss.uim"
  1816.  
  1817. MacroClear :
  1818.     if (2 exist "NOTHER.ui") (-2 ovlread "NOTHER.ui")
  1819.     else    if (2 exist "sp.spm") (2 mread "sp.spm")
  1820.     else error "Macro file SP.SPM not found."    ; until I learn command line switches
  1821.  
  1822. QuickCard : if ovlmodf (2 ovlwrite "sp") 2 mread "qcard"
  1823.  
  1824. ;----------------------------------------------
  1825. ;    subsection:    window management
  1826. ScreenBottom : wlines - 1->dline
  1827.  
  1828. ScreenTop : 0->dline while (inruler || isopen) (toeol c)
  1829.  
  1830. ScreenCenter : (wlines/2) redraw
  1831.  
  1832. ContScrollMsg : message "\nContinuous scroll. Press 0 - 9 to change rate, any other key to stop."
  1833.  
  1834. ContScrollDown :
  1835.     ContScrollMsg
  1836.     while (!RateChange && line != ++line) (draw RepeatRate ?(RepeatRate wait))
  1837.     status ""
  1838.  
  1839. ContScrollUp :
  1840.     ContScrollMsg
  1841.     while (!RateChange && line != --line) (draw RepeatRate ?(RepeatRate wait))                                
  1842.     status ""
  1843.  
  1844. ScrollRight :
  1845.         leftedge+40->leftedge
  1846.  
  1847. ScrollLeft :
  1848.                 if !leftedge (1 Bell return)
  1849.                 if ((leftedge-40) > 0) (leftedge-40) ->leftedge
  1850.                 else 0->leftedge
  1851.  
  1852. ScrollBack : r scroll
  1853.  
  1854. ScrollFwd : scroll
  1855.  
  1856. ScrollPrevUp : ->x if !(windows=1) {winswitch x ScreenBack r winswitch}
  1857.  
  1858. ScrollPrevDown : ->x if !(windows=1) {winswitch x ScreenFwd r winswitch}
  1859.  
  1860. WindowBack : r winswitch
  1861.       ExtConfig
  1862.  
  1863. WindowFwd : f winswitch
  1864.      ExtConfig
  1865.  
  1866. WindowClose :
  1867.      0->zoom
  1868.     if windows (--windows
  1869.            ExtConfig)
  1870.  
  1871. WindowOpen :
  1872.     if !zoom ++windows 
  1873.     else {
  1874.         1 Bell
  1875.         message "\nNo new windows may be opened while zoomed."
  1876.         }
  1877.  
  1878. WindowCloseAll :
  1879.      if zoom (--zoom) 1->windows
  1880.      ExtConfig
  1881.  
  1882. WindowDown :
  1883.     windows repeat {
  1884.         winswitch
  1885.         forced (draw)
  1886.         if !dline (toeol c)
  1887.         scroll
  1888.         }
  1889.     while keypressed key
  1890.  
  1891. WindowUp :
  1892.     windows repeat {
  1893.         winswitch
  1894.         forced (draw)
  1895.         if (dline = wlines - 1) (tosol r c)
  1896.         r scroll
  1897.         }
  1898.     while keypressed key
  1899.  
  1900. WindowResize :            ; This is a mode
  1901.     if (windows > 1 && !zoom) {
  1902.         do    {
  1903.             draw
  1904.             message "\nPlus (+) and minus (-) resize current window, ESC and ENTER exit."
  1905.             KeyGet case {
  1906.             '^M'    break,
  1907.             18dh    break,
  1908.             '^['    break,
  1909.             '+'    ++wlines,
  1910.             1abh    ++wlines,
  1911.             '-'    --wlines,
  1912.             1adh    --wlines,
  1913.             $    0 Bell
  1914.                 }
  1915.             }
  1916.         status ""    ; force status line update
  1917.         }
  1918.     else (message "\nCan't resize single window.")
  1919.  
  1920. WindowZoom : if (windows > 1) ++zoom $ redraw
  1921.  
  1922. ;----------------------------------------------
  1923. ;    subsection:    direction /unit control
  1924. ;ToggleDir : Dir ? 0 ->Dir->flag4 -> SearchDirection : 1->Dir->flag4 -> SearchDirection
  1925. ;DirBack    : 0->Dir->flag4 -> SearchDirection
  1926. ;DirFwd : 1->Dir-> flag4 -> SearchDirection
  1927.  
  1928. ;ParagraphObject : repeat (Dir ? ParagraphFwd : ParagraphBack)
  1929. ;SentenceObject : repeat (Dir ? SentenceFwd : SentenceBack)
  1930. ;WordObject :    repeat (Dir ? WordFwd : WordBack)
  1931.  
  1932. ;int TUnit 'w'    ; remember most recent unit of text movement
  1933.  
  1934. ;TUnitFwd : repeat {
  1935. ;    TUnit case (
  1936. ;    'c'    Right,
  1937. ;    'w'    WordFwd,
  1938. ;    'l'    Down,
  1939. ;    's'    SentenceFwd,
  1940. ;    'p'    ParagraphFwd
  1941. ;    )
  1942. ;    1->SearchDirection
  1943. ;    }
  1944. ;
  1945. ;TUnitBack : repeat {
  1946. ;    TUnit case (
  1947. ;    'c'    Left,
  1948. ;    'w'    WordBack,
  1949. ;    'l'    Up,
  1950. ;    's'    SentenceBack,
  1951. ;    'p'    ParagraphBack
  1952. ;    )
  1953. ;    0->SearchDirection    ; a nice assumption
  1954. ;    }
  1955. ;
  1956. ;CharUnit    : 'c' -> TUnit -> flag5 draw
  1957. ;WordUnit    : 'w' -> TUnit -> flag5 draw
  1958. ;LineUnit    : 'l' -> TUnit -> flag5 draw
  1959. ;SentenceUnit    : 's' -> TUnit -> flag5 draw
  1960. ;ParagraphUnit    : 'p' -> TUnit -> flag5 draw
  1961.  
  1962.  
  1963. ;----------------------------------------------
  1964. ;    SECTION:    Automatically-called macro definitions (Main, Init,
  1965. ;            EditKey, MenuKey, etc.)
  1966.  
  1967. : 1->showkeys 
  1968. : 50 -> sounddur
  1969. : 500->soundfreq
  1970. ;: TUnit -> flag5 
  1971. ;see main now : BlockCursor
  1972.  
  1973. HelpDisk :    ; This must preserve Q0 since it has help context!
  1974.     set QD Q0
  1975.     set Q0 "sphelp.hlp" NeedDisk
  1976.     set Q0 QD
  1977.  
  1978. ;DoHelp :
  1979. ;    HelpDisk
  1980. ;    2 help Q0
  1981.  
  1982. DoHelp :    ; whatever is in here is done for 101h code
  1983.     message "\n" Q0    ; this shows macro in menu choice
  1984.  
  1985. EditKey :
  1986.     KeyGet->int ktmp case {
  1987.     '^Q'        KeyGet + 180h,        ; quote
  1988.     1aah        '*',                ; PrtScr
  1989.     1adh        '-',                ; Grey-
  1990.     1abh        '+',                ; Grey+
  1991. ;    101h        101h,            ; F1: help
  1992. ;    10Ah        0,                ; F10: Nothing
  1993.     140h,144h    '^M',            ; mouse left key is accept
  1994.     141h,145h    '^[',            ; mouse right key is cancel
  1995.     14ch        150h,            ; Make '5' be down arrow if code comes
  1996.     189h        '^I',            ; ^I
  1997.     152h,
  1998.     18Ah        '^J',            ; ^J & Ins put in newline
  1999.     18dh        '^M',            ; Enter on numpad
  2000.     '^Z',19bh    exitmenus '^[',    ; Ctrl/Alt-ESC
  2001.     abortkey    exitmenus '^[',
  2002.     $        ktmp
  2003.         }
  2004.  
  2005. MenuBind :
  2006.     do    {
  2007.         status "\nShortcut for menu item: " KeyGet->x
  2008.         if x = '^[' {0 return}    ; if ESC pressed return Null
  2009.         if (x KeyCanAssign) {
  2010.             x keypushback
  2011.             if (x > 255) (0 keypushback)
  2012.             break
  2013.             }
  2014.         else KeyAssignError
  2015.         }
  2016.         '^J' return
  2017.  
  2018. MenuKey :
  2019.     KeyGet->int ktmp case {
  2020.     ' '    150h,            ; down
  2021. ;    '^N'        148h,            ; up
  2022.     '^J'        MenuBind,        ; rebind
  2023.     189h        148h,            ; TabBack:  up
  2024.     '^['        if IsShift (exitmenus 17fh)
  2025.             else ('^['),
  2026.     101h        101h,            ; F1: dohelp
  2027.     14ch        150h,            ; Make '5' be down arrow if code comes
  2028.     140h,144h    '^M',            ; mouse left key is accept
  2029.     141h,145h    '^[',            ; mouse right key is cancel
  2030.     14dh,17fh    '^[',            ; R. Arrow, keyboard record of ESC feeds back as this
  2031.     14bh,18dh    '^M',            ; left Arrow, Enter on numpad
  2032.     1adh        0->showkeys 0,        ; Grey-
  2033.     1abh        1->showkeys 0,        ; Grey+
  2034.     '^Z',19bh    exitmenus '^[',    ; Ctrl/Alt-ESC
  2035.     $        ktmp
  2036.         }
  2037.  
  2038. ; Mode variables
  2039. ;    Select, Append, OverWrite, flag3, flag4, flag5, flag6, hour,
  2040. ;    Minute, Hour>=12
  2041. ; Flag 3 contains the status of 'Column select' mode
  2042. ; Flag 4 Wrap mode, see usage for WordWrap and Space Insert
  2043.  
  2044. NormalMode :
  2045. ;    flags " %2g%[Ins%:Ovr%] %0g%[   %:Sel%] %3g%[   %:Col%] %4g%c/%5g%c"
  2046. ;    flags " %2g%[Ins%:Ovr%] %0g%[   %:Sel%] %3g%[   %:Col%] %4g%[Bck%:Fwd%]"
  2047.     flags " %4g%[Off%:Wrp%:TeX%] %0g%[   %:Sel%] %3g%[   %:Col%] %7g%11+12#+2u:%02u%[a%:p%]m"
  2048.        mode ""
  2049.  
  2050. ; read command-line arguments as file names to open:
  2051.  
  2052. GetConfig :    ; Set FloppyDisk variable
  2053.     int numdisks
  2054.     (hardware "int 11h" & 0c0h)>>6 ->numdisks ; number of floppies - 1
  2055.             ; Drive > ('A'+numdisks) are supposed to be hard
  2056.     if (0 subchar home) > ('A'+numdisks)        0->FloppyDisk    ; Hard-Disk
  2057.     else if !(exist "spsort.exe")            1->FloppyDisk    ; 360ko
  2058.     else if !(exist "qcard.spm")            2->FloppyDisk    ; 720ko
  2059.     else                        3->FloppyDisk    ; 1.2Mo
  2060.  
  2061. InitScreen : ; This makes the initial "sign-on" screen
  2062.     ; over write core's
  2063.     ovlmodf->int saveovlmodf
  2064.     stopped{
  2065.         statline -> x
  2066.         0->statline
  2067.         mark {
  2068.             to QD clear
  2069.             version put "%d" toend r (c c)
  2070.             if (version < 100) "0." else "."
  2071.             }
  2072.         open "" draw
  2073.         infobox "" {
  2074.             "",
  2075.             "\>NOTHER Scribe/TeX Compatible\>",
  2076.             "\>Alternative User Interface\>",
  2077.             "_",
  2078.             "\>Sprint Version " QD "\>",
  2079.             "\>Copyright (c) 1988 Borland International\>",
  2080.             "\>All Rights Reserved\>",
  2081.             ""
  2082.             }
  2083.         {if keypressed (500 delay) else (500 wait)}
  2084.         } {close x -> statline}
  2085.         saveovlmodf->ovlmodf
  2086.  
  2087. LoadSpeller:    ;fwd declare, it's in spell.uim
  2088. Init :
  2089.     ovlmodf -> int OMSave
  2090.     NormalMode
  2091.     forced InitScreen        ; Show UI sign-on
  2092.     GetConfig            ; Set FloppyDisk variable
  2093.     if AutoCorrect LoadSpeller    ; if required, load speller
  2094.     set QA "STANDARD.SPG"    ; default glossary name (if used)
  2095.     set QJ "SPELLER AMERICAN.LX1 USER.LX2" ; standard speller
  2096.     set QK "\xff\xff\xff"    ; empty Spmerge menu data
  2097.     OMSave ->ovlmodf
  2098.  
  2099. InitArg :
  2100.     if (n < 6) (++n->windows)
  2101. ; Just to prevent seeing an existing file in a buffer when a starname
  2102. ; is given from the command line, we do the following:
  2103. ;    if (0 QWild) {
  2104. ;        open ""            ; force user to select filename commented out 
  2105. ;        draw }
  2106.     set Q9 Q0
  2107.     9 FileTest ; returns 1 exist, 2 spec, no file, or 0 no spec
  2108.     FileGet
  2109.  
  2110. ; The following macro is run every time Sprint starts up.  It is called from
  2111. ; main, before any other processing.  This means, that regardless of how the
  2112. ; editor was started (init, or via restart macro), all variables are sure to be 
  2113. ; reset to their defaults.  Users may add any other variable initialization
  2114. ; to this macro.
  2115.  
  2116. ResetDefaults :    
  2117.     0->n                ; n=count of command-line files
  2118.     ->ColMode
  2119.     ->flag3            ; Col mode flag
  2120.     1->statline
  2121.     2 ->scrollborder
  2122.     3 ->SearchOpt        ; FinalWord uses wild card searches?
  2123.     '^['->abortkey
  2124.     InsertMode ->overwrite    ; restore old overwrite mode
  2125.  
  2126. ; Note: main do loop is executed for *every* key, including letters. 
  2127. ; Don't make it too complicated or it will slow down maximum typing
  2128. ; speed!
  2129.  
  2130. Main :
  2131.     ResetDefaults    ; initialize all vars here.
  2132.     BlockCursor    ; make sure it's on
  2133.     stopped { ; so user can't abort while checking file dates.
  2134.         if !files (stopped DefaultRuler)                ; make sure files have rulers
  2135.         else {
  2136.             bufnum -> x
  2137.             do { ; read any files that have newer versions
  2138.                 stopped                    ; to disable abortcheck in loop
  2139.                 if (!modf && (datecheck fname == 1)) {    ; newer version of file; used to be > 0
  2140.                     clear
  2141.                     read fname
  2142.                     r toend
  2143.                     }
  2144.                 bufswitch
  2145.                 } while bufnum!=x
  2146.             }
  2147.         }
  2148.     do {
  2149.         if stopped dokey
  2150.         else {
  2151. ;            QuickFill
  2152.             AppendNext->append
  2153.             0->AppendNext
  2154.             }
  2155.         }
  2156.  
  2157. ; This macro is called when -r is passed to the editor.  The editor does 
  2158. ; that itself when it reloads after calling the formatter to do a pagination 
  2159. ; operation.  This is controlled by the 8 bit in the argument to the 
  2160. ; "call spfmt" macro.  See Paginate.
  2161. ; removed conversion code, added restart code for faster previewing with TeX 
  2162. ; RDT, 4/8/91
  2163.  
  2164. Restart :
  2165.     -> ReturnCode
  2166.     NormalMode
  2167.         if (exist "log.$$$") {            ; paginated, need to fix for network
  2168.         draw pageread "log.$$$"
  2169.         fdelete "log.$$$"
  2170.         }
  2171.     while keypressed key    ; eliminate type-ahead
  2172. ; otta have home var. inserted here for network users
  2173.  
  2174. GlossSave:    ;fwd declare, it follows in gloss.uim
  2175. ExitEditor :     bufnum->x
  2176.     do    {
  2177.         if NeedSave WantSave
  2178.         else if (IsUnnamed && IsOnlyRuler) {
  2179.             (if (bufnum==x) (close bufnum->x) else close)
  2180.             }
  2181.         } while (bufswitch && bufnum != x)
  2182.     EraseSwap || !files -> killswap
  2183. ;    set Q0 "spedit.exe" NeedDisk
  2184.     GlossSave    ; save glossary if in use
  2185.     SetOvlModf    ; save variables always, use resetdefaults to counteract
  2186.     exit
  2187.  
  2188. ;## end
  2189.