Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  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.