Subversion Repositories Kolibri OS

Rev

Rev 8762 | Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
8728 leency 1
(*
2
    Copyright 2021 Anton Krotov
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,
29
    ChangeLog,
30
    Lang := Languages;
31
 
32
 
33
CONST
34
 
35
    SPACE = 20X;
36
    TAB = RW.TAB_SIZE;
37
    lenEOL = CB.lenEOL;
38
 
39
    SHIFT* = 0; CTRL* = 1;
40
 
41
    mark_width = 2;
42
    pad_left = mark_width + 3;
43
    pad_top = 1;
44
    inter = 2;
45
 
46
 
47
TYPE
48
 
49
    tPoint = RECORD
50
        X, Y: INTEGER
51
    END;
52
 
53
    pPoint = POINTER TO tPoint;
54
 
55
    tString* = ARRAY 1000 OF WCHAR;
56
 
57
    tLine = Lines.tLine;
58
 
59
    tGuard = POINTER TO RECORD (ChangeLog.tGuard)
60
        selected: BOOLEAN;
61
        cursor, select2, scroll: tPoint;
62
        CurX: INTEGER
63
    END;
64
 
65
    tText* = POINTER TO RECORD (List.tList)
66
        cursor, select, select2: pPoint;
67
        scroll: tPoint;
68
        CurX: INTEGER;
69
        modified*: BOOLEAN;
70
 
71
        edition*: tGuard;
72
        comments, numbers*, guard,
73
        search, cs, whole: BOOLEAN;
74
        curLine: tLine;
75
        fileName*: RW.tFileName;
76
        lang*: INTEGER;
77
        enc*: INTEGER;
78
        table: Search.IdxTable;
79
        foundList: List.tList;
80
        idxData: Search.tBuffer;
81
        foundSel: INTEGER;
82
        searchText: tString
83
    END;
84
 
85
    tProcedure = PROCEDURE;
86
 
87
 
88
VAR
89
 
90
    pdelete: PROCEDURE (text: tText);
91
    ShowCursor: PROCEDURE;
92
 
93
    colors*: RECORD
94
                text, back, seltext, selback, modified, saved, curline, numtext, numback, border*: INTEGER;
95
                comment, string, num, delim, key1, key2, key3: INTEGER
96
             END;
97
    canvas: G.tCanvas;
98
    drawCursor*: BOOLEAN;
99
    padding: RECORD left, top: INTEGER END;
100
    size, textsize: tPoint;
101
    charWidth, charHeight: INTEGER;
102
 
103
 
104
PROCEDURE setName* (text: tText; name: RW.tFileName);
105
VAR
106
    ext: RW.tFileName;
107
BEGIN
108
    text.fileName := name;
109
    U.getFileName(text.fileName, ext, ".");
110
    U.upcase(ext);
111
    IF ext = "OB07" THEN
112
        text.lang := Lang.langOberon
113
    ELSIF (ext = "C") OR (ext = "H") OR (ext = "CPP") THEN
114
        text.lang := Lang.langC
115
    ELSIF (ext = "PAS") OR (ext = "PP") THEN
116
        text.lang := Lang.langPascal
117
    ELSIF ext = "ASM" THEN
118
        text.lang := Lang.langFasm
119
    ELSIF ext = "LUA" THEN
120
        text.lang := Lang.langLua
121
    ELSIF ext = "INI" THEN
122
        text.lang := Lang.langIni
123
    ELSE
124
        text.lang := Lang.langNone
125
    END
126
END setName;
127
 
128
 
129
PROCEDURE setLang* (text: tText; lang: INTEGER);
130
BEGIN
131
    text.lang := lang;
132
    text.comments := TRUE
133
END setLang;
134
 
135
 
136
PROCEDURE getPos* (text: tText; VAR x, y: INTEGER);
137
BEGIN
138
    x := text.cursor.X + 1;
139
    y := text.cursor.Y + 1
140
END getPos;
141
 
142
 
143
PROCEDURE getScroll* (text: tText; VAR x, y: INTEGER);
144
BEGIN
145
    x := text.scroll.X;
146
    y := text.scroll.Y
147
END getScroll;
148
 
149
 
150
PROCEDURE getTextSize* (VAR x, y: INTEGER);
151
BEGIN
152
    x := textsize.X;
153
    y := textsize.Y
154
END getTextSize;
155
 
156
 
157
PROCEDURE getTextRect* (VAR left, top, rigth, bottom: INTEGER);
158
BEGIN
159
    left := padding.left - 1;
160
    top := padding.top - 1;
161
    rigth := size.X - 1;
162
    bottom := top + size.Y - 1;
163
END getTextRect;
164
 
165
 
166
PROCEDURE toggleNumbers* (text: tText);
167
BEGIN
168
    text.numbers := ~text.numbers
169
END toggleNumbers;
170
 
171
 
172
PROCEDURE toggleCursor*;
173
BEGIN
174
    drawCursor := ~drawCursor
175
END toggleCursor;
176
 
177
 
178
PROCEDURE getChar (line: tLine; i: INTEGER): WCHAR;
179
VAR
180
    res: WCHAR;
181
BEGIN
182
    IF i >= line.length THEN
183
        res := 0X
184
    ELSE
185
        res := Lines.getChar(line, i)
186
    END
187
    RETURN res
188
END getChar;
189
 
190
 
191
PROCEDURE getString (src: tLine; pos, cnt: INTEGER; VAR dst: ARRAY OF WCHAR): INTEGER;
192
VAR
193
    i: INTEGER;
194
BEGIN
195
    i := 0;
196
    WHILE (pos < src.length) & (cnt > 0) DO
197
        IF i < LEN(dst) - 1 THEN
198
            dst[i] := getChar(src, pos);
199
            INC(i)
200
        END;
201
        INC(pos);
202
        DEC(cnt)
203
    END;
204
    dst[i] := 0X
205
    RETURN i
206
END getString;
207
 
208
 
209
PROCEDURE NextLine (VAR line: tLine);
210
BEGIN
211
    line := line.next(tLine)
212
END NextLine;
213
 
214
 
215
PROCEDURE PrevLine (VAR line: tLine);
216
BEGIN
217
    line := line.prev(tLine)
218
END PrevLine;
219
 
220
 
221
PROCEDURE SetColor (textColor, backColor: INTEGER);
222
BEGIN
223
    G.SetTextColor(canvas, textColor);
224
    G.SetBkColor(canvas, backColor)
225
END SetColor;
226
 
227
 
228
PROCEDURE ProcessComments (line: tLine; VAR depth, pos: INTEGER; minDepth, n: INTEGER; lang: INTEGER);
229
VAR
230
    cond: INTEGER;
231
BEGIN
232
    cond := 0;
233
    WHILE (pos <= n) & (depth > minDepth) DO
234
        Lang.comments(line, depth, cond, pos, n, lang);
235
        INC(pos)
236
    END;
237
    DEC(pos)
238
END ProcessComments;
239
 
240
 
241
PROCEDURE Comments (text: tText);
242
VAR
243
    line: tLine;
244
    i: INTEGER;
245
BEGIN
246
    line := text.first(tLine);
247
    line.cin := 0;
248
    line.cout := 0;
249
    i := 0;
250
    ProcessComments(line, line.cout, i, -1, line.length - 1, text.lang);
251
    NextLine(line);
252
    WHILE line # NIL DO
253
        line.cin := line.prev(tLine).cout;
254
        line.cout := line.cin;
255
        i := 0;
256
        ProcessComments(line, line.cout, i, -1, line.length - 1, text.lang);
257
        NextLine(line)
258
    END;
259
    text.comments := FALSE
260
END Comments;
261
 
262
 
263
PROCEDURE parse (text: tText; line: tLine; y: INTEGER; backColor: INTEGER; lang: INTEGER);
264
VAR
265
    c: WCHAR;
266
    i, n, k: INTEGER;
267
    cond, depth: INTEGER;
268
    color: INTEGER;
269
    hex: BOOLEAN;
270
    isDgt: PROCEDURE (c: WCHAR): BOOLEAN;
271
 
272
 
273
    PROCEDURE PrintLex (text: tText; line: tLine; lexStart, lexEnd: INTEGER; y: INTEGER; color, backColor: INTEGER);
274
    VAR
275
        lexLen: INTEGER;
276
    BEGIN
277
        SetColor(color, backColor);
278
        lexLen := MAX(MIN(line.length - lexStart, lexEnd - lexStart + 1), 0);
279
        G.TextOut(canvas, padding.left + (lexStart - text.scroll.X) * charWidth, y, Lines.getPChar(line, lexStart), lexLen)
280
    END PrintLex;
281
 
282
 
283
    PROCEDURE PrintComment (text: tText; line: tLine; VAR depth, i: INTEGER; y: INTEGER; backColor: INTEGER);
284
    VAR
285
        lexStart: INTEGER;
286
        color: INTEGER;
287
    BEGIN
288
        IF (text.lang = Lang.langLua) & ~ODD(depth) THEN
289
            color := colors.string
290
        ELSIF (text.lang = Lang.langIni) & (depth = 1) THEN
291
            color := colors.key2
292
        ELSIF (text.lang = Lang.langPascal) & (depth = 3) THEN
293
            color := colors.key3
294
        ELSE
295
            color := colors.comment
296
        END;
297
        lexStart := MAX(i - 2, 0);
298
        ProcessComments(line, depth, i, 0, line.length - 1, text.lang);
299
        PrintLex(text, line, lexStart, i, y, color, backColor)
300
    END PrintComment;
301
 
302
 
303
    PROCEDURE cap (c: WCHAR): WCHAR;
304
    BEGIN
305
        IF U.cap(c) THEN END
306
        RETURN c
307
    END cap;
308
 
309
 
310
    PROCEDURE UL (c: WCHAR): BOOLEAN;
311
        RETURN (cap(c) = "U") OR (cap(c) = "L")
312
    END UL;
313
 
314
 
315
    PROCEDURE FL (c: WCHAR): BOOLEAN;
316
        RETURN (cap(c) = "F") OR (cap(c) = "L")
317
    END FL;
318
 
319
 
320
    PROCEDURE isFASMdelim (c: WCHAR): BOOLEAN;
321
    VAR
322
        s: ARRAY 19 OF WCHAR;
323
        i: INTEGER;
324
    BEGIN
325
        s := "{}[]<>:,()&*/|+-\#";
326
        i := LEN(s) - 2;
327
        WHILE (i >= 0) & (c # s[i]) DO
328
            DEC(i)
329
        END
330
        RETURN i >= 0
331
    END isFASMdelim;
332
 
333
 
334
    PROCEDURE ident (text: tText; VAR i: INTEGER; first, y: INTEGER; line: tLine; backColor: INTEGER; cs: BOOLEAN);
335
    VAR
336
        c: WCHAR;
337
        lexLen: INTEGER;
338
        s: ARRAY 32 OF WCHAR;
339
        color: INTEGER;
340
    BEGIN
341
        c := getChar(line, i);
342
        WHILE U.isLetter(c) OR (c = "_") OR U.isDigit(c) DO
343
            INC(i);
344
            c := getChar(line, i);
345
        END;
346
        DEC(i);
347
        lexLen := getString(line, first, i - first + 1, s);
348
        IF ~cs THEN
349
            U.upcase16(s)
350
        END;
351
        IF Lang.isKey(s, text.lang, 1) THEN
352
            color := colors.key1
353
        ELSIF Lang.isKey(s, text.lang, 2) THEN
354
            color := colors.key2
355
        ELSIF Lang.isKey(s, text.lang, 3) THEN
356
            color := colors.key3
357
        ELSE
358
            color := colors.text
359
        END;
360
        IF color # colors.text THEN
361
            PrintLex(text, line, first, i, y, color, backColor)
362
        END
363
    END ident;
364
 
365
 
366
    PROCEDURE String (text: tText; line: tLine; VAR i: INTEGER; y: INTEGER; backColor: INTEGER);
367
    VAR
368
        k: INTEGER;
369
    BEGIN
370
        k := i;
371
        Lang.SkipString(line, i, line.length - 1);
372
        PrintLex(text, line, k, i, y, colors.string, backColor)
373
    END String;
374
 
375
 
376
BEGIN
377
    depth := line.cin;
378
    n := line.length - 1;
379
    i := 0;
380
    IF (depth > 0) & (n >= 0) THEN
381
        PrintComment(text, line, depth, i, y, backColor)
382
    END;
383
    cond := 0;
384
    WHILE i <= n DO
385
        c := getChar(line, i);
386
 
387
        IF lang = Lang.langFasm THEN
388
 
389
            IF c = ";" THEN
390
                PrintLex(text, line, i, n, y, colors.comment, backColor);
391
                i := n
392
            ELSIF (c = "'") OR (c = '"') THEN
393
                String(text, line, i, y, backColor)
394
            ELSIF (U.isLetter(c) OR (c = "_")) THEN
395
                ident(text, i, i, y, line, backColor, FALSE)
396
            ELSIF isFASMdelim(c) THEN
397
                PrintLex(text, line, i, i, y, colors.delim, backColor)
398
            ELSIF U.isDigit(c) THEN
399
                hex := FALSE;
400
                k := i;
401
                INC(i);
402
                c := getChar(line, i);
403
                IF (cap(c) = "X") & (getChar(line, i - 1) = "0") THEN
404
                    INC(i);
405
                    hex := TRUE
406
                END;
407
 
408
                WHILE U.isHex(cap(getChar(line, i))) DO
409
                    INC(i)
410
                END;
411
 
412
                IF (cap(getChar(line, i)) = "H") & ~hex THEN
413
                    INC(i)
414
                END;
415
 
416
                DEC(i);
417
                PrintLex(text, line, k, i, y, colors.num, backColor)
418
            END
419
 
420
        ELSIF lang = Lang.langC THEN
421
 
422
        IF depth = 0 THEN
423
            IF c = "/" THEN
424
                IF cond = 0 THEN
425
                    cond := 1
426
                ELSE
427
                    PrintLex(text, line, i - 1, n, y, colors.comment, backColor);
428
                    cond := 0;
429
                    i := n
430
                END
431
            ELSIF (c = "*") & (cond = 1) THEN
432
                depth := 1;
433
                INC(i);
434
                PrintComment(text, line, depth, i, y, backColor);
435
                cond := 0
436
            ELSIF (c = "'") OR (c = '"') THEN
437
                String(text, line, i, y, backColor);
438
                cond := 0
439
            ELSIF (U.isLetter(c) OR (c = "_")) THEN
440
                ident(text, i, i - ORD((i > 0) & (getChar(line, i - 1) = "#")), y, line, backColor, TRUE);
441
                cond := 0
442
            ELSIF U.isDigit(c) THEN
443
                k := i;
444
                INC(i);
445
                c := getChar(line, i);
446
                IF c = "." THEN
447
                    DEC(i);
448
                    c := getChar(line, i)
449
                END;
450
                IF (cap(c) = "X") & (getChar(line, i - 1) = "0") THEN
451
                    REPEAT
452
                        INC(i);
453
                        c := getChar(line, i)
454
                    UNTIL ~U.isHex(cap(c));
455
                    IF UL(c) THEN
456
                        INC(i)
457
                    END
458
                ELSIF UL(c) THEN
459
                    INC(i)
460
                ELSIF U.isDigit(c) THEN
461
                    REPEAT
462
                        INC(i)
463
                    UNTIL ~U.isDigit(getChar(line, i));
464
                    c := getChar(line, i);
465
                    IF UL(c) THEN
466
                        INC(i)
467
                    ELSIF c = "." THEN
468
                        INC(i);
469
                        WHILE U.isDigit(getChar(line, i)) DO
470
                            INC(i)
471
                        END;
472
                        c := getChar(line, i);
473
                        IF cap(c) = "E" THEN
474
                            INC(i);
475
                            c := getChar(line, i);
476
                            IF (c = "+") OR (c = "-") THEN
477
                                INC(i)
478
                            END;
479
                            IF U.isDigit(getChar(line, i)) THEN
480
                                WHILE U.isDigit(getChar(line, i)) DO
481
                                    INC(i)
482
                                END;
483
                                c := getChar(line, i);
484
                                IF FL(c) THEN
485
                                    INC(i)
486
                                END
487
                            END
488
                        ELSIF FL(c) THEN
489
                            INC(i)
490
                        END
491
                    END
492
                END;
493
                DEC(i);
494
                PrintLex(text, line, k, i, y, colors.num, backColor);
495
                cond := 0
496
            ELSE
497
                cond := 0
498
            END
499
        ELSIF depth = 1 THEN
500
            IF c = "*" THEN
501
                cond := 1
502
            ELSIF (c = "/") & (cond = 1) THEN
503
                cond := 0;
504
                depth := 0
505
            ELSE
506
                cond := 0
507
            END
508
        END;
509
 
510
        ELSIF lang = Lang.langOberon THEN
511
 
512
        IF (depth = 0) & (c = "/") THEN
513
            IF cond = 3 THEN
514
                PrintLex(text, line, i - 1, n, y, colors.comment, backColor);
515
                cond := 0;
516
                i := n
517
            ELSE
518
                cond := 3
519
            END
520
        ELSIF (depth = 0) & ((c = "'") OR (c = '"')) THEN
521
            String(text, line, i, y, backColor);
522
            cond := 0
523
        ELSIF (depth = 0) & U.isDigit(c) THEN
524
            color := colors.num;
525
            k := i;
526
            INC(i);
527
            WHILE U.isHex(getChar(line, i)) DO
528
                INC(i)
529
            END;
530
            IF i <= n THEN
531
                IF getChar(line, i) = "." THEN
532
                    INC(i);
533
                    IF getChar(line, i) = "." THEN
534
                        DEC(i)
535
                    END;
536
                    WHILE U.isDigit(getChar(line, i)) DO
537
                        INC(i)
538
                    END;
539
                    IF getChar(line, i) = "E" THEN
540
                        INC(i);
541
                        IF (getChar(line, i) = "+") OR (getChar(line, i) = "-") THEN
542
                            INC(i)
543
                        END;
544
                        WHILE U.isDigit(getChar(line, i)) DO
545
                            INC(i)
546
                        END
547
                    END
548
                ELSIF getChar(line, i) = "H" THEN
549
                    INC(i)
550
                ELSIF getChar(line, i) = "X" THEN
551
                    color := colors.string;
552
                    INC(i)
553
                END
554
            END;
555
            DEC(i);
556
            PrintLex(text, line, k, i, y, color, backColor);
557
            cond := 0
558
        ELSIF (depth = 0) & (U.isLetter(c) OR (c = "_")) THEN
559
            ident(text, i, i, y, line, backColor, TRUE);
560
            cond := 0
561
        ELSIF c = "(" THEN
562
            cond := 1
563
        ELSIF c = "*" THEN
564
            IF cond = 1 THEN
565
                INC(depth);
566
                INC(i);
567
                PrintComment(text, line, depth, i, y, backColor);
568
                cond := 0
569
            ELSE
570
                cond := 2
571
            END
572
        ELSIF c = ")" THEN
573
            IF cond = 2 THEN
574
                IF depth > 0 THEN
575
                    DEC(depth)
576
                END
577
            END;
578
            cond := 0
579
        ELSE
580
            cond := 0
581
        END
582
 
583
        ELSIF lang = Lang.langLua THEN
584
 
585
        IF depth = 0 THEN
586
            IF c = "-" THEN
587
                IF cond = 1 THEN
588
                    IF Lang.LuaLong(line, i + 1) >= 0 THEN
589
                        depth := Lang.LuaLong(line, i + 1)*2 + 1;
590
                        INC(i);
591
                        PrintComment(text, line, depth, i, y, backColor)
592
                    ELSE
593
                        PrintLex(text, line, i - 1, n, y, colors.comment, backColor);
594
                        i := n
595
                    END;
596
                    cond := 0
597
                ELSE
598
                    cond := 1
599
                END
600
            ELSIF c = "[" THEN
601
                cond := 0;
602
                k := Lang.LuaLong(line, i);
603
                IF k >= 0 THEN
604
                    depth := (k + 1)*2;
605
                    INC(i, 2);
606
                    PrintComment(text, line, depth, i, y, backColor);
607
                    cond := 0
608
                END
609
            ELSIF (c = "'") OR (c = '"') THEN
610
                String(text, line, i, y, backColor);
611
                cond := 0
612
            ELSIF U.isDigit(c) THEN
613
                k := i;
614
                IF (c = "0") & (cap(getChar(line, i + 1)) = "X") THEN
615
                    isDgt := U.isHex;
616
                    hex := TRUE;
617
                    INC(i, 2)
618
                ELSE
619
                    isDgt := U.isDigit;
620
                    hex := FALSE
621
                END;
622
                WHILE isDgt(cap(getChar(line, i))) DO
623
                    INC(i)
624
                END;
625
                IF getChar(line, i) = "." THEN
626
                    INC(i);
627
                    IF getChar(line, i) = "." THEN
628
                        DEC(i)
629
                    END;
630
                    WHILE isDgt(cap(getChar(line, i))) DO
631
                        INC(i)
632
                    END
633
                END;
634
                IF (cap(getChar(line, i)) = "E") OR hex & (cap(getChar(line, i)) = "P") THEN
635
                    INC(i);
636
                    IF (getChar(line, i) = "-") OR (getChar(line, i) = "+") THEN
637
                        INC(i)
638
                    END;
639
                    WHILE isDgt(cap(getChar(line, i))) DO
640
                        INC(i)
641
                    END
642
                END;
643
                DEC(i);
644
                PrintLex(text, line, k, i, y, colors.num, backColor);
645
                cond := 0
646
            ELSIF U.isLetter(c) OR (c = "_") THEN
647
                ident(text, i, i, y, line, backColor, TRUE);
648
                cond := 0
649
            ELSE
650
                cond := 0
651
            END
652
 
653
        ELSIF depth > 0 THEN
654
            IF (cond = 0) & (c = "]") THEN
655
                cond := 1
656
            ELSIF (cond >= 1) & (c = "=") THEN
657
                INC(cond)
658
            ELSIF (cond >= 1) & (c = "]") & (cond * 2 - depth MOD 2 = depth) THEN
659
                depth := 0;
660
                cond := 0
661
            ELSE
662
                cond := 0
663
            END
664
        END
665
 
666
        ELSIF lang = Lang.langPascal THEN
667
 
668
        IF depth = 0 THEN
669
            IF c = "(" THEN
670
                cond := 1
671
            ELSIF (c = "*") & (cond = 1) THEN
672
                depth := 2;
673
                INC(i);
674
                PrintComment(text, line, depth, i, y, backColor);
675
                cond := 0
676
            ELSIF c = "/" THEN
677
                IF cond = 2 THEN
678
                    PrintLex(text, line, i - 1, n, y, colors.comment, backColor);
679
                    cond := 0;
680
                    i := n
681
                ELSE
682
                    cond := 2
683
                END
684
            ELSIF c = "'" THEN
685
                String(text, line, i, y, backColor);
686
                cond := 0
687
            ELSIF c = "{" THEN
688
                IF getChar(line, i + 1) = "$" THEN
689
                    depth := 3
690
                ELSE
691
                    depth := 1
692
                END;
693
                INC(i, 2);
694
                PrintComment(text, line, depth, i, y, backColor);
695
                cond := 0
696
            ELSIF c = "#" THEN
697
                k := i;
698
                INC(i);
699
                WHILE U.isDigit(getChar(line, i)) DO
700
                    INC(i)
701
                END;
702
                DEC(i);
703
                PrintLex(text, line, k, i, y, colors.string, backColor);
704
                cond := 0
705
            ELSIF c = "$" THEN
706
                IF (i > 0 ) & (getChar(line, i - 1) = "#") THEN
707
                    color := colors.string
708
                ELSE
709
                    color := colors.num
710
                END;
711
                k := i;
712
                INC(i);
713
                WHILE U.isHex(cap(getChar(line, i))) DO
714
                    INC(i)
715
                END;
716
                DEC(i);
717
                PrintLex(text, line, k, i, y, color, backColor);
718
                cond := 0
719
            ELSIF U.isDigit(c) THEN
720
                k := i;
721
                WHILE U.isDigit(getChar(line, i)) DO
722
                    INC(i)
723
                END;
724
                IF getChar(line, i) = "." THEN
725
                    INC(i);
726
                    IF getChar(line, i) = "." THEN
727
                        DEC(i)
728
                    END;
729
                    WHILE U.isDigit(getChar(line, i)) DO
730
                        INC(i)
731
                    END;
732
                    IF cap(getChar(line, i)) = "E" THEN
733
                        INC(i);
734
                        IF (getChar(line, i) = "-") OR (getChar(line, i) = "+") THEN
735
                            INC(i)
736
                        END;
737
                        WHILE U.isDigit(getChar(line, i)) DO
738
                            INC(i)
739
                        END
740
                    END
741
                END;
742
                DEC(i);
743
                PrintLex(text, line, k, i, y, colors.num, backColor);
744
                cond := 0
745
            ELSIF (U.isLetter(c) OR (c = "_")) THEN
746
                ident(text, i, i, y, line, backColor, FALSE);
747
                cond := 0
748
            ELSE
749
                cond := 0
750
            END
751
        ELSIF depth IN {1, 3} THEN
752
            IF c = "}" THEN
753
                depth := 0
754
            END
755
        ELSIF depth = 2 THEN
756
            IF c = "*" THEN
757
                cond := 1
758
            ELSIF (c = ")") & (cond = 1) THEN
759
                depth := 0;
760
                cond := 0
761
            ELSE
762
                cond := 0
763
            END
764
        END
765
 
766
        ELSIF lang = Lang.langIni THEN
767
 
768
        IF depth = 0 THEN
769
            IF c = ";" THEN
770
                PrintLex(text, line, i, n, y, colors.comment, backColor);
771
                i := n
772
            ELSIF c = '"' THEN
773
                String(text, line, i, y, backColor)
774
            ELSIF c = "=" THEN
775
                PrintLex(text, line, i, i, y, colors.delim, backColor)
776
            ELSIF c = "[" THEN
777
                depth := 1;
778
                INC(i, 2);
779
                PrintComment(text, line, depth, i, y, backColor)
780
            ELSIF U.isDigit(c) THEN
781
                k := i;
782
                WHILE U.isDigit(getChar(line, i)) DO
783
                    INC(i)
784
                END;
785
                DEC(i);
786
                PrintLex(text, line, k, i, y, colors.num, backColor)
787
            ELSIF (U.isLetter(c) OR (c = "_")) THEN
788
                ident(text, i, i, y, line, backColor, TRUE)
789
            END
790
        ELSIF depth = 1 THEN
791
            IF c = "]" THEN
792
                depth := 0
793
            END
794
        END
795
 
796
        END;
797
        INC(i)
798
    END
799
END parse;
800
 
801
 
802
PROCEDURE leadingSpaces (line: tLine): INTEGER;
803
VAR
804
    i: INTEGER;
805
BEGIN
806
    i := 0;
807
    WHILE getChar(line, i) = SPACE DO
808
        INC(i)
809
    END
810
    RETURN i
811
END leadingSpaces;
812
 
813
 
814
PROCEDURE plain (text: tText; eot: BOOLEAN): CB.tBuffer;
815
VAR
816
    buf: CB.tBuffer;
817
    size: INTEGER;
818
    line: tLine;
819
    EOT: ARRAY 2 OF WCHAR;
820
BEGIN
821
    size := 0;
822
    line := text.first(tLine);
823
    WHILE line # NIL DO
824
        line.pos := size;
825
        INC(size, line.length);
826
        NextLine(line);
827
        IF line # NIL THEN
828
            INC(size, CB.lenEOL)
829
        END
830
    END;
831
    IF eot THEN
832
        INC(size, 2)
833
    END;
834
    buf := CB.create(size);
835
    line := text.first(tLine);
836
    WHILE line # NIL DO
837
        CB.append(buf, line, 0, line.length - 1);
838
        NextLine(line);
839
        IF line # NIL THEN
840
            CB.eol(buf)
841
        END
842
    END;
843
    IF eot THEN
844
        EOT[0] := 0X;
845
        EOT[1] := 0X;
846
        CB.appends(buf, EOT, 0, 1)
847
    END
848
    RETURN buf
849
END plain;
850
 
851
 
852
PROCEDURE search* (text: tText; s: ARRAY OF WCHAR; cs, whole: BOOLEAN): BOOLEAN;
853
VAR
854
    pos: List.tItem;
855
    res: BOOLEAN;
856
    plainText: Search.tBuffer;
857
BEGIN
858
    plainText := NIL;
859
    WHILE text.foundList.count # 0 DO
860
        pos := List.pop(text.foundList);
861
        DISPOSE(pos)
862
    END;
863
    text.whole := whole;
864
    text.cs := cs;
865
    text.searchText := s;
866
    IF ~cs THEN
867
        U.upcase16(text.searchText)
868
    END;
869
    IF text.searchText # "" THEN
870
        plainText := plain(text, TRUE);
871
        text.idxData := Search.index(plainText, text.table, cs);
872
        Search.find(plainText, text.table, text.searchText, whole, text.foundList);
873
        res := text.foundList.count > 0
874
    ELSE
875
        res := TRUE
876
    END;
877
    CB.destroy(plainText);
878
    CB.destroy(text.idxData);
879
    text.search := FALSE;
880
    text.foundSel := 0
881
    RETURN res
882
END search;
883
 
884
 
885
PROCEDURE modify (text: tText);
886
BEGIN
887
    text.modified := TRUE;
888
    text.comments := TRUE;
889
    text.search := TRUE;
890
    text.guard := TRUE
891
END modify;
892
 
893
 
894
PROCEDURE DelLine (text: tText; line: tLine);
895
BEGIN
896
    List._delete(text, line);
897
    Lines.destroy(line);
898
    modify(text)
899
END DelLine;
900
 
901
 
902
PROCEDURE setSelect (text: tText);
903
BEGIN
904
    IF text.select = text.cursor THEN
905
        text.select2^ := text.cursor^;
906
        text.select := text.select2
907
    END
908
END setSelect;
909
 
910
 
911
PROCEDURE resetSelect* (text: tText);
912
BEGIN
913
    text.select := text.cursor
914
END resetSelect;
915
 
916
 
917
PROCEDURE getLine (text: tText; n: INTEGER): tLine;
918
VAR
919
    item: List.tItem;
920
BEGIN
921
    item := List.getItem(text, n);
922
    RETURN item(tLine)
923
END getLine;
924
 
925
 
926
PROCEDURE SetPos* (text: tText; x, y: INTEGER);
927
VAR
928
    deltaY: INTEGER;
929
    cursor: pPoint;
930
   (* trimLength: INTEGER; *)
931
BEGIN
932
    cursor := text.cursor;
933
    y := MIN(MAX(y, 0), text.count - 1);
934
    deltaY := y - cursor.Y;
935
    IF deltaY # 0 THEN
936
        cursor.Y := y;
937
(*        trimLength := Lines.trimLength(text.curLine);
938
        IF text.curLine.length # trimLength THEN
939
            Lines.setChar(text.curLine, trimLength, 0X);
940
            text.curLine.length := trimLength
941
        END;*)
942
        IF deltaY = 1 THEN
943
            NextLine(text.curLine)
944
        ELSIF deltaY = -1 THEN
945
            PrevLine(text.curLine)
946
        ELSE
947
            text.curLine := getLine(text, y)
948
        END
949
    END;
950
    cursor.X := MIN(MAX(x, 0), text.curLine.length);
951
    IF text.scroll.Y > cursor.Y THEN
952
        text.scroll.Y := cursor.Y
953
    ELSIF text.scroll.Y + textsize.Y <= cursor.Y THEN
954
        text.scroll.Y := cursor.Y - textsize.Y + 1
955
    END;
956
    IF text.scroll.X > cursor.X THEN
957
        text.scroll.X := cursor.X
958
    ELSIF text.scroll.X + textsize.X <= cursor.X THEN
959
        text.scroll.X := cursor.X - textsize.X + 1
960
    END;
961
    IF (text.select.Y = cursor.Y) & (text.select.X > text.curLine.length) THEN
962
        text.select.X := text.curLine.length
963
    END;
964
    setSelect(text);
965
    text.foundSel := 0;
966
    ShowCursor;
967
    drawCursor := TRUE;
968
    text.CurX := -1
969
END SetPos;
970
 
971
 
972
PROCEDURE getSelect (text: tText; VAR selBeg, selEnd: tPoint);
973
BEGIN
974
    selBeg := text.cursor^;
975
    selEnd := text.select^;
976
    IF (selBeg.Y > selEnd.Y) OR (selBeg.Y = selEnd.Y) & (selBeg.X > selEnd.X) THEN
977
        selBeg := text.select^;
978
        selEnd := text.cursor^
979
    END
980
END getSelect;
981
 
982
 
983
PROCEDURE selected* (text: tText): BOOLEAN;
984
    RETURN (text.cursor.X # text.select.X) OR (text.cursor.Y # text.select.Y)
985
END selected;
986
 
987
 
988
PROCEDURE delSelect (text: tText);
989
VAR
990
    selBeg, selEnd: tPoint;
991
    line, last, cur: tLine;
992
BEGIN
993
    getSelect(text, selBeg, selEnd);
994
    IF (selBeg.Y = selEnd.Y) & (selBeg.X < selEnd.X) THEN
995
        line := text.curLine;
996
        Lines.delCharN(line, selBeg.X, selEnd.X - selBeg.X);
997
        Lines.modify(line);
998
        text.cursor^ := selBeg;
999
        resetSelect(text);
1000
        SetPos(text, text.cursor.X, text.cursor.Y);
1001
        modify(text)
1002
    ELSIF selBeg.Y < selEnd.Y THEN
1003
        SetPos(text, selBeg.X, selBeg.Y);
1004
        line := text.curLine;
1005
        Lines.delCharN(line, selBeg.X, line.length - selBeg.X);
1006
        last := getLine(text, selEnd.Y);
1007
        Lines.delCharN(last, 0, selEnd.X);
1008
        cur := line.next(tLine);
1009
        WHILE cur # last DO
1010
            DelLine(text, cur);
1011
            cur := line.next(tLine)
1012
        END;
1013
        resetSelect(text);
1014
        SetPos(text, text.cursor.X, text.cursor.Y);
1015
        pdelete(text);
1016
        modify(text)
1017
    END;
1018
    resetSelect(text)
1019
END delSelect;
1020
 
1021
 
1022
PROCEDURE delete (text: tText);
1023
VAR
1024
    i: INTEGER;
1025
    nextLine, curLine: tLine;
1026
BEGIN
1027
    IF selected(text) THEN
1028
        delSelect(text)
1029
    ELSE
1030
        i := text.cursor.X;
1031
        curLine := text.curLine;
1032
        IF i < curLine.length THEN
1033
            Lines.delChar(curLine, i);
1034
            Lines.modify(curLine);
1035
            modify(text)
1036
        ELSE
1037
            nextLine := curLine.next(tLine);
1038
            IF nextLine # NIL THEN
1039
                Lines.modify(curLine);
1040
                modify(text);
1041
                Lines.insert2(curLine, i, nextLine);
1042
                DelLine(text, nextLine)
1043
            END
1044
        END
1045
    END;
1046
    setSelect(text)
1047
END delete;
1048
 
1049
 
1050
PROCEDURE BkSpace (text: tText);
1051
VAR
1052
    i, n, k: INTEGER;
1053
    curLine, line: tLine;
1054
BEGIN
1055
    IF selected(text) THEN
1056
        delSelect(text)
1057
    ELSE
1058
        resetSelect(text);
1059
        i := text.cursor.X;
1060
        curLine := text.curLine;
1061
        IF i > 0 THEN
1062
            modify(text);
1063
            n := leadingSpaces(curLine);
1064
            IF n < i THEN
1065
                Lines.delChar(curLine, i - 1);
1066
                Lines.modify(curLine);
1067
                k := 1
1068
            ELSE
1069
                n := i;
1070
                line := curLine.prev(tLine);
1071
                k := n;
1072
                WHILE (line # NIL) & (k >= n) DO
1073
                    IF Lines.trimLength(line) # 0 THEN
1074
                        k := leadingSpaces(line)
1075
                    END;
1076
                    PrevLine(line)
1077
                END;
1078
                IF k >= n THEN
1079
                    k := 0
1080
                END;
1081
                DEC(n, k);
1082
                k := n;
1083
                Lines.modify(curLine);
1084
                Lines.delCharN(curLine, 0, n)
1085
            END;
1086
            SetPos(text, text.cursor.X - k, text.cursor.Y)
1087
        ELSE
1088
            PrevLine(curLine);
1089
            IF curLine # NIL THEN
1090
                SetPos(text, curLine.length, text.cursor.Y - 1);
1091
                delete(text)
1092
            END
1093
        END
1094
    END;
1095
    setSelect(text)
1096
END BkSpace;
1097
 
1098
 
1099
PROCEDURE enter (text: tText);
1100
VAR
1101
    n: INTEGER;
1102
    curLine, newLine, line: tLine;
1103
BEGIN
1104
    delSelect(text);
1105
    newLine := Lines.create(FALSE);
1106
    Lines.modify(newLine);
1107
    modify(text);
1108
    curLine := text.curLine;
1109
    IF text.cursor.X < curLine.length THEN
1110
        Lines.modify(curLine);
1111
        Lines.wrap(curLine, newLine, text.cursor.X)
1112
    END;
1113
    List._insert(text, curLine, newLine);
1114
    SetPos(text, 0, text.cursor.Y + 1);
1115
    line := text.curLine.prev(tLine);
1116
    n := -1;
1117
    WHILE (line # NIL) & (n = -1) DO
1118
        IF (*line.length*)Lines.trimLength(line) # 0 THEN
1119
            n := leadingSpaces(line)
1120
        END;
1121
        PrevLine(line)
1122
    END;
1123
    IF n = -1 THEN
1124
        n := 0
1125
    END;
1126
    Lines.insert3(text.curLine, 0, n);
1127
    SetPos(text, n, text.cursor.Y);
1128
    resetSelect(text);
1129
    WHILE n > 0 DO
1130
        Lines.setChar(text.curLine, n - 1, SPACE);
1131
        DEC(n)
1132
    END
1133
END enter;
1134
 
1135
 
1136
PROCEDURE input* (text: tText; code: INTEGER);
1137
VAR
1138
    curLine: tLine;
1139
 
1140
    PROCEDURE tab (text: tText);
1141
    VAR
1142
        i, x: INTEGER;
1143
        curLine: tLine;
1144
    BEGIN
1145
        delSelect(text);
1146
        curLine := text.curLine;
1147
        x := text.cursor.X;
1148
        Lines.modify(curLine);
1149
        modify(text);
1150
        i := TAB - x MOD TAB;
1151
        Lines.insert3(curLine, x, i);
1152
        SetPos(text, x + i, text.cursor.Y);
1153
        WHILE i > 0 DO
1154
            Lines.setChar(curLine, x + i - 1, SPACE);
1155
            DEC(i)
1156
        END
1157
    END tab;
1158
 
1159
BEGIN
1160
    IF (code >= ORD(SPACE)) & (code # 127) THEN
1161
        delSelect(text);
1162
        curLine := text.curLine;
1163
        Lines.insert(curLine, text.cursor.X, WCHR(code));
1164
        Lines.modify(curLine);
1165
        modify(text);
1166
        SetPos(text, text.cursor.X + 1, text.cursor.Y)
1167
    ELSIF code = 8 THEN
1168
        BkSpace(text)
1169
    ELSIF code = 9 THEN
1170
        tab(text)
1171
    ELSIF code = 13 THEN
1172
        enter(text)
1173
    END
1174
END input;
1175
 
1176
 
1177
PROCEDURE scroll* (text: tText; h, v: INTEGER);
1178
BEGIN
1179
    INC(text.scroll.X, h);
1180
    INC(text.scroll.Y, v);
1181
    text.scroll.X := MIN(MAX(text.scroll.X, 0), Lines.maxLength);
1182
    text.scroll.Y := MIN(MAX(text.scroll.Y, 0), text.count - 1)
1183
END scroll;
1184
 
1185
 
1186
PROCEDURE save* (text: tText; name: RW.tFileName; enc, nl: INTEGER): BOOLEAN;
1187
VAR
1188
    line: tLine;
1189
    file: RW.tOutput;
1190
    res: BOOLEAN;
1191
    Len: INTEGER;
1192
(*    item: List.tItem;*)
1193
BEGIN
1194
    res := TRUE;
1195
    file := RW.create(name, enc, nl);
1196
    IF file # NIL THEN
1197
(*        IF ChangeLog.Log.last IS ChangeLog.tGuard THEN
1198
            item := List.pop(ChangeLog.Log);
1199
            DISPOSE(item)
1200
        END;*)
1201
        line := text.first(tLine);
1202
        WHILE (line # NIL) & res DO
1203
            Len := Lines.trimLength(line);
1204
            IF RW.putString(file, line, Len) # Len THEN
1205
                res := FALSE
1206
            END;
1207
            IF line.modified THEN
1208
                Lines.save(line)
1209
            END;
1210
            NextLine(line);
1211
            IF line # NIL THEN
1212
                IF ~RW.newLine(file) THEN
1213
                    res := FALSE
1214
                END
1215
            END
1216
        END;
1217
        IF ~RW.close(file) THEN
1218
            res := FALSE
1219
        END;
1220
        IF res THEN
1221
            text.modified := FALSE
1222
        END
1223
    ELSE
1224
        res := FALSE
1225
    END;
1226
    text.guard := TRUE
1227
    RETURN res
1228
END save;
1229
 
1230
 
1231
PROCEDURE redoGuard (text: tText; guard: tGuard);
1232
BEGIN
1233
    text.edition := guard;
1234
    text.cursor^ := guard.cursor;
1235
    text.select2^ := guard.select2;
1236
    text.scroll := guard.scroll;
1237
    text.CurX := guard.CurX;
1238
    IF guard.selected THEN
1239
        text.select := text.select2
1240
    ELSE
1241
        text.select := text.cursor
1242
    END;
1243
    text.curLine := getLine(text, text.cursor.Y);
1244
    text.comments := TRUE;
1245
    text.search := TRUE
1246
END redoGuard;
1247
 
1248
 
1249
PROCEDURE undo* (text: tText);
1250
VAR
1251
    item: List.tItem;
1252
    guard: tGuard;
1253
BEGIN
1254
    guard := text.edition;
1255
    item := guard.prev;
1256
    WHILE (item # NIL) & ~(item IS tGuard) DO
1257
        item := item.prev
1258
    END;
1259
 
1260
    IF item # NIL THEN
1261
        guard := item(tGuard);
1262
        text.edition := guard;
1263
        text.modified := TRUE
1264
    END;
1265
 
1266
    item := ChangeLog.Log.first;
1267
    WHILE item # guard DO
1268
        ChangeLog.redo(item);
1269
        item := item.next
1270
    END;
1271
    redoGuard(text, guard);
1272
    ChangeLog.setGuard(guard)
1273
END undo;
1274
 
1275
 
1276
PROCEDURE redo* (text: tText);
1277
VAR
1278
    item: List.tItem;
1279
    guard: tGuard;
1280
BEGIN
1281
    guard := text.edition;
1282
    item := guard.next;
1283
    WHILE (item # NIL) & ~(item IS tGuard) DO
1284
        ChangeLog.redo(item);
1285
        item := item.next
1286
    END;
1287
    IF item # NIL THEN
1288
        guard := item(tGuard);
1289
        redoGuard(text, guard)
1290
    END;
1291
    ChangeLog.setGuard(guard)
1292
END redo;
1293
 
1294
 
1295
PROCEDURE copy (text: tText);
1296
VAR
1297
    selBeg, selEnd: tPoint;
1298
    first, line: tLine;
1299
    cnt, n: INTEGER;
1300
    buffer: CB.tBuffer;
1301
 
1302
 
1303
    PROCEDURE append (buffer: CB.tBuffer; line: tLine; first, last: INTEGER);
1304
    BEGIN
1305
        IF first <= last THEN
1306
            CB.append(buffer, line, first, last)
1307
        ELSE
1308
            IF U.OS = "KOS" THEN
1309
                CB.appends(buffer, SPACE, 0, 0)
1310
            END
1311
        END
1312
    END append;
1313
 
1314
 
1315
BEGIN
1316
    getSelect(text, selBeg, selEnd);
1317
 
1318
    first := getLine(text, selBeg.Y);
1319
    line := first;
1320
 
1321
    n := selEnd.Y - selBeg.Y;
1322
    cnt := 0;
1323
    WHILE n >= 0 DO
1324
        INC(cnt, line.length + lenEOL);
1325
        NextLine(line);
1326
        DEC(n)
1327
    END;
1328
 
1329
    buffer := CB.create(cnt);
1330
 
1331
    n := selEnd.Y - selBeg.Y;
1332
    line := first;
1333
    IF n = 0 THEN
1334
        CB.append(buffer, line, selBeg.X, selEnd.X - 1)
1335
    ELSE
1336
        append(buffer, line, selBeg.X, line.length - 1);
1337
        REPEAT
1338
            DEC(n);
1339
            CB.eol(buffer);
1340
            NextLine(line);
1341
            IF n > 0 THEN
1342
                append(buffer, line, 0, line.length - 1)
1343
            END
1344
        UNTIL n = 0;
1345
        append(buffer, line, 0, selEnd.X - 1)
1346
    END;
1347
    CB.eot(buffer);
1348
    CB.put(buffer);
1349
    CB.destroy(buffer)
1350
END copy;
1351
 
1352
 
1353
PROCEDURE paste (text: tText);
1354
VAR
1355
    line, newLine, curLine: tLine;
1356
    L: INTEGER;
1357
    cliptext: RW.tInput;
1358
    eol: BOOLEAN;
1359
    cursor: pPoint;
1360
BEGIN
1361
    line := Lines.create(TRUE);
1362
    cliptext := RW.clipboard();
1363
    delSelect(text);
1364
    cursor := text.cursor;
1365
    WHILE (cliptext # NIL) & (RW.getString(cliptext, line, eol) >= 0) DO
1366
        L := line.length;
1367
        IF L > 0 THEN
1368
            Lines.insert2(text.curLine, cursor.X, line);
1369
            Lines.modify(text.curLine);
1370
            modify(text);
1371
            SetPos(text, cursor.X + L, cursor.Y);
1372
            resetSelect(text)
1373
        END;
1374
        IF eol THEN
1375
            newLine := Lines.create(FALSE);
1376
            Lines.modify(newLine);
1377
            modify(text);
1378
            curLine := text.curLine;
1379
            IF cursor.X < curLine.length THEN
1380
                Lines.modify(curLine);
1381
                Lines.wrap(curLine, newLine, cursor.X)
1382
            END;
1383
            List._insert(text, curLine, newLine);
1384
            SetPos(text, 0, cursor.Y + 1);
1385
            resetSelect(text)
1386
        END;
1387
        Lines.destroy(line);
1388
        line := Lines.create(TRUE)
1389
    END;
1390
    Lines.destroy(line);
1391
    RW.destroy(cliptext)
1392
END paste;
1393
 
1394
 
1395
PROCEDURE searchScroll (text: tText; n: INTEGER);
1396
BEGIN
1397
    IF n - text.scroll.Y > textsize.Y - 1 THEN
1398
        text.scroll.Y := MAX(n - 2 * textsize.Y DIV 3, 0)
1399
    ELSIF n < text.scroll.Y THEN
1400
        text.scroll.Y := MAX(n - textsize.Y DIV 3, 0)
1401
    END
1402
END searchScroll;
1403
 
1404
 
1405
PROCEDURE goto* (text: tText; n: INTEGER): BOOLEAN;
1406
VAR
1407
    res: BOOLEAN;
1408
BEGIN
1409
    DEC(n);
1410
    IF (0 <= n) & (n < text.count) THEN
1411
        resetSelect(text);
1412
        searchScroll(text, n);
1413
        SetPos(text, 0, n);
1414
        res := TRUE
1415
    ELSE
1416
        res := FALSE
1417
    END
1418
    RETURN res
1419
END goto;
1420
 
1421
 
1422
PROCEDURE changeCase (text: tText; upper: BOOLEAN);
1423
VAR
1424
    i: INTEGER;
1425
    line: tLine;
1426
BEGIN
1427
    line := text.curLine;
1428
    i := text.cursor.X - 1;
1429
 
1430
    WHILE (i >= 0) & U.isLetter(getChar(line, i)) DO
1431
        DEC(i)
1432
    END;
1433
 
1434
    IF Lines.chCase(line, i + 1, text.cursor.X - 1, upper) THEN
1435
        modify(text)
1436
    END
1437
END changeCase;
1438
 
1439
 
1440
PROCEDURE chCase* (text: tText; upper: BOOLEAN);
1441
VAR
1442
    selBeg, selEnd: tPoint;
1443
    first, line: Lines.tLine;
1444
    cnt: INTEGER;
1445
    modified: BOOLEAN;
1446
BEGIN
1447
    modified := FALSE;
1448
    IF selected(text) THEN
1449
        getSelect(text, selBeg, selEnd);
1450
        first := getLine(text, selBeg.Y);
1451
        line := first;
1452
        cnt := selEnd.Y - selBeg.Y;
1453
        IF cnt = 0 THEN
1454
            IF Lines.chCase(line, selBeg.X, selEnd.X - 1, upper) THEN
1455
                modified := TRUE
1456
            END
1457
        ELSE
1458
            IF Lines.chCase(line, selBeg.X, line.length - 1, upper) THEN
1459
                modified := TRUE
1460
            END;
1461
            WHILE cnt > 1 DO
1462
                NextLine(line);
1463
                IF Lines.chCase(line, 0, line.length - 1, upper) THEN
1464
                    modified := TRUE
1465
                END;
1466
                DEC(cnt)
1467
            END;
1468
            NextLine(line);
1469
            IF Lines.chCase(line, 0, selEnd.X - 1, upper) THEN
1470
                modified := TRUE
1471
            END
1472
        END
1473
    END;
1474
    IF modified THEN
1475
        modify(text)
1476
    END
1477
END chCase;
1478
 
1479
 
1480
PROCEDURE UpDown (text: tText; step: INTEGER);
1481
VAR
1482
    temp: INTEGER;
1483
BEGIN
1484
    IF text.CurX = -1 THEN
1485
        text.CurX := text.cursor.X
1486
    END;
1487
    temp := text.CurX;
1488
    SetPos(text, temp, text.cursor.Y + step);
1489
    text.CurX := temp
1490
END UpDown;
1491
 
1492
 
1493
PROCEDURE delLine* (text: tText);
1494
BEGIN
1495
    resetSelect(text);
1496
    IF text.curLine.length > 0 THEN
1497
        Lines.delCharN(text.curLine, 0, text.curLine.length)
1498
    END;
1499
    SetPos(text, 0, text.cursor.Y);
1500
    IF text.cursor.Y = text.count - 1 THEN
1501
        BkSpace(text)
1502
    ELSE
1503
        delete(text)
1504
    END
1505
END delLine;
1506
 
1507
 
1508
PROCEDURE key* (text: tText; code: INTEGER; shift: SET);
1509
BEGIN
1510
    IF SHIFT IN shift THEN
1511
        setSelect(text)
1512
    ELSE
1513
        IF (33 <= code) & (code <= 40) THEN
1514
            resetSelect(text)
1515
        END
1516
    END;
1517
 
1518
    CASE code OF
1519
    |33:
1520
        IF CTRL IN shift THEN
1521
            UpDown(text, text.scroll.Y - text.cursor.Y)
1522
        ELSE
1523
            text.scroll.Y := MAX(text.scroll.Y - textsize.Y, 0);
1524
            UpDown(text, -textsize.Y)
1525
        END
1526
    |34:
1527
        IF CTRL IN shift THEN
1528
            UpDown(text, MIN(text.scroll.Y + textsize.Y - 1, text.count - 1) - text.cursor.Y)
1529
        ELSE
1530
            text.scroll.Y := MIN(text.scroll.Y + textsize.Y, text.count - 1);
1531
            UpDown(text, textsize.Y)
1532
        END
1533
    |35:
1534
        IF CTRL IN shift THEN
1535
            SetPos(text, text.last(tLine).length, text.count - 1)
1536
        ELSE
1537
            SetPos(text, text.curLine.length, text.cursor.Y)
1538
        END
1539
    |36:
1540
        IF CTRL IN shift THEN
1541
            SetPos(text, 0, 0)
1542
        ELSE
1543
            SetPos(text, 0, text.cursor.Y)
1544
        END
1545
    |37:
1546
        IF (text.cursor.X = 0) & (text.curLine.prev # NIL) THEN
1547
            SetPos(text, text.curLine.prev(tLine).length, text.cursor.Y - 1)
1548
        ELSE
1549
            SetPos(text, text.cursor.X - 1, text.cursor.Y)
1550
        END
1551
    |38:
1552
        UpDown(text, -1)
1553
    |39:
1554
        IF (text.cursor.X = text.curLine.length) & (text.curLine.next # NIL) THEN
1555
            SetPos(text, 0, text.cursor.Y + 1)
1556
        ELSE
1557
            SetPos(text, text.cursor.X + 1, text.cursor.Y)
1558
        END
1559
    |40:
1560
        UpDown(text, 1)
1561
 
1562
    |46: delete(text); ShowCursor; drawCursor := TRUE
1563
 
1564
    |ORD("C"):
1565
        IF CTRL IN shift THEN
1566
            IF selected(text) THEN
1567
                copy(text)
1568
            END
1569
        END
1570
    |ORD("X"):
1571
        IF CTRL IN shift THEN
1572
            IF selected(text) THEN
1573
                copy(text);
1574
                delSelect(text)
1575
            END
1576
        END
1577
    |ORD("V"):
1578
        IF CTRL IN shift THEN
1579
            IF CB.available() THEN
1580
                paste(text)
1581
            END
1582
        END
1583
    |ORD("A"):
1584
        IF CTRL IN shift THEN
1585
            text.select2.X := 0;
1586
            text.select2.Y := 0;
1587
            text.select := text.select2;
1588
            SetPos(text, text.last(tLine).length, text.count - 1)
1589
        END
1590
    |ORD("L"), ORD("U"):
1591
        IF CTRL IN shift THEN
1592
            changeCase(text, code = ORD("U"))
1593
        END
1594
    ELSE
1595
    END
1596
END key;
1597
 
1598
 
1599
PROCEDURE mouse* (text: tText; x, y: INTEGER);
1600
VAR
1601
    cursorX: INTEGER;
1602
BEGIN
1603
    DEC(x, padding.left);
1604
    DEC(y, padding.top);
1605
    cursorX := (x*2) DIV charWidth;
1606
    SetPos(text, cursorX DIV 2 + cursorX MOD 2 + text.scroll.X, y DIV charHeight + text.scroll.Y)
1607
END mouse;
1608
 
1609
 
1610
PROCEDURE selectWord* (text: tText);
1611
VAR
1612
    cursorX, x1, x2: INTEGER;
1613
    line: tLine;
1614
 
1615
    PROCEDURE isWordChar (c: WCHAR): BOOLEAN;
1616
        RETURN U.isLetter(c) OR U.isDigit(c) OR (c = "_")
1617
    END isWordChar;
1618
 
1619
BEGIN
1620
    resetSelect(text);
1621
    cursorX := text.cursor.X;
1622
    line := text.curLine;
1623
    x1 := cursorX - 1;
1624
    IF (cursorX < line.length) & isWordChar(getChar(line,cursorX)) THEN
1625
        x2 := cursorX;
1626
        WHILE (x2 < line.length) & isWordChar(getChar(line, x2)) DO
1627
            INC(x2)
1628
        END
1629
    ELSE
1630
        WHILE (x1 >= 0) & ~isWordChar(getChar(line, x1)) DO
1631
            DEC(x1)
1632
        END;
1633
        x2 := x1 + 1
1634
    END;
1635
    WHILE (x1 >= 0) & isWordChar(getChar(line, x1)) DO
1636
        DEC(x1)
1637
    END;
1638
    INC(x1);
1639
    IF x1 < x2 THEN
1640
        SetPos(text, x1, text.cursor.Y);
1641
        setSelect(text);
1642
        SetPos(text, x2, text.cursor.Y)
1643
    END
1644
END selectWord;
1645
 
1646
 
1647
PROCEDURE cursor (text: tText);
1648
VAR
1649
    x, y, h: INTEGER;
1650
    cursor: pPoint;
1651
BEGIN
1652
    cursor := text.cursor;
1653
    IF ~((text.scroll.Y > cursor.Y) OR (text.scroll.Y + textsize.Y <= cursor.Y) OR
1654
       (text.scroll.X > cursor.X) OR (text.scroll.X + textsize.X <= cursor.X)) THEN
1655
        x := (cursor.X - text.scroll.X)*charWidth + padding.left;
1656
        y := (cursor.Y - text.scroll.Y)*charHeight + 1 + padding.top;
1657
        h := charHeight - 2;
1658
        G.notVLine(canvas, x, y + inter DIV 2, y + h - inter DIV 2);
1659
        G.notVLine(canvas, x - 1, y + inter DIV 2, y + h - inter DIV 2)
1660
    END
1661
END cursor;
1662
 
1663
 
1664
PROCEDURE drawSelect (text: tText; line: tLine; selBeg, selEnd, y: INTEGER);
1665
VAR
1666
    Len, pos, x, firstCharIdx: INTEGER;
1667
BEGIN
1668
    firstCharIdx := MAX(text.scroll.X, selBeg);
1669
    Len := MAX(MIN(line.length - firstCharIdx, selEnd - firstCharIdx), 0);
1670
    Len := MIN(Len, textsize.X - pos + 1);
1671
    SetColor(colors.seltext, colors.selback);
1672
    pos := MAX((selBeg - text.scroll.X), 0);
1673
    x := pos*charWidth + padding.left;
1674
    G.SetColor(canvas, colors.selback);
1675
    G.FillRect(canvas, x - 2, y - inter DIV 2, x + 1 + Len*charWidth, y - inter DIV 2 + charHeight);
1676
    G.TextOut(canvas, pos*charWidth + padding.left, y, Lines.getPChar(line, firstCharIdx), Len)
1677
END drawSelect;
1678
 
1679
 
1680
PROCEDURE mark (line: tLine; y: INTEGER);
1681
VAR
1682
    color, i: INTEGER;
1683
BEGIN
1684
    IF line.modified THEN
1685
        color := colors.modified
1686
    ELSIF line.saved THEN
1687
        color := colors.saved
1688
    ELSE
1689
        color := colors.back
1690
    END;
1691
    G.SetColor(canvas, color);
1692
 
1693
    FOR i := 3 TO mark_width + 2 DO
1694
        G.VLine(canvas, padding.left - i, y, y + charHeight)
1695
    END
1696
END mark;
1697
 
1698
 
1699
PROCEDURE setPadding (left, top: INTEGER);
1700
BEGIN
1701
    padding.left := left;
1702
    padding.top := top;
1703
    textsize.X := (size.X - padding.left) DIV charWidth;
1704
    textsize.Y := (size.Y - padding.top) DIV charHeight;
1705
END setPadding;
1706
 
1707
 
1708
PROCEDURE draw* (text: tText);
1709
VAR
1710
    y, n, Len, cnt, i, x: INTEGER;
1711
    line, firstLine, lastLine: tLine;
1712
    selBeg, selEnd: tPoint;
1713
    s: ARRAY 12 OF WCHAR;
1714
    backColor, numWidth, xNum, wNum: INTEGER;
1715
    p: Search.tPos;
1716
    guard: tGuard;
1717
BEGIN
1718
    IF text.search & search(text, text.searchText, text.cs, text.whole) THEN END;
1719
    IF (text.lang # Lang.langNone) & text.comments THEN
1720
        Comments(text)
1721
    END;
1722
    IF text.guard THEN
1723
        NEW(guard);
1724
        List.append(ChangeLog.Log, guard);
1725
        text.edition := guard;
1726
        text.guard := FALSE;
1727
    ELSE
1728
        guard := text.edition
1729
    END;
1730
 
1731
    guard.cursor := text.cursor^;
1732
    guard.select2 := text.select2^;
1733
    guard.scroll := text.scroll;
1734
    guard.CurX := text.CurX;
1735
    guard.selected := text.select = text.select2;
1736
 
1737
    G.SetColor(canvas, colors.back);
1738
    G.clear(canvas);
1739
    IF text.numbers THEN
1740
        numWidth := U.lg10(text.count) + 2;
1741
        wNum := charWidth;
1742
        xNum := numWidth*wNum - wNum DIV 2;
1743
        setPadding(numWidth*wNum + pad_left, padding.top);
1744
    ELSE
1745
        setPadding(pad_left, padding.top)
1746
    END;
1747
    getSelect(text, selBeg, selEnd);
1748
    y := padding.top + inter DIV 2;
1749
    n := text.scroll.Y;
1750
    line := getLine(text, n);
1751
    firstLine := line;
1752
    cnt := 0;
1753
    WHILE (line # NIL) & (cnt <= textsize.Y) DO
1754
        backColor := colors.back;
1755
        IF (line = text.curLine) & ~selected(text) THEN
1756
            G.SetColor(canvas, colors.curline);
1757
            G.FillRect(canvas, padding.left - 2, y - inter DIV 2, size.X - 1, y - inter DIV 2 + charHeight);
1758
            backColor := colors.curline
1759
        END;
1760
        SetColor(colors.text, backColor);
1761
        Len := MAX(line.length - text.scroll.X, 0);
1762
        G.TextOut(canvas, padding.left, y, Lines.getPChar(line, text.scroll.X), MIN(Len, textsize.X + 1));
1763
        IF text.lang # Lang.langNone THEN
1764
            parse(text, line, y, backColor, text.lang)
1765
        END;
1766
        mark(line, y - inter DIV 2);
1767
        IF (selBeg.Y < n) & (n < selEnd.Y) THEN
1768
            drawSelect(text, line, 0, line.length, y)
1769
        ELSIF (selBeg.Y = n) & (selEnd.Y = n) & (selBeg.X # selEnd.X) THEN
1770
            drawSelect(text, line, selBeg.X, selEnd.X, y)
1771
        ELSIF (selBeg.Y = n) & (selEnd.Y # n) THEN
1772
            drawSelect(text, line, selBeg.X, line.length, y)
1773
        ELSIF (selBeg.Y # n) & (selEnd.Y = n) THEN
1774
            drawSelect(text, line, 0, selEnd.X, y)
1775
        END;
1776
        NextLine(line);
1777
        INC(y, charHeight);
1778
        INC(n);
1779
        INC(cnt)
1780
    END;
1781
    IF text.numbers THEN
1782
        G.SetColor(canvas, colors.numback);
1783
        G.FillRect(canvas, 0, 0, padding.left - pad_left (*+ 1*), size.Y - 1);
1784
        SetColor(colors.numtext, colors.numback);
1785
        y := padding.top + inter DIV 2;
1786
        n := MIN(text.scroll.Y + textsize.Y + 1, text.count);
1787
        FOR i := text.scroll.Y + 1 TO n DO
1788
            IF (i MOD 10 = 0) OR (i - 1 = text.cursor.Y) THEN
1789
                U.int2str(i, s);
1790
                G.TextOut2(canvas, (numWidth - U.lg10(i) - 1)*wNum - wNum DIV 2, y, s, LENGTH(s));
1791
            ELSIF i MOD 5 = 0 THEN
1792
                G.SetColor(canvas, colors.numtext);
1793
                G.HLine(canvas, y - inter DIV 2 + charHeight DIV 2, xNum - wNum, xNum)
1794
            ELSE
1795
                G.SetColor(canvas, colors.numtext);
1796
                G.HLine(canvas, y - inter DIV 2 + charHeight DIV 2, xNum - wNum DIV 2, xNum)
1797
            END;
1798
            INC(y, charHeight)
1799
        END
1800
    END;
1801
 
1802
    IF text.searchText # "" THEN
1803
        cnt := 0;
1804
        line := firstLine;
1805
        lastLine := line;
1806
        WHILE (line # NIL) & (cnt <= textsize.Y) DO
1807
            lastLine := line;
1808
            NextLine(line);
1809
            INC(cnt)
1810
        END;
1811
        p := text.foundList.first(Search.tPos);
1812
        WHILE p # NIL DO
1813
            y := padding.top + inter DIV 2;
1814
            IF (firstLine.pos <= p.pos) & (p.pos <= lastLine.pos + lastLine.length) THEN
1815
                line := firstLine;
1816
                WHILE (line.pos <= p.pos) & (line # lastLine) DO
1817
                    NextLine(line);
1818
                    INC(y, charHeight)
1819
                END;
1820
                IF (line # lastLine) & (line # firstLine) OR (line = lastLine) & (line.pos > p.pos) THEN
1821
                    PrevLine(line);
1822
                    DEC(y, charHeight)
1823
                END;
1824
                x := (p.pos - line.pos - text.scroll.X)*charWidth + padding.left;
1825
                n := LENGTH(text.searchText)*charWidth;
1826
                WHILE n > 0 DO
1827
                    IF x >= padding.left THEN
1828
                        G.notVLine(canvas, x, y, y + charHeight - inter)
1829
                    END;
1830
                    INC(x);
1831
                    DEC(n)
1832
                END;
1833
            END;
1834
            p := p.next(Search.tPos)
1835
        END
1836
    END;
1837
 
1838
    IF text.foundSel > 0 THEN
1839
        x := (text.cursor.X - text.scroll.X)*charWidth + padding.left;
1840
        y := (text.cursor.Y - text.scroll.Y)*charHeight + padding.top + inter DIV 2;
1841
        n := text.foundSel*charWidth;
1842
        WHILE n > 0 DO
1843
            IF x >= padding.left THEN
1844
                G.xorVLine(canvas, x, y, y + charHeight - inter)
1845
            END;
1846
            INC(x);
1847
            DEC(n)
1848
        END
1849
    END;
1850
 
1851
    IF drawCursor THEN
1852
        cursor(text)
1853
    END;
1854
    G.SetColor(canvas, colors.border);
1855
    G.Rect(canvas, 0, 0, size.X - 1, size.Y - 1);
1856
END draw;
1857
 
1858
 
1859
PROCEDURE create (fileName: RW.tFileName): tText;
1860
VAR
1861
    text: tText;
1862
BEGIN
1863
    NEW(text);
1864
    NEW(text.cursor);
1865
    NEW(text.select2);
1866
    text.cursor.X := 0;
1867
    text.cursor.Y := 0;
1868
    resetSelect(text);
1869
    text.scroll.X := 0;
1870
    text.scroll.Y := 0;
1871
    setPadding(padding.left, padding.top);
1872
    text.curLine := NIL;
1873
    text.modified := FALSE;
1874
    text.comments := TRUE;
1875
    text.search := TRUE;
1876
    text.cs := FALSE;
1877
    text.whole := FALSE;
1878
    text.numbers := TRUE;
1879
    text.guard := TRUE;
1880
    text.idxData := NIL;
1881
    text.edition := NIL;
1882
    text.foundList := List.create(NIL);
1883
    text.searchText := "";
1884
    text.foundSel := 0;
1885
    text.CurX := -1;
1886
    setName(text, fileName);
1887
    ASSERT(text = List.create(text))
1888
    RETURN text
1889
END create;
1890
 
1891
 
1892
PROCEDURE setColors* (text, back, seltext, selback, modified, saved, curline, numtext, numback,
1893
                        comment, string, num, delim, key1, key2, key3, border: INTEGER);
1894
BEGIN
1895
    colors.text := text;
1896
    colors.back := back;
1897
    colors.seltext := seltext;
1898
    colors.selback := selback;
1899
    colors.modified := modified;
1900
    colors.saved := saved;
1901
    colors.curline := curline;
1902
    colors.numtext := numtext;
1903
    colors.numback := numback;
1904
    colors.comment := comment;
1905
    colors.string  := string;
1906
    colors.num := num;
1907
    colors.delim := delim;
1908
    colors.key1 := key1;
1909
    colors.key2 := key2;
1910
    colors.key3 := key3;
1911
    colors.border := border;
1912
END setColors;
1913
 
1914
 
1915
PROCEDURE setCanvas* (Canvas: G.tCanvas);
1916
BEGIN
1917
    canvas := Canvas;
1918
    charWidth := canvas.font.width;
1919
    charHeight := canvas.font.height + inter
1920
END setCanvas;
1921
 
1922
 
1923
PROCEDURE resize* (width, height: INTEGER);
1924
BEGIN
1925
    size.X := width;
1926
    size.Y := height;
1927
    setPadding(padding.left, padding.top)
1928
END resize;
1929
 
1930
 
1931
PROCEDURE destroy* (VAR text: tText);
1932
BEGIN
1933
    IF search(text, "", FALSE, FALSE) THEN END;
1934
    WHILE text.last # NIL DO
1935
        DelLine(text, text.last(tLine))
1936
    END;
1937
    DISPOSE(text.foundList);
1938
    DISPOSE(text.cursor);
1939
    DISPOSE(text.select2);
1940
    DISPOSE(text)
1941
END destroy;
1942
 
1943
 
1944
PROCEDURE open* (name: RW.tFileName; VAR errno: INTEGER): tText;
1945
VAR
1946
    text: tText;
1947
    file: RW.tInput;
1948
    n, enc: INTEGER;
1949
    eol: BOOLEAN;
1950
    line: tLine;
1951
BEGIN
1952
    errno := 0;
1953
    text := NIL;
1954
    file := RW.load(name, enc);
1955
    IF file # NIL THEN
1956
        text := create(name);
1957
        text.enc := enc;
1958
        REPEAT
1959
            line := Lines.create(FALSE);
1960
            n := RW.getString(file, line, eol);
1961
            IF n >= 0 THEN
1962
                List._append(text, line)
1963
            ELSE
1964
                Lines.destroy(line)
1965
            END
1966
        UNTIL n < 0;
1967
        RW.destroy(file);
1968
        IF n = -1 THEN
1969
            IF text.count = 0 THEN
1970
                List._append(text, Lines.create(FALSE))
1971
            END;
1972
            text.curLine := text.first(tLine);
1973
            SetPos(text, 0, 0);
1974
            resetSelect(text)
1975
        END
1976
    ELSE
1977
        errno := 1
1978
    END;
1979
    IF (text # NIL) & (text.lang # Lang.langNone) THEN
1980
        Comments(text)
1981
    END
1982
    RETURN text
1983
END open;
1984
 
1985
 
1986
PROCEDURE findNext* (text: tText; prev: BOOLEAN): BOOLEAN;
1987
VAR
1988
    cursorPos, x, y, X, Y, Len: INTEGER;
1989
    p: Search.tPos;
1990
    line: tLine;
1991
    res: BOOLEAN;
1992
BEGIN
1993
    X := text.cursor.X;
1994
    Y := text.cursor.Y;
1995
    text.cursor.X := MIN(text.cursor.X, text.curLine.length);
1996
    cursorPos := text.curLine.pos + text.cursor.X - ORD(prev) - ORD(~prev & (text.foundSel = 0));
1997
    p := text.foundList.first(Search.tPos);
1998
    WHILE (p # NIL) & (p.pos <= cursorPos) DO
1999
        p := p.next(Search.tPos)
2000
    END;
2001
    IF prev THEN
2002
        IF p = NIL THEN
2003
            p := text.foundList.last(Search.tPos)
2004
        ELSE
2005
            p := p.prev(Search.tPos)
2006
        END
2007
    END;
2008
    res := p # NIL;
2009
    IF res THEN
2010
        y := 0;
2011
        line := text.first(tLine);
2012
        WHILE (line.pos <= p.pos) & (line.next # NIL) DO
2013
            NextLine(line);
2014
            INC(y)
2015
        END;
2016
        IF (line.next # NIL) OR (line.pos > p.pos) THEN
2017
            PrevLine(line);
2018
            DEC(y)
2019
        END;
2020
        resetSelect(text);
2021
        searchScroll(text, y);
2022
        x := p.pos - line.pos;
2023
        Len := LENGTH(text.searchText);
2024
        IF x + Len > text.scroll.X + textsize.X THEN
2025
            text.scroll.X := MAX(x + Len - textsize.X + 3, 0)
2026
        ELSIF x < text.scroll.X THEN
2027
            text.scroll.X := MAX(x - 3, 0)
2028
        END;
2029
        SetPos(text, x, y);
2030
        text.foundSel := Len
2031
    ELSE
2032
        SetPos(text, X, Y)
2033
    END
2034
    RETURN res
2035
END findNext;
2036
 
2037
 
2038
PROCEDURE rewrite (line: tLine; repl: ARRAY OF WCHAR; pos, n: INTEGER);
2039
BEGIN
2040
    IF n > 0 THEN
2041
        Lines.copy(line)
2042
    END;
2043
    WHILE n > 0 DO
2044
        DEC(n);
2045
        Lines.setChar(line, pos + n, repl[n])
2046
    END
2047
END rewrite;
2048
 
2049
 
2050
PROCEDURE replace* (text: tText; s: ARRAY OF WCHAR; n: INTEGER);
2051
VAR
2052
    line: tLine;
2053
    sLen, i: INTEGER;
2054
BEGIN
2055
    IF text.foundSel > 0 THEN
2056
        line := text.curLine;
2057
        sLen := LENGTH(s);
2058
        i := text.cursor.X;
2059
        IF sLen > n THEN
2060
            Lines.insert3(line, i, sLen - n)
2061
        END;
2062
        SetPos(text, i + sLen, text.cursor.Y);
2063
        rewrite(line, s, i, sLen);
2064
        IF n > sLen THEN
2065
            Lines.delCharN(line, text.cursor.X, n - sLen)
2066
        END;
2067
        resetSelect(text);
2068
        Lines.modify(line);
2069
        modify(text)
2070
    END
2071
END replace;
2072
 
2073
 
2074
PROCEDURE replaceAll* (text: tText; s: ARRAY OF WCHAR; n: INTEGER): INTEGER;
2075
VAR
2076
    p: Search.tPos;
2077
    line: tLine;
2078
    y, k, d, pos, y0: INTEGER;
2079
BEGIN
2080
    resetSelect(text);
2081
    SetPos(text, 0, 0);
2082
    line := text.first(tLine);
2083
    y := 0;
2084
    y0 := -1;
2085
    k := 0;
2086
    d := LENGTH(s) - n;
2087
    p := text.foundList.first(Search.tPos);
2088
    WHILE p # NIL DO
2089
        pos := p.pos;
2090
        WHILE (line.pos <= pos) & (line.next # NIL) DO
2091
            NextLine(line);
2092
            INC(y)
2093
        END;
2094
        IF (line.next # NIL) OR (line.pos > pos) THEN
2095
            PrevLine(line);
2096
            DEC(y)
2097
        END;
2098
        IF y = y0 THEN
2099
            INC(k, d)
2100
        ELSE
2101
            k := 0;
2102
            y0 := y
2103
        END;
2104
        SetPos(text, pos - line.pos + k, y);
2105
        text.foundSel := n;
2106
        replace(text, s, n);
2107
        p := p.next(Search.tPos)
2108
    END
2109
    RETURN text.foundList.count
2110
END replaceAll;
2111
 
2112
 
2113
PROCEDURE New* (): tText;
2114
VAR
2115
    text: tText;
2116
BEGIN
2117
    text := create("");
2118
    List._append(text, Lines.create(FALSE));
2119
    text.curLine := text.first(tLine);
2120
    text.enc := E.CP866;
2121
    SetPos(text, 0, 0);
2122
    resetSelect(text)
2123
    RETURN text
2124
END New;
2125
 
2126
 
2127
PROCEDURE empty;
2128
END empty;
2129
 
2130
 
2131
PROCEDURE init* (pShowCursor: tProcedure);
2132
BEGIN
2133
    ShowCursor := empty;
2134
    IF pShowCursor # NIL THEN
2135
        ShowCursor := pShowCursor
2136
    END;
2137
    pdelete := delete;
2138
    drawCursor := TRUE;
2139
    padding.left := pad_left;
2140
    padding.top := pad_top;
2141
END init;
2142
 
2143
 
2144
END Text.