<> <> <> <<>> <> <> DIRECTORY FS USING [StreamOpen], IO USING [STREAM], IPBasic USING [ImagerVariable, Op, StrokeEnd], IPWriter USING [Close, Create, PutHeader, PutIdentifier, PutInt, PutOp, PutReal, PutString, Writer], IPOutput USING [Master, MasterRep], Rope USING [Index, ROPE, Size, Substr]; IPOutputImpl: CEDAR PROGRAM IMPORTS FS, IPWriter, Rope EXPORTS IPOutput ~ BEGIN ROPE: TYPE ~ Rope.ROPE; STREAM: TYPE ~ IO.STREAM; Writer: TYPE ~ IPWriter.Writer; Op: TYPE ~ IPBasic.Op; Master: TYPE ~ IPOutput.Master; Error: PUBLIC ERROR[explanation: ROPE] ~ CODE; OpenMaster: PUBLIC PROC[fileName: ROPE, encoding: ATOM _ NIL] RETURNS[Master] ~ { stream: STREAM ~ FS.StreamOpen[fileName, $create]; RETURN[OpenMasterFromStream[stream, encoding]]; }; OpenMasterFromStream: PUBLIC PROC[stream: STREAM, encoding: ATOM _ NIL] RETURNS[Master] ~ { writer: IPWriter.Writer ~ IPWriter.Create[stream, IF encoding=NIL THEN $Xerox ELSE encoding]; writer.PutHeader[]; writer.PutOp[$beginBlock]; RETURN[NEW[IPOutput.MasterRep _ [writer: writer, state: new, page: 0]]]; }; BeginPreamble: PUBLIC PROC[self: Master] ~ { IF self.state=new THEN { self.writer.PutOp[$beginBody]; self.state _ begin; } ELSE ERROR Error["BeginPreamble out of sequence."]; }; EndPreamble: PUBLIC PROC[self: Master] ~ { IF self.state=begin AND self.page=0 THEN { self.writer.PutOp[$endBody]; self.state _ end; } ELSE ERROR Error["EndPreamble out of sequence."]; }; BeginPage: PUBLIC PROC[self: Master] ~ { IF self.state=end THEN { self.writer.PutOp[$beginBody]; self.state _ begin; self.page _ self.page+1; } ELSE ERROR Error["BeginPage out of sequence."]; }; EndPage: PUBLIC PROC[self: Master] ~ { IF self.state=begin AND self.page>0 THEN { self.writer.PutOp[$endBody]; self.state _ end; } ELSE ERROR Error["EndPage out of sequence."]; }; Close: PUBLIC PROC[self: Master] ~ { IF self.state=end AND self.page>0 THEN { self.writer.PutOp[$endBlock]; self.writer.Close[]; self.state _ closed; } ELSE ERROR Error["Close out of sequence."]; }; PutOp: PUBLIC PROC[self: Master, op: Op] ~ { self.writer.PutOp[op]; }; PutInt: PUBLIC PROC[self: Master, int: INT] ~ { self.writer.PutInt[int]; }; PutReal: PUBLIC PROC[self: Master, real: REAL] ~ { self.writer.PutReal[real]; }; PutIdentifier: PUBLIC PROC[self: Master, identifier: ROPE] ~ { self.writer.PutIdentifier[identifier]; }; PutName: PUBLIC PROC[self: Master, name: ROPE] ~ { size: INT ~ name.Size[]; start: INT _ 0; n: INT _ 0; DO stop: INT ~ name.Index[pos1: start, s2: "/"]; id: ROPE ~ name.Substr[start: start, len: stop-start]; self.writer.PutIdentifier[id]; n _ n+1; IF stop