-- edited by Teitelman March 24, 1982 7:45 pm DIRECTORY ViewersIOStream, IOStream, Rope, ViewerClasses, TypeScript; ViewersIOStreamImpl: PROGRAM IMPORTS IOStream, TypeScript EXPORTS ViewersIOStream SHARES IOStream = BEGIN Viewer: TYPE = ViewerClasses.Viewer; ViewerStreamData: TYPE = REF ViewerStreamDataRecord; ViewerStreamDataRecord: TYPE = RECORD[ viewer: Viewer, echoTo: IOStream.Handle ← NIL ]; ViewerInStreamProcs: REF IOStream.StreamProcs ← IOStream.CreateRefStreamProcs[ getChar: ViewerGetChar, close: ViewerClose, endOf: ViewerEndOf, charsAvail: ViewerCharsAvail, setEcho: ViewerSetEcho, name: "Viewers Input" ]; ViewerOutStreamProcs: REF IOStream.StreamProcs ← IOStream.CreateRefStreamProcs[ putChar: ViewerPutChar, putBlock: ViewerPutBlock, close: ViewerClose, endOf: ViewerEndOf, eraseChar: ViewerEraseChar, name: "Viewers Output" ]; CreateViewerStreams: PUBLIC PROC [name: Rope.ROPE ← NIL, viewer: Viewer ← NIL] RETURNS [in: IOStream.Handle, out: IOStream.Handle] = {OPEN IOStream; IF viewer = NIL THEN viewer ← TypeScript.Create[info: [name: name]]; {in ← CreateProcsStream[streamProcs: ViewerInStreamProcs, streamData: NEW[ViewerStreamDataRecord ← [viewer: viewer]] ]; out ← CreateProcsStream[streamProcs: ViewerOutStreamProcs, streamData: NEW[ViewerStreamDataRecord ← [viewer: viewer]] ]; [] ← SetEcho[in, out]; -- do the echoing at the level of handle, since this permits echoing to an arbitrary handle. }; }; ViewerGetChar: PROCEDURE [self: IOStream.Handle] RETURNS [char: CHARACTER] = BEGIN data: ViewerStreamData ← NARROW[self.streamData]; IF data.viewer.destroyed THEN IOStream.Error[StreamClosed]; char ← TypeScript.GetChar[data.viewer]; IF data.echoTo # NIL THEN IOStream.PutChar[data.echoTo, char]; END; -- of ViewerGetChar ViewerPutChar: PROCEDURE[self: IOStream.Handle, char: CHARACTER] = BEGIN data: ViewerStreamData ← NARROW[self.streamData]; IF data.viewer.destroyed THEN IOStream.Error[StreamClosed]; TypeScript.PutChar[data.viewer, char]; END; -- of ViewerPutChar ViewerPutBlock: PROCEDURE[self: IOStream.Handle, block: REF READONLY TEXT, startIndex: NAT, stopIndexPlusOne: NAT] = BEGIN data: ViewerStreamData ← NARROW[self.streamData]; IF data.viewer.destroyed THEN IOStream.Error[StreamClosed]; TypeScript.PutText[ts: data.viewer, text: block, start: startIndex, stopPlusOne: stopIndexPlusOne]; END; -- of ViewerPutChar ViewerReset: PROCEDURE[self: IOStream.Handle] = BEGIN data: ViewerStreamData ← NARROW[self.streamData]; TypeScript.Reset[data.viewer]; END; -- of ViewerClose ViewerClose: PROCEDURE[self: IOStream.Handle, abort: BOOLEAN] = BEGIN data: ViewerStreamData ← NARROW[self.streamData]; IF ~data.viewer.destroyed THEN TypeScript.Destroy[data.viewer]; END; -- of ViewerClose ViewerEndOf: PROCEDURE[self: IOStream.Handle] RETURNS [BOOLEAN] = BEGIN data: ViewerStreamData ← NARROW[self.streamData]; IF data.viewer.destroyed THEN IOStream.Error[StreamClosed]; RETURN[FALSE]; END; -- ViewerEndOf ViewerCharsAvail: PROCEDURE[self: IOStream.Handle] RETURNS [BOOLEAN] = BEGIN data: ViewerStreamData ← NARROW[self.streamData]; IF data.viewer.destroyed THEN IOStream.Error[StreamClosed]; RETURN[TypeScript.CharsAvailable[data.viewer]]; END; -- ViewerCharsAvail ViewerEraseChar: PROCEDURE[self: IOStream.Handle, char: CHARACTER] = BEGIN data: ViewerStreamData ← NARROW[self.streamData]; IF data.viewer.destroyed THEN IOStream.Error[StreamClosed]; TypeScript.BackSpace[data.viewer]; END; -- of ViewerEraseChar ViewerSetEcho: PROCEDURE[self: IOStream.Handle, echoTo: IOStream.Handle] RETURNS[oldEcho: IOStream.Handle] = BEGIN data: ViewerStreamData ← NARROW[self.streamData]; IF data.viewer.destroyed THEN IOStream.Error[StreamClosed]; oldEcho ← data.echoTo; data.echoTo ← echoTo; END; -- of ViewerSetEcho DefaultCreateIn: PROC RETURNS [IOStream.Handle] = -- creates a viewer. sets defaultOut to same window. {in, out: IOStream.Handle; [in, out] ← CreateViewerStreams[]; IOStream.SetDefaultStreams[out: out]; RETURN[in]; }; DefaultCreateError, DefaultCreateOut: PROC RETURNS [IOStream.Handle] = {in, out: IOStream.Handle; [in, out] ← CreateViewerStreams[]; IOStream.SetDefaultStreams[in: in]; RETURN[out]; }; CreateViewerStream1: PROC [name: Rope.ROPE ← NIL] RETURNS [in: IOStream.Handle, out: IOStream.Handle] = {[in, out] ← CreateViewerStreams[name]}; IOStream.SetTTYCreate[CreateViewerStream1]; IOStream.SetDefaultStreams[createIn: DefaultCreateIn, createOut: DefaultCreateOut, createError: DefaultCreateError]; END. March 24, 1982 7:46 pm W. Teitelman. Fixed Close to check if viewer already destroyed. Added name argument to CreateRefStreamProcs. 13-Apr-82 14:05:22 W. Teitelman. Added checks for whether viewer was destroyed, and if so, raised IOStream error.