Subversion Repositories Kolibri OS

Rev

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