Subversion Repositories Kolibri OS

Rev

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

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