(* Copyright (C) 1989, Digital Equipment Corporation *) (* All rights reserved. *) (* See the file COPYRIGHT for a full description. *) (* Modula-2+ version created by Benli Pierce and John Ellis. *) (* Ported to Modula-3 by S.Harrison and J.Stolfi on May 1990. *) (* Last modified on Sun Mar 1 16:14:29 PST 1992 by meehan *) (* modified on Wed Nov 20 18:10:51 PST 1991 by stolfi *) MODULE FWr; (* Note: This implementation is not an entirely correct use of WrClass. To be fixed. *) IMPORT Formatter, Wr, WrClass, Thread; CONST FWrBufferLength = 1024; REVEAL T = Wr.T BRANDED OBJECT formatter: Formatter.T; underlyingWr: Wr.T; lineWidth: INTEGER; END; EXCEPTION FWrIsClosed; (* Raised when client attempts to use a FWr.T that has been closed *) PROCEDURE New( underlyingWr: Wr.T; lineWidth: CARDINAL := 75; ): Wr.T = VAR wr: Wr.T; BEGIN wr := NEW (T, st := 0, lo := 0, cur := 0, hi := FWrBufferLength, buff := NEW(REF ARRAY OF CHAR, FWrBufferLength), closed := FALSE, seekable := FALSE, buffered := TRUE, seek := SeekMethod, flush := FlushMethod, close := Close, formatter := Formatter.New (underlyingWr, lineWidth), underlyingWr := underlyingWr, lineWidth := lineWidth ); RETURN wr; END New; PROCEDURE UnderlyingWr (fwr: T): Wr.T = BEGIN RETURN fwr.underlyingWr; END UnderlyingWr; (**********************************************************) (* WRITER METHODS *) (**********************************************************) PROCEDURE SeekMethod(wr: T; n: CARDINAL) RAISES {Wr.Failure, Thread.Alerted} = BEGIN <* ASSERT n = wr.cur *> WITH b = wr.buff, fmt = wr.formatter DO IF fmt # NIL THEN FOR i := 0 TO wr.cur - wr.lo - 1 DO Formatter.PutChar(fmt, b[i]) END; wr.lo := wr.cur; wr.hi := wr.lo + NUMBER(b^) END END END SeekMethod; PROCEDURE FlushMethod(wr: T) RAISES {Wr.Failure, Thread.Alerted} = BEGIN IF wr.lo < wr.cur THEN SeekMethod(wr, wr.cur); (*!!! Formatter.Flush(wr.formatter) *) END END FlushMethod; PROCEDURE Close(wr: T) RAISES {Wr.Failure, Thread.Alerted} = BEGIN (* Assumes wr.flush has been called already *) IF wr.formatter # NIL THEN Formatter.Close(wr.formatter); wr.formatter := NIL; wr.underlyingWr := NIL END; END Close; (**********************************************************) (* FORMATTING OPERATIONS *) (**********************************************************) PROCEDURE Flush(fwr: T) RAISES {Wr.Failure, Thread.Alerted} = <* FATAL FWrIsClosed *> BEGIN IF fwr.formatter = NIL THEN RAISE FWrIsClosed END; Wr.Flush(fwr); Formatter.Flush(fwr.formatter) END Flush; PROCEDURE Group(fwr: T) RAISES {Wr.Failure, Thread.Alerted} = <* FATAL FWrIsClosed *> BEGIN IF fwr.formatter = NIL THEN RAISE FWrIsClosed END; Wr.Flush(fwr); Formatter.Group(fwr.formatter) END Group; PROCEDURE Begin(fwr: T; offset := 0; width: CARDINAL := LAST (CARDINAL)) RAISES {Wr.Failure, Thread.Alerted} = <* FATAL FWrIsClosed *> BEGIN IF fwr.formatter = NIL THEN RAISE FWrIsClosed END; Wr.Flush(fwr); Formatter.Begin(fwr.formatter, offset, width) END Begin; PROCEDURE End(fwr: T) RAISES {Wr.Failure, Thread.Alerted} = <* FATAL FWrIsClosed *> BEGIN IF fwr.formatter = NIL THEN RAISE FWrIsClosed END; Wr.Flush(fwr); Formatter.End(fwr.formatter) END End; PROCEDURE Break(fwr: T; offset := 0; type := BreakType.OptimalBreak; freshLine := TRUE) RAISES {Wr.Failure, Thread.Alerted} = <* FATAL FWrIsClosed *> BEGIN IF fwr.formatter = NIL THEN RAISE FWrIsClosed END; Wr.Flush(fwr); Formatter.Break(fwr.formatter, offset, type, freshLine) END Break; PROCEDURE UnitedBreak(fwr: T; offset := 0; freshLine := TRUE) RAISES {Wr.Failure, Thread.Alerted} = <* FATAL FWrIsClosed *> BEGIN IF fwr.formatter = NIL THEN RAISE FWrIsClosed END; Wr.Flush(fwr); Formatter.UnitedBreak(fwr.formatter, offset, freshLine) END UnitedBreak; PROCEDURE PartialBreak (fwr: T; offset := 0; freshLine := TRUE) RAISES {Wr.Failure, Thread.Alerted} = <* FATAL FWrIsClosed *> BEGIN IF fwr.formatter = NIL THEN RAISE FWrIsClosed END; Wr.Flush(fwr); Formatter.PartialBreak(fwr.formatter, offset, freshLine) END PartialBreak; PROCEDURE NewLine (fwr: T; offset := 0; freshLine := TRUE) RAISES {Wr.Failure, Thread.Alerted} = <* FATAL FWrIsClosed *> BEGIN IF fwr.formatter = NIL THEN RAISE FWrIsClosed END; Wr.Flush(fwr); Formatter.NewLine(fwr.formatter, offset, freshLine) END NewLine; PROCEDURE Align ( fwr: T; columns: CARDINAL; tryOneLine: BOOLEAN := TRUE; offset: INTEGER := 0; alignPred: Formatter.AlignPred := NIL; ) RAISES {Wr.Failure, Thread.Alerted} = <* FATAL FWrIsClosed *> BEGIN IF fwr.formatter = NIL THEN RAISE FWrIsClosed END; Wr.Flush(fwr); Formatter.Align( fwr.formatter, columns, tryOneLine, offset, alignPred ); END Align; PROCEDURE NoAlign (fwr: T) RAISES {Wr.Failure, Thread.Alerted} = <* FATAL FWrIsClosed *> BEGIN IF fwr.formatter = NIL THEN RAISE FWrIsClosed END; Wr.Flush(fwr); Formatter.NoAlign(fwr.formatter) END NoAlign; PROCEDURE Col (fwr: T; column: CARDINAL; relative := FALSE; space := 0) RAISES {Wr.Failure, Thread.Alerted} = <* FATAL FWrIsClosed *> BEGIN IF fwr.formatter = NIL THEN RAISE FWrIsClosed END; Wr.Flush(fwr); Formatter.Col(fwr.formatter, column, relative, space) END Col; BEGIN END FWr.