Subversion Repositories Kolibri OS

Rev

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

  1. (*
  2.     Copyright 2021-2023 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 Lines;
  21.  
  22. IMPORT
  23.     List, SYSTEM, API, Utils;
  24.  
  25. CONST
  26.     WCHAR_SIZE = 2;
  27.     SPACE* = 20X;
  28.     TAB* = 9X;
  29.     NUL* = 0FDD0X;
  30.     TAB1* = 0FDD1X;
  31.     MAX_TAB_WIDTH* = 16;
  32.  
  33. TYPE
  34.  
  35.     tLine* = POINTER TO RECORD (List.tItem)
  36.         ptr: INTEGER;
  37.         length*: INTEGER;
  38.         modified*, saved*, temp, label*: BOOLEAN;
  39.         cin*, cout*, pos*: INTEGER
  40.     END;
  41.  
  42.     PmovInt = PROCEDURE (VAR v: INTEGER; x: INTEGER);
  43.     PmovBool = PROCEDURE (save: BOOLEAN; VAR v1: BOOLEAN; x1: BOOLEAN; VAR v2: BOOLEAN; x2: BOOLEAN);
  44.     PmovPtr = PROCEDURE (VAR v: List.tItem; x: List.tItem);
  45.  
  46.     PTypedPtr = PROCEDURE (p: List.tItem);
  47.     PUntypedPtr = PROCEDURE (p: INTEGER);
  48.  
  49.     tVector* = POINTER TO RECORD
  50.         size, data: INTEGER
  51.     END;
  52.  
  53.     tVectorItem = tLine;
  54.  
  55.     fConvert* = PROCEDURE (VAR c: WCHAR): BOOLEAN;
  56.  
  57.  
  58. VAR
  59.  
  60.     _movInt: PmovInt;
  61.     _movBool: PmovBool;
  62.     _movPtr: PmovPtr;
  63.     _typedPtr: PTypedPtr;
  64.     _untypedPtr: PUntypedPtr;
  65.  
  66.     pMaxLength, tab*: INTEGER;
  67.     tabs*: BOOLEAN;
  68.  
  69.  
  70. PROCEDURE createVector* (size: INTEGER): tVector;
  71. VAR
  72.         res: tVector;
  73. BEGIN
  74.         IF size > 0 THEN
  75.                 NEW(res);
  76.                 res.size := size;
  77.                 IF size < 4096 THEN
  78.                         size := 4096
  79.                 END;
  80.                 res.data := API._NEW(size*SYSTEM.SIZE(tVectorItem));
  81.                 IF res.data = 0 THEN
  82.                         DISPOSE(res)
  83.                 END
  84.         ELSE
  85.                 res := NIL
  86.         END
  87.         RETURN res
  88. END createVector;
  89.  
  90.  
  91. PROCEDURE destroyVector* (VAR vector: tVector);
  92. BEGIN
  93.         IF vector # NIL THEN
  94.                 IF vector.data # 0 THEN
  95.                         vector.data := API._DISPOSE(vector.data)
  96.                 END;
  97.                 DISPOSE(vector)
  98.         END
  99. END destroyVector;
  100.  
  101.  
  102. PROCEDURE setVectorItem* (vector: tVector; idx: INTEGER; item: tVectorItem);
  103. BEGIN
  104.         ASSERT(vector # NIL);
  105.         ASSERT((0 <= idx) & (idx < vector.size));
  106.         SYSTEM.PUT(vector.data + idx*SYSTEM.SIZE(tVectorItem), item)
  107. END setVectorItem;
  108.  
  109.  
  110. PROCEDURE getVectorItem* (vector: tVector; idx: INTEGER): tVectorItem;
  111. VAR
  112.         res: tVectorItem;
  113. BEGIN
  114.         ASSERT(vector # NIL);
  115.         ASSERT((0 <= idx) & (idx < vector.size));
  116.         SYSTEM.GET(vector.data + idx*SYSTEM.SIZE(tVectorItem), res)
  117.         RETURN res
  118. END getVectorItem;
  119.  
  120.  
  121. PROCEDURE movInt (VAR v: INTEGER; x: INTEGER);
  122. BEGIN
  123.     _movInt(v, x)
  124. END movInt;
  125.  
  126.  
  127. PROCEDURE movPtr (VAR v: List.tItem; x: List.tItem);
  128. BEGIN
  129.     _movPtr(v, x)
  130. END movPtr;
  131.  
  132.  
  133. PROCEDURE malloc (size: INTEGER): INTEGER;
  134. VAR
  135.     maxLength: INTEGER;
  136. BEGIN
  137.     ASSERT(pMaxLength # 0);
  138.     SYSTEM.GET(pMaxLength, maxLength);
  139.     IF size > maxLength THEN
  140.         SYSTEM.PUT(pMaxLength, size)
  141.     END;
  142.     size := size*WCHAR_SIZE + 4;
  143.     INC(size, (-size) MOD 32)
  144.     RETURN API._NEW(size)
  145. END malloc;
  146.  
  147.  
  148. PROCEDURE free (line: tLine; newPtr: INTEGER);
  149. BEGIN
  150.     IF line.ptr # 0 THEN
  151.         IF line.temp THEN
  152.             line.ptr := API._DISPOSE(line.ptr)
  153.         ELSE
  154.             line.ptr := 0
  155.         END
  156.     END;
  157.     IF ~line.temp THEN
  158.         movInt(line.ptr, newPtr);
  159.         IF newPtr # 0 THEN
  160.             _untypedPtr(newPtr)
  161.         END
  162.     END;
  163.     line.ptr := newPtr
  164. END free;
  165.  
  166.  
  167. PROCEDURE create* (temp: BOOLEAN): tLine;
  168. VAR
  169.     line: tLine;
  170. BEGIN
  171.     NEW(line);
  172.     line.label := FALSE;
  173.     ASSERT(line # NIL);
  174.     IF ~temp THEN
  175.         _typedPtr(line)
  176.     END;
  177.     line.next := NIL;
  178.     line.prev := NIL;
  179.     IF ~temp THEN
  180.         movPtr(line.next, NIL);
  181.         movPtr(line.prev, NIL)
  182.     END;
  183.     line.ptr := malloc(1);
  184.     ASSERT(line.ptr # 0);
  185.     IF ~temp THEN
  186.         _untypedPtr(line.ptr);
  187.         movInt(line.ptr, line.ptr)
  188.     END;
  189.     SYSTEM.PUT16(line.ptr, 0);
  190.     line.length := 0;
  191.     IF ~temp THEN
  192.         movInt(line.length, 0)
  193.     END;
  194.     line.temp := temp;
  195.     line.modified := FALSE;
  196.     line.saved := FALSE;
  197.     IF ~temp THEN
  198.         _movBool(FALSE, line.modified, FALSE, line.saved, FALSE)
  199.     END;
  200.     line.cin := 0;
  201.     line.cout := 0;
  202.     line.pos := 0
  203.     RETURN line
  204. END create;
  205.  
  206.  
  207. PROCEDURE destroy* (VAR line: tLine);
  208. BEGIN
  209.     IF line.temp THEN
  210.         free(line, 0);
  211.         DISPOSE(line)
  212.     ELSE
  213.         line := NIL
  214.     END
  215. END destroy;
  216.  
  217.  
  218. PROCEDURE resize* (line: tLine; size: INTEGER);
  219. BEGIN
  220.         ASSERT(line.temp);
  221.         IF size > 0 THEN
  222.                 line.ptr := API._DISPOSE(line.ptr);
  223.                 size := size*WCHAR_SIZE + 4;
  224.                 INC(size, (-size) MOD 32);
  225.                 line.ptr := API._NEW(size)
  226.         ELSE
  227.                 destroy(line)
  228.         END
  229. END resize;
  230.  
  231.  
  232. PROCEDURE getChar* (line: tLine; i: INTEGER): WCHAR;
  233. VAR
  234.     res: WCHAR;
  235. BEGIN
  236.     IF i >= line.length THEN
  237.         res := 0X
  238.     ELSE
  239.         SYSTEM.GET(line.ptr + i*WCHAR_SIZE, res)
  240.     END
  241.     RETURN res
  242. END getChar;
  243.  
  244.  
  245. PROCEDURE tabWidth (line: tLine; pos: INTEGER): INTEGER;
  246. VAR
  247.     n: INTEGER;
  248. BEGIN
  249.     n := pos;
  250.     IF getChar(line, pos) = TAB THEN
  251.         INC(pos);
  252.         WHILE getChar(line, pos) = TAB1 DO
  253.             INC(pos)
  254.         END
  255.     END
  256.     RETURN pos - n
  257. END tabWidth;
  258.  
  259.  
  260. PROCEDURE save* (line: tLine);
  261. BEGIN
  262.     IF ~line.temp THEN
  263.         _movBool(TRUE, line.modified, FALSE, line.saved, TRUE)
  264.     END;
  265.     line.modified := FALSE;
  266.     line.saved := TRUE
  267. END save;
  268.  
  269.  
  270. PROCEDURE isSpace* (c: WCHAR): BOOLEAN;
  271.     RETURN (c = SPACE) OR (c = TAB) OR (c = TAB1)
  272. END isSpace;
  273.  
  274.  
  275. PROCEDURE trimLength* (line: tLine): INTEGER;
  276. VAR
  277.     i: INTEGER;
  278. BEGIN
  279.     i := line.length - 1;
  280.     WHILE (i >= 0) & isSpace(getChar(line, i)) DO
  281.         DEC(i)
  282.     END
  283.     RETURN i + 1
  284. END trimLength;
  285.  
  286.  
  287. PROCEDURE getPChar* (line: tLine; i: INTEGER): INTEGER;
  288.     RETURN line.ptr + i*WCHAR_SIZE
  289. END getPChar;
  290.  
  291.  
  292. PROCEDURE setChar* (line: tLine; i: INTEGER; c: WCHAR);
  293. BEGIN
  294.     SYSTEM.PUT(line.ptr + i*WCHAR_SIZE, c)
  295. END setChar;
  296.  
  297.  
  298. PROCEDURE move* (src, dst: tLine);
  299. BEGIN
  300.     SYSTEM.MOVE(src.ptr, dst.ptr, (MIN(src.length, dst.length) + 1)*WCHAR_SIZE)
  301. END move;
  302.  
  303.  
  304. PROCEDURE delChar* (line: tLine; pos: INTEGER);
  305. VAR
  306.     ptr: INTEGER;
  307. BEGIN
  308.     IF pos < line.length THEN
  309.         ptr := malloc(line.length);
  310.         ASSERT(ptr # 0);
  311.         IF ~line.temp THEN
  312.             movInt(line.length, line.length - 1)
  313.         END;
  314.         DEC(line.length);
  315.         SYSTEM.MOVE(line.ptr, ptr, pos*WCHAR_SIZE);
  316.         SYSTEM.MOVE(line.ptr + pos*WCHAR_SIZE + WCHAR_SIZE, ptr + pos*WCHAR_SIZE, (line.length - pos)*WCHAR_SIZE);
  317.         SYSTEM.PUT16(ptr + line.length*WCHAR_SIZE, 0);
  318.         free(line, ptr)
  319.     END
  320. END delChar;
  321.  
  322.  
  323. PROCEDURE insert* (line: tLine; pos: INTEGER; c: WCHAR);
  324. VAR
  325.     ptr: INTEGER;
  326. BEGIN
  327.     ptr := malloc(line.length + 2);
  328.     ASSERT(ptr # 0);
  329.     SYSTEM.MOVE(line.ptr, ptr, pos*WCHAR_SIZE);
  330.     SYSTEM.PUT(ptr + pos*WCHAR_SIZE, c);
  331.     SYSTEM.MOVE(line.ptr + pos*WCHAR_SIZE, ptr + pos*WCHAR_SIZE + WCHAR_SIZE, (line.length - pos)*WCHAR_SIZE);
  332.     IF ~line.temp THEN
  333.         movInt(line.length, line.length + 1)
  334.     END;
  335.     INC(line.length);
  336.     SYSTEM.PUT16(ptr + line.length*WCHAR_SIZE, 0);
  337.     free(line, ptr)
  338. END insert;
  339.  
  340.  
  341. PROCEDURE _insert2* (line1: tLine; pos: INTEGER; line2: tLine);
  342. VAR
  343.     ptr: INTEGER;
  344. BEGIN
  345.     IF line2.length > 0 THEN
  346.         ptr := malloc(line1.length + line2.length + 1);
  347.         ASSERT(ptr # 0);
  348.         SYSTEM.MOVE(line1.ptr, ptr, pos*WCHAR_SIZE);
  349.         SYSTEM.MOVE(line2.ptr, ptr + pos*WCHAR_SIZE, line2.length*WCHAR_SIZE);
  350.         SYSTEM.MOVE(line1.ptr + pos*WCHAR_SIZE, ptr + (pos + line2.length)*WCHAR_SIZE, (line1.length - pos)*WCHAR_SIZE);
  351.         SYSTEM.PUT16(ptr + (line1.length + line2.length)*WCHAR_SIZE, 0);
  352.         IF ~line1.temp THEN
  353.             movInt(line1.length, line1.length + line2.length)
  354.         END;
  355.         IF ~line2.temp THEN
  356.             movInt(line2.length, 0)
  357.         END;
  358.         INC(line1.length, line2.length);
  359.         free(line1, ptr)
  360.     END
  361. END _insert2;
  362.  
  363.  
  364. PROCEDURE insert2* (line1: tLine; pos: INTEGER; line2: tLine);
  365. BEGIN
  366.         _insert2(line1, pos, line2);
  367.         IF line2.length > 0 THEN
  368.                 line2.length := 0;
  369.                 free(line2, 0)
  370.         END
  371. END insert2;
  372.  
  373.  
  374. PROCEDURE insert3* (line: tLine; pos, n: INTEGER);
  375. VAR
  376.     ptr: INTEGER;
  377. BEGIN
  378.     IF n > 0 THEN
  379.         ptr := malloc(line.length + n + 1);
  380.         ASSERT(ptr # 0);
  381.         SYSTEM.MOVE(line.ptr, ptr, pos*WCHAR_SIZE);
  382.         SYSTEM.MOVE(line.ptr + pos*WCHAR_SIZE, ptr + (pos + n)*WCHAR_SIZE, (line.length - pos)*WCHAR_SIZE);
  383.         SYSTEM.PUT16(ptr + (line.length + n)*WCHAR_SIZE, 0);
  384.         IF ~line.temp THEN
  385.             movInt(line.length, line.length + n)
  386.         END;
  387.         INC(line.length, n);
  388.         free(line, ptr)
  389.     END
  390. END insert3;
  391.  
  392.  
  393. PROCEDURE delCharN* (line: tLine; pos, n: INTEGER);
  394. VAR
  395.     ptr: INTEGER;
  396. BEGIN
  397.     IF n > 0 THEN
  398.         ptr := malloc(line.length - n + 1);
  399.         ASSERT(ptr # 0);
  400.         SYSTEM.MOVE(line.ptr, ptr, pos*WCHAR_SIZE);
  401.         SYSTEM.MOVE(line.ptr + (pos + n)*WCHAR_SIZE, ptr + pos*WCHAR_SIZE, (line.length - pos - n)*WCHAR_SIZE);
  402.         SYSTEM.PUT16(ptr + (line.length - n)*WCHAR_SIZE, 0);
  403.         IF ~line.temp THEN
  404.             movInt(line.length, line.length - n)
  405.         END;
  406.         DEC(line.length, n);
  407.         free(line, ptr)
  408.     END
  409. END delCharN;
  410.  
  411.  
  412. PROCEDURE fixTabs (line: tLine);
  413. VAR
  414.     i, n, k: INTEGER;
  415. BEGIN
  416.     i := 0;
  417.     WHILE i < line.length DO
  418.         n := tabWidth(line, i);
  419.         IF n # 0 THEN
  420.             k := tab - i MOD tab;
  421.             IF n > k THEN
  422.                 delCharN(line, i + 1, n - k)
  423.             ELSIF n < k THEN
  424.                 DEC(k, n);
  425.                 insert3(line, i + 1, k);
  426.                 WHILE k > 0 DO
  427.                     setChar(line, i + 1, TAB1);
  428.                     INC(i);
  429.                     DEC(k)
  430.                 END
  431.             END
  432.         END;
  433.         INC(i)
  434.     END
  435. END fixTabs;
  436.  
  437.  
  438. PROCEDURE modify* (line: tLine);
  439. BEGIN
  440.     IF ~line.temp THEN
  441.         _movBool(FALSE, line.modified, TRUE, line.saved, FALSE)
  442.     END;
  443.     line.modified := TRUE;
  444.     line.saved := FALSE;
  445.     fixTabs(line)
  446. END modify;
  447.  
  448.  
  449. PROCEDURE wrap* (line, nextLine: tLine; pos: INTEGER);
  450. VAR
  451.     ptr1, ptr2: INTEGER;
  452.     n: INTEGER;
  453. BEGIN
  454.     ptr1 := malloc(pos + 1);
  455.     ASSERT(ptr1 # 0);
  456.     n := line.length - pos;
  457.     ptr2 := malloc(n + 1);
  458.     ASSERT(ptr2 # 0);
  459.     SYSTEM.MOVE(line.ptr, ptr1, pos*WCHAR_SIZE);
  460.     SYSTEM.PUT16(ptr1 + pos*WCHAR_SIZE, 0);
  461.     SYSTEM.MOVE(line.ptr + pos*WCHAR_SIZE, ptr2, n*WCHAR_SIZE);
  462.     SYSTEM.PUT16(ptr2 + n*WCHAR_SIZE, 0);
  463.     IF ~line.temp THEN
  464.         movInt(line.length, pos)
  465.     END;
  466.     IF ~nextLine.temp THEN
  467.         movInt(nextLine.length, n)
  468.     END;
  469.     line.length := pos;
  470.     nextLine.length := n;
  471.     free(line, ptr1);
  472.     free(nextLine, ptr2)
  473. END wrap;
  474.  
  475.  
  476. PROCEDURE copy* (line: tLine);
  477. VAR
  478.     ptr: INTEGER;
  479. BEGIN
  480.     ptr := malloc(line.length + 1);
  481.     ASSERT(ptr # 0);
  482.     SYSTEM.MOVE(line.ptr, ptr, line.length*WCHAR_SIZE);
  483.     SYSTEM.PUT16(ptr + line.length*WCHAR_SIZE, 0);
  484.     free(line, ptr)
  485. END copy;
  486.  
  487.  
  488. PROCEDURE convert* (line: tLine; pos1, pos2: INTEGER; func: fConvert): BOOLEAN;
  489. VAR
  490.     i: INTEGER;
  491.     modified: BOOLEAN;
  492.     c: WCHAR;
  493. BEGIN
  494.         ASSERT(func # NIL);
  495.     modified := FALSE;
  496.     i := pos2;
  497.     WHILE i >= pos1 DO
  498.         c := getChar(line, i);
  499.         IF func(c) THEN
  500.             modified := TRUE
  501.         END;
  502.         DEC(i)
  503.     END;
  504.  
  505.     IF modified THEN
  506.         copy(line);
  507.         i := pos2;
  508.         WHILE i >= pos1 DO
  509.             c := getChar(line, i);
  510.             IF func(c) THEN
  511.                 setChar(line, i, c)
  512.             END;
  513.             DEC(i)
  514.         END;
  515.         modify(line)
  516.     END
  517.     RETURN modified
  518. END convert;
  519.  
  520.  
  521. PROCEDURE init* (movInt: PmovInt; movPtr: PmovPtr; movBool: PmovBool; typedPtr: PTypedPtr; untypedPtr: PUntypedPtr);
  522. BEGIN
  523.     _movInt := movInt;
  524.     _movPtr := movPtr;
  525.     _movBool := movBool;
  526.     _typedPtr := typedPtr;
  527.     _untypedPtr := untypedPtr;
  528. END init;
  529.  
  530.  
  531. PROCEDURE setMaxLength* (VAR maxLength: INTEGER);
  532. BEGIN
  533.     pMaxLength := SYSTEM.ADR(maxLength)
  534. END setMaxLength;
  535.  
  536.  
  537. PROCEDURE setTabs* (_tab: INTEGER);
  538. BEGIN
  539.     IF _tab = 0 THEN
  540.         _tab := 4
  541.     END;
  542.     tabs := _tab > 0;
  543.     tab := ABS(_tab);
  544.     IF tab > MAX_TAB_WIDTH THEN
  545.         tab := MAX_TAB_WIDTH
  546.     END
  547. END setTabs;
  548.  
  549.  
  550. BEGIN
  551.     pMaxLength := 0
  552. END Lines.