Subversion Repositories Kolibri OS

Rev

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