Subversion Repositories Kolibri OS

Rev

Rev 8762 | Rev 9050 | 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
 
9010 leency 1509
PROCEDURE dupLine (text: tText);
1510
VAR
1511
    newLine, curLine: tLine;
1512
BEGIN
1513
    curLine := text.curLine;
1514
    newLine := Lines.create(FALSE);
1515
    Lines.modify(newLine);
1516
    modify(text);
1517
    Lines.insert3(newLine, 0, curLine.length);
1518
    List._insert(text, curLine, newLine);
1519
    Lines.move(curLine, newLine)
1520
END dupLine;
1521
 
1522
 
1523
PROCEDURE exchange (text: tText; first, second: tLine);
1524
BEGIN
1525
    List._exchange(text, first, second);
1526
    Lines.modify(text.curLine);
1527
    modify(text);
1528
    UpDown(text, 0)
1529
END exchange;
1530
 
1531
 
1532
PROCEDURE upLine (text: tText);
1533
BEGIN
1534
    IF text.cursor.Y > 0 THEN
1535
        DEC(text.cursor.Y);
1536
        exchange(text, text.curLine.prev(tLine), text.curLine)
1537
    END
1538
END upLine;
1539
 
1540
 
1541
PROCEDURE downLine (text: tText);
1542
BEGIN
1543
    IF text.cursor.Y < text.count - 1 THEN
1544
        INC(text.cursor.Y);
1545
        exchange(text, text.curLine, text.curLine.next(tLine))
1546
    END
1547
END downLine;
1548
 
1549
 
1550
PROCEDURE isWordChar (c: WCHAR): BOOLEAN;
1551
    RETURN U.isLetter(c) OR U.isDigit(c) OR (c = "_")
1552
END isWordChar;
1553
 
1554
 
1555
PROCEDURE wordSel* (text: tText);
1556
VAR
1557
    n, i, x1, x2: INTEGER;
1558
    selBeg, selEnd: tPoint;
1559
    str: tString;
1560
    curLine: tLine;
1561
BEGIN
1562
    curLine := text.curLine;
1563
    IF selected(text) & (text.cursor.Y = text.select.Y) THEN
1564
        getSelect(text, selBeg, selEnd);
1565
        x1 := selBeg.X;
1566
        x2 := selEnd.X;
1567
        n := getString(curLine, x1, x2 - x1, str);
1568
    ELSE
1569
        str := ""
1570
    END;
1571
    IF str # "" THEN
1572
        i := 0;
1573
        WHILE (i < n) & isWordChar(str[i]) DO
1574
            INC(i)
1575
        END;
1576
        IF (i # n) OR
1577
            ((x1 > 0) & isWordChar(getChar(curLine, x1 - 1))) OR
1578
            ((x2 < curLine.length) & isWordChar(getChar(curLine, x2))) THEN
1579
            str := ""
1580
        END
1581
    END;
1582
    IF search(text, str, TRUE, TRUE) THEN END
1583
END wordSel;
1584
 
1585
 
8728 leency 1586
PROCEDURE key* (text: tText; code: INTEGER; shift: SET);
1587
BEGIN
1588
    IF SHIFT IN shift THEN
1589
        setSelect(text)
1590
    ELSE
1591
        IF (33 <= code) & (code <= 40) THEN
1592
            resetSelect(text)
1593
        END
1594
    END;
1595
 
1596
    CASE code OF
1597
    |33:
1598
        IF CTRL IN shift THEN
1599
            UpDown(text, text.scroll.Y - text.cursor.Y)
1600
        ELSE
1601
            text.scroll.Y := MAX(text.scroll.Y - textsize.Y, 0);
1602
            UpDown(text, -textsize.Y)
1603
        END
1604
    |34:
1605
        IF CTRL IN shift THEN
1606
            UpDown(text, MIN(text.scroll.Y + textsize.Y - 1, text.count - 1) - text.cursor.Y)
1607
        ELSE
1608
            text.scroll.Y := MIN(text.scroll.Y + textsize.Y, text.count - 1);
1609
            UpDown(text, textsize.Y)
1610
        END
1611
    |35:
1612
        IF CTRL IN shift THEN
1613
            SetPos(text, text.last(tLine).length, text.count - 1)
1614
        ELSE
1615
            SetPos(text, text.curLine.length, text.cursor.Y)
1616
        END
1617
    |36:
1618
        IF CTRL IN shift THEN
1619
            SetPos(text, 0, 0)
1620
        ELSE
1621
            SetPos(text, 0, text.cursor.Y)
1622
        END
1623
    |37:
1624
        IF (text.cursor.X = 0) & (text.curLine.prev # NIL) THEN
1625
            SetPos(text, text.curLine.prev(tLine).length, text.cursor.Y - 1)
1626
        ELSE
1627
            SetPos(text, text.cursor.X - 1, text.cursor.Y)
1628
        END
1629
    |38:
9010 leency 1630
        IF CTRL IN shift THEN
1631
            upLine(text)
1632
        ELSE
1633
            UpDown(text, -1)
1634
        END
8728 leency 1635
    |39:
1636
        IF (text.cursor.X = text.curLine.length) & (text.curLine.next # NIL) THEN
1637
            SetPos(text, 0, text.cursor.Y + 1)
1638
        ELSE
1639
            SetPos(text, text.cursor.X + 1, text.cursor.Y)
1640
        END
1641
    |40:
9010 leency 1642
        IF CTRL IN shift THEN
1643
            downLine(text)
1644
        ELSE
1645
            UpDown(text, 1)
1646
        END
1647
    |46:
1648
        IF CTRL IN shift THEN
1649
            delLine(text)
1650
        ELSE
1651
            delete(text); ShowCursor; drawCursor := TRUE
1652
        END
8728 leency 1653
    |ORD("C"):
1654
        IF CTRL IN shift THEN
1655
            IF selected(text) THEN
1656
                copy(text)
1657
            END
1658
        END
1659
    |ORD("X"):
1660
        IF CTRL IN shift THEN
1661
            IF selected(text) THEN
1662
                copy(text);
1663
                delSelect(text)
1664
            END
1665
        END
1666
    |ORD("V"):
1667
        IF CTRL IN shift THEN
1668
            IF CB.available() THEN
1669
                paste(text)
1670
            END
1671
        END
1672
    |ORD("A"):
1673
        IF CTRL IN shift THEN
1674
            text.select2.X := 0;
1675
            text.select2.Y := 0;
1676
            text.select := text.select2;
1677
            SetPos(text, text.last(tLine).length, text.count - 1)
1678
        END
1679
    |ORD("L"), ORD("U"):
1680
        IF CTRL IN shift THEN
1681
            changeCase(text, code = ORD("U"))
1682
        END
9010 leency 1683
    |ORD("D"):
1684
        IF CTRL IN shift THEN
1685
            dupLine(text)
1686
        END
8728 leency 1687
    ELSE
1688
    END
1689
END key;
1690
 
1691
 
1692
PROCEDURE mouse* (text: tText; x, y: INTEGER);
1693
VAR
1694
    cursorX: INTEGER;
1695
BEGIN
1696
    DEC(x, padding.left);
1697
    DEC(y, padding.top);
1698
    cursorX := (x*2) DIV charWidth;
1699
    SetPos(text, cursorX DIV 2 + cursorX MOD 2 + text.scroll.X, y DIV charHeight + text.scroll.Y)
1700
END mouse;
1701
 
1702
 
1703
PROCEDURE selectWord* (text: tText);
1704
VAR
1705
    cursorX, x1, x2: INTEGER;
1706
    line: tLine;
1707
BEGIN
1708
    resetSelect(text);
1709
    cursorX := text.cursor.X;
1710
    line := text.curLine;
1711
    x1 := cursorX - 1;
1712
    IF (cursorX < line.length) & isWordChar(getChar(line,cursorX)) THEN
1713
        x2 := cursorX;
1714
        WHILE (x2 < line.length) & isWordChar(getChar(line, x2)) DO
1715
            INC(x2)
1716
        END
1717
    ELSE
1718
        WHILE (x1 >= 0) & ~isWordChar(getChar(line, x1)) DO
1719
            DEC(x1)
1720
        END;
1721
        x2 := x1 + 1
1722
    END;
1723
    WHILE (x1 >= 0) & isWordChar(getChar(line, x1)) DO
1724
        DEC(x1)
1725
    END;
1726
    INC(x1);
1727
    IF x1 < x2 THEN
1728
        SetPos(text, x1, text.cursor.Y);
1729
        setSelect(text);
1730
        SetPos(text, x2, text.cursor.Y)
1731
    END
1732
END selectWord;
1733
 
1734
 
1735
PROCEDURE cursor (text: tText);
1736
VAR
1737
    x, y, h: INTEGER;
1738
    cursor: pPoint;
1739
BEGIN
1740
    cursor := text.cursor;
1741
    IF ~((text.scroll.Y > cursor.Y) OR (text.scroll.Y + textsize.Y <= cursor.Y) OR
1742
       (text.scroll.X > cursor.X) OR (text.scroll.X + textsize.X <= cursor.X)) THEN
1743
        x := (cursor.X - text.scroll.X)*charWidth + padding.left;
1744
        y := (cursor.Y - text.scroll.Y)*charHeight + 1 + padding.top;
1745
        h := charHeight - 2;
1746
        G.notVLine(canvas, x, y + inter DIV 2, y + h - inter DIV 2);
1747
        G.notVLine(canvas, x - 1, y + inter DIV 2, y + h - inter DIV 2)
1748
    END
1749
END cursor;
1750
 
1751
 
1752
PROCEDURE drawSelect (text: tText; line: tLine; selBeg, selEnd, y: INTEGER);
1753
VAR
1754
    Len, pos, x, firstCharIdx: INTEGER;
1755
BEGIN
1756
    firstCharIdx := MAX(text.scroll.X, selBeg);
1757
    Len := MAX(MIN(line.length - firstCharIdx, selEnd - firstCharIdx), 0);
1758
    Len := MIN(Len, textsize.X - pos + 1);
1759
    SetColor(colors.seltext, colors.selback);
1760
    pos := MAX((selBeg - text.scroll.X), 0);
1761
    x := pos*charWidth + padding.left;
1762
    G.SetColor(canvas, colors.selback);
1763
    G.FillRect(canvas, x - 2, y - inter DIV 2, x + 1 + Len*charWidth, y - inter DIV 2 + charHeight);
1764
    G.TextOut(canvas, pos*charWidth + padding.left, y, Lines.getPChar(line, firstCharIdx), Len)
1765
END drawSelect;
1766
 
1767
 
1768
PROCEDURE mark (line: tLine; y: INTEGER);
1769
VAR
1770
    color, i: INTEGER;
1771
BEGIN
1772
    IF line.modified THEN
1773
        color := colors.modified
1774
    ELSIF line.saved THEN
1775
        color := colors.saved
1776
    ELSE
1777
        color := colors.back
1778
    END;
1779
    G.SetColor(canvas, color);
1780
 
1781
    FOR i := 3 TO mark_width + 2 DO
1782
        G.VLine(canvas, padding.left - i, y, y + charHeight)
1783
    END
1784
END mark;
1785
 
1786
 
1787
PROCEDURE setPadding (left, top: INTEGER);
1788
BEGIN
1789
    padding.left := left;
1790
    padding.top := top;
1791
    textsize.X := (size.X - padding.left) DIV charWidth;
1792
    textsize.Y := (size.Y - padding.top) DIV charHeight;
1793
END setPadding;
1794
 
1795
 
1796
PROCEDURE draw* (text: tText);
1797
VAR
1798
    y, n, Len, cnt, i, x: INTEGER;
1799
    line, firstLine, lastLine: tLine;
1800
    selBeg, selEnd: tPoint;
1801
    s: ARRAY 12 OF WCHAR;
1802
    backColor, numWidth, xNum, wNum: INTEGER;
1803
    p: Search.tPos;
1804
    guard: tGuard;
1805
BEGIN
1806
    IF text.search & search(text, text.searchText, text.cs, text.whole) THEN END;
1807
    IF (text.lang # Lang.langNone) & text.comments THEN
1808
        Comments(text)
1809
    END;
1810
    IF text.guard THEN
1811
        NEW(guard);
1812
        List.append(ChangeLog.Log, guard);
1813
        text.edition := guard;
1814
        text.guard := FALSE;
1815
    ELSE
1816
        guard := text.edition
1817
    END;
1818
 
1819
    guard.cursor := text.cursor^;
1820
    guard.select2 := text.select2^;
1821
    guard.scroll := text.scroll;
1822
    guard.CurX := text.CurX;
1823
    guard.selected := text.select = text.select2;
1824
 
1825
    G.SetColor(canvas, colors.back);
1826
    G.clear(canvas);
1827
    IF text.numbers THEN
1828
        numWidth := U.lg10(text.count) + 2;
1829
        wNum := charWidth;
1830
        xNum := numWidth*wNum - wNum DIV 2;
1831
        setPadding(numWidth*wNum + pad_left, padding.top);
1832
    ELSE
1833
        setPadding(pad_left, padding.top)
1834
    END;
1835
    getSelect(text, selBeg, selEnd);
1836
    y := padding.top + inter DIV 2;
1837
    n := text.scroll.Y;
1838
    line := getLine(text, n);
1839
    firstLine := line;
1840
    cnt := 0;
1841
    WHILE (line # NIL) & (cnt <= textsize.Y) DO
1842
        backColor := colors.back;
1843
        IF (line = text.curLine) & ~selected(text) THEN
1844
            G.SetColor(canvas, colors.curline);
1845
            G.FillRect(canvas, padding.left - 2, y - inter DIV 2, size.X - 1, y - inter DIV 2 + charHeight);
1846
            backColor := colors.curline
1847
        END;
1848
        SetColor(colors.text, backColor);
1849
        Len := MAX(line.length - text.scroll.X, 0);
1850
        G.TextOut(canvas, padding.left, y, Lines.getPChar(line, text.scroll.X), MIN(Len, textsize.X + 1));
1851
        IF text.lang # Lang.langNone THEN
1852
            parse(text, line, y, backColor, text.lang)
1853
        END;
1854
        mark(line, y - inter DIV 2);
1855
        IF (selBeg.Y < n) & (n < selEnd.Y) THEN
1856
            drawSelect(text, line, 0, line.length, y)
1857
        ELSIF (selBeg.Y = n) & (selEnd.Y = n) & (selBeg.X # selEnd.X) THEN
1858
            drawSelect(text, line, selBeg.X, selEnd.X, y)
1859
        ELSIF (selBeg.Y = n) & (selEnd.Y # n) THEN
1860
            drawSelect(text, line, selBeg.X, line.length, y)
1861
        ELSIF (selBeg.Y # n) & (selEnd.Y = n) THEN
1862
            drawSelect(text, line, 0, selEnd.X, y)
1863
        END;
1864
        NextLine(line);
1865
        INC(y, charHeight);
1866
        INC(n);
1867
        INC(cnt)
1868
    END;
1869
    IF text.numbers THEN
1870
        G.SetColor(canvas, colors.numback);
1871
        G.FillRect(canvas, 0, 0, padding.left - pad_left (*+ 1*), size.Y - 1);
1872
        SetColor(colors.numtext, colors.numback);
1873
        y := padding.top + inter DIV 2;
1874
        n := MIN(text.scroll.Y + textsize.Y + 1, text.count);
1875
        FOR i := text.scroll.Y + 1 TO n DO
1876
            IF (i MOD 10 = 0) OR (i - 1 = text.cursor.Y) THEN
1877
                U.int2str(i, s);
1878
                G.TextOut2(canvas, (numWidth - U.lg10(i) - 1)*wNum - wNum DIV 2, y, s, LENGTH(s));
1879
            ELSIF i MOD 5 = 0 THEN
1880
                G.SetColor(canvas, colors.numtext);
1881
                G.HLine(canvas, y - inter DIV 2 + charHeight DIV 2, xNum - wNum, xNum)
1882
            ELSE
1883
                G.SetColor(canvas, colors.numtext);
1884
                G.HLine(canvas, y - inter DIV 2 + charHeight DIV 2, xNum - wNum DIV 2, xNum)
1885
            END;
1886
            INC(y, charHeight)
1887
        END
1888
    END;
1889
 
1890
    IF text.searchText # "" THEN
1891
        cnt := 0;
1892
        line := firstLine;
1893
        lastLine := line;
1894
        WHILE (line # NIL) & (cnt <= textsize.Y) DO
1895
            lastLine := line;
1896
            NextLine(line);
1897
            INC(cnt)
1898
        END;
1899
        p := text.foundList.first(Search.tPos);
1900
        WHILE p # NIL DO
1901
            y := padding.top + inter DIV 2;
1902
            IF (firstLine.pos <= p.pos) & (p.pos <= lastLine.pos + lastLine.length) THEN
1903
                line := firstLine;
1904
                WHILE (line.pos <= p.pos) & (line # lastLine) DO
1905
                    NextLine(line);
1906
                    INC(y, charHeight)
1907
                END;
1908
                IF (line # lastLine) & (line # firstLine) OR (line = lastLine) & (line.pos > p.pos) THEN
1909
                    PrevLine(line);
1910
                    DEC(y, charHeight)
1911
                END;
1912
                x := (p.pos - line.pos - text.scroll.X)*charWidth + padding.left;
1913
                n := LENGTH(text.searchText)*charWidth;
1914
                WHILE n > 0 DO
1915
                    IF x >= padding.left THEN
1916
                        G.notVLine(canvas, x, y, y + charHeight - inter)
1917
                    END;
1918
                    INC(x);
1919
                    DEC(n)
1920
                END;
1921
            END;
1922
            p := p.next(Search.tPos)
1923
        END
1924
    END;
1925
 
1926
    IF text.foundSel > 0 THEN
1927
        x := (text.cursor.X - text.scroll.X)*charWidth + padding.left;
1928
        y := (text.cursor.Y - text.scroll.Y)*charHeight + padding.top + inter DIV 2;
1929
        n := text.foundSel*charWidth;
1930
        WHILE n > 0 DO
1931
            IF x >= padding.left THEN
1932
                G.xorVLine(canvas, x, y, y + charHeight - inter)
1933
            END;
1934
            INC(x);
1935
            DEC(n)
1936
        END
1937
    END;
1938
 
1939
    IF drawCursor THEN
1940
        cursor(text)
1941
    END;
8762 leency 1942
    G.SetColor(canvas, K.borderColor);
8728 leency 1943
    G.Rect(canvas, 0, 0, size.X - 1, size.Y - 1);
1944
END draw;
1945
 
1946
 
1947
PROCEDURE create (fileName: RW.tFileName): tText;
1948
VAR
1949
    text: tText;
1950
BEGIN
1951
    NEW(text);
1952
    NEW(text.cursor);
1953
    NEW(text.select2);
1954
    text.cursor.X := 0;
1955
    text.cursor.Y := 0;
1956
    resetSelect(text);
1957
    text.scroll.X := 0;
1958
    text.scroll.Y := 0;
1959
    setPadding(padding.left, padding.top);
1960
    text.curLine := NIL;
1961
    text.modified := FALSE;
1962
    text.comments := TRUE;
1963
    text.search := TRUE;
1964
    text.cs := FALSE;
1965
    text.whole := FALSE;
1966
    text.numbers := TRUE;
1967
    text.guard := TRUE;
1968
    text.idxData := NIL;
1969
    text.edition := NIL;
1970
    text.foundList := List.create(NIL);
1971
    text.searchText := "";
1972
    text.foundSel := 0;
1973
    text.CurX := -1;
1974
    setName(text, fileName);
1975
    ASSERT(text = List.create(text))
1976
    RETURN text
1977
END create;
1978
 
1979
 
1980
PROCEDURE setColors* (text, back, seltext, selback, modified, saved, curline, numtext, numback,
8762 leency 1981
                        comment, string, num, delim, key1, key2, key3: INTEGER);
8728 leency 1982
BEGIN
1983
    colors.text := text;
1984
    colors.back := back;
1985
    colors.seltext := seltext;
1986
    colors.selback := selback;
1987
    colors.modified := modified;
1988
    colors.saved := saved;
1989
    colors.curline := curline;
1990
    colors.numtext := numtext;
1991
    colors.numback := numback;
1992
    colors.comment := comment;
1993
    colors.string  := string;
1994
    colors.num := num;
1995
    colors.delim := delim;
1996
    colors.key1 := key1;
1997
    colors.key2 := key2;
1998
    colors.key3 := key3;
1999
END setColors;
2000
 
2001
 
2002
PROCEDURE setCanvas* (Canvas: G.tCanvas);
2003
BEGIN
2004
    canvas := Canvas;
2005
    charWidth := canvas.font.width;
2006
    charHeight := canvas.font.height + inter
2007
END setCanvas;
2008
 
2009
 
2010
PROCEDURE resize* (width, height: INTEGER);
2011
BEGIN
2012
    size.X := width;
2013
    size.Y := height;
2014
    setPadding(padding.left, padding.top)
2015
END resize;
2016
 
2017
 
2018
PROCEDURE destroy* (VAR text: tText);
2019
BEGIN
2020
    IF search(text, "", FALSE, FALSE) THEN END;
2021
    WHILE text.last # NIL DO
2022
        DelLine(text, text.last(tLine))
2023
    END;
2024
    DISPOSE(text.foundList);
2025
    DISPOSE(text.cursor);
2026
    DISPOSE(text.select2);
2027
    DISPOSE(text)
2028
END destroy;
2029
 
2030
 
2031
PROCEDURE open* (name: RW.tFileName; VAR errno: INTEGER): tText;
2032
VAR
2033
    text: tText;
2034
    file: RW.tInput;
2035
    n, enc: INTEGER;
2036
    eol: BOOLEAN;
2037
    line: tLine;
2038
BEGIN
2039
    errno := 0;
2040
    text := NIL;
2041
    file := RW.load(name, enc);
2042
    IF file # NIL THEN
2043
        text := create(name);
2044
        text.enc := enc;
2045
        REPEAT
2046
            line := Lines.create(FALSE);
2047
            n := RW.getString(file, line, eol);
2048
            IF n >= 0 THEN
2049
                List._append(text, line)
2050
            ELSE
2051
                Lines.destroy(line)
2052
            END
2053
        UNTIL n < 0;
2054
        RW.destroy(file);
2055
        IF n = -1 THEN
2056
            IF text.count = 0 THEN
2057
                List._append(text, Lines.create(FALSE))
2058
            END;
2059
            text.curLine := text.first(tLine);
2060
            SetPos(text, 0, 0);
2061
            resetSelect(text)
2062
        END
2063
    ELSE
2064
        errno := 1
2065
    END;
2066
    IF (text # NIL) & (text.lang # Lang.langNone) THEN
2067
        Comments(text)
2068
    END
2069
    RETURN text
2070
END open;
2071
 
2072
 
2073
PROCEDURE findNext* (text: tText; prev: BOOLEAN): BOOLEAN;
2074
VAR
2075
    cursorPos, x, y, X, Y, Len: INTEGER;
2076
    p: Search.tPos;
2077
    line: tLine;
2078
    res: BOOLEAN;
2079
BEGIN
2080
    X := text.cursor.X;
2081
    Y := text.cursor.Y;
2082
    text.cursor.X := MIN(text.cursor.X, text.curLine.length);
2083
    cursorPos := text.curLine.pos + text.cursor.X - ORD(prev) - ORD(~prev & (text.foundSel = 0));
2084
    p := text.foundList.first(Search.tPos);
2085
    WHILE (p # NIL) & (p.pos <= cursorPos) DO
2086
        p := p.next(Search.tPos)
2087
    END;
2088
    IF prev THEN
2089
        IF p = NIL THEN
2090
            p := text.foundList.last(Search.tPos)
2091
        ELSE
2092
            p := p.prev(Search.tPos)
2093
        END
2094
    END;
2095
    res := p # NIL;
2096
    IF res THEN
2097
        y := 0;
2098
        line := text.first(tLine);
2099
        WHILE (line.pos <= p.pos) & (line.next # NIL) DO
2100
            NextLine(line);
2101
            INC(y)
2102
        END;
2103
        IF (line.next # NIL) OR (line.pos > p.pos) THEN
2104
            PrevLine(line);
2105
            DEC(y)
2106
        END;
2107
        resetSelect(text);
2108
        searchScroll(text, y);
2109
        x := p.pos - line.pos;
2110
        Len := LENGTH(text.searchText);
2111
        IF x + Len > text.scroll.X + textsize.X THEN
2112
            text.scroll.X := MAX(x + Len - textsize.X + 3, 0)
2113
        ELSIF x < text.scroll.X THEN
2114
            text.scroll.X := MAX(x - 3, 0)
2115
        END;
2116
        SetPos(text, x, y);
2117
        text.foundSel := Len
2118
    ELSE
2119
        SetPos(text, X, Y)
2120
    END
2121
    RETURN res
2122
END findNext;
2123
 
2124
 
2125
PROCEDURE rewrite (line: tLine; repl: ARRAY OF WCHAR; pos, n: INTEGER);
2126
BEGIN
2127
    IF n > 0 THEN
2128
        Lines.copy(line)
2129
    END;
2130
    WHILE n > 0 DO
2131
        DEC(n);
2132
        Lines.setChar(line, pos + n, repl[n])
2133
    END
2134
END rewrite;
2135
 
2136
 
2137
PROCEDURE replace* (text: tText; s: ARRAY OF WCHAR; n: INTEGER);
2138
VAR
2139
    line: tLine;
2140
    sLen, i: INTEGER;
2141
BEGIN
2142
    IF text.foundSel > 0 THEN
2143
        line := text.curLine;
2144
        sLen := LENGTH(s);
2145
        i := text.cursor.X;
2146
        IF sLen > n THEN
2147
            Lines.insert3(line, i, sLen - n)
2148
        END;
2149
        SetPos(text, i + sLen, text.cursor.Y);
2150
        rewrite(line, s, i, sLen);
2151
        IF n > sLen THEN
2152
            Lines.delCharN(line, text.cursor.X, n - sLen)
2153
        END;
2154
        resetSelect(text);
2155
        Lines.modify(line);
2156
        modify(text)
2157
    END
2158
END replace;
2159
 
2160
 
2161
PROCEDURE replaceAll* (text: tText; s: ARRAY OF WCHAR; n: INTEGER): INTEGER;
2162
VAR
2163
    p: Search.tPos;
2164
    line: tLine;
2165
    y, k, d, pos, y0: INTEGER;
2166
BEGIN
2167
    resetSelect(text);
2168
    SetPos(text, 0, 0);
2169
    line := text.first(tLine);
2170
    y := 0;
2171
    y0 := -1;
2172
    k := 0;
2173
    d := LENGTH(s) - n;
2174
    p := text.foundList.first(Search.tPos);
2175
    WHILE p # NIL DO
2176
        pos := p.pos;
2177
        WHILE (line.pos <= pos) & (line.next # NIL) DO
2178
            NextLine(line);
2179
            INC(y)
2180
        END;
2181
        IF (line.next # NIL) OR (line.pos > pos) THEN
2182
            PrevLine(line);
2183
            DEC(y)
2184
        END;
2185
        IF y = y0 THEN
2186
            INC(k, d)
2187
        ELSE
2188
            k := 0;
2189
            y0 := y
2190
        END;
2191
        SetPos(text, pos - line.pos + k, y);
2192
        text.foundSel := n;
2193
        replace(text, s, n);
2194
        p := p.next(Search.tPos)
2195
    END
2196
    RETURN text.foundList.count
2197
END replaceAll;
2198
 
2199
 
2200
PROCEDURE New* (): tText;
2201
VAR
2202
    text: tText;
2203
BEGIN
2204
    text := create("");
2205
    List._append(text, Lines.create(FALSE));
2206
    text.curLine := text.first(tLine);
2207
    text.enc := E.CP866;
2208
    SetPos(text, 0, 0);
2209
    resetSelect(text)
2210
    RETURN text
2211
END New;
2212
 
2213
 
2214
PROCEDURE empty;
2215
END empty;
2216
 
2217
 
2218
PROCEDURE init* (pShowCursor: tProcedure);
2219
BEGIN
2220
    ShowCursor := empty;
2221
    IF pShowCursor # NIL THEN
2222
        ShowCursor := pShowCursor
2223
    END;
2224
    pdelete := delete;
2225
    drawCursor := TRUE;
2226
    padding.left := pad_left;
2227
    padding.top := pad_top;
2228
END init;
2229
 
2230
 
2231
END Text.