Subversion Repositories Kolibri OS

Rev

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