Subversion Repositories Kolibri OS

Rev

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