Subversion Repositories Kolibri OS

Rev

Rev 9891 | 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
(*
9891 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 Text;
21
 
22
IMPORT
23
    List, Lines,
24
    G := Graph,
25
    U := Utils,
26
    RW, Search,
27
    E := Encodings,
28
    CB := Clipboard,
9073 leency 29
    ChangeLog, File,
8728 leency 30
    Lang := Languages;
31
 
32
 
33
CONST
34
 
9174 akron1 35
    SPACE = Lines.SPACE;
36
    TAB = Lines.TAB;
37
    TAB1 = Lines.TAB1;
8728 leency 38
    lenEOL = CB.lenEOL;
39
 
40
    mark_width = 2;
41
    pad_left = mark_width + 3;
9892 akron1 42
    pad_top = 1;
8728 leency 43
    inter = 2;
44
 
45
 
46
TYPE
47
 
9210 akron1 48
    tPoint* = RECORD
49
        X*, Y*: INTEGER
8728 leency 50
    END;
51
 
52
    pPoint = POINTER TO tPoint;
53
 
54
    tString* = ARRAY 1000 OF WCHAR;
55
 
56
    tLine = Lines.tLine;
57
 
58
    tGuard = POINTER TO RECORD (ChangeLog.tGuard)
59
        selected: BOOLEAN;
60
        cursor, select2, scroll: tPoint;
61
        CurX: INTEGER
62
    END;
63
 
64
    tText* = POINTER TO RECORD (List.tList)
65
        cursor, select, select2: pPoint;
66
        scroll: tPoint;
67
        CurX: INTEGER;
9668 akron1 68
        smallChange: INTEGER;
9671 akron1 69
        modified*, smallMove,
9674 akron1 70
        comments, guard, fasm*,
9671 akron1 71
        search, cs, whole: BOOLEAN;
8728 leency 72
        edition*: tGuard;
73
        curLine: tLine;
74
        lang*: INTEGER;
9336 akron1 75
        enc, eol: INTEGER;
8728 leency 76
        foundList: List.tList;
77
        foundSel: INTEGER;
9050 leency 78
        searchText: tString;
9668 akron1 79
        LinesVector: Lines.tVector;
9050 leency 80
        chLog*: ChangeLog.tLog;
9210 akron1 81
        maxLength*: INTEGER;
82
        fileName*: RW.tFileName
8728 leency 83
    END;
84
 
85
    tProcedure = PROCEDURE;
86
 
87
 
88
VAR
89
 
90
    pdelete: PROCEDURE (text: tText);
91
    ShowCursor: PROCEDURE;
92
 
9671 akron1 93
    colors: RECORD
8762 leency 94
                text, back, seltext, selback, modified, saved, curline, numtext, numback: INTEGER;
9413 akron1 95
                comment, string, escape, num, delim, key1, key2, key3: INTEGER
8728 leency 96
             END;
97
    canvas: G.tCanvas;
9174 akron1 98
    drawCursor: BOOLEAN;
8728 leency 99
    padding: RECORD left, top: INTEGER END;
100
    size, textsize: tPoint;
101
    charWidth, charHeight: INTEGER;
9671 akron1 102
    autoIndents*, lineNumbers*, autoBrackets*, trimSpace*: BOOLEAN;
9674 akron1 103
    idxTable: Search.IdxTable;
8728 leency 104
 
105
 
9210 akron1 106
PROCEDURE setLang* (text: tText; lang: INTEGER);
107
BEGIN
9674 akron1 108
	IF text.lang # lang THEN
109
		text.fasm := lang = Lang.langFasm;
110
		text.lang := lang
111
	END;
9210 akron1 112
    text.comments := TRUE;
113
    Lang.setCurLang(text.lang)
114
END setLang;
115
 
116
 
8728 leency 117
PROCEDURE setName* (text: tText; name: RW.tFileName);
118
VAR
119
    ext: RW.tFileName;
120
BEGIN
121
    text.fileName := name;
9210 akron1 122
    U.getFileName(name, ext, ".");
8728 leency 123
    U.upcase(ext);
9210 akron1 124
    setLang(text, Lang.getLang(ext))
8728 leency 125
END setName;
126
 
127
 
128
PROCEDURE getPos* (text: tText; VAR x, y: INTEGER);
129
BEGIN
130
    x := text.cursor.X + 1;
131
    y := text.cursor.Y + 1
132
END getPos;
133
 
134
 
135
PROCEDURE getScroll* (text: tText; VAR x, y: INTEGER);
136
BEGIN
137
    x := text.scroll.X;
138
    y := text.scroll.Y
139
END getScroll;
140
 
141
 
142
PROCEDURE getTextSize* (VAR x, y: INTEGER);
143
BEGIN
144
    x := textsize.X;
145
    y := textsize.Y
146
END getTextSize;
147
 
148
 
149
PROCEDURE getTextRect* (VAR left, top, rigth, bottom: INTEGER);
150
BEGIN
151
    left := padding.left - 1;
152
    top := padding.top - 1;
153
    rigth := size.X - 1;
154
    bottom := top + size.Y - 1;
155
END getTextRect;
156
 
157
 
9671 akron1 158
PROCEDURE toggleNumbers*;
8728 leency 159
BEGIN
9671 akron1 160
    lineNumbers := ~lineNumbers
8728 leency 161
END toggleNumbers;
162
 
163
 
9671 akron1 164
PROCEDURE toggleIndents*;
165
BEGIN
166
    autoIndents := ~autoIndents
167
END toggleIndents;
168
 
169
 
170
PROCEDURE toggleBrackets*;
171
BEGIN
172
    autoBrackets := ~autoBrackets
173
END toggleBrackets;
174
 
175
 
176
PROCEDURE toggleTrimSpace*;
177
BEGIN
178
    trimSpace := ~trimSpace
179
END toggleTrimSpace;
180
 
181
 
9174 akron1 182
PROCEDURE showCursor*;
183
BEGIN
184
	drawCursor := TRUE
185
END showCursor;
186
 
187
 
188
PROCEDURE hideCursor*;
189
BEGIN
190
	drawCursor := FALSE
191
END hideCursor;
192
 
193
 
8728 leency 194
PROCEDURE getString (src: tLine; pos, cnt: INTEGER; VAR dst: ARRAY OF WCHAR): INTEGER;
195
VAR
196
    i: INTEGER;
197
BEGIN
198
    i := 0;
199
    WHILE (pos < src.length) & (cnt > 0) DO
200
        IF i < LEN(dst) - 1 THEN
9659 akron1 201
            dst[i] := Lines.getChar(src, pos);
8728 leency 202
            INC(i)
203
        END;
204
        INC(pos);
205
        DEC(cnt)
206
    END;
207
    dst[i] := 0X
208
    RETURN i
209
END getString;
210
 
211
 
212
PROCEDURE NextLine (VAR line: tLine);
213
BEGIN
214
    line := line.next(tLine)
215
END NextLine;
216
 
217
 
218
PROCEDURE PrevLine (VAR line: tLine);
219
BEGIN
220
    line := line.prev(tLine)
221
END PrevLine;
222
 
223
 
224
PROCEDURE SetColor (textColor, backColor: INTEGER);
225
BEGIN
226
    G.SetTextColor(canvas, textColor);
227
    G.SetBkColor(canvas, backColor)
228
END SetColor;
229
 
230
 
231
PROCEDURE ProcessComments (line: tLine; VAR depth, pos: INTEGER; minDepth, n: INTEGER; lang: INTEGER);
232
VAR
233
    cond: INTEGER;
234
BEGIN
235
    cond := 0;
236
    WHILE (pos <= n) & (depth > minDepth) DO
237
        Lang.comments(line, depth, cond, pos, n, lang);
238
        INC(pos)
239
    END;
240
    DEC(pos)
241
END ProcessComments;
242
 
243
 
9668 akron1 244
PROCEDURE getLine2 (text: tText; n: INTEGER): tLine;
245
VAR
246
	item: tLine;
247
BEGIN
248
	IF (0 <= n) & (n < text.count) THEN
249
		item := Lines.getVectorItem(text.LinesVector, n)
250
	ELSE
251
		item := NIL
252
	END
253
	RETURN item
254
END getLine2;
255
 
256
 
8728 leency 257
PROCEDURE Comments (text: tText);
258
VAR
9668 akron1 259
	line: tLine;
260
	i, k, cout: INTEGER;
8728 leency 261
BEGIN
9668 akron1 262
	IF text.smallChange = 1 THEN
263
		line := getLine2(text, text.cursor.Y);
264
		IF line.prev # NIL THEN
265
			line.cin := line.prev(tLine).cout
266
		ELSE
267
			line.cin := 0
268
		END;
269
		cout := line.cout;
270
		line.cout := line.cin;
271
		i := 0;
272
		ProcessComments(line, line.cout, i, -1, line.length - 1, text.lang);
273
		IF line.cout # cout THEN
274
			text.smallChange := 0;
275
			Comments(text)
276
		END
277
	ELSE
278
		Lines.destroyVector(text.LinesVector);
279
		text.LinesVector := Lines.createVector(text.count);
280
		k := 0;
281
		line := text.first(tLine);
282
		Lines.setVectorItem(text.LinesVector, k, line);
283
		INC(k);
284
		line.cin := 0;
285
		line.cout := 0;
286
		i := 0;
287
		ProcessComments(line, line.cout, i, -1, line.length - 1, text.lang);
288
		NextLine(line);
289
		WHILE line # NIL DO
290
			Lines.setVectorItem(text.LinesVector, k, line);
291
			INC(k);
292
			line.cin := line.prev(tLine).cout;
293
			line.cout := line.cin;
294
			i := 0;
295
			ProcessComments(line, line.cout, i, -1, line.length - 1, text.lang);
296
			NextLine(line)
297
		END
298
	END;
299
	text.smallChange := 0;
300
	text.comments := FALSE
8728 leency 301
END Comments;
302
 
303
 
9674 akron1 304
PROCEDURE leadingSpaces (line: tLine): INTEGER;
305
VAR
306
    i: INTEGER;
307
BEGIN
308
    i := 0;
309
    WHILE Lines.isSpace(Lines.getChar(line, i)) DO
310
        INC(i)
311
    END
312
    RETURN i
313
END leadingSpaces;
314
 
315
 
8728 leency 316
PROCEDURE parse (text: tText; line: tLine; y: INTEGER; backColor: INTEGER; lang: INTEGER);
317
VAR
318
    c: WCHAR;
319
    i, n, k: INTEGER;
320
    cond, depth: INTEGER;
321
    color: INTEGER;
322
    hex: BOOLEAN;
323
    isDgt: PROCEDURE (c: WCHAR): BOOLEAN;
324
 
325
 
326
    PROCEDURE PrintLex (text: tText; line: tLine; lexStart, lexEnd: INTEGER; y: INTEGER; color, backColor: INTEGER);
327
    VAR
328
        lexLen: INTEGER;
329
    BEGIN
330
        SetColor(color, backColor);
331
        lexLen := MAX(MIN(line.length - lexStart, lexEnd - lexStart + 1), 0);
9193 akron1 332
        G.TextOut(canvas, padding.left + (lexStart - text.scroll.X) * charWidth, y, Lines.getPChar(line, lexStart), lexLen, color)
8728 leency 333
    END PrintLex;
334
 
335
 
9193 akron1 336
    PROCEDURE PrintComment (text: tText; line: tLine; VAR depth, i: INTEGER; w, y: INTEGER; backColor: INTEGER);
8728 leency 337
    VAR
338
        lexStart: INTEGER;
339
        color: INTEGER;
340
    BEGIN
341
        IF (text.lang = Lang.langLua) & ~ODD(depth) THEN
342
            color := colors.string
343
        ELSIF (text.lang = Lang.langIni) & (depth = 1) THEN
344
            color := colors.key2
345
        ELSIF (text.lang = Lang.langPascal) & (depth = 3) THEN
346
            color := colors.key3
347
        ELSE
348
            color := colors.comment
349
        END;
9193 akron1 350
        lexStart := MAX(i - w, 0);
8728 leency 351
        ProcessComments(line, depth, i, 0, line.length - 1, text.lang);
352
        PrintLex(text, line, lexStart, i, y, color, backColor)
353
    END PrintComment;
354
 
355
 
356
    PROCEDURE cap (c: WCHAR): WCHAR;
357
    BEGIN
358
        IF U.cap(c) THEN END
359
        RETURN c
360
    END cap;
361
 
362
 
363
    PROCEDURE UL (c: WCHAR): BOOLEAN;
364
        RETURN (cap(c) = "U") OR (cap(c) = "L")
365
    END UL;
366
 
367
 
368
    PROCEDURE FL (c: WCHAR): BOOLEAN;
369
        RETURN (cap(c) = "F") OR (cap(c) = "L")
370
    END FL;
371
 
372
 
373
    PROCEDURE ident (text: tText; VAR i: INTEGER; first, y: INTEGER; line: tLine; backColor: INTEGER; cs: BOOLEAN);
374
    VAR
375
        c: WCHAR;
376
        lexLen: INTEGER;
377
        s: ARRAY 32 OF WCHAR;
378
        color: INTEGER;
379
    BEGIN
9659 akron1 380
        c := Lines.getChar(line, i);
8728 leency 381
        WHILE U.isLetter(c) OR (c = "_") OR U.isDigit(c) DO
382
            INC(i);
9659 akron1 383
            c := Lines.getChar(line, i);
8728 leency 384
        END;
385
        DEC(i);
386
        lexLen := getString(line, first, i - first + 1, s);
387
        IF ~cs THEN
388
            U.upcase16(s)
389
        END;
390
        IF Lang.isKey(s, text.lang, 1) THEN
391
            color := colors.key1
392
        ELSIF Lang.isKey(s, text.lang, 2) THEN
393
            color := colors.key2
394
        ELSIF Lang.isKey(s, text.lang, 3) THEN
395
            color := colors.key3
396
        ELSE
397
            color := colors.text
398
        END;
399
        IF color # colors.text THEN
400
            PrintLex(text, line, first, i, y, color, backColor)
401
        END
402
    END ident;
403
 
404
 
405
    PROCEDURE String (text: tText; line: tLine; VAR i: INTEGER; y: INTEGER; backColor: INTEGER);
406
    VAR
9413 akron1 407
        k, j, Start, End: INTEGER;
408
        c: WCHAR;
8728 leency 409
    BEGIN
410
        k := i;
9413 akron1 411
        Lang.SkipString(line, i, line.length - 1, text.lang);
412
        PrintLex(text, line, k, i, y, colors.string, backColor);
413
        IF text.lang IN Lang.escLang THEN
414
	        Start := k + 1;
415
	        End := i - 1;
416
	        k := Start;
417
	        WHILE k <= End DO
9659 akron1 418
	        	c := Lines.getChar(line, k);
9413 akron1 419
	        	IF c = "\" THEN
420
	        		j := k;
421
	        		Lang.SkipEsc(line, k, line.length - 1, text.lang);
422
	        		PrintLex(text, line, j, k, y, colors.escape, backColor)
423
	        	END;
424
	        	INC(k)
425
	        END
426
        END
8728 leency 427
    END String;
428
 
429
 
430
BEGIN
431
    depth := line.cin;
432
    n := line.length - 1;
433
    i := 0;
434
    IF (depth > 0) & (n >= 0) THEN
9193 akron1 435
        PrintComment(text, line, depth, i, 2, y, backColor)
8728 leency 436
    END;
437
    cond := 0;
438
    WHILE i <= n DO
9659 akron1 439
        c := Lines.getChar(line, i);
8728 leency 440
 
441
        IF lang = Lang.langFasm THEN
442
 
443
            IF c = ";" THEN
444
                PrintLex(text, line, i, n, y, colors.comment, backColor);
445
                i := n
446
            ELSIF (c = "'") OR (c = '"') THEN
447
                String(text, line, i, y, backColor)
448
            ELSIF (U.isLetter(c) OR (c = "_")) THEN
9050 leency 449
                ident(text, i, i, y, line, backColor, Lang.isCS(lang))
8728 leency 450
            ELSIF U.isDigit(c) THEN
451
                hex := FALSE;
452
                k := i;
453
                INC(i);
9659 akron1 454
                c := Lines.getChar(line, i);
455
                IF (cap(c) = "X") & (Lines.getChar(line, i - 1) = "0") THEN
8728 leency 456
                    INC(i);
457
                    hex := TRUE
458
                END;
459
 
9659 akron1 460
                WHILE U.isHex(cap(Lines.getChar(line, i))) DO
8728 leency 461
                    INC(i)
462
                END;
463
 
9659 akron1 464
                IF (cap(Lines.getChar(line, i)) = "H") & ~hex THEN
8728 leency 465
                    INC(i)
466
                END;
467
 
468
                DEC(i);
469
                PrintLex(text, line, k, i, y, colors.num, backColor)
470
            END
471
 
9174 akron1 472
        ELSIF (lang = Lang.langC) OR (lang = Lang.langJSON) THEN
8728 leency 473
 
9210 akron1 474
	        IF depth = 0 THEN
475
	            IF c = "/" THEN
476
	                IF cond = 0 THEN
477
	                    cond := 1
478
	                ELSE
479
	                    PrintLex(text, line, i - 1, n, y, colors.comment, backColor);
480
	                    cond := 0;
481
	                    i := n
482
	                END
483
	            ELSIF (c = "*") & (cond = 1) THEN
484
	                depth := 1;
485
	                INC(i);
486
	                PrintComment(text, line, depth, i, 2, y, backColor);
487
	                cond := 0
488
	            ELSIF U.isLetter(c) OR (c = "_") OR (c = "'") OR (c = '"') THEN
489
	            	k := i;
490
	            	IF (c = "'") OR (c = '"') THEN
491
	            		String(text, line, i, y, backColor);
492
	            	ELSE
9659 akron1 493
	            		ident(text, i, i - ORD((lang = Lang.langC) & (i > 0) & (Lines.getChar(line, i - 1) = "#")), y, line, backColor, Lang.isCS(lang))
9210 akron1 494
	            	END;
495
	                IF lang = Lang.langJSON THEN
9659 akron1 496
		                WHILE Lines.isSpace(Lines.getChar(line, i + 1)) DO
9210 akron1 497
		                	INC(i)
498
		                END;
9659 akron1 499
		                IF Lines.getChar(line, i + 1) = ":" THEN
9210 akron1 500
		                	PrintLex(text, line, k, i, y, colors.key1, backColor)
501
		                END
9174 akron1 502
	                END;
9210 akron1 503
	                cond := 0
504
	            ELSIF U.isDigit(c) THEN
505
	                k := i;
506
	                INC(i);
9659 akron1 507
	                c := Lines.getChar(line, i);
9210 akron1 508
	                IF c = "." THEN
509
	                    DEC(i);
9659 akron1 510
	                    c := Lines.getChar(line, i)
9210 akron1 511
	                END;
9659 akron1 512
	                IF (cap(c) = "X") & (Lines.getChar(line, i - 1) = "0") THEN
9210 akron1 513
	                    REPEAT
514
	                        INC(i);
9659 akron1 515
	                        c := Lines.getChar(line, i)
9210 akron1 516
	                    UNTIL ~U.isHex(cap(c));
517
	                    IF UL(c) THEN
518
	                        INC(i)
519
	                    END
520
	                ELSIF UL(c) THEN
521
	                    INC(i)
522
	                ELSIF U.isDigit(c) THEN
523
	                    REPEAT
524
	                        INC(i)
9659 akron1 525
	                    UNTIL ~U.isDigit(Lines.getChar(line, i));
526
	                    c := Lines.getChar(line, i);
9210 akron1 527
	                    IF UL(c) THEN
528
	                        INC(i)
529
	                    ELSIF c = "." THEN
530
	                        INC(i);
9659 akron1 531
	                        WHILE U.isDigit(Lines.getChar(line, i)) DO
9210 akron1 532
	                            INC(i)
533
	                        END;
9659 akron1 534
	                        c := Lines.getChar(line, i);
9210 akron1 535
	                        IF cap(c) = "E" THEN
536
	                            INC(i);
9659 akron1 537
	                            c := Lines.getChar(line, i);
9210 akron1 538
	                            IF (c = "+") OR (c = "-") THEN
539
	                                INC(i)
540
	                            END;
9659 akron1 541
	                            IF U.isDigit(Lines.getChar(line, i)) THEN
542
	                                WHILE U.isDigit(Lines.getChar(line, i)) DO
9210 akron1 543
	                                    INC(i)
544
	                                END;
9659 akron1 545
	                                c := Lines.getChar(line, i);
9210 akron1 546
	                                IF FL(c) THEN
547
	                                    INC(i)
548
	                                END
549
	                            END
550
	                        ELSIF FL(c) THEN
551
	                            INC(i)
552
	                        END
553
	                    END
554
	                END;
555
	                DEC(i);
556
	                PrintLex(text, line, k, i, y, colors.num, backColor);
557
	                cond := 0
558
	            ELSE
559
	                cond := 0
560
	            END
561
	        ELSIF depth = 1 THEN
562
	            IF c = "*" THEN
563
	                cond := 1
564
	            ELSIF (c = "/") & (cond = 1) THEN
565
	                cond := 0;
566
	                depth := 0
567
	            ELSE
568
	                cond := 0
569
	            END
570
	        END
8728 leency 571
 
572
        ELSIF lang = Lang.langOberon THEN
573
 
9210 akron1 574
	        IF (depth = 0) & (c = "/") THEN
575
	            IF cond = 3 THEN
576
	                PrintLex(text, line, i - 1, n, y, colors.comment, backColor);
577
	                cond := 0;
578
	                i := n
579
	            ELSE
580
	                cond := 3
581
	            END
582
	        ELSIF (depth = 0) & ((c = "'") OR (c = '"')) THEN
583
	            String(text, line, i, y, backColor);
584
	            cond := 0
585
	        ELSIF (depth = 0) & U.isDigit(c) THEN
586
	            color := colors.num;
587
	            k := i;
588
	            INC(i);
9659 akron1 589
	            WHILE U.isHex(Lines.getChar(line, i)) DO
9210 akron1 590
	                INC(i)
591
	            END;
592
	            IF i <= n THEN
9659 akron1 593
	                IF Lines.getChar(line, i) = "." THEN
9210 akron1 594
	                    INC(i);
9659 akron1 595
	                    IF Lines.getChar(line, i) = "." THEN
9210 akron1 596
	                        DEC(i)
597
	                    END;
9659 akron1 598
	                    WHILE U.isDigit(Lines.getChar(line, i)) DO
9210 akron1 599
	                        INC(i)
600
	                    END;
9659 akron1 601
	                    IF Lines.getChar(line, i) = "E" THEN
9210 akron1 602
	                        INC(i);
9659 akron1 603
	                        IF (Lines.getChar(line, i) = "+") OR (Lines.getChar(line, i) = "-") THEN
9210 akron1 604
	                            INC(i)
605
	                        END;
9659 akron1 606
	                        WHILE U.isDigit(Lines.getChar(line, i)) DO
9210 akron1 607
	                            INC(i)
608
	                        END
609
	                    END
9659 akron1 610
	                ELSIF Lines.getChar(line, i) = "H" THEN
9210 akron1 611
	                    INC(i)
9659 akron1 612
	                ELSIF Lines.getChar(line, i) = "X" THEN
9210 akron1 613
	                    color := colors.string;
614
	                    INC(i)
615
	                END
616
	            END;
617
	            DEC(i);
618
	            PrintLex(text, line, k, i, y, color, backColor);
619
	            cond := 0
620
	        ELSIF (depth = 0) & (U.isLetter(c) OR (c = "_")) THEN
621
	            ident(text, i, i, y, line, backColor, Lang.isCS(lang));
622
	            cond := 0
623
	        ELSIF c = "(" THEN
624
	            cond := 1
625
	        ELSIF c = "*" THEN
626
	            IF cond = 1 THEN
627
	                INC(depth);
628
	                INC(i);
629
	                PrintComment(text, line, depth, i, 2, y, backColor);
630
	                cond := 0
631
	            ELSE
632
	                cond := 2
633
	            END
634
	        ELSIF c = ")" THEN
635
	            IF cond = 2 THEN
636
	                IF depth > 0 THEN
637
	                    DEC(depth)
638
	                END
639
	            END;
640
	            cond := 0
641
	        ELSE
642
	            cond := 0
643
	        END
8728 leency 644
 
645
        ELSIF lang = Lang.langLua THEN
646
 
9210 akron1 647
	        IF depth = 0 THEN
648
	            IF c = "-" THEN
649
	                IF cond = 1 THEN
650
	                    IF Lang.LuaLong(line, i + 1) >= 0 THEN
651
	                        depth := Lang.LuaLong(line, i + 1)*2 + 1;
652
	                        INC(i);
653
	                        PrintComment(text, line, depth, i, 2, y, backColor)
654
	                    ELSE
655
	                        PrintLex(text, line, i - 1, n, y, colors.comment, backColor);
656
	                        i := n
657
	                    END;
658
	                    cond := 0
659
	                ELSE
660
	                    cond := 1
661
	                END
662
	            ELSIF c = "[" THEN
663
	                cond := 0;
664
	                k := Lang.LuaLong(line, i);
665
	                IF k >= 0 THEN
666
	                    depth := (k + 1)*2;
667
	                    INC(i, 2);
668
	                    PrintComment(text, line, depth, i, 2, y, backColor);
669
	                    cond := 0
670
	                END
671
	            ELSIF (c = "'") OR (c = '"') THEN
672
	                String(text, line, i, y, backColor);
673
	                cond := 0
674
	            ELSIF U.isDigit(c) THEN
675
	                k := i;
9659 akron1 676
	                IF (c = "0") & (cap(Lines.getChar(line, i + 1)) = "X") THEN
9210 akron1 677
	                    isDgt := U.isHex;
678
	                    hex := TRUE;
679
	                    INC(i, 2)
680
	                ELSE
681
	                    isDgt := U.isDigit;
682
	                    hex := FALSE
683
	                END;
9659 akron1 684
	                WHILE isDgt(cap(Lines.getChar(line, i))) DO
9210 akron1 685
	                    INC(i)
686
	                END;
9659 akron1 687
	                IF Lines.getChar(line, i) = "." THEN
9210 akron1 688
	                    INC(i);
9659 akron1 689
	                    IF Lines.getChar(line, i) = "." THEN
9210 akron1 690
	                        DEC(i)
691
	                    END;
9659 akron1 692
	                    WHILE isDgt(cap(Lines.getChar(line, i))) DO
9210 akron1 693
	                        INC(i)
694
	                    END
695
	                END;
9659 akron1 696
	                IF (cap(Lines.getChar(line, i)) = "E") OR hex & (cap(Lines.getChar(line, i)) = "P") THEN
9210 akron1 697
	                    INC(i);
9659 akron1 698
	                    IF (Lines.getChar(line, i) = "-") OR (Lines.getChar(line, i) = "+") THEN
9210 akron1 699
	                        INC(i)
700
	                    END;
9659 akron1 701
	                    WHILE isDgt(cap(Lines.getChar(line, i))) DO
9210 akron1 702
	                        INC(i)
703
	                    END
704
	                END;
705
	                DEC(i);
706
	                PrintLex(text, line, k, i, y, colors.num, backColor);
707
	                cond := 0
708
	            ELSIF U.isLetter(c) OR (c = "_") THEN
709
	                ident(text, i, i, y, line, backColor, Lang.isCS(lang));
710
	                cond := 0
711
	            ELSE
712
	                cond := 0
713
	            END
8728 leency 714
 
9210 akron1 715
	        ELSIF depth > 0 THEN
716
	            IF (cond = 0) & (c = "]") THEN
717
	                cond := 1
718
	            ELSIF (cond >= 1) & (c = "=") THEN
719
	                INC(cond)
720
	            ELSIF (cond >= 1) & (c = "]") & (cond * 2 - depth MOD 2 = depth) THEN
721
	                depth := 0;
722
	                cond := 0
723
	            ELSE
724
	                cond := 0
725
	            END
726
	        END
8728 leency 727
 
728
        ELSIF lang = Lang.langPascal THEN
729
 
9210 akron1 730
	        IF depth = 0 THEN
731
	            IF c = "(" THEN
732
	                cond := 1
733
	            ELSIF (c = "*") & (cond = 1) THEN
734
	                depth := 2;
735
	                INC(i);
736
	                PrintComment(text, line, depth, i, 2, y, backColor);
737
	                cond := 0
738
	            ELSIF c = "/" THEN
739
	                IF cond = 2 THEN
740
	                    PrintLex(text, line, i - 1, n, y, colors.comment, backColor);
741
	                    cond := 0;
742
	                    i := n
743
	                ELSE
744
	                    cond := 2
745
	                END
746
	            ELSIF c = "'" THEN
747
	                String(text, line, i, y, backColor);
748
	                cond := 0
749
	            ELSIF c = "{" THEN
9659 akron1 750
	                IF Lines.getChar(line, i + 1) = "$" THEN
9210 akron1 751
	                    depth := 3
752
	                ELSE
753
	                    depth := 1
754
	                END;
755
	                INC(i);
756
	                PrintComment(text, line, depth, i, 1, y, backColor);
757
	                cond := 0
758
	            ELSIF c = "#" THEN
759
	                k := i;
760
	                INC(i);
9659 akron1 761
	                WHILE U.isDigit(Lines.getChar(line, i)) DO
9210 akron1 762
	                    INC(i)
763
	                END;
764
	                DEC(i);
765
	                PrintLex(text, line, k, i, y, colors.string, backColor);
766
	                cond := 0
767
	            ELSIF c = "$" THEN
9659 akron1 768
	                IF (i > 0 ) & (Lines.getChar(line, i - 1) = "#") THEN
9210 akron1 769
	                    color := colors.string
770
	                ELSE
771
	                    color := colors.num
772
	                END;
773
	                k := i;
774
	                INC(i);
9659 akron1 775
	                WHILE U.isHex(cap(Lines.getChar(line, i))) DO
9210 akron1 776
	                    INC(i)
777
	                END;
778
	                DEC(i);
779
	                PrintLex(text, line, k, i, y, color, backColor);
780
	                cond := 0
781
	            ELSIF U.isDigit(c) THEN
782
	                k := i;
9659 akron1 783
	                WHILE U.isDigit(Lines.getChar(line, i)) DO
9210 akron1 784
	                    INC(i)
785
	                END;
9659 akron1 786
	                IF Lines.getChar(line, i) = "." THEN
9210 akron1 787
	                    INC(i);
9659 akron1 788
	                    IF Lines.getChar(line, i) = "." THEN
9210 akron1 789
	                        DEC(i)
790
	                    END;
9659 akron1 791
	                    WHILE U.isDigit(Lines.getChar(line, i)) DO
9210 akron1 792
	                        INC(i)
793
	                    END;
9659 akron1 794
	                    IF cap(Lines.getChar(line, i)) = "E" THEN
9210 akron1 795
	                        INC(i);
9659 akron1 796
	                        IF (Lines.getChar(line, i) = "-") OR (Lines.getChar(line, i) = "+") THEN
9210 akron1 797
	                            INC(i)
798
	                        END;
9659 akron1 799
	                        WHILE U.isDigit(Lines.getChar(line, i)) DO
9210 akron1 800
	                            INC(i)
801
	                        END
802
	                    END
803
	                END;
804
	                DEC(i);
805
	                PrintLex(text, line, k, i, y, colors.num, backColor);
806
	                cond := 0
807
	            ELSIF (U.isLetter(c) OR (c = "_")) THEN
808
	                ident(text, i, i, y, line, backColor, Lang.isCS(lang));
809
	                cond := 0
810
	            ELSE
811
	                cond := 0
812
	            END
813
	        ELSIF depth IN {1, 3} THEN
814
	            IF c = "}" THEN
815
	                depth := 0
816
	            END
817
	        ELSIF depth = 2 THEN
818
	            IF c = "*" THEN
819
	                cond := 1
820
	            ELSIF (c = ")") & (cond = 1) THEN
821
	                depth := 0;
822
	                cond := 0
823
	            ELSE
824
	                cond := 0
825
	            END
826
	        END
8728 leency 827
 
828
        ELSIF lang = Lang.langIni THEN
829
 
9210 akron1 830
	        IF depth = 0 THEN
9674 akron1 831
	            IF ((c = ";") OR (c = "#")) & (leadingSpaces(line) = i) THEN
9210 akron1 832
	                PrintLex(text, line, i, n, y, colors.comment, backColor);
833
	                i := n
834
	            ELSIF c = '"' THEN
835
	                String(text, line, i, y, backColor)
836
	            ELSIF c = "[" THEN
837
	                depth := 1;
838
	                INC(i);
839
	                PrintComment(text, line, depth, i, 1, y, backColor)
840
	            ELSIF U.isDigit(c) THEN
841
	                k := i;
9659 akron1 842
	                WHILE U.isDigit(Lines.getChar(line, i)) DO
9210 akron1 843
	                    INC(i)
844
	                END;
845
	                DEC(i);
846
	                PrintLex(text, line, k, i, y, colors.num, backColor)
847
	            ELSIF (U.isLetter(c) OR (c = "_")) THEN
848
	                ident(text, i, i, y, line, backColor, Lang.isCS(lang))
849
	            END
850
	        ELSIF depth = 1 THEN
851
	            IF c = "]" THEN
852
	                depth := 0
853
	            END
854
	        END
8728 leency 855
 
856
        END;
857
        INC(i)
858
    END
859
END parse;
860
 
861
 
9599 akron1 862
PROCEDURE plain (text: tText): CB.tBuffer;
8728 leency 863
VAR
864
    buf: CB.tBuffer;
865
    size: INTEGER;
866
    line: tLine;
867
BEGIN
868
    size := 0;
869
    line := text.first(tLine);
870
    WHILE line # NIL DO
871
        line.pos := size;
872
        INC(size, line.length);
873
        NextLine(line);
874
        IF line # NIL THEN
875
            INC(size, CB.lenEOL)
876
        END
877
    END;
9599 akron1 878
    buf := CB.create(size + 2);
8728 leency 879
    line := text.first(tLine);
880
    WHILE line # NIL DO
881
        CB.append(buf, line, 0, line.length - 1);
882
        NextLine(line);
883
        IF line # NIL THEN
884
            CB.eol(buf)
885
        END
886
    END;
9599 akron1 887
    CB.appends(buf, 0X, 0, 0);
888
    CB.appends(buf, 0X, 0, 0)
8728 leency 889
    RETURN buf
890
END plain;
891
 
892
 
893
PROCEDURE search* (text: tText; s: ARRAY OF WCHAR; cs, whole: BOOLEAN): BOOLEAN;
894
VAR
9599 akron1 895
	pos: List.tItem;
896
	res: BOOLEAN;
897
	plainText, idxData: Search.tBuffer;
8728 leency 898
BEGIN
9599 akron1 899
	res := TRUE;
900
	plainText := NIL;
901
	idxData := NIL;
902
	WHILE text.foundList.count # 0 DO
903
		pos := List.pop(text.foundList);
904
		DISPOSE(pos)
905
	END;
906
	text.whole := whole;
907
	text.cs := cs;
908
	text.searchText := s;
909
	IF ~cs THEN
910
		U.upcase16(text.searchText)
911
	END;
912
	IF text.searchText # "" THEN
913
		plainText := plain(text);
9674 akron1 914
		idxData := Search.index(plainText, idxTable, cs);
915
		Search.find(plainText, idxTable, text.searchText, whole, text.foundList);
9599 akron1 916
		res := text.foundList.count > 0
917
	END;
918
	CB.destroy(plainText);
919
	CB.destroy(idxData);
920
	text.search := FALSE;
921
	text.foundSel := 0
922
	RETURN res
8728 leency 923
END search;
924
 
925
 
926
PROCEDURE modify (text: tText);
927
BEGIN
928
    text.modified := TRUE;
929
    text.comments := TRUE;
930
    text.search := TRUE;
931
    text.guard := TRUE
932
END modify;
933
 
934
 
9336 akron1 935
PROCEDURE setEnc* (text: tText; enc: INTEGER);
936
BEGIN
937
	IF text.enc # enc THEN
938
		ChangeLog.changeInt(text.enc, enc);
939
		text.enc := enc;
940
		modify(text)
941
	END
942
END setEnc;
943
 
944
 
945
PROCEDURE setEol* (text: tText; eol: INTEGER);
946
BEGIN
947
	IF text.eol # eol THEN
948
		ChangeLog.changeInt(text.eol, eol);
949
		text.eol := eol;
950
		modify(text)
951
	END
952
END setEol;
953
 
954
 
955
PROCEDURE getEnc* (text: tText): INTEGER;
956
	RETURN text.enc
957
END getEnc;
958
 
959
 
960
PROCEDURE getEol* (text: tText): INTEGER;
961
	RETURN text.eol
962
END getEol;
963
 
964
 
8728 leency 965
PROCEDURE DelLine (text: tText; line: tLine);
966
BEGIN
967
    List._delete(text, line);
968
    Lines.destroy(line);
969
    modify(text)
970
END DelLine;
971
 
972
 
973
PROCEDURE setSelect (text: tText);
974
BEGIN
975
    IF text.select = text.cursor THEN
976
        text.select2^ := text.cursor^;
977
        text.select := text.select2
978
    END
979
END setSelect;
980
 
981
 
982
PROCEDURE resetSelect* (text: tText);
983
BEGIN
984
    text.select := text.cursor
985
END resetSelect;
986
 
987
 
988
PROCEDURE getLine (text: tText; n: INTEGER): tLine;
989
VAR
9668 akron1 990
	item: List.tItem;
8728 leency 991
BEGIN
9668 akron1 992
	item := List.getItem(text, n)
993
	RETURN item(tLine)
8728 leency 994
END getLine;
995
 
996
 
997
PROCEDURE SetPos* (text: tText; x, y: INTEGER);
998
VAR
9174 akron1 999
    deltaY, n, L, R: INTEGER;
8728 leency 1000
    cursor: pPoint;
9174 akron1 1001
    c: WCHAR;
8728 leency 1002
   (* trimLength: INTEGER; *)
1003
BEGIN
1004
    cursor := text.cursor;
1005
    y := MIN(MAX(y, 0), text.count - 1);
1006
    deltaY := y - cursor.Y;
1007
    IF deltaY # 0 THEN
1008
        cursor.Y := y;
1009
(*        trimLength := Lines.trimLength(text.curLine);
1010
        IF text.curLine.length # trimLength THEN
1011
            Lines.setChar(text.curLine, trimLength, 0X);
1012
            text.curLine.length := trimLength
1013
        END;*)
1014
        IF deltaY = 1 THEN
1015
            NextLine(text.curLine)
1016
        ELSIF deltaY = -1 THEN
1017
            PrevLine(text.curLine)
1018
        ELSE
1019
            text.curLine := getLine(text, y)
1020
        END
1021
    END;
1022
    cursor.X := MIN(MAX(x, 0), text.curLine.length);
9659 akron1 1023
    c := Lines.getChar(text.curLine, cursor.X);
9174 akron1 1024
    IF c = TAB1 THEN
1025
        n := cursor.X;
9659 akron1 1026
        WHILE Lines.getChar(text.curLine, n) = TAB1 DO
9174 akron1 1027
            INC(n)
1028
        END;
1029
        R := n - cursor.X;
1030
        n := cursor.X;
9659 akron1 1031
        WHILE Lines.getChar(text.curLine, n) # TAB DO
9174 akron1 1032
            DEC(n)
1033
        END;
1034
        L := cursor.X - n;
1035
        IF L < R THEN
1036
            DEC(cursor.X, L)
1037
        ELSE
1038
            INC(cursor.X, R)
1039
        END
1040
    END;
8728 leency 1041
    IF text.scroll.Y > cursor.Y THEN
1042
        text.scroll.Y := cursor.Y
1043
    ELSIF text.scroll.Y + textsize.Y <= cursor.Y THEN
1044
        text.scroll.Y := cursor.Y - textsize.Y + 1
1045
    END;
1046
    IF text.scroll.X > cursor.X THEN
1047
        text.scroll.X := cursor.X
1048
    ELSIF text.scroll.X + textsize.X <= cursor.X THEN
1049
        text.scroll.X := cursor.X - textsize.X + 1
1050
    END;
1051
    IF (text.select.Y = cursor.Y) & (text.select.X > text.curLine.length) THEN
1052
        text.select.X := text.curLine.length
1053
    END;
1054
    setSelect(text);
1055
    text.foundSel := 0;
1056
    ShowCursor;
1057
    text.CurX := -1
1058
END SetPos;
1059
 
1060
 
1061
PROCEDURE getSelect (text: tText; VAR selBeg, selEnd: tPoint);
1062
BEGIN
1063
    selBeg := text.cursor^;
1064
    selEnd := text.select^;
1065
    IF (selBeg.Y > selEnd.Y) OR (selBeg.Y = selEnd.Y) & (selBeg.X > selEnd.X) THEN
1066
        selBeg := text.select^;
1067
        selEnd := text.cursor^
1068
    END
1069
END getSelect;
1070
 
1071
 
1072
PROCEDURE selected* (text: tText): BOOLEAN;
1073
    RETURN (text.cursor.X # text.select.X) OR (text.cursor.Y # text.select.Y)
1074
END selected;
1075
 
1076
 
1077
PROCEDURE delSelect (text: tText);
1078
VAR
1079
    selBeg, selEnd: tPoint;
1080
    line, last, cur: tLine;
1081
BEGIN
1082
    getSelect(text, selBeg, selEnd);
1083
    IF (selBeg.Y = selEnd.Y) & (selBeg.X < selEnd.X) THEN
1084
        line := text.curLine;
1085
        Lines.delCharN(line, selBeg.X, selEnd.X - selBeg.X);
1086
        Lines.modify(line);
1087
        text.cursor^ := selBeg;
1088
        resetSelect(text);
1089
        SetPos(text, text.cursor.X, text.cursor.Y);
1090
        modify(text)
1091
    ELSIF selBeg.Y < selEnd.Y THEN
1092
        SetPos(text, selBeg.X, selBeg.Y);
1093
        line := text.curLine;
1094
        Lines.delCharN(line, selBeg.X, line.length - selBeg.X);
1095
        last := getLine(text, selEnd.Y);
1096
        Lines.delCharN(last, 0, selEnd.X);
1097
        cur := line.next(tLine);
1098
        WHILE cur # last DO
1099
            DelLine(text, cur);
1100
            cur := line.next(tLine)
1101
        END;
1102
        resetSelect(text);
1103
        SetPos(text, text.cursor.X, text.cursor.Y);
1104
        pdelete(text);
1105
        modify(text)
1106
    END;
1107
    resetSelect(text)
1108
END delSelect;
1109
 
1110
 
1111
PROCEDURE delete (text: tText);
1112
VAR
9174 akron1 1113
    i, n: INTEGER;
8728 leency 1114
    nextLine, curLine: tLine;
1115
BEGIN
1116
    IF selected(text) THEN
1117
        delSelect(text)
1118
    ELSE
1119
        i := text.cursor.X;
1120
        curLine := text.curLine;
1121
        IF i < curLine.length THEN
9174 akron1 1122
            n := i;
1123
            INC(i);
9659 akron1 1124
            IF Lines.getChar(curLine, i - 1) = TAB THEN
1125
                WHILE Lines.getChar(curLine, i) = TAB1 DO
9174 akron1 1126
                    INC(i)
1127
                END
1128
            END;
1129
            Lines.delCharN(curLine, n, i - n);
8728 leency 1130
            Lines.modify(curLine);
1131
            modify(text)
1132
        ELSE
1133
            nextLine := curLine.next(tLine);
1134
            IF nextLine # NIL THEN
9174 akron1 1135
                Lines.insert2(curLine, i, nextLine);
1136
                DelLine(text, nextLine);
8728 leency 1137
                Lines.modify(curLine);
9174 akron1 1138
                modify(text)
8728 leency 1139
            END
1140
        END
1141
    END;
1142
    setSelect(text)
1143
END delete;
1144
 
1145
 
9174 akron1 1146
PROCEDURE move (text: tText; d: INTEGER);
1147
VAR
1148
    pos: INTEGER;
1149
BEGIN
1150
    pos := text.cursor.X + d;
9659 akron1 1151
    WHILE Lines.getChar(text.curLine, pos) = TAB1 DO
9174 akron1 1152
        INC(pos, d)
1153
    END;
1154
    SetPos(text, pos, text.cursor.Y)
1155
END move;
1156
 
1157
 
8728 leency 1158
PROCEDURE BkSpace (text: tText);
1159
VAR
9174 akron1 1160
    i, k, n: INTEGER;
1161
    curLine, line, line2: tLine;
8728 leency 1162
BEGIN
1163
    IF selected(text) THEN
1164
        delSelect(text)
1165
    ELSE
1166
        resetSelect(text);
1167
        curLine := text.curLine;
9174 akron1 1168
        IF text.cursor.X > 0 THEN
9668 akron1 1169
        	INC(text.smallChange);
9174 akron1 1170
            i := text.cursor.X;
9671 akron1 1171
            IF autoIndents THEN
1172
	            n := leadingSpaces(curLine)
1173
            ELSE
1174
    	        n := 0
1175
            END;
9175 akron1 1176
            modify(text);
8728 leency 1177
            IF n < i THEN
9174 akron1 1178
                move(text, -1);
1179
                delete(text)
8728 leency 1180
            ELSE
1181
                n := i;
1182
                line := curLine.prev(tLine);
9174 akron1 1183
                line2 := line;
8728 leency 1184
                k := n;
1185
                WHILE (line # NIL) & (k >= n) DO
1186
                    IF Lines.trimLength(line) # 0 THEN
9174 akron1 1187
                        k := leadingSpaces(line);
1188
                        line2 := line;
8728 leency 1189
                    END;
1190
                    PrevLine(line)
1191
                END;
1192
                IF k >= n THEN
1193
                    k := 0
1194
                END;
9174 akron1 1195
                n := k;
1196
                Lines.delCharN(curLine, 0, i);
1197
                Lines.insert3(curLine, 0, k);
1198
                WHILE k > 0 DO
9659 akron1 1199
                    Lines.setChar(curLine, k - 1, Lines.getChar(line2, k - 1));
9174 akron1 1200
                    DEC(k)
1201
                END;
8728 leency 1202
                Lines.modify(curLine);
9174 akron1 1203
                SetPos(text, n, text.cursor.Y)
1204
            END
8728 leency 1205
        ELSE
1206
            PrevLine(curLine);
1207
            IF curLine # NIL THEN
1208
                SetPos(text, curLine.length, text.cursor.Y - 1);
1209
                delete(text)
1210
            END
1211
        END
1212
    END;
1213
    setSelect(text)
1214
END BkSpace;
1215
 
1216
 
1217
PROCEDURE enter (text: tText);
1218
VAR
1219
    n: INTEGER;
9174 akron1 1220
    curLine, newLine, line, line2: tLine;
8728 leency 1221
BEGIN
1222
    delSelect(text);
1223
    newLine := Lines.create(FALSE);
1224
    modify(text);
1225
    curLine := text.curLine;
1226
    IF text.cursor.X < curLine.length THEN
9174 akron1 1227
        Lines.wrap(curLine, newLine, text.cursor.X);
1228
        Lines.modify(curLine)
8728 leency 1229
    END;
1230
    List._insert(text, curLine, newLine);
1231
    SetPos(text, 0, text.cursor.Y + 1);
1232
    line := text.curLine.prev(tLine);
1233
    n := -1;
9671 akron1 1234
    WHILE (line # NIL) & (n = -1) & autoIndents DO
8728 leency 1235
        IF (*line.length*)Lines.trimLength(line) # 0 THEN
9174 akron1 1236
            n := leadingSpaces(line);
1237
            line2 := line
8728 leency 1238
        END;
1239
        PrevLine(line)
1240
    END;
1241
    IF n = -1 THEN
1242
        n := 0
1243
    END;
1244
    Lines.insert3(text.curLine, 0, n);
1245
    SetPos(text, n, text.cursor.Y);
1246
    resetSelect(text);
1247
    WHILE n > 0 DO
9659 akron1 1248
        Lines.setChar(text.curLine, n - 1, Lines.getChar(line2, n - 1));
8728 leency 1249
        DEC(n)
9174 akron1 1250
    END;
9835 akron1 1251
    Lines.modify(newLine);
1252
    SetPos(text, text.cursor.X, text.cursor.Y)
8728 leency 1253
END enter;
1254
 
1255
 
9174 akron1 1256
PROCEDURE incIndent (line: tLine);
1257
VAR
1258
	c: WCHAR;
1259
	i: INTEGER;
1260
BEGIN
1261
	Lines.modify(line);
1262
	Lines.insert3(line, 0, Lines.tab);
1263
	IF Lines.tabs THEN
1264
		c := TAB1
1265
	ELSE
1266
		c := SPACE
1267
	END;
1268
	i := Lines.tab - 1;
1269
	WHILE i >= 0 DO
1270
		Lines.setChar(line, i, c);
1271
		DEC(i)
1272
	END;
1273
	IF Lines.tabs THEN
1274
		Lines.setChar(line, 0, TAB)
1275
	END
1276
END incIndent;
1277
 
1278
 
1279
PROCEDURE decIndent (line: tLine): BOOLEAN;
1280
VAR
1281
	n: INTEGER;
1282
BEGIN
1283
	n := leadingSpaces(line);
1284
	IF n > 0 THEN
1285
		Lines.delCharN(line, 0, MIN(Lines.tab, n));
1286
		Lines.modify(line)
1287
	END
1288
	RETURN n > 0
1289
END decIndent;
1290
 
1291
 
1292
PROCEDURE Indent* (text: tText; incr: BOOLEAN);
1293
VAR
1294
    i: INTEGER;
1295
    line: tLine;
1296
    selBeg, selEnd: tPoint;
1297
    modified: BOOLEAN;
1298
BEGIN
1299
	getSelect(text, selBeg, selEnd);
1300
	i := selEnd.Y - selBeg.Y + 1;
9668 akron1 1301
	line := getLine2(text, selBeg.Y);
9174 akron1 1302
	modified := incr;
1303
	WHILE i > 0 DO
1304
		IF incr THEN
1305
			incIndent(line)
1306
		ELSE
1307
    		modified := decIndent(line) OR modified
1308
		END;
1309
		NextLine(line);
1310
		DEC(i)
1311
	END;
9668 akron1 1312
	line := getLine2(text, selEnd.Y);
9174 akron1 1313
	text.select^ := selBeg;
1314
	text.select.X := 0;
1315
	SetPos(text, line.length, selEnd.Y);
1316
	IF modified THEN
9668 akron1 1317
		INC(text.smallChange);
9174 akron1 1318
   		modify(text)
1319
	END
1320
END Indent;
1321
 
1322
 
8728 leency 1323
PROCEDURE input* (text: tText; code: INTEGER);
1324
VAR
1325
    curLine: tLine;
1326
 
9174 akron1 1327
 
8728 leency 1328
    PROCEDURE tab (text: tText);
1329
    VAR
1330
        i, x: INTEGER;
1331
        curLine: tLine;
9174 akron1 1332
        c: WCHAR;
8728 leency 1333
    BEGIN
9174 akron1 1334
		delSelect(text);
1335
		curLine := text.curLine;
1336
		x := text.cursor.X;
1337
		i := Lines.tab - x MOD Lines.tab;
1338
		Lines.insert3(curLine, x, i);
1339
		SetPos(text, x + i, text.cursor.Y);
1340
		IF Lines.tabs THEN
1341
			c := TAB1
1342
		ELSE
1343
			c := SPACE
1344
		END;
1345
		WHILE i > 0 DO
1346
			Lines.setChar(curLine, x + i - 1, c);
1347
			DEC(i)
1348
		END;
1349
		IF Lines.tabs THEN
1350
			Lines.setChar(curLine, x + i, TAB)
1351
		END;
1352
		Lines.modify(curLine);
1353
		modify(text)
8728 leency 1354
    END tab;
1355
 
9174 akron1 1356
 
8728 leency 1357
BEGIN
1358
    IF (code >= ORD(SPACE)) & (code # 127) THEN
9668 akron1 1359
    	IF ~selected(text) THEN
1360
    		INC(text.smallChange)
1361
    	END;
8728 leency 1362
        delSelect(text);
1363
        curLine := text.curLine;
1364
        Lines.insert(curLine, text.cursor.X, WCHR(code));
9671 akron1 1365
        IF autoBrackets THEN
1366
        	IF code = ORD("(") THEN
1367
        		code := ORD(")")
1368
        	ELSIF code = ORD("[") THEN
1369
        		code := ORD("]")
1370
        	ELSIF code = ORD("{") THEN
1371
        		code := ORD("}")
1372
        	ELSE
1373
        		code := -1
1374
        	END;
1375
        	IF code # -1 THEN
1376
        		Lines.insert(curLine, text.cursor.X + 1, WCHR(code))
1377
        	END
1378
        END;
8728 leency 1379
        Lines.modify(curLine);
1380
        modify(text);
1381
        SetPos(text, text.cursor.X + 1, text.cursor.Y)
1382
    ELSIF code = 8 THEN
9174 akron1 1383
		BkSpace(text)
1384
    ELSIF code = -8 THEN
1385
    	IF selected(text) THEN
1386
    		Indent(text, FALSE)
1387
        END
8728 leency 1388
    ELSIF code = 9 THEN
9174 akron1 1389
    	IF selected(text) THEN
1390
    		Indent(text, TRUE)
1391
    	ELSE
9668 akron1 1392
    		INC(text.smallChange);
9174 akron1 1393
	        tab(text)
1394
        END
8728 leency 1395
    ELSIF code = 13 THEN
1396
        enter(text)
1397
    END
1398
END input;
1399
 
1400
 
1401
PROCEDURE scroll* (text: tText; h, v: INTEGER);
1402
BEGIN
1403
    INC(text.scroll.X, h);
1404
    INC(text.scroll.Y, v);
9050 leency 1405
    text.scroll.X := MIN(MAX(text.scroll.X, 0), text.maxLength);
8728 leency 1406
    text.scroll.Y := MIN(MAX(text.scroll.Y, 0), text.count - 1)
1407
END scroll;
1408
 
1409
 
9180 akron1 1410
PROCEDURE save* (text: tText; name: RW.tFileName): BOOLEAN;
9073 leency 1411
CONST
1412
    tempFile = "/tmp0/1/cedit~.tmp";
8728 leency 1413
VAR
1414
    line: tLine;
1415
    file: RW.tOutput;
1416
    res: BOOLEAN;
9671 akron1 1417
    Len: INTEGER;
8728 leency 1418
BEGIN
9073 leency 1419
    ChangeLog.setGuard(text.edition);
9180 akron1 1420
    file := RW.create(tempFile, text.enc, text.eol);
8728 leency 1421
    IF file # NIL THEN
9073 leency 1422
        ChangeLog.delSaved;
8728 leency 1423
        line := text.first(tLine);
9522 akron1 1424
        WHILE line # NIL DO
9671 akron1 1425
        	IF trimSpace THEN
1426
        		Len := Lines.trimLength(line)
1427
        	ELSE
1428
        		Len := line.length
1429
        	END;
1430
            RW.putString(file, line, Len);
8728 leency 1431
            NextLine(line);
1432
            IF line # NIL THEN
9522 akron1 1433
                RW.newLine(file)
8728 leency 1434
            END
1435
        END;
9522 akron1 1436
        res := RW.close(file)
8728 leency 1437
    ELSE
1438
        res := FALSE
1439
    END;
9073 leency 1440
    IF res THEN
1441
        res := File.Copy(tempFile, name);
1442
        IF res THEN
1443
            text.modified := FALSE;
1444
            ChangeLog.save(text.edition);
9452 akron1 1445
 
1446
	        line := text.first(tLine);
1447
	        WHILE line # NIL DO
1448
	            IF line.modified THEN
1449
	                Lines.save(line)
1450
	            END;
1451
	            NextLine(line)
9522 akron1 1452
	        END
9073 leency 1453
        END
1454
    END;
9522 akron1 1455
    IF File.Delete(tempFile) THEN END;
9073 leency 1456
    IF ~res THEN
1457
        ChangeLog.delCurSaved
1458
    END
8728 leency 1459
    RETURN res
1460
END save;
1461
 
1462
 
1463
PROCEDURE redoGuard (text: tText; guard: tGuard);
1464
BEGIN
1465
    text.edition := guard;
1466
    text.cursor^ := guard.cursor;
1467
    text.select2^ := guard.select2;
1468
    text.scroll := guard.scroll;
1469
    text.CurX := guard.CurX;
1470
    IF guard.selected THEN
1471
        text.select := text.select2
1472
    ELSE
1473
        text.select := text.cursor
1474
    END;
1475
    text.curLine := getLine(text, text.cursor.Y);
1476
    text.comments := TRUE;
1477
    text.search := TRUE
1478
END redoGuard;
1479
 
1480
 
1481
PROCEDURE undo* (text: tText);
1482
VAR
1483
    item: List.tItem;
1484
    guard: tGuard;
1485
BEGIN
1486
    guard := text.edition;
1487
    item := guard.prev;
1488
    WHILE (item # NIL) & ~(item IS tGuard) DO
1489
        item := item.prev
1490
    END;
1491
 
1492
    IF item # NIL THEN
1493
        guard := item(tGuard);
9073 leency 1494
        text.edition := guard
8728 leency 1495
    END;
1496
 
9050 leency 1497
    item := ChangeLog.CL.Log.first;
8728 leency 1498
    WHILE item # guard DO
1499
        ChangeLog.redo(item);
1500
        item := item.next
1501
    END;
1502
    redoGuard(text, guard);
9073 leency 1503
    ChangeLog.setGuard(guard);
9174 akron1 1504
    text.modified := ~guard.saved;
1505
    ShowCursor
8728 leency 1506
END undo;
1507
 
1508
 
1509
PROCEDURE redo* (text: tText);
1510
VAR
1511
    item: List.tItem;
1512
    guard: tGuard;
1513
BEGIN
1514
    guard := text.edition;
1515
    item := guard.next;
1516
    WHILE (item # NIL) & ~(item IS tGuard) DO
1517
        ChangeLog.redo(item);
1518
        item := item.next
1519
    END;
1520
    IF item # NIL THEN
1521
        guard := item(tGuard);
1522
        redoGuard(text, guard)
1523
    END;
9073 leency 1524
    ChangeLog.setGuard(guard);
9174 akron1 1525
    text.modified := ~guard.saved;
1526
    ShowCursor
8728 leency 1527
END redo;
1528
 
1529
 
9462 akron1 1530
PROCEDURE getSelCnt* (text: tText; VAR chars, lines: INTEGER);
1531
VAR
1532
	selBeg, selEnd: tPoint;
1533
	first, last, line: tLine;
1534
 
1535
	PROCEDURE charCnt (line: tLine; first, last: INTEGER): INTEGER;
1536
	VAR
1537
		i, res: INTEGER;
1538
	BEGIN
1539
		res := 0;
1540
		FOR i := first TO last DO
9659 akron1 1541
			IF Lines.getChar(line, i) # TAB1 THEN
9462 akron1 1542
				INC(res)
1543
			END
1544
		END
1545
		RETURN res
1546
	END charCnt;
1547
 
1548
BEGIN
1549
	IF selected(text) THEN
1550
		getSelect(text, selBeg, selEnd);
9668 akron1 1551
		first := getLine2(text, selBeg.Y);
1552
		last  := getLine2(text, selEnd.Y);
9462 akron1 1553
		lines := selEnd.Y - selBeg.Y + 1;
1554
 
1555
		IF lines > 1 THEN
1556
			chars := charCnt(first, selBeg.X, first.length - 1) + charCnt(last, 0, selEnd.X - 1) + lenEOL;
9659 akron1 1557
			line := first.next(tLine);
1558
			WHILE line # last DO
1559
				INC(chars, charCnt(line, 0, line.length - 1) + lenEOL);
1560
				NextLine(line)
1561
			END
9462 akron1 1562
		ELSE
9659 akron1 1563
			chars := charCnt(first, selBeg.X, selEnd.X - 1)
9462 akron1 1564
		END
1565
	ELSE
1566
		chars := 0;
1567
		lines := 0
1568
	END
1569
END getSelCnt;
1570
 
1571
 
8728 leency 1572
PROCEDURE copy (text: tText);
1573
VAR
1574
    selBeg, selEnd: tPoint;
1575
    first, line: tLine;
1576
    cnt, n: INTEGER;
1577
    buffer: CB.tBuffer;
1578
 
1579
 
1580
    PROCEDURE append (buffer: CB.tBuffer; line: tLine; first, last: INTEGER);
1581
    BEGIN
1582
        IF first <= last THEN
1583
            CB.append(buffer, line, first, last)
1584
        ELSE
1585
            IF U.OS = "KOS" THEN
1586
                CB.appends(buffer, SPACE, 0, 0)
1587
            END
1588
        END
1589
    END append;
1590
 
1591
 
1592
BEGIN
1593
    getSelect(text, selBeg, selEnd);
1594
 
9668 akron1 1595
    first := getLine2(text, selBeg.Y);
8728 leency 1596
    line := first;
1597
 
1598
    n := selEnd.Y - selBeg.Y;
1599
    cnt := 0;
1600
    WHILE n >= 0 DO
9457 akron1 1601
        INC(cnt, line.length + (lenEOL + ORD(U.OS = "KOS")));
8728 leency 1602
        NextLine(line);
1603
        DEC(n)
1604
    END;
1605
 
9599 akron1 1606
    buffer := CB.create(cnt + 2); (* +2 wchars EOT *)
8728 leency 1607
 
1608
    n := selEnd.Y - selBeg.Y;
1609
    line := first;
1610
    IF n = 0 THEN
9457 akron1 1611
        append(buffer, line, selBeg.X, selEnd.X - 1)
8728 leency 1612
    ELSE
1613
        append(buffer, line, selBeg.X, line.length - 1);
1614
        REPEAT
1615
            DEC(n);
1616
            CB.eol(buffer);
1617
            NextLine(line);
1618
            IF n > 0 THEN
1619
                append(buffer, line, 0, line.length - 1)
1620
            END
1621
        UNTIL n = 0;
1622
        append(buffer, line, 0, selEnd.X - 1)
1623
    END;
1624
    CB.eot(buffer);
1625
    CB.put(buffer);
1626
    CB.destroy(buffer)
1627
END copy;
1628
 
1629
 
1630
PROCEDURE paste (text: tText);
1631
VAR
1632
    line, newLine, curLine: tLine;
9174 akron1 1633
    w: INTEGER;
8728 leency 1634
    cliptext: RW.tInput;
1635
    eol: BOOLEAN;
1636
    cursor: pPoint;
9174 akron1 1637
 
1638
 
1639
    PROCEDURE lineWidth (line: tLine; pos: INTEGER): INTEGER;
1640
    VAR
1641
    	i, res: INTEGER;
1642
    	c: WCHAR;
1643
    BEGIN
1644
    	res := pos;
1645
    	i := 0;
1646
    	REPEAT
9659 akron1 1647
	    	c := Lines.getChar(line, i);
9174 akron1 1648
	    	IF c = TAB THEN
1649
	    		INC(res, Lines.tab - res MOD Lines.tab)
1650
	    	ELSIF c # TAB1 THEN
1651
	    		INC(res)
1652
	    	END;
1653
	    	INC(i)
1654
    	UNTIL c = 0X
1655
    	RETURN res - pos - 1
1656
    END lineWidth;
1657
 
1658
 
8728 leency 1659
BEGIN
1660
    line := Lines.create(TRUE);
1661
    cliptext := RW.clipboard();
1662
    delSelect(text);
1663
    cursor := text.cursor;
9174 akron1 1664
    WHILE (cliptext # NIL) & (RW.getString(cliptext, line, Lines.tabs, eol) >= 0) DO
1665
        IF line.length > 0 THEN
1666
        	w := lineWidth(line, cursor.X);
8728 leency 1667
            Lines.insert2(text.curLine, cursor.X, line);
1668
            Lines.modify(text.curLine);
1669
            modify(text);
9174 akron1 1670
            SetPos(text, cursor.X + w, cursor.Y);
8728 leency 1671
            resetSelect(text)
1672
        END;
1673
        IF eol THEN
1674
            newLine := Lines.create(FALSE);
1675
            modify(text);
1676
            curLine := text.curLine;
1677
            IF cursor.X < curLine.length THEN
9174 akron1 1678
                Lines.wrap(curLine, newLine, cursor.X);
1679
                Lines.modify(curLine)
8728 leency 1680
            END;
1681
            List._insert(text, curLine, newLine);
9174 akron1 1682
            Lines.modify(newLine);
8728 leency 1683
            SetPos(text, 0, cursor.Y + 1);
1684
            resetSelect(text)
1685
        END;
1686
        Lines.destroy(line);
1687
        line := Lines.create(TRUE)
1688
    END;
9818 akron1 1689
    SetPos(text, cursor.X, cursor.Y);
8728 leency 1690
    Lines.destroy(line);
1691
    RW.destroy(cliptext)
1692
END paste;
1693
 
1694
 
1695
PROCEDURE searchScroll (text: tText; n: INTEGER);
1696
BEGIN
1697
    IF n - text.scroll.Y > textsize.Y - 1 THEN
1698
        text.scroll.Y := MAX(n - 2 * textsize.Y DIV 3, 0)
1699
    ELSIF n < text.scroll.Y THEN
1700
        text.scroll.Y := MAX(n - textsize.Y DIV 3, 0)
1701
    END
1702
END searchScroll;
1703
 
1704
 
1705
PROCEDURE goto* (text: tText; n: INTEGER): BOOLEAN;
1706
VAR
1707
    res: BOOLEAN;
1708
BEGIN
1709
    DEC(n);
1710
    IF (0 <= n) & (n < text.count) THEN
1711
        resetSelect(text);
1712
        searchScroll(text, n);
1713
        SetPos(text, 0, n);
1714
        res := TRUE
1715
    ELSE
1716
        res := FALSE
1717
    END
1718
    RETURN res
1719
END goto;
1720
 
1721
 
9060 leency 1722
PROCEDURE toggleLabel* (text: tText);
1723
BEGIN
1724
    text.curLine.label := ~text.curLine.label
1725
END toggleLabel;
1726
 
1727
 
1728
PROCEDURE gotoLabel* (text: tText; frw: BOOLEAN);
1729
VAR
1730
    line: tLine;
1731
    n: INTEGER;
9073 leency 1732
 
1733
    PROCEDURE search (VAR line: tLine; VAR n: INTEGER; frw: BOOLEAN);
1734
    BEGIN
1735
        IF frw THEN
1736
            WHILE (line # NIL) & ~line.label DO
1737
                NextLine(line);
1738
                INC(n)
1739
            END
1740
        ELSE
1741
            WHILE (line # NIL) & ~line.label DO
1742
                PrevLine(line);
1743
                DEC(n)
1744
            END
1745
        END
1746
    END search;
1747
 
9060 leency 1748
BEGIN
1749
    n := text.cursor.Y;
1750
    line := text.curLine;
1751
    IF frw THEN
9073 leency 1752
        NextLine(line);
1753
        INC(n)
9060 leency 1754
    ELSE
9073 leency 1755
        PrevLine(line);
1756
        DEC(n)
9060 leency 1757
    END;
9073 leency 1758
    search(line, n, frw);
1759
    IF line = NIL THEN
1760
        IF frw THEN
1761
            n := 0;
1762
            line := text.first(tLine)
1763
        ELSE
1764
            n := text.count - 1;
1765
            line := text.last(tLine)
1766
        END;
1767
        search(line, n, frw)
1768
    END;
9060 leency 1769
    IF line # NIL THEN
1770
        IF goto(text, n + 1) THEN END
1771
    END
1772
END gotoLabel;
1773
 
1774
 
8728 leency 1775
PROCEDURE changeCase (text: tText; upper: BOOLEAN);
1776
VAR
1777
    i: INTEGER;
1778
    line: tLine;
9674 akron1 1779
    func: Lines.fConvert;
8728 leency 1780
BEGIN
1781
    line := text.curLine;
1782
    i := text.cursor.X - 1;
1783
 
9659 akron1 1784
    WHILE (i >= 0) & U.isLetter(Lines.getChar(line, i)) DO
8728 leency 1785
        DEC(i)
1786
    END;
1787
 
9674 akron1 1788
    IF upper THEN
1789
    	func := U.cap
1790
    ELSE
1791
    	func := U.low
1792
    END;
1793
 
1794
    IF Lines.convert(line, i + 1, text.cursor.X - 1, func) THEN
9668 akron1 1795
    	INC(text.smallChange);
8728 leency 1796
        modify(text)
1797
    END
1798
END changeCase;
1799
 
1800
 
1801
PROCEDURE chCase* (text: tText; upper: BOOLEAN);
1802
VAR
1803
    selBeg, selEnd: tPoint;
1804
    first, line: Lines.tLine;
1805
    cnt: INTEGER;
9674 akron1 1806
    func: Lines.fConvert;
8728 leency 1807
    modified: BOOLEAN;
1808
BEGIN
1809
    modified := FALSE;
1810
    IF selected(text) THEN
1811
        getSelect(text, selBeg, selEnd);
9668 akron1 1812
        first := getLine2(text, selBeg.Y);
8728 leency 1813
        line := first;
1814
        cnt := selEnd.Y - selBeg.Y;
9674 akron1 1815
 
1816
	    IF upper THEN
1817
	    	func := U.cap
1818
	    ELSE
1819
	    	func := U.low
1820
	    END;
1821
 
8728 leency 1822
        IF cnt = 0 THEN
9674 akron1 1823
            IF Lines.convert(line, selBeg.X, selEnd.X - 1, func) THEN
8728 leency 1824
                modified := TRUE
1825
            END
1826
        ELSE
9674 akron1 1827
            IF Lines.convert(line, selBeg.X, line.length - 1, func) THEN
8728 leency 1828
                modified := TRUE
1829
            END;
1830
            WHILE cnt > 1 DO
1831
                NextLine(line);
9674 akron1 1832
                IF Lines.convert(line, 0, line.length - 1, func) THEN
8728 leency 1833
                    modified := TRUE
1834
                END;
1835
                DEC(cnt)
1836
            END;
1837
            NextLine(line);
9674 akron1 1838
            IF Lines.convert(line, 0, selEnd.X - 1, func) THEN
8728 leency 1839
                modified := TRUE
1840
            END
1841
        END
1842
    END;
1843
    IF modified THEN
9668 akron1 1844
    	INC(text.smallChange);
8728 leency 1845
        modify(text)
1846
    END
1847
END chCase;
1848
 
1849
 
1850
PROCEDURE UpDown (text: tText; step: INTEGER);
1851
VAR
1852
    temp: INTEGER;
1853
BEGIN
1854
    IF text.CurX = -1 THEN
1855
        text.CurX := text.cursor.X
1856
    END;
1857
    temp := text.CurX;
1858
    SetPos(text, temp, text.cursor.Y + step);
1859
    text.CurX := temp
1860
END UpDown;
1861
 
1862
 
1863
PROCEDURE delLine* (text: tText);
1864
BEGIN
9668 akron1 1865
	text.smallChange := 2;
8728 leency 1866
    resetSelect(text);
1867
    IF text.curLine.length > 0 THEN
1868
        Lines.delCharN(text.curLine, 0, text.curLine.length)
1869
    END;
1870
    SetPos(text, 0, text.cursor.Y);
1871
    IF text.cursor.Y = text.count - 1 THEN
1872
        BkSpace(text)
1873
    ELSE
1874
        delete(text)
1875
    END
1876
END delLine;
1877
 
1878
 
9174 akron1 1879
PROCEDURE dupLine* (text: tText);
9010 leency 1880
VAR
1881
    newLine, curLine: tLine;
1882
BEGIN
1883
    curLine := text.curLine;
1884
    newLine := Lines.create(FALSE);
1885
    modify(text);
1886
    Lines.insert3(newLine, 0, curLine.length);
1887
    List._insert(text, curLine, newLine);
9174 akron1 1888
    Lines.move(curLine, newLine);
1889
    Lines.modify(newLine)
9010 leency 1890
END dupLine;
1891
 
1892
 
9413 akron1 1893
PROCEDURE MoveLines* (text: tText; down: BOOLEAN);
1894
VAR
9560 akron1 1895
	last, first, line: tLine;
9413 akron1 1896
	selBeg, selEnd, temp: tPoint;
9560 akron1 1897
	step: INTEGER;
9413 akron1 1898
	frw: BOOLEAN;
1899
BEGIN
1900
	getSelect(text, selBeg, selEnd);
9560 akron1 1901
	IF ((selBeg.Y > 0) & ~down OR (selEnd.Y < text.count - 1) & down) THEN
1902
		modify(text);
1903
		step := ORD(down)*2 - 1;
1904
		IF selBeg.Y # selEnd.Y THEN
1905
			frw := (text.cursor.X = selEnd.X) & (text.cursor.Y = selEnd.Y);
1906
 
9413 akron1 1907
			IF down # frw THEN
1908
				temp := text.cursor^;
1909
				SetPos(text, 0, text.select.Y);
1910
				setSelect(text);
1911
				text.select^ := temp
1912
			END;
9560 akron1 1913
 
1914
			ASSERT(selBeg.Y < selEnd.Y);
1915
 
1916
			first := getLine(text, selBeg.Y);
9413 akron1 1917
			last := getLine(text, selEnd.Y);
9560 akron1 1918
 
1919
			line := first;
1920
			Lines.modify(line);
1921
			REPEAT
1922
				NextLine(line);
1923
				Lines.modify(line)
1924
			UNTIL line = last;
1925
 
1926
			IF down THEN
1927
				text.curLine := last.prev(tLine)
1928
			ELSE
1929
				text.curLine := first.next(tLine)
1930
			END;
9413 akron1 1931
			selBeg.X := 0;
1932
			selEnd.X := last.length;
9560 akron1 1933
			IF down THEN
1934
				last := last.next(tLine);
1935
				List._delete(text, last);
1936
				List._insert(text, first.prev, last)
1937
			ELSE
1938
				first := first.prev(tLine);
1939
				List._delete(text, first);
1940
				List._insert(text, last, first)
1941
			END;
1942
			IF down THEN
1943
				temp := selBeg;
1944
				selBeg := selEnd;
1945
				selEnd := temp;
1946
			END;
1947
			SetPos(text, selBeg.X, selBeg.Y + step);
1948
			setSelect(text);
1949
			text.select.X := selEnd.X;
1950
			text.select.Y := selEnd.Y + step
9413 akron1 1951
		ELSE
9560 akron1 1952
			first := getLine(text, selBeg.Y);
1953
			Lines.modify(first);
1954
			IF down THEN
1955
				last := first.next(tLine)
1956
			ELSE
1957
				last := first.prev.prev(tLine)
1958
			END;
1959
			List._delete(text, first);
1960
			List._insert(text, last, first);
1961
			INC(text.cursor.Y, step);
1962
			INC(text.select.Y, step);
1963
			SetPos(text, text.cursor.X, text.cursor.Y)
1964
		END
9413 akron1 1965
	END
1966
END MoveLines;
1967
 
1968
 
9010 leency 1969
PROCEDURE isWordChar (c: WCHAR): BOOLEAN;
1970
    RETURN U.isLetter(c) OR U.isDigit(c) OR (c = "_")
1971
END isWordChar;
1972
 
1973
 
9197 akron1 1974
PROCEDURE getSelectedText* (text: tText; VAR s: ARRAY OF WCHAR);
1975
VAR
1976
    n: INTEGER;
1977
    selBeg, selEnd: tPoint;
1978
BEGIN
1979
	s[0] := 0X;
1980
    IF selected(text) & (text.cursor.Y = text.select.Y) THEN
1981
        getSelect(text, selBeg, selEnd);
1982
        n := getString(text.curLine, selBeg.X, selEnd.X - selBeg.X, s)
1983
    END
1984
END getSelectedText;
1985
 
1986
 
9010 leency 1987
PROCEDURE wordSel* (text: tText);
1988
VAR
1989
    n, i, x1, x2: INTEGER;
1990
    selBeg, selEnd: tPoint;
1991
    str: tString;
1992
    curLine: tLine;
1993
BEGIN
1994
    curLine := text.curLine;
1995
    IF selected(text) & (text.cursor.Y = text.select.Y) THEN
1996
        getSelect(text, selBeg, selEnd);
1997
        x1 := selBeg.X;
1998
        x2 := selEnd.X;
1999
        n := getString(curLine, x1, x2 - x1, str);
2000
    ELSE
2001
        str := ""
2002
    END;
2003
    IF str # "" THEN
2004
        i := 0;
2005
        WHILE (i < n) & isWordChar(str[i]) DO
2006
            INC(i)
2007
        END;
2008
        IF (i # n) OR
9659 akron1 2009
            ((x1 > 0) & isWordChar(Lines.getChar(curLine, x1 - 1))) OR
2010
            ((x2 < curLine.length) & isWordChar(Lines.getChar(curLine, x2))) THEN
9010 leency 2011
            str := ""
2012
        END
2013
    END;
9668 akron1 2014
    IF text.searchText # str THEN
2015
    	text.smallMove := FALSE
2016
    END;
9050 leency 2017
    IF search(text, str, Lang.isCS(text.lang), TRUE) THEN END
9010 leency 2018
END wordSel;
2019
 
2020
 
9336 akron1 2021
PROCEDURE getWordPos (line: tLine; pos: INTEGER): INTEGER;
2022
VAR
2023
	c: WCHAR;
2024
BEGIN
9659 akron1 2025
	c := Lines.getChar(line, pos);
9336 akron1 2026
	IF isWordChar(c) THEN
9659 akron1 2027
		WHILE (pos < line.length) & isWordChar(Lines.getChar(line, pos)) DO
9336 akron1 2028
			INC(pos)
2029
		END
2030
	ELSIF Lines.isSpace(c) THEN
9659 akron1 2031
		WHILE (pos < line.length) & Lines.isSpace(Lines.getChar(line, pos)) DO
9336 akron1 2032
			INC(pos)
2033
		END
2034
	ELSE
9659 akron1 2035
		WHILE (pos < line.length) & ~Lines.isSpace(Lines.getChar(line, pos)) & ~isWordChar(Lines.getChar(line, pos)) DO
9336 akron1 2036
			INC(pos)
2037
		END
2038
	END
2039
	RETURN pos
2040
END getWordPos;
2041
 
2042
 
9073 leency 2043
PROCEDURE key* (text: tText; code: INTEGER; shift, ctrl: BOOLEAN);
9174 akron1 2044
VAR
9336 akron1 2045
	n, wPos: INTEGER;
9668 akron1 2046
	scrX, scrY: INTEGER;
2047
	resSel: BOOLEAN;
8728 leency 2048
BEGIN
9668 akron1 2049
	resSel := FALSE;
9073 leency 2050
    IF shift THEN
8728 leency 2051
        setSelect(text)
2052
    ELSE
2053
        IF (33 <= code) & (code <= 40) THEN
9413 akron1 2054
        	IF ~(((code = 38) OR (code = 40)) & ctrl) THEN
9668 akron1 2055
        		resSel := selected(text);
9413 akron1 2056
	            resetSelect(text)
2057
            END
8728 leency 2058
        END
2059
    END;
2060
 
2061
    CASE code OF
2062
    |33:
9073 leency 2063
        IF ctrl THEN
8728 leency 2064
            UpDown(text, text.scroll.Y - text.cursor.Y)
2065
        ELSE
2066
            text.scroll.Y := MAX(text.scroll.Y - textsize.Y, 0);
2067
            UpDown(text, -textsize.Y)
2068
        END
2069
    |34:
9073 leency 2070
        IF ctrl THEN
8728 leency 2071
            UpDown(text, MIN(text.scroll.Y + textsize.Y - 1, text.count - 1) - text.cursor.Y)
2072
        ELSE
2073
            text.scroll.Y := MIN(text.scroll.Y + textsize.Y, text.count - 1);
2074
            UpDown(text, textsize.Y)
2075
        END
2076
    |35:
9073 leency 2077
        IF ctrl THEN
8728 leency 2078
            SetPos(text, text.last(tLine).length, text.count - 1)
2079
        ELSE
2080
            SetPos(text, text.curLine.length, text.cursor.Y)
2081
        END
2082
    |36:
9073 leency 2083
        IF ctrl THEN
8728 leency 2084
            SetPos(text, 0, 0)
2085
        ELSE
9174 akron1 2086
        	n := leadingSpaces(text.curLine);
9659 akron1 2087
        	IF text.cursor.X <= n THEN
2088
	            n := 0
2089
        	END;
2090
        	SetPos(text, n, text.cursor.Y)
8728 leency 2091
        END
2092
    |37:
2093
        IF (text.cursor.X = 0) & (text.curLine.prev # NIL) THEN
2094
            SetPos(text, text.curLine.prev(tLine).length, text.cursor.Y - 1)
2095
        ELSE
9668 akron1 2096
        	scrX := text.scroll.X;
2097
        	scrY := text.scroll.Y;
9336 akron1 2098
        	IF ctrl THEN
2099
        		wPos := 0;
2100
        		REPEAT
2101
        			n := wPos;
2102
        			wPos := getWordPos(text.curLine, wPos)
2103
        		UNTIL wPos >= text.cursor.X;
2104
				move(text, n - text.cursor.X)
2105
        	ELSE
2106
            	move(text, -1)
9668 akron1 2107
            END;
2108
            text.smallMove := (scrX = text.scroll.X) & (scrY = text.scroll.Y) & ~resSel
8728 leency 2109
        END
2110
    |38:
9073 leency 2111
        IF ctrl THEN
9413 akron1 2112
            MoveLines(text, FALSE)
9010 leency 2113
        ELSE
2114
            UpDown(text, -1)
2115
        END
8728 leency 2116
    |39:
2117
        IF (text.cursor.X = text.curLine.length) & (text.curLine.next # NIL) THEN
2118
            SetPos(text, 0, text.cursor.Y + 1)
2119
        ELSE
9668 akron1 2120
        	scrX := text.scroll.X;
2121
        	scrY := text.scroll.Y;
9336 akron1 2122
        	IF ctrl THEN
2123
				move(text, getWordPos(text.curLine, text.cursor.X) - text.cursor.X)
2124
        	ELSE
2125
            	move(text, 1)
9668 akron1 2126
        	END;
2127
        	text.smallMove := (scrX = text.scroll.X) & (scrY = text.scroll.Y) & ~resSel
8728 leency 2128
        END
2129
    |40:
9073 leency 2130
        IF ctrl THEN
9413 akron1 2131
            MoveLines(text, TRUE)
9010 leency 2132
        ELSE
2133
            UpDown(text, 1)
2134
        END
2135
    |46:
9073 leency 2136
        IF ctrl THEN
9010 leency 2137
            delLine(text)
2138
        ELSE
9668 akron1 2139
        	IF ~selected(text) & (text.cursor.X < text.curLine.length) THEN
2140
        		INC(text.smallChange)
2141
        	END;
9174 akron1 2142
            delete(text);
2143
            ShowCursor
9010 leency 2144
        END
9659 akron1 2145
    |ORD("C"), ORD("X"):
9073 leency 2146
        IF ctrl THEN
8728 leency 2147
            IF selected(text) THEN
2148
                copy(text);
9659 akron1 2149
                IF code = ORD("X") THEN
2150
                	delSelect(text)
2151
                END
8728 leency 2152
            END
2153
        END
2154
    |ORD("V"):
9073 leency 2155
        IF ctrl THEN
8728 leency 2156
            IF CB.available() THEN
2157
                paste(text)
2158
            END
2159
        END
2160
    |ORD("A"):
9073 leency 2161
        IF ctrl THEN
8728 leency 2162
            text.select2.X := 0;
2163
            text.select2.Y := 0;
2164
            text.select := text.select2;
2165
            SetPos(text, text.last(tLine).length, text.count - 1)
2166
        END
2167
    |ORD("L"), ORD("U"):
9073 leency 2168
        IF ctrl THEN
9174 akron1 2169
        	IF selected(text) THEN
2170
            	chCase(text, code = ORD("U"))
2171
            ELSE
2172
            	changeCase(text, code = ORD("U"))
2173
            END;
2174
            ShowCursor
8728 leency 2175
        END
9010 leency 2176
    |ORD("D"):
9073 leency 2177
        IF ctrl THEN
9010 leency 2178
            dupLine(text)
2179
        END
8728 leency 2180
    ELSE
2181
    END
2182
END key;
2183
 
2184
 
2185
PROCEDURE mouse* (text: tText; x, y: INTEGER);
2186
VAR
2187
    cursorX: INTEGER;
2188
BEGIN
2189
    DEC(x, padding.left);
2190
    DEC(y, padding.top);
2191
    cursorX := (x*2) DIV charWidth;
2192
    SetPos(text, cursorX DIV 2 + cursorX MOD 2 + text.scroll.X, y DIV charHeight + text.scroll.Y)
2193
END mouse;
2194
 
2195
 
2196
PROCEDURE selectWord* (text: tText);
2197
VAR
2198
    cursorX, x1, x2: INTEGER;
2199
    line: tLine;
2200
BEGIN
2201
    resetSelect(text);
2202
    cursorX := text.cursor.X;
2203
    line := text.curLine;
2204
    x1 := cursorX - 1;
9659 akron1 2205
    IF (cursorX < line.length) & isWordChar(Lines.getChar(line, cursorX)) THEN
8728 leency 2206
        x2 := cursorX;
9659 akron1 2207
        WHILE (x2 < line.length) & isWordChar(Lines.getChar(line, x2)) DO
8728 leency 2208
            INC(x2)
2209
        END
2210
    ELSE
9659 akron1 2211
        WHILE (x1 >= 0) & ~isWordChar(Lines.getChar(line, x1)) DO
8728 leency 2212
            DEC(x1)
2213
        END;
2214
        x2 := x1 + 1
2215
    END;
9659 akron1 2216
    WHILE (x1 >= 0) & isWordChar(Lines.getChar(line, x1)) DO
8728 leency 2217
        DEC(x1)
2218
    END;
2219
    INC(x1);
2220
    IF x1 < x2 THEN
2221
        SetPos(text, x1, text.cursor.Y);
2222
        setSelect(text);
2223
        SetPos(text, x2, text.cursor.Y)
2224
    END
2225
END selectWord;
2226
 
2227
 
9668 akron1 2228
PROCEDURE cursor* (text: tText);
8728 leency 2229
VAR
9295 akron1 2230
    x, y1, y2, scrollX, scrollY: INTEGER;
8728 leency 2231
    cursor: pPoint;
2232
BEGIN
9668 akron1 2233
	IF drawCursor THEN
2234
	    cursor := text.cursor;
2235
	    scrollX := text.scroll.X;
2236
	    scrollY := text.scroll.Y;
9892 akron1 2237
	    IF ~((scrollY > cursor.Y) OR (scrollY + textsize.Y + 1 <= cursor.Y) OR
9668 akron1 2238
	       (scrollX > cursor.X) OR (scrollX + textsize.X <= cursor.X)) THEN
2239
	        x := (cursor.X - scrollX)*charWidth + padding.left;
2240
	        y1 := (cursor.Y - scrollY)*charHeight + padding.top + (inter DIV 2 + 1);
2241
	        y2 := y1 + charHeight - (inter + 2);
2242
	        G.notVLine(canvas, x, y1, y2);
2243
	        G.notVLine(canvas, x - 1, y1, y2)
2244
	    END
8728 leency 2245
    END
2246
END cursor;
2247
 
2248
 
2249
PROCEDURE drawSelect (text: tText; line: tLine; selBeg, selEnd, y: INTEGER);
2250
VAR
2251
    Len, pos, x, firstCharIdx: INTEGER;
2252
BEGIN
2253
    firstCharIdx := MAX(text.scroll.X, selBeg);
2254
    Len := MAX(MIN(line.length - firstCharIdx, selEnd - firstCharIdx), 0);
2255
    Len := MIN(Len, textsize.X - pos + 1);
2256
    SetColor(colors.seltext, colors.selback);
2257
    pos := MAX((selBeg - text.scroll.X), 0);
2258
    x := pos*charWidth + padding.left;
2259
    G.SetColor(canvas, colors.selback);
9891 akron1 2260
    G.FillRect(canvas, x - 1, y - inter DIV 2, x + Len*charWidth, y - inter DIV 2 + charHeight);
9193 akron1 2261
    G.TextOut(canvas, pos*charWidth + padding.left, y, Lines.getPChar(line, firstCharIdx), Len, colors.seltext)
8728 leency 2262
END drawSelect;
2263
 
2264
 
2265
PROCEDURE mark (line: tLine; y: INTEGER);
2266
VAR
2267
    color, i: INTEGER;
2268
BEGIN
2269
    IF line.modified THEN
2270
        color := colors.modified
2271
    ELSIF line.saved THEN
2272
        color := colors.saved
2273
    ELSE
2274
        color := colors.back
2275
    END;
2276
    G.SetColor(canvas, color);
2277
 
2278
    FOR i := 3 TO mark_width + 2 DO
2279
        G.VLine(canvas, padding.left - i, y, y + charHeight)
2280
    END
2281
END mark;
2282
 
2283
 
2284
PROCEDURE setPadding (left, top: INTEGER);
2285
BEGIN
2286
    padding.left := left;
2287
    padding.top := top;
2288
    textsize.X := (size.X - padding.left) DIV charWidth;
2289
    textsize.Y := (size.Y - padding.top) DIV charHeight;
2290
END setPadding;
2291
 
2292
 
2293
PROCEDURE draw* (text: tText);
2294
VAR
9668 akron1 2295
    y, n, cnt, i, x: INTEGER;
8728 leency 2296
    line, firstLine, lastLine: tLine;
2297
    selBeg, selEnd: tPoint;
2298
    s: ARRAY 12 OF WCHAR;
2299
    backColor, numWidth, xNum, wNum: INTEGER;
2300
    p: Search.tPos;
2301
    guard: tGuard;
2302
BEGIN
9668 akron1 2303
    IF text.comments THEN
8728 leency 2304
        Comments(text)
2305
    END;
9668 akron1 2306
    IF text.search & search(text, text.searchText, text.cs, text.whole) THEN END;
8728 leency 2307
    IF text.guard THEN
2308
        NEW(guard);
9050 leency 2309
        List.append(ChangeLog.CL.Log, guard);
9073 leency 2310
        guard.saved := ChangeLog.isFirstGuard(guard);
8728 leency 2311
        text.edition := guard;
9073 leency 2312
        text.guard := FALSE
8728 leency 2313
    ELSE
2314
        guard := text.edition
2315
    END;
2316
 
2317
    guard.cursor := text.cursor^;
2318
    guard.select2 := text.select2^;
2319
    guard.scroll := text.scroll;
2320
    guard.CurX := text.CurX;
2321
    guard.selected := text.select = text.select2;
2322
 
2323
    G.SetColor(canvas, colors.back);
9668 akron1 2324
    IF ~text.smallMove THEN
2325
    	G.clear(canvas)
2326
    END;
9060 leency 2327
    wNum := charWidth;
9671 akron1 2328
    IF lineNumbers THEN
8728 leency 2329
        numWidth := U.lg10(text.count) + 2;
2330
        xNum := numWidth*wNum - wNum DIV 2;
2331
        setPadding(numWidth*wNum + pad_left, padding.top);
2332
    ELSE
9060 leency 2333
        setPadding(pad_left + wNum*2, padding.top)
8728 leency 2334
    END;
2335
    getSelect(text, selBeg, selEnd);
2336
    y := padding.top + inter DIV 2;
2337
    n := text.scroll.Y;
9668 akron1 2338
    firstLine := getLine2(text, n);
9892 akron1 2339
 
9668 akron1 2340
    IF text.smallMove THEN
2341
    	line := text.curLine;
9892 akron1 2342
    	cnt := textsize.Y;
9668 akron1 2343
    	y := y + charHeight*(text.cursor.Y - text.scroll.Y);
2344
    	G.SetColor(canvas, colors.back);
2345
    	G.FillRect(canvas, padding.left - 2, y - inter DIV 2, size.X - 1, y - inter DIV 2 + charHeight);
2346
    	n := text.cursor.Y
2347
    ELSE
2348
	    line := firstLine;
2349
    	cnt := 0
2350
    END;
2351
 
9892 akron1 2352
    WHILE (line # NIL) & (cnt <= textsize.Y) DO
8728 leency 2353
        backColor := colors.back;
2354
        IF (line = text.curLine) & ~selected(text) THEN
2355
            G.SetColor(canvas, colors.curline);
2356
            G.FillRect(canvas, padding.left - 2, y - inter DIV 2, size.X - 1, y - inter DIV 2 + charHeight);
2357
            backColor := colors.curline
2358
        END;
2359
        SetColor(colors.text, backColor);
9668 akron1 2360
		IF (selBeg.Y < n) & (n < selEnd.Y) THEN
2361
			drawSelect(text, line, 0, line.length, y)
2362
		ELSE
2363
			G.TextOut(canvas, padding.left, y, Lines.getPChar(line, text.scroll.X), MIN(MAX(line.length - text.scroll.X, 0), textsize.X + 1), colors.delim);
2364
			IF text.lang # Lang.langText THEN
2365
				parse(text, line, y, backColor, text.lang)
2366
			END
2367
		END;
2368
		IF (selBeg.Y = n) & (selEnd.Y = n) & (selBeg.X # selEnd.X) THEN
8728 leency 2369
            drawSelect(text, line, selBeg.X, selEnd.X, y)
2370
        ELSIF (selBeg.Y = n) & (selEnd.Y # n) THEN
2371
            drawSelect(text, line, selBeg.X, line.length, y)
2372
        ELSIF (selBeg.Y # n) & (selEnd.Y = n) THEN
2373
            drawSelect(text, line, 0, selEnd.X, y)
2374
        END;
9668 akron1 2375
        mark(line, y - inter DIV 2);
8728 leency 2376
        NextLine(line);
2377
        INC(y, charHeight);
2378
        INC(n);
2379
        INC(cnt)
2380
    END;
9668 akron1 2381
 
9060 leency 2382
    G.SetColor(canvas, colors.numback);
2383
    G.FillRect(canvas, 0, 0, padding.left - pad_left (*+ 1*), size.Y - 1);
2384
    line := firstLine;
2385
    SetColor(colors.numtext, colors.numback);
2386
    y := padding.top + inter DIV 2;
9892 akron1 2387
    n := MIN(text.scroll.Y + textsize.Y + 1, text.count);
9060 leency 2388
    FOR i := text.scroll.Y + 1 TO n DO
9671 akron1 2389
        IF lineNumbers THEN
9060 leency 2390
            IF (i MOD 10 = 0) OR (i - 1 = text.cursor.Y) OR line.label THEN
8728 leency 2391
                U.int2str(i, s);
9060 leency 2392
                G.TextOut2(canvas, (numWidth - U.lg10(i) - 1)*wNum - wNum DIV 2, y, s, LENGTH(s))
8728 leency 2393
            ELSE
2394
                G.SetColor(canvas, colors.numtext);
9208 akron1 2395
                G.HLine(canvas, y - inter DIV 2 + charHeight DIV 2, xNum - wNum DIV (1 + ORD(i MOD 5 # 0)), xNum)
9060 leency 2396
            END
2397
        END;
2398
        IF line.label THEN
2399
            FOR x := wNum DIV 2 TO (padding.left - pad_left) - wNum DIV 2 DO
9892 akron1 2400
                G.notVLine(canvas, x, y, y + charHeight - (inter + 1));
2401
                G.xorVLine(canvas, x, y, y + charHeight - (inter + 1))
9060 leency 2402
            END
2403
        END;
2404
        NextLine(line);
2405
        INC(y, charHeight)
8728 leency 2406
    END;
2407
 
2408
    IF text.searchText # "" THEN
9668 akron1 2409
    	IF text.smallMove THEN
2410
    		firstLine := text.curLine;
2411
    		lastLine := firstLine
2412
    	ELSE
9892 akron1 2413
    	    lastLine := getLine2(text, MIN(text.scroll.Y + textsize.Y + 1, text.count) - 1)
8728 leency 2414
        END;
2415
        p := text.foundList.first(Search.tPos);
2416
        WHILE p # NIL DO
9668 akron1 2417
        	y := padding.top + inter DIV 2;
2418
        	IF text.smallMove THEN
2419
        		y := y + charHeight*(text.cursor.Y - text.scroll.Y)
2420
            END;
8728 leency 2421
            IF (firstLine.pos <= p.pos) & (p.pos <= lastLine.pos + lastLine.length) THEN
2422
                line := firstLine;
2423
                WHILE (line.pos <= p.pos) & (line # lastLine) DO
2424
                    NextLine(line);
2425
                    INC(y, charHeight)
2426
                END;
2427
                IF (line # lastLine) & (line # firstLine) OR (line = lastLine) & (line.pos > p.pos) THEN
2428
                    PrevLine(line);
2429
                    DEC(y, charHeight)
2430
                END;
2431
                x := (p.pos - line.pos - text.scroll.X)*charWidth + padding.left;
2432
                n := LENGTH(text.searchText)*charWidth;
2433
                WHILE n > 0 DO
2434
                    IF x >= padding.left THEN
2435
                        G.notVLine(canvas, x, y, y + charHeight - inter)
2436
                    END;
2437
                    INC(x);
2438
                    DEC(n)
9668 akron1 2439
                END
8728 leency 2440
            END;
2441
            p := p.next(Search.tPos)
2442
        END
2443
    END;
2444
 
9668 akron1 2445
    text.smallMove := FALSE;
2446
 
8728 leency 2447
    IF text.foundSel > 0 THEN
2448
        x := (text.cursor.X - text.scroll.X)*charWidth + padding.left;
2449
        y := (text.cursor.Y - text.scroll.Y)*charHeight + padding.top + inter DIV 2;
2450
        n := text.foundSel*charWidth;
2451
        WHILE n > 0 DO
2452
            IF x >= padding.left THEN
2453
                G.xorVLine(canvas, x, y, y + charHeight - inter)
2454
            END;
2455
            INC(x);
2456
            DEC(n)
2457
        END
2458
    END;
9668 akron1 2459
	cursor(text)
8728 leency 2460
END draw;
2461
 
2462
 
9050 leency 2463
PROCEDURE switch* (text: tText);
2464
BEGIN
2465
    ChangeLog.set(text.chLog);
9194 akron1 2466
    Lines.setMaxLength(text.maxLength);
2467
    Lang.setCurLang(text.lang)
9050 leency 2468
END switch;
2469
 
2470
 
8728 leency 2471
PROCEDURE create (fileName: RW.tFileName): tText;
2472
VAR
2473
    text: tText;
2474
BEGIN
2475
    NEW(text);
9050 leency 2476
    text.maxLength := 64;
2477
    text.chLog := ChangeLog.create(text.maxLength);
8728 leency 2478
    NEW(text.cursor);
2479
    NEW(text.select2);
2480
    text.cursor.X := 0;
2481
    text.cursor.Y := 0;
2482
    resetSelect(text);
2483
    text.scroll.X := 0;
2484
    text.scroll.Y := 0;
2485
    setPadding(padding.left, padding.top);
2486
    text.curLine := NIL;
2487
    text.modified := FALSE;
9668 akron1 2488
    text.smallMove := FALSE;
8728 leency 2489
    text.comments := TRUE;
2490
    text.search := TRUE;
2491
    text.cs := FALSE;
2492
    text.whole := FALSE;
2493
    text.guard := TRUE;
2494
    text.edition := NIL;
2495
    text.foundList := List.create(NIL);
2496
    text.searchText := "";
2497
    text.foundSel := 0;
2498
    text.CurX := -1;
9668 akron1 2499
    text.smallChange := 0;
9193 akron1 2500
    text.lang := Lang.langText;
9668 akron1 2501
    text.LinesVector := NIL;
9193 akron1 2502
    Lang.setCurLang(Lang.langText);
8728 leency 2503
    setName(text, fileName);
2504
    ASSERT(text = List.create(text))
2505
    RETURN text
2506
END create;
2507
 
2508
 
2509
PROCEDURE setColors* (text, back, seltext, selback, modified, saved, curline, numtext, numback,
9413 akron1 2510
                        comment, string, escape, num, delim, key1, key2, key3: INTEGER);
8728 leency 2511
BEGIN
2512
    colors.text := text;
2513
    colors.back := back;
2514
    colors.seltext := seltext;
2515
    colors.selback := selback;
2516
    colors.modified := modified;
2517
    colors.saved := saved;
2518
    colors.curline := curline;
2519
    colors.numtext := numtext;
2520
    colors.numback := numback;
2521
    colors.comment := comment;
2522
    colors.string  := string;
9413 akron1 2523
    colors.escape  := escape;
8728 leency 2524
    colors.num := num;
2525
    colors.delim := delim;
2526
    colors.key1 := key1;
2527
    colors.key2 := key2;
2528
    colors.key3 := key3;
2529
END setColors;
2530
 
2531
 
9659 akron1 2532
PROCEDURE setCanvas* (_canvas: G.tCanvas);
8728 leency 2533
BEGIN
9659 akron1 2534
    canvas := _canvas;
2535
    charWidth := _canvas.font.width;
2536
    charHeight := _canvas.font.height + inter
8728 leency 2537
END setCanvas;
2538
 
2539
 
2540
PROCEDURE resize* (width, height: INTEGER);
2541
BEGIN
2542
    size.X := width;
2543
    size.Y := height;
2544
    setPadding(padding.left, padding.top)
2545
END resize;
2546
 
2547
 
2548
PROCEDURE destroy* (VAR text: tText);
2549
BEGIN
2550
    IF search(text, "", FALSE, FALSE) THEN END;
9448 akron1 2551
    ChangeLog.destroy(text.chLog);
9668 akron1 2552
    Lines.destroyVector(text.LinesVector);
8728 leency 2553
    DISPOSE(text.foundList);
2554
    DISPOSE(text.cursor);
2555
    DISPOSE(text.select2);
2556
    DISPOSE(text)
2557
END destroy;
2558
 
2559
 
9674 akron1 2560
PROCEDURE open* (name: RW.tFileName; ptr, size: INTEGER; VAR errno: INTEGER): tText;
8728 leency 2561
VAR
2562
    text: tText;
2563
    file: RW.tInput;
9180 akron1 2564
    n, enc, eol: INTEGER;
2565
    _eol: BOOLEAN;
8728 leency 2566
    line: tLine;
2567
BEGIN
2568
    errno := 0;
9522 akron1 2569
    text := create(name);
2570
    IF text # NIL THEN
9674 akron1 2571
    	IF ptr = 0 THEN
2572
    		file := RW.loadFromFile(name, enc, eol)
2573
    	ELSE
2574
    		file := RW.loadFromMem(ptr, size, enc, eol)
2575
    	END;
9522 akron1 2576
    	IF file = NIL THEN
2577
    		destroy(text)
2578
    	END
2579
    ELSE
2580
    	file := NIL
2581
    END;
8728 leency 2582
    IF file # NIL THEN
9336 akron1 2583
        ChangeLog.changeInt(text.enc, enc);
2584
        ChangeLog.changeInt(text.eol, eol);
8728 leency 2585
        text.enc := enc;
9180 akron1 2586
        text.eol := eol;
2587
        line := Lines.create(FALSE);
2588
        List._append(text, line);
8728 leency 2589
        REPEAT
9180 akron1 2590
            n := RW.getString(file, line, Lines.tabs, _eol);
2591
            IF _eol THEN
2592
            	line := Lines.create(FALSE);
2593
            	List._append(text, line)
8728 leency 2594
            END
9180 akron1 2595
        UNTIL ~_eol;
8728 leency 2596
        RW.destroy(file);
9180 akron1 2597
        text.curLine := text.first(tLine);
2598
        SetPos(text, 0, 0);
9668 akron1 2599
        resetSelect(text);
2600
        Comments(text)
8728 leency 2601
    ELSE
2602
        errno := 1
2603
    END
2604
    RETURN text
2605
END open;
2606
 
2607
 
2608
PROCEDURE findNext* (text: tText; prev: BOOLEAN): BOOLEAN;
2609
VAR
2610
    cursorPos, x, y, X, Y, Len: INTEGER;
2611
    p: Search.tPos;
2612
    line: tLine;
2613
    res: BOOLEAN;
2614
BEGIN
2615
    X := text.cursor.X;
2616
    Y := text.cursor.Y;
2617
    text.cursor.X := MIN(text.cursor.X, text.curLine.length);
2618
    cursorPos := text.curLine.pos + text.cursor.X - ORD(prev) - ORD(~prev & (text.foundSel = 0));
2619
    p := text.foundList.first(Search.tPos);
2620
    WHILE (p # NIL) & (p.pos <= cursorPos) DO
2621
        p := p.next(Search.tPos)
2622
    END;
2623
    IF prev THEN
2624
        IF p = NIL THEN
2625
            p := text.foundList.last(Search.tPos)
2626
        ELSE
2627
            p := p.prev(Search.tPos)
2628
        END
2629
    END;
2630
    res := p # NIL;
2631
    IF res THEN
2632
        y := 0;
2633
        line := text.first(tLine);
2634
        WHILE (line.pos <= p.pos) & (line.next # NIL) DO
2635
            NextLine(line);
2636
            INC(y)
2637
        END;
2638
        IF (line.next # NIL) OR (line.pos > p.pos) THEN
2639
            PrevLine(line);
2640
            DEC(y)
2641
        END;
2642
        resetSelect(text);
2643
        searchScroll(text, y);
2644
        x := p.pos - line.pos;
2645
        Len := LENGTH(text.searchText);
2646
        IF x + Len > text.scroll.X + textsize.X THEN
2647
            text.scroll.X := MAX(x + Len - textsize.X + 3, 0)
2648
        ELSIF x < text.scroll.X THEN
2649
            text.scroll.X := MAX(x - 3, 0)
2650
        END;
2651
        SetPos(text, x, y);
2652
        text.foundSel := Len
2653
    ELSE
2654
        SetPos(text, X, Y)
2655
    END
2656
    RETURN res
2657
END findNext;
2658
 
2659
 
2660
PROCEDURE replace* (text: tText; s: ARRAY OF WCHAR; n: INTEGER);
2661
VAR
2662
    line: tLine;
2663
    sLen, i: INTEGER;
2664
BEGIN
2665
    IF text.foundSel > 0 THEN
2666
        line := text.curLine;
2667
        sLen := LENGTH(s);
2668
        i := text.cursor.X;
2669
        IF sLen > n THEN
2670
            Lines.insert3(line, i, sLen - n)
9560 akron1 2671
        ELSIF n > sLen THEN
2672
            Lines.delCharN(line, i, n - sLen)
2673
        ELSE (* n = sLen *)
2674
        	Lines.copy(line)
8728 leency 2675
        END;
2676
        SetPos(text, i + sLen, text.cursor.Y);
9560 akron1 2677
	    WHILE sLen > 0 DO
2678
	        DEC(sLen);
2679
	        Lines.setChar(line, i + sLen, s[sLen])
2680
	    END;
8728 leency 2681
        resetSelect(text);
2682
        Lines.modify(line);
2683
        modify(text)
2684
    END
2685
END replace;
2686
 
2687
 
2688
PROCEDURE replaceAll* (text: tText; s: ARRAY OF WCHAR; n: INTEGER): INTEGER;
2689
VAR
2690
    p: Search.tPos;
2691
    line: tLine;
2692
    y, k, d, pos, y0: INTEGER;
2693
BEGIN
2694
    resetSelect(text);
2695
    SetPos(text, 0, 0);
2696
    line := text.first(tLine);
2697
    y := 0;
2698
    y0 := -1;
2699
    k := 0;
2700
    d := LENGTH(s) - n;
2701
    p := text.foundList.first(Search.tPos);
2702
    WHILE p # NIL DO
2703
        pos := p.pos;
2704
        WHILE (line.pos <= pos) & (line.next # NIL) DO
2705
            NextLine(line);
2706
            INC(y)
2707
        END;
2708
        IF (line.next # NIL) OR (line.pos > pos) THEN
2709
            PrevLine(line);
2710
            DEC(y)
2711
        END;
2712
        IF y = y0 THEN
2713
            INC(k, d)
2714
        ELSE
2715
            k := 0;
2716
            y0 := y
2717
        END;
2718
        SetPos(text, pos - line.pos + k, y);
2719
        text.foundSel := n;
2720
        replace(text, s, n);
2721
        p := p.next(Search.tPos)
2722
    END
2723
    RETURN text.foundList.count
2724
END replaceAll;
2725
 
2726
 
9674 akron1 2727
PROCEDURE conv (VAR c: WCHAR; cp: E.CP; enc: INTEGER): BOOLEAN;
2728
VAR
2729
	code: INTEGER;
2730
	res: BOOLEAN;
2731
BEGIN
2732
	res := FALSE;
2733
	IF (c # 0X) & (c # Lines.NUL) & (c # Lines.TAB1) THEN
2734
		code := E.UNI[ORD(c), enc];
2735
		IF (0 <= code) & (code <= 255) THEN
2736
			code := cp[code]
2737
		ELSE
2738
			code := ORD(c)
2739
		END;
9708 akron1 2740
		IF code # ORD(c) THEN
2741
			c := WCHR(code);
2742
			res := TRUE
2743
		END
9674 akron1 2744
	END
2745
	RETURN res
2746
END conv;
2747
 
2748
 
2749
PROCEDURE conv1251to866 (VAR c: WCHAR): BOOLEAN;
9708 akron1 2750
	RETURN conv(c, E.cp866, E.CP1251)
9674 akron1 2751
END conv1251to866;
2752
 
2753
 
2754
PROCEDURE conv866to1251 (VAR c: WCHAR): BOOLEAN;
2755
	RETURN conv(c, E.cp1251, E.CP866)
2756
END conv866to1251;
2757
 
2758
 
9708 akron1 2759
PROCEDURE convert* (text: tText; (*cp: E.CP;*) enc: INTEGER);
9674 akron1 2760
VAR
2761
	line: tLine;
2762
	func: Lines.fConvert;
2763
	modified: BOOLEAN;
2764
BEGIN
2765
	modified := FALSE;
2766
	line := text.first(tLine);
2767
	IF enc = E.CP866 THEN
2768
		func := conv866to1251
9708 akron1 2769
	ELSIF enc = E.CP1251 THEN
9674 akron1 2770
		func := conv1251to866
2771
	ELSE
2772
		line := NIL
2773
	END;
2774
 
2775
	WHILE line # NIL DO
2776
		IF Lines.convert(line, 0, line.length - 1, func) THEN
2777
			modified := TRUE
2778
		END;
2779
		NextLine(line)
2780
	END;
2781
 
2782
	IF modified THEN
2783
		modify(text)
2784
	END
2785
END convert;
2786
 
2787
 
8728 leency 2788
PROCEDURE New* (): tText;
2789
VAR
2790
    text: tText;
2791
BEGIN
2792
    text := create("");
2793
    List._append(text, Lines.create(FALSE));
2794
    text.curLine := text.first(tLine);
9336 akron1 2795
    ChangeLog.changeInt(text.enc, E.CP866);
9659 akron1 2796
    ChangeLog.changeInt(text.eol, E.EOL_CRLF);
8728 leency 2797
    text.enc := E.CP866;
9659 akron1 2798
    text.eol := E.EOL_CRLF;
8728 leency 2799
    SetPos(text, 0, 0);
2800
    resetSelect(text)
2801
    RETURN text
2802
END New;
2803
 
2804
 
9731 akron1 2805
PROCEDURE empty* (text: tText): BOOLEAN;
2806
	RETURN (text.count = 1) & (text.curLine.length = 0)
2807
END empty;
2808
 
2809
 
9671 akron1 2810
PROCEDURE init* (pShowCursor: tProcedure; _lineNumbers, _autoIndents, _autoBrackets, _trimSpace: BOOLEAN);
8728 leency 2811
BEGIN
9174 akron1 2812
    ShowCursor := pShowCursor;
8728 leency 2813
    pdelete := delete;
2814
    drawCursor := TRUE;
9671 akron1 2815
    lineNumbers := _lineNumbers;
2816
    autoIndents := _autoIndents;
2817
    autoBrackets := _autoBrackets;
2818
    trimSpace := _trimSpace;
8728 leency 2819
    padding.left := pad_left;
2820
    padding.top := pad_top;
2821
END init;
2822
 
2823
 
2824
END Text.