Subversion Repositories Kolibri OS

Rev

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