Subversion Repositories Kolibri OS

Rev

Rev 8762 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. (*
  2.     Copyright 2021 Anton Krotov
  3.  
  4.     This file is part of CEdit.
  5.  
  6.     CEdit is free software: you can redistribute it and/or modify
  7.     it under the terms of the GNU General Public License as published by
  8.     the Free Software Foundation, either version 3 of the License, or
  9.     (at your option) any later version.
  10.  
  11.     CEdit is distributed in the hope that it will be useful,
  12.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.     GNU General Public License for more details.
  15.  
  16.     You should have received a copy of the GNU General Public License
  17.     along with CEdit. If not, see <http://www.gnu.org/licenses/>.
  18. *)
  19.  
  20. MODULE Text;
  21.  
  22. IMPORT
  23.     List, Lines,
  24.     G := Graph,
  25.     U := Utils,
  26.     RW, Search,
  27.     E := Encodings,
  28.     CB := Clipboard,
  29.     ChangeLog,
  30.     Lang := Languages;
  31.  
  32.  
  33. CONST
  34.  
  35.     SPACE = 20X;
  36.     TAB = RW.TAB_SIZE;
  37.     lenEOL = CB.lenEOL;
  38.  
  39.     SHIFT* = 0; CTRL* = 1;
  40.  
  41.     mark_width = 2;
  42.     pad_left = mark_width + 3;
  43.     pad_top = 1;
  44.     inter = 2;
  45.  
  46.  
  47. TYPE
  48.  
  49.     tPoint = RECORD
  50.         X, Y: INTEGER
  51.     END;
  52.  
  53.     pPoint = POINTER TO tPoint;
  54.  
  55.     tString* = ARRAY 1000 OF WCHAR;
  56.  
  57.     tLine = Lines.tLine;
  58.  
  59.     tGuard = POINTER TO RECORD (ChangeLog.tGuard)
  60.         selected: BOOLEAN;
  61.         cursor, select2, scroll: tPoint;
  62.         CurX: INTEGER
  63.     END;
  64.  
  65.     tText* = POINTER TO RECORD (List.tList)
  66.         cursor, select, select2: pPoint;
  67.         scroll: tPoint;
  68.         CurX: INTEGER;
  69.         modified*: BOOLEAN;
  70.  
  71.         edition*: tGuard;
  72.         comments, numbers*, guard,
  73.         search, cs, whole: BOOLEAN;
  74.         curLine: tLine;
  75.         fileName*: RW.tFileName;
  76.         lang*: INTEGER;
  77.         enc*: INTEGER;
  78.         table: Search.IdxTable;
  79.         foundList: List.tList;
  80.         idxData: Search.tBuffer;
  81.         foundSel: INTEGER;
  82.         searchText: tString
  83.     END;
  84.  
  85.     tProcedure = PROCEDURE;
  86.  
  87.  
  88. VAR
  89.  
  90.     pdelete: PROCEDURE (text: tText);
  91.     ShowCursor: PROCEDURE;
  92.  
  93.     colors*: RECORD
  94.                 text, back, seltext, selback, modified, saved, curline, numtext, numback, border*: INTEGER;
  95.                 comment, string, num, delim, key1, key2, key3: INTEGER
  96.              END;
  97.     canvas: G.tCanvas;
  98.     drawCursor*: BOOLEAN;
  99.     padding: RECORD left, top: INTEGER END;
  100.     size, textsize: tPoint;
  101.     charWidth, charHeight: INTEGER;
  102.  
  103.  
  104. PROCEDURE setName* (text: tText; name: RW.tFileName);
  105. VAR
  106.     ext: RW.tFileName;
  107. BEGIN
  108.     text.fileName := name;
  109.     U.getFileName(text.fileName, ext, ".");
  110.     U.upcase(ext);
  111.     IF ext = "OB07" THEN
  112.         text.lang := Lang.langOberon
  113.     ELSIF (ext = "C") OR (ext = "H") OR (ext = "CPP") THEN
  114.         text.lang := Lang.langC
  115.     ELSIF (ext = "PAS") OR (ext = "PP") THEN
  116.         text.lang := Lang.langPascal
  117.     ELSIF ext = "ASM" THEN
  118.         text.lang := Lang.langFasm
  119.     ELSIF ext = "LUA" THEN
  120.         text.lang := Lang.langLua
  121.     ELSIF ext = "INI" THEN
  122.         text.lang := Lang.langIni
  123.     ELSE
  124.         text.lang := Lang.langNone
  125.     END
  126. END setName;
  127.  
  128.  
  129. PROCEDURE setLang* (text: tText; lang: INTEGER);
  130. BEGIN
  131.     text.lang := lang;
  132.     text.comments := TRUE
  133. END setLang;
  134.  
  135.  
  136. PROCEDURE getPos* (text: tText; VAR x, y: INTEGER);
  137. BEGIN
  138.     x := text.cursor.X + 1;
  139.     y := text.cursor.Y + 1
  140. END getPos;
  141.  
  142.  
  143. PROCEDURE getScroll* (text: tText; VAR x, y: INTEGER);
  144. BEGIN
  145.     x := text.scroll.X;
  146.     y := text.scroll.Y
  147. END getScroll;
  148.  
  149.  
  150. PROCEDURE getTextSize* (VAR x, y: INTEGER);
  151. BEGIN
  152.     x := textsize.X;
  153.     y := textsize.Y
  154. END getTextSize;
  155.  
  156.  
  157. PROCEDURE getTextRect* (VAR left, top, rigth, bottom: INTEGER);
  158. BEGIN
  159.     left := padding.left - 1;
  160.     top := padding.top - 1;
  161.     rigth := size.X - 1;
  162.     bottom := top + size.Y - 1;
  163. END getTextRect;
  164.  
  165.  
  166. PROCEDURE toggleNumbers* (text: tText);
  167. BEGIN
  168.     text.numbers := ~text.numbers
  169. END toggleNumbers;
  170.  
  171.  
  172. PROCEDURE toggleCursor*;
  173. BEGIN
  174.     drawCursor := ~drawCursor
  175. END toggleCursor;
  176.  
  177.  
  178. PROCEDURE getChar (line: tLine; i: INTEGER): WCHAR;
  179. VAR
  180.     res: WCHAR;
  181. BEGIN
  182.     IF i >= line.length THEN
  183.         res := 0X
  184.     ELSE
  185.         res := Lines.getChar(line, i)
  186.     END
  187.     RETURN res
  188. END getChar;
  189.  
  190.  
  191. PROCEDURE getString (src: tLine; pos, cnt: INTEGER; VAR dst: ARRAY OF WCHAR): INTEGER;
  192. VAR
  193.     i: INTEGER;
  194. BEGIN
  195.     i := 0;
  196.     WHILE (pos < src.length) & (cnt > 0) DO
  197.         IF i < LEN(dst) - 1 THEN
  198.             dst[i] := getChar(src, pos);
  199.             INC(i)
  200.         END;
  201.         INC(pos);
  202.         DEC(cnt)
  203.     END;
  204.     dst[i] := 0X
  205.     RETURN i
  206. END getString;
  207.  
  208.  
  209. PROCEDURE NextLine (VAR line: tLine);
  210. BEGIN
  211.     line := line.next(tLine)
  212. END NextLine;
  213.  
  214.  
  215. PROCEDURE PrevLine (VAR line: tLine);
  216. BEGIN
  217.     line := line.prev(tLine)
  218. END PrevLine;
  219.  
  220.  
  221. PROCEDURE SetColor (textColor, backColor: INTEGER);
  222. BEGIN
  223.     G.SetTextColor(canvas, textColor);
  224.     G.SetBkColor(canvas, backColor)
  225. END SetColor;
  226.  
  227.  
  228. PROCEDURE ProcessComments (line: tLine; VAR depth, pos: INTEGER; minDepth, n: INTEGER; lang: INTEGER);
  229. VAR
  230.     cond: INTEGER;
  231. BEGIN
  232.     cond := 0;
  233.     WHILE (pos <= n) & (depth > minDepth) DO
  234.         Lang.comments(line, depth, cond, pos, n, lang);
  235.         INC(pos)
  236.     END;
  237.     DEC(pos)
  238. END ProcessComments;
  239.  
  240.  
  241. PROCEDURE Comments (text: tText);
  242. VAR
  243.     line: tLine;
  244.     i: INTEGER;
  245. BEGIN
  246.     line := text.first(tLine);
  247.     line.cin := 0;
  248.     line.cout := 0;
  249.     i := 0;
  250.     ProcessComments(line, line.cout, i, -1, line.length - 1, text.lang);
  251.     NextLine(line);
  252.     WHILE line # NIL DO
  253.         line.cin := line.prev(tLine).cout;
  254.         line.cout := line.cin;
  255.         i := 0;
  256.         ProcessComments(line, line.cout, i, -1, line.length - 1, text.lang);
  257.         NextLine(line)
  258.     END;
  259.     text.comments := FALSE
  260. END Comments;
  261.  
  262.  
  263. PROCEDURE parse (text: tText; line: tLine; y: INTEGER; backColor: INTEGER; lang: INTEGER);
  264. VAR
  265.     c: WCHAR;
  266.     i, n, k: INTEGER;
  267.     cond, depth: INTEGER;
  268.     color: INTEGER;
  269.     hex: BOOLEAN;
  270.     isDgt: PROCEDURE (c: WCHAR): BOOLEAN;
  271.  
  272.  
  273.     PROCEDURE PrintLex (text: tText; line: tLine; lexStart, lexEnd: INTEGER; y: INTEGER; color, backColor: INTEGER);
  274.     VAR
  275.         lexLen: INTEGER;
  276.     BEGIN
  277.         SetColor(color, backColor);
  278.         lexLen := MAX(MIN(line.length - lexStart, lexEnd - lexStart + 1), 0);
  279.         G.TextOut(canvas, padding.left + (lexStart - text.scroll.X) * charWidth, y, Lines.getPChar(line, lexStart), lexLen)
  280.     END PrintLex;
  281.  
  282.  
  283.     PROCEDURE PrintComment (text: tText; line: tLine; VAR depth, i: INTEGER; y: INTEGER; backColor: INTEGER);
  284.     VAR
  285.         lexStart: INTEGER;
  286.         color: INTEGER;
  287.     BEGIN
  288.         IF (text.lang = Lang.langLua) & ~ODD(depth) THEN
  289.             color := colors.string
  290.         ELSIF (text.lang = Lang.langIni) & (depth = 1) THEN
  291.             color := colors.key2
  292.         ELSIF (text.lang = Lang.langPascal) & (depth = 3) THEN
  293.             color := colors.key3
  294.         ELSE
  295.             color := colors.comment
  296.         END;
  297.         lexStart := MAX(i - 2, 0);
  298.         ProcessComments(line, depth, i, 0, line.length - 1, text.lang);
  299.         PrintLex(text, line, lexStart, i, y, color, backColor)
  300.     END PrintComment;
  301.  
  302.  
  303.     PROCEDURE cap (c: WCHAR): WCHAR;
  304.     BEGIN
  305.         IF U.cap(c) THEN END
  306.         RETURN c
  307.     END cap;
  308.  
  309.  
  310.     PROCEDURE UL (c: WCHAR): BOOLEAN;
  311.         RETURN (cap(c) = "U") OR (cap(c) = "L")
  312.     END UL;
  313.  
  314.  
  315.     PROCEDURE FL (c: WCHAR): BOOLEAN;
  316.         RETURN (cap(c) = "F") OR (cap(c) = "L")
  317.     END FL;
  318.  
  319.  
  320.     PROCEDURE isFASMdelim (c: WCHAR): BOOLEAN;
  321.     VAR
  322.         s: ARRAY 19 OF WCHAR;
  323.         i: INTEGER;
  324.     BEGIN
  325.         s := "{}[]<>:,()&*/|+-\#";
  326.         i := LEN(s) - 2;
  327.         WHILE (i >= 0) & (c # s[i]) DO
  328.             DEC(i)
  329.         END
  330.         RETURN i >= 0
  331.     END isFASMdelim;
  332.  
  333.  
  334.     PROCEDURE ident (text: tText; VAR i: INTEGER; first, y: INTEGER; line: tLine; backColor: INTEGER; cs: BOOLEAN);
  335.     VAR
  336.         c: WCHAR;
  337.         lexLen: INTEGER;
  338.         s: ARRAY 32 OF WCHAR;
  339.         color: INTEGER;
  340.     BEGIN
  341.         c := getChar(line, i);
  342.         WHILE U.isLetter(c) OR (c = "_") OR U.isDigit(c) DO
  343.             INC(i);
  344.             c := getChar(line, i);
  345.         END;
  346.         DEC(i);
  347.         lexLen := getString(line, first, i - first + 1, s);
  348.         IF ~cs THEN
  349.             U.upcase16(s)
  350.         END;
  351.         IF Lang.isKey(s, text.lang, 1) THEN
  352.             color := colors.key1
  353.         ELSIF Lang.isKey(s, text.lang, 2) THEN
  354.             color := colors.key2
  355.         ELSIF Lang.isKey(s, text.lang, 3) THEN
  356.             color := colors.key3
  357.         ELSE
  358.             color := colors.text
  359.         END;
  360.         IF color # colors.text THEN
  361.             PrintLex(text, line, first, i, y, color, backColor)
  362.         END
  363.     END ident;
  364.  
  365.  
  366.     PROCEDURE String (text: tText; line: tLine; VAR i: INTEGER; y: INTEGER; backColor: INTEGER);
  367.     VAR
  368.         k: INTEGER;
  369.     BEGIN
  370.         k := i;
  371.         Lang.SkipString(line, i, line.length - 1);
  372.         PrintLex(text, line, k, i, y, colors.string, backColor)
  373.     END String;
  374.  
  375.  
  376. BEGIN
  377.     depth := line.cin;
  378.     n := line.length - 1;
  379.     i := 0;
  380.     IF (depth > 0) & (n >= 0) THEN
  381.         PrintComment(text, line, depth, i, y, backColor)
  382.     END;
  383.     cond := 0;
  384.     WHILE i <= n DO
  385.         c := getChar(line, i);
  386.  
  387.         IF lang = Lang.langFasm THEN
  388.  
  389.             IF c = ";" THEN
  390.                 PrintLex(text, line, i, n, y, colors.comment, backColor);
  391.                 i := n
  392.             ELSIF (c = "'") OR (c = '"') THEN
  393.                 String(text, line, i, y, backColor)
  394.             ELSIF (U.isLetter(c) OR (c = "_")) THEN
  395.                 ident(text, i, i, y, line, backColor, FALSE)
  396.             ELSIF isFASMdelim(c) THEN
  397.                 PrintLex(text, line, i, i, y, colors.delim, backColor)
  398.             ELSIF U.isDigit(c) THEN
  399.                 hex := FALSE;
  400.                 k := i;
  401.                 INC(i);
  402.                 c := getChar(line, i);
  403.                 IF (cap(c) = "X") & (getChar(line, i - 1) = "0") THEN
  404.                     INC(i);
  405.                     hex := TRUE
  406.                 END;
  407.  
  408.                 WHILE U.isHex(cap(getChar(line, i))) DO
  409.                     INC(i)
  410.                 END;
  411.  
  412.                 IF (cap(getChar(line, i)) = "H") & ~hex THEN
  413.                     INC(i)
  414.                 END;
  415.  
  416.                 DEC(i);
  417.                 PrintLex(text, line, k, i, y, colors.num, backColor)
  418.             END
  419.  
  420.         ELSIF lang = Lang.langC THEN
  421.  
  422.         IF depth = 0 THEN
  423.             IF c = "/" THEN
  424.                 IF cond = 0 THEN
  425.                     cond := 1
  426.                 ELSE
  427.                     PrintLex(text, line, i - 1, n, y, colors.comment, backColor);
  428.                     cond := 0;
  429.                     i := n
  430.                 END
  431.             ELSIF (c = "*") & (cond = 1) THEN
  432.                 depth := 1;
  433.                 INC(i);
  434.                 PrintComment(text, line, depth, i, y, backColor);
  435.                 cond := 0
  436.             ELSIF (c = "'") OR (c = '"') THEN
  437.                 String(text, line, i, y, backColor);
  438.                 cond := 0
  439.             ELSIF (U.isLetter(c) OR (c = "_")) THEN
  440.                 ident(text, i, i - ORD((i > 0) & (getChar(line, i - 1) = "#")), y, line, backColor, TRUE);
  441.                 cond := 0
  442.             ELSIF U.isDigit(c) THEN
  443.                 k := i;
  444.                 INC(i);
  445.                 c := getChar(line, i);
  446.                 IF c = "." THEN
  447.                     DEC(i);
  448.                     c := getChar(line, i)
  449.                 END;
  450.                 IF (cap(c) = "X") & (getChar(line, i - 1) = "0") THEN
  451.                     REPEAT
  452.                         INC(i);
  453.                         c := getChar(line, i)
  454.                     UNTIL ~U.isHex(cap(c));
  455.                     IF UL(c) THEN
  456.                         INC(i)
  457.                     END
  458.                 ELSIF UL(c) THEN
  459.                     INC(i)
  460.                 ELSIF U.isDigit(c) THEN
  461.                     REPEAT
  462.                         INC(i)
  463.                     UNTIL ~U.isDigit(getChar(line, i));
  464.                     c := getChar(line, i);
  465.                     IF UL(c) THEN
  466.                         INC(i)
  467.                     ELSIF c = "." THEN
  468.                         INC(i);
  469.                         WHILE U.isDigit(getChar(line, i)) DO
  470.                             INC(i)
  471.                         END;
  472.                         c := getChar(line, i);
  473.                         IF cap(c) = "E" THEN
  474.                             INC(i);
  475.                             c := getChar(line, i);
  476.                             IF (c = "+") OR (c = "-") THEN
  477.                                 INC(i)
  478.                             END;
  479.                             IF U.isDigit(getChar(line, i)) THEN
  480.                                 WHILE U.isDigit(getChar(line, i)) DO
  481.                                     INC(i)
  482.                                 END;
  483.                                 c := getChar(line, i);
  484.                                 IF FL(c) THEN
  485.                                     INC(i)
  486.                                 END
  487.                             END
  488.                         ELSIF FL(c) THEN
  489.                             INC(i)
  490.                         END
  491.                     END
  492.                 END;
  493.                 DEC(i);
  494.                 PrintLex(text, line, k, i, y, colors.num, backColor);
  495.                 cond := 0
  496.             ELSE
  497.                 cond := 0
  498.             END
  499.         ELSIF depth = 1 THEN
  500.             IF c = "*" THEN
  501.                 cond := 1
  502.             ELSIF (c = "/") & (cond = 1) THEN
  503.                 cond := 0;
  504.                 depth := 0
  505.             ELSE
  506.                 cond := 0
  507.             END
  508.         END;
  509.  
  510.         ELSIF lang = Lang.langOberon THEN
  511.  
  512.         IF (depth = 0) & (c = "/") THEN
  513.             IF cond = 3 THEN
  514.                 PrintLex(text, line, i - 1, n, y, colors.comment, backColor);
  515.                 cond := 0;
  516.                 i := n
  517.             ELSE
  518.                 cond := 3
  519.             END
  520.         ELSIF (depth = 0) & ((c = "'") OR (c = '"')) THEN
  521.             String(text, line, i, y, backColor);
  522.             cond := 0
  523.         ELSIF (depth = 0) & U.isDigit(c) THEN
  524.             color := colors.num;
  525.             k := i;
  526.             INC(i);
  527.             WHILE U.isHex(getChar(line, i)) DO
  528.                 INC(i)
  529.             END;
  530.             IF i <= n THEN
  531.                 IF getChar(line, i) = "." THEN
  532.                     INC(i);
  533.                     IF getChar(line, i) = "." THEN
  534.                         DEC(i)
  535.                     END;
  536.                     WHILE U.isDigit(getChar(line, i)) DO
  537.                         INC(i)
  538.                     END;
  539.                     IF getChar(line, i) = "E" THEN
  540.                         INC(i);
  541.                         IF (getChar(line, i) = "+") OR (getChar(line, i) = "-") THEN
  542.                             INC(i)
  543.                         END;
  544.                         WHILE U.isDigit(getChar(line, i)) DO
  545.                             INC(i)
  546.                         END
  547.                     END
  548.                 ELSIF getChar(line, i) = "H" THEN
  549.                     INC(i)
  550.                 ELSIF getChar(line, i) = "X" THEN
  551.                     color := colors.string;
  552.                     INC(i)
  553.                 END
  554.             END;
  555.             DEC(i);
  556.             PrintLex(text, line, k, i, y, color, backColor);
  557.             cond := 0
  558.         ELSIF (depth = 0) & (U.isLetter(c) OR (c = "_")) THEN
  559.             ident(text, i, i, y, line, backColor, TRUE);
  560.             cond := 0
  561.         ELSIF c = "(" THEN
  562.             cond := 1
  563.         ELSIF c = "*" THEN
  564.             IF cond = 1 THEN
  565.                 INC(depth);
  566.                 INC(i);
  567.                 PrintComment(text, line, depth, i, y, backColor);
  568.                 cond := 0
  569.             ELSE
  570.                 cond := 2
  571.             END
  572.         ELSIF c = ")" THEN
  573.             IF cond = 2 THEN
  574.                 IF depth > 0 THEN
  575.                     DEC(depth)
  576.                 END
  577.             END;
  578.             cond := 0
  579.         ELSE
  580.             cond := 0
  581.         END
  582.  
  583.         ELSIF lang = Lang.langLua THEN
  584.  
  585.         IF depth = 0 THEN
  586.             IF c = "-" THEN
  587.                 IF cond = 1 THEN
  588.                     IF Lang.LuaLong(line, i + 1) >= 0 THEN
  589.                         depth := Lang.LuaLong(line, i + 1)*2 + 1;
  590.                         INC(i);
  591.                         PrintComment(text, line, depth, i, y, backColor)
  592.                     ELSE
  593.                         PrintLex(text, line, i - 1, n, y, colors.comment, backColor);
  594.                         i := n
  595.                     END;
  596.                     cond := 0
  597.                 ELSE
  598.                     cond := 1
  599.                 END
  600.             ELSIF c = "[" THEN
  601.                 cond := 0;
  602.                 k := Lang.LuaLong(line, i);
  603.                 IF k >= 0 THEN
  604.                     depth := (k + 1)*2;
  605.                     INC(i, 2);
  606.                     PrintComment(text, line, depth, i, y, backColor);
  607.                     cond := 0
  608.                 END
  609.             ELSIF (c = "'") OR (c = '"') THEN
  610.                 String(text, line, i, y, backColor);
  611.                 cond := 0
  612.             ELSIF U.isDigit(c) THEN
  613.                 k := i;
  614.                 IF (c = "0") & (cap(getChar(line, i + 1)) = "X") THEN
  615.                     isDgt := U.isHex;
  616.                     hex := TRUE;
  617.                     INC(i, 2)
  618.                 ELSE
  619.                     isDgt := U.isDigit;
  620.                     hex := FALSE
  621.                 END;
  622.                 WHILE isDgt(cap(getChar(line, i))) DO
  623.                     INC(i)
  624.                 END;
  625.                 IF getChar(line, i) = "." THEN
  626.                     INC(i);
  627.                     IF getChar(line, i) = "." THEN
  628.                         DEC(i)
  629.                     END;
  630.                     WHILE isDgt(cap(getChar(line, i))) DO
  631.                         INC(i)
  632.                     END
  633.                 END;
  634.                 IF (cap(getChar(line, i)) = "E") OR hex & (cap(getChar(line, i)) = "P") THEN
  635.                     INC(i);
  636.                     IF (getChar(line, i) = "-") OR (getChar(line, i) = "+") THEN
  637.                         INC(i)
  638.                     END;
  639.                     WHILE isDgt(cap(getChar(line, i))) DO
  640.                         INC(i)
  641.                     END
  642.                 END;
  643.                 DEC(i);
  644.                 PrintLex(text, line, k, i, y, colors.num, backColor);
  645.                 cond := 0
  646.             ELSIF U.isLetter(c) OR (c = "_") THEN
  647.                 ident(text, i, i, y, line, backColor, TRUE);
  648.                 cond := 0
  649.             ELSE
  650.                 cond := 0
  651.             END
  652.  
  653.         ELSIF depth > 0 THEN
  654.             IF (cond = 0) & (c = "]") THEN
  655.                 cond := 1
  656.             ELSIF (cond >= 1) & (c = "=") THEN
  657.                 INC(cond)
  658.             ELSIF (cond >= 1) & (c = "]") & (cond * 2 - depth MOD 2 = depth) THEN
  659.                 depth := 0;
  660.                 cond := 0
  661.             ELSE
  662.                 cond := 0
  663.             END
  664.         END
  665.  
  666.         ELSIF lang = Lang.langPascal THEN
  667.  
  668.         IF depth = 0 THEN
  669.             IF c = "(" THEN
  670.                 cond := 1
  671.             ELSIF (c = "*") & (cond = 1) THEN
  672.                 depth := 2;
  673.                 INC(i);
  674.                 PrintComment(text, line, depth, i, y, backColor);
  675.                 cond := 0
  676.             ELSIF c = "/" THEN
  677.                 IF cond = 2 THEN
  678.                     PrintLex(text, line, i - 1, n, y, colors.comment, backColor);
  679.                     cond := 0;
  680.                     i := n
  681.                 ELSE
  682.                     cond := 2
  683.                 END
  684.             ELSIF c = "'" THEN
  685.                 String(text, line, i, y, backColor);
  686.                 cond := 0
  687.             ELSIF c = "{" THEN
  688.                 IF getChar(line, i + 1) = "$" THEN
  689.                     depth := 3
  690.                 ELSE
  691.                     depth := 1
  692.                 END;
  693.                 INC(i, 2);
  694.                 PrintComment(text, line, depth, i, y, backColor);
  695.                 cond := 0
  696.             ELSIF c = "#" THEN
  697.                 k := i;
  698.                 INC(i);
  699.                 WHILE U.isDigit(getChar(line, i)) DO
  700.                     INC(i)
  701.                 END;
  702.                 DEC(i);
  703.                 PrintLex(text, line, k, i, y, colors.string, backColor);
  704.                 cond := 0
  705.             ELSIF c = "$" THEN
  706.                 IF (i > 0 ) & (getChar(line, i - 1) = "#") THEN
  707.                     color := colors.string
  708.                 ELSE
  709.                     color := colors.num
  710.                 END;
  711.                 k := i;
  712.                 INC(i);
  713.                 WHILE U.isHex(cap(getChar(line, i))) DO
  714.                     INC(i)
  715.                 END;
  716.                 DEC(i);
  717.                 PrintLex(text, line, k, i, y, color, backColor);
  718.                 cond := 0
  719.             ELSIF U.isDigit(c) THEN
  720.                 k := i;
  721.                 WHILE U.isDigit(getChar(line, i)) DO
  722.                     INC(i)
  723.                 END;
  724.                 IF getChar(line, i) = "." THEN
  725.                     INC(i);
  726.                     IF getChar(line, i) = "." THEN
  727.                         DEC(i)
  728.                     END;
  729.                     WHILE U.isDigit(getChar(line, i)) DO
  730.                         INC(i)
  731.                     END;
  732.                     IF cap(getChar(line, i)) = "E" THEN
  733.                         INC(i);
  734.                         IF (getChar(line, i) = "-") OR (getChar(line, i) = "+") THEN
  735.                             INC(i)
  736.                         END;
  737.                         WHILE U.isDigit(getChar(line, i)) DO
  738.                             INC(i)
  739.                         END
  740.                     END
  741.                 END;
  742.                 DEC(i);
  743.                 PrintLex(text, line, k, i, y, colors.num, backColor);
  744.                 cond := 0
  745.             ELSIF (U.isLetter(c) OR (c = "_")) THEN
  746.                 ident(text, i, i, y, line, backColor, FALSE);
  747.                 cond := 0
  748.             ELSE
  749.                 cond := 0
  750.             END
  751.         ELSIF depth IN {1, 3} THEN
  752.             IF c = "}" THEN
  753.                 depth := 0
  754.             END
  755.         ELSIF depth = 2 THEN
  756.             IF c = "*" THEN
  757.                 cond := 1
  758.             ELSIF (c = ")") & (cond = 1) THEN
  759.                 depth := 0;
  760.                 cond := 0
  761.             ELSE
  762.                 cond := 0
  763.             END
  764.         END
  765.  
  766.         ELSIF lang = Lang.langIni THEN
  767.  
  768.         IF depth = 0 THEN
  769.             IF c = ";" THEN
  770.                 PrintLex(text, line, i, n, y, colors.comment, backColor);
  771.                 i := n
  772.             ELSIF c = '"' THEN
  773.                 String(text, line, i, y, backColor)
  774.             ELSIF c = "=" THEN
  775.                 PrintLex(text, line, i, i, y, colors.delim, backColor)
  776.             ELSIF c = "[" THEN
  777.                 depth := 1;
  778.                 INC(i, 2);
  779.                 PrintComment(text, line, depth, i, y, backColor)
  780.             ELSIF U.isDigit(c) THEN
  781.                 k := i;
  782.                 WHILE U.isDigit(getChar(line, i)) DO
  783.                     INC(i)
  784.                 END;
  785.                 DEC(i);
  786.                 PrintLex(text, line, k, i, y, colors.num, backColor)
  787.             ELSIF (U.isLetter(c) OR (c = "_")) THEN
  788.                 ident(text, i, i, y, line, backColor, TRUE)
  789.             END
  790.         ELSIF depth = 1 THEN
  791.             IF c = "]" THEN
  792.                 depth := 0
  793.             END
  794.         END
  795.  
  796.         END;
  797.         INC(i)
  798.     END
  799. END parse;
  800.  
  801.  
  802. PROCEDURE leadingSpaces (line: tLine): INTEGER;
  803. VAR
  804.     i: INTEGER;
  805. BEGIN
  806.     i := 0;
  807.     WHILE getChar(line, i) = SPACE DO
  808.         INC(i)
  809.     END
  810.     RETURN i
  811. END leadingSpaces;
  812.  
  813.  
  814. PROCEDURE plain (text: tText; eot: BOOLEAN): CB.tBuffer;
  815. VAR
  816.     buf: CB.tBuffer;
  817.     size: INTEGER;
  818.     line: tLine;
  819.     EOT: ARRAY 2 OF WCHAR;
  820. BEGIN
  821.     size := 0;
  822.     line := text.first(tLine);
  823.     WHILE line # NIL DO
  824.         line.pos := size;
  825.         INC(size, line.length);
  826.         NextLine(line);
  827.         IF line # NIL THEN
  828.             INC(size, CB.lenEOL)
  829.         END
  830.     END;
  831.     IF eot THEN
  832.         INC(size, 2)
  833.     END;
  834.     buf := CB.create(size);
  835.     line := text.first(tLine);
  836.     WHILE line # NIL DO
  837.         CB.append(buf, line, 0, line.length - 1);
  838.         NextLine(line);
  839.         IF line # NIL THEN
  840.             CB.eol(buf)
  841.         END
  842.     END;
  843.     IF eot THEN
  844.         EOT[0] := 0X;
  845.         EOT[1] := 0X;
  846.         CB.appends(buf, EOT, 0, 1)
  847.     END
  848.     RETURN buf
  849. END plain;
  850.  
  851.  
  852. PROCEDURE search* (text: tText; s: ARRAY OF WCHAR; cs, whole: BOOLEAN): BOOLEAN;
  853. VAR
  854.     pos: List.tItem;
  855.     res: BOOLEAN;
  856.     plainText: Search.tBuffer;
  857. BEGIN
  858.     plainText := NIL;
  859.     WHILE text.foundList.count # 0 DO
  860.         pos := List.pop(text.foundList);
  861.         DISPOSE(pos)
  862.     END;
  863.     text.whole := whole;
  864.     text.cs := cs;
  865.     text.searchText := s;
  866.     IF ~cs THEN
  867.         U.upcase16(text.searchText)
  868.     END;
  869.     IF text.searchText # "" THEN
  870.         plainText := plain(text, TRUE);
  871.         text.idxData := Search.index(plainText, text.table, cs);
  872.         Search.find(plainText, text.table, text.searchText, whole, text.foundList);
  873.         res := text.foundList.count > 0
  874.     ELSE
  875.         res := TRUE
  876.     END;
  877.     CB.destroy(plainText);
  878.     CB.destroy(text.idxData);
  879.     text.search := FALSE;
  880.     text.foundSel := 0
  881.     RETURN res
  882. END search;
  883.  
  884.  
  885. PROCEDURE modify (text: tText);
  886. BEGIN
  887.     text.modified := TRUE;
  888.     text.comments := TRUE;
  889.     text.search := TRUE;
  890.     text.guard := TRUE
  891. END modify;
  892.  
  893.  
  894. PROCEDURE DelLine (text: tText; line: tLine);
  895. BEGIN
  896.     List._delete(text, line);
  897.     Lines.destroy(line);
  898.     modify(text)
  899. END DelLine;
  900.  
  901.  
  902. PROCEDURE setSelect (text: tText);
  903. BEGIN
  904.     IF text.select = text.cursor THEN
  905.         text.select2^ := text.cursor^;
  906.         text.select := text.select2
  907.     END
  908. END setSelect;
  909.  
  910.  
  911. PROCEDURE resetSelect* (text: tText);
  912. BEGIN
  913.     text.select := text.cursor
  914. END resetSelect;
  915.  
  916.  
  917. PROCEDURE getLine (text: tText; n: INTEGER): tLine;
  918. VAR
  919.     item: List.tItem;
  920. BEGIN
  921.     item := List.getItem(text, n);
  922.     RETURN item(tLine)
  923. END getLine;
  924.  
  925.  
  926. PROCEDURE SetPos* (text: tText; x, y: INTEGER);
  927. VAR
  928.     deltaY: INTEGER;
  929.     cursor: pPoint;
  930.    (* trimLength: INTEGER; *)
  931. BEGIN
  932.     cursor := text.cursor;
  933.     y := MIN(MAX(y, 0), text.count - 1);
  934.     deltaY := y - cursor.Y;
  935.     IF deltaY # 0 THEN
  936.         cursor.Y := y;
  937. (*        trimLength := Lines.trimLength(text.curLine);
  938.         IF text.curLine.length # trimLength THEN
  939.             Lines.setChar(text.curLine, trimLength, 0X);
  940.             text.curLine.length := trimLength
  941.         END;*)
  942.         IF deltaY = 1 THEN
  943.             NextLine(text.curLine)
  944.         ELSIF deltaY = -1 THEN
  945.             PrevLine(text.curLine)
  946.         ELSE
  947.             text.curLine := getLine(text, y)
  948.         END
  949.     END;
  950.     cursor.X := MIN(MAX(x, 0), text.curLine.length);
  951.     IF text.scroll.Y > cursor.Y THEN
  952.         text.scroll.Y := cursor.Y
  953.     ELSIF text.scroll.Y + textsize.Y <= cursor.Y THEN
  954.         text.scroll.Y := cursor.Y - textsize.Y + 1
  955.     END;
  956.     IF text.scroll.X > cursor.X THEN
  957.         text.scroll.X := cursor.X
  958.     ELSIF text.scroll.X + textsize.X <= cursor.X THEN
  959.         text.scroll.X := cursor.X - textsize.X + 1
  960.     END;
  961.     IF (text.select.Y = cursor.Y) & (text.select.X > text.curLine.length) THEN
  962.         text.select.X := text.curLine.length
  963.     END;
  964.     setSelect(text);
  965.     text.foundSel := 0;
  966.     ShowCursor;
  967.     drawCursor := TRUE;
  968.     text.CurX := -1
  969. END SetPos;
  970.  
  971.  
  972. PROCEDURE getSelect (text: tText; VAR selBeg, selEnd: tPoint);
  973. BEGIN
  974.     selBeg := text.cursor^;
  975.     selEnd := text.select^;
  976.     IF (selBeg.Y > selEnd.Y) OR (selBeg.Y = selEnd.Y) & (selBeg.X > selEnd.X) THEN
  977.         selBeg := text.select^;
  978.         selEnd := text.cursor^
  979.     END
  980. END getSelect;
  981.  
  982.  
  983. PROCEDURE selected* (text: tText): BOOLEAN;
  984.     RETURN (text.cursor.X # text.select.X) OR (text.cursor.Y # text.select.Y)
  985. END selected;
  986.  
  987.  
  988. PROCEDURE delSelect (text: tText);
  989. VAR
  990.     selBeg, selEnd: tPoint;
  991.     line, last, cur: tLine;
  992. BEGIN
  993.     getSelect(text, selBeg, selEnd);
  994.     IF (selBeg.Y = selEnd.Y) & (selBeg.X < selEnd.X) THEN
  995.         line := text.curLine;
  996.         Lines.delCharN(line, selBeg.X, selEnd.X - selBeg.X);
  997.         Lines.modify(line);
  998.         text.cursor^ := selBeg;
  999.         resetSelect(text);
  1000.         SetPos(text, text.cursor.X, text.cursor.Y);
  1001.         modify(text)
  1002.     ELSIF selBeg.Y < selEnd.Y THEN
  1003.         SetPos(text, selBeg.X, selBeg.Y);
  1004.         line := text.curLine;
  1005.         Lines.delCharN(line, selBeg.X, line.length - selBeg.X);
  1006.         last := getLine(text, selEnd.Y);
  1007.         Lines.delCharN(last, 0, selEnd.X);
  1008.         cur := line.next(tLine);
  1009.         WHILE cur # last DO
  1010.             DelLine(text, cur);
  1011.             cur := line.next(tLine)
  1012.         END;
  1013.         resetSelect(text);
  1014.         SetPos(text, text.cursor.X, text.cursor.Y);
  1015.         pdelete(text);
  1016.         modify(text)
  1017.     END;
  1018.     resetSelect(text)
  1019. END delSelect;
  1020.  
  1021.  
  1022. PROCEDURE delete (text: tText);
  1023. VAR
  1024.     i: INTEGER;
  1025.     nextLine, curLine: tLine;
  1026. BEGIN
  1027.     IF selected(text) THEN
  1028.         delSelect(text)
  1029.     ELSE
  1030.         i := text.cursor.X;
  1031.         curLine := text.curLine;
  1032.         IF i < curLine.length THEN
  1033.             Lines.delChar(curLine, i);
  1034.             Lines.modify(curLine);
  1035.             modify(text)
  1036.         ELSE
  1037.             nextLine := curLine.next(tLine);
  1038.             IF nextLine # NIL THEN
  1039.                 Lines.modify(curLine);
  1040.                 modify(text);
  1041.                 Lines.insert2(curLine, i, nextLine);
  1042.                 DelLine(text, nextLine)
  1043.             END
  1044.         END
  1045.     END;
  1046.     setSelect(text)
  1047. END delete;
  1048.  
  1049.  
  1050. PROCEDURE BkSpace (text: tText);
  1051. VAR
  1052.     i, n, k: INTEGER;
  1053.     curLine, line: tLine;
  1054. BEGIN
  1055.     IF selected(text) THEN
  1056.         delSelect(text)
  1057.     ELSE
  1058.         resetSelect(text);
  1059.         i := text.cursor.X;
  1060.         curLine := text.curLine;
  1061.         IF i > 0 THEN
  1062.             modify(text);
  1063.             n := leadingSpaces(curLine);
  1064.             IF n < i THEN
  1065.                 Lines.delChar(curLine, i - 1);
  1066.                 Lines.modify(curLine);
  1067.                 k := 1
  1068.             ELSE
  1069.                 n := i;
  1070.                 line := curLine.prev(tLine);
  1071.                 k := n;
  1072.                 WHILE (line # NIL) & (k >= n) DO
  1073.                     IF Lines.trimLength(line) # 0 THEN
  1074.                         k := leadingSpaces(line)
  1075.                     END;
  1076.                     PrevLine(line)
  1077.                 END;
  1078.                 IF k >= n THEN
  1079.                     k := 0
  1080.                 END;
  1081.                 DEC(n, k);
  1082.                 k := n;
  1083.                 Lines.modify(curLine);
  1084.                 Lines.delCharN(curLine, 0, n)
  1085.             END;
  1086.             SetPos(text, text.cursor.X - k, text.cursor.Y)
  1087.         ELSE
  1088.             PrevLine(curLine);
  1089.             IF curLine # NIL THEN
  1090.                 SetPos(text, curLine.length, text.cursor.Y - 1);
  1091.                 delete(text)
  1092.             END
  1093.         END
  1094.     END;
  1095.     setSelect(text)
  1096. END BkSpace;
  1097.  
  1098.  
  1099. PROCEDURE enter (text: tText);
  1100. VAR
  1101.     n: INTEGER;
  1102.     curLine, newLine, line: tLine;
  1103. BEGIN
  1104.     delSelect(text);
  1105.     newLine := Lines.create(FALSE);
  1106.     Lines.modify(newLine);
  1107.     modify(text);
  1108.     curLine := text.curLine;
  1109.     IF text.cursor.X < curLine.length THEN
  1110.         Lines.modify(curLine);
  1111.         Lines.wrap(curLine, newLine, text.cursor.X)
  1112.     END;
  1113.     List._insert(text, curLine, newLine);
  1114.     SetPos(text, 0, text.cursor.Y + 1);
  1115.     line := text.curLine.prev(tLine);
  1116.     n := -1;
  1117.     WHILE (line # NIL) & (n = -1) DO
  1118.         IF (*line.length*)Lines.trimLength(line) # 0 THEN
  1119.             n := leadingSpaces(line)
  1120.         END;
  1121.         PrevLine(line)
  1122.     END;
  1123.     IF n = -1 THEN
  1124.         n := 0
  1125.     END;
  1126.     Lines.insert3(text.curLine, 0, n);
  1127.     SetPos(text, n, text.cursor.Y);
  1128.     resetSelect(text);
  1129.     WHILE n > 0 DO
  1130.         Lines.setChar(text.curLine, n - 1, SPACE);
  1131.         DEC(n)
  1132.     END
  1133. END enter;
  1134.  
  1135.  
  1136. PROCEDURE input* (text: tText; code: INTEGER);
  1137. VAR
  1138.     curLine: tLine;
  1139.  
  1140.     PROCEDURE tab (text: tText);
  1141.     VAR
  1142.         i, x: INTEGER;
  1143.         curLine: tLine;
  1144.     BEGIN
  1145.         delSelect(text);
  1146.         curLine := text.curLine;
  1147.         x := text.cursor.X;
  1148.         Lines.modify(curLine);
  1149.         modify(text);
  1150.         i := TAB - x MOD TAB;
  1151.         Lines.insert3(curLine, x, i);
  1152.         SetPos(text, x + i, text.cursor.Y);
  1153.         WHILE i > 0 DO
  1154.             Lines.setChar(curLine, x + i - 1, SPACE);
  1155.             DEC(i)
  1156.         END
  1157.     END tab;
  1158.  
  1159. BEGIN
  1160.     IF (code >= ORD(SPACE)) & (code # 127) THEN
  1161.         delSelect(text);
  1162.         curLine := text.curLine;
  1163.         Lines.insert(curLine, text.cursor.X, WCHR(code));
  1164.         Lines.modify(curLine);
  1165.         modify(text);
  1166.         SetPos(text, text.cursor.X + 1, text.cursor.Y)
  1167.     ELSIF code = 8 THEN
  1168.         BkSpace(text)
  1169.     ELSIF code = 9 THEN
  1170.         tab(text)
  1171.     ELSIF code = 13 THEN
  1172.         enter(text)
  1173.     END
  1174. END input;
  1175.  
  1176.  
  1177. PROCEDURE scroll* (text: tText; h, v: INTEGER);
  1178. BEGIN
  1179.     INC(text.scroll.X, h);
  1180.     INC(text.scroll.Y, v);
  1181.     text.scroll.X := MIN(MAX(text.scroll.X, 0), Lines.maxLength);
  1182.     text.scroll.Y := MIN(MAX(text.scroll.Y, 0), text.count - 1)
  1183. END scroll;
  1184.  
  1185.  
  1186. PROCEDURE save* (text: tText; name: RW.tFileName; enc, nl: INTEGER): BOOLEAN;
  1187. VAR
  1188.     line: tLine;
  1189.     file: RW.tOutput;
  1190.     res: BOOLEAN;
  1191.     Len: INTEGER;
  1192. (*    item: List.tItem;*)
  1193. BEGIN
  1194.     res := TRUE;
  1195.     file := RW.create(name, enc, nl);
  1196.     IF file # NIL THEN
  1197. (*        IF ChangeLog.Log.last IS ChangeLog.tGuard THEN
  1198.             item := List.pop(ChangeLog.Log);
  1199.             DISPOSE(item)
  1200.         END;*)
  1201.         line := text.first(tLine);
  1202.         WHILE (line # NIL) & res DO
  1203.             Len := Lines.trimLength(line);
  1204.             IF RW.putString(file, line, Len) # Len THEN
  1205.                 res := FALSE
  1206.             END;
  1207.             IF line.modified THEN
  1208.                 Lines.save(line)
  1209.             END;
  1210.             NextLine(line);
  1211.             IF line # NIL THEN
  1212.                 IF ~RW.newLine(file) THEN
  1213.                     res := FALSE
  1214.                 END
  1215.             END
  1216.         END;
  1217.         IF ~RW.close(file) THEN
  1218.             res := FALSE
  1219.         END;
  1220.         IF res THEN
  1221.             text.modified := FALSE
  1222.         END
  1223.     ELSE
  1224.         res := FALSE
  1225.     END;
  1226.     text.guard := TRUE
  1227.     RETURN res
  1228. END save;
  1229.  
  1230.  
  1231. PROCEDURE redoGuard (text: tText; guard: tGuard);
  1232. BEGIN
  1233.     text.edition := guard;
  1234.     text.cursor^ := guard.cursor;
  1235.     text.select2^ := guard.select2;
  1236.     text.scroll := guard.scroll;
  1237.     text.CurX := guard.CurX;
  1238.     IF guard.selected THEN
  1239.         text.select := text.select2
  1240.     ELSE
  1241.         text.select := text.cursor
  1242.     END;
  1243.     text.curLine := getLine(text, text.cursor.Y);
  1244.     text.comments := TRUE;
  1245.     text.search := TRUE
  1246. END redoGuard;
  1247.  
  1248.  
  1249. PROCEDURE undo* (text: tText);
  1250. VAR
  1251.     item: List.tItem;
  1252.     guard: tGuard;
  1253. BEGIN
  1254.     guard := text.edition;
  1255.     item := guard.prev;
  1256.     WHILE (item # NIL) & ~(item IS tGuard) DO
  1257.         item := item.prev
  1258.     END;
  1259.  
  1260.     IF item # NIL THEN
  1261.         guard := item(tGuard);
  1262.         text.edition := guard;
  1263.         text.modified := TRUE
  1264.     END;
  1265.  
  1266.     item := ChangeLog.Log.first;
  1267.     WHILE item # guard DO
  1268.         ChangeLog.redo(item);
  1269.         item := item.next
  1270.     END;
  1271.     redoGuard(text, guard);
  1272.     ChangeLog.setGuard(guard)
  1273. END undo;
  1274.  
  1275.  
  1276. PROCEDURE redo* (text: tText);
  1277. VAR
  1278.     item: List.tItem;
  1279.     guard: tGuard;
  1280. BEGIN
  1281.     guard := text.edition;
  1282.     item := guard.next;
  1283.     WHILE (item # NIL) & ~(item IS tGuard) DO
  1284.         ChangeLog.redo(item);
  1285.         item := item.next
  1286.     END;
  1287.     IF item # NIL THEN
  1288.         guard := item(tGuard);
  1289.         redoGuard(text, guard)
  1290.     END;
  1291.     ChangeLog.setGuard(guard)
  1292. END redo;
  1293.  
  1294.  
  1295. PROCEDURE copy (text: tText);
  1296. VAR
  1297.     selBeg, selEnd: tPoint;
  1298.     first, line: tLine;
  1299.     cnt, n: INTEGER;
  1300.     buffer: CB.tBuffer;
  1301.  
  1302.  
  1303.     PROCEDURE append (buffer: CB.tBuffer; line: tLine; first, last: INTEGER);
  1304.     BEGIN
  1305.         IF first <= last THEN
  1306.             CB.append(buffer, line, first, last)
  1307.         ELSE
  1308.             IF U.OS = "KOS" THEN
  1309.                 CB.appends(buffer, SPACE, 0, 0)
  1310.             END
  1311.         END
  1312.     END append;
  1313.  
  1314.  
  1315. BEGIN
  1316.     getSelect(text, selBeg, selEnd);
  1317.  
  1318.     first := getLine(text, selBeg.Y);
  1319.     line := first;
  1320.  
  1321.     n := selEnd.Y - selBeg.Y;
  1322.     cnt := 0;
  1323.     WHILE n >= 0 DO
  1324.         INC(cnt, line.length + lenEOL);
  1325.         NextLine(line);
  1326.         DEC(n)
  1327.     END;
  1328.  
  1329.     buffer := CB.create(cnt);
  1330.  
  1331.     n := selEnd.Y - selBeg.Y;
  1332.     line := first;
  1333.     IF n = 0 THEN
  1334.         CB.append(buffer, line, selBeg.X, selEnd.X - 1)
  1335.     ELSE
  1336.         append(buffer, line, selBeg.X, line.length - 1);
  1337.         REPEAT
  1338.             DEC(n);
  1339.             CB.eol(buffer);
  1340.             NextLine(line);
  1341.             IF n > 0 THEN
  1342.                 append(buffer, line, 0, line.length - 1)
  1343.             END
  1344.         UNTIL n = 0;
  1345.         append(buffer, line, 0, selEnd.X - 1)
  1346.     END;
  1347.     CB.eot(buffer);
  1348.     CB.put(buffer);
  1349.     CB.destroy(buffer)
  1350. END copy;
  1351.  
  1352.  
  1353. PROCEDURE paste (text: tText);
  1354. VAR
  1355.     line, newLine, curLine: tLine;
  1356.     L: INTEGER;
  1357.     cliptext: RW.tInput;
  1358.     eol: BOOLEAN;
  1359.     cursor: pPoint;
  1360. BEGIN
  1361.     line := Lines.create(TRUE);
  1362.     cliptext := RW.clipboard();
  1363.     delSelect(text);
  1364.     cursor := text.cursor;
  1365.     WHILE (cliptext # NIL) & (RW.getString(cliptext, line, eol) >= 0) DO
  1366.         L := line.length;
  1367.         IF L > 0 THEN
  1368.             Lines.insert2(text.curLine, cursor.X, line);
  1369.             Lines.modify(text.curLine);
  1370.             modify(text);
  1371.             SetPos(text, cursor.X + L, cursor.Y);
  1372.             resetSelect(text)
  1373.         END;
  1374.         IF eol THEN
  1375.             newLine := Lines.create(FALSE);
  1376.             Lines.modify(newLine);
  1377.             modify(text);
  1378.             curLine := text.curLine;
  1379.             IF cursor.X < curLine.length THEN
  1380.                 Lines.modify(curLine);
  1381.                 Lines.wrap(curLine, newLine, cursor.X)
  1382.             END;
  1383.             List._insert(text, curLine, newLine);
  1384.             SetPos(text, 0, cursor.Y + 1);
  1385.             resetSelect(text)
  1386.         END;
  1387.         Lines.destroy(line);
  1388.         line := Lines.create(TRUE)
  1389.     END;
  1390.     Lines.destroy(line);
  1391.     RW.destroy(cliptext)
  1392. END paste;
  1393.  
  1394.  
  1395. PROCEDURE searchScroll (text: tText; n: INTEGER);
  1396. BEGIN
  1397.     IF n - text.scroll.Y > textsize.Y - 1 THEN
  1398.         text.scroll.Y := MAX(n - 2 * textsize.Y DIV 3, 0)
  1399.     ELSIF n < text.scroll.Y THEN
  1400.         text.scroll.Y := MAX(n - textsize.Y DIV 3, 0)
  1401.     END
  1402. END searchScroll;
  1403.  
  1404.  
  1405. PROCEDURE goto* (text: tText; n: INTEGER): BOOLEAN;
  1406. VAR
  1407.     res: BOOLEAN;
  1408. BEGIN
  1409.     DEC(n);
  1410.     IF (0 <= n) & (n < text.count) THEN
  1411.         resetSelect(text);
  1412.         searchScroll(text, n);
  1413.         SetPos(text, 0, n);
  1414.         res := TRUE
  1415.     ELSE
  1416.         res := FALSE
  1417.     END
  1418.     RETURN res
  1419. END goto;
  1420.  
  1421.  
  1422. PROCEDURE changeCase (text: tText; upper: BOOLEAN);
  1423. VAR
  1424.     i: INTEGER;
  1425.     line: tLine;
  1426. BEGIN
  1427.     line := text.curLine;
  1428.     i := text.cursor.X - 1;
  1429.  
  1430.     WHILE (i >= 0) & U.isLetter(getChar(line, i)) DO
  1431.         DEC(i)
  1432.     END;
  1433.  
  1434.     IF Lines.chCase(line, i + 1, text.cursor.X - 1, upper) THEN
  1435.         modify(text)
  1436.     END
  1437. END changeCase;
  1438.  
  1439.  
  1440. PROCEDURE chCase* (text: tText; upper: BOOLEAN);
  1441. VAR
  1442.     selBeg, selEnd: tPoint;
  1443.     first, line: Lines.tLine;
  1444.     cnt: INTEGER;
  1445.     modified: BOOLEAN;
  1446. BEGIN
  1447.     modified := FALSE;
  1448.     IF selected(text) THEN
  1449.         getSelect(text, selBeg, selEnd);
  1450.         first := getLine(text, selBeg.Y);
  1451.         line := first;
  1452.         cnt := selEnd.Y - selBeg.Y;
  1453.         IF cnt = 0 THEN
  1454.             IF Lines.chCase(line, selBeg.X, selEnd.X - 1, upper) THEN
  1455.                 modified := TRUE
  1456.             END
  1457.         ELSE
  1458.             IF Lines.chCase(line, selBeg.X, line.length - 1, upper) THEN
  1459.                 modified := TRUE
  1460.             END;
  1461.             WHILE cnt > 1 DO
  1462.                 NextLine(line);
  1463.                 IF Lines.chCase(line, 0, line.length - 1, upper) THEN
  1464.                     modified := TRUE
  1465.                 END;
  1466.                 DEC(cnt)
  1467.             END;
  1468.             NextLine(line);
  1469.             IF Lines.chCase(line, 0, selEnd.X - 1, upper) THEN
  1470.                 modified := TRUE
  1471.             END
  1472.         END
  1473.     END;
  1474.     IF modified THEN
  1475.         modify(text)
  1476.     END
  1477. END chCase;
  1478.  
  1479.  
  1480. PROCEDURE UpDown (text: tText; step: INTEGER);
  1481. VAR
  1482.     temp: INTEGER;
  1483. BEGIN
  1484.     IF text.CurX = -1 THEN
  1485.         text.CurX := text.cursor.X
  1486.     END;
  1487.     temp := text.CurX;
  1488.     SetPos(text, temp, text.cursor.Y + step);
  1489.     text.CurX := temp
  1490. END UpDown;
  1491.  
  1492.  
  1493. PROCEDURE delLine* (text: tText);
  1494. BEGIN
  1495.     resetSelect(text);
  1496.     IF text.curLine.length > 0 THEN
  1497.         Lines.delCharN(text.curLine, 0, text.curLine.length)
  1498.     END;
  1499.     SetPos(text, 0, text.cursor.Y);
  1500.     IF text.cursor.Y = text.count - 1 THEN
  1501.         BkSpace(text)
  1502.     ELSE
  1503.         delete(text)
  1504.     END
  1505. END delLine;
  1506.  
  1507.  
  1508. PROCEDURE key* (text: tText; code: INTEGER; shift: SET);
  1509. BEGIN
  1510.     IF SHIFT IN shift THEN
  1511.         setSelect(text)
  1512.     ELSE
  1513.         IF (33 <= code) & (code <= 40) THEN
  1514.             resetSelect(text)
  1515.         END
  1516.     END;
  1517.  
  1518.     CASE code OF
  1519.     |33:
  1520.         IF CTRL IN shift THEN
  1521.             UpDown(text, text.scroll.Y - text.cursor.Y)
  1522.         ELSE
  1523.             text.scroll.Y := MAX(text.scroll.Y - textsize.Y, 0);
  1524.             UpDown(text, -textsize.Y)
  1525.         END
  1526.     |34:
  1527.         IF CTRL IN shift THEN
  1528.             UpDown(text, MIN(text.scroll.Y + textsize.Y - 1, text.count - 1) - text.cursor.Y)
  1529.         ELSE
  1530.             text.scroll.Y := MIN(text.scroll.Y + textsize.Y, text.count - 1);
  1531.             UpDown(text, textsize.Y)
  1532.         END
  1533.     |35:
  1534.         IF CTRL IN shift THEN
  1535.             SetPos(text, text.last(tLine).length, text.count - 1)
  1536.         ELSE
  1537.             SetPos(text, text.curLine.length, text.cursor.Y)
  1538.         END
  1539.     |36:
  1540.         IF CTRL IN shift THEN
  1541.             SetPos(text, 0, 0)
  1542.         ELSE
  1543.             SetPos(text, 0, text.cursor.Y)
  1544.         END
  1545.     |37:
  1546.         IF (text.cursor.X = 0) & (text.curLine.prev # NIL) THEN
  1547.             SetPos(text, text.curLine.prev(tLine).length, text.cursor.Y - 1)
  1548.         ELSE
  1549.             SetPos(text, text.cursor.X - 1, text.cursor.Y)
  1550.         END
  1551.     |38:
  1552.         UpDown(text, -1)
  1553.     |39:
  1554.         IF (text.cursor.X = text.curLine.length) & (text.curLine.next # NIL) THEN
  1555.             SetPos(text, 0, text.cursor.Y + 1)
  1556.         ELSE
  1557.             SetPos(text, text.cursor.X + 1, text.cursor.Y)
  1558.         END
  1559.     |40:
  1560.         UpDown(text, 1)
  1561.  
  1562.     |46: delete(text); ShowCursor; drawCursor := TRUE
  1563.  
  1564.     |ORD("C"):
  1565.         IF CTRL IN shift THEN
  1566.             IF selected(text) THEN
  1567.                 copy(text)
  1568.             END
  1569.         END
  1570.     |ORD("X"):
  1571.         IF CTRL IN shift THEN
  1572.             IF selected(text) THEN
  1573.                 copy(text);
  1574.                 delSelect(text)
  1575.             END
  1576.         END
  1577.     |ORD("V"):
  1578.         IF CTRL IN shift THEN
  1579.             IF CB.available() THEN
  1580.                 paste(text)
  1581.             END
  1582.         END
  1583.     |ORD("A"):
  1584.         IF CTRL IN shift THEN
  1585.             text.select2.X := 0;
  1586.             text.select2.Y := 0;
  1587.             text.select := text.select2;
  1588.             SetPos(text, text.last(tLine).length, text.count - 1)
  1589.         END
  1590.     |ORD("L"), ORD("U"):
  1591.         IF CTRL IN shift THEN
  1592.             changeCase(text, code = ORD("U"))
  1593.         END
  1594.     ELSE
  1595.     END
  1596. END key;
  1597.  
  1598.  
  1599. PROCEDURE mouse* (text: tText; x, y: INTEGER);
  1600. VAR
  1601.     cursorX: INTEGER;
  1602. BEGIN
  1603.     DEC(x, padding.left);
  1604.     DEC(y, padding.top);
  1605.     cursorX := (x*2) DIV charWidth;
  1606.     SetPos(text, cursorX DIV 2 + cursorX MOD 2 + text.scroll.X, y DIV charHeight + text.scroll.Y)
  1607. END mouse;
  1608.  
  1609.  
  1610. PROCEDURE selectWord* (text: tText);
  1611. VAR
  1612.     cursorX, x1, x2: INTEGER;
  1613.     line: tLine;
  1614.  
  1615.     PROCEDURE isWordChar (c: WCHAR): BOOLEAN;
  1616.         RETURN U.isLetter(c) OR U.isDigit(c) OR (c = "_")
  1617.     END isWordChar;
  1618.  
  1619. BEGIN
  1620.     resetSelect(text);
  1621.     cursorX := text.cursor.X;
  1622.     line := text.curLine;
  1623.     x1 := cursorX - 1;
  1624.     IF (cursorX < line.length) & isWordChar(getChar(line,cursorX)) THEN
  1625.         x2 := cursorX;
  1626.         WHILE (x2 < line.length) & isWordChar(getChar(line, x2)) DO
  1627.             INC(x2)
  1628.         END
  1629.     ELSE
  1630.         WHILE (x1 >= 0) & ~isWordChar(getChar(line, x1)) DO
  1631.             DEC(x1)
  1632.         END;
  1633.         x2 := x1 + 1
  1634.     END;
  1635.     WHILE (x1 >= 0) & isWordChar(getChar(line, x1)) DO
  1636.         DEC(x1)
  1637.     END;
  1638.     INC(x1);
  1639.     IF x1 < x2 THEN
  1640.         SetPos(text, x1, text.cursor.Y);
  1641.         setSelect(text);
  1642.         SetPos(text, x2, text.cursor.Y)
  1643.     END
  1644. END selectWord;
  1645.  
  1646.  
  1647. PROCEDURE cursor (text: tText);
  1648. VAR
  1649.     x, y, h: INTEGER;
  1650.     cursor: pPoint;
  1651. BEGIN
  1652.     cursor := text.cursor;
  1653.     IF ~((text.scroll.Y > cursor.Y) OR (text.scroll.Y + textsize.Y <= cursor.Y) OR
  1654.        (text.scroll.X > cursor.X) OR (text.scroll.X + textsize.X <= cursor.X)) THEN
  1655.         x := (cursor.X - text.scroll.X)*charWidth + padding.left;
  1656.         y := (cursor.Y - text.scroll.Y)*charHeight + 1 + padding.top;
  1657.         h := charHeight - 2;
  1658.         G.notVLine(canvas, x, y + inter DIV 2, y + h - inter DIV 2);
  1659.         G.notVLine(canvas, x - 1, y + inter DIV 2, y + h - inter DIV 2)
  1660.     END
  1661. END cursor;
  1662.  
  1663.  
  1664. PROCEDURE drawSelect (text: tText; line: tLine; selBeg, selEnd, y: INTEGER);
  1665. VAR
  1666.     Len, pos, x, firstCharIdx: INTEGER;
  1667. BEGIN
  1668.     firstCharIdx := MAX(text.scroll.X, selBeg);
  1669.     Len := MAX(MIN(line.length - firstCharIdx, selEnd - firstCharIdx), 0);
  1670.     Len := MIN(Len, textsize.X - pos + 1);
  1671.     SetColor(colors.seltext, colors.selback);
  1672.     pos := MAX((selBeg - text.scroll.X), 0);
  1673.     x := pos*charWidth + padding.left;
  1674.     G.SetColor(canvas, colors.selback);
  1675.     G.FillRect(canvas, x - 2, y - inter DIV 2, x + 1 + Len*charWidth, y - inter DIV 2 + charHeight);
  1676.     G.TextOut(canvas, pos*charWidth + padding.left, y, Lines.getPChar(line, firstCharIdx), Len)
  1677. END drawSelect;
  1678.  
  1679.  
  1680. PROCEDURE mark (line: tLine; y: INTEGER);
  1681. VAR
  1682.     color, i: INTEGER;
  1683. BEGIN
  1684.     IF line.modified THEN
  1685.         color := colors.modified
  1686.     ELSIF line.saved THEN
  1687.         color := colors.saved
  1688.     ELSE
  1689.         color := colors.back
  1690.     END;
  1691.     G.SetColor(canvas, color);
  1692.  
  1693.     FOR i := 3 TO mark_width + 2 DO
  1694.         G.VLine(canvas, padding.left - i, y, y + charHeight)
  1695.     END
  1696. END mark;
  1697.  
  1698.  
  1699. PROCEDURE setPadding (left, top: INTEGER);
  1700. BEGIN
  1701.     padding.left := left;
  1702.     padding.top := top;
  1703.     textsize.X := (size.X - padding.left) DIV charWidth;
  1704.     textsize.Y := (size.Y - padding.top) DIV charHeight;
  1705. END setPadding;
  1706.  
  1707.  
  1708. PROCEDURE draw* (text: tText);
  1709. VAR
  1710.     y, n, Len, cnt, i, x: INTEGER;
  1711.     line, firstLine, lastLine: tLine;
  1712.     selBeg, selEnd: tPoint;
  1713.     s: ARRAY 12 OF WCHAR;
  1714.     backColor, numWidth, xNum, wNum: INTEGER;
  1715.     p: Search.tPos;
  1716.     guard: tGuard;
  1717. BEGIN
  1718.     IF text.search & search(text, text.searchText, text.cs, text.whole) THEN END;
  1719.     IF (text.lang # Lang.langNone) & text.comments THEN
  1720.         Comments(text)
  1721.     END;
  1722.     IF text.guard THEN
  1723.         NEW(guard);
  1724.         List.append(ChangeLog.Log, guard);
  1725.         text.edition := guard;
  1726.         text.guard := FALSE;
  1727.     ELSE
  1728.         guard := text.edition
  1729.     END;
  1730.  
  1731.     guard.cursor := text.cursor^;
  1732.     guard.select2 := text.select2^;
  1733.     guard.scroll := text.scroll;
  1734.     guard.CurX := text.CurX;
  1735.     guard.selected := text.select = text.select2;
  1736.  
  1737.     G.SetColor(canvas, colors.back);
  1738.     G.clear(canvas);
  1739.     IF text.numbers THEN
  1740.         numWidth := U.lg10(text.count) + 2;
  1741.         wNum := charWidth;
  1742.         xNum := numWidth*wNum - wNum DIV 2;
  1743.         setPadding(numWidth*wNum + pad_left, padding.top);
  1744.     ELSE
  1745.         setPadding(pad_left, padding.top)
  1746.     END;
  1747.     getSelect(text, selBeg, selEnd);
  1748.     y := padding.top + inter DIV 2;
  1749.     n := text.scroll.Y;
  1750.     line := getLine(text, n);
  1751.     firstLine := line;
  1752.     cnt := 0;
  1753.     WHILE (line # NIL) & (cnt <= textsize.Y) DO
  1754.         backColor := colors.back;
  1755.         IF (line = text.curLine) & ~selected(text) THEN
  1756.             G.SetColor(canvas, colors.curline);
  1757.             G.FillRect(canvas, padding.left - 2, y - inter DIV 2, size.X - 1, y - inter DIV 2 + charHeight);
  1758.             backColor := colors.curline
  1759.         END;
  1760.         SetColor(colors.text, backColor);
  1761.         Len := MAX(line.length - text.scroll.X, 0);
  1762.         G.TextOut(canvas, padding.left, y, Lines.getPChar(line, text.scroll.X), MIN(Len, textsize.X + 1));
  1763.         IF text.lang # Lang.langNone THEN
  1764.             parse(text, line, y, backColor, text.lang)
  1765.         END;
  1766.         mark(line, y - inter DIV 2);
  1767.         IF (selBeg.Y < n) & (n < selEnd.Y) THEN
  1768.             drawSelect(text, line, 0, line.length, y)
  1769.         ELSIF (selBeg.Y = n) & (selEnd.Y = n) & (selBeg.X # selEnd.X) THEN
  1770.             drawSelect(text, line, selBeg.X, selEnd.X, y)
  1771.         ELSIF (selBeg.Y = n) & (selEnd.Y # n) THEN
  1772.             drawSelect(text, line, selBeg.X, line.length, y)
  1773.         ELSIF (selBeg.Y # n) & (selEnd.Y = n) THEN
  1774.             drawSelect(text, line, 0, selEnd.X, y)
  1775.         END;
  1776.         NextLine(line);
  1777.         INC(y, charHeight);
  1778.         INC(n);
  1779.         INC(cnt)
  1780.     END;
  1781.     IF text.numbers THEN
  1782.         G.SetColor(canvas, colors.numback);
  1783.         G.FillRect(canvas, 0, 0, padding.left - pad_left (*+ 1*), size.Y - 1);
  1784.         SetColor(colors.numtext, colors.numback);
  1785.         y := padding.top + inter DIV 2;
  1786.         n := MIN(text.scroll.Y + textsize.Y + 1, text.count);
  1787.         FOR i := text.scroll.Y + 1 TO n DO
  1788.             IF (i MOD 10 = 0) OR (i - 1 = text.cursor.Y) THEN
  1789.                 U.int2str(i, s);
  1790.                 G.TextOut2(canvas, (numWidth - U.lg10(i) - 1)*wNum - wNum DIV 2, y, s, LENGTH(s));
  1791.             ELSIF i MOD 5 = 0 THEN
  1792.                 G.SetColor(canvas, colors.numtext);
  1793.                 G.HLine(canvas, y - inter DIV 2 + charHeight DIV 2, xNum - wNum, xNum)
  1794.             ELSE
  1795.                 G.SetColor(canvas, colors.numtext);
  1796.                 G.HLine(canvas, y - inter DIV 2 + charHeight DIV 2, xNum - wNum DIV 2, xNum)
  1797.             END;
  1798.             INC(y, charHeight)
  1799.         END
  1800.     END;
  1801.  
  1802.     IF text.searchText # "" THEN
  1803.         cnt := 0;
  1804.         line := firstLine;
  1805.         lastLine := line;
  1806.         WHILE (line # NIL) & (cnt <= textsize.Y) DO
  1807.             lastLine := line;
  1808.             NextLine(line);
  1809.             INC(cnt)
  1810.         END;
  1811.         p := text.foundList.first(Search.tPos);
  1812.         WHILE p # NIL DO
  1813.             y := padding.top + inter DIV 2;
  1814.             IF (firstLine.pos <= p.pos) & (p.pos <= lastLine.pos + lastLine.length) THEN
  1815.                 line := firstLine;
  1816.                 WHILE (line.pos <= p.pos) & (line # lastLine) DO
  1817.                     NextLine(line);
  1818.                     INC(y, charHeight)
  1819.                 END;
  1820.                 IF (line # lastLine) & (line # firstLine) OR (line = lastLine) & (line.pos > p.pos) THEN
  1821.                     PrevLine(line);
  1822.                     DEC(y, charHeight)
  1823.                 END;
  1824.                 x := (p.pos - line.pos - text.scroll.X)*charWidth + padding.left;
  1825.                 n := LENGTH(text.searchText)*charWidth;
  1826.                 WHILE n > 0 DO
  1827.                     IF x >= padding.left THEN
  1828.                         G.notVLine(canvas, x, y, y + charHeight - inter)
  1829.                     END;
  1830.                     INC(x);
  1831.                     DEC(n)
  1832.                 END;
  1833.             END;
  1834.             p := p.next(Search.tPos)
  1835.         END
  1836.     END;
  1837.  
  1838.     IF text.foundSel > 0 THEN
  1839.         x := (text.cursor.X - text.scroll.X)*charWidth + padding.left;
  1840.         y := (text.cursor.Y - text.scroll.Y)*charHeight + padding.top + inter DIV 2;
  1841.         n := text.foundSel*charWidth;
  1842.         WHILE n > 0 DO
  1843.             IF x >= padding.left THEN
  1844.                 G.xorVLine(canvas, x, y, y + charHeight - inter)
  1845.             END;
  1846.             INC(x);
  1847.             DEC(n)
  1848.         END
  1849.     END;
  1850.  
  1851.     IF drawCursor THEN
  1852.         cursor(text)
  1853.     END;
  1854.     G.SetColor(canvas, colors.border);
  1855.     G.Rect(canvas, 0, 0, size.X - 1, size.Y - 1);
  1856. END draw;
  1857.  
  1858.  
  1859. PROCEDURE create (fileName: RW.tFileName): tText;
  1860. VAR
  1861.     text: tText;
  1862. BEGIN
  1863.     NEW(text);
  1864.     NEW(text.cursor);
  1865.     NEW(text.select2);
  1866.     text.cursor.X := 0;
  1867.     text.cursor.Y := 0;
  1868.     resetSelect(text);
  1869.     text.scroll.X := 0;
  1870.     text.scroll.Y := 0;
  1871.     setPadding(padding.left, padding.top);
  1872.     text.curLine := NIL;
  1873.     text.modified := FALSE;
  1874.     text.comments := TRUE;
  1875.     text.search := TRUE;
  1876.     text.cs := FALSE;
  1877.     text.whole := FALSE;
  1878.     text.numbers := TRUE;
  1879.     text.guard := TRUE;
  1880.     text.idxData := NIL;
  1881.     text.edition := NIL;
  1882.     text.foundList := List.create(NIL);
  1883.     text.searchText := "";
  1884.     text.foundSel := 0;
  1885.     text.CurX := -1;
  1886.     setName(text, fileName);
  1887.     ASSERT(text = List.create(text))
  1888.     RETURN text
  1889. END create;
  1890.  
  1891.  
  1892. PROCEDURE setColors* (text, back, seltext, selback, modified, saved, curline, numtext, numback,
  1893.                         comment, string, num, delim, key1, key2, key3, border: INTEGER);
  1894. BEGIN
  1895.     colors.text := text;
  1896.     colors.back := back;
  1897.     colors.seltext := seltext;
  1898.     colors.selback := selback;
  1899.     colors.modified := modified;
  1900.     colors.saved := saved;
  1901.     colors.curline := curline;
  1902.     colors.numtext := numtext;
  1903.     colors.numback := numback;
  1904.     colors.comment := comment;
  1905.     colors.string  := string;
  1906.     colors.num := num;
  1907.     colors.delim := delim;
  1908.     colors.key1 := key1;
  1909.     colors.key2 := key2;
  1910.     colors.key3 := key3;
  1911.     colors.border := border;
  1912. END setColors;
  1913.  
  1914.  
  1915. PROCEDURE setCanvas* (Canvas: G.tCanvas);
  1916. BEGIN
  1917.     canvas := Canvas;
  1918.     charWidth := canvas.font.width;
  1919.     charHeight := canvas.font.height + inter
  1920. END setCanvas;
  1921.  
  1922.  
  1923. PROCEDURE resize* (width, height: INTEGER);
  1924. BEGIN
  1925.     size.X := width;
  1926.     size.Y := height;
  1927.     setPadding(padding.left, padding.top)
  1928. END resize;
  1929.  
  1930.  
  1931. PROCEDURE destroy* (VAR text: tText);
  1932. BEGIN
  1933.     IF search(text, "", FALSE, FALSE) THEN END;
  1934.     WHILE text.last # NIL DO
  1935.         DelLine(text, text.last(tLine))
  1936.     END;
  1937.     DISPOSE(text.foundList);
  1938.     DISPOSE(text.cursor);
  1939.     DISPOSE(text.select2);
  1940.     DISPOSE(text)
  1941. END destroy;
  1942.  
  1943.  
  1944. PROCEDURE open* (name: RW.tFileName; VAR errno: INTEGER): tText;
  1945. VAR
  1946.     text: tText;
  1947.     file: RW.tInput;
  1948.     n, enc: INTEGER;
  1949.     eol: BOOLEAN;
  1950.     line: tLine;
  1951. BEGIN
  1952.     errno := 0;
  1953.     text := NIL;
  1954.     file := RW.load(name, enc);
  1955.     IF file # NIL THEN
  1956.         text := create(name);
  1957.         text.enc := enc;
  1958.         REPEAT
  1959.             line := Lines.create(FALSE);
  1960.             n := RW.getString(file, line, eol);
  1961.             IF n >= 0 THEN
  1962.                 List._append(text, line)
  1963.             ELSE
  1964.                 Lines.destroy(line)
  1965.             END
  1966.         UNTIL n < 0;
  1967.         RW.destroy(file);
  1968.         IF n = -1 THEN
  1969.             IF text.count = 0 THEN
  1970.                 List._append(text, Lines.create(FALSE))
  1971.             END;
  1972.             text.curLine := text.first(tLine);
  1973.             SetPos(text, 0, 0);
  1974.             resetSelect(text)
  1975.         END
  1976.     ELSE
  1977.         errno := 1
  1978.     END;
  1979.     IF (text # NIL) & (text.lang # Lang.langNone) THEN
  1980.         Comments(text)
  1981.     END
  1982.     RETURN text
  1983. END open;
  1984.  
  1985.  
  1986. PROCEDURE findNext* (text: tText; prev: BOOLEAN): BOOLEAN;
  1987. VAR
  1988.     cursorPos, x, y, X, Y, Len: INTEGER;
  1989.     p: Search.tPos;
  1990.     line: tLine;
  1991.     res: BOOLEAN;
  1992. BEGIN
  1993.     X := text.cursor.X;
  1994.     Y := text.cursor.Y;
  1995.     text.cursor.X := MIN(text.cursor.X, text.curLine.length);
  1996.     cursorPos := text.curLine.pos + text.cursor.X - ORD(prev) - ORD(~prev & (text.foundSel = 0));
  1997.     p := text.foundList.first(Search.tPos);
  1998.     WHILE (p # NIL) & (p.pos <= cursorPos) DO
  1999.         p := p.next(Search.tPos)
  2000.     END;
  2001.     IF prev THEN
  2002.         IF p = NIL THEN
  2003.             p := text.foundList.last(Search.tPos)
  2004.         ELSE
  2005.             p := p.prev(Search.tPos)
  2006.         END
  2007.     END;
  2008.     res := p # NIL;
  2009.     IF res THEN
  2010.         y := 0;
  2011.         line := text.first(tLine);
  2012.         WHILE (line.pos <= p.pos) & (line.next # NIL) DO
  2013.             NextLine(line);
  2014.             INC(y)
  2015.         END;
  2016.         IF (line.next # NIL) OR (line.pos > p.pos) THEN
  2017.             PrevLine(line);
  2018.             DEC(y)
  2019.         END;
  2020.         resetSelect(text);
  2021.         searchScroll(text, y);
  2022.         x := p.pos - line.pos;
  2023.         Len := LENGTH(text.searchText);
  2024.         IF x + Len > text.scroll.X + textsize.X THEN
  2025.             text.scroll.X := MAX(x + Len - textsize.X + 3, 0)
  2026.         ELSIF x < text.scroll.X THEN
  2027.             text.scroll.X := MAX(x - 3, 0)
  2028.         END;
  2029.         SetPos(text, x, y);
  2030.         text.foundSel := Len
  2031.     ELSE
  2032.         SetPos(text, X, Y)
  2033.     END
  2034.     RETURN res
  2035. END findNext;
  2036.  
  2037.  
  2038. PROCEDURE rewrite (line: tLine; repl: ARRAY OF WCHAR; pos, n: INTEGER);
  2039. BEGIN
  2040.     IF n > 0 THEN
  2041.         Lines.copy(line)
  2042.     END;
  2043.     WHILE n > 0 DO
  2044.         DEC(n);
  2045.         Lines.setChar(line, pos + n, repl[n])
  2046.     END
  2047. END rewrite;
  2048.  
  2049.  
  2050. PROCEDURE replace* (text: tText; s: ARRAY OF WCHAR; n: INTEGER);
  2051. VAR
  2052.     line: tLine;
  2053.     sLen, i: INTEGER;
  2054. BEGIN
  2055.     IF text.foundSel > 0 THEN
  2056.         line := text.curLine;
  2057.         sLen := LENGTH(s);
  2058.         i := text.cursor.X;
  2059.         IF sLen > n THEN
  2060.             Lines.insert3(line, i, sLen - n)
  2061.         END;
  2062.         SetPos(text, i + sLen, text.cursor.Y);
  2063.         rewrite(line, s, i, sLen);
  2064.         IF n > sLen THEN
  2065.             Lines.delCharN(line, text.cursor.X, n - sLen)
  2066.         END;
  2067.         resetSelect(text);
  2068.         Lines.modify(line);
  2069.         modify(text)
  2070.     END
  2071. END replace;
  2072.  
  2073.  
  2074. PROCEDURE replaceAll* (text: tText; s: ARRAY OF WCHAR; n: INTEGER): INTEGER;
  2075. VAR
  2076.     p: Search.tPos;
  2077.     line: tLine;
  2078.     y, k, d, pos, y0: INTEGER;
  2079. BEGIN
  2080.     resetSelect(text);
  2081.     SetPos(text, 0, 0);
  2082.     line := text.first(tLine);
  2083.     y := 0;
  2084.     y0 := -1;
  2085.     k := 0;
  2086.     d := LENGTH(s) - n;
  2087.     p := text.foundList.first(Search.tPos);
  2088.     WHILE p # NIL DO
  2089.         pos := p.pos;
  2090.         WHILE (line.pos <= pos) & (line.next # NIL) DO
  2091.             NextLine(line);
  2092.             INC(y)
  2093.         END;
  2094.         IF (line.next # NIL) OR (line.pos > pos) THEN
  2095.             PrevLine(line);
  2096.             DEC(y)
  2097.         END;
  2098.         IF y = y0 THEN
  2099.             INC(k, d)
  2100.         ELSE
  2101.             k := 0;
  2102.             y0 := y
  2103.         END;
  2104.         SetPos(text, pos - line.pos + k, y);
  2105.         text.foundSel := n;
  2106.         replace(text, s, n);
  2107.         p := p.next(Search.tPos)
  2108.     END
  2109.     RETURN text.foundList.count
  2110. END replaceAll;
  2111.  
  2112.  
  2113. PROCEDURE New* (): tText;
  2114. VAR
  2115.     text: tText;
  2116. BEGIN
  2117.     text := create("");
  2118.     List._append(text, Lines.create(FALSE));
  2119.     text.curLine := text.first(tLine);
  2120.     text.enc := E.CP866;
  2121.     SetPos(text, 0, 0);
  2122.     resetSelect(text)
  2123.     RETURN text
  2124. END New;
  2125.  
  2126.  
  2127. PROCEDURE empty;
  2128. END empty;
  2129.  
  2130.  
  2131. PROCEDURE init* (pShowCursor: tProcedure);
  2132. BEGIN
  2133.     ShowCursor := empty;
  2134.     IF pShowCursor # NIL THEN
  2135.         ShowCursor := pShowCursor
  2136.     END;
  2137.     pdelete := delete;
  2138.     drawCursor := TRUE;
  2139.     padding.left := pad_left;
  2140.     padding.top := pad_top;
  2141. END init;
  2142.  
  2143.  
  2144. END Text.