home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 9 / CD_ASCQ_09_1193.iso / news / 557 / anedit / ae2.pas < prev    next >
Pascal/Delphi Source File  |  1992-09-07  |  18KB  |  480 lines

  1. UNIT AE2 ;
  2.  
  3. {$R-}
  4. {$B-}
  5. {$I-}
  6. {$S+}
  7. {$V-}
  8.  
  9. {-----------------------------------------------------------------------------}
  10. { This unit contains all movement procedures.                                 }
  11. { All procedures operate on the current workspace (CurrentWs),                }
  12. { unless specified otherwise.                                                 }
  13. {-----------------------------------------------------------------------------}
  14.  
  15. INTERFACE
  16.  
  17. USES Crt, Dos, AE0, AE1 ;
  18.  
  19. PROCEDURE Home (VAR P : Position) ;
  20. PROCEDURE EndOfLine (VAR P : Position) ;
  21. PROCEDURE CalculateColnr (VAR P : position) ;
  22. PROCEDURE SkipDown (VAR P : Position ; Distance : WORD) ;
  23. PROCEDURE SkipUp (VAR P : Position ; Distance : WORD) ;
  24. PROCEDURE WordDown (VAR P : Position) ;
  25. PROCEDURE WordUp (VAR P : Position) ;
  26. PROCEDURE LineDown (VAR P : Position) ;
  27. PROCEDURE LineUp (VAR P : Position) ;
  28. PROCEDURE SearchUp (Target : STRING ; VAR P : Position ; LimitIndex : WORD) ;
  29. PROCEDURE SearchDown (Target : STRING ; VAR P : Position ; LimitIndex : WORD) ;
  30. PROCEDURE SearchString (Target : STRING ; VAR P : Position) ;
  31. PROCEDURE MatchBracketsDown (OpenBracket, CloseBracket : CHAR ; VAR P : Position) ;
  32. PROCEDURE MatchBracketsUp (OpenBracket, CloseBracket : CHAR ; VAR P : Position) ;
  33.  
  34. IMPLEMENTATION
  35.  
  36. {-----------------------------------------------------------------------------}
  37. { Sets P to the first column of the line it is pointing to                    }
  38. {-----------------------------------------------------------------------------}
  39.  
  40. PROCEDURE Home (VAR P : Position) ;
  41.  
  42. BEGIN
  43. DEC (P.Index, P.Colnr - 1) ;
  44. P.Colnr := 1 ;
  45. END ;
  46.  
  47. {-----------------------------------------------------------------------------}
  48. { Sets P to the last column of the current line (line separator or            }
  49. { end of file)                                                                }
  50. {-----------------------------------------------------------------------------}
  51.  
  52. PROCEDURE EndOfLine (VAR P : Position) ;
  53.  
  54. BEGIN
  55. WITH CurrentWs DO
  56.      BEGIN
  57.      WHILE (Buffer^ [P.Index] <> LF) AND
  58.            (P.Index < Buffersize) DO
  59.            BEGIN
  60.            INC (P.Index) ;
  61.            INC (P.Colnr) ;
  62.            END ;
  63.      IF (Buffer^ [P.Index - 1] = CR) AND
  64.         (Buffer^ [P.Index] = LF)
  65.         THEN BEGIN
  66.              DEC (P.Index) ;
  67.              DEC (P.Colnr) ;
  68.              END ;
  69.      END ; { of with }
  70. END ;
  71.  
  72. {-----------------------------------------------------------------------------}
  73. { Re-calculates the column number by searching for a previous line feed       }
  74. {-----------------------------------------------------------------------------}
  75.  
  76. PROCEDURE CalculateColnr (VAR P : position) ;
  77.  
  78. BEGIN
  79. WITH CurrentWs DO
  80.      BEGIN
  81.      IF P.Linenr = 1
  82.         THEN P.Colnr := P.Index
  83.         ELSE BEGIN
  84.              P.Colnr := 1 ;
  85.              WHILE (Buffer^ [P.Index - P.Colnr] <> LF) DO INC (P.Colnr) ;
  86.              END ;
  87.      END ;
  88. END ;
  89.  
  90. {-----------------------------------------------------------------------------}
  91. { Skips P <Distance> positions downward, adjusting line and column number.    }
  92. { If the end of the buffer is reached, the procedure stops.                   }
  93. {-----------------------------------------------------------------------------}
  94.  
  95. PROCEDURE SkipDown (VAR P : Position ; Distance : WORD) ;
  96.  
  97. VAR Counter : WORD ;
  98.  
  99. BEGIN
  100. WITH CurrentWs DO
  101.      BEGIN
  102.      IF (P.Index + Distance) > BufferSize
  103.         THEN Distance := BufferSize - P.Index ;
  104.      FOR Counter := 1 TO Distance DO
  105.          BEGIN
  106.          IF Buffer^ [P.Index] = LF
  107.             THEN INC (P.Linenr) ;
  108.          INC (P.Index) ;
  109.          END ;
  110.      CalculateColnr (P) ;
  111.      END ;
  112. END ;
  113.  
  114. {-----------------------------------------------------------------------------}
  115. { Skips P <Distance> positions upward, adjusting line and column number.      }
  116. { If the start of the buffer is reached, the procedure stops.                 }
  117. {-----------------------------------------------------------------------------}
  118.  
  119. PROCEDURE SkipUp (VAR P : Position ; Distance : WORD) ;
  120.  
  121. VAR Counter : WORD ;
  122.  
  123. BEGIN
  124. WITH CurrentWs DO
  125.      BEGIN
  126.      IF Distance < P.Colnr
  127.         THEN BEGIN
  128.              { P will remain within current line }
  129.              DEC (P.Colnr, Distance) ;
  130.              DEC (P.Index, Distance) ;
  131.              END
  132.         ELSE BEGIN
  133.              IF P.Index <= Distance
  134.                 THEN BEGIN
  135.                      { go to start of buffer }
  136.                      P.Index := 1 ;
  137.                      P.Linenr := 1 ;
  138.                      END 
  139.                 ELSE FOR Counter := 1 TO Distance DO
  140.                          BEGIN
  141.                          DEC (P.Index) ;
  142.                          IF Buffer^ [P.Index] = LF
  143.                             THEN DEC (P.Linenr) ;
  144.                          END ;
  145.              CalculateColnr (P) ;
  146.              END ;
  147.      END ;
  148. END ;
  149.  
  150. {-----------------------------------------------------------------------------}
  151. { Skips P downward until the beginning of the next word in the text.          }
  152. {-----------------------------------------------------------------------------}
  153.  
  154. PROCEDURE WordDown (VAR P : Position) ;
  155.  
  156. BEGIN
  157. WITH CurrentWs DO
  158.      BEGIN
  159.      WHILE NOT ( (Buffer^ [P.Index] IN WordDelimiters) OR
  160.                 (P.Index = BufferSize) ) DO
  161.            BEGIN
  162.            INC (P.Colnr) ;
  163.            INC (P.Index) ;
  164.            END ;
  165.      WHILE (Buffer^ [P.Index] IN WordDelimiters) AND
  166.            (P.Index < BufferSize) DO
  167.            BEGIN
  168.            IF Buffer^ [P.Index] = LF
  169.               THEN BEGIN
  170.                    INC (P.Linenr) ;
  171.                    P.Colnr := 1 ;
  172.                    END
  173.               ELSE IF NOT ( (Buffer^ [P.Index] = CR) AND
  174.                            (Buffer^ [P.Index + 1] = LF) )
  175.                       THEN INC (P.Colnr) ;
  176.            INC (P.Index) ;
  177.            END ;
  178.      END ;
  179. END ;
  180.  
  181. {-----------------------------------------------------------------------------}
  182. { Skips P upward until the beginning of the previous word in the text.        }
  183. {-----------------------------------------------------------------------------}
  184.  
  185. PROCEDURE WordUp (VAR P : Position) ;
  186.  
  187. BEGIN
  188. WITH CurrentWs DO
  189.      BEGIN
  190.      IF P.Index > 1
  191.         THEN BEGIN
  192.              REPEAT DEC (P.Index) ;
  193.                     IF Buffer^ [P.Index] = LF
  194.                        THEN DEC (P.Linenr) ;
  195.              UNTIL ( (NOT (Buffer^ [P.Index] IN WordDelimiters) ) OR
  196.                     (P.Index = 1) ) ;
  197.              WHILE ( (NOT (Buffer^ [P.Index] IN WordDelimiters) ) AND
  198.                     (P.Index > 0) ) DO
  199.                    BEGIN
  200.                    DEC (P.Index) ;
  201.                    END ;
  202.              INC (P.Index) ;
  203.              CalculateColnr (P) ;
  204.              END ;
  205.      END ;
  206. END ;
  207.  
  208. {-----------------------------------------------------------------------------}
  209. { Skips P downward to the first column of the next line.                      }
  210. { If the end of the buffer is reached, the procedure stops.                   }
  211. {-----------------------------------------------------------------------------}
  212.  
  213. PROCEDURE LineDown (VAR P : Position) ;
  214.  
  215. VAR StartIndex : WORD ;
  216.  
  217. BEGIN
  218. StartIndex := P.Index ;
  219. WITH CurrentWs DO
  220.      BEGIN
  221.      WHILE (Buffer^ [P.Index] <> LF) AND (P.Index < BufferSize) DO
  222.            INC (P.Index) ;
  223.      IF (Buffer^ [P.Index] = LF)
  224.         THEN BEGIN
  225.              INC (P.Index) ;
  226.              P.Colnr := 1 ;
  227.              INC (P.Linenr) ;
  228.              END
  229.         ELSE INC (P.Colnr, P.Index - StartIndex) ;
  230.      END ;
  231. END ;
  232.  
  233. {-----------------------------------------------------------------------------}
  234. { Skips P upward to the first column of the previous line.                    }
  235. { If the start of the buffer is reached, the procedure stops.                 }
  236. {-----------------------------------------------------------------------------}
  237.  
  238. PROCEDURE LineUp (VAR P : Position) ;
  239.  
  240. BEGIN
  241. IF P.Linenr <= 2
  242.    THEN BEGIN
  243.         P.Index := 1 ;
  244.         P.Linenr := 1 ;
  245.         END
  246.    ELSE WITH CurrentWs DO
  247.              BEGIN
  248.              { go to line feed before start of current line }
  249.              DEC (P.Index, P.Colnr) ;
  250.              { find start of line }
  251.              WHILE (Buffer^ [P.Index - 1] <> LF) DO
  252.                    DEC (P.Index) ;
  253.              DEC (P.Linenr) ;
  254.              END ;
  255. P.Colnr := 1 ;
  256. END ;
  257.  
  258. {-----------------------------------------------------------------------------}
  259. { Searches downward for the string <Target>. On exit, P points to the first   }
  260. { character of the string in the text buffer, if the string is found before   }
  261. { index <LimitIndex> is reached. Otherwise, P will point to <LimitIndex>.     }
  262. { The value of global variable Found will be set accordingly.                 }
  263. {-----------------------------------------------------------------------------}
  264.  
  265. PROCEDURE SearchDown (Target : STRING ; VAR P : Position ; LimitIndex : WORD) ;
  266.  
  267. VAR Counter : BYTE ;
  268.  
  269. BEGIN
  270. Found := FALSE ;
  271. WITH CurrentWs DO
  272.      BEGIN
  273.      IF IgnoreCase
  274.         THEN BEGIN
  275.              { case-insensitive search }
  276.              Target := UpperCase (Target) ;
  277.              WHILE (NOT Found) AND (P.Index <= LimitIndex) DO
  278.                    BEGIN
  279.                    { search text for first character of Target }
  280.                    REPEAT IF Buffer^ [P.Index] = LF
  281.                              THEN INC (P.Linenr) ;
  282.                           INC (P.Index) ;
  283.                    UNTIL (UPCASE (Buffer^ [P.Index]) = Target [1]) OR
  284.                          (P.Index > LimitIndex) ;
  285.                    Counter := 2 ;
  286.                    { check if following characters are equal to Target }
  287.                    WHILE (UPCASE (Buffer^ [P.Index + Counter - 1]) = Target [Counter])
  288.                          AND (Counter <= LENGTH (Target) ) DO
  289.                          INC (Counter) ;
  290.                    Found := (Counter > LENGTH (Target) ) AND
  291.                             ( (P.Index + LENGTH (Target) - 1) <= LimitIndex) ;
  292.                    IF WholeWords
  293.                       THEN Found := Found AND
  294.                              (Buffer^ [P.Index-1] IN WordSeparators) AND
  295.                              (Buffer^ [P.Index+Counter-1] IN WordSeparators) ;
  296.                    END ; { of while }
  297.              END { of case-insensitive search }
  298.         ELSE BEGIN
  299.              { normal search }
  300.              WHILE (NOT Found) AND (P.Index <= LimitIndex) DO
  301.                    BEGIN
  302.                    { search text for first character of Target }
  303.                    REPEAT IF Buffer^ [P.Index] = LF
  304.                              THEN INC (P.Linenr) ;
  305.                           INC (P.Index) ;
  306.                    UNTIL (Buffer^ [P.Index] = Target [1]) OR
  307.                          (P.Index > LimitIndex) ;
  308.                    Counter := 2 ;
  309.                    { check if following characters are equal to Target }
  310.                    WHILE (Buffer^ [P.Index + Counter - 1] = Target [Counter]) AND
  311.                          (Counter <= LENGTH (Target) ) DO
  312.                          INC (Counter) ;
  313.                    Found := (Counter > LENGTH (Target) ) AND
  314.                             ( (P.Index + LENGTH (Target) - 1) <= LimitIndex) ;
  315.                    IF WholeWords
  316.                       THEN Found := Found AND
  317.                              (Buffer^ [P.Index-1] IN WordSeparators) AND
  318.                              (Buffer^ [P.Index+Counter-1] IN WordSeparators) ;
  319.                    END ; { of while }
  320.              END ; { of normal search }
  321.      CalculateColnr (P) ;
  322.      END ; { of with }
  323. END ; { of procedure }
  324.  
  325. {-----------------------------------------------------------------------------}
  326. { Searches upward for the string <Target>. On exit, P points to the first     }
  327. { character of the string in the text buffer, if the string is found before   }
  328. { index <LimitIndex> is reached. Otherwise, P will point to <LimitIndex>.     }
  329. { The value of global variable Found will be set accordingly.                 }
  330. {-----------------------------------------------------------------------------}
  331.  
  332. PROCEDURE SearchUp (Target : STRING ; VAR P : Position ; LimitIndex : WORD) ;
  333.  
  334. VAR Counter : WORD ;
  335.  
  336. BEGIN
  337. Found := FALSE ;
  338. WITH CurrentWs DO
  339.      BEGIN
  340.      IF IgnoreCase
  341.         THEN BEGIN
  342.              { case-insensitive search }
  343.              Target := UpperCase (Target) ;
  344.              WHILE (NOT Found) AND (P.Index >= LimitIndex) DO
  345.                    BEGIN
  346.                    { search text for first character of Target }
  347.                    REPEAT DEC (P.Index) ;
  348.                           IF Buffer^ [P.Index] = LF
  349.                              THEN DEC (P.Linenr) ;
  350.                    UNTIL (UPCASE (Buffer^ [P.Index]) = Target [1]) OR
  351.                          (P.Index < LimitIndex) ;
  352.                    Counter := 2 ;
  353.                    { check if following characters are equal to Target }
  354.                    WHILE (UPCASE (Buffer^ [P.Index + Counter - 1]) =
  355.                           Target [Counter]) AND
  356.                          (Counter <= LENGTH (Target) ) DO
  357.                          INC (Counter) ;
  358.                    Found := (Counter > LENGTH (Target) ) AND
  359.                             (P.Index >= LimitIndex) ;
  360.                    IF WholeWords
  361.                       THEN Found := Found AND
  362.                              (Buffer^ [P.Index-1] IN WordSeparators) AND
  363.                              (Buffer^ [P.Index+Counter-1] IN WordSeparators) ;
  364.                    END ; { of while }
  365.              END { of case-insensitive search }
  366.         ELSE BEGIN
  367.              { normal search }
  368.              WHILE (NOT Found) AND (P.Index >= LimitIndex) DO
  369.                    BEGIN
  370.                    { search text for first character of Target }
  371.                    REPEAT DEC (P.Index) ;
  372.                           IF Buffer^ [P.Index] = LF
  373.                              THEN DEC (P.Linenr) ;
  374.                    UNTIL (Buffer^ [P.Index] = Target [1]) OR
  375.                          (P.Index < LimitIndex) ;
  376.                    Counter := 2 ;
  377.                    { check if following characters are equal to Target }
  378.                    WHILE (Buffer^ [P.Index + Counter - 1] = Target [Counter]) AND
  379.                          (Counter <= LENGTH (Target) ) DO
  380.                          INC (Counter) ;
  381.                    Found := (Counter > LENGTH (Target) ) AND
  382.                             (P.Index >= LimitIndex) ;
  383.                    IF WholeWords
  384.                       THEN Found := Found AND
  385.                              (Buffer^ [P.Index-1] IN WordSeparators) AND
  386.                              (Buffer^ [P.Index+Counter-1] IN WordSeparators) ;
  387.                    END ; { of while }
  388.              END { of normal search } ;
  389.      CalculateColnr (P) ;
  390.      END ; { of with }
  391. END ; { of procedure }
  392.  
  393. {-----------------------------------------------------------------------------}
  394. { Performs a general search for <Target> according to the search options      }
  395. { that are stored in global boolean variables. (Searching is done by calling  }
  396. { SearchDown or SearchUp.) If Target is found, P will point to the first      }
  397. { character.                                                                  }
  398. {-----------------------------------------------------------------------------}
  399.  
  400. PROCEDURE SearchString (Target : STRING ; VAR P : Position) ;
  401.  
  402. BEGIN
  403. Found := FALSE ;
  404. IF LENGTH (Target) > 0
  405.    THEN BEGIN
  406.         WITH CurrentWs DO
  407.              BEGIN
  408.              IF ReverseSearch
  409.                 THEN BEGIN
  410.                      SearchUp (Target, P, 1) ;
  411.                      END
  412.                 ELSE BEGIN
  413.                      SearchDown (Target, P, BufferSize - 1) ;
  414.                      END ;
  415.              END ; { of with }
  416.         END ;
  417. END ;
  418.  
  419. {-----------------------------------------------------------------------------}
  420. { Searches downward for an occurrence of CloseBracket in the buffer,          }
  421. { matching the OpenBracket that P is assumed to point at when the procedure   }
  422. { is called. If no matching bracket is found, P will point to the end of the  }
  423. { buffer, and Found is set to False.                                          }
  424. {-----------------------------------------------------------------------------}
  425.  
  426. PROCEDURE MatchBracketsDown (OpenBracket, CloseBracket : CHAR ; VAR P : Position) ;
  427.  
  428. VAR Level : INTEGER ;
  429.     { Level keeps track of the nesting level of the brackets }
  430.  
  431. BEGIN
  432. Level := 1 ;
  433. WITH CurrentWs DO
  434.      BEGIN
  435.      WHILE (Level > 0) AND (P.Index < BufferSize) DO
  436.            BEGIN
  437.            IF Buffer^ [P.Index] = LF
  438.               THEN INC (P.Linenr) ;
  439.            INC (P.Index) ;
  440.            IF Buffer^ [P.Index] = OpenBracket THEN INC (Level) ;
  441.            IF Buffer^ [P.Index] = CloseBracket THEN DEC (Level) ;
  442.            END ; { of while }
  443.      CalculateColnr (P) ;
  444.      END ;
  445. Found := (Level = 0) ;
  446. END ;
  447.  
  448. {-----------------------------------------------------------------------------}
  449. { Searches upward for an occurrence of CloseBracket in the buffer, matching   }
  450. { the OpenBracket that P is assumed to point at when the procedure is called. }
  451. { If no matching bracket is found, P will point to the start of the           }
  452. { buffer, and Found is set to False.                                          }
  453. {-----------------------------------------------------------------------------}
  454.  
  455. PROCEDURE MatchBracketsUp (OpenBracket, CloseBracket : CHAR ; VAR P : Position) ;
  456.  
  457. VAR Level : INTEGER ;
  458.     { Level keeps track of the nesting level of the brackets }
  459.  
  460. BEGIN
  461. Level := - 1 ;
  462. WITH CurrentWs DO
  463.      BEGIN
  464.      WHILE (Level < 0) AND (P.Index > 1) DO
  465.            BEGIN
  466.            DEC (P.Index) ;
  467.            IF Buffer^ [P.Index] = LF
  468.               THEN DEC (P.Linenr) ;
  469.            IF Buffer^ [P.Index] = OpenBracket THEN INC (Level) ;
  470.            IF Buffer^ [P.Index] = CloseBracket THEN DEC (Level) ;
  471.            END ; { of while }
  472.      CalculateColnr (P) ;
  473.      END ;
  474. Found := (Level = 0) ;
  475. END ;
  476.  
  477. {-----------------------------------------------------------------------------}
  478.  
  479. END.
  480.