Subversion Repositories Kolibri OS

Rev

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