Subversion Repositories Kolibri OS

Rev

Rev 9194 | Rev 9208 | 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
 
9197 akron1 1779
PROCEDURE getSelectedText* (text: tText; VAR s: ARRAY OF WCHAR);
1780
VAR
1781
    n: INTEGER;
1782
    selBeg, selEnd: tPoint;
1783
BEGIN
1784
	s[0] := 0X;
1785
    IF selected(text) & (text.cursor.Y = text.select.Y) THEN
1786
        getSelect(text, selBeg, selEnd);
1787
        n := getString(text.curLine, selBeg.X, selEnd.X - selBeg.X, s)
1788
    END
1789
END getSelectedText;
1790
 
1791
 
9010 leency 1792
PROCEDURE wordSel* (text: tText);
1793
VAR
1794
    n, i, x1, x2: INTEGER;
1795
    selBeg, selEnd: tPoint;
1796
    str: tString;
1797
    curLine: tLine;
1798
BEGIN
1799
    curLine := text.curLine;
1800
    IF selected(text) & (text.cursor.Y = text.select.Y) THEN
1801
        getSelect(text, selBeg, selEnd);
1802
        x1 := selBeg.X;
1803
        x2 := selEnd.X;
1804
        n := getString(curLine, x1, x2 - x1, str);
1805
    ELSE
1806
        str := ""
1807
    END;
1808
    IF str # "" THEN
1809
        i := 0;
1810
        WHILE (i < n) & isWordChar(str[i]) DO
1811
            INC(i)
1812
        END;
1813
        IF (i # n) OR
1814
            ((x1 > 0) & isWordChar(getChar(curLine, x1 - 1))) OR
1815
            ((x2 < curLine.length) & isWordChar(getChar(curLine, x2))) THEN
1816
            str := ""
1817
        END
1818
    END;
9050 leency 1819
    IF search(text, str, Lang.isCS(text.lang), TRUE) THEN END
9010 leency 1820
END wordSel;
1821
 
1822
 
9073 leency 1823
PROCEDURE key* (text: tText; code: INTEGER; shift, ctrl: BOOLEAN);
9174 akron1 1824
VAR
1825
	n: INTEGER;
8728 leency 1826
BEGIN
9073 leency 1827
    IF shift THEN
8728 leency 1828
        setSelect(text)
1829
    ELSE
1830
        IF (33 <= code) & (code <= 40) THEN
1831
            resetSelect(text)
1832
        END
1833
    END;
1834
 
1835
    CASE code OF
1836
    |33:
9073 leency 1837
        IF ctrl THEN
8728 leency 1838
            UpDown(text, text.scroll.Y - text.cursor.Y)
1839
        ELSE
1840
            text.scroll.Y := MAX(text.scroll.Y - textsize.Y, 0);
1841
            UpDown(text, -textsize.Y)
1842
        END
1843
    |34:
9073 leency 1844
        IF ctrl THEN
8728 leency 1845
            UpDown(text, MIN(text.scroll.Y + textsize.Y - 1, text.count - 1) - text.cursor.Y)
1846
        ELSE
1847
            text.scroll.Y := MIN(text.scroll.Y + textsize.Y, text.count - 1);
1848
            UpDown(text, textsize.Y)
1849
        END
1850
    |35:
9073 leency 1851
        IF ctrl THEN
8728 leency 1852
            SetPos(text, text.last(tLine).length, text.count - 1)
1853
        ELSE
1854
            SetPos(text, text.curLine.length, text.cursor.Y)
1855
        END
1856
    |36:
9073 leency 1857
        IF ctrl THEN
8728 leency 1858
            SetPos(text, 0, 0)
1859
        ELSE
9174 akron1 1860
        	n := leadingSpaces(text.curLine);
1861
        	IF text.cursor.X > n THEN
1862
	            SetPos(text, n, text.cursor.Y)
1863
        	ELSE
1864
        		SetPos(text, 0, text.cursor.Y)
1865
        	END
8728 leency 1866
        END
1867
    |37:
1868
        IF (text.cursor.X = 0) & (text.curLine.prev # NIL) THEN
1869
            SetPos(text, text.curLine.prev(tLine).length, text.cursor.Y - 1)
1870
        ELSE
9174 akron1 1871
            move(text, -1)
8728 leency 1872
        END
1873
    |38:
9073 leency 1874
        IF ctrl THEN
9010 leency 1875
            upLine(text)
1876
        ELSE
1877
            UpDown(text, -1)
1878
        END
8728 leency 1879
    |39:
1880
        IF (text.cursor.X = text.curLine.length) & (text.curLine.next # NIL) THEN
1881
            SetPos(text, 0, text.cursor.Y + 1)
1882
        ELSE
9174 akron1 1883
            move(text, 1)
8728 leency 1884
        END
1885
    |40:
9073 leency 1886
        IF ctrl THEN
9010 leency 1887
            downLine(text)
1888
        ELSE
1889
            UpDown(text, 1)
1890
        END
1891
    |46:
9073 leency 1892
        IF ctrl THEN
9010 leency 1893
            delLine(text)
1894
        ELSE
9174 akron1 1895
            delete(text);
1896
            ShowCursor
9010 leency 1897
        END
8728 leency 1898
    |ORD("C"):
9073 leency 1899
        IF ctrl THEN
8728 leency 1900
            IF selected(text) THEN
1901
                copy(text)
1902
            END
1903
        END
1904
    |ORD("X"):
9073 leency 1905
        IF ctrl THEN
8728 leency 1906
            IF selected(text) THEN
1907
                copy(text);
1908
                delSelect(text)
1909
            END
1910
        END
1911
    |ORD("V"):
9073 leency 1912
        IF ctrl THEN
8728 leency 1913
            IF CB.available() THEN
1914
                paste(text)
1915
            END
1916
        END
1917
    |ORD("A"):
9073 leency 1918
        IF ctrl THEN
8728 leency 1919
            text.select2.X := 0;
1920
            text.select2.Y := 0;
1921
            text.select := text.select2;
1922
            SetPos(text, text.last(tLine).length, text.count - 1)
1923
        END
1924
    |ORD("L"), ORD("U"):
9073 leency 1925
        IF ctrl THEN
9174 akron1 1926
        	IF selected(text) THEN
1927
            	chCase(text, code = ORD("U"))
1928
            ELSE
1929
            	changeCase(text, code = ORD("U"))
1930
            END;
1931
            ShowCursor
8728 leency 1932
        END
9010 leency 1933
    |ORD("D"):
9073 leency 1934
        IF ctrl THEN
9010 leency 1935
            dupLine(text)
1936
        END
8728 leency 1937
    ELSE
1938
    END
1939
END key;
1940
 
1941
 
1942
PROCEDURE mouse* (text: tText; x, y: INTEGER);
1943
VAR
1944
    cursorX: INTEGER;
1945
BEGIN
1946
    DEC(x, padding.left);
1947
    DEC(y, padding.top);
1948
    cursorX := (x*2) DIV charWidth;
1949
    SetPos(text, cursorX DIV 2 + cursorX MOD 2 + text.scroll.X, y DIV charHeight + text.scroll.Y)
1950
END mouse;
1951
 
1952
 
1953
PROCEDURE selectWord* (text: tText);
1954
VAR
1955
    cursorX, x1, x2: INTEGER;
1956
    line: tLine;
1957
BEGIN
1958
    resetSelect(text);
1959
    cursorX := text.cursor.X;
1960
    line := text.curLine;
1961
    x1 := cursorX - 1;
1962
    IF (cursorX < line.length) & isWordChar(getChar(line,cursorX)) THEN
1963
        x2 := cursorX;
1964
        WHILE (x2 < line.length) & isWordChar(getChar(line, x2)) DO
1965
            INC(x2)
1966
        END
1967
    ELSE
1968
        WHILE (x1 >= 0) & ~isWordChar(getChar(line, x1)) DO
1969
            DEC(x1)
1970
        END;
1971
        x2 := x1 + 1
1972
    END;
1973
    WHILE (x1 >= 0) & isWordChar(getChar(line, x1)) DO
1974
        DEC(x1)
1975
    END;
1976
    INC(x1);
1977
    IF x1 < x2 THEN
1978
        SetPos(text, x1, text.cursor.Y);
1979
        setSelect(text);
1980
        SetPos(text, x2, text.cursor.Y)
1981
    END
1982
END selectWord;
1983
 
1984
 
1985
PROCEDURE cursor (text: tText);
1986
VAR
1987
    x, y, h: INTEGER;
1988
    cursor: pPoint;
1989
BEGIN
1990
    cursor := text.cursor;
1991
    IF ~((text.scroll.Y > cursor.Y) OR (text.scroll.Y + textsize.Y <= cursor.Y) OR
1992
       (text.scroll.X > cursor.X) OR (text.scroll.X + textsize.X <= cursor.X)) THEN
1993
        x := (cursor.X - text.scroll.X)*charWidth + padding.left;
1994
        y := (cursor.Y - text.scroll.Y)*charHeight + 1 + padding.top;
1995
        h := charHeight - 2;
1996
        G.notVLine(canvas, x, y + inter DIV 2, y + h - inter DIV 2);
1997
        G.notVLine(canvas, x - 1, y + inter DIV 2, y + h - inter DIV 2)
1998
    END
1999
END cursor;
2000
 
2001
 
2002
PROCEDURE drawSelect (text: tText; line: tLine; selBeg, selEnd, y: INTEGER);
2003
VAR
2004
    Len, pos, x, firstCharIdx: INTEGER;
2005
BEGIN
2006
    firstCharIdx := MAX(text.scroll.X, selBeg);
2007
    Len := MAX(MIN(line.length - firstCharIdx, selEnd - firstCharIdx), 0);
2008
    Len := MIN(Len, textsize.X - pos + 1);
2009
    SetColor(colors.seltext, colors.selback);
2010
    pos := MAX((selBeg - text.scroll.X), 0);
2011
    x := pos*charWidth + padding.left;
2012
    G.SetColor(canvas, colors.selback);
2013
    G.FillRect(canvas, x - 2, y - inter DIV 2, x + 1 + Len*charWidth, y - inter DIV 2 + charHeight);
9193 akron1 2014
    G.TextOut(canvas, pos*charWidth + padding.left, y, Lines.getPChar(line, firstCharIdx), Len, colors.seltext)
8728 leency 2015
END drawSelect;
2016
 
2017
 
2018
PROCEDURE mark (line: tLine; y: INTEGER);
2019
VAR
2020
    color, i: INTEGER;
2021
BEGIN
2022
    IF line.modified THEN
2023
        color := colors.modified
2024
    ELSIF line.saved THEN
2025
        color := colors.saved
2026
    ELSE
2027
        color := colors.back
2028
    END;
2029
    G.SetColor(canvas, color);
2030
 
2031
    FOR i := 3 TO mark_width + 2 DO
2032
        G.VLine(canvas, padding.left - i, y, y + charHeight)
2033
    END
2034
END mark;
2035
 
2036
 
2037
PROCEDURE setPadding (left, top: INTEGER);
2038
BEGIN
2039
    padding.left := left;
2040
    padding.top := top;
2041
    textsize.X := (size.X - padding.left) DIV charWidth;
2042
    textsize.Y := (size.Y - padding.top) DIV charHeight;
2043
END setPadding;
2044
 
2045
 
2046
PROCEDURE draw* (text: tText);
2047
VAR
2048
    y, n, Len, cnt, i, x: INTEGER;
2049
    line, firstLine, lastLine: tLine;
2050
    selBeg, selEnd: tPoint;
2051
    s: ARRAY 12 OF WCHAR;
2052
    backColor, numWidth, xNum, wNum: INTEGER;
2053
    p: Search.tPos;
2054
    guard: tGuard;
2055
BEGIN
2056
    IF text.search & search(text, text.searchText, text.cs, text.whole) THEN END;
9190 akron1 2057
    IF (text.lang # Lang.langText) & text.comments THEN
8728 leency 2058
        Comments(text)
2059
    END;
2060
    IF text.guard THEN
2061
        NEW(guard);
9050 leency 2062
        List.append(ChangeLog.CL.Log, guard);
9073 leency 2063
        guard.saved := ChangeLog.isFirstGuard(guard);
8728 leency 2064
        text.edition := guard;
9073 leency 2065
        text.guard := FALSE
8728 leency 2066
    ELSE
2067
        guard := text.edition
2068
    END;
2069
 
2070
    guard.cursor := text.cursor^;
2071
    guard.select2 := text.select2^;
2072
    guard.scroll := text.scroll;
2073
    guard.CurX := text.CurX;
2074
    guard.selected := text.select = text.select2;
2075
 
2076
    G.SetColor(canvas, colors.back);
2077
    G.clear(canvas);
9060 leency 2078
    wNum := charWidth;
8728 leency 2079
    IF text.numbers THEN
2080
        numWidth := U.lg10(text.count) + 2;
2081
        xNum := numWidth*wNum - wNum DIV 2;
2082
        setPadding(numWidth*wNum + pad_left, padding.top);
2083
    ELSE
9060 leency 2084
        setPadding(pad_left + wNum*2, padding.top)
8728 leency 2085
    END;
2086
    getSelect(text, selBeg, selEnd);
2087
    y := padding.top + inter DIV 2;
2088
    n := text.scroll.Y;
2089
    line := getLine(text, n);
2090
    firstLine := line;
2091
    cnt := 0;
2092
    WHILE (line # NIL) & (cnt <= textsize.Y) DO
2093
        backColor := colors.back;
2094
        IF (line = text.curLine) & ~selected(text) THEN
2095
            G.SetColor(canvas, colors.curline);
2096
            G.FillRect(canvas, padding.left - 2, y - inter DIV 2, size.X - 1, y - inter DIV 2 + charHeight);
2097
            backColor := colors.curline
2098
        END;
2099
        SetColor(colors.text, backColor);
2100
        Len := MAX(line.length - text.scroll.X, 0);
9193 akron1 2101
        G.TextOut(canvas, padding.left, y, Lines.getPChar(line, text.scroll.X), MIN(Len, textsize.X + 1), colors.delim);
9190 akron1 2102
        IF text.lang # Lang.langText THEN
8728 leency 2103
            parse(text, line, y, backColor, text.lang)
2104
        END;
2105
        mark(line, y - inter DIV 2);
2106
        IF (selBeg.Y < n) & (n < selEnd.Y) THEN
2107
            drawSelect(text, line, 0, line.length, y)
2108
        ELSIF (selBeg.Y = n) & (selEnd.Y = n) & (selBeg.X # selEnd.X) THEN
2109
            drawSelect(text, line, selBeg.X, selEnd.X, y)
2110
        ELSIF (selBeg.Y = n) & (selEnd.Y # n) THEN
2111
            drawSelect(text, line, selBeg.X, line.length, y)
2112
        ELSIF (selBeg.Y # n) & (selEnd.Y = n) THEN
2113
            drawSelect(text, line, 0, selEnd.X, y)
2114
        END;
2115
        NextLine(line);
2116
        INC(y, charHeight);
2117
        INC(n);
2118
        INC(cnt)
2119
    END;
9060 leency 2120
    G.SetColor(canvas, colors.numback);
2121
    G.FillRect(canvas, 0, 0, padding.left - pad_left (*+ 1*), size.Y - 1);
2122
    line := firstLine;
2123
    SetColor(colors.numtext, colors.numback);
2124
    y := padding.top + inter DIV 2;
2125
    n := MIN(text.scroll.Y + textsize.Y + 1, text.count);
2126
    FOR i := text.scroll.Y + 1 TO n DO
2127
        IF text.numbers THEN
2128
            IF (i MOD 10 = 0) OR (i - 1 = text.cursor.Y) OR line.label THEN
8728 leency 2129
                U.int2str(i, s);
9060 leency 2130
                G.TextOut2(canvas, (numWidth - U.lg10(i) - 1)*wNum - wNum DIV 2, y, s, LENGTH(s))
8728 leency 2131
            ELSIF i MOD 5 = 0 THEN
2132
                G.SetColor(canvas, colors.numtext);
2133
                G.HLine(canvas, y - inter DIV 2 + charHeight DIV 2, xNum - wNum, xNum)
2134
            ELSE
2135
                G.SetColor(canvas, colors.numtext);
2136
                G.HLine(canvas, y - inter DIV 2 + charHeight DIV 2, xNum - wNum DIV 2, xNum)
9060 leency 2137
            END
2138
        END;
2139
        IF line.label THEN
2140
            FOR x := wNum DIV 2 TO (padding.left - pad_left) - wNum DIV 2 DO
2141
                G.notVLine(canvas, x, y, y + charHeight - inter);
2142
                G.xorVLine(canvas, x, y, y + charHeight - inter)
2143
            END
2144
        END;
2145
        NextLine(line);
2146
        INC(y, charHeight)
8728 leency 2147
    END;
2148
 
2149
    IF text.searchText # "" THEN
2150
        cnt := 0;
2151
        line := firstLine;
2152
        lastLine := line;
2153
        WHILE (line # NIL) & (cnt <= textsize.Y) DO
2154
            lastLine := line;
2155
            NextLine(line);
2156
            INC(cnt)
2157
        END;
2158
        p := text.foundList.first(Search.tPos);
2159
        WHILE p # NIL DO
2160
            y := padding.top + inter DIV 2;
2161
            IF (firstLine.pos <= p.pos) & (p.pos <= lastLine.pos + lastLine.length) THEN
2162
                line := firstLine;
2163
                WHILE (line.pos <= p.pos) & (line # lastLine) DO
2164
                    NextLine(line);
2165
                    INC(y, charHeight)
2166
                END;
2167
                IF (line # lastLine) & (line # firstLine) OR (line = lastLine) & (line.pos > p.pos) THEN
2168
                    PrevLine(line);
2169
                    DEC(y, charHeight)
2170
                END;
2171
                x := (p.pos - line.pos - text.scroll.X)*charWidth + padding.left;
2172
                n := LENGTH(text.searchText)*charWidth;
2173
                WHILE n > 0 DO
2174
                    IF x >= padding.left THEN
2175
                        G.notVLine(canvas, x, y, y + charHeight - inter)
2176
                    END;
2177
                    INC(x);
2178
                    DEC(n)
2179
                END;
2180
            END;
2181
            p := p.next(Search.tPos)
2182
        END
2183
    END;
2184
 
2185
    IF text.foundSel > 0 THEN
2186
        x := (text.cursor.X - text.scroll.X)*charWidth + padding.left;
2187
        y := (text.cursor.Y - text.scroll.Y)*charHeight + padding.top + inter DIV 2;
2188
        n := text.foundSel*charWidth;
2189
        WHILE n > 0 DO
2190
            IF x >= padding.left THEN
2191
                G.xorVLine(canvas, x, y, y + charHeight - inter)
2192
            END;
2193
            INC(x);
2194
            DEC(n)
2195
        END
2196
    END;
2197
 
2198
    IF drawCursor THEN
2199
        cursor(text)
2200
    END;
8762 leency 2201
    G.SetColor(canvas, K.borderColor);
9060 leency 2202
    G.VLine(canvas, 0, 0, size.Y - 1);
8728 leency 2203
END draw;
2204
 
2205
 
9050 leency 2206
PROCEDURE switch* (text: tText);
2207
BEGIN
2208
    ChangeLog.set(text.chLog);
9194 akron1 2209
    Lines.setMaxLength(text.maxLength);
2210
    Lang.setCurLang(text.lang)
9050 leency 2211
END switch;
2212
 
2213
 
8728 leency 2214
PROCEDURE create (fileName: RW.tFileName): tText;
2215
VAR
2216
    text: tText;
2217
BEGIN
2218
    NEW(text);
9050 leency 2219
    text.maxLength := 64;
2220
    text.chLog := ChangeLog.create(text.maxLength);
8728 leency 2221
    NEW(text.cursor);
2222
    NEW(text.select2);
2223
    text.cursor.X := 0;
2224
    text.cursor.Y := 0;
2225
    resetSelect(text);
2226
    text.scroll.X := 0;
2227
    text.scroll.Y := 0;
2228
    setPadding(padding.left, padding.top);
2229
    text.curLine := NIL;
2230
    text.modified := FALSE;
2231
    text.comments := TRUE;
2232
    text.search := TRUE;
2233
    text.cs := FALSE;
2234
    text.whole := FALSE;
2235
    text.numbers := TRUE;
2236
    text.guard := TRUE;
2237
    text.idxData := NIL;
2238
    text.edition := NIL;
2239
    text.foundList := List.create(NIL);
2240
    text.searchText := "";
2241
    text.foundSel := 0;
2242
    text.CurX := -1;
9193 akron1 2243
    text.lang := Lang.langText;
2244
    Lang.setCurLang(Lang.langText);
8728 leency 2245
    setName(text, fileName);
2246
    ASSERT(text = List.create(text))
2247
    RETURN text
2248
END create;
2249
 
2250
 
2251
PROCEDURE setColors* (text, back, seltext, selback, modified, saved, curline, numtext, numback,
8762 leency 2252
                        comment, string, num, delim, key1, key2, key3: INTEGER);
8728 leency 2253
BEGIN
2254
    colors.text := text;
2255
    colors.back := back;
2256
    colors.seltext := seltext;
2257
    colors.selback := selback;
2258
    colors.modified := modified;
2259
    colors.saved := saved;
2260
    colors.curline := curline;
2261
    colors.numtext := numtext;
2262
    colors.numback := numback;
2263
    colors.comment := comment;
2264
    colors.string  := string;
2265
    colors.num := num;
2266
    colors.delim := delim;
2267
    colors.key1 := key1;
2268
    colors.key2 := key2;
2269
    colors.key3 := key3;
2270
END setColors;
2271
 
2272
 
2273
PROCEDURE setCanvas* (Canvas: G.tCanvas);
2274
BEGIN
2275
    canvas := Canvas;
2276
    charWidth := canvas.font.width;
2277
    charHeight := canvas.font.height + inter
2278
END setCanvas;
2279
 
2280
 
2281
PROCEDURE resize* (width, height: INTEGER);
2282
BEGIN
2283
    size.X := width;
2284
    size.Y := height;
2285
    setPadding(padding.left, padding.top)
2286
END resize;
2287
 
2288
 
2289
PROCEDURE destroy* (VAR text: tText);
2290
BEGIN
2291
    IF search(text, "", FALSE, FALSE) THEN END;
2292
    WHILE text.last # NIL DO
2293
        DelLine(text, text.last(tLine))
2294
    END;
2295
    DISPOSE(text.foundList);
2296
    DISPOSE(text.cursor);
2297
    DISPOSE(text.select2);
2298
    DISPOSE(text)
2299
END destroy;
2300
 
2301
 
2302
PROCEDURE open* (name: RW.tFileName; VAR errno: INTEGER): tText;
2303
VAR
2304
    text: tText;
2305
    file: RW.tInput;
9180 akron1 2306
    n, enc, eol: INTEGER;
2307
    _eol: BOOLEAN;
8728 leency 2308
    line: tLine;
2309
BEGIN
2310
    errno := 0;
2311
    text := NIL;
9180 akron1 2312
    file := RW.load(name, enc, eol);
8728 leency 2313
    IF file # NIL THEN
2314
        text := create(name);
2315
        text.enc := enc;
9180 akron1 2316
        text.eol := eol;
2317
        line := Lines.create(FALSE);
2318
        List._append(text, line);
8728 leency 2319
        REPEAT
9180 akron1 2320
            n := RW.getString(file, line, Lines.tabs, _eol);
2321
            IF _eol THEN
2322
            	line := Lines.create(FALSE);
2323
            	List._append(text, line)
8728 leency 2324
            END
9180 akron1 2325
        UNTIL ~_eol;
8728 leency 2326
        RW.destroy(file);
9180 akron1 2327
        text.curLine := text.first(tLine);
2328
        SetPos(text, 0, 0);
2329
        resetSelect(text)
8728 leency 2330
    ELSE
2331
        errno := 1
2332
    END;
9190 akron1 2333
    IF (text # NIL) & (text.lang # Lang.langText) THEN
8728 leency 2334
        Comments(text)
2335
    END
2336
    RETURN text
2337
END open;
2338
 
2339
 
2340
PROCEDURE findNext* (text: tText; prev: BOOLEAN): BOOLEAN;
2341
VAR
2342
    cursorPos, x, y, X, Y, Len: INTEGER;
2343
    p: Search.tPos;
2344
    line: tLine;
2345
    res: BOOLEAN;
2346
BEGIN
2347
    X := text.cursor.X;
2348
    Y := text.cursor.Y;
2349
    text.cursor.X := MIN(text.cursor.X, text.curLine.length);
2350
    cursorPos := text.curLine.pos + text.cursor.X - ORD(prev) - ORD(~prev & (text.foundSel = 0));
2351
    p := text.foundList.first(Search.tPos);
2352
    WHILE (p # NIL) & (p.pos <= cursorPos) DO
2353
        p := p.next(Search.tPos)
2354
    END;
2355
    IF prev THEN
2356
        IF p = NIL THEN
2357
            p := text.foundList.last(Search.tPos)
2358
        ELSE
2359
            p := p.prev(Search.tPos)
2360
        END
2361
    END;
2362
    res := p # NIL;
2363
    IF res THEN
2364
        y := 0;
2365
        line := text.first(tLine);
2366
        WHILE (line.pos <= p.pos) & (line.next # NIL) DO
2367
            NextLine(line);
2368
            INC(y)
2369
        END;
2370
        IF (line.next # NIL) OR (line.pos > p.pos) THEN
2371
            PrevLine(line);
2372
            DEC(y)
2373
        END;
2374
        resetSelect(text);
2375
        searchScroll(text, y);
2376
        x := p.pos - line.pos;
2377
        Len := LENGTH(text.searchText);
2378
        IF x + Len > text.scroll.X + textsize.X THEN
2379
            text.scroll.X := MAX(x + Len - textsize.X + 3, 0)
2380
        ELSIF x < text.scroll.X THEN
2381
            text.scroll.X := MAX(x - 3, 0)
2382
        END;
2383
        SetPos(text, x, y);
2384
        text.foundSel := Len
2385
    ELSE
2386
        SetPos(text, X, Y)
2387
    END
2388
    RETURN res
2389
END findNext;
2390
 
2391
 
2392
PROCEDURE rewrite (line: tLine; repl: ARRAY OF WCHAR; pos, n: INTEGER);
2393
BEGIN
2394
    IF n > 0 THEN
2395
        Lines.copy(line)
2396
    END;
2397
    WHILE n > 0 DO
2398
        DEC(n);
2399
        Lines.setChar(line, pos + n, repl[n])
2400
    END
2401
END rewrite;
2402
 
2403
 
2404
PROCEDURE replace* (text: tText; s: ARRAY OF WCHAR; n: INTEGER);
2405
VAR
2406
    line: tLine;
2407
    sLen, i: INTEGER;
2408
BEGIN
2409
    IF text.foundSel > 0 THEN
2410
        line := text.curLine;
2411
        sLen := LENGTH(s);
2412
        i := text.cursor.X;
2413
        IF sLen > n THEN
2414
            Lines.insert3(line, i, sLen - n)
2415
        END;
2416
        SetPos(text, i + sLen, text.cursor.Y);
2417
        rewrite(line, s, i, sLen);
2418
        IF n > sLen THEN
2419
            Lines.delCharN(line, text.cursor.X, n - sLen)
2420
        END;
2421
        resetSelect(text);
2422
        Lines.modify(line);
2423
        modify(text)
2424
    END
2425
END replace;
2426
 
2427
 
2428
PROCEDURE replaceAll* (text: tText; s: ARRAY OF WCHAR; n: INTEGER): INTEGER;
2429
VAR
2430
    p: Search.tPos;
2431
    line: tLine;
2432
    y, k, d, pos, y0: INTEGER;
2433
BEGIN
2434
    resetSelect(text);
2435
    SetPos(text, 0, 0);
2436
    line := text.first(tLine);
2437
    y := 0;
2438
    y0 := -1;
2439
    k := 0;
2440
    d := LENGTH(s) - n;
2441
    p := text.foundList.first(Search.tPos);
2442
    WHILE p # NIL DO
2443
        pos := p.pos;
2444
        WHILE (line.pos <= pos) & (line.next # NIL) DO
2445
            NextLine(line);
2446
            INC(y)
2447
        END;
2448
        IF (line.next # NIL) OR (line.pos > pos) THEN
2449
            PrevLine(line);
2450
            DEC(y)
2451
        END;
2452
        IF y = y0 THEN
2453
            INC(k, d)
2454
        ELSE
2455
            k := 0;
2456
            y0 := y
2457
        END;
2458
        SetPos(text, pos - line.pos + k, y);
2459
        text.foundSel := n;
2460
        replace(text, s, n);
2461
        p := p.next(Search.tPos)
2462
    END
2463
    RETURN text.foundList.count
2464
END replaceAll;
2465
 
2466
 
2467
PROCEDURE New* (): tText;
2468
VAR
2469
    text: tText;
2470
BEGIN
2471
    text := create("");
2472
    List._append(text, Lines.create(FALSE));
2473
    text.curLine := text.first(tLine);
2474
    text.enc := E.CP866;
9180 akron1 2475
    text.eol := RW.EOL_CRLF;
8728 leency 2476
    SetPos(text, 0, 0);
2477
    resetSelect(text)
2478
    RETURN text
2479
END New;
2480
 
2481
 
2482
PROCEDURE init* (pShowCursor: tProcedure);
2483
BEGIN
9174 akron1 2484
    ShowCursor := pShowCursor;
8728 leency 2485
    pdelete := delete;
2486
    drawCursor := TRUE;
2487
    padding.left := pad_left;
2488
    padding.top := pad_top;
2489
END init;
2490
 
2491
 
2492
END Text.