Subversion Repositories Kolibri OS

Rev

Rev 9060 | Rev 9174 | 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,
9073 leency 30
    ChangeLog, File,
8728 leency 31
    Lang := Languages;
32
 
33
 
34
CONST
35
 
36
    SPACE = 20X;
37
    TAB = RW.TAB_SIZE;
38
    lenEOL = CB.lenEOL;
39
 
40
    mark_width = 2;
41
    pad_left = mark_width + 3;
9060 leency 42
    pad_top = 0;
8728 leency 43
    inter = 2;
44
 
45
 
46
TYPE
47
 
48
    tPoint = RECORD
49
        X, Y: INTEGER
50
    END;
51
 
52
    pPoint = POINTER TO tPoint;
53
 
54
    tString* = ARRAY 1000 OF WCHAR;
55
 
56
    tLine = Lines.tLine;
57
 
58
    tGuard = POINTER TO RECORD (ChangeLog.tGuard)
59
        selected: BOOLEAN;
60
        cursor, select2, scroll: tPoint;
61
        CurX: INTEGER
62
    END;
63
 
64
    tText* = POINTER TO RECORD (List.tList)
65
        cursor, select, select2: pPoint;
66
        scroll: tPoint;
67
        CurX: INTEGER;
68
        modified*: BOOLEAN;
69
 
70
        edition*: tGuard;
71
        comments, numbers*, guard,
72
        search, cs, whole: BOOLEAN;
73
        curLine: tLine;
74
        fileName*: RW.tFileName;
75
        lang*: INTEGER;
76
        enc*: INTEGER;
77
        table: Search.IdxTable;
78
        foundList: List.tList;
79
        idxData: Search.tBuffer;
80
        foundSel: INTEGER;
9050 leency 81
        searchText: tString;
82
        chLog*: ChangeLog.tLog;
83
        maxLength*: INTEGER
8728 leency 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
9050 leency 396
                ident(text, i, i, y, line, backColor, Lang.isCS(lang))
8728 leency 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
9050 leency 441
                ident(text, i, i - ORD((i > 0) & (getChar(line, i - 1) = "#")), y, line, backColor, Lang.isCS(lang));
8728 leency 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
9050 leency 560
            ident(text, i, i, y, line, backColor, Lang.isCS(lang));
8728 leency 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
9050 leency 648
                ident(text, i, i, y, line, backColor, Lang.isCS(lang));
8728 leency 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
9050 leency 747
                ident(text, i, i, y, line, backColor, Lang.isCS(lang));
8728 leency 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
9050 leency 789
                ident(text, i, i, y, line, backColor, Lang.isCS(lang))
8728 leency 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);
9050 leency 1182
    text.scroll.X := MIN(MAX(text.scroll.X, 0), text.maxLength);
8728 leency 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;
9073 leency 1188
CONST
1189
    tempFile = "/tmp0/1/cedit~.tmp";
8728 leency 1190
VAR
1191
    line: tLine;
1192
    file: RW.tOutput;
1193
    res: BOOLEAN;
1194
    Len: INTEGER;
1195
BEGIN
9073 leency 1196
    ChangeLog.setGuard(text.edition);
8728 leency 1197
    res := TRUE;
9073 leency 1198
    file := RW.create(tempFile, enc, nl);
8728 leency 1199
    IF file # NIL THEN
9073 leency 1200
        ChangeLog.delSaved;
8728 leency 1201
        line := text.first(tLine);
1202
        WHILE (line # NIL) & res DO
1203
            Len := Lines.trimLength(line);
1204
            IF RW.putString(file, line, Len) # Len THEN
1205
                res := FALSE
1206
            END;
1207
            IF line.modified THEN
1208
                Lines.save(line)
1209
            END;
1210
            NextLine(line);
1211
            IF line # NIL THEN
1212
                IF ~RW.newLine(file) THEN
1213
                    res := FALSE
1214
                END
1215
            END
1216
        END;
1217
        IF ~RW.close(file) THEN
1218
            res := FALSE
1219
        END
1220
    ELSE
1221
        res := FALSE
1222
    END;
9073 leency 1223
    IF res THEN
1224
        res := File.Copy(tempFile, name);
1225
        IF res THEN
1226
            text.modified := FALSE;
1227
            ChangeLog.save(text.edition);
1228
            IF File.Delete(tempFile) THEN END
1229
        END
1230
    END;
1231
    IF ~res THEN
1232
        ChangeLog.delCurSaved
1233
    END
8728 leency 1234
    RETURN res
1235
END save;
1236
 
1237
 
1238
PROCEDURE redoGuard (text: tText; guard: tGuard);
1239
BEGIN
1240
    text.edition := guard;
1241
    text.cursor^ := guard.cursor;
1242
    text.select2^ := guard.select2;
1243
    text.scroll := guard.scroll;
1244
    text.CurX := guard.CurX;
1245
    IF guard.selected THEN
1246
        text.select := text.select2
1247
    ELSE
1248
        text.select := text.cursor
1249
    END;
1250
    text.curLine := getLine(text, text.cursor.Y);
1251
    text.comments := TRUE;
1252
    text.search := TRUE
1253
END redoGuard;
1254
 
1255
 
1256
PROCEDURE undo* (text: tText);
1257
VAR
1258
    item: List.tItem;
1259
    guard: tGuard;
1260
BEGIN
1261
    guard := text.edition;
1262
    item := guard.prev;
1263
    WHILE (item # NIL) & ~(item IS tGuard) DO
1264
        item := item.prev
1265
    END;
1266
 
1267
    IF item # NIL THEN
1268
        guard := item(tGuard);
9073 leency 1269
        text.edition := guard
8728 leency 1270
    END;
1271
 
9050 leency 1272
    item := ChangeLog.CL.Log.first;
8728 leency 1273
    WHILE item # guard DO
1274
        ChangeLog.redo(item);
1275
        item := item.next
1276
    END;
1277
    redoGuard(text, guard);
9073 leency 1278
    ChangeLog.setGuard(guard);
1279
    text.modified := ~guard.saved
8728 leency 1280
END undo;
1281
 
1282
 
1283
PROCEDURE redo* (text: tText);
1284
VAR
1285
    item: List.tItem;
1286
    guard: tGuard;
1287
BEGIN
1288
    guard := text.edition;
1289
    item := guard.next;
1290
    WHILE (item # NIL) & ~(item IS tGuard) DO
1291
        ChangeLog.redo(item);
1292
        item := item.next
1293
    END;
1294
    IF item # NIL THEN
1295
        guard := item(tGuard);
1296
        redoGuard(text, guard)
1297
    END;
9073 leency 1298
    ChangeLog.setGuard(guard);
1299
    text.modified := ~guard.saved
8728 leency 1300
END redo;
1301
 
1302
 
1303
PROCEDURE copy (text: tText);
1304
VAR
1305
    selBeg, selEnd: tPoint;
1306
    first, line: tLine;
1307
    cnt, n: INTEGER;
1308
    buffer: CB.tBuffer;
1309
 
1310
 
1311
    PROCEDURE append (buffer: CB.tBuffer; line: tLine; first, last: INTEGER);
1312
    BEGIN
1313
        IF first <= last THEN
1314
            CB.append(buffer, line, first, last)
1315
        ELSE
1316
            IF U.OS = "KOS" THEN
1317
                CB.appends(buffer, SPACE, 0, 0)
1318
            END
1319
        END
1320
    END append;
1321
 
1322
 
1323
BEGIN
1324
    getSelect(text, selBeg, selEnd);
1325
 
1326
    first := getLine(text, selBeg.Y);
1327
    line := first;
1328
 
1329
    n := selEnd.Y - selBeg.Y;
1330
    cnt := 0;
1331
    WHILE n >= 0 DO
1332
        INC(cnt, line.length + lenEOL);
1333
        NextLine(line);
1334
        DEC(n)
1335
    END;
1336
 
1337
    buffer := CB.create(cnt);
1338
 
1339
    n := selEnd.Y - selBeg.Y;
1340
    line := first;
1341
    IF n = 0 THEN
1342
        CB.append(buffer, line, selBeg.X, selEnd.X - 1)
1343
    ELSE
1344
        append(buffer, line, selBeg.X, line.length - 1);
1345
        REPEAT
1346
            DEC(n);
1347
            CB.eol(buffer);
1348
            NextLine(line);
1349
            IF n > 0 THEN
1350
                append(buffer, line, 0, line.length - 1)
1351
            END
1352
        UNTIL n = 0;
1353
        append(buffer, line, 0, selEnd.X - 1)
1354
    END;
1355
    CB.eot(buffer);
1356
    CB.put(buffer);
1357
    CB.destroy(buffer)
1358
END copy;
1359
 
1360
 
1361
PROCEDURE paste (text: tText);
1362
VAR
1363
    line, newLine, curLine: tLine;
1364
    L: INTEGER;
1365
    cliptext: RW.tInput;
1366
    eol: BOOLEAN;
1367
    cursor: pPoint;
1368
BEGIN
1369
    line := Lines.create(TRUE);
1370
    cliptext := RW.clipboard();
1371
    delSelect(text);
1372
    cursor := text.cursor;
1373
    WHILE (cliptext # NIL) & (RW.getString(cliptext, line, eol) >= 0) DO
1374
        L := line.length;
1375
        IF L > 0 THEN
1376
            Lines.insert2(text.curLine, cursor.X, line);
1377
            Lines.modify(text.curLine);
1378
            modify(text);
1379
            SetPos(text, cursor.X + L, cursor.Y);
1380
            resetSelect(text)
1381
        END;
1382
        IF eol THEN
1383
            newLine := Lines.create(FALSE);
1384
            Lines.modify(newLine);
1385
            modify(text);
1386
            curLine := text.curLine;
1387
            IF cursor.X < curLine.length THEN
1388
                Lines.modify(curLine);
1389
                Lines.wrap(curLine, newLine, cursor.X)
1390
            END;
1391
            List._insert(text, curLine, newLine);
1392
            SetPos(text, 0, cursor.Y + 1);
1393
            resetSelect(text)
1394
        END;
1395
        Lines.destroy(line);
1396
        line := Lines.create(TRUE)
1397
    END;
1398
    Lines.destroy(line);
1399
    RW.destroy(cliptext)
1400
END paste;
1401
 
1402
 
1403
PROCEDURE searchScroll (text: tText; n: INTEGER);
1404
BEGIN
1405
    IF n - text.scroll.Y > textsize.Y - 1 THEN
1406
        text.scroll.Y := MAX(n - 2 * textsize.Y DIV 3, 0)
1407
    ELSIF n < text.scroll.Y THEN
1408
        text.scroll.Y := MAX(n - textsize.Y DIV 3, 0)
1409
    END
1410
END searchScroll;
1411
 
1412
 
1413
PROCEDURE goto* (text: tText; n: INTEGER): BOOLEAN;
1414
VAR
1415
    res: BOOLEAN;
1416
BEGIN
1417
    DEC(n);
1418
    IF (0 <= n) & (n < text.count) THEN
1419
        resetSelect(text);
1420
        searchScroll(text, n);
1421
        SetPos(text, 0, n);
1422
        res := TRUE
1423
    ELSE
1424
        res := FALSE
1425
    END
1426
    RETURN res
1427
END goto;
1428
 
1429
 
9060 leency 1430
PROCEDURE toggleLabel* (text: tText);
1431
BEGIN
1432
    text.curLine.label := ~text.curLine.label
1433
END toggleLabel;
1434
 
1435
 
1436
PROCEDURE gotoLabel* (text: tText; frw: BOOLEAN);
1437
VAR
1438
    line: tLine;
1439
    n: INTEGER;
9073 leency 1440
 
1441
    PROCEDURE search (VAR line: tLine; VAR n: INTEGER; frw: BOOLEAN);
1442
    BEGIN
1443
        IF frw THEN
1444
            WHILE (line # NIL) & ~line.label DO
1445
                NextLine(line);
1446
                INC(n)
1447
            END
1448
        ELSE
1449
            WHILE (line # NIL) & ~line.label DO
1450
                PrevLine(line);
1451
                DEC(n)
1452
            END
1453
        END
1454
    END search;
1455
 
9060 leency 1456
BEGIN
1457
    n := text.cursor.Y;
1458
    line := text.curLine;
1459
    IF frw THEN
9073 leency 1460
        NextLine(line);
1461
        INC(n)
9060 leency 1462
    ELSE
9073 leency 1463
        PrevLine(line);
1464
        DEC(n)
9060 leency 1465
    END;
9073 leency 1466
    search(line, n, frw);
1467
    IF line = NIL THEN
1468
        IF frw THEN
1469
            n := 0;
1470
            line := text.first(tLine)
1471
        ELSE
1472
            n := text.count - 1;
1473
            line := text.last(tLine)
1474
        END;
1475
        search(line, n, frw)
1476
    END;
9060 leency 1477
    IF line # NIL THEN
1478
        IF goto(text, n + 1) THEN END
1479
    END
1480
END gotoLabel;
1481
 
1482
 
8728 leency 1483
PROCEDURE changeCase (text: tText; upper: BOOLEAN);
1484
VAR
1485
    i: INTEGER;
1486
    line: tLine;
1487
BEGIN
1488
    line := text.curLine;
1489
    i := text.cursor.X - 1;
1490
 
1491
    WHILE (i >= 0) & U.isLetter(getChar(line, i)) DO
1492
        DEC(i)
1493
    END;
1494
 
1495
    IF Lines.chCase(line, i + 1, text.cursor.X - 1, upper) THEN
1496
        modify(text)
1497
    END
1498
END changeCase;
1499
 
1500
 
1501
PROCEDURE chCase* (text: tText; upper: BOOLEAN);
1502
VAR
1503
    selBeg, selEnd: tPoint;
1504
    first, line: Lines.tLine;
1505
    cnt: INTEGER;
1506
    modified: BOOLEAN;
1507
BEGIN
1508
    modified := FALSE;
1509
    IF selected(text) THEN
1510
        getSelect(text, selBeg, selEnd);
1511
        first := getLine(text, selBeg.Y);
1512
        line := first;
1513
        cnt := selEnd.Y - selBeg.Y;
1514
        IF cnt = 0 THEN
1515
            IF Lines.chCase(line, selBeg.X, selEnd.X - 1, upper) THEN
1516
                modified := TRUE
1517
            END
1518
        ELSE
1519
            IF Lines.chCase(line, selBeg.X, line.length - 1, upper) THEN
1520
                modified := TRUE
1521
            END;
1522
            WHILE cnt > 1 DO
1523
                NextLine(line);
1524
                IF Lines.chCase(line, 0, line.length - 1, upper) THEN
1525
                    modified := TRUE
1526
                END;
1527
                DEC(cnt)
1528
            END;
1529
            NextLine(line);
1530
            IF Lines.chCase(line, 0, selEnd.X - 1, upper) THEN
1531
                modified := TRUE
1532
            END
1533
        END
1534
    END;
1535
    IF modified THEN
1536
        modify(text)
1537
    END
1538
END chCase;
1539
 
1540
 
1541
PROCEDURE UpDown (text: tText; step: INTEGER);
1542
VAR
1543
    temp: INTEGER;
1544
BEGIN
1545
    IF text.CurX = -1 THEN
1546
        text.CurX := text.cursor.X
1547
    END;
1548
    temp := text.CurX;
1549
    SetPos(text, temp, text.cursor.Y + step);
1550
    text.CurX := temp
1551
END UpDown;
1552
 
1553
 
1554
PROCEDURE delLine* (text: tText);
1555
BEGIN
1556
    resetSelect(text);
1557
    IF text.curLine.length > 0 THEN
1558
        Lines.delCharN(text.curLine, 0, text.curLine.length)
1559
    END;
1560
    SetPos(text, 0, text.cursor.Y);
1561
    IF text.cursor.Y = text.count - 1 THEN
1562
        BkSpace(text)
1563
    ELSE
1564
        delete(text)
1565
    END
1566
END delLine;
1567
 
1568
 
9010 leency 1569
PROCEDURE dupLine (text: tText);
1570
VAR
1571
    newLine, curLine: tLine;
1572
BEGIN
1573
    curLine := text.curLine;
1574
    newLine := Lines.create(FALSE);
1575
    Lines.modify(newLine);
1576
    modify(text);
1577
    Lines.insert3(newLine, 0, curLine.length);
1578
    List._insert(text, curLine, newLine);
1579
    Lines.move(curLine, newLine)
1580
END dupLine;
1581
 
1582
 
1583
PROCEDURE exchange (text: tText; first, second: tLine);
1584
BEGIN
1585
    List._exchange(text, first, second);
1586
    Lines.modify(text.curLine);
1587
    modify(text);
1588
    UpDown(text, 0)
1589
END exchange;
1590
 
1591
 
1592
PROCEDURE upLine (text: tText);
1593
BEGIN
1594
    IF text.cursor.Y > 0 THEN
1595
        DEC(text.cursor.Y);
1596
        exchange(text, text.curLine.prev(tLine), text.curLine)
1597
    END
1598
END upLine;
1599
 
1600
 
1601
PROCEDURE downLine (text: tText);
1602
BEGIN
1603
    IF text.cursor.Y < text.count - 1 THEN
1604
        INC(text.cursor.Y);
1605
        exchange(text, text.curLine, text.curLine.next(tLine))
1606
    END
1607
END downLine;
1608
 
1609
 
1610
PROCEDURE isWordChar (c: WCHAR): BOOLEAN;
1611
    RETURN U.isLetter(c) OR U.isDigit(c) OR (c = "_")
1612
END isWordChar;
1613
 
1614
 
1615
PROCEDURE wordSel* (text: tText);
1616
VAR
1617
    n, i, x1, x2: INTEGER;
1618
    selBeg, selEnd: tPoint;
1619
    str: tString;
1620
    curLine: tLine;
1621
BEGIN
1622
    curLine := text.curLine;
1623
    IF selected(text) & (text.cursor.Y = text.select.Y) THEN
1624
        getSelect(text, selBeg, selEnd);
1625
        x1 := selBeg.X;
1626
        x2 := selEnd.X;
1627
        n := getString(curLine, x1, x2 - x1, str);
1628
    ELSE
1629
        str := ""
1630
    END;
1631
    IF str # "" THEN
1632
        i := 0;
1633
        WHILE (i < n) & isWordChar(str[i]) DO
1634
            INC(i)
1635
        END;
1636
        IF (i # n) OR
1637
            ((x1 > 0) & isWordChar(getChar(curLine, x1 - 1))) OR
1638
            ((x2 < curLine.length) & isWordChar(getChar(curLine, x2))) THEN
1639
            str := ""
1640
        END
1641
    END;
9050 leency 1642
    IF search(text, str, Lang.isCS(text.lang), TRUE) THEN END
9010 leency 1643
END wordSel;
1644
 
1645
 
9073 leency 1646
PROCEDURE key* (text: tText; code: INTEGER; shift, ctrl: BOOLEAN);
8728 leency 1647
BEGIN
9073 leency 1648
    IF shift THEN
8728 leency 1649
        setSelect(text)
1650
    ELSE
1651
        IF (33 <= code) & (code <= 40) THEN
1652
            resetSelect(text)
1653
        END
1654
    END;
1655
 
1656
    CASE code OF
1657
    |33:
9073 leency 1658
        IF ctrl THEN
8728 leency 1659
            UpDown(text, text.scroll.Y - text.cursor.Y)
1660
        ELSE
1661
            text.scroll.Y := MAX(text.scroll.Y - textsize.Y, 0);
1662
            UpDown(text, -textsize.Y)
1663
        END
1664
    |34:
9073 leency 1665
        IF ctrl THEN
8728 leency 1666
            UpDown(text, MIN(text.scroll.Y + textsize.Y - 1, text.count - 1) - text.cursor.Y)
1667
        ELSE
1668
            text.scroll.Y := MIN(text.scroll.Y + textsize.Y, text.count - 1);
1669
            UpDown(text, textsize.Y)
1670
        END
1671
    |35:
9073 leency 1672
        IF ctrl THEN
8728 leency 1673
            SetPos(text, text.last(tLine).length, text.count - 1)
1674
        ELSE
1675
            SetPos(text, text.curLine.length, text.cursor.Y)
1676
        END
1677
    |36:
9073 leency 1678
        IF ctrl THEN
8728 leency 1679
            SetPos(text, 0, 0)
1680
        ELSE
1681
            SetPos(text, 0, text.cursor.Y)
1682
        END
1683
    |37:
1684
        IF (text.cursor.X = 0) & (text.curLine.prev # NIL) THEN
1685
            SetPos(text, text.curLine.prev(tLine).length, text.cursor.Y - 1)
1686
        ELSE
1687
            SetPos(text, text.cursor.X - 1, text.cursor.Y)
1688
        END
1689
    |38:
9073 leency 1690
        IF ctrl THEN
9010 leency 1691
            upLine(text)
1692
        ELSE
1693
            UpDown(text, -1)
1694
        END
8728 leency 1695
    |39:
1696
        IF (text.cursor.X = text.curLine.length) & (text.curLine.next # NIL) THEN
1697
            SetPos(text, 0, text.cursor.Y + 1)
1698
        ELSE
1699
            SetPos(text, text.cursor.X + 1, text.cursor.Y)
1700
        END
1701
    |40:
9073 leency 1702
        IF ctrl THEN
9010 leency 1703
            downLine(text)
1704
        ELSE
1705
            UpDown(text, 1)
1706
        END
1707
    |46:
9073 leency 1708
        IF ctrl THEN
9010 leency 1709
            delLine(text)
1710
        ELSE
1711
            delete(text); ShowCursor; drawCursor := TRUE
1712
        END
8728 leency 1713
    |ORD("C"):
9073 leency 1714
        IF ctrl THEN
8728 leency 1715
            IF selected(text) THEN
1716
                copy(text)
1717
            END
1718
        END
1719
    |ORD("X"):
9073 leency 1720
        IF ctrl THEN
8728 leency 1721
            IF selected(text) THEN
1722
                copy(text);
1723
                delSelect(text)
1724
            END
1725
        END
1726
    |ORD("V"):
9073 leency 1727
        IF ctrl THEN
8728 leency 1728
            IF CB.available() THEN
1729
                paste(text)
1730
            END
1731
        END
1732
    |ORD("A"):
9073 leency 1733
        IF ctrl THEN
8728 leency 1734
            text.select2.X := 0;
1735
            text.select2.Y := 0;
1736
            text.select := text.select2;
1737
            SetPos(text, text.last(tLine).length, text.count - 1)
1738
        END
1739
    |ORD("L"), ORD("U"):
9073 leency 1740
        IF ctrl THEN
8728 leency 1741
            changeCase(text, code = ORD("U"))
1742
        END
9010 leency 1743
    |ORD("D"):
9073 leency 1744
        IF ctrl THEN
9010 leency 1745
            dupLine(text)
1746
        END
8728 leency 1747
    ELSE
1748
    END
1749
END key;
1750
 
1751
 
1752
PROCEDURE mouse* (text: tText; x, y: INTEGER);
1753
VAR
1754
    cursorX: INTEGER;
1755
BEGIN
1756
    DEC(x, padding.left);
1757
    DEC(y, padding.top);
1758
    cursorX := (x*2) DIV charWidth;
1759
    SetPos(text, cursorX DIV 2 + cursorX MOD 2 + text.scroll.X, y DIV charHeight + text.scroll.Y)
1760
END mouse;
1761
 
1762
 
1763
PROCEDURE selectWord* (text: tText);
1764
VAR
1765
    cursorX, x1, x2: INTEGER;
1766
    line: tLine;
1767
BEGIN
1768
    resetSelect(text);
1769
    cursorX := text.cursor.X;
1770
    line := text.curLine;
1771
    x1 := cursorX - 1;
1772
    IF (cursorX < line.length) & isWordChar(getChar(line,cursorX)) THEN
1773
        x2 := cursorX;
1774
        WHILE (x2 < line.length) & isWordChar(getChar(line, x2)) DO
1775
            INC(x2)
1776
        END
1777
    ELSE
1778
        WHILE (x1 >= 0) & ~isWordChar(getChar(line, x1)) DO
1779
            DEC(x1)
1780
        END;
1781
        x2 := x1 + 1
1782
    END;
1783
    WHILE (x1 >= 0) & isWordChar(getChar(line, x1)) DO
1784
        DEC(x1)
1785
    END;
1786
    INC(x1);
1787
    IF x1 < x2 THEN
1788
        SetPos(text, x1, text.cursor.Y);
1789
        setSelect(text);
1790
        SetPos(text, x2, text.cursor.Y)
1791
    END
1792
END selectWord;
1793
 
1794
 
1795
PROCEDURE cursor (text: tText);
1796
VAR
1797
    x, y, h: INTEGER;
1798
    cursor: pPoint;
1799
BEGIN
1800
    cursor := text.cursor;
1801
    IF ~((text.scroll.Y > cursor.Y) OR (text.scroll.Y + textsize.Y <= cursor.Y) OR
1802
       (text.scroll.X > cursor.X) OR (text.scroll.X + textsize.X <= cursor.X)) THEN
1803
        x := (cursor.X - text.scroll.X)*charWidth + padding.left;
1804
        y := (cursor.Y - text.scroll.Y)*charHeight + 1 + padding.top;
1805
        h := charHeight - 2;
1806
        G.notVLine(canvas, x, y + inter DIV 2, y + h - inter DIV 2);
1807
        G.notVLine(canvas, x - 1, y + inter DIV 2, y + h - inter DIV 2)
1808
    END
1809
END cursor;
1810
 
1811
 
1812
PROCEDURE drawSelect (text: tText; line: tLine; selBeg, selEnd, y: INTEGER);
1813
VAR
1814
    Len, pos, x, firstCharIdx: INTEGER;
1815
BEGIN
1816
    firstCharIdx := MAX(text.scroll.X, selBeg);
1817
    Len := MAX(MIN(line.length - firstCharIdx, selEnd - firstCharIdx), 0);
1818
    Len := MIN(Len, textsize.X - pos + 1);
1819
    SetColor(colors.seltext, colors.selback);
1820
    pos := MAX((selBeg - text.scroll.X), 0);
1821
    x := pos*charWidth + padding.left;
1822
    G.SetColor(canvas, colors.selback);
1823
    G.FillRect(canvas, x - 2, y - inter DIV 2, x + 1 + Len*charWidth, y - inter DIV 2 + charHeight);
1824
    G.TextOut(canvas, pos*charWidth + padding.left, y, Lines.getPChar(line, firstCharIdx), Len)
1825
END drawSelect;
1826
 
1827
 
1828
PROCEDURE mark (line: tLine; y: INTEGER);
1829
VAR
1830
    color, i: INTEGER;
1831
BEGIN
1832
    IF line.modified THEN
1833
        color := colors.modified
1834
    ELSIF line.saved THEN
1835
        color := colors.saved
1836
    ELSE
1837
        color := colors.back
1838
    END;
1839
    G.SetColor(canvas, color);
1840
 
1841
    FOR i := 3 TO mark_width + 2 DO
1842
        G.VLine(canvas, padding.left - i, y, y + charHeight)
1843
    END
1844
END mark;
1845
 
1846
 
1847
PROCEDURE setPadding (left, top: INTEGER);
1848
BEGIN
1849
    padding.left := left;
1850
    padding.top := top;
1851
    textsize.X := (size.X - padding.left) DIV charWidth;
1852
    textsize.Y := (size.Y - padding.top) DIV charHeight;
1853
END setPadding;
1854
 
1855
 
1856
PROCEDURE draw* (text: tText);
1857
VAR
1858
    y, n, Len, cnt, i, x: INTEGER;
1859
    line, firstLine, lastLine: tLine;
1860
    selBeg, selEnd: tPoint;
1861
    s: ARRAY 12 OF WCHAR;
1862
    backColor, numWidth, xNum, wNum: INTEGER;
1863
    p: Search.tPos;
1864
    guard: tGuard;
1865
BEGIN
1866
    IF text.search & search(text, text.searchText, text.cs, text.whole) THEN END;
1867
    IF (text.lang # Lang.langNone) & text.comments THEN
1868
        Comments(text)
1869
    END;
1870
    IF text.guard THEN
1871
        NEW(guard);
9050 leency 1872
        List.append(ChangeLog.CL.Log, guard);
9073 leency 1873
        guard.saved := ChangeLog.isFirstGuard(guard);
8728 leency 1874
        text.edition := guard;
9073 leency 1875
        text.guard := FALSE
8728 leency 1876
    ELSE
1877
        guard := text.edition
1878
    END;
1879
 
1880
    guard.cursor := text.cursor^;
1881
    guard.select2 := text.select2^;
1882
    guard.scroll := text.scroll;
1883
    guard.CurX := text.CurX;
1884
    guard.selected := text.select = text.select2;
1885
 
1886
    G.SetColor(canvas, colors.back);
1887
    G.clear(canvas);
9060 leency 1888
    wNum := charWidth;
8728 leency 1889
    IF text.numbers THEN
1890
        numWidth := U.lg10(text.count) + 2;
1891
        xNum := numWidth*wNum - wNum DIV 2;
1892
        setPadding(numWidth*wNum + pad_left, padding.top);
1893
    ELSE
9060 leency 1894
        setPadding(pad_left + wNum*2, padding.top)
8728 leency 1895
    END;
1896
    getSelect(text, selBeg, selEnd);
1897
    y := padding.top + inter DIV 2;
1898
    n := text.scroll.Y;
1899
    line := getLine(text, n);
1900
    firstLine := line;
1901
    cnt := 0;
1902
    WHILE (line # NIL) & (cnt <= textsize.Y) DO
1903
        backColor := colors.back;
1904
        IF (line = text.curLine) & ~selected(text) THEN
1905
            G.SetColor(canvas, colors.curline);
1906
            G.FillRect(canvas, padding.left - 2, y - inter DIV 2, size.X - 1, y - inter DIV 2 + charHeight);
1907
            backColor := colors.curline
1908
        END;
1909
        SetColor(colors.text, backColor);
1910
        Len := MAX(line.length - text.scroll.X, 0);
1911
        G.TextOut(canvas, padding.left, y, Lines.getPChar(line, text.scroll.X), MIN(Len, textsize.X + 1));
1912
        IF text.lang # Lang.langNone THEN
1913
            parse(text, line, y, backColor, text.lang)
1914
        END;
1915
        mark(line, y - inter DIV 2);
1916
        IF (selBeg.Y < n) & (n < selEnd.Y) THEN
1917
            drawSelect(text, line, 0, line.length, y)
1918
        ELSIF (selBeg.Y = n) & (selEnd.Y = n) & (selBeg.X # selEnd.X) THEN
1919
            drawSelect(text, line, selBeg.X, selEnd.X, y)
1920
        ELSIF (selBeg.Y = n) & (selEnd.Y # n) THEN
1921
            drawSelect(text, line, selBeg.X, line.length, y)
1922
        ELSIF (selBeg.Y # n) & (selEnd.Y = n) THEN
1923
            drawSelect(text, line, 0, selEnd.X, y)
1924
        END;
1925
        NextLine(line);
1926
        INC(y, charHeight);
1927
        INC(n);
1928
        INC(cnt)
1929
    END;
9060 leency 1930
    G.SetColor(canvas, colors.numback);
1931
    G.FillRect(canvas, 0, 0, padding.left - pad_left (*+ 1*), size.Y - 1);
1932
    line := firstLine;
1933
    SetColor(colors.numtext, colors.numback);
1934
    y := padding.top + inter DIV 2;
1935
    n := MIN(text.scroll.Y + textsize.Y + 1, text.count);
1936
    FOR i := text.scroll.Y + 1 TO n DO
1937
        IF text.numbers THEN
1938
            IF (i MOD 10 = 0) OR (i - 1 = text.cursor.Y) OR line.label THEN
8728 leency 1939
                U.int2str(i, s);
9060 leency 1940
                G.TextOut2(canvas, (numWidth - U.lg10(i) - 1)*wNum - wNum DIV 2, y, s, LENGTH(s))
8728 leency 1941
            ELSIF i MOD 5 = 0 THEN
1942
                G.SetColor(canvas, colors.numtext);
1943
                G.HLine(canvas, y - inter DIV 2 + charHeight DIV 2, xNum - wNum, xNum)
1944
            ELSE
1945
                G.SetColor(canvas, colors.numtext);
1946
                G.HLine(canvas, y - inter DIV 2 + charHeight DIV 2, xNum - wNum DIV 2, xNum)
9060 leency 1947
            END
1948
        END;
1949
        IF line.label THEN
1950
            FOR x := wNum DIV 2 TO (padding.left - pad_left) - wNum DIV 2 DO
1951
                G.notVLine(canvas, x, y, y + charHeight - inter);
1952
                G.xorVLine(canvas, x, y, y + charHeight - inter)
1953
            END
1954
        END;
1955
        NextLine(line);
1956
        INC(y, charHeight)
8728 leency 1957
    END;
1958
 
1959
    IF text.searchText # "" THEN
1960
        cnt := 0;
1961
        line := firstLine;
1962
        lastLine := line;
1963
        WHILE (line # NIL) & (cnt <= textsize.Y) DO
1964
            lastLine := line;
1965
            NextLine(line);
1966
            INC(cnt)
1967
        END;
1968
        p := text.foundList.first(Search.tPos);
1969
        WHILE p # NIL DO
1970
            y := padding.top + inter DIV 2;
1971
            IF (firstLine.pos <= p.pos) & (p.pos <= lastLine.pos + lastLine.length) THEN
1972
                line := firstLine;
1973
                WHILE (line.pos <= p.pos) & (line # lastLine) DO
1974
                    NextLine(line);
1975
                    INC(y, charHeight)
1976
                END;
1977
                IF (line # lastLine) & (line # firstLine) OR (line = lastLine) & (line.pos > p.pos) THEN
1978
                    PrevLine(line);
1979
                    DEC(y, charHeight)
1980
                END;
1981
                x := (p.pos - line.pos - text.scroll.X)*charWidth + padding.left;
1982
                n := LENGTH(text.searchText)*charWidth;
1983
                WHILE n > 0 DO
1984
                    IF x >= padding.left THEN
1985
                        G.notVLine(canvas, x, y, y + charHeight - inter)
1986
                    END;
1987
                    INC(x);
1988
                    DEC(n)
1989
                END;
1990
            END;
1991
            p := p.next(Search.tPos)
1992
        END
1993
    END;
1994
 
1995
    IF text.foundSel > 0 THEN
1996
        x := (text.cursor.X - text.scroll.X)*charWidth + padding.left;
1997
        y := (text.cursor.Y - text.scroll.Y)*charHeight + padding.top + inter DIV 2;
1998
        n := text.foundSel*charWidth;
1999
        WHILE n > 0 DO
2000
            IF x >= padding.left THEN
2001
                G.xorVLine(canvas, x, y, y + charHeight - inter)
2002
            END;
2003
            INC(x);
2004
            DEC(n)
2005
        END
2006
    END;
2007
 
2008
    IF drawCursor THEN
2009
        cursor(text)
2010
    END;
8762 leency 2011
    G.SetColor(canvas, K.borderColor);
9060 leency 2012
    G.HLine(canvas, size.Y - 1, 0, size.X - 1);
2013
    G.VLine(canvas, 0, 0, size.Y - 1);
2014
    G.VLine(canvas, size.X - 1, 0, size.Y - 1)
8728 leency 2015
END draw;
2016
 
2017
 
9050 leency 2018
PROCEDURE switch* (text: tText);
2019
BEGIN
2020
    ChangeLog.set(text.chLog);
2021
    Lines.setMaxLength(text.maxLength)
2022
END switch;
2023
 
2024
 
8728 leency 2025
PROCEDURE create (fileName: RW.tFileName): tText;
2026
VAR
2027
    text: tText;
2028
BEGIN
2029
    NEW(text);
9050 leency 2030
    text.maxLength := 64;
2031
    text.chLog := ChangeLog.create(text.maxLength);
8728 leency 2032
    NEW(text.cursor);
2033
    NEW(text.select2);
2034
    text.cursor.X := 0;
2035
    text.cursor.Y := 0;
2036
    resetSelect(text);
2037
    text.scroll.X := 0;
2038
    text.scroll.Y := 0;
2039
    setPadding(padding.left, padding.top);
2040
    text.curLine := NIL;
2041
    text.modified := FALSE;
2042
    text.comments := TRUE;
2043
    text.search := TRUE;
2044
    text.cs := FALSE;
2045
    text.whole := FALSE;
2046
    text.numbers := TRUE;
2047
    text.guard := TRUE;
2048
    text.idxData := NIL;
2049
    text.edition := NIL;
2050
    text.foundList := List.create(NIL);
2051
    text.searchText := "";
2052
    text.foundSel := 0;
2053
    text.CurX := -1;
2054
    setName(text, fileName);
2055
    ASSERT(text = List.create(text))
2056
    RETURN text
2057
END create;
2058
 
2059
 
2060
PROCEDURE setColors* (text, back, seltext, selback, modified, saved, curline, numtext, numback,
8762 leency 2061
                        comment, string, num, delim, key1, key2, key3: INTEGER);
8728 leency 2062
BEGIN
2063
    colors.text := text;
2064
    colors.back := back;
2065
    colors.seltext := seltext;
2066
    colors.selback := selback;
2067
    colors.modified := modified;
2068
    colors.saved := saved;
2069
    colors.curline := curline;
2070
    colors.numtext := numtext;
2071
    colors.numback := numback;
2072
    colors.comment := comment;
2073
    colors.string  := string;
2074
    colors.num := num;
2075
    colors.delim := delim;
2076
    colors.key1 := key1;
2077
    colors.key2 := key2;
2078
    colors.key3 := key3;
2079
END setColors;
2080
 
2081
 
2082
PROCEDURE setCanvas* (Canvas: G.tCanvas);
2083
BEGIN
2084
    canvas := Canvas;
2085
    charWidth := canvas.font.width;
2086
    charHeight := canvas.font.height + inter
2087
END setCanvas;
2088
 
2089
 
2090
PROCEDURE resize* (width, height: INTEGER);
2091
BEGIN
2092
    size.X := width;
2093
    size.Y := height;
2094
    setPadding(padding.left, padding.top)
2095
END resize;
2096
 
2097
 
2098
PROCEDURE destroy* (VAR text: tText);
2099
BEGIN
2100
    IF search(text, "", FALSE, FALSE) THEN END;
2101
    WHILE text.last # NIL DO
2102
        DelLine(text, text.last(tLine))
2103
    END;
2104
    DISPOSE(text.foundList);
2105
    DISPOSE(text.cursor);
2106
    DISPOSE(text.select2);
2107
    DISPOSE(text)
2108
END destroy;
2109
 
2110
 
2111
PROCEDURE open* (name: RW.tFileName; VAR errno: INTEGER): tText;
2112
VAR
2113
    text: tText;
2114
    file: RW.tInput;
2115
    n, enc: INTEGER;
2116
    eol: BOOLEAN;
2117
    line: tLine;
2118
BEGIN
2119
    errno := 0;
2120
    text := NIL;
2121
    file := RW.load(name, enc);
2122
    IF file # NIL THEN
2123
        text := create(name);
2124
        text.enc := enc;
2125
        REPEAT
2126
            line := Lines.create(FALSE);
2127
            n := RW.getString(file, line, eol);
2128
            IF n >= 0 THEN
2129
                List._append(text, line)
2130
            ELSE
2131
                Lines.destroy(line)
2132
            END
2133
        UNTIL n < 0;
2134
        RW.destroy(file);
2135
        IF n = -1 THEN
2136
            IF text.count = 0 THEN
2137
                List._append(text, Lines.create(FALSE))
2138
            END;
2139
            text.curLine := text.first(tLine);
2140
            SetPos(text, 0, 0);
2141
            resetSelect(text)
2142
        END
2143
    ELSE
2144
        errno := 1
2145
    END;
2146
    IF (text # NIL) & (text.lang # Lang.langNone) THEN
2147
        Comments(text)
2148
    END
2149
    RETURN text
2150
END open;
2151
 
2152
 
2153
PROCEDURE findNext* (text: tText; prev: BOOLEAN): BOOLEAN;
2154
VAR
2155
    cursorPos, x, y, X, Y, Len: INTEGER;
2156
    p: Search.tPos;
2157
    line: tLine;
2158
    res: BOOLEAN;
2159
BEGIN
2160
    X := text.cursor.X;
2161
    Y := text.cursor.Y;
2162
    text.cursor.X := MIN(text.cursor.X, text.curLine.length);
2163
    cursorPos := text.curLine.pos + text.cursor.X - ORD(prev) - ORD(~prev & (text.foundSel = 0));
2164
    p := text.foundList.first(Search.tPos);
2165
    WHILE (p # NIL) & (p.pos <= cursorPos) DO
2166
        p := p.next(Search.tPos)
2167
    END;
2168
    IF prev THEN
2169
        IF p = NIL THEN
2170
            p := text.foundList.last(Search.tPos)
2171
        ELSE
2172
            p := p.prev(Search.tPos)
2173
        END
2174
    END;
2175
    res := p # NIL;
2176
    IF res THEN
2177
        y := 0;
2178
        line := text.first(tLine);
2179
        WHILE (line.pos <= p.pos) & (line.next # NIL) DO
2180
            NextLine(line);
2181
            INC(y)
2182
        END;
2183
        IF (line.next # NIL) OR (line.pos > p.pos) THEN
2184
            PrevLine(line);
2185
            DEC(y)
2186
        END;
2187
        resetSelect(text);
2188
        searchScroll(text, y);
2189
        x := p.pos - line.pos;
2190
        Len := LENGTH(text.searchText);
2191
        IF x + Len > text.scroll.X + textsize.X THEN
2192
            text.scroll.X := MAX(x + Len - textsize.X + 3, 0)
2193
        ELSIF x < text.scroll.X THEN
2194
            text.scroll.X := MAX(x - 3, 0)
2195
        END;
2196
        SetPos(text, x, y);
2197
        text.foundSel := Len
2198
    ELSE
2199
        SetPos(text, X, Y)
2200
    END
2201
    RETURN res
2202
END findNext;
2203
 
2204
 
2205
PROCEDURE rewrite (line: tLine; repl: ARRAY OF WCHAR; pos, n: INTEGER);
2206
BEGIN
2207
    IF n > 0 THEN
2208
        Lines.copy(line)
2209
    END;
2210
    WHILE n > 0 DO
2211
        DEC(n);
2212
        Lines.setChar(line, pos + n, repl[n])
2213
    END
2214
END rewrite;
2215
 
2216
 
2217
PROCEDURE replace* (text: tText; s: ARRAY OF WCHAR; n: INTEGER);
2218
VAR
2219
    line: tLine;
2220
    sLen, i: INTEGER;
2221
BEGIN
2222
    IF text.foundSel > 0 THEN
2223
        line := text.curLine;
2224
        sLen := LENGTH(s);
2225
        i := text.cursor.X;
2226
        IF sLen > n THEN
2227
            Lines.insert3(line, i, sLen - n)
2228
        END;
2229
        SetPos(text, i + sLen, text.cursor.Y);
2230
        rewrite(line, s, i, sLen);
2231
        IF n > sLen THEN
2232
            Lines.delCharN(line, text.cursor.X, n - sLen)
2233
        END;
2234
        resetSelect(text);
2235
        Lines.modify(line);
2236
        modify(text)
2237
    END
2238
END replace;
2239
 
2240
 
2241
PROCEDURE replaceAll* (text: tText; s: ARRAY OF WCHAR; n: INTEGER): INTEGER;
2242
VAR
2243
    p: Search.tPos;
2244
    line: tLine;
2245
    y, k, d, pos, y0: INTEGER;
2246
BEGIN
2247
    resetSelect(text);
2248
    SetPos(text, 0, 0);
2249
    line := text.first(tLine);
2250
    y := 0;
2251
    y0 := -1;
2252
    k := 0;
2253
    d := LENGTH(s) - n;
2254
    p := text.foundList.first(Search.tPos);
2255
    WHILE p # NIL DO
2256
        pos := p.pos;
2257
        WHILE (line.pos <= pos) & (line.next # NIL) DO
2258
            NextLine(line);
2259
            INC(y)
2260
        END;
2261
        IF (line.next # NIL) OR (line.pos > pos) THEN
2262
            PrevLine(line);
2263
            DEC(y)
2264
        END;
2265
        IF y = y0 THEN
2266
            INC(k, d)
2267
        ELSE
2268
            k := 0;
2269
            y0 := y
2270
        END;
2271
        SetPos(text, pos - line.pos + k, y);
2272
        text.foundSel := n;
2273
        replace(text, s, n);
2274
        p := p.next(Search.tPos)
2275
    END
2276
    RETURN text.foundList.count
2277
END replaceAll;
2278
 
2279
 
2280
PROCEDURE New* (): tText;
2281
VAR
2282
    text: tText;
2283
BEGIN
2284
    text := create("");
2285
    List._append(text, Lines.create(FALSE));
2286
    text.curLine := text.first(tLine);
2287
    text.enc := E.CP866;
2288
    SetPos(text, 0, 0);
2289
    resetSelect(text)
2290
    RETURN text
2291
END New;
2292
 
2293
 
2294
PROCEDURE empty;
2295
END empty;
2296
 
2297
 
2298
PROCEDURE init* (pShowCursor: tProcedure);
2299
BEGIN
2300
    ShowCursor := empty;
2301
    IF pShowCursor # NIL THEN
2302
        ShowCursor := pShowCursor
2303
    END;
2304
    pdelete := delete;
2305
    drawCursor := TRUE;
2306
    padding.left := pad_left;
2307
    padding.top := pad_top;
2308
END init;
2309
 
2310
 
2311
END Text.