Subversion Repositories Kolibri OS

Rev

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

  1. (*
  2.     BSD 2-Clause License
  3.  
  4.     Copyright (c) 2018-2021, 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; HT = 9X;
  16.  
  17.     CHUNK = 1024 * 256;
  18.  
  19.     defTabSize* = 4;
  20.  
  21.  
  22. TYPE
  23.  
  24.     TEXT* = POINTER TO RECORD (C.ITEM)
  25.  
  26.         chunk:        ARRAY CHUNK OF CHAR;
  27.         pos, size:    INTEGER;
  28.         file:         FILES.FILE;
  29.         utf8:         BOOLEAN;
  30.         CR:           BOOLEAN;
  31.  
  32.         line*, col*:  INTEGER;
  33.         ifc*:         INTEGER;
  34.         elsec*:       INTEGER;
  35.         eof*:         BOOLEAN;
  36.         eol*:         BOOLEAN;
  37.         skip*:        BOOLEAN;
  38.         peak*:        CHAR;
  39.         _skip*,
  40.         _elsif*,
  41.         _else*:       ARRAY 100 OF BOOLEAN;
  42.         fname*:       ARRAY 2048 OF CHAR
  43.  
  44.     END;
  45.  
  46.  
  47. VAR
  48.  
  49.     texts: C.COLLECTION;
  50.     TabSize: INTEGER;
  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;
  60.             text.chunk[0] := 0X
  61.         END;
  62.         text.peak := text.chunk[0]
  63.     END
  64. END load;
  65.  
  66.  
  67. PROCEDURE next* (text: TEXT);
  68. VAR
  69.     c: CHAR;
  70.  
  71. BEGIN
  72.     IF text.pos < text.size - 1 THEN
  73.         INC(text.pos);
  74.         text.peak := text.chunk[text.pos]
  75.     ELSE
  76.         load(text)
  77.     END;
  78.  
  79.     IF ~text.eof THEN
  80.  
  81.         c := text.peak;
  82.  
  83.         IF c = CR THEN
  84.             INC(text.line);
  85.             text.col := 0;
  86.             text.eol := TRUE;
  87.             text.CR  := TRUE
  88.         ELSIF c = LF THEN
  89.             IF ~text.CR THEN
  90.                 INC(text.line);
  91.                 text.col := 0;
  92.                 text.eol := TRUE
  93.             ELSE
  94.                 text.eol := FALSE
  95.             END;
  96.             text.CR := FALSE
  97.         ELSIF c = HT THEN
  98.             text.col := text.col + TabSize - text.col MOD TabSize;
  99.             text.eol := FALSE;
  100.             text.CR  := FALSE
  101.         ELSE
  102.             IF text.utf8 THEN
  103.                 IF ORD(c) DIV 64 # 2 THEN
  104.                     INC(text.col)
  105.                 END
  106.             ELSE
  107.                 INC(text.col)
  108.             END;
  109.             text.eol := FALSE;
  110.             text.CR  := FALSE
  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
  121.         IF (text.chunk[0] = 0EFX) &
  122.            (text.chunk[1] = 0BBX) &
  123.            (text.chunk[2] = 0BFX) THEN
  124.             text.pos := 3;
  125.             text.utf8 := TRUE
  126.         END
  127.     END;
  128.  
  129.     IF text.size = 0 THEN
  130.         text.chunk[0] := 0X;
  131.         text.size := 1;
  132.         text.eof := FALSE
  133.     END;
  134.  
  135.     text.line := 1;
  136.     text.col  := 1;
  137.  
  138.     text.peak := text.chunk[text.pos]
  139. END init;
  140.  
  141.  
  142. PROCEDURE close* (VAR text: TEXT);
  143. BEGIN
  144.     IF text # NIL THEN
  145.         IF text.file # NIL THEN
  146.             FILES.close(text.file)
  147.         END;
  148.  
  149.         C.push(texts, text);
  150.         text := NIL
  151.     END
  152. END close;
  153.  
  154.  
  155. PROCEDURE open* (name: ARRAY OF CHAR): TEXT;
  156. VAR
  157.     text: TEXT;
  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)
  166.     END;
  167.  
  168.     IF text # NIL THEN
  169.         text.chunk[0] := 0X;
  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;
  178.         text.skip := FALSE;
  179.         text.ifc  := 0;
  180.         text.elsec := 0;
  181.         text._skip[0] := FALSE;
  182.         text.peak := 0X;
  183.         text.file := FILES.open(name);
  184.         COPY(name, text.fname);
  185.         IF text.file # NIL THEN
  186.             load(text);
  187.             init(text)
  188.         ELSE
  189.             close(text)
  190.         END
  191.     END
  192.  
  193.     RETURN text
  194. END open;
  195.  
  196.  
  197. PROCEDURE setTabSize* (n: INTEGER);
  198. BEGIN
  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;
  209.     texts := C.create()
  210. END TEXTDRV.