Subversion Repositories Kolibri OS

Rev

Rev 9902 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
8728 leency 1
(*
9902 akron1 2
    Copyright 2021-2023 Anton Krotov
8728 leency 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 .
18
*)
19
 
20
MODULE ChangeLog;
21
 
9448 akron1 22
IMPORT List, Lines, API, SYSTEM;
8728 leency 23
 
9903 akron1 24
CONST
25
	boolItemSize = 8;
26
	fillMap = {0..boolItemSize-1};
27
 
8728 leency 28
TYPE
9903 akron1 29
	tIntItem = POINTER TO RECORD (List.tItem)
30
		cnt: INTEGER;
31
		adr, val: ARRAY 8 OF INTEGER
32
	END;
8728 leency 33
 
9903 akron1 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;
9448 akron1 43
 
9903 akron1 44
	tUntypedPtr = POINTER TO RECORD (List.tItem)
45
		cnt: INTEGER;
46
		p: ARRAY 64 OF INTEGER
47
	END;
8728 leency 48
 
9903 akron1 49
	tTypedPtr = POINTER TO RECORD (List.tItem)
50
		cnt: INTEGER;
51
		p: ARRAY 64 OF List.tItem
52
	END;
9448 akron1 53
 
9903 akron1 54
	tGuard* = POINTER TO RECORD (List.tItem)
55
		saved*: BOOLEAN
56
	END;
8728 leency 57
 
9903 akron1 58
	tLog* = POINTER TO RECORD
59
		Log*, TPointers, UPointers: List.tList;
60
		guard, first: tGuard;
61
		isLast: BOOLEAN
62
	END;
8728 leency 63
 
9050 leency 64
 
8728 leency 65
VAR
9903 akron1 66
	CL*: tLog;
8728 leency 67
 
68
 
69
PROCEDURE isLastGuard* (guard: tGuard): BOOLEAN;
70
VAR
9903 akron1 71
	item: List.tItem;
72
	res: BOOLEAN;
8728 leency 73
BEGIN
9903 akron1 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
8728 leency 84
END isLastGuard;
85
 
86
 
9668 akron1 87
PROCEDURE getFirstGuard (): tGuard;
8728 leency 88
VAR
9668 akron1 89
	item: List.tItem;
8728 leency 90
BEGIN
9668 akron1 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
8728 leency 106
END isFirstGuard;
107
 
108
 
109
PROCEDURE setGuard* (_guard: tGuard);
110
BEGIN
9903 akron1 111
	CL.guard := _guard;
112
	CL.isLast := isLastGuard(_guard)
8728 leency 113
END setGuard;
114
 
115
 
116
PROCEDURE redo* (item: List.tItem);
9902 akron1 117
VAR
118
	i: INTEGER;
8728 leency 119
BEGIN
9902 akron1 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
9903 akron1 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
9902 akron1 130
	END
8728 leency 131
END redo;
132
 
133
 
134
PROCEDURE clear (guard: tGuard);
135
VAR
9903 akron1 136
	item: List.tItem;
8728 leency 137
BEGIN
9903 akron1 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)
8728 leency 146
END clear;
147
 
148
 
9073 leency 149
PROCEDURE save* (guard: tGuard);
150
VAR
9452 akron1 151
	item: List.tItem;
152
	boolItem: tBoolItem;
153
	cur: List.tItem;
9903 akron1 154
	i: INTEGER;
9073 leency 155
BEGIN
9903 akron1 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;
9452 akron1 164
 
9903 akron1 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
9073 leency 182
END save;
183
 
184
 
8728 leency 185
PROCEDURE changeWord (adrV, adrX: INTEGER);
186
VAR
9902 akron1 187
	item: tIntItem;
188
	cur: List.tItem;
8728 leency 189
BEGIN
9902 akron1 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)
8728 leency 207
END changeWord;
208
 
209
 
9073 leency 210
PROCEDURE delSaved*;
211
VAR
9903 akron1 212
	boolItem: tBoolItem;
213
	cur: List.tItem;
214
	i: INTEGER;
9073 leency 215
BEGIN
9903 akron1 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
9073 leency 232
END delSaved;
233
 
234
 
235
PROCEDURE delCurSaved*;
236
VAR
9903 akron1 237
	boolItem: tBoolItem;
238
	cur: List.tItem;
239
	i: INTEGER;
9073 leency 240
BEGIN
9903 akron1 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
9073 leency 258
END delCurSaved;
259
 
260
 
9903 akron1 261
PROCEDURE _changeBool (fn2: BOOLEAN; line: Lines.tLine; VAR v: BOOLEAN; x: BOOLEAN);
9073 leency 262
VAR
9903 akron1 263
	item: tBoolItem;
264
	cur: List.tItem;
265
	i: INTEGER;
9073 leency 266
BEGIN
9903 akron1 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)
9073 leency 316
END changeBool2;
317
 
318
 
9336 akron1 319
PROCEDURE changeInt* (VAR v: INTEGER; x: INTEGER);
8728 leency 320
BEGIN
9903 akron1 321
	changeWord(SYSTEM.ADR(v), SYSTEM.ADR(x))
8728 leency 322
END changeInt;
323
 
324
 
325
PROCEDURE changePtr (VAR v: List.tItem; x: List.tItem);
326
BEGIN
9903 akron1 327
	changeWord(SYSTEM.ADR(v), SYSTEM.ADR(x))
8728 leency 328
END changePtr;
329
 
9448 akron1 330
 
8728 leency 331
PROCEDURE typedPtr (p: List.tItem);
332
VAR
9902 akron1 333
	item: tTypedPtr;
8728 leency 334
BEGIN
9902 akron1 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)
8728 leency 343
END typedPtr;
344
 
345
 
346
PROCEDURE untypedPtr (p: INTEGER);
347
VAR
9902 akron1 348
	item: tUntypedPtr;
8728 leency 349
BEGIN
9902 akron1 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)
8728 leency 358
END untypedPtr;
359
 
9448 akron1 360
 
9902 akron1 361
PROCEDURE setLog* (_CL: tLog);
8728 leency 362
BEGIN
9903 akron1 363
	CL := _CL
9902 akron1 364
END setLog;
9050 leency 365
 
366
 
367
PROCEDURE create* (VAR maxLength: INTEGER): tLog;
368
VAR
9903 akron1 369
	newLog: tLog;
9050 leency 370
BEGIN
9903 akron1 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
9050 leency 381
END create;
382
 
383
 
9448 akron1 384
PROCEDURE destroy* (VAR log: tLog);
385
VAR
386
	item: List.tItem;
9902 akron1 387
	res, i: INTEGER;
9050 leency 388
BEGIN
9448 akron1 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
 
9902 akron1 397
		item := List.pop(log.TPointers);
9448 akron1 398
		WHILE item # NIL DO
9902 akron1 399
			FOR i := 0 TO item(tTypedPtr).cnt - 1 DO
400
				DISPOSE(item(tTypedPtr).p[i])
401
			END;
9448 akron1 402
			DISPOSE(item);
9902 akron1 403
			item := List.pop(log.TPointers)
9448 akron1 404
		END;
9902 akron1 405
		DISPOSE(log.TPointers);
9448 akron1 406
 
9902 akron1 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
 
9448 akron1 417
		DISPOSE(log)
418
	END
419
END destroy;
420
 
421
 
422
BEGIN
9903 akron1 423
	List.init(changeInt, changePtr);
424
	Lines.init(changeInt, changePtr, changeBool, changeBool2, typedPtr, untypedPtr)
8728 leency 425
END ChangeLog.