Subversion Repositories Kolibri OS

Rev

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