DIRECTORY Atom, Convert, Vector2, IO, RefText, Rope, SessionLog, SlackProcess; SessionLogImpl: CEDAR PROGRAM IMPORTS Atom, Convert, RefText, IO, Rope EXPORTS SessionLog = BEGIN EnterAction: PUBLIC PROC [f: IO.STREAM, action: LIST OF REF ANY] = { FOR actionList: LIST OF REF ANY _ action, actionList.rest UNTIL actionList = NIL DO WITH actionList.first SELECT FROM atom: ATOM => f.PutF["%g", [rope[Atom.GetPName[atom]]]]; n: REF INT => f.PutF["%g", [integer[n^]]]; r: REF REAL => f.PutF["%g", [real[r^]]]; c: REF CHAR => f.PutF["'%g", [character[c^]]]; cd: REF CARD => f.PutF["%g", [cardinal[cd^]]]; rope: Rope.ROPE => f.PutF["\"%g\"", [rope[rope]]]; refText: REF TEXT => f.PutF["\"%g\"", [text[refText]]]; refPoint: REF Vector2.VEC => f.PutF["[%g, %g]", [real[refPoint.x]], [real[refPoint.y]]]; ENDCASE => ERROR; IF actionList.rest = NIL THEN f.PutChar[IO.CR] ELSE f.PutChar[IO.SP]; ENDLOOP; }; PlayScript: PUBLIC PROC [f: IO.STREAM, clientData: REF ANY, notifyProc: SlackProcess.EventProc] = { endOfStream: BOOL _ FALSE; WHILE NOT endOfStream DO endOfStream _ PlayAction[f, clientData, notifyProc]; ENDLOOP; }; PlayAction: PUBLIC PROC [f: IO.STREAM, clientData: REF ANY, notifyProc: SlackProcess.EventProc] RETURNS [endOfStream: BOOL _ FALSE] = { c: CHAR; mouseEvent: BOOL; point: Vector2.VEC; good: BOOL; token: REF ANY; action: LIST OF REF ANY; ReadBlank[f]; c _ IO.GetChar[f !IO.EndOfStream => {endOfStream _ TRUE; CONTINUE}]; IF endOfStream THEN RETURN; IF c = '* THEN { atom: ATOM; refPoint: REF Vector2.VEC; good _ ReadHorizontalBlank[f]; IF NOT good THEN ERROR; point _ ReadPoint[f]; refPoint _ NEW[Vector2.VEC _ point]; token _ ReadSpacesAndToken[f]; atom _ NARROW[token]; UNTIL token = $EndOfLine DO token _ ReadSpacesAndToken[f]; ENDLOOP; action _ LIST[atom, refPoint]; } ELSE { mouseEvent _ FALSE; IO.Backup[f, c]; token _ $Start; UNTIL token = $EndOfLine DO token _ ReadSpacesAndToken[f]; IF token = $EndOfLine THEN LOOP; action _ AppendToken[token, action] ENDLOOP; }; notifyProc[action, clientData]; }; ReadSpacesAndToken: PUBLIC PROC [f: IO.STREAM] RETURNS [token: REF ANY] = { word: Rope.ROPE; good: BOOL; int: INT; real: REAL; firstChar: CHAR; good _ ReadHorizontalBlank[f]; IF NOT good THEN { token _ $EndOfLine; RETURN; }; firstChar _ IO.PeekChar[f]; SELECT TRUE FROM firstChar = '" => { token _ f.GetRopeLiteral[]; }; firstChar = '' => { [] _ f.GetChar[]; token _ NEW[CHAR _ f.GetChar[]]; }; firstChar = '[ => { point: Vector2.VEC _ ReadPoint[f]; token _ NEW[Vector2.VEC _ point]; }; IsDigitOrOp[firstChar] => { word _ ReadBlankAndWord[f]; IF Rope.Find[word, "."] = -1 THEN { -- an integer int _ IO.GetInt[IO.RIS[word]]; token _ NEW[INT _ int]; } ELSE { real _ IO.GetReal[IO.RIS[word]]; token _ NEW[REAL _ real]; }; }; ENDCASE => { word _ ReadBlankAndWord[f]; token _ Atom.MakeAtom[word]; }; }; ReadLine: PROC [f: IO.STREAM] RETURNS [line: Rope.ROPE] = { LineBreakProc: SAFE PROC [char: CHAR] RETURNS [IO.CharClass] = CHECKED { SELECT char FROM IO.CR =>RETURN [break]; ENDCASE => RETURN [other]; }; end: BOOL _ FALSE; [line, ----] _ IO.GetTokenRope[f, LineBreakProc !IO.EndOfStream => {end _ TRUE; CONTINUE}]; IF end THEN {line _ NIL; RETURN}; }; ReadSpaceAndChar: PROC [f: IO.STREAM] RETURNS [token: REF ANY] = { c: CHAR; good: BOOL; c _ IO.GetChar[f !IO.EndOfStream => ERROR]; c _ IO.GetChar[f !IO.EndOfStream => ERROR]; good _ ReadHorizontalBlank[f]; IF good THEN ERROR; token _ NEW[CHAR _ c]; }; AppendToken: PROC [token: REF ANY, list: LIST OF REF ANY] RETURNS [newList: LIST OF REF ANY] = { l: LIST OF REF ANY _ list; IF l = NIL THEN RETURN[LIST[token]]; UNTIL l.rest = NIL DO l _ l.rest ENDLOOP; l.rest _ CONS[token, NIL]; newList _ list; }; IsDigitOrOp: PROC [c: CHAR] RETURNS [BOOL] = { RETURN[c IN ['0..'9] OR c = '- OR c = '+]; }; ReadBlank: PUBLIC PROC [f: IO.STREAM] = { [] _ IO.SkipWhitespace[f, TRUE]; }; ReadHorizontalBlank: PUBLIC PROC [f: IO.STREAM] RETURNS [good: BOOL] = { HorizontalBlankProc: SAFE PROC [char: CHAR] RETURNS [IO.CharClass] = TRUSTED { SELECT char FROM IO.TAB, IO.SP => RETURN [other]; ENDCASE => RETURN [break]; }; whiteSpace: Rope.ROPE; c: CHAR; end: BOOL _ FALSE; good _ TRUE; [whiteSpace, ----] _ IO.GetTokenRope[f, HorizontalBlankProc !IO.EndOfStream => {end _ TRUE; CONTINUE}]; IF end THEN {good _ FALSE; RETURN}; c _ Rope.Fetch[whiteSpace, 0]; SELECT c FROM IO.CR => {good _ FALSE; RETURN}; IO.TAB, IO.SP => {good _ TRUE; RETURN}; ENDCASE => {good _ TRUE; IO.Backup[f, c]; RETURN}; }; ReadBlankAndReal: PUBLIC PROC [f: IO.STREAM] RETURNS [r: REAL] = { ReadBlank[f]; r _ ReadReal[f]; }; ReadReal: PUBLIC PROC [f: IO.STREAM] RETURNS [r: REAL] = { RealBreakProc: SAFE PROC [char: CHAR] RETURNS [IO.CharClass] = TRUSTED { SELECT char FROM '), '], ', => RETURN [break]; IO.CR =>RETURN [break]; IO.SP => RETURN [break]; ENDCASE => RETURN [other]; }; realText, buffer: REF TEXT; end: BOOL _ FALSE; buffer _ RefText.ObtainScratch[50]; [realText, ----] _ IO.GetToken[f, RealBreakProc, buffer !IO.EndOfStream => {end _ TRUE; CONTINUE}]; IF end THEN {r _ 0.0; RETURN}; IF RefText.Find[realText, ".", 0, FALSE] = -1 THEN realText _ RefText.Append[realText, ".0"]; r _ Convert.RealFromRope[RefText.TrustTextAsRope[realText]]; RefText.ReleaseScratch[buffer]; }; ReadPoint: PUBLIC PROC [f: IO.STREAM] RETURNS [point: Vector2.VEC] = { ReadBlank[f]; ReadRope[f, "["]; point.x _ ReadBlankAndReal[f]; ReadRope[f, ","]; point.y _ ReadBlankAndReal[f]; ReadRope[f, "]"]; }; SyntaxError: PUBLIC SIGNAL [position: NAT, wasThere: Rope.ROPE, notThere: Rope.ROPE] = CODE; ReadRope: PROC [f: IO.STREAM, rope: Rope.ROPE] = { c: CHAR; endofstream: BOOL _ FALSE; FOR i: INT IN[1..Rope.Length[rope]] DO c _ IO.GetChar[f ! IO.EndOfStream => {endofstream _ TRUE; CONTINUE}]; IF endofstream THEN SIGNAL SyntaxError [IO.GetIndex[f], NIL, rope]; IF NOT c = Rope.Fetch[rope,i-1] THEN SIGNAL SyntaxError [IO.GetIndex[f], Rope.FromChar[c], rope]; ENDLOOP; }; ReadBlankAndWord: PUBLIC PROC [f: IO.STREAM] RETURNS [word: Rope.ROPE] = { ReadBlank[f]; word _ ReadWord[f]; }; ReadWord: PROC [f: IO.STREAM] RETURNS [word: Rope.ROPE] = { WordBreakProc: PROC [char: CHAR] RETURNS [IO.CharClass] = { SELECT char FROM IO.TAB => RETURN [break]; IO.CR =>RETURN [break]; IO.SP => RETURN [break]; ', => RETURN [break]; '] => RETURN [break]; ') => RETURN [break]; ENDCASE => RETURN [other]; }; [word, ----] _ IO.GetTokenRope[f, WordBreakProc !IO.EndOfStream => {word _ NIL; CONTINUE}]; }; END. DSessionLogImpl.mesa Copyright c 1986 by Xerox Corporation. All rights reserved. Last edited by Bier on April 27, 1987 10:47:48 pm PDT Contents: Routines recording and playing back a record of an interactive session. SessionLog is intended to be used with SlackProcess in systems built according to the new user interface architecture (see SlackProcessDoc and AtomButtonsDoc). Recording Playing Back For compatibility with the old style of script. End of compatibility. Reads a rope UNTIL is encountered. Parsing Reads, 's, 's, and 's until something else is encountered. Doesn't mind if no white space characters are found. Treats comments as white space. Reads 's, and 's until something else is encountered. Returns good = FALSE if a CR is encountered before anything else A convenience function. Equivalent to ReadBlank[f]; r _ ReadReal[f]; Reads digits up to the next ), ], , or . Leaves these terminators on the stream. Assumes the next rope on the stream will be of the form "[,]". Removes the given rope from the top of the stream. Used to remove formatting words and phrases from 3d files. We are not interested in these strings but only in the data in between them. Signals SyntaxError if some other rope is on top. Used to read in a rope which is data. Κ ˜J˜Icodešœ™Kšœ Οmœ1™