DIRECTORY Atom, ProcessProps, EditedStream, Ascii, Commander, CommanderOps, Imager, ImagerColor, ImagerFont, InputFocus, IO, Process, Rope, TIPUser, ViewerClasses, ViewerOps, MessageWindow, ViewerForkers; SimpleCommandViewerImpl: CEDAR MONITOR LOCKS data USING data: Data IMPORTS ProcessProps, EditedStream, Commander, CommanderOps, Imager, ImagerColor, ImagerFont, InputFocus, IO, Process, Rope, TIPUser, ViewerOps, MessageWindow, ViewerForkers ~ BEGIN ROPE: TYPE ~ Rope.ROPE; STREAM: TYPE ~ IO.STREAM; Viewer: TYPE ~ ViewerClasses.Viewer; Data: TYPE ~ REF DataRep; DataRep: TYPE ~ MONITORED RECORD [ font: Imager.Font, focusColor: ImagerColor.Color, lines: ARRAY [0..24) OF ROPE ¬ ALL[NIL], valid: PACKED ARRAY [0..24) OF BOOL ¬ ALL[FALSE], currentLine: NAT, focus: BOOL, inputAvailable: CONDITION, input: LIST OF CHAR ]; PaintLines: ENTRY PROC [data: Data, context: Imager.Context, cw, ch: REAL, whatChanged: REF] ~ { ENABLE UNWIND => NULL; IF whatChanged = NIL THEN data.valid ¬ ALL[FALSE]; IF data.font = NIL THEN data.font ¬ ImagerFont.Find["Xerox/TiogaFonts/Tioga10"]; IF data.focusColor = NIL THEN data.focusColor ¬ ImagerColor.ColorFromRGB[[1, 0, 0]]; Imager.SetFont[context, data.font]; FOR i: NAT IN [0..LENGTH[data.lines]) DO IF NOT data.valid[i] THEN { y: REAL ~ ch-2-12*(i+1); Imager.SetGray[context, 0]; Imager.MaskRectangle [context, [0, y-5, cw, 12]]; Imager.SetGray[context, 1]; Imager.SetXY[context, [4, ch-4-12*(i+1)]]; Imager.ShowRope[context, data.lines[i]]; IF i = data.currentLine AND data.focus THEN { Imager.StartUnderline[context]; Imager.ShowRope[context, " "]; Imager.SetColor[context, data.focusColor]; Imager.MaskUnderline[context, -7, 7]; }; }; ENDLOOP; data.valid ¬ ALL[TRUE]; }; ViewerPaint: ViewerClasses.PaintProc ~ { data: Data ~ NARROW[self.data]; PaintLines[data: data, context: context, cw: self.cw, ch: self.ch, whatChanged: whatChanged ! UNCAUGHT => {MessageWindow.Append["BUG! "]; CONTINUE} ]; }; AppendChar: ENTRY PROC [data: Data, char: CHAR] ~ { cur: NAT ¬ data.currentLine; SELECT char FROM '\l, '\r => { IF cur+1 = LENGTH[data.lines] THEN { FOR i: NAT IN (0..LENGTH[data.lines]) DO data.lines[i-1] ¬ data.lines[i] ENDLOOP; data.lines[LENGTH[data.lines]-1] ¬ NIL; data.valid ¬ ALL[FALSE]; } ELSE { IF data.focus THEN data.valid[cur] _ FALSE; data.currentLine ¬ cur ¬ cur+1; }; }; Ascii.BS => { WHILE cur > 0 AND Rope.Size[data.lines[cur]] = 0 DO IF data.focus THEN data.valid[cur] _ FALSE; cur ¬ cur - 1; ENDLOOP; data.currentLine ¬ cur; data.lines[cur] ¬ Rope.Substr[data.lines[cur], 0, Rope.Size[data.lines[cur]]-1]; data.valid[cur] ¬ FALSE; }; ENDCASE => { data.lines[cur] ¬ Rope.Concat[data.lines[cur], Rope.FromChar[char]]; data.valid[cur] ¬ FALSE; }; }; BufferChar: ENTRY PROC [data: Data, char: CHAR] ~ { new: LIST OF CHAR ~ LIST[char]; IF data.input = NIL THEN { data.input ¬ new; NOTIFY data.inputAvailable } ELSE { last: LIST OF CHAR ¬ data.input; UNTIL last.rest = NIL DO last ¬ last.rest ENDLOOP; last.rest ¬ new; }; }; ViewerNotify: ViewerClasses.NotifyProc ~ { data: Data ~ NARROW[self.data]; BufferRope: PROC [rope: ROPE] ~ { FOR i: INT IN [0..Rope.Size[rope]) DO BufferChar[data, Rope.Fetch[rope, i]] ENDLOOP; }; FOR tail: LIST OF REF ¬ input, tail.rest UNTIL tail = NIL DO WITH tail.first SELECT FROM mouse: TIPUser.TIPScreenCoords => InputFocus.SetInputFocus[self]; x: REF CHAR => BufferChar[data, x­]; x: ROPE => BufferRope[x]; x: REF TEXT => BufferRope[Rope.FromRefText[x]]; ENDCASE; ENDLOOP; }; ViewerModify: ViewerClasses.ModifyProc ~ { changed: BOOL ¬ FALSE; Inner: PROC [data: Data] ~ { new: BOOL ¬ SELECT change FROM set => TRUE, kill => FALSE ENDCASE => data.focus; changed ¬ new # data.focus; data.focus ¬ new; data.valid[data.currentLine] ¬ NOT changed; }; WITH self.data SELECT FROM data: Data => Inner[data]; ENDCASE; IF changed THEN ViewerForkers.ForkPaint[self, client, FALSE, $Edit, TRUE]; }; ViewerGone: ERROR ~ CODE; ViewerCmd: Commander.CommandProc ~ { viewer: Viewer; data: Data ~ NEW[DataRep]; viewer ¬ ViewerOps.CreateViewer[ flavor: $SimpleCommandViewer, info: [name: "Simple Command Viewer", data: data]]; ViewerOps.OpenIcon[viewer]; Process.Detach[FORK RunCommander[viewer]]; }; RunCommander: PROC [viewer: Viewer] ~ { ENABLE ViewerGone => CONTINUE; out: IO.STREAM ~ CreateSVOutStream[viewer]; rawin: IO.STREAM ~ CreateSVInStream[viewer]; in: IO.STREAM ~ EditedStream.Create[in: rawin, echoTo: out]; cmd: Commander.Handle ~ CommanderOps.CreateFromStreams[in: in, out: out]; Inner: PROC ~ { [] ¬ CommanderOps.ReadEvalPrintLoop[cmd]; }; ProcessProps.AddPropList[LIST[NEW[Atom.DottedPairNode ¬ ["",""]]], Inner]; -- dummy prop list so SetProcessProperty has a chance to work. }; SVOutStreamProcs: REF IO.StreamProcs ~ IO.CreateStreamProcs[ variety: $output, class: $SVOut, putChar: SVOutStreamPutChar, eraseChar: SVOutStreamEraseChar, close: SVOutStreamClose ]; CreateSVOutStream: PROC [viewer: ViewerClasses.Viewer] RETURNS [STREAM] = { data: Data = NARROW[viewer.data]; RETURN[IO.CreateStream[streamProcs: SVOutStreamProcs, streamData: viewer]]; }; SVOutStreamPutChar: PROC [self: STREAM, char: CHAR] = { viewer: ViewerClasses.Viewer ~ NARROW[self.streamData]; WITH viewer.data SELECT FROM data: Data => { AppendChar[data, char]; ViewerForkers.ForkPaint[viewer, client, FALSE, $Edit, TRUE]; }; ENDCASE => ERROR ViewerGone; }; SVOutStreamEraseChar: PROC [self: STREAM, char: CHAR] = { SVOutStreamPutChar[self, Ascii.BS] }; SVOutStreamClose: PROC [self: STREAM, abort: BOOL] = { }; SVInStreamProcs: REF IO.StreamProcs ~ IO.CreateStreamProcs[ variety: $input, class: $SVIn, getChar: SVInStreamGetChar, charsAvail: SVInStreamCharsAvail, backup: SVInStreamBackup, endOf: SVInStreamEndOf, reset: SVInStreamReset, close: SVInStreamClose ]; CreateSVInStream: PUBLIC PROC [viewer: ViewerClasses.Viewer] RETURNS [STREAM] = { data: Data = NARROW[viewer.data]; RETURN[IO.CreateStream[streamProcs: SVInStreamProcs, streamData: viewer]]; }; SVInStreamGetChar: PROC [self: STREAM] RETURNS [char: CHAR ¬ '\000] = { viewer: ViewerClasses.Viewer ~ NARROW[self.streamData]; Inner: ENTRY PROC [data: Data] ~ { UNTIL data.input # NIL DO WAIT data.inputAvailable ENDLOOP; char ¬ data.input.first; data.input ¬ data.input.rest; }; Inner[NARROW[viewer.data]]; }; SVInStreamEndOf: PROC [self: STREAM] RETURNS [BOOL] = { viewer: ViewerClasses.Viewer ~ NARROW[self.streamData]; data: Data = NARROW[viewer.data]; RETURN [FALSE] }; SVInStreamCharsAvail: PROC [self: STREAM, wait: BOOL] RETURNS [count: INT ¬ 0] = { viewer: ViewerClasses.Viewer ~ NARROW[self.streamData]; data: Data = NARROW[viewer.data]; Inner: ENTRY PROC [data: Data] ~ { FOR tail: LIST OF CHAR ¬ data.input, tail.rest UNTIL tail = NIL DO count ¬ count + 1; ENDLOOP; }; Inner[NARROW[viewer.data]]; }; SVInStreamBackup: PROC [self: STREAM, char: CHAR] = { viewer: ViewerClasses.Viewer ~ NARROW[self.streamData]; data: Data = NARROW[viewer.data]; Inner: ENTRY PROC [data: Data] ~ { data.input ¬ CONS[char, data.input]; NOTIFY data.inputAvailable; }; Inner[NARROW[viewer.data]]; }; SVInStreamReset: PROC [self: STREAM] = { viewer: ViewerClasses.Viewer ~ NARROW[self.streamData]; data: Data = NARROW[viewer.data]; Inner: ENTRY PROC [data: Data] ~ { data.input ¬ NIL; }; Inner[NARROW[viewer.data]]; }; SVInStreamClose: PROC [self: STREAM, abort: BOOL] = { SVInStreamReset[self]; }; ViewerOps.RegisterViewerClass[ $SimpleCommandViewer, NEW[ViewerClasses.ViewerClassRec ¬ [ paint: ViewerPaint, notify: ViewerNotify, modify: ViewerModify, tipTable: TIPUser.InstantiateNewTIPTable["SimpleCommandViewer.tip"] ]] ]; Commander.Register["SimpleCommandViewer", ViewerCmd, "Simple Command Viewer"]; END.  SimpleCommandViewerImpl.mesa Copyright Σ 1991 by Xerox Corporation. All rights reserved. Michael Plass, October 23, 1991 2:49 pm PDT A Simple Text Viewer ModifyProc: TYPE = PROC [self: Viewer, change: ModifyAction]; ModifyAction: TYPE = {set, push, pop, kill}; Called when the input focus ownership is changing so that the client can modify things like selection feedback on the screen or private data structures and state. Commander Interface Output Stream Interface Input Stream Interface Start Code Κ N•NewlineDelimiter –(cedarcode) style™™Jšœ Οeœ1™˜‰Kšœ˜K˜——š ™š‘œžœžœžœ˜