Subversion Repositories Kolibri OS

Rev

Rev 9903 | 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
9904 akron1 38
				adr1, adr2: INTEGER;
39
				val1, val2, save: BOOLEAN
9903 akron1 40
			END
41
	END;
9448 akron1 42
 
9903 akron1 43
	tUntypedPtr = POINTER TO RECORD (List.tItem)
44
		cnt: INTEGER;
45
		p: ARRAY 64 OF INTEGER
46
	END;
8728 leency 47
 
9903 akron1 48
	tTypedPtr = POINTER TO RECORD (List.tItem)
49
		cnt: INTEGER;
50
		p: ARRAY 64 OF List.tItem
51
	END;
9448 akron1 52
 
9903 akron1 53
	tGuard* = POINTER TO RECORD (List.tItem)
54
		saved*: BOOLEAN
55
	END;
8728 leency 56
 
9903 akron1 57
	tLog* = POINTER TO RECORD
58
		Log*, TPointers, UPointers: List.tList;
59
		guard, first: tGuard;
60
		isLast: BOOLEAN
61
	END;
8728 leency 62
 
9050 leency 63
 
8728 leency 64
VAR
9903 akron1 65
	CL*: tLog;
8728 leency 66
 
67
 
68
PROCEDURE isLastGuard* (guard: tGuard): BOOLEAN;
69
VAR
9903 akron1 70
	item: List.tItem;
71
	res: BOOLEAN;
8728 leency 72
BEGIN
9903 akron1 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
8728 leency 83
END isLastGuard;
84
 
85
 
9668 akron1 86
PROCEDURE getFirstGuard (): tGuard;
8728 leency 87
VAR
9668 akron1 88
	item: List.tItem;
8728 leency 89
BEGIN
9668 akron1 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
8728 leency 105
END isFirstGuard;
106
 
107
 
108
PROCEDURE setGuard* (_guard: tGuard);
109
BEGIN
9903 akron1 110
	CL.guard := _guard;
111
	CL.isLast := isLastGuard(_guard)
8728 leency 112
END setGuard;
113
 
114
 
115
PROCEDURE redo* (item: List.tItem);
9902 akron1 116
VAR
117
	i: INTEGER;
8728 leency 118
BEGIN
9902 akron1 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
9903 akron1 124
		FOR i := 0 TO boolItemSize - 1 DO
125
			IF i IN item(tBoolItem).map THEN
9904 akron1 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)
9903 akron1 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;
9904 akron1 155
	line_modified: BOOLEAN;
9073 leency 156
BEGIN
9903 akron1 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;
9452 akron1 165
 
9903 akron1 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
9904 akron1 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
9903 akron1 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
9073 leency 185
END save;
186
 
187
 
8728 leency 188
PROCEDURE changeWord (adrV, adrX: INTEGER);
189
VAR
9902 akron1 190
	item: tIntItem;
191
	cur: List.tItem;
8728 leency 192
BEGIN
9902 akron1 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)
8728 leency 210
END changeWord;
211
 
212
 
9073 leency 213
PROCEDURE delSaved*;
214
VAR
9903 akron1 215
	boolItem: tBoolItem;
216
	cur: List.tItem;
217
	i: INTEGER;
9073 leency 218
BEGIN
9903 akron1 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
9073 leency 235
END delSaved;
236
 
237
 
238
PROCEDURE delCurSaved*;
239
VAR
9903 akron1 240
	boolItem: tBoolItem;
241
	cur: List.tItem;
242
	i: INTEGER;
9073 leency 243
BEGIN
9903 akron1 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
9904 akron1 250
					SYSTEM.PUT(boolItem.data[i].adr1, ~boolItem.data[i].val1);
251
					SYSTEM.PUT(boolItem.data[i].adr2, ~boolItem.data[i].val2);
9903 akron1 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
9073 leency 262
END delCurSaved;
263
 
264
 
9904 akron1 265
PROCEDURE changeBool (save: BOOLEAN; VAR v1: BOOLEAN; x1: BOOLEAN; VAR v2: BOOLEAN; x2: BOOLEAN);
9073 leency 266
VAR
9903 akron1 267
	item: tBoolItem;
268
	cur: List.tItem;
269
	i: INTEGER;
9073 leency 270
BEGIN
9904 akron1 271
	IF save THEN
9903 akron1 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) &
9904 akron1 281
			( ~(cur IS tBoolItem) (*OR (cur(tBoolItem).map = fillMap)*) ) DO
9903 akron1 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 := {};
9904 akron1 289
		IF save THEN
9903 akron1 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
9904 akron1 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;
9903 akron1 304
			INCL(item.map, i);
305
			i := boolItemSize
306
		END;
307
		INC(i)
308
	END
309
END changeBool;
310
 
311
 
9336 akron1 312
PROCEDURE changeInt* (VAR v: INTEGER; x: INTEGER);
8728 leency 313
BEGIN
9903 akron1 314
	changeWord(SYSTEM.ADR(v), SYSTEM.ADR(x))
8728 leency 315
END changeInt;
316
 
317
 
318
PROCEDURE changePtr (VAR v: List.tItem; x: List.tItem);
319
BEGIN
9903 akron1 320
	changeWord(SYSTEM.ADR(v), SYSTEM.ADR(x))
8728 leency 321
END changePtr;
322
 
9448 akron1 323
 
8728 leency 324
PROCEDURE typedPtr (p: List.tItem);
325
VAR
9902 akron1 326
	item: tTypedPtr;
8728 leency 327
BEGIN
9902 akron1 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)
8728 leency 336
END typedPtr;
337
 
338
 
339
PROCEDURE untypedPtr (p: INTEGER);
340
VAR
9902 akron1 341
	item: tUntypedPtr;
8728 leency 342
BEGIN
9902 akron1 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)
8728 leency 351
END untypedPtr;
352
 
9448 akron1 353
 
9902 akron1 354
PROCEDURE setLog* (_CL: tLog);
8728 leency 355
BEGIN
9903 akron1 356
	CL := _CL
9902 akron1 357
END setLog;
9050 leency 358
 
359
 
360
PROCEDURE create* (VAR maxLength: INTEGER): tLog;
361
VAR
9903 akron1 362
	newLog: tLog;
9050 leency 363
BEGIN
9903 akron1 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
9050 leency 374
END create;
375
 
376
 
9448 akron1 377
PROCEDURE destroy* (VAR log: tLog);
378
VAR
379
	item: List.tItem;
9902 akron1 380
	res, i: INTEGER;
9050 leency 381
BEGIN
9448 akron1 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
 
9902 akron1 390
		item := List.pop(log.TPointers);
9448 akron1 391
		WHILE item # NIL DO
9902 akron1 392
			FOR i := 0 TO item(tTypedPtr).cnt - 1 DO
393
				DISPOSE(item(tTypedPtr).p[i])
394
			END;
9448 akron1 395
			DISPOSE(item);
9902 akron1 396
			item := List.pop(log.TPointers)
9448 akron1 397
		END;
9902 akron1 398
		DISPOSE(log.TPointers);
9448 akron1 399
 
9902 akron1 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
 
9448 akron1 410
		DISPOSE(log)
411
	END
412
END destroy;
413
 
414
 
415
BEGIN
9903 akron1 416
	List.init(changeInt, changePtr);
9904 akron1 417
	Lines.init(changeInt, changePtr, changeBool, typedPtr, untypedPtr)
8728 leency 418
END ChangeLog.