home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 9 / CD_ASCQ_09_1193.iso / news / 557 / anedit / ae5.pas < prev    next >
Pascal/Delphi Source File  |  1993-03-24  |  47KB  |  1,188 lines

  1. UNIT AE5 ;
  2.  
  3. {$R-}
  4. {$B-}
  5. {$I-}
  6. {$S+}
  7. {$V-}
  8.  
  9. INTERFACE
  10.  
  11. USES Crt, Dos, Printer, AE0, AE1, AE2, AE3, AE4 ;
  12.  
  13. PROCEDURE Initialize ;
  14. PROCEDURE ShutOff ;
  15. PROCEDURE ExecKey (KeyNr : WORD) ;
  16.  
  17. IMPLEMENTATION
  18.  
  19. {-----------------------------------------------------------------------------}
  20. { Initializes all necessary variables, and loads the file specified on the    }
  21. { command line into the first workspace.                                      }
  22. {-----------------------------------------------------------------------------}
  23.  
  24. PROCEDURE Initialize ;
  25.  
  26. VAR Reg : REGISTERS ;
  27.     Counter : WORD ;
  28.     ConfigFile : FILE OF ConfigBlock ;
  29.     ConfigFilePath : PathStr ;
  30.     AEDir : DirStr ;
  31.     AEName : NameStr ;
  32.     AEExt : ExtStr ;
  33.     WorkFile : FILE OF WorkBlock ;
  34.     Work : WorkBlock ;
  35.     ValidConfig : boolean ;
  36.  
  37. BEGIN
  38. CLRSCR ;
  39. ProgramFinished := FALSE ;
  40. {$IFDEF DEVELOP }
  41. MinMemAvail := MEMAVAIL ;
  42. InitMemAvail := MEMAVAIL ;
  43. {$ENDIF }
  44. { check the presence of a color video adapter }
  45. Reg.AH := 15 ;
  46. INTR ($10, Reg) ;
  47. ColorCard := Reg.AL <> Mono ;
  48. { set start address of screen memory }
  49. IF ColorCard
  50.    THEN BEGIN
  51.         DisplayPtr := PTR ($B800, 0) ;
  52.         StatusLinePtr := PTR ($B800, NrOfTextLines * ColsOnScreen * 2) ;
  53.         END
  54.    ELSE BEGIN
  55.         DisplayPtr := PTR ($B000, 0) ;
  56.         StatusLinePtr := PTR ($B000, NrOfTextLines * ColsOnScreen * 2) ;
  57.         END ;
  58. { store screen settings }
  59. OrigCursorType := GetCursor ;
  60. OrigTextAttr := TextAttr ;
  61. { initialize setup }
  62. Config.Setup := DefaultSetup ;
  63. TextAttr := ScreenColorArray [Config.Setup.ScreenColors].NormAttr ;
  64. { initialize paste buffer, macro stack and several global variables }
  65. NEW (PasteBuffer) ;
  66. PasteBuffersize := 0 ;
  67. MacroStackpointer := Inactive ;
  68. MacroDefining := Inactive ;
  69. LoadfileName := '*.*' ;
  70. FindString := '' ;
  71. ReplaceString := '' ;
  72. SearchOptions := '' ;
  73. SearchType := Find ;
  74. { clear keyboard buffer }
  75. ClearKeyBuffer ;
  76. EscPressed := FALSE ;
  77. { create empty histories }
  78. CreateHistory (FileHist, 80) ;
  79. CreateHistory (FindHist, 255) ;
  80. CreateHistory (ReplaceHist, 255) ;
  81. { initialize workspaces }
  82. CurrentWsnr := 1 ;
  83. REPEAT
  84.     NEW (Workspace [CurrentWsnr].Buffer) ;
  85.     ClearCurrentWs ;
  86.     {$IFDEF DEVELOP }
  87.     IF CurrentWsnr = 1
  88.        THEN BasicMemAvail := MEMAVAIL ;
  89.     {$ENDIF }
  90.     INC (CurrentWsnr) ;
  91. UNTIL (CurrentWsnr > MaxNrOfWorkspaces) OR (MAXAVAIL < WsBufSize) ;
  92. NrOfWorkspaces := CurrentWsnr - 1 ;
  93. CurrentWsnr := 1 ;
  94. CurrentWs := Workspace [CurrentWsnr] ;
  95. { initialize macros to default }
  96. FOR Counter := 1 TO NrOfMacros DO
  97.     Config.Macro.Length [Counter] := Inactive ;
  98. { try to find setup file }
  99. ConfigFilePath := '' ;
  100. IF Exists (ConfigFileName)
  101.    THEN ConfigFilePath := FExpand (ConfigFileName)
  102.    ELSE BEGIN
  103.         IF LO (DosVersion) >= 3
  104.            THEN BEGIN
  105.                 { look for setup file in directory where AE.EXE is }
  106.                 FSplit (PARAMSTR (0), AEDir, AEName, AEExt) ;
  107.                 IF Exists (AEDir + ConfigFileName)
  108.                    THEN ConfigFilePath := AEDir + ConfigFileName ;
  109.                 END
  110.         END ;
  111. ValidConfig := TRUE ;
  112. IF LENGTH (ConfigFilePath) > 0
  113.    THEN BEGIN
  114.         { load setup }
  115.         ASSIGN (ConfigFile, ConfigFilePath) ;
  116.         RESET (ConfigFile) ;
  117.         READ (ConfigFile, Config) ;
  118.         CLOSE (ConfigFile) ;
  119.         CheckDiskError ;
  120.         IF (DiskError <> 0) OR
  121.            (Config.Setup.Version < UpCompatSetupVersion) OR
  122.            (Config.Setup.Version > AEVersionNr)
  123.            THEN BEGIN
  124.                 { error reading setup file or incompatible version:
  125.                   reset to default }
  126.                 Config.Setup := DefaultSetup ;
  127.                 FOR Counter := 1 TO NrOfMacros DO
  128.                     Config.Macro.Length [Counter] := Inactive ;
  129.                 ValidConfig := FALSE ;
  130.                 END ;
  131.         END ;
  132. Config.Setup.Version := AEVersionNr ;
  133. { set screen colors and cursor }
  134. IF (NOT ColorCard) AND (Config.Setup.ScreenColors > 2)
  135.    THEN { on monochrome card only color settings 1 and 2 are valid }
  136.         Config.Setup.ScreenColors := 1 ;
  137. TextAttr := ScreenColorArray [Config.Setup.ScreenColors].NormAttr ;
  138. CLRSCR ;
  139. SetCursor (Config.Setup.Cursortype) ;
  140. IF NOT ValidConfig
  141.    THEN ErrorMessage (19) ;
  142. { load file(s) to edit }
  143. WorkFilePath := '' ;
  144. IF LENGTH (PARAMSTR (1) ) = 0
  145.    THEN BEGIN
  146.         IF Config.Setup.SaveWork
  147.            THEN BEGIN
  148.                 { look for work file }
  149.                 IF Exists (WorkFileName)
  150.                    THEN WorkFilePath := FExpand (WorkFileName)
  151.                    ELSE BEGIN
  152.                         IF LO (DosVersion) >= 3
  153.                            THEN BEGIN
  154.                                 { look in directory where AE.EXE is }
  155.                                 FSplit (PARAMSTR (0), AEDir, AEName, AEExt) ;
  156.                                 IF Exists (AEDir + WorkFileName)
  157.                                    THEN WorkFilePath := AEDir + WorkFileName ;
  158.                                 END ;
  159.                         END ;
  160.                 END ;
  161.         IF WorkFilePath = ''
  162.            THEN Message ('Another Editor, version ' + AEVersionNr +
  163.                          '. Press F1 for help')
  164.            ELSE BEGIN
  165.                 { load work file }
  166.                 ASSIGN (WorkFile, WorkFilePath) ;
  167.                 RESET (WorkFile) ;
  168.                 READ (WorkFile, Work) ;
  169.                 CLOSE (WorkFile) ;
  170.                 IF (DiskError <> 0) OR
  171.                    (Work.Version < UpCompatWorkVersion) OR
  172.                    (Work.Version > AEVersionNr)
  173.                    THEN ErrorMessage (23)
  174.                    ELSE BEGIN
  175.                         IF Work.NrOfWorkspaces > NrOfWorkspaces
  176.                            THEN Work.NrOfWorkspaces := NrOfWorkspaces ;
  177.                         FOR CurrentWsnr := 1 TO Work.NrOfWorkspaces DO
  178.                             BEGIN
  179.                             LoadFile (Work.Filename [CurrentWsnr]) ;
  180.                             { set cursor position }
  181.                             FOR Counter := 1 TO
  182.                                 (Work.CursorPos [CurrentWsnr].Linenr - 1) DO
  183.                                 LineDown (CurrentWs.CurPos) ;
  184.                             EndOfLine (CurrentWs.CurPos) ;
  185.                             IF (Work.CursorPos [CurrentWsnr].Index <
  186.                                 CurrentWs.CurPos.Index)
  187.                                 THEN SkipUp (CurrentWs.CurPos,
  188.                                              (CurrentWs.CurPos.Index -
  189.                                           Work.CursorPos [CurrentWsnr].Index) ) ;
  190.                             CurrentWs.FirstVisibleLine :=
  191.                                 Work.FirstVisibleLine [CurrentWsnr] ;
  192.                             CurrentWs.FirstScreenCol :=
  193.                                 Work.FirstScreenCol [CurrentWsnr] ;
  194.                             Workspace[CurrentWsnr] := CurrentWs ;
  195.                             END ;
  196.                         CurrentWsnr := Work.CurrentWsnr ;
  197.                         CurrentWs := Workspace [CurrentWsnr] ;
  198.                         END ;
  199.                 END ;
  200.         END
  201.    ELSE BEGIN
  202.         LoadfileName := FExpand (PARAMSTR (1) ) ;
  203.         AddToHistory (FileHist,UpperCase(PARAMSTR (1))) ;
  204.         IF Wildcarded (Loadfilename)
  205.            THEN BEGIN
  206.                 GetFileFromList (LoadfileName) ;
  207.                 IF NOT EscPressed
  208.                    THEN LoadFile (LoadfileName) ;
  209.                 END
  210.            ELSE LoadFile (LoadfileName) ;
  211.         END ;
  212. {$IFDEF DEVELOP }
  213. StdMemAvail := MEMAVAIL ;
  214. MinMemAvail := MEMAVAIL ;
  215. {$ENDIF }
  216. END ;
  217.  
  218. {-----------------------------------------------------------------------------}
  219. { Saves workspace and restores screen settings before exiting program.        }
  220. {-----------------------------------------------------------------------------}
  221.  
  222. PROCEDURE ShutOff ;
  223.  
  224. VAR WorkFile : FILE OF WorkBlock ;
  225.     Work : WorkBlock ;
  226.     i : BYTE ;
  227.  
  228. BEGIN
  229. IF Config.Setup.SaveWork
  230.    THEN BEGIN
  231.         {save work file }
  232.         IF LENGTH (WorkFilePath) = 0
  233.            THEN WorkFilePath := FExpand (WorkFileName) ;
  234.         Work.Banner := WorkFileName ;
  235.         Work.Version := AEVersionNr ;
  236.         Work.NrOfWorkspaces := NrOfWorkspaces ;
  237.         FOR i := 1 TO MaxNrOfWorkspaces DO
  238.             BEGIN
  239.             Work.Filename [i] := Workspace [i].Name ;
  240.             Work.CursorPos [i] := Workspace [i].CurPos ;
  241.             Work.FirstVisibleLine [i] := Workspace [i].FirstVisibleLine ;
  242.             Work.FirstScreenCol [i] := Workspace [i].FirstScreenCol ;
  243.             END ;
  244.         Work.CurrentWsnr := CurrentWsnr ;
  245.         ASSIGN (WorkFile, WorkFilePath) ;
  246.         REWRITE (WorkFile) ;
  247.         WRITE (WorkFile, Work) ;
  248.         CLOSE (WorkFile) ;
  249.         END ;
  250. SetCursor (OrigCursorType) ;
  251. TextAttr := OrigTextAttr ;
  252. CLRSCR ;
  253. {$IFDEF DEVELOP }
  254. WRITELN ('HEAP MEMORY:') ;
  255. WRITELN ('Available at startup        ',InitMemAvail:6, ' bytes') ;
  256. WRITELN ('Minimal needs (1 workspace) ',(InitMemAvail-BasicMemAvail):6,
  257.          ' bytes') ;
  258. IF NrOfWorkspaces > 1
  259.    THEN WRITELN ('Needed for ',NrOfWorkspaces,' workspaces     ',
  260.                  (InitMemAvail-StdMemAvail):6,' bytes') ;
  261. WRITELN ('Dynamically used            ',(StdMemAvail-MinMemAvail):6,
  262.          ' bytes') ;
  263. WRITELN ('Always available            ',MinMemAvail:6, ' bytes') ;
  264. {$ENDIF }
  265. END ;
  266.  
  267. {-----------------------------------------------------------------------------}
  268. { Executes the action corresponding to the key number given.                  }
  269. {-----------------------------------------------------------------------------}
  270.  
  271. PROCEDURE ExecKey (KeyNr : WORD) ;
  272.  
  273. VAR Counter               : WORD ;
  274.     OldCurPos             : Position ;
  275.     MacroNumber           : WORD ;
  276.     NextPos               : Position ;
  277.     BlockStart, BlockStop : WORD ;
  278.     TabSteps              : WORD ;
  279.     LineLength, NewSpaces : WORD ;
  280.     OldMark               : WORD ;
  281.  
  282. BEGIN
  283. WITH CurrentWs DO
  284.   BEGIN
  285.   CASE KeyNr OF
  286.     331 : { left }
  287.           BEGIN
  288.           IF (Buffer^ [CurPos.Index - 2] = CR) AND (Buffer^ [CurPos.Index - 1] = LF)
  289.              THEN SkipUp (CurPos, 2)
  290.              ELSE SkipUp (CurPos, 1) ;
  291.           END ;
  292.     333 : { right }
  293.           BEGIN
  294.           IF (Buffer^ [CurPos.Index] = CR) AND (Buffer^ [CurPos.Index + 1] = LF)
  295.              THEN SkipDown (CurPos, 2)
  296.              ELSE SkipDown (CurPos, 1) ;
  297.           END ;
  298.     328 : { up }
  299.           BEGIN
  300.           LineUp (CurPos) ;
  301.           END ;
  302.     336 : { down }
  303.           BEGIN
  304.           LineDown (CurPos) ;
  305.           END ;
  306.     327 : { Home }
  307.           BEGIN
  308.           Home (CurPos) ;
  309.           END ;
  310.     335 : { End }
  311.           BEGIN
  312.           EndOfLine (CurPos) ;
  313.           END ;
  314.     329 : { PgUp }
  315.           BEGIN
  316.           FOR Counter := 1 TO (NrOfTextLines - 1) DO
  317.               LineUp (CurPos) ;
  318.           END ;
  319.     337 : { PgDn }
  320.           BEGIN
  321.           FOR Counter := 1 TO (NrOfTextLines - 1) DO
  322.               LineDown (CurPos) ;
  323.           END ;
  324.     388 : { ^PgUp }
  325.           BEGIN
  326.           CurPos.Index := 1 ;
  327.           CurPos.Linenr := 1 ;
  328.           CurPos.Colnr := 1 ;
  329.           END ;
  330.     374 : { ^PgDn }
  331.           BEGIN
  332.           FOR Counter := CurPos.Index TO BufferSize DO
  333.               IF Buffer^ [Counter] = LF THEN INC (CurPos.Linenr) ;
  334.           CurPos.Index := BufferSize ;
  335.           CalculateColnr (CurPos) ;
  336.           END ;
  337.     375 : { ^Home }
  338.           BEGIN
  339.           WHILE CurPos.Linenr > FirstVisibleLine.Linenr
  340.                 DO LineUp (CurPos) ;
  341.           Home (CurPos) ;
  342.           END ;
  343.     373 : { ^End }
  344.           BEGIN
  345.           WHILE (CurPos.Linenr < (FirstVisibleLine.Linenr + NrOfTextLines - 1) ) AND
  346.                 (CurPos.Index < BufferSize)
  347.                 DO LineDown (CurPos) ;
  348.           Home (CurPos) ;
  349.           END ;
  350.     371 : { ^left }
  351.           BEGIN
  352.           IF CurPos.Index > 1
  353.              THEN BEGIN
  354.                   REPEAT DEC (CurPos.Index) ;
  355.                          IF Buffer^ [CurPos.Index] = LF
  356.                             THEN DEC (CurPos.Linenr) ;
  357.                   UNTIL ( (NOT (Buffer^ [CurPos.Index] IN WordSeparators) ) OR
  358.                          (CurPos.Index = 1) ) ;
  359.                   WHILE ( (NOT (Buffer^ [CurPos.Index] IN WordSeparators) ) AND
  360.                          (CurPos.Index > 0) ) DO
  361.                         DEC (CurPos.Index) ;
  362.                   INC (CurPos.Index) ;
  363.                   CalculateColnr (CurPos) ;
  364.                   END ;
  365.           END ;
  366.     372 : { ^right }
  367.           BEGIN
  368.           WHILE NOT ( (Buffer^ [CurPos.Index] IN WordSeparators) OR
  369.                      (CurPos.Index = BufferSize) ) DO
  370.                 INC (CurPos.Index) ;
  371.           WHILE (Buffer^ [CurPos.Index] IN WordSeparators) AND
  372.                 (CurPos.Index < BufferSize) DO
  373.                 BEGIN
  374.                 IF Buffer^ [CurPos.Index] = LF
  375.                    THEN INC (CurPos.Linenr) ;
  376.                 INC (CurPos.Index) ;
  377.                 END ;
  378.           CalculateColnr (CurPos) ;
  379.           END ;
  380.     340 : { shift-F1 }
  381.           BEGIN
  382.           AlterSetup ;
  383.           END ;
  384.     316 : { F2 }
  385.           BEGIN
  386.           Workspace [CurrentWsnr] := CurrentWs ;
  387.           SaveFile (CurrentWsnr) ;
  388.           CurrentWs := Workspace [CurrentWsnr] ;
  389.           END ;
  390.     341 : { shift-F2 }
  391.           BEGIN
  392.           Workspace [CurrentWsnr] := CurrentWs ;
  393.           EnterString (Name, NIL, 'New file name: ', 79, TRUE, TRUE) ;
  394.           IF NOT EscPressed
  395.              THEN BEGIN
  396.                   Name := FExpand (Name) ;
  397.                   SaveFile (CurrentWsnr) ;
  398.                   END ;
  399.           CurrentWs := Workspace [CurrentWsnr] ;
  400.           END ;
  401.     317 : { F3 }
  402.           BEGIN
  403.           LoadfileName := '*.*' ;
  404.           EnterString (LoadfileName, FileHist, 'Load file: ', 79, TRUE, TRUE) ;
  405.           IF Wildcarded (LoadfileName) AND (NOT EscPressed)
  406.              THEN GetFileFromList (LoadfileName) ;
  407.           IF NOT EscPressed
  408.              THEN
  409.                BEGIN
  410.                IF ChangesMade
  411.                   THEN
  412.                     BEGIN
  413.                     IF Answer ('File has been changed. Save?')
  414.                        THEN SaveFile (CurrentWsnr) ;
  415.                     END ;
  416.                IF NOT EscPressed
  417.                   THEN LoadFile (LoadfileName) ;
  418.                END ;
  419.           END ;
  420.     342 : { shift-F3 }
  421.           BEGIN
  422.           LoadfileName := '*.*' ;
  423.           EnterString (LoadfileName, FileHist, 'Insert file: ', 79, TRUE, TRUE) ;
  424.           IF Wildcarded (LoadfileName) AND (NOT EscPressed)
  425.              THEN GetFileFromList (LoadfileName) ;
  426.           IF NOT EscPressed
  427.              THEN InsertFile (LoadfileName, CurPos) ;
  428.           END ;
  429.     305 : { alt-N }
  430.           BEGIN
  431.           EscPressed := FALSE ;
  432.           IF ChangesMade
  433.              THEN
  434.                BEGIN
  435.                IF Answer ('File has been changed. Save?')
  436.                   THEN SaveFile (CurrentWsnr) ;
  437.                END ;
  438.           IF NOT EscPressed
  439.              THEN
  440.                BEGIN
  441.                ClearCurrentWs ;
  442.                END ;
  443.           END ;
  444.     318, 343,
  445.     275 : { F4,shift-F4,alt-R }
  446.           BEGIN
  447.           IF KeyNr <> 275
  448.              THEN
  449.                BEGIN
  450.                { if size of block <= 255: copy contents to FindString }
  451.                IF Mark <> Inactive
  452.                   THEN BEGIN
  453.                        IF Mark < CurPos.Index
  454.                           THEN BEGIN
  455.                                BlockStart := Mark ;
  456.                                BlockStop := Curpos.Index ;
  457.                                END
  458.                           ELSE BEGIN
  459.                                BlockStart := Curpos.Index ;
  460.                                BlockStop := Mark ;
  461.                                END ;
  462.                        IF (BlockStop - BlockStart) <= 255
  463.                           THEN BEGIN
  464.                                MOVE (Buffer^ [BlockStart], FindString [1],
  465.                                      BlockStop - BlockStart) ;
  466.                                FindString [0] := CHR (BlockStop - BlockStart) ;
  467.                                END ;
  468.                        END
  469.                   ELSE FindString := '' ;
  470.                { enter new search parameters }
  471.                EnterString (FindString, FindHist, 'Find: ', 255, FALSE, FALSE) ;
  472.                IF (KeyNr = 343) AND (NOT EscPressed)
  473.                   THEN EnterString (ReplaceString, ReplaceHist, 'Replace with: ',
  474.                                     255, FALSE, FALSE) ;
  475.                IF NOT EscPressed
  476.                   THEN
  477.                     BEGIN
  478.                     IF KeyNr = 318
  479.                        THEN BEGIN
  480.                             EnterString (SearchOptions, NIL,
  481.                                          'Options (I,R,W): ',
  482.                                          6, TRUE, TRUE) ;
  483.                             SearchType := Find ;
  484.                             END
  485.                        ELSE BEGIN
  486.                             EnterString (SearchOptions, NIL,
  487.                                          'Options (I,N,R,W): ',
  488.                                          6, TRUE, TRUE) ;
  489.                             SearchType := FindAndReplace ;
  490.                             END ;
  491.                     END ;
  492.                END ;
  493.           IgnoreCase := POS ('I', SearchOptions) <> 0 ;
  494.           ReverseSearch := POS ('R', SearchOptions) <> 0 ;
  495.           NoQuery := POS ('N', SearchOptions) <> 0 ;
  496.           WholeWords := POS ('W', SearchOptions) <> 0 ;
  497.           IF (NOT EscPressed) OR (KeyNr = 275)
  498.              THEN
  499.                BEGIN
  500.                { start search }
  501.                OldCurPos := CurPos ;
  502.                SearchString (FindString, CurPos) ;
  503.                IF NOT Found
  504.                   THEN
  505.                     BEGIN
  506.                     CurPos := OldCurPos ;
  507.                     ErrorMessage (15) ;
  508.                     END ;
  509.                IF Found AND (SearchType = FindAndReplace)
  510.                   THEN
  511.                     BEGIN
  512.                     { Counter will contain number of replacements made }
  513.                     Counter := 0 ;
  514.                     REPEAT
  515.                       { show found string as block (if queried replace) }
  516.                       OldMark := Mark ;
  517.                       MARK := CurPos.Index + LENGTH (FindString) ;
  518.                       IF NOT NoQuery
  519.                          THEN RedrawScreen ;
  520.                       { restore block mark }
  521.                       Mark := OldMark ;
  522.                       { determine if string must be replaced }
  523.                       IF NoQuery OR Answer ('Replace?')
  524.                          THEN
  525.                            BEGIN
  526.                            { OldCurPos will point to last replaced string }
  527.                            OldCurPos := CurPos ;
  528.                            { replace FindString with ReplaceString }
  529.                            IF LENGTH (FindString) >= LENGTH (ReplaceString)
  530.                               THEN
  531.                                 BEGIN
  532.                                 { adapt buffer size }
  533.                                 Shrink (CurPos.Index, LENGTH (FindString) -
  534.                                                      LENGTH (ReplaceString) ) ;
  535.                                 IF LENGTH (ReplaceString) > 0
  536.                                    THEN
  537.                                      BEGIN
  538.                                      { write ReplaceString }
  539.                                      MOVE (ReplaceString [1], 
  540.                                            Buffer^ [CurPos.Index],
  541.                                            LENGTH (ReplaceString) ) ;
  542.                                      IF NOT ReverseSearch
  543.                                         THEN
  544.                                           BEGIN
  545.                                           { resume search after ReplaceString }
  546.                                           SkipDown (CurPos,
  547.                                                    LENGTH (ReplaceString) - 1) ;
  548.                                           END ;
  549.                                 END ;
  550.                                 INC (Counter) ;
  551.                                 END
  552.                               ELSE
  553.                                 BEGIN
  554.                                 IF Grow (CurPos.Index,
  555.                                          LENGTH (ReplaceString) -
  556.                                          LENGTH (FindString) )
  557.                                    THEN
  558.                                      BEGIN
  559.                                      { write ReplaceString }
  560.                                      MOVE (ReplaceString [1],
  561.                                            Buffer^ [CurPos.Index],
  562.                                            LENGTH (ReplaceString) ) ;
  563.                                      IF NOT ReverseSearch
  564.                                         THEN
  565.                                           BEGIN
  566.                                           { resume search after ReplaceString }
  567.                                           SkipDown (CurPos,
  568.                                                     LENGTH (ReplaceString) ) ;
  569.                                           END ;
  570.                                      INC (Counter) ;
  571.                                      END
  572.                                    ELSE
  573.                                      { no room for replace: stop search }
  574.                                      EscPressed := TRUE ;
  575.                                 END ;
  576.                            { show replacement counter }
  577.                            Message (WordToString (Counter, 0) +
  578.                                     ' replacement(s) made') ;
  579.                            END ;
  580.                       IF NOT EscPressed
  581.                          THEN CheckEsc ;
  582.                       IF NOT EscPressed
  583.                          THEN SearchString (FindString, CurPos) ;
  584.                     UNTIL (NOT Found) OR EscPressed ;
  585.                     { return to last replaced string }
  586.                     CurPos := OldCurPos ;
  587.                     END ;
  588.                END ;
  589.           END ;
  590.     319 : { F5 }
  591.           BEGIN
  592.           MARK := CurPos.Index ;
  593.           END ;
  594.     344 : { shift-F5 }
  595.           BEGIN
  596.           MARK := Inactive ;
  597.           END ;
  598.     320 : { F6 }
  599.           BEGIN
  600.           IF CopyBlock
  601.              THEN BEGIN
  602.                   DeleteBlock ;
  603.                   END ;
  604.           END ;
  605.     345 : { shift-F6 }
  606.           BEGIN
  607.           DeleteBlock ;
  608.           END ;
  609.     321 : { F7 }
  610.           BEGIN
  611.           IF CopyBlock
  612.              THEN BEGIN
  613.                   MARK := Inactive ;
  614.                   Message ('Block copied into paste buffer') ;
  615.                   END ;
  616.           END ;
  617.     346 : { shift-F7 }
  618.           BEGIN
  619.           IF MARK = Inactive
  620.              THEN ErrorMessage (5)
  621.              ELSE BEGIN
  622.                   IF MARK < CurPos.Index
  623.                      THEN BEGIN
  624.                           BlockStart := MARK ;
  625.                           BlockStop := CurPos.Index ;
  626.                           END
  627.                      ELSE BEGIN
  628.                           BlockStart := CurPos.Index ;
  629.                           BlockStop := MARK ;
  630.                           END ;
  631.                   Counter := BlockStart ;
  632.                   WHILE (Buffer^ [Counter] =
  633.                          PasteBuffer^ [Counter - BlockStart + 1]) AND
  634.                         (Counter < BlockStop) DO
  635.                         INC (Counter) ;
  636.                   IF (Counter >= BlockStop) AND
  637.                      ( (BlockStop - BlockStart) = PasteBufferSize)
  638.                      THEN Message ('Block is equal to paste buffer')
  639.                      ELSE Message ('Block differs from paste buffer at' +
  640.                                    ' character '+
  641.                                    WordToString(Counter-BlockStart+1,0)) ;
  642.                   END ;
  643.           END ;
  644.     322 : { F8 }
  645.           BEGIN
  646.           IF InsertBlock THEN
  647.              SkipDown (Curpos, PasteBufferSize) ;
  648.           END ;
  649.     347 : { shift-F8 }
  650.           BEGIN
  651.           IF MARK = Inactive
  652.              THEN ErrorMessage (5)
  653.              ELSE BEGIN
  654.                   IF MARK < CurPos.Index
  655.                      THEN PrintBlock (Buffer, MARK, CurPos.Index - 1)
  656.                      ELSE PrintBlock (Buffer, CurPos.Index, MARK - 1) ;
  657.                   END ;
  658.           END ;
  659.     281 : { alt-P }
  660.           BEGIN
  661.           IF Answer ('Print entire file buffer?')
  662.              THEN PrintBlock (Buffer, 1, BufferSize - 1) ;
  663.           END ;
  664.     323 : { F9 }
  665.           BEGIN
  666.           Workspace [CurrentWsnr] := CurrentWs ;
  667.           IF CurrentWsnr = NrOfWorkspaces
  668.              THEN CurrentWsnr := 1
  669.              ELSE INC (CurrentWsnr) ;
  670.           CurrentWs := Workspace [CurrentWsnr] ;
  671.           END ;
  672.     348 : { shift-F9 }
  673.           BEGIN
  674.           Workspace [CurrentWsnr] := CurrentWs ;
  675.           IF CurrentWsnr = 1
  676.              THEN CurrentWsnr := NrOfWorkspaces
  677.              ELSE DEC (CurrentWsnr) ;
  678.           CurrentWs := Workspace [CurrentWsnr] ;
  679.           END ;
  680.     324 : { F10 }
  681.           BEGIN
  682.           { restore screen settings }
  683.           TextAttr := OrigTextAttr ;
  684.           SetCursor (OrigCursorType) ;
  685.           CLRSCR ;
  686.           WRITELN ('Type EXIT to return to AE ...') ;
  687.           SwapVectors ;
  688.           EXEC (GetEnv ('COMSPEC'), '') ;
  689.           SwapVectors ;
  690.           IF DosError <> 0
  691.              THEN ErrorMessage (14) ;
  692.           { reset screen settings }
  693.           TextAttr := ScreenColorArray [Config.Setup.ScreenColors].NormAttr ;
  694.           SetCursor (Config.Setup.CursorType) ;
  695.           END ;
  696.     274 : { alt-E }
  697.           BEGIN
  698.           WRITE (Lst, FF) ;
  699.           CheckDiskError ;
  700.           END ;
  701.     286 : { alt-A }
  702.           BEGIN
  703.           Workspace [CurrentWsnr] := CurrentWs ;
  704.           CurrentWsnr := 1 ;
  705.           CurrentWs := Workspace [CurrentWsnr] ;
  706.           END ;
  707.     376..
  708.     385 : { alt-1 .. alt-0 }
  709.           BEGIN
  710.           MacroNumber := KeyNr - 375 ;
  711.           IF MacroDefining = MacroNumber
  712.              THEN BEGIN
  713.                   DEC (Config.Macro.LENGTH [MacroDefining]) ;
  714.                   ErrorMessage (9) ;
  715.                   END
  716.              ELSE BEGIN
  717.                   IF Config.Macro.LENGTH [MacroNumber] > 0
  718.                      THEN BEGIN
  719.                           IF MacroStackpointer = MacroStackDepth
  720.                              THEN BEGIN
  721.                                   MacroStackpointer := Inactive ;
  722.                                   ErrorMessage (10) ;
  723.                                   END
  724.                              ELSE BEGIN
  725.                                   { push macro onto MacroStack }
  726.                                   INC (MacroStackpointer) ;
  727.                                   WITH MacroStack [MacroStackpointer] DO
  728.                                        BEGIN
  729.                                        Macronr := MacroNumber ;
  730.                                        Index := 1 ;
  731.                                        END ;
  732.                                   END ;
  733.                           END ;
  734.                   END ;
  735.           END ;
  736.     288 : { alt-D }
  737.           BEGIN
  738.           IF MacroDefining = Inactive
  739.              THEN BEGIN
  740.                   { Start define mode }
  741.                   MacroNumber := 1 ;
  742.                   EnterWord (MacroNumber,
  743.                              'Define keyboard Macro nr. (1-10): ', 1, 10) ;
  744.                   IF NOT EscPressed
  745.                      THEN BEGIN
  746.                           { reset old macro }
  747.                           Config.Macro.LENGTH [MacroNumber] := 0 ;
  748.                           MacroDefining := MacroNumber ;
  749.                           END ;
  750.                   END
  751.              ELSE { end define mode }
  752.                   MacroDefining := Inactive ;
  753.           END ;
  754.     289 : { alt-F }
  755.           BEGIN
  756.           IF Config.Setup.WordWrapLength = Inactive
  757.              THEN ErrorMessage (11)
  758.              ELSE BEGIN
  759.                   FormatParagraph (CurPos) ;
  760.                   WordDown (CurPos) ;
  761.                   END ;
  762.           END ;
  763. 292, 302 : { alt-J, alt-C }
  764.           BEGIN
  765.           IF Config.Setup.WordWrapLength = Inactive
  766.              THEN ErrorMessage (11)
  767.              ELSE BEGIN
  768.                   { measure line length }
  769.                   EndOfLine (CurPos) ;
  770.                   { remove trailing spaces }
  771.                   Counter := 1 ;
  772.                   WHILE (Buffer^ [CurPos.Index - Counter] = ' ') AND
  773.                         (Counter < CurPos.Colnr) DO
  774.                         INC (Counter) ;
  775.                   DEC (CurPos.Index, Counter - 1) ;
  776.                   DEC (CurPos.Colnr, Counter - 1) ;
  777.                   Shrink (CurPos.Index, Counter - 1) ;
  778.                   LineLength := CurPos.Colnr - 1 ;
  779.                   { remove leading spaces }
  780.                   Home (CurPos) ;
  781.                   Counter := 0 ;
  782.                   WHILE (Buffer^ [CurPos.Index + Counter] = ' ') AND
  783.                         (Counter <= LineLength) DO
  784.                         INC (Counter) ;
  785.                   Shrink (CurPos.Index, Counter) ;
  786.                   DEC (LineLength, Counter) ;
  787.                   NewSpaces := (Config.Setup.WordWrapLength - LineLength) ;
  788.                   IF KeyNr = 302
  789.                      THEN NewSpaces := NewSpaces DIV 2 ;
  790.                   IF NewSpaces > 0
  791.                      THEN InsertSpaces (CurPos, NewSpaces) ;
  792.                   END
  793.           END ;
  794.     306 : { alt-M }
  795.           BEGIN
  796.           OldCurPos := CurPos ;
  797.           Found := TRUE ;
  798.           CASE Buffer^ [CurPos.Index] OF
  799.                '{' : MatchBracketsDown ('{', '}', CurPos) ;
  800.                '}' : MatchBracketsUp ('{', '}', CurPos) ;
  801.                '(' : MatchBracketsDown ('(', ')', CurPos) ;
  802.                ')' : MatchBracketsUp ('(', ')', CurPos) ;
  803.                '[' : MatchBracketsDown ('[', ']', CurPos) ;
  804.                ']' : MatchBracketsUp ('[', ']', CurPos) ;
  805.                '<' : MatchBracketsDown ('<', '>', CurPos) ;
  806.                '>' : MatchBracketsUp ('<', '>', CurPos) ;
  807.                ELSE Message ('Cursor must be on bracket ({[<>]})') ;
  808.                END ; { of case }
  809.           IF NOT Found
  810.              THEN BEGIN
  811.                   Message ('No matching bracket found') ;
  812.                   CurPos := OldCurPos ;
  813.                   END ;
  814.           END ;
  815.     287 : { alt-S }
  816.           BEGIN
  817.           IF PosStackpointer = PosStackDepth
  818.              THEN ErrorMessage (12)
  819.              ELSE BEGIN
  820.                   INC (PosStackpointer) ;
  821.                   PosStack [PosStackpointer] := CurPos.Index ;
  822.                   END ;
  823.            END ;
  824.     290 : { alt-G }
  825.           BEGIN
  826.           IF PosStackpointer = Inactive
  827.              THEN ErrorMessage (13)
  828.              ELSE BEGIN
  829.                   IF CurPos.Index < PosStack [PosStackpointer]
  830.                      THEN SkipDown (CurPos,
  831.                                     PosStack [PosStackpointer] - CurPos.Index)
  832.                      ELSE SkipUp (CurPos,
  833.                                   CurPos.Index - PosStack [PosStackpointer]) ;
  834.                   DEC (PosStackpointer) ;
  835.                   END ;
  836.           END ;
  837.     276, 278 : { alt-T, alt-U }
  838.           BEGIN
  839.           IF MARK = Inactive
  840.              THEN BEGIN
  841.                   IF KeyNr = 276
  842.                      THEN BEGIN
  843.                           IF Buffer^ [CurPos.Index] IN ['A'..'Z', 'a'..'z']
  844.                              THEN BEGIN
  845.                                   Buffer^ [CurPos.Index] :=
  846.                                      CHR (ORD (Buffer^ [CurPos.Index]) XOR $20) ;
  847.                                   ChangesMade := TRUE ;
  848.                                   END ;
  849.                           SkipDown (CurPos, 1) ;
  850.                           END
  851.                      ELSE BEGIN
  852.                           IF Buffer^ [CurPos.Index] IN ['a'..'z']
  853.                              THEN BEGIN
  854.                                   Buffer^ [CurPos.Index] :=
  855.                                      UPCASE (Buffer^ [CurPos.Index]) ;
  856.                                   ChangesMade := TRUE ;
  857.                                   END ;
  858.                           SkipDown (CurPos, 1) ;
  859.                           END
  860.                   END
  861.              ELSE BEGIN
  862.                   IF MARK < CurPos.Index
  863.                      THEN BEGIN
  864.                           BlockStart := MARK ;
  865.                           BlockStop := CurPos.Index ;
  866.                           END
  867.                      ELSE BEGIN
  868.                           BlockStart := CurPos.Index  ;
  869.                           BlockStop := MARK ;
  870.                           END ;
  871.                   IF KeyNr = 276
  872.                      THEN BEGIN
  873.                           { toggle case }
  874.                           FOR Counter := BlockStart TO (BlockStop - 1) DO
  875.                               IF Buffer^ [Counter] IN ['A'..'Z', 'a'..'z']
  876.                                  THEN BEGIN
  877.                                       Buffer^ [Counter] :=
  878.                                          CHR (ORD (Buffer^ [Counter]) XOR $20) ;
  879.                                       ChangesMade := TRUE ;
  880.                                       END ;
  881.                           END
  882.                      ELSE BEGIN
  883.                           { convert to upper case }
  884.                           FOR Counter := BlockStart TO (BlockStop - 1) DO
  885.                               IF Buffer^ [Counter] IN ['a'..'z']
  886.                                  THEN BEGIN
  887.                                       Buffer^ [Counter] :=
  888.                                          UPCASE (Buffer^ [Counter]) ;
  889.                                       ChangesMade := TRUE ;
  890.                                       END ;
  891.                           END ;
  892.                   END ;
  893.           END ;
  894.  0..255 : { character-keys }
  895.           BEGIN
  896.           IF KeyNr = 26
  897.              THEN Message ('Warning: Inserting end-of-file character') ;
  898.           IF (NOT Config.Setup.Insertmode) AND
  899.              (NOT ( (Buffer^ [CurPos.Index] = CR) AND
  900.                    (Buffer^ [CurPos.Index + 1] = LF) ) ) AND
  901.              (Buffer^ [CurPos.Index] <> LF) AND
  902.              (CurPos.Index < Buffersize)
  903.              THEN BEGIN
  904.                   { if in overwrite mode and not at }
  905.                   { end of line or buffer: overwrite character }
  906.                   Buffer^ [CurPos.Index] := CHR (KeyNr) ;
  907.                   INC (CurPos.Index) ;
  908.                   IF KeyNr = 13
  909.                      THEN BEGIN
  910.                           INC (Curpos.Linenr) ;
  911.                           CurPos.Colnr := 1 ;
  912.                           END
  913.                      ELSE INC (CurPos.Colnr) ;
  914.                   ChangesMade := TRUE ;
  915.                   END
  916.              ELSE BEGIN
  917.                   IF Grow (CurPos.Index, 1)
  918.                      THEN BEGIN
  919.                           { insert character }
  920.                           Buffer^ [CurPos.Index] := CHR (KeyNr) ;
  921.                           INC (CurPos.Index) ;
  922.                           IF KeyNr = 13
  923.                              THEN BEGIN
  924.                                   INC (Curpos.Linenr) ;
  925.                                   CurPos.Colnr := 1 ;
  926.                                   END
  927.                              ELSE INC (CurPos.Colnr) ;
  928.                           END ;
  929.                   END ;
  930.           { check if line must be broken }
  931.           IF (Config.Setup.WordWrapLength <> Inactive)
  932.              THEN BEGIN
  933.                   IF (CurPos.Colnr > Config.Setup.WordWrapLength)
  934.                      THEN BEGIN
  935.                           OldCurPos := CurPos ;
  936.                           { find position for line break }
  937.                           REPEAT WordUp (CurPos) ;
  938.                           UNTIL (CurPos.Colnr <= Config.Setup.WordWrapLength)
  939.                                 OR (CurPos.Linenr < OldCurPos.Linenr) ;
  940.                           { use NextPos to store index value of CurPos }
  941.                           NextPos := CurPos ;
  942.                           IF (CurPos.Linenr = OldCurPos.Linenr)
  943.                              THEN BEGIN
  944.                                   { remove spaces at end of line }
  945.                                   Counter := 1 ;
  946.                                   WHILE (Buffer^[Curpos.Index-Counter] = ' ')
  947.                                         AND (Counter < Curpos.Colnr) DO
  948.                                         INC (Counter) ;
  949.                                   { only break line if not at left margin }
  950.                                   IF Counter < CurPos.Colnr
  951.                                      THEN BEGIN
  952.                                           DEC (Counter) ;
  953.                                           Shrink (CurPos.Index-Counter,Counter) ;
  954.                                           DEC (CurPos.Index,Counter) ;
  955.                                           DEC (CurPos.Colnr,Counter) ;
  956.                                           InsertCRLF (CurPos) ;
  957.                                           END ;
  958.                                   END ;
  959.                           { restore position }
  960.                           SkipDown (CurPos,OldCurPos.Index - NextPos.Index) ;
  961.                           FirstScreenCol := 1 ;
  962.                           END ;
  963.                   END ;
  964.           END ;
  965. 266, 269 : { Enter,^Enter }
  966.           BEGIN
  967.           InsertCRLF (CurPos) ;
  968.           END ;
  969.     265 : { Tab }
  970.           BEGIN
  971.           IF Config.Setup.TabSpacing = 0
  972.              THEN BEGIN
  973.                   { find nearest beginning of word in previous line }
  974.                   OldCurPos := CurPos ;
  975.                   LineUp (Curpos) ;
  976.                   WHILE (CurPos.Colnr <= OldCurPos.Colnr) AND
  977.                         (CurPos.Linenr < OldCurpos.Linenr) DO
  978.                         WordDown (CurPos) ;
  979.                   IF CurPos.Linenr < OldCurpos.Linenr
  980.                      THEN TabSteps := Curpos.Colnr - OldCurpos.Colnr
  981.                      ELSE TabSteps := 0 ;
  982.                   CurPos := OldCurPos ;
  983.                   END
  984.              ELSE BEGIN
  985.                   { fixed-distance tabs }
  986.                   TabSteps := Config.Setup.TabSpacing -
  987.                               ( (CurPos.Colnr - 1) MOD Config.Setup.TabSpacing) ;
  988.                   END ;
  989.           IF (NOT Config.Setup.Insertmode)
  990.              THEN BEGIN
  991.                   { overwrite mode: skip tabsteps until eoln or eof }
  992.                   WHILE (TabSteps > 0) AND
  993.                         (Buffer^ [CurPos.Index] <> LF) AND
  994.                         (CurPos.Index < Buffersize) DO
  995.                         BEGIN
  996.                         INC (CurPos.Index) ;
  997.                         INC (CurPos.Colnr) ;
  998.                         DEC (TabSteps) ;
  999.                         END ;
  1000.                   { rest will be inserted as spaces }
  1001.                   END ; { of if }
  1002.           IF TabSteps > 0
  1003.              THEN InsertSpaces (CurPos, TabSteps) ;
  1004.           END ;
  1005.     271 : { shift-Tab }
  1006.           BEGIN
  1007.           IF Config.Setup.TabSpacing = 0
  1008.              THEN BEGIN
  1009.                   OldCurPos := CurPos ;
  1010.                   LineUp (CurPos) ;
  1011.                   EndOfLine (CurPos) ;
  1012.                   IF CurPos.ColNr > OldCurPos.Colnr
  1013.                      THEN BEGIN
  1014.                           DEC (CurPos.Index, CurPos.Colnr - OldCurPos.Colnr) ;
  1015.                           CurPos.Colnr := OldCurpos.Colnr ;
  1016.                           END ;
  1017.                   WordUp (CurPos) ;
  1018.                   IF CurPos.Linenr = (OldCurpos.Linenr - 1)
  1019.                      THEN TabSteps := OldCurpos.Colnr - Curpos.Colnr
  1020.                      ELSE TabSteps := OldCurPos.Colnr - 1 ;
  1021.                   CurPos := OldCurPos ;
  1022.                   END
  1023.              ELSE IF CurPos.Colnr > Config.Setup.TabSpacing
  1024.                      THEN BEGIN
  1025.                           TabSteps := (CurPos.Colnr - 1) MOD
  1026.                                       Config.Setup.TabSpacing ;
  1027.                           IF TabSteps = 0
  1028.                              THEN TabSteps := Config.Setup.TabSpacing ;
  1029.                           END
  1030.                      ELSE TabSteps := CurPos.Colnr - 1 ;
  1031.           DEC (CurPos.Index, TabSteps) ;
  1032.           DEC (CurPos.Colnr, TabSteps) ;
  1033.           END ;
  1034.     338 : { Ins }
  1035.           BEGIN
  1036.           Config.Setup.Insertmode := NOT Config.Setup.Insertmode ;
  1037.           END ;
  1038.     339 : { Del }
  1039.           BEGIN
  1040.           IF CurPos.Index < Buffersize
  1041.              THEN BEGIN
  1042.                   IF (Buffer^ [CurPos.Index] = CR) AND
  1043.                      (Buffer^ [CurPos.Index + 1] = LF)
  1044.                      THEN Shrink (CurPos.Index, 2)
  1045.                      ELSE Shrink (CurPos.Index, 1) ;
  1046.                   END ;
  1047.           END ;
  1048.     264 : { Backspace }
  1049.           BEGIN
  1050.           IF CurPos.Index > 1
  1051.              THEN BEGIN
  1052.                   IF (Buffer^ [CurPos.Index - 1] = LF) AND
  1053.                      (Buffer^ [CurPos.Index - 2] = CR)
  1054.                      THEN BEGIN
  1055.                           SkipUp (CurPos, 2) ;
  1056.                           Shrink (CurPos.Index, 2) ;
  1057.                           END
  1058.                      ELSE BEGIN
  1059.                           SkipUp (CurPos, 1) ;
  1060.                           Shrink (CurPos.Index, 1) ;
  1061.                           END ;
  1062.                   END ;
  1063.           END ;
  1064.     273 : { alt-W }
  1065.           BEGIN
  1066.           NextPos := CurPos ;
  1067.           { if at end of line: skip line separator }
  1068.           IF (Buffer^ [NextPos.Index] = LF) OR
  1069.              ((Buffer^ [NextPos.Index] = CR) AND
  1070.               (Buffer^ [NextPos.Index+1] = LF))
  1071.              THEN LineDown (NextPos)
  1072.              ELSE BEGIN
  1073.                   { skip to end of word }
  1074.                   WHILE (Buffer^ [NextPos.Index] IN
  1075.                          ['0'..'9','A'..'Z','a'..'z']) AND
  1076.                         (NextPos.Index < BufferSize) DO
  1077.                         BEGIN Inc (NextPos.Index) ;
  1078.                               Inc (NextPos.Colnr) ;
  1079.                         END ;
  1080.                   IF (Buffer^ [NextPos.Index] <> LF) AND
  1081.                      (NOT ((Buffer^ [NextPos.Index] = CR) AND
  1082.                            (Buffer^ [NextPos.Index+1] = LF)))
  1083.                      THEN SkipDown (Nextpos,1) ;
  1084.                   { skip all subsequent spaces }
  1085.                   WHILE (Buffer^ [NextPos.Index] = ' ') AND
  1086.                         (NextPos.Index < BufferSize)
  1087.                         DO BEGIN
  1088.                            INC (NextPos.Index) ;
  1089.                            INC (NextPos.Colnr) ;
  1090.                            END ;
  1091.                   END ;
  1092.           Shrink (CurPos.Index, NextPos.Index - CurPos.Index) ;
  1093.           END ;
  1094.     294 : { alt-L }
  1095.           BEGIN
  1096.           Home (CurPos) ;
  1097.           NextPos := CurPos ;
  1098.           LineDown (NextPos) ;
  1099.           Shrink (CurPos.Index, NextPos.Index - CurPos.Index) ;
  1100.           END ;
  1101.     301 : { alt-X }
  1102.           BEGIN
  1103.           Workspace [CurrentWsnr] := CurrentWs ;
  1104.           Counter := 1 ;
  1105.           EscPressed := FALSE ;
  1106.           WHILE (Counter <= NrOfWorkspaces) AND (NOT EscPressed) DO
  1107.                 BEGIN
  1108.                 WITH Workspace [Counter] DO
  1109.                      IF ChangesMade
  1110.                         THEN BEGIN
  1111.                              IF Config.Setup.SaveOnExit
  1112.                                 THEN SaveFile (Counter)
  1113.                                 ELSE IF Answer ('File in ' + CHR (64 + Counter) +
  1114.                                                ' has been changed. Save?')
  1115.                                         THEN BEGIN
  1116.                                              SaveFile (Counter) ;
  1117.                                              { if save unsuccessful: }
  1118.                                              { stop exit procedure }
  1119.                                              IF ChangesMade
  1120.                                                 THEN EscPressed := TRUE ;
  1121.                                              END ;
  1122.                              END ;
  1123.                 INC (Counter) ;
  1124.                 END ; { of while }
  1125.           { do not exit from program if Escape was pressed }
  1126.           ProgramFinished := NOT EscPressed ;
  1127.           END ;
  1128.     272 : { alt-Q }
  1129.           BEGIN
  1130.           Workspace [CurrentWsnr] := CurrentWs ;
  1131.           DisplayInfo ;
  1132.           END ;
  1133.     300 : { alt-Z }
  1134.           BEGIN
  1135.           Message ('Another Editor by Dick Alstein.  Version '
  1136.                    + AEVersionNr + ', ' + AEVersionDate + '.') ;
  1137.           END ;
  1138.     283 : { Escape }
  1139.           BEGIN
  1140.           MARK := Inactive ;
  1141.           END ;
  1142.     ELSE  BEGIN
  1143.           WarningBeep ;
  1144.           Message ('This key has no function') ;
  1145.           END ;
  1146.     END  ; { of case }
  1147.   CASE KeyNr OF
  1148.     0..255, 264, 265, 266, 269, 273, 320, 322, 339, 345 :
  1149.     { char-keys, Backspace, Tab, Enter, ^Enter, Alt-W, F6, F8, Del, Shift-F6 }
  1150.                       IF Config.Setup.AutoWrap
  1151.                          THEN BEGIN
  1152.                               { do auto-wrap }
  1153.                               OldCurPos := CurPos ;
  1154.                               FormatParagraph (CurPos) ;
  1155.                               CurPos := OldCurpos ;
  1156.                               END ;
  1157.     END ;
  1158.   CASE KeyNr OF
  1159.     328, 336, 329, 337, 375, 373 : { up,down,PgUp,PgDn,^Home, ^End }
  1160.                       BEGIN
  1161.                       { when moving vertically through the buffer: }
  1162.                       { try to make Colnr equal to VirtualColnr }
  1163.                       { (i.e. the value that it "should" have) }
  1164.                       WHILE (CurPos.Colnr < VirtualColnr) AND
  1165.                             (Buffer^ [CurPos.Index] <> LF) AND
  1166.                             (CurPos.Index < BufferSize) DO
  1167.                             BEGIN
  1168.                             INC (CurPos.Index) ;
  1169.                             INC (CurPos.Colnr) ;
  1170.                             END ;
  1171.                       IF (Buffer^ [CurPos.Index] = LF) AND
  1172.                          (Buffer^ [CurPos.Index - 1] = CR)
  1173.                          THEN BEGIN
  1174.                               DEC (CurPos.Index) ;
  1175.                               DEC (CurPos.Colnr) ;
  1176.                               END ;
  1177.                       END ;
  1178.     ELSE              { all other keys }
  1179.                       VirtualColnr := Curpos.Colnr ;
  1180.     END  ; { of case }
  1181.   END ; { of with }
  1182. END ; { of procedure }
  1183.  
  1184. {-----------------------------------------------------------------------------}
  1185.  
  1186. BEGIN
  1187. END.
  1188.