Subversion Repositories Kolibri OS

Rev

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

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