Subversion Repositories Kolibri OS

Rev

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