Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
8728 leency 1
(*
9904 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 Lines;
21
 
22
IMPORT
23
    List, SYSTEM, API, Utils;
24
 
25
CONST
26
    WCHAR_SIZE = 2;
9174 akron1 27
    SPACE* = 20X;
28
    TAB* = 9X;
9560 akron1 29
    NUL* = 0FDD0X;
30
    TAB1* = 0FDD1X;
9906 akron1 31
    MAX_TAB_WIDTH* = 16;
8728 leency 32
 
33
TYPE
34
 
35
    tLine* = POINTER TO RECORD (List.tItem)
36
        ptr: INTEGER;
37
        length*: INTEGER;
9060 leency 38
        modified*, saved*, temp, label*: BOOLEAN;
8728 leency 39
        cin*, cout*, pos*: INTEGER
40
    END;
41
 
42
    PmovInt = PROCEDURE (VAR v: INTEGER; x: INTEGER);
9904 akron1 43
    PmovBool = PROCEDURE (save: BOOLEAN; VAR v1: BOOLEAN; x1: BOOLEAN; VAR v2: BOOLEAN; x2: BOOLEAN);
8728 leency 44
    PmovPtr = PROCEDURE (VAR v: List.tItem; x: List.tItem);
9448 akron1 45
 
8728 leency 46
    PTypedPtr = PROCEDURE (p: List.tItem);
47
    PUntypedPtr = PROCEDURE (p: INTEGER);
48
 
9668 akron1 49
    tVector* = POINTER TO RECORD
50
    	size, data: INTEGER
51
    END;
9448 akron1 52
 
9668 akron1 53
    tVectorItem = tLine;
54
 
9674 akron1 55
    fConvert* = PROCEDURE (VAR c: WCHAR): BOOLEAN;
9668 akron1 56
 
9674 akron1 57
 
8728 leency 58
VAR
59
 
60
    _movInt: PmovInt;
9904 akron1 61
    _movBool: PmovBool;
8728 leency 62
    _movPtr: PmovPtr;
9448 akron1 63
    _typedPtr: PTypedPtr;
64
    _untypedPtr: PUntypedPtr;
8728 leency 65
 
9174 akron1 66
    pMaxLength, tab*: INTEGER;
67
    tabs*: BOOLEAN;
8728 leency 68
 
69
 
9668 akron1 70
PROCEDURE createVector* (size: INTEGER): tVector;
71
VAR
72
	res: tVector;
73
BEGIN
74
	IF size > 0 THEN
75
		NEW(res);
76
		res.size := size;
77
		IF size < 4096 THEN
78
			size := 4096
79
		END;
80
		res.data := API._NEW(size*SYSTEM.SIZE(tVectorItem));
81
		IF res.data = 0 THEN
82
			DISPOSE(res)
83
		END
84
	ELSE
85
		res := NIL
86
	END
87
	RETURN res
88
END createVector;
89
 
90
 
91
PROCEDURE destroyVector* (VAR vector: tVector);
92
BEGIN
93
	IF vector # NIL THEN
94
		IF vector.data # 0 THEN
95
			vector.data := API._DISPOSE(vector.data)
96
		END;
97
		DISPOSE(vector)
98
	END
99
END destroyVector;
100
 
101
 
102
PROCEDURE setVectorItem* (vector: tVector; idx: INTEGER; item: tVectorItem);
103
BEGIN
104
	ASSERT(vector # NIL);
105
	ASSERT((0 <= idx) & (idx < vector.size));
106
	SYSTEM.PUT(vector.data + idx*SYSTEM.SIZE(tVectorItem), item)
107
END setVectorItem;
108
 
109
 
110
PROCEDURE getVectorItem* (vector: tVector; idx: INTEGER): tVectorItem;
111
VAR
112
	res: tVectorItem;
113
BEGIN
114
	ASSERT(vector # NIL);
115
	ASSERT((0 <= idx) & (idx < vector.size));
116
	SYSTEM.GET(vector.data + idx*SYSTEM.SIZE(tVectorItem), res)
117
	RETURN res
118
END getVectorItem;
119
 
120
 
8728 leency 121
PROCEDURE movInt (VAR v: INTEGER; x: INTEGER);
122
BEGIN
123
    _movInt(v, x)
124
END movInt;
125
 
126
 
127
PROCEDURE movPtr (VAR v: List.tItem; x: List.tItem);
128
BEGIN
129
    _movPtr(v, x)
130
END movPtr;
131
 
132
 
133
PROCEDURE malloc (size: INTEGER): INTEGER;
134
VAR
9050 leency 135
    maxLength: INTEGER;
8728 leency 136
BEGIN
9050 leency 137
    ASSERT(pMaxLength # 0);
138
    SYSTEM.GET(pMaxLength, maxLength);
8728 leency 139
    IF size > maxLength THEN
9050 leency 140
        SYSTEM.PUT(pMaxLength, size)
8728 leency 141
    END;
142
    size := size*WCHAR_SIZE + 4;
9448 akron1 143
    INC(size, (-size) MOD 32)
144
    RETURN API._NEW(size)
8728 leency 145
END malloc;
146
 
147
 
148
PROCEDURE free (line: tLine; newPtr: INTEGER);
149
BEGIN
150
    IF line.ptr # 0 THEN
151
        IF line.temp THEN
152
            line.ptr := API._DISPOSE(line.ptr)
153
        ELSE
154
            line.ptr := 0
155
        END
156
    END;
157
    IF ~line.temp THEN
158
        movInt(line.ptr, newPtr);
9448 akron1 159
        IF newPtr # 0 THEN
8728 leency 160
            _untypedPtr(newPtr)
9448 akron1 161
        END
8728 leency 162
    END;
163
    line.ptr := newPtr
164
END free;
165
 
166
 
167
PROCEDURE create* (temp: BOOLEAN): tLine;
168
VAR
169
    line: tLine;
170
BEGIN
171
    NEW(line);
9060 leency 172
    line.label := FALSE;
8728 leency 173
    ASSERT(line # NIL);
9448 akron1 174
    IF ~temp THEN
8728 leency 175
        _typedPtr(line)
9448 akron1 176
    END;
8728 leency 177
    line.next := NIL;
178
    line.prev := NIL;
179
    IF ~temp THEN
180
        movPtr(line.next, NIL);
181
        movPtr(line.prev, NIL)
182
    END;
183
    line.ptr := malloc(1);
184
    ASSERT(line.ptr # 0);
185
    IF ~temp THEN
9448 akron1 186
        _untypedPtr(line.ptr);
8728 leency 187
        movInt(line.ptr, line.ptr)
188
    END;
189
    SYSTEM.PUT16(line.ptr, 0);
190
    line.length := 0;
191
    IF ~temp THEN
192
        movInt(line.length, 0)
193
    END;
194
    line.temp := temp;
195
    line.modified := FALSE;
196
    line.saved := FALSE;
197
    IF ~temp THEN
9904 akron1 198
        _movBool(FALSE, line.modified, FALSE, line.saved, FALSE)
8728 leency 199
    END;
200
    line.cin := 0;
201
    line.cout := 0;
202
    line.pos := 0
203
    RETURN line
204
END create;
205
 
206
 
207
PROCEDURE destroy* (VAR line: tLine);
208
BEGIN
209
    IF line.temp THEN
210
        free(line, 0);
211
        DISPOSE(line)
212
    ELSE
213
        line := NIL
214
    END
215
END destroy;
216
 
217
 
9522 akron1 218
PROCEDURE resize* (line: tLine; size: INTEGER);
219
BEGIN
220
	ASSERT(line.temp);
221
	IF size > 0 THEN
222
		line.ptr := API._DISPOSE(line.ptr);
9668 akron1 223
		size := size*WCHAR_SIZE + 4;
224
		INC(size, (-size) MOD 32);
9522 akron1 225
		line.ptr := API._NEW(size)
226
	ELSE
227
		destroy(line)
228
	END
229
END resize;
230
 
231
 
9174 akron1 232
PROCEDURE getChar* (line: tLine; i: INTEGER): WCHAR;
233
VAR
9659 akron1 234
    res: WCHAR;
8728 leency 235
BEGIN
9659 akron1 236
    IF i >= line.length THEN
237
        res := 0X
238
    ELSE
239
    	SYSTEM.GET(line.ptr + i*WCHAR_SIZE, res)
240
    END
241
    RETURN res
9174 akron1 242
END getChar;
8728 leency 243
 
244
 
9174 akron1 245
PROCEDURE tabWidth (line: tLine; pos: INTEGER): INTEGER;
246
VAR
247
    n: INTEGER;
248
BEGIN
249
    n := pos;
250
    IF getChar(line, pos) = TAB THEN
251
        INC(pos);
252
        WHILE getChar(line, pos) = TAB1 DO
253
            INC(pos)
254
        END
255
    END
256
    RETURN pos - n
257
END tabWidth;
258
 
259
 
8728 leency 260
PROCEDURE save* (line: tLine);
261
BEGIN
262
    IF ~line.temp THEN
9904 akron1 263
    	_movBool(TRUE, line.modified, FALSE, line.saved, TRUE)
8728 leency 264
    END;
265
    line.modified := FALSE;
266
    line.saved := TRUE
267
END save;
268
 
269
 
9174 akron1 270
PROCEDURE isSpace* (c: WCHAR): BOOLEAN;
271
    RETURN (c = SPACE) OR (c = TAB) OR (c = TAB1)
272
END isSpace;
8728 leency 273
 
274
 
275
PROCEDURE trimLength* (line: tLine): INTEGER;
276
VAR
277
    i: INTEGER;
278
BEGIN
279
    i := line.length - 1;
9174 akron1 280
    WHILE (i >= 0) & isSpace(getChar(line, i)) DO
8728 leency 281
        DEC(i)
282
    END
283
    RETURN i + 1
284
END trimLength;
285
 
286
 
287
PROCEDURE getPChar* (line: tLine; i: INTEGER): INTEGER;
288
    RETURN line.ptr + i*WCHAR_SIZE
289
END getPChar;
290
 
291
 
292
PROCEDURE setChar* (line: tLine; i: INTEGER; c: WCHAR);
293
BEGIN
294
    SYSTEM.PUT(line.ptr + i*WCHAR_SIZE, c)
295
END setChar;
296
 
297
 
9010 leency 298
PROCEDURE move* (src, dst: tLine);
299
BEGIN
300
    SYSTEM.MOVE(src.ptr, dst.ptr, (MIN(src.length, dst.length) + 1)*WCHAR_SIZE)
301
END move;
302
 
303
 
8728 leency 304
PROCEDURE delChar* (line: tLine; pos: INTEGER);
305
VAR
306
    ptr: INTEGER;
307
BEGIN
308
    IF pos < line.length THEN
309
        ptr := malloc(line.length);
310
        ASSERT(ptr # 0);
311
        IF ~line.temp THEN
312
            movInt(line.length, line.length - 1)
313
        END;
314
        DEC(line.length);
315
        SYSTEM.MOVE(line.ptr, ptr, pos*WCHAR_SIZE);
316
        SYSTEM.MOVE(line.ptr + pos*WCHAR_SIZE + WCHAR_SIZE, ptr + pos*WCHAR_SIZE, (line.length - pos)*WCHAR_SIZE);
317
        SYSTEM.PUT16(ptr + line.length*WCHAR_SIZE, 0);
318
        free(line, ptr)
319
    END
320
END delChar;
321
 
322
 
323
PROCEDURE insert* (line: tLine; pos: INTEGER; c: WCHAR);
324
VAR
325
    ptr: INTEGER;
326
BEGIN
327
    ptr := malloc(line.length + 2);
328
    ASSERT(ptr # 0);
329
    SYSTEM.MOVE(line.ptr, ptr, pos*WCHAR_SIZE);
330
    SYSTEM.PUT(ptr + pos*WCHAR_SIZE, c);
331
    SYSTEM.MOVE(line.ptr + pos*WCHAR_SIZE, ptr + pos*WCHAR_SIZE + WCHAR_SIZE, (line.length - pos)*WCHAR_SIZE);
332
    IF ~line.temp THEN
333
        movInt(line.length, line.length + 1)
334
    END;
335
    INC(line.length);
336
    SYSTEM.PUT16(ptr + line.length*WCHAR_SIZE, 0);
337
    free(line, ptr)
338
END insert;
339
 
340
 
9522 akron1 341
PROCEDURE _insert2* (line1: tLine; pos: INTEGER; line2: tLine);
8728 leency 342
VAR
343
    ptr: INTEGER;
344
BEGIN
345
    IF line2.length > 0 THEN
346
        ptr := malloc(line1.length + line2.length + 1);
347
        ASSERT(ptr # 0);
348
        SYSTEM.MOVE(line1.ptr, ptr, pos*WCHAR_SIZE);
349
        SYSTEM.MOVE(line2.ptr, ptr + pos*WCHAR_SIZE, line2.length*WCHAR_SIZE);
350
        SYSTEM.MOVE(line1.ptr + pos*WCHAR_SIZE, ptr + (pos + line2.length)*WCHAR_SIZE, (line1.length - pos)*WCHAR_SIZE);
351
        SYSTEM.PUT16(ptr + (line1.length + line2.length)*WCHAR_SIZE, 0);
352
        IF ~line1.temp THEN
353
            movInt(line1.length, line1.length + line2.length)
354
        END;
355
        IF ~line2.temp THEN
356
            movInt(line2.length, 0)
357
        END;
358
        INC(line1.length, line2.length);
9522 akron1 359
        free(line1, ptr)
8728 leency 360
    END
9522 akron1 361
END _insert2;
362
 
363
 
364
PROCEDURE insert2* (line1: tLine; pos: INTEGER; line2: tLine);
365
BEGIN
366
	_insert2(line1, pos, line2);
367
	IF line2.length > 0 THEN
368
		line2.length := 0;
369
		free(line2, 0)
370
	END
8728 leency 371
END insert2;
372
 
373
 
374
PROCEDURE insert3* (line: tLine; pos, n: INTEGER);
375
VAR
376
    ptr: INTEGER;
377
BEGIN
378
    IF n > 0 THEN
379
        ptr := malloc(line.length + n + 1);
380
        ASSERT(ptr # 0);
381
        SYSTEM.MOVE(line.ptr, ptr, pos*WCHAR_SIZE);
382
        SYSTEM.MOVE(line.ptr + pos*WCHAR_SIZE, ptr + (pos + n)*WCHAR_SIZE, (line.length - pos)*WCHAR_SIZE);
383
        SYSTEM.PUT16(ptr + (line.length + n)*WCHAR_SIZE, 0);
384
        IF ~line.temp THEN
385
            movInt(line.length, line.length + n)
386
        END;
387
        INC(line.length, n);
388
        free(line, ptr)
389
    END
390
END insert3;
391
 
392
 
393
PROCEDURE delCharN* (line: tLine; pos, n: INTEGER);
394
VAR
395
    ptr: INTEGER;
396
BEGIN
397
    IF n > 0 THEN
398
        ptr := malloc(line.length - n + 1);
399
        ASSERT(ptr # 0);
400
        SYSTEM.MOVE(line.ptr, ptr, pos*WCHAR_SIZE);
401
        SYSTEM.MOVE(line.ptr + (pos + n)*WCHAR_SIZE, ptr + pos*WCHAR_SIZE, (line.length - pos - n)*WCHAR_SIZE);
402
        SYSTEM.PUT16(ptr + (line.length - n)*WCHAR_SIZE, 0);
403
        IF ~line.temp THEN
404
            movInt(line.length, line.length - n)
405
        END;
406
        DEC(line.length, n);
407
        free(line, ptr)
408
    END
409
END delCharN;
410
 
411
 
9174 akron1 412
PROCEDURE fixTabs (line: tLine);
413
VAR
414
    i, n, k: INTEGER;
415
BEGIN
416
    i := 0;
417
    WHILE i < line.length DO
418
        n := tabWidth(line, i);
419
        IF n # 0 THEN
420
            k := tab - i MOD tab;
421
            IF n > k THEN
422
                delCharN(line, i + 1, n - k)
423
            ELSIF n < k THEN
424
                DEC(k, n);
425
                insert3(line, i + 1, k);
426
                WHILE k > 0 DO
427
                    setChar(line, i + 1, TAB1);
428
                    INC(i);
429
                    DEC(k)
430
                END
431
            END
432
        END;
433
        INC(i)
434
    END
435
END fixTabs;
436
 
437
 
438
PROCEDURE modify* (line: tLine);
439
BEGIN
440
    IF ~line.temp THEN
9904 akron1 441
        _movBool(FALSE, line.modified, TRUE, line.saved, FALSE)
9174 akron1 442
    END;
443
    line.modified := TRUE;
444
    line.saved := FALSE;
445
    fixTabs(line)
446
END modify;
447
 
448
 
8728 leency 449
PROCEDURE wrap* (line, nextLine: tLine; pos: INTEGER);
450
VAR
451
    ptr1, ptr2: INTEGER;
452
    n: INTEGER;
453
BEGIN
454
    ptr1 := malloc(pos + 1);
455
    ASSERT(ptr1 # 0);
456
    n := line.length - pos;
457
    ptr2 := malloc(n + 1);
458
    ASSERT(ptr2 # 0);
459
    SYSTEM.MOVE(line.ptr, ptr1, pos*WCHAR_SIZE);
460
    SYSTEM.PUT16(ptr1 + pos*WCHAR_SIZE, 0);
461
    SYSTEM.MOVE(line.ptr + pos*WCHAR_SIZE, ptr2, n*WCHAR_SIZE);
462
    SYSTEM.PUT16(ptr2 + n*WCHAR_SIZE, 0);
463
    IF ~line.temp THEN
464
        movInt(line.length, pos)
465
    END;
466
    IF ~nextLine.temp THEN
467
        movInt(nextLine.length, n)
468
    END;
469
    line.length := pos;
470
    nextLine.length := n;
471
    free(line, ptr1);
472
    free(nextLine, ptr2)
473
END wrap;
474
 
475
 
476
PROCEDURE copy* (line: tLine);
477
VAR
478
    ptr: INTEGER;
479
BEGIN
480
    ptr := malloc(line.length + 1);
481
    ASSERT(ptr # 0);
482
    SYSTEM.MOVE(line.ptr, ptr, line.length*WCHAR_SIZE);
483
    SYSTEM.PUT16(ptr + line.length*WCHAR_SIZE, 0);
484
    free(line, ptr)
485
END copy;
486
 
487
 
9674 akron1 488
PROCEDURE convert* (line: tLine; pos1, pos2: INTEGER; func: fConvert): BOOLEAN;
8728 leency 489
VAR
490
    i: INTEGER;
491
    modified: BOOLEAN;
492
    c: WCHAR;
493
BEGIN
9674 akron1 494
	ASSERT(func # NIL);
8728 leency 495
    modified := FALSE;
496
    i := pos2;
497
    WHILE i >= pos1 DO
498
        c := getChar(line, i);
499
        IF func(c) THEN
500
            modified := TRUE
501
        END;
502
        DEC(i)
503
    END;
504
 
505
    IF modified THEN
506
        copy(line);
507
        i := pos2;
508
        WHILE i >= pos1 DO
509
            c := getChar(line, i);
510
            IF func(c) THEN
511
                setChar(line, i, c)
512
            END;
513
            DEC(i)
514
        END;
515
        modify(line)
516
    END
517
    RETURN modified
9674 akron1 518
END convert;
8728 leency 519
 
520
 
9904 akron1 521
PROCEDURE init* (movInt: PmovInt; movPtr: PmovPtr; movBool: PmovBool; typedPtr: PTypedPtr; untypedPtr: PUntypedPtr);
8728 leency 522
BEGIN
523
    _movInt := movInt;
524
    _movPtr := movPtr;
525
    _movBool := movBool;
9448 akron1 526
    _typedPtr := typedPtr;
527
    _untypedPtr := untypedPtr;
8728 leency 528
END init;
529
 
530
 
9050 leency 531
PROCEDURE setMaxLength* (VAR maxLength: INTEGER);
8728 leency 532
BEGIN
9050 leency 533
    pMaxLength := SYSTEM.ADR(maxLength)
534
END setMaxLength;
535
 
536
 
9174 akron1 537
PROCEDURE setTabs* (_tab: INTEGER);
9050 leency 538
BEGIN
9174 akron1 539
    IF _tab = 0 THEN
540
        _tab := 4
541
    END;
542
    tabs := _tab > 0;
9599 akron1 543
    tab := ABS(_tab);
9906 akron1 544
    IF tab > MAX_TAB_WIDTH THEN
545
    	tab := MAX_TAB_WIDTH
9599 akron1 546
    END
9174 akron1 547
END setTabs;
548
 
549
 
550
BEGIN
9050 leency 551
    pMaxLength := 0
8728 leency 552
END Lines.