DEADSOFTWARE

cpmake: fix preprocessor selector handling
[cpc.git] / src / generic / Dsw / Mod / Documents.cp
index 12cb6b5338dcbc474be472a3727879b31fac122d..8ebfa3abf46acdc39903eb1fb572d496a7524f9a 100644 (file)
@@ -1,12 +1,15 @@
 MODULE DswDocuments;
 
-  IMPORT Files;
+  IMPORT SYSTEM, Kernel, Files;
 
   (* !!! make better store type and version checking *)
 
   TYPE
     Name = ARRAY 256 OF SHORTCHAR;
 
+    ShortString = POINTER TO ARRAY OF SHORTCHAR;
+    String = POINTER TO ARRAY OF CHAR;
+
     Store = RECORD
       (* type: Name; *)
       next, down, len: INTEGER;
@@ -14,32 +17,104 @@ MODULE DswDocuments;
       isElem: BOOLEAN;
     END;
 
-    Text* = POINTER TO RECORD
-      t*: POINTER TO ARRAY OF CHAR;
+    Model* = POINTER TO ABSTRACT RECORD END;
+
+    Reader* = POINTER TO ABSTRACT RECORD
+      eot*: BOOLEAN;
+      char*: CHAR;
+    END;
+
+    StdModel = POINTER TO RECORD (Model)
+      str: String;
+      len: INTEGER
+    END;
+
+    StdReader = POINTER TO RECORD (Reader)
+      base: StdModel;
+      i: INTEGER
     END;
 
-  PROCEDURE Import* (loc: Files.Locator; IN name: Files.Name; OUT text: Text; OUT res: INTEGER);
+  VAR
+    oldReader: Files.Reader;
+
+  PROCEDURE (m: Model) NewReader* (old: Reader): Reader, NEW, ABSTRACT;
+  PROCEDURE (m: Model) Length* (): INTEGER, NEW, ABSTRACT;
+
+  PROCEDURE (r: Reader) Base* (): Model, NEW, ABSTRACT;
+  PROCEDURE (r: Reader) Pos* (): INTEGER, NEW, ABSTRACT;
+  PROCEDURE (r: Reader) SetPos* (pos: INTEGER), NEW, ABSTRACT;
+  PROCEDURE (r: Reader) Read*, NEW, ABSTRACT;
+  PROCEDURE (r: Reader) ReadPrev*, NEW, ABSTRACT;
+
+  PROCEDURE (m: StdModel) NewReader (old: Reader): StdReader;
+    VAR r: StdReader;
+  BEGIN
+    IF (old # NIL) & (old IS StdReader) THEN r := old(StdReader) ELSE NEW(r) END;
+    r.eot := FALSE; r.char := 0X; r.base := m; r.i := 0;
+    RETURN r
+  END NewReader;
+
+  PROCEDURE (m: StdModel) Length (): INTEGER;
+  BEGIN
+    RETURN m.len
+  END Length;
+
+
+  PROCEDURE (r: StdReader) Base (): StdModel;
+  BEGIN
+    RETURN r.base
+  END Base;
+
+  PROCEDURE (r: StdReader) Pos (): INTEGER;
+  BEGIN
+    RETURN r.i
+  END Pos; 
+
+  PROCEDURE (r: StdReader) SetPos (pos: INTEGER);
+  BEGIN
+    ASSERT(pos >= 0, 20);
+    ASSERT(pos <= r.base.len, 21);
+    r.i := pos
+  END SetPos;
+
+  PROCEDURE (r: StdReader) Read;
+  BEGIN
+    IF r.i < r.base.len THEN
+      r.char := r.base.str[r.i]; r.eot := FALSE; INC(r.i)
+    ELSE
+      r.char := 0X; r.eot := TRUE
+    END
+  END Read;
+
+  PROCEDURE (r: StdReader) ReadPrev;
+  BEGIN
+    IF r.i > 0 THEN
+      DEC(r.i); r.char := r.base.str[r.i]; r.eot := FALSE
+    ELSE
+      r.char := 0X; r.eot := TRUE
+    END
+  END ReadPrev;
+
+
+  PROCEDURE Import* (loc: Files.Locator; IN name: Files.Name; OUT m: Model; OUT res: INTEGER);
     CONST
       docTag = 6F4F4443H; docVersion = 0;
       Step = 256;
-    VAR f: Files.File; r: Files.Reader; tag, version, chid: INTEGER; s: Store;
+    VAR f: Files.File; r: Files.Reader; tag, version, chid: INTEGER; s: Store; text: StdModel;
 
     PROCEDURE AddChar (ch: CHAR);
-      VAR i, len: INTEGER; t: POINTER TO ARRAY OF CHAR;
+      VAR i, len: INTEGER; t: String;
     BEGIN
       IF text = NIL THEN
-        NEW(text); NEW(text.t, Step); chid := 0
+        NEW(text); NEW(text.str, Step); chid := 0
       END;
-      len := LEN(text.t);
+      len := LEN(text.str);
       IF chid + 1 >= len THEN
-        NEW(t, len + Step);
-        FOR i := 0 TO len - 1 DO
-          t[i] := text.t[i]
-        END;
-        text.t := t
+        NEW(t, len + Step); t^ := text.str$; text.str := t;
       END;
-      text.t[chid] := ch; INC(chid);
-      text.t[chid] := 0X;
+      text.str[chid] := ch; INC(chid);
+      text.str[chid] := 0X;
+      text.len := chid
     END AddChar;
 
     PROCEDURE ReadSChar (OUT x: SHORTCHAR);
@@ -137,6 +212,7 @@ MODULE DswDocuments;
           END;
           r.ReadByte(ano)
         END;
+        m := text;
         res := 0 (* ok *)
       ELSE
         res := 4 (* unsupported text model version *)
@@ -202,7 +278,7 @@ MODULE DswDocuments;
   BEGIN
     ASSERT(loc # NIL, 20);
     ASSERT(name # "", 21);
-    text := NIL;
+    m := NIL; res := 0;
     f := Files.dir.Old(loc, name, Files.shared);
     IF f # NIL THEN
       IF f.Length() > 8 THEN (* !!! calculate minimal document size *)
@@ -230,4 +306,28 @@ MODULE DswDocuments;
     END
   END Import;
 
+  PROCEDURE Open* (loc: Files.Locator; IN name: Files.Name; OUT m: Model; OUT res: INTEGER);
+    VAR f: Files.File; r: Files.Reader; len: INTEGER; s: ShortString; l: String; text: StdModel;
+  BEGIN
+    m := NIL; res := 0;
+    Import(loc, name, m, res);
+    IF res = 2 THEN
+      f := Files.dir.Old(loc, name, Files.shared);
+      IF f # NIL THEN
+        len := f.Length();
+        r := f.NewReader(oldReader); oldReader := r; r.SetPos(0);
+        NEW(s, len + 1); r.ReadBytes(SYSTEM.THISARRAY(SYSTEM.ADR(s[0]), len + 1), 0, len);
+        NEW(l, len + 1); Kernel.Utf8ToString(s, l, res);
+        IF res = 0 THEN
+          NEW(text); text.str := l; text.len := LEN(text.str$); m := text; res := 0 (* ok *)
+        ELSE
+          res := 5 (* broken encoding *)
+        END;
+        f.Close
+      ELSE
+        res := 1 (* unable to open *)
+      END
+    END
+  END Open;
+
 END DswDocuments.