Subversion Repositories Kolibri OS

Rev

Rev 8859 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
7983 leency 1
(*
7597 akron1 2
    BSD 2-Clause License
3
 
9177 akron1 4
    Copyright (c) 2018-2021, Anton Krotov
7597 akron1 5
    All rights reserved.
6
*)
7
 
8
MODULE TEXTDRV;
9
 
10
IMPORT FILES, C := COLLECTIONS;
11
 
12
 
13
CONST
14
 
9177 akron1 15
    CR = 0DX; LF = 0AX; HT = 9X;
7597 akron1 16
 
17
    CHUNK = 1024 * 256;
18
 
9177 akron1 19
    defTabSize* = 4;
7597 akron1 20
 
9177 akron1 21
 
7597 akron1 22
TYPE
23
 
24
    TEXT* = POINTER TO RECORD (C.ITEM)
25
 
7696 akron1 26
        chunk:        ARRAY CHUNK OF CHAR;
7597 akron1 27
        pos, size:    INTEGER;
28
        file:         FILES.FILE;
29
        utf8:         BOOLEAN;
30
        CR:           BOOLEAN;
31
 
32
        line*, col*:  INTEGER;
8097 maxcodehac 33
        ifc*:         INTEGER;
34
        elsec*:       INTEGER;
7597 akron1 35
        eof*:         BOOLEAN;
36
        eol*:         BOOLEAN;
8097 maxcodehac 37
        skip*:        BOOLEAN;
38
        peak*:        CHAR;
39
        _skip*,
40
        _elsif*,
41
        _else*:       ARRAY 100 OF BOOLEAN;
42
        fname*:       ARRAY 2048 OF CHAR
7597 akron1 43
 
44
    END;
45
 
46
 
47
VAR
48
 
49
    texts: C.COLLECTION;
9177 akron1 50
    TabSize: INTEGER;
7597 akron1 51
 
52
 
53
PROCEDURE load (text: TEXT);
54
BEGIN
55
    IF ~text.eof THEN
56
        text.size := FILES.read(text.file, text.chunk, LEN(text.chunk));
57
        text.pos := 0;
58
        IF text.size = 0 THEN
59
            text.eof := TRUE;
7696 akron1 60
            text.chunk[0] := 0X
7693 akron1 61
        END;
7696 akron1 62
        text.peak := text.chunk[0]
7597 akron1 63
    END
64
END load;
65
 
66
 
7693 akron1 67
PROCEDURE next* (text: TEXT);
7597 akron1 68
VAR
69
    c: CHAR;
7693 akron1 70
 
7597 akron1 71
BEGIN
72
    IF text.pos < text.size - 1 THEN
7693 akron1 73
        INC(text.pos);
7696 akron1 74
        text.peak := text.chunk[text.pos]
7597 akron1 75
    ELSE
76
        load(text)
77
    END;
78
 
79
    IF ~text.eof THEN
80
 
7693 akron1 81
        c := text.peak;
7597 akron1 82
 
83
        IF c = CR THEN
84
            INC(text.line);
7693 akron1 85
            text.col := 0;
86
            text.eol := TRUE;
87
            text.CR  := TRUE
7597 akron1 88
        ELSIF c = LF THEN
89
            IF ~text.CR THEN
90
                INC(text.line);
7693 akron1 91
                text.col := 0;
92
                text.eol := TRUE
7597 akron1 93
            ELSE
7693 akron1 94
                text.eol := FALSE
7597 akron1 95
            END;
96
            text.CR := FALSE
9177 akron1 97
        ELSIF c = HT THEN
98
            text.col := text.col + TabSize - text.col MOD TabSize;
99
            text.eol := FALSE;
100
            text.CR  := FALSE
7597 akron1 101
        ELSE
102
            IF text.utf8 THEN
7696 akron1 103
                IF ORD(c) DIV 64 # 2 THEN
7597 akron1 104
                    INC(text.col)
105
                END
106
            ELSE
107
                INC(text.col)
108
            END;
9177 akron1 109
            text.eol := FALSE;
110
            text.CR  := FALSE
7597 akron1 111
        END
112
 
113
    END
114
 
115
END next;
116
 
117
 
118
PROCEDURE init (text: TEXT);
119
BEGIN
120
    IF (text.pos = 0) & (text.size >= 3) THEN
7696 akron1 121
        IF (text.chunk[0] = 0EFX) &
122
           (text.chunk[1] = 0BBX) &
123
           (text.chunk[2] = 0BFX) THEN
7597 akron1 124
            text.pos := 3;
125
            text.utf8 := TRUE
126
        END
127
    END;
128
 
129
    IF text.size = 0 THEN
7696 akron1 130
        text.chunk[0] := 0X;
7597 akron1 131
        text.size := 1;
132
        text.eof := FALSE
133
    END;
134
 
135
    text.line := 1;
7693 akron1 136
    text.col  := 1;
7597 akron1 137
 
7696 akron1 138
    text.peak := text.chunk[text.pos]
7597 akron1 139
END init;
140
 
141
 
7693 akron1 142
PROCEDURE close* (VAR text: TEXT);
7597 akron1 143
BEGIN
7693 akron1 144
    IF text # NIL THEN
145
        IF text.file # NIL THEN
146
            FILES.close(text.file)
147
        END;
7597 akron1 148
 
7693 akron1 149
        C.push(texts, text);
150
        text := NIL
7597 akron1 151
    END
7693 akron1 152
END close;
7597 akron1 153
 
154
 
7693 akron1 155
PROCEDURE open* (name: ARRAY OF CHAR): TEXT;
7597 akron1 156
VAR
7693 akron1 157
    text: TEXT;
7597 akron1 158
    citem: C.ITEM;
159
 
160
BEGIN
161
    citem := C.pop(texts);
162
    IF citem = NIL THEN
163
        NEW(text)
164
    ELSE
165
        text := citem(TEXT)
7693 akron1 166
    END;
7597 akron1 167
 
168
    IF text # NIL THEN
7696 akron1 169
        text.chunk[0] := 0X;
7693 akron1 170
        text.pos  := 0;
171
        text.size := 0;
172
        text.utf8 := FALSE;
173
        text.CR   := FALSE;
174
        text.line := 1;
175
        text.col  := 1;
176
        text.eof  := FALSE;
177
        text.eol  := FALSE;
8097 maxcodehac 178
        text.skip := FALSE;
179
        text.ifc  := 0;
180
        text.elsec := 0;
181
        text._skip[0] := FALSE;
7693 akron1 182
        text.peak := 0X;
183
        text.file := FILES.open(name);
8097 maxcodehac 184
        COPY(name, text.fname);
7597 akron1 185
        IF text.file # NIL THEN
7693 akron1 186
            load(text);
187
            init(text)
188
        ELSE
189
            close(text)
190
        END
7597 akron1 191
    END
192
 
7693 akron1 193
    RETURN text
194
END open;
7597 akron1 195
 
7693 akron1 196
 
9177 akron1 197
PROCEDURE setTabSize* (n: INTEGER);
7597 akron1 198
BEGIN
9177 akron1 199
    IF (0 < n) & (n <= 64) THEN
200
        TabSize := n
201
    ELSE
202
        TabSize := defTabSize
203
    END
204
END setTabSize;
205
 
206
 
207
BEGIN
208
    TabSize := defTabSize;
7597 akron1 209
    texts := C.create()
7983 leency 210
END TEXTDRV.