<> <<>> <> <> <> <> <<>> DIRECTORY FS USING [StreamOpen], Imager USING [Context, Create], IO USING [STREAM], IPBasic USING [ImagerVariable, Op, StrokeEnd], IPWriter USING [Close, Create, PutHeader, PutIdentifier, PutInt, PutOp, PutReal, PutString, Writer], IPOutput USING [], Rope USING [Index, ROPE, Size, Substr]; IPOutputImpl: CEDAR PROGRAM IMPORTS FS, Imager, IPWriter, Rope EXPORTS IPOutput ~ BEGIN ROPE: TYPE ~ Rope.ROPE; STREAM: TYPE ~ IO.STREAM; Writer: TYPE ~ IPWriter.Writer; Op: TYPE ~ IPBasic.Op; Master: TYPE ~ REF MasterRep; MasterRep: PUBLIC TYPE ~ RECORD[ writer: Writer, page: INT _ 0, stack: LIST OF Op _ NIL, imager: Imager.Context _ NIL ]; Error: PUBLIC ERROR[explanation: ROPE] ~ CODE; Narrow: PUBLIC PROC[x: REF] RETURNS[Master] ~ { RETURN[NARROW[x]] }; BeginMaster: PUBLIC PROC[fileName: ROPE, encoding: ATOM _ NIL] RETURNS[Master] ~ { stream: STREAM ~ FS.StreamOpen[fileName, $create]; RETURN[BeginMasterFromStream[stream, encoding]]; }; BeginMasterFromStream: PUBLIC PROC[stream: STREAM, encoding: ATOM _ NIL] RETURNS[Master] ~ { self: Master ~ NEW[MasterRep _ []]; IF encoding=NIL THEN encoding _ $Xerox; self.writer _ IPWriter.Create[stream, encoding]; self.writer.PutHeader[]; self.writer.PutOp[$beginBlock]; RETURN[self]; }; Begin: PROC[self: Master, op: Op] ~ { top: LIST OF Op ~ self.stack; self.stack _ CONS[op, top]; }; End: PROC[self: Master, op: Op] ~ { top: LIST OF Op ~ self.stack; IF top.first=op THEN self.stack _ top.rest ELSE ERROR Error["Bodies improperly nested."]; }; BeginPreamble: PUBLIC PROC[self: Master] ~ { writer: Writer ~ self.writer; IF self.page#0 THEN ERROR Error["BeginPreamble misplaced."]; Begin[self, $nil]; writer.PutOp[$beginBody]; }; EndPreamble: PUBLIC PROC[self: Master] ~ { writer: Writer ~ self.writer; End[self, $nil]; writer.PutOp[$endBody]; self.page _ 1; }; BeginPage: PUBLIC PROC[self: Master] ~ { writer: Writer ~ self.writer; IF self.page=0 THEN ERROR Error["BeginPage misplaced."]; Begin[self, $nil]; writer.PutOp[$beginBody]; }; EndPage: PUBLIC PROC[self: Master] ~ { writer: Writer ~ self.writer; End[self, $nil]; writer.PutOp[$endBody]; self.page _ self.page+1; }; EndMaster: PUBLIC PROC[self: Master] ~ { writer: Writer ~ self.writer; writer.PutOp[$endBlock]; writer.Close[]; }; BeginBodyOp: PROC[self: Master, op: Op] ~ { writer: Writer ~ self.writer; Begin[self, op]; writer.PutOp[op]; writer.PutOp[$beginBody]; }; EndBodyOp: PROC[self: Master, op: Op] ~ { writer: Writer ~ self.writer; End[self, op]; writer.PutOp[$endBody]; }; Display: PUBLIC PROC[self: Master, action: PROC[Imager.Context]] ~ { IF self.imager=NIL THEN self.imager _ Imager.Create[$Interpress, self]; action[self.imager]; }; PutOp: PUBLIC PROC[self: Master, op: Op] ~ { writer: Writer ~ self.writer; writer.PutOp[op]; }; PutInt: PUBLIC PROC[self: Master, int: INT] ~ { writer: Writer ~ self.writer; writer.PutInt[int]; }; PutReal: PUBLIC PROC[self: Master, real: REAL] ~ { writer: Writer ~ self.writer; writer.PutReal[real]; }; PutIdentifier: PUBLIC PROC[self: Master, identifier: ROPE] ~ { writer: Writer ~ self.writer; writer.PutIdentifier[identifier]; }; PutName: PUBLIC PROC[self: Master, name: ROPE] ~ { writer: Writer ~ self.writer; 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]; writer.PutIdentifier[id]; n _ n+1; IF stop