Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

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