Subversion Repositories Kolibri OS

Rev

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