Subversion Repositories Kolibri OS

Rev

Rev 9902 | 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 ChangeLog;
  21.  
  22. IMPORT List, Lines, API, SYSTEM;
  23.  
  24. CONST
  25.         boolItemSize = 8;
  26.         fillMap = {0..boolItemSize-1};
  27.  
  28. TYPE
  29.         tIntItem = POINTER TO RECORD (List.tItem)
  30.                 cnt: INTEGER;
  31.                 adr, val: ARRAY 8 OF INTEGER
  32.         END;
  33.  
  34.         tBoolItem = POINTER TO RECORD (List.tItem)
  35.                 map: SET;
  36.                 data: ARRAY boolItemSize OF
  37.                         RECORD
  38.                                 line: Lines.tLine;
  39.                                 adr: INTEGER;
  40.                                 val, save: BOOLEAN
  41.                         END
  42.         END;
  43.  
  44.         tUntypedPtr = POINTER TO RECORD (List.tItem)
  45.                 cnt: INTEGER;
  46.                 p: ARRAY 64 OF INTEGER
  47.         END;
  48.  
  49.         tTypedPtr = POINTER TO RECORD (List.tItem)
  50.                 cnt: INTEGER;
  51.                 p: ARRAY 64 OF List.tItem
  52.         END;
  53.  
  54.         tGuard* = POINTER TO RECORD (List.tItem)
  55.                 saved*: BOOLEAN
  56.         END;
  57.  
  58.         tLog* = POINTER TO RECORD
  59.                 Log*, TPointers, UPointers: List.tList;
  60.                 guard, first: tGuard;
  61.                 isLast: BOOLEAN
  62.         END;
  63.  
  64.  
  65. VAR
  66.         CL*: tLog;
  67.  
  68.  
  69. PROCEDURE isLastGuard* (guard: tGuard): BOOLEAN;
  70. VAR
  71.         item: List.tItem;
  72.         res: BOOLEAN;
  73. BEGIN
  74.         IF guard # NIL THEN
  75.                 item := CL.Log.last;
  76.                 WHILE ~(item IS tGuard) DO
  77.                         item := item.prev
  78.                 END;
  79.                 res := guard = item
  80.         ELSE
  81.                 res := TRUE
  82.         END
  83.         RETURN res
  84. END isLastGuard;
  85.  
  86.  
  87. PROCEDURE getFirstGuard (): tGuard;
  88. VAR
  89.         item: List.tItem;
  90. BEGIN
  91.         item := CL.Log.first;
  92.         WHILE ~(item IS tGuard) DO
  93.                 item := item.next
  94.         END
  95.         RETURN item(tGuard)
  96. END getFirstGuard;
  97.  
  98.  
  99. PROCEDURE isFirstGuard* (guard: tGuard): BOOLEAN;
  100. BEGIN
  101.         ASSERT(guard # NIL);
  102.         IF CL.first = NIL THEN
  103.                 CL.first := getFirstGuard()
  104.         END
  105.         RETURN guard = CL.first
  106. END isFirstGuard;
  107.  
  108.  
  109. PROCEDURE setGuard* (_guard: tGuard);
  110. BEGIN
  111.         CL.guard := _guard;
  112.         CL.isLast := isLastGuard(_guard)
  113. END setGuard;
  114.  
  115.  
  116. PROCEDURE redo* (item: List.tItem);
  117. VAR
  118.         i: INTEGER;
  119. BEGIN
  120.         IF item IS tIntItem THEN
  121.                 FOR i := 0 TO item(tIntItem).cnt - 1 DO
  122.                         SYSTEM.PUT(item(tIntItem).adr[i], item(tIntItem).val[i])
  123.                 END
  124.         ELSIF item IS tBoolItem THEN
  125.                 FOR i := 0 TO boolItemSize - 1 DO
  126.                         IF i IN item(tBoolItem).map THEN
  127.                                 SYSTEM.PUT(item(tBoolItem).data[i].adr, item(tBoolItem).data[i].val)
  128.                         END
  129.                 END
  130.         END
  131. END redo;
  132.  
  133.  
  134. PROCEDURE clear (guard: tGuard);
  135. VAR
  136.         item: List.tItem;
  137. BEGIN
  138.         CL.isLast := TRUE;
  139.         REPEAT
  140.                 item := List.pop(CL.Log);
  141.                 IF item # guard THEN
  142.                         DISPOSE(item)
  143.                 END
  144.         UNTIL item = guard;
  145.         List.append(CL.Log, item)
  146. END clear;
  147.  
  148.  
  149. PROCEDURE save* (guard: tGuard);
  150. VAR
  151.         item: List.tItem;
  152.         boolItem: tBoolItem;
  153.         cur: List.tItem;
  154.         i: INTEGER;
  155. BEGIN
  156.         item := CL.Log.first;
  157.         WHILE item # NIL DO
  158.                 IF item IS tGuard THEN
  159.                         item(tGuard).saved := FALSE
  160.                 END;
  161.                 item := item.next
  162.         END;
  163.         guard.saved := TRUE;
  164.  
  165.         cur := CL.guard.prev;
  166.         WHILE cur # NIL DO
  167.                 IF cur IS tBoolItem THEN
  168.                         boolItem := cur(tBoolItem);
  169.                         FOR i := 0 TO boolItemSize - 1 DO
  170.                                 IF (i IN boolItem.map) & boolItem.data[i].save &
  171.                                                 boolItem.data[i].line.modified THEN
  172.                                         EXCL(boolItem.map, i)
  173.                                 END
  174.                         END
  175.                 END;
  176.                 cur := cur.prev;
  177.                 IF boolItem.map = {} THEN
  178.                         List.delete(CL.Log, boolItem);
  179.                         DISPOSE(boolItem)
  180.                 END
  181.         END
  182. END save;
  183.  
  184.  
  185. PROCEDURE changeWord (adrV, adrX: INTEGER);
  186. VAR
  187.         item: tIntItem;
  188.         cur: List.tItem;
  189. BEGIN
  190.         IF ~CL.isLast THEN
  191.                 clear(CL.guard)
  192.         END;
  193.         cur := CL.Log.last;
  194.         WHILE (cur # NIL) & ~(cur IS tGuard) & ~(cur IS tIntItem) DO
  195.                 cur := cur.prev
  196.         END;
  197.         IF (cur IS tIntItem) & (cur(tIntItem).cnt < LEN(cur(tIntItem).adr)) THEN
  198.                 item := cur(tIntItem)
  199.         ELSE
  200.                 NEW(item);
  201.                 item.cnt := 0;
  202.                 List.append(CL.Log, item)
  203.         END;
  204.         item.adr[item.cnt] := adrV;
  205.         SYSTEM.GET(adrX, item.val[item.cnt]);
  206.         INC(item.cnt)
  207. END changeWord;
  208.  
  209.  
  210. PROCEDURE delSaved*;
  211. VAR
  212.         boolItem: tBoolItem;
  213.         cur: List.tItem;
  214.         i: INTEGER;
  215. BEGIN
  216.         cur := CL.guard.next;
  217.         WHILE cur # NIL DO
  218.                 IF cur IS tBoolItem THEN
  219.                         boolItem := cur(tBoolItem);
  220.                         FOR i := 0 TO boolItemSize - 1 DO
  221.                                 IF (i IN boolItem.map) & boolItem.data[i].save THEN
  222.                                         EXCL(boolItem.map, i)
  223.                                 END
  224.                         END
  225.                 END;
  226.                 cur := cur.next;
  227.                 IF boolItem.map = {} THEN
  228.                         List.delete(CL.Log, boolItem);
  229.                         DISPOSE(boolItem)
  230.                 END
  231.         END
  232. END delSaved;
  233.  
  234.  
  235. PROCEDURE delCurSaved*;
  236. VAR
  237.         boolItem: tBoolItem;
  238.         cur: List.tItem;
  239.         i: INTEGER;
  240. BEGIN
  241.         cur := CL.guard.prev;
  242.         WHILE (cur # NIL) & ~(cur IS tGuard) DO
  243.                 IF cur IS tBoolItem THEN
  244.                         boolItem := cur(tBoolItem);
  245.                         FOR i := 0 TO boolItemSize - 1 DO
  246.                                 IF (i IN boolItem.map) & boolItem.data[i].save THEN
  247.                                         SYSTEM.PUT(boolItem.data[i].adr, ~boolItem.data[i].val);
  248.                                         EXCL(boolItem.map, i)
  249.                                 END
  250.                         END
  251.                 END;
  252.                 cur := cur.prev;
  253.                 IF boolItem.map = {} THEN
  254.                         List.delete(CL.Log, boolItem);
  255.                         DISPOSE(boolItem)
  256.                 END
  257.         END
  258. END delCurSaved;
  259.  
  260.  
  261. PROCEDURE _changeBool (fn2: BOOLEAN; line: Lines.tLine; VAR v: BOOLEAN; x: BOOLEAN);
  262. VAR
  263.         item: tBoolItem;
  264.         cur: List.tItem;
  265.         i: INTEGER;
  266. BEGIN
  267.         IF fn2 THEN
  268.                 cur := CL.guard.prev
  269.         ELSE
  270.                 IF ~CL.isLast THEN
  271.                         clear(CL.guard)
  272.                 END;
  273.                 cur := CL.Log.last
  274.         END;
  275.  
  276.         WHILE (cur # NIL) & ~(cur IS tGuard) &
  277.                         (~(cur IS tBoolItem) OR (cur(tBoolItem).map = fillMap)) DO
  278.                 cur := cur.prev
  279.         END;
  280.         IF (cur IS tBoolItem) & (cur(tBoolItem).map # fillMap) THEN
  281.                 item := cur(tBoolItem)
  282.         ELSE
  283.                 NEW(item);
  284.                 item.map := {};
  285.                 IF fn2 THEN
  286.                         List.insert(CL.Log, CL.guard.prev, item)
  287.                 ELSE
  288.                         List.append(CL.Log, item)
  289.                 END
  290.         END;
  291.  
  292.         i := 0;
  293.         WHILE i < boolItemSize DO
  294.                 IF ~(i IN item.map) THEN
  295.                         item.data[i].line := line;
  296.                         item.data[i].adr := SYSTEM.ADR(v);
  297.                         item.data[i].val := x;
  298.                         item.data[i].save := fn2;
  299.                         INCL(item.map, i);
  300.                         i := boolItemSize
  301.                 END;
  302.                 INC(i)
  303.         END
  304. END _changeBool;
  305.  
  306.  
  307. PROCEDURE changeBool (line: Lines.tLine; VAR v: BOOLEAN; x: BOOLEAN);
  308. BEGIN
  309.         _changeBool(FALSE, line, v, x)
  310. END changeBool;
  311.  
  312.  
  313. PROCEDURE changeBool2 (line: Lines.tLine; VAR v: BOOLEAN; x: BOOLEAN);
  314. BEGIN
  315.         _changeBool(TRUE, line, v, x)
  316. END changeBool2;
  317.  
  318.  
  319. PROCEDURE changeInt* (VAR v: INTEGER; x: INTEGER);
  320. BEGIN
  321.         changeWord(SYSTEM.ADR(v), SYSTEM.ADR(x))
  322. END changeInt;
  323.  
  324.  
  325. PROCEDURE changePtr (VAR v: List.tItem; x: List.tItem);
  326. BEGIN
  327.         changeWord(SYSTEM.ADR(v), SYSTEM.ADR(x))
  328. END changePtr;
  329.  
  330.  
  331. PROCEDURE typedPtr (p: List.tItem);
  332. VAR
  333.         item: tTypedPtr;
  334. BEGIN
  335.         item := CL.TPointers.last(tTypedPtr);
  336.         IF (item = NIL) OR (item.cnt = LEN(item.p)) THEN
  337.                 NEW(item);
  338.                 item.cnt := 0;
  339.                 List.append(CL.TPointers, item)
  340.         END;
  341.         item.p[item.cnt] := p;
  342.         INC(item.cnt)
  343. END typedPtr;
  344.  
  345.  
  346. PROCEDURE untypedPtr (p: INTEGER);
  347. VAR
  348.         item: tUntypedPtr;
  349. BEGIN
  350.         item := CL.UPointers.last(tUntypedPtr);
  351.         IF (item = NIL) OR (item.cnt = LEN(item.p)) THEN
  352.                 NEW(item);
  353.                 item.cnt := 0;
  354.                 List.append(CL.UPointers, item)
  355.         END;
  356.         item.p[item.cnt] := p;
  357.         INC(item.cnt)
  358. END untypedPtr;
  359.  
  360.  
  361. PROCEDURE setLog* (_CL: tLog);
  362. BEGIN
  363.         CL := _CL
  364. END setLog;
  365.  
  366.  
  367. PROCEDURE create* (VAR maxLength: INTEGER): tLog;
  368. VAR
  369.         newLog: tLog;
  370. BEGIN
  371.         NEW(newLog);
  372.         newLog.guard := NIL;
  373.         newLog.first := NIL;
  374.         newLog.isLast := TRUE;
  375.         newLog.Log := List.create(NIL);
  376.         newLog.TPointers := List.create(NIL);
  377.         newLog.UPointers := List.create(NIL);
  378.         CL := newLog;
  379.         Lines.setMaxLength(maxLength)
  380.         RETURN newLog
  381. END create;
  382.  
  383.  
  384. PROCEDURE destroy* (VAR log: tLog);
  385. VAR
  386.         item: List.tItem;
  387.         res, i: INTEGER;
  388. BEGIN
  389.         IF log # NIL THEN
  390.                 item := List.pop(log.Log);
  391.                 WHILE item # NIL DO
  392.                         DISPOSE(item);
  393.                         item := List.pop(log.Log)
  394.                 END;
  395.                 DISPOSE(log.Log);
  396.  
  397.                 item := List.pop(log.TPointers);
  398.                 WHILE item # NIL DO
  399.                         FOR i := 0 TO item(tTypedPtr).cnt - 1 DO
  400.                                 DISPOSE(item(tTypedPtr).p[i])
  401.                         END;
  402.                         DISPOSE(item);
  403.                         item := List.pop(log.TPointers)
  404.                 END;
  405.                 DISPOSE(log.TPointers);
  406.  
  407.                 item := List.pop(log.UPointers);
  408.                 WHILE item # NIL DO
  409.                         FOR i := 0 TO item(tUntypedPtr).cnt - 1 DO
  410.                                 res := API._DISPOSE(item(tUntypedPtr).p[i])
  411.                         END;
  412.                         DISPOSE(item);
  413.                         item := List.pop(log.UPointers)
  414.                 END;
  415.                 DISPOSE(log.UPointers);
  416.  
  417.                 DISPOSE(log)
  418.         END
  419. END destroy;
  420.  
  421.  
  422. BEGIN
  423.         List.init(changeInt, changePtr);
  424.         Lines.init(changeInt, changePtr, changeBool, changeBool2, typedPtr, untypedPtr)
  425. END ChangeLog.