home *** CD-ROM | disk | FTP | other *** search
- (***************************************************************************
-
- $RCSfile: Texts.mod $
- Description: A port of the Project Oberon Texts module
-
- Created by: J. Gutknecht
- Ported by: fjc (Frank Copeland)
- $Revision: 1.6 $
- $Author: fjc $
- $Date: 1995/01/26 00:48:34 $
-
- Copyright © 1990-1993, ETH Zuerich
- Copyright © 1994, Frank Copeland.
- This file is part of the Oberon-A Library.
- See Oberon-A.doc for conditions of use and distribution.
-
- Log entries are at the end of the file.
-
- ***************************************************************************)
-
- <* STANDARD- *> <* MAIN- *>
-
- MODULE Texts;
-
- IMPORT Kernel, Files, Fonts, Reals;
-
- CONST
-
- (* symbol classes *)
-
- Inval * = 0; (* invalid symbol *)
- Name * = 1; (* name s (length len) *)
- String * = 2; (* literal string s (length len) *)
- Int * = 3; (* integer i (decimal or hexadecimal) *)
- Real * = 4; (* real number x *)
- LongReal * = 5; (* long real number y *)
- Char * = 6; (* special character c *)
-
- TAB = 9X; CR = 0DX; maxD = 9;
- LF = 0AX; (* Amiga end-of-line character *)
-
- (* TextBlock = TextBlock off run {run} 0 len {AsciiCode}.
- run = fnt [name] col voff len. *)
-
- TextBlockId = 1FFH;
-
- replace * = 0; insert * = 1; delete * = 2; (* op-codes *)
-
- TYPE
-
- Piece = POINTER TO PieceDesc;
- PieceDesc = RECORD
- f : Files.File;
- off : LONGINT;
- len : LONGINT;
- fnt : Fonts.Font;
- col : SHORTINT;
- voff : SHORTINT;
- prev,
- next : Piece
- END; (* PieceDesc *)
-
- Text * = POINTER TO TextDesc;
-
- Notifier * = PROCEDURE (T : Text; op : INTEGER; beg, end : LONGINT);
-
- TextDesc * = RECORD
- len * : LONGINT;
- notify * : Notifier;
- trailer : Piece;
- org : LONGINT; (* cache *)
- pce : Piece;
- f : Files.File (* Holds handle for file opened by Open(). *)
- END; (* TextDesc *)
-
- Reader * = RECORD (Files.Rider)
- eot * : BOOLEAN;
- fnt * : Fonts.Font;
- col * : SHORTINT;
- voff * : SHORTINT;
- ref : Piece;
- org : LONGINT;
- off : LONGINT
- END; (* Reader *)
-
- Scanner * = RECORD (Reader)
- nextCh * : CHAR;
- line * : INTEGER;
- class * : INTEGER;
- i * : LONGINT;
- x * : REAL;
- y * : LONGREAL;
- c * : CHAR;
- len * : SHORTINT;
- s * : ARRAY 32 OF CHAR
- END; (* Scanner *)
-
- Buffer * = POINTER TO BufDesc;
- BufDesc * = RECORD
- len * : LONGINT;
- header,
- last : Piece
- END; (* BufDesc *)
-
- Writer * = RECORD (Files.Rider)
- buf * : Buffer;
- fnt * : Fonts.Font;
- col * : SHORTINT;
- voff * : SHORTINT
- END; (* Writer *)
-
- VAR
- W : Writer; WFile : Files.File; DelBuf : Buffer;
-
- (*------------------------------------*)
- PROCEDURE ReadName ( VAR R : Files.Rider; VAR name : ARRAY OF CHAR );
-
- VAR i : INTEGER; ch : CHAR;
-
- BEGIN (* ReadName *)
- i := 0; Files.Read (R, ch); IF ch = LF THEN ch := CR END;
- WHILE ch # 0X DO
- name [i] := ch; INC (i); Files.Read (R, ch);
- IF ch = LF THEN ch := CR END
- END; (* WHILE *)
- name [i] := 0X
- END ReadName;
-
- (*------------------------------------*)
- PROCEDURE WriteName ( VAR W : Files.Rider; VAR name : ARRAY OF CHAR );
-
- VAR i : INTEGER; ch : CHAR;
-
- BEGIN (* WriteName *)
- i := 0; ch := name [i];
- WHILE ch # 0X DO
- Files.Write (W, ch); INC (i); ch := name [i]
- END; (* WHILE *)
- Files.Write (W, 0X)
- END WriteName;
-
- (*------------------------------------*)
- PROCEDURE Load *
- ( T : Text;
- f : Files.File;
- pos : LONGINT;
- VAR len : LONGINT);
-
- VAR
- R : Files.Rider;
- Q, q, p : Piece;
- off : LONGINT;
- N, fnt : SHORTINT;
- FName : ARRAY 32 OF CHAR;
- Dict : ARRAY 32 OF Fonts.Font;
-
- BEGIN (* Load *)
- N := 1;
- NEW (Q);
- Q.f := WFile; Q.off := 0; Q.len := 1; Q.fnt := NIL; Q.col := 0;
- Q.voff := 0; p := Q;
- Files.Set (R, f, pos); Files.ReadBytes (R, off, SIZE (LONGINT));
- LOOP
- Files.Read (R, fnt);
- IF fnt = 0 THEN EXIT END;
- IF fnt = N THEN
- ReadName (R, FName);
- Dict [N] := Fonts.This (FName);
- INC (N)
- END; (* IF *)
- NEW (q);
- q.fnt := Dict [fnt];
- Files.Read (R, q.col);
- Files.Read (R, q.voff);
- Files.ReadBytes (R, q.len, SIZE (LONGINT));
- q.f := f; q.off := off;
- off := off + q.len;
- p.next := q; q.prev := p; p := q
- END; (* LOOP *)
- p.next := Q; Q.prev := p;
- T.trailer := Q; Files.ReadBytes (R, T.len, SIZE (LONGINT));
- T.org := -1; T.pce := T.trailer; (* init cache *)
- len := off - pos
- END Load;
-
- (*------------------------------------*)
- PROCEDURE Open * ( T : Text; name : ARRAY OF CHAR );
-
- VAR
- f : Files.File;
- R : Files.Rider;
- Q, q : Piece;
- id : INTEGER;
- len : LONGINT;
-
- <*$CopyArrays-*>
- BEGIN (* Open *)
- T.f := NIL; f := Files.Old (name);
- IF f # NIL THEN
- Files.Set (R, f, 0); Files.ReadBytes (R, id, SIZE (INTEGER));
- IF id = TextBlockId THEN
- Load (T, f, 2, len)
- ELSE (* Ascii file *)
- len := Files.Length (f);
- NEW (Q);
- Q.fnt := NIL; Q.col := 0; Q.voff := 0; Q.f := WFile;
- Q.off := 0; Q.len := 1;
- NEW (q);
- q.fnt := Fonts.Default; q.col := 1; q.voff := 0; q.f := f;
- q.off := 0; q.len := len;
- Q.next := q; q.prev := Q; q.next := Q; Q.prev := q;
- T.trailer := Q; T.len := len;
- T.org := -1; T.pce := T.trailer (* init cache *)
- END
- ELSE (* create new text *)
- NEW (Q);
- Q.fnt := NIL; Q.col := 0; Q.voff := 0; Q.f := WFile;
- Q.off := 0; Q.len := 1; Q.next := Q; Q.prev := Q;
- T.trailer := Q; T.len := 0;
- T.org := -1; T.pce := T.trailer (* init cache *)
- END;
- T.f := f;
- END Open;
-
- (*------------------------------------*)
- PROCEDURE Close * ( T : Text );
-
- BEGIN (* Close *)
- IF T.f # NIL THEN Files.Close (T.f) END
- END Close;
-
- (*------------------------------------*)
- PROCEDURE OpenBuf * (B : Buffer);
-
- BEGIN (* OpenBuf *)
- NEW (B.header); (* null piece *)
- B.last := B.header; B.len := 0
- END OpenBuf;
-
- (*------------------------------------*)
- PROCEDURE FindPiece
- ( T : Text;
- pos : LONGINT;
- VAR org : LONGINT;
- VAR p : Piece );
-
- VAR n : INTEGER;
-
- BEGIN (* FindPiece *)
- IF pos < T.org THEN T.org := -1; T.pce := T.trailer END;
- org := T.org; p := T.pce; (* from cache *)
- n := 0;
- WHILE pos >= org + p.len DO
- org := org + p.len; p := p.next; INC (n)
- END; (* WHILE *)
- IF n > 50 THEN T.org := org; T.pce := p END;
- END FindPiece;
-
- (*------------------------------------*)
- PROCEDURE SplitPiece ( p : Piece; off : LONGINT; VAR pr : Piece );
-
- VAR q : Piece;
-
- BEGIN (* SplitPiece *)
- IF off > 0 THEN
- NEW (q);
- q.fnt := p.fnt; q.col := p.col; q.voff := p.voff; q.len := p.len - off;
- q.f := p.f; q.off := p.off + off;
- p.len := off;
- q.next := p.next; p.next := q;
- q.prev := p; q.next.prev := q;
- pr := q
- ELSE
- pr := p
- END; (* ELSE *)
- END SplitPiece;
-
- (*------------------------------------*)
- PROCEDURE OpenReader * ( VAR R : Reader; T : Text; pos : LONGINT );
-
- VAR p : Piece; org : LONGINT;
-
- BEGIN (* OpenReader *)
- FindPiece (T, pos, org, p);
- R.ref := p; R.org := org; R.off := pos - org;
- Files.Set (R, R.ref.f, R.ref.off + R.off); R.eot := FALSE;
- END OpenReader;
-
- (*------------------------------------*)
- PROCEDURE Read * ( VAR R : Reader; VAR ch : CHAR );
-
- BEGIN (* Read *)
- Files.Read (R, ch); IF ch = LF THEN ch := CR END;
- R.fnt := R.ref.fnt; R.col := R.ref.col;
- R.voff := R.ref.voff; INC (R.off);
- IF R.off = R.ref.len THEN
- IF R.ref.f = WFile THEN R.eot := TRUE END;
- R.org := R.org + R.off; R.off := 0;
- R.ref := R.ref.next;
- R.org := R.org + R.off; R.off := 0;
- Files.Set (R, R.ref.f, R.ref.off)
- END; (* IF *)
- END Read;
-
- (*------------------------------------*)
- PROCEDURE Pos * ( VAR R : Reader ) : LONGINT;
-
- BEGIN (* Pos *)
- RETURN R.org + R.off
- END Pos;
-
- (*------------------------------------*)
- PROCEDURE Store *
- ( T : Text;
- f : Files.File;
- pos : LONGINT;
- VAR len : LONGINT );
-
- VAR
- p, q : Piece;
- R : Reader; W : Files.Rider;
- off, rlen : LONGINT; id : INTEGER;
- N, n : SHORTINT; ch : CHAR;
- Dict : ARRAY 32 OF Fonts.Name;
-
- BEGIN (* Store *)
- Files.Set (W, f, pos);
- id := TextBlockId; Files.WriteBytes (W, id, SIZE (INTEGER));
- Files.WriteBytes (W, off, SIZE (LONGINT)); (* place holder *)
- N := 1;
- p := T.trailer.next;
- WHILE p # T.trailer DO
- rlen := p.len; q := p.next;
- WHILE
- (q # T.trailer)
- & (q.fnt = p.fnt) & (q.col = p.col) & (q.voff = p.voff)
- DO
- rlen := rlen + q.len; q := q.next;
- END; (* WHILE *)
- Dict [N] := p.fnt.name; n := 1;
- WHILE Dict [n] # p.fnt.name DO INC (n) END;
- Files.Write (W, n);
- IF n = N THEN WriteName (W, p.fnt.name); INC (N) END;
- Files.Write (W, p.col); Files.Write (W, p.voff);
- Files.WriteBytes (W, rlen, SIZE (LONGINT));
- p := q
- END; (* WHILE *)
- Files.Write (W, 0); Files.WriteBytes (W, T.len, SIZE (LONGINT));
- off := Files.Pos (W);
- OpenReader (R, T, 0); Read (R, ch);
- WHILE ~R.eot DO Files.Write (W, ch); Read (R, ch) END;
- Files.Set (W, f, pos + SIZE (INTEGER));
- Files.WriteBytes (W, off, SIZE (LONGINT)); (* fixup *)
- len := off + T.len - pos
- END Store;
-
- (*------------------------------------*)
- PROCEDURE Save * ( T : Text; beg, end : LONGINT; B : Buffer );
-
- VAR
- p, q, qb, qe : Piece;
- org : LONGINT;
-
- BEGIN (* Save *)
- IF end > T.len THEN end := T.len END;
- FindPiece (T, beg, org, p);
- NEW (qb);
- qb^ := p^; qb.len := qb.len - (beg - org);
- qb.off := qb.off + (beg - org);
- qe := qb;
- WHILE end > org + p.len DO
- org := org + p.len; p := p.next;
- NEW (q);
- q^ := p^; qe.next := q; q.prev := qe; qe := q
- END; (* WHILE *)
- qe.next := NIL; qe.len := qe.len - (org + p.len - end);
- B.last.next := qb; qb.prev := B.last; B.last := qe;
- B.len := B.len + (end - beg)
- END Save;
-
- (*------------------------------------*)
- PROCEDURE Copy * ( SB, DB : Buffer );
-
- VAR Q, q, p : Piece;
-
- BEGIN (* Copy *)
- p := SB.header; Q := DB.last;
- WHILE p # SB.last DO
- p := p.next;
- NEW (q);
- q^ := p^; Q.next := q; q.prev := Q; Q := q
- END; (* WHILE *)
- DB.last := Q; DB.len := DB.len + SB.len
- END Copy;
-
- (*------------------------------------*)
- PROCEDURE ChangeLooks *
- ( T : Text;
- beg, end : LONGINT;
- sel : SET;
- fnt : Fonts.Font;
- col, voff : SHORTINT );
-
- VAR
- pb, pe, p : Piece;
- org : LONGINT;
-
- BEGIN (* ChangeLooks *)
- IF end > T.len THEN end := T.len END;
- FindPiece (T, beg, org, p); SplitPiece (p, beg - org, pb);
- FindPiece (T, end, org, p); SplitPiece (p, end - org, pe);
- p := pb;
- REPEAT
- IF 0 IN sel THEN p.fnt := fnt END;
- IF 1 IN sel THEN p.col := col END;
- IF 2 IN sel THEN p.voff := voff END;
- UNTIL p = pe;
- T.notify (T, replace, beg, end)
- END ChangeLooks;
-
- (*------------------------------------*)
- PROCEDURE Insert * ( T : Text; pos : LONGINT; B : Buffer );
-
- VAR
- pl, pr, p, qb, qe : Piece;
- org, end : LONGINT;
-
- BEGIN (* Insert *)
- FindPiece (T, pos, org, p); SplitPiece (p, pos - org, pr);
- IF T.org >= org THEN (* adjust cache *)
- T.org := org - p.prev.len; T.pce := p.prev
- END; (* IF *)
- pl := pr.prev;
- qb := B.header.next;
- IF
- (qb # NIL) & (qb.f = pl.f) & (qb.off = pl.off + pl.len)
- & (qb.fnt = pl.fnt) & (qb.col = pl.col) & (qb.voff = pl.voff)
- THEN
- pl.len := pl.len + qb.len; qb := qb.next
- END; (* IF *)
- IF qb # NIL THEN
- qe := B.last;
- qb.prev := pl; pl.next := qb; qe.next := pr; pr.prev := qe
- END; (* IF *)
- T.len := T.len + B.len; end := pos + B.len;
- B.last := B.header; B.last.next := NIL; B.len := 0;
- T.notify (T, insert, pos, end)
- END Insert;
-
- (*------------------------------------*)
- PROCEDURE Append * ( T : Text; B : Buffer );
-
- BEGIN (* Append *)
- Insert (T, T.len, B)
- END Append;
-
- (*------------------------------------*)
- PROCEDURE Delete * ( T : Text; beg, end : LONGINT );
-
- VAR
- pb, pe, pbr, per : Piece;
- orgb, orge : LONGINT;
-
- BEGIN (* Delete *)
- IF end > T.len THEN end := T.len END;
- FindPiece (T, beg, orgb, pb); SplitPiece (pb, beg - orgb, pbr);
- FindPiece (T, end, orge, pe); SplitPiece (pe, end - orge, per);
- IF T.org >= orgb THEN (* adjust cache *)
- T.org := orgb - pb.prev.len; T.pce := pb.prev
- END; (* IF *)
- DelBuf.header.next := pbr; DelBuf.last := per.prev;
- DelBuf.last.next := NIL; DelBuf.len := end - beg;
- per.prev := pbr.prev;
- pbr.prev.next := per;
- T.len := T.len - DelBuf.len;
- T.notify (T, delete, beg, end)
- END Delete;
-
- (*------------------------------------*)
- PROCEDURE Recall ( VAR B : Buffer ); (* deleted text *)
-
- BEGIN (* Recall *)
- B := DelBuf; NEW (DelBuf); OpenBuf (DelBuf)
- END Recall;
-
- (*------------------------------------*)
- PROCEDURE OpenScanner * ( VAR S : Scanner; T : Text; pos : LONGINT );
-
- BEGIN (* OpenScanner *)
- OpenReader (S, T, pos); S.line := 0; Read (S, S.nextCh)
- END OpenScanner;
-
- (*------------------------------------*)
- PROCEDURE Scan * ( VAR S : Scanner );
-
- CONST
- maxD = 32;
- (* Limits for exponents *)
- MaxNegD = 20; (* LONGREAL : Motorola FFP reals *)
- MaxPosD = 18;
- MaxNegE = 20; (* REAL : Motorola FFP reals *)
- MaxPosE = 18;
-
- VAR
- ch, term : CHAR;
- neg, negE, hex : BOOLEAN;
- i, j, h : SHORTINT;
- e : INTEGER; k : LONGINT;
- x, f : REAL; y, g : LONGREAL;
- d : ARRAY maxD OF CHAR;
-
- (*------------------------------------*)
- PROCEDURE ReadScaleFactor ();
-
- BEGIN (* ReadScaleFactor *)
- Read (S, ch);
- IF ch = "-" THEN
- negE := TRUE; Read (S, ch)
- ELSE
- negE := FALSE; IF ch = "+" THEN Read (S, ch) END;
- END;
- WHILE (ch >= "0") & (ch <= "9") DO
- e := e * 10 + ORD (ch) - 30H; Read (S, ch)
- END; (* WHILE *)
- END ReadScaleFactor;
-
- BEGIN (* Scan *)
- ch := S.nextCh; i := 0;
- LOOP
- IF (ch = CR) OR (ch = LF) THEN INC (S.line)
- ELSIF (ch # " ") & (ch # TAB) THEN EXIT
- END;
- Read (S, ch)
- END; (* LOOP *)
- IF (CAP (ch) >= "A") & (CAP (ch) <= "Z") THEN (* name *)
- REPEAT
- S.s [i] := ch; INC (i); Read (S, ch)
- UNTIL
- (CAP (ch) > "Z")
- OR (CAP (ch) < "A") & (ch > "9")
- OR (ch < "0") & (ch # ".")
- OR (i = 31);
- S.s [i] := 0X; S.len := i; S.class := Name
- ELSIF ch = 22X THEN (* literal string *)
- Read (S, ch);
- WHILE (ch # 22X) & (ch >= " ") & (i # 31) DO
- S.s [i] := ch; INC (i); Read (S, ch)
- END; (* WHILE *)
- S.s [i] := 0X; S.len := i + 1; S.class := String
- ELSE
- IF ch = "-" THEN neg := TRUE; Read (S, ch) ELSE neg := FALSE END;
- IF (ch >= "0") & (ch <= "9") THEN (* number *)
- hex := FALSE; j := 0;
- LOOP
- d [i] := ch; INC (i); Read (S, ch);
- IF ch < "0" THEN EXIT END;
- IF "9" < ch THEN
- IF ("A" <= ch) & (ch <= "F") THEN
- hex := TRUE; ch := CHR (ORD (ch) - 7)
- ELSIF ("a" <= ch) & (ch <= "f") THEN
- hex := TRUE; ch := CHR (ORD (ch) - 27H)
- ELSE
- EXIT
- END; (* ELSE *)
- END; (* IF *)
- END; (* LOOP *)
- IF ch = "H" THEN (* hex number *)
- Read (S, ch); S.class := Int;
- IF i - j > 8 THEN j := i - 8 END;
- k := ORD (d [j]) - 30H; INC (j);
- IF (i - j = 7) & (k >= 8) THEN DEC (k, 16) END;
- WHILE j < i DO k := k * 10H + (ORD (d [j]) - 30H); INC (j) END;
- IF neg THEN S.i := -k ELSE S.i := k END;
- ELSIF ch = "." THEN (* read real *)
- Read (S, ch); h := i;
- WHILE ("0" <= ch) & (ch <= "9") DO
- d [i] := ch; INC (i); Read (S, ch)
- END;
- IF ch = "D" THEN
- e := 0; y := 0.0; g := 1.0;
- REPEAT y := y * 10.0 + (ORD (d [j]) - 30H); INC (j) UNTIL j = h;
- WHILE j < i DO
- g := g / 10.0; y := (ORD (d [j]) - 30H) * g + y; INC (j)
- END;
- ReadScaleFactor;
- IF negE THEN
- IF e <= MaxNegD THEN y := y / Reals.TenL (e) ELSE y := 0.0 END
- ELSIF e > 0 THEN
- IF e <= MaxPosD THEN y := y * Reals.TenL (e) ELSE HALT (40) END
- END; (* IF *)
- IF neg THEN y := -y END;
- S.class := LongReal; S.y := y
- ELSE
- e := 0; x := 0.0; f := 1.0;
- REPEAT x := x * 10.0 + (ORD (d [j]) - 30H); INC (j) UNTIL j = h;
- WHILE j < i DO
- f := f / 10.0; x := (ORD (d [j]) - 30H) * f + x; INC (j)
- END;
- IF ch = "E" THEN ReadScaleFactor END;
- IF negE THEN
- IF e <= MaxNegE THEN x := x / Reals.Ten (e) ELSE x := 0.0 END
- ELSIF e > 0 THEN
- IF e <= MaxPosE THEN x := x * Reals.Ten (e) ELSE HALT (40) END
- END; (* IF *)
- IF neg THEN x := -x END;
- S.class := Real; S.x := x
- END; (* ELSE *)
- IF hex THEN S.class := Inval END
- ELSE (* decimal integer *)
- S.class := Int; k := 0;
- REPEAT k := k * 10 + (ORD (d [j]) - 30H); INC (j) UNTIL j = i;
- IF neg THEN S.i := -k ELSE S.i := k END;
- IF hex THEN S.class := Inval ELSE S.class := Int END
- END; (* ELSE *)
- ELSE
- S.class := Char;
- IF neg THEN S.c := "-" ELSE S.c := ch; Read (S, ch) END
- END; (* ELSE *)
- END; (* ELSE *)
- S.nextCh := ch
- END Scan;
-
- (*------------------------------------*)
- PROCEDURE OpenWriter * ( VAR W : Writer );
-
- BEGIN (* OpenWriter *)
- NEW (W.buf); OpenBuf (W.buf); W.fnt := Fonts.Default; W.col := 1;
- W.voff := 0; Files.Set (W, Files.New (""), 0)
- END OpenWriter;
-
- (*------------------------------------*)
- PROCEDURE CloseWriter * ( VAR W : Writer );
-
- BEGIN (* CloseWriter *)
- Files.Purge (Files.Base (W))
- END CloseWriter;
-
- (*------------------------------------*)
- PROCEDURE SetFont * ( VAR W : Writer; fnt : Fonts.Font );
-
- BEGIN (* SetFont *)
- W.fnt := fnt
- END SetFont;
-
- (*------------------------------------*)
- PROCEDURE SetColor * ( VAR W : Writer; col : SHORTINT );
-
- BEGIN (* SetColor *)
- W.col := col
- END SetColor;
-
- (*------------------------------------*)
- PROCEDURE SetOffset * ( VAR W : Writer; voff : SHORTINT );
-
- BEGIN (* SetOffset *)
- W.voff := voff
- END SetOffset;
-
- (*------------------------------------*)
- PROCEDURE Write * ( VAR W : Writer; ch : CHAR );
-
- VAR p : Piece;
-
- BEGIN (* Write *)
- IF
- (W.buf.last.fnt # W.fnt) OR (W.buf.last.col # W.col)
- OR (W.buf.last.voff # W.voff)
- THEN
- NEW (p);
- p.f := Files.Base (W); p.off := Files.Pos (W); p.len := 0;
- p.fnt := W.fnt; p.col := W.col; p.voff := W.voff;
- p.next := NIL; W.buf.last.next := p;
- p.prev := W.buf.last; W.buf.last := p
- END; (* IF *)
- Files.Write (W, ch);
- INC (W.buf.last.len); INC (W.buf.len)
- END Write;
-
- (*------------------------------------*)
- PROCEDURE WriteLn * ( VAR W : Writer );
-
- BEGIN (* WriteLn *)
- Write (W, CR)
- END WriteLn;
-
- (*------------------------------------*)
- PROCEDURE WriteString * ( VAR W : Writer; s : ARRAY OF CHAR );
-
- VAR i : LONGINT;
-
- <*$CopyArrays-*>
- BEGIN (* WriteString *)
- i := 0; WHILE s [i] # 0X DO Write (W, s [i]); INC (i) END
- END WriteString;
-
- (*------------------------------------*)
- PROCEDURE WriteInt * ( VAR W : Writer; x, n : LONGINT );
-
- VAR i : INTEGER; x0 : LONGINT; a : ARRAY 11 OF CHAR;
-
- BEGIN (* WriteInt *)
- i := 0;
- IF x < 0 THEN
- IF x = MIN (LONGINT) THEN
- WriteString (W, " -2147483648"); RETURN
- ELSE
- DEC (n); x0 := -x
- END; (* ELSE *)
- ELSE
- x0 := x
- END; (* ELSE *)
- REPEAT
- a [i] := CHR (x0 MOD 10 + 30H); x0 := x0 DIV 10; INC (i)
- UNTIL x0 = 0;
- WHILE n > i DO Write (W, " "); DEC (n) END;
- IF x < 0 THEN Write (W, "-") END;
- REPEAT DEC (i); Write (W, a [i]) UNTIL i = 0;
- END WriteInt;
-
- (*------------------------------------*)
- PROCEDURE WriteHex * ( VAR W : Writer; x : LONGINT );
-
- VAR i : INTEGER; y : LONGINT; a : ARRAY 10 OF CHAR;
-
- BEGIN (* WriteHex *)
- i := 0; Write (W, " ");
- REPEAT
- y := x MOD 10H;
- IF y < 10 THEN a [i] := CHR (y + 30H) ELSE a [i] := CHR (y + 37H) END;
- x := x DIV 10H; INC (i)
- UNTIL i = 8;
- REPEAT DEC (i); Write (W, a [i]) UNTIL i = 0
- END WriteHex;
-
- (*------------------------------------*)
- PROCEDURE WriteReal * ( VAR W : Writer; x : REAL; n : INTEGER );
-
- VAR e : INTEGER; x0 : REAL; d : ARRAY maxD OF CHAR;
-
- BEGIN (* WriteReal *)
- (*
- * This implementation uses Motorola FFP format reals instead of IEEE
- * single-precision reals. The Project Oberon code has been modified to
- * remove the special-case handling of unnormal and NaN values and assume
- * 7-bit exponents instead of 8-bit.
- *)
- e := Reals.Expo (x);
- IF n <= 9 THEN n := 3 ELSE DEC (n, 6) END;
- REPEAT Write (W, " "); DEC (n) UNTIL n <= 8;
- (* there are 2 < n <= 8 digits to be written *)
- IF x < 0.0 THEN Write (W, "-"); x := -x ELSE Write (W, " ") END;
- e := (e - 64) * 77 DIV 256;
- IF e >= 0 THEN x := x / Reals.Ten (e) ELSE x := Reals.Ten (-e) * x END;
- IF x >= 10.0 THEN x := 0.1 * x; INC (e) END;
- x0 := Reals.Ten (n - 1); x := x0 * x + 0.5;
- IF x >= 10.0 * x0 THEN x := x * 0.1; INC (e) END;
- Reals.Convert (x, n, d);
- DEC (n); Write (W, d [n]); Write (W, ".");
- REPEAT DEC (n); Write (W, d [n]) UNTIL n = 0;
- Write (W, "E");
- IF e < 0 THEN Write (W, "-"); e := -e ELSE Write (W, "+") END;
- Write (W, CHR (e DIV 10 + 30H)); Write (W, CHR (e MOD 10 + 30H))
- END WriteReal;
-
- (*------------------------------------*)
- PROCEDURE WriteRealFix * ( VAR W : Writer; x : REAL; n, k : INTEGER );
-
- VAR e, i : INTEGER; sign : CHAR; x0 : REAL; d : ARRAY maxD OF CHAR;
-
- (*------------------------------------*)
- PROCEDURE seq ( ch : CHAR; n : LONGINT );
-
- BEGIN (* seq *)
- WHILE n > 0 DO Write (W, ch); DEC (n) END
- END seq;
-
- (*------------------------------------*)
- PROCEDURE dig (n : INTEGER);
-
- BEGIN (* dig *)
- WHILE n > 0 DO
- DEC (i); Write (W, d [i]); DEC (n)
- END;
- END dig;
-
- BEGIN (* WriteRealFix *)
- (*
- * This implementation uses Motorola FFP format reals instead of IEEE
- * single-precision reals. The Project Oberon code has been modified to
- * remove the special-case handling of unnormal and NaN values and assume
- * 7-bit exponents instead of 8-bit.
- *)
- IF k < 0 THEN k := 0 END;
- e := (Reals.Expo (x) - 64) * 77 DIV 256;
- IF x < 0.0 THEN sign := "-"; x := -x ELSE sign := " " END;
- IF e >= 0 THEN (* x >= 1.0, 77/256 = log 2 *) x := x / Reals.Ten (e)
- ELSE (* x < 1.0 *) x := Reals.Ten (-e) * x END;
- IF x >= 10.0 THEN x := 0.1 * x; INC (e) END;
- (* 1 <= x < 10 *)
- IF k + e >= maxD - 1 THEN k := maxD - 1 - e
- ELSIF k + e < 0 THEN k := -e; x := 0.0
- END;
- x0 := Reals.Ten (k + e); x := x0 * x + 0.5;
- IF x >= 10.0 * x0 THEN INC (e) END;
- (* e = no. of digits before decimal point *)
- INC (e); i := k + e; Reals.Convert (x, i, d);
- IF e > 0 THEN
- seq (" ", n - e - k - 2); Write (W, sign); dig (e); Write (W, ".");
- dig (k)
- ELSE
- seq (" ", n - k - 3); Write (W, sign); Write (W, "0"); Write (W, ".");
- seq ("0", -e); dig (k + e)
- END; (* ELSE *)
- END WriteRealFix;
-
- (*------------------------------------*)
- PROCEDURE WriteRealHex * ( VAR W : Writer; x : REAL );
-
- VAR i : INTEGER; d : ARRAY 8 OF CHAR;
-
- BEGIN (* WriteRealHex *)
- Reals.ConvertH (x, d); i := 0;
- REPEAT Write (W, d [i]); INC (i) UNTIL i = 8
- END WriteRealHex;
-
- (*------------------------------------*)
- PROCEDURE WriteLongReal * ( VAR W : Writer; x : LONGREAL; n : INTEGER );
-
- BEGIN (* WriteLongReal *)
- (*
- * In this implementation, LONGREAL and REAL types are the same, so this
- * procedure is implemented as a call to WriteReal ().
- *)
- WriteReal (W, SHORT (x), n)
- END WriteLongReal;
-
- (*------------------------------------*)
- PROCEDURE WriteLongRealHex * ( VAR W : Writer; x : LONGREAL );
-
- BEGIN (* WriteLongRealHex *)
- (*
- * In this implementation, LONGREAL and REAL types are the same, so this
- * procedure is implemented as a call to WriteRealHex ().
- *)
- WriteRealHex (W, SHORT (x))
- END WriteLongRealHex;
-
- (*------------------------------------*)
- PROCEDURE WriteDate * ( VAR W : Writer; t, d : LONGINT );
-
- (*------------------------------------*)
- PROCEDURE WritePair (ch : CHAR; x : LONGINT);
-
- BEGIN (* WritePair *)
- Write (W, ch);
- Write (W, CHR (x DIV 10 + 30H)); Write (W, CHR (x MOD 10 + 30H))
- END WritePair;
-
- BEGIN (* WriteDate *)
- WritePair (" ", d MOD 32); WritePair (".", d DIV 32 MOD 16);
- WritePair (".", d DIV 512 MOD 128);
- WritePair (" ", t DIV 4096 MOD 32); WritePair (":", t DIV 64 MOD 64);
- WritePair (":", t MOD 64)
- END WriteDate;
-
- (*------------------------------------*)
- PROCEDURE * Cleanup (VAR rc : LONGINT);
-
- BEGIN (* Cleanup *)
- CloseWriter (W);
- END Cleanup;
-
- BEGIN (* Texts *)
- NEW (DelBuf); OpenBuf (DelBuf);
- OpenWriter (W); Write (W, 0X);
- WFile := Files.Base (W);
- Kernel.SetCleanup (Cleanup)
- END Texts.
-
- (***************************************************************************
-
- $Log: Texts.mod $
- Revision 1.6 1995/01/26 00:48:34 fjc
- - Release 1.5
-
- Revision 1.5 1994/11/11 17:00:38 fjc
- - Uses new external code interface.
-
- Revision 1.5 1994/11/11 17:00:38 fjc
- - Uses new external code interface.
-
- Revision 1.4 1994/09/18 21:25:47 fjc
- - Converted switches to pragmas/options
-
- Revision 1.4 1994/09/18 21:25:47 fjc
- - Converted switches to pragmas/options
-
- Revision 1.3 1994/08/08 16:42:00 fjc
- Release 1.4
-
- Revision 1.2 1994/05/12 20:45:18 fjc
- - Prepared for release
-
- # Revision 1.1 1994/01/15 21:39:12 fjc
- # Start of revision control
- #
- ***************************************************************************)
-
-
-