Subversion Repositories Kolibri OS

Rev

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