DIRECTORY BasicTime, CedarProcess, Commander, CommanderOps, FS, IO, KeyMapping, KeyMappingTypes, KeySymsKB, KeyTypes, Process, RelativeTimes, RemoteEventTime, Rope, TerminalReceiver, TerminalSpy, UserInput, UserInputLookahead, UserInputOps, UserInputOpsExtras, UserInputGetActions, ViewerIO, ViewerOps, ViewersWorld, ViewersWorldInstance; TerminalSpyImpl: CEDAR PROGRAM IMPORTS BasicTime, CedarProcess, Commander, CommanderOps, FS, IO, KeyMapping, Process, RemoteEventTime, Rope, TerminalReceiver, UserInputLookahead, UserInputOps, UserInputOpsExtras, UserInputGetActions, ViewerIO, ViewerOps, ViewersWorld, ViewersWorldInstance EXPORTS TerminalSpy = BEGIN OPEN RET:RemoteEventTime, TerminalSpy; ROPE: TYPE = Rope.ROPE; ActionBody: TYPE ~ UserInputGetActions.InputActionBody; MousePosition: TYPE ~ RECORD [x, y: REAL, display: ATOM]; EventDesc: TYPE ~ TerminalReceiver.EventDesc; ShowTimeByGet: PROC [cmd: Commander.Handle] RETURNS [result: REF ANY ¬ NIL, msg: ROPE ¬ NIL] --Commander.CommandProc-- ~ { increek: UserInput.Handle ¬ TheHandle[]; ts: RelativeTimes.TimeStamp ¬ UserInputOps.GetLatestTime[increek]; egmt: BasicTime.ExtendedGMT ¬ BasicTime.ExtendedNow[]; gmt: BasicTime.GMT; ms: INT; [gmt, ms] ¬ UserInputOps.GetAbsoluteTime[increek, ts]; cmd.out.PutFL["UserInput time = %g + %g ms;\nBasicTime.Now = %g + %g us.\n", LIST[[time[gmt]], [integer[ms]], [time[egmt.gmt]], [cardinal[egmt.usecs]]] ]; UserInputOps.Close[increek]; RETURN}; ShowTimeBySet: PROC [cmd: Commander.Handle] RETURNS [result: REF ANY ¬ NIL, msg: ROPE ¬ NIL] --Commander.CommandProc-- ~ { increek: UserInput.Handle ¬ TheHandle[]; ts: RelativeTimes.TimeStamp ¬ UserInputOps.GetLatestTime[increek]; egmt: BasicTime.ExtendedGMT; gmt: BasicTime.GMT; ms: INT; UserInputOps.SetAtLatest[increek]; {ab: UserInputGetActions.InputActionBody ~ UserInputGetActions.GetInputActionBody[increek]; egmt ¬ BasicTime.ExtendedNow[]; [gmt, ms] ¬ UserInputOps.GetAbsoluteTime[increek, ab.eventTime]; cmd.out.PutFL["UserInput time = %g + %g ms;\nBasicTime.Now = %g + %g us.\n", LIST[[time[gmt]], [integer[ms]], [time[egmt.gmt]], [cardinal[egmt.usecs]]] ]; UserInputOps.Close[increek]; RETURN}}; PlaySelfCmd: PROC [cmd: Commander.Handle] RETURNS [result: REF ANY ¬ NIL, msg: ROPE ¬ NIL] --Commander.CommandProc-- ~ { allTime, allMouse: BOOL ¬ FALSE; argv: CommanderOps.ArgumentVector ~ CommanderOps.Parse[cmd]; increek: UserInput.Handle ¬ NIL; FOR i: NAT IN [1..argv.argc) DO SELECT TRUE FROM argv[i].Equal["allTime", FALSE] => allTime ¬ TRUE; argv[i].Equal["allMouse", FALSE] => allMouse ¬ TRUE; ENDCASE => RETURN [$Failure, "Usage: PlaySelf (allTime|allMouse)*"]; ENDLOOP; increek ¬ TheHandle[]; UserInputOps.SetAtLatest[increek]; SpyOnCreek[cmd.out, increek, endOfTime, allTime, allMouse !UNWIND => UserInputOps.Close[increek]]; UserInputOps.Close[increek]; RETURN}; FullSpy: PROC [to: IO.STREAM, Produce: PROC [Consume: PROC [ActionBody], Repaint: PROC, TakeTimeReply: PROC [org, mid: EventTime, descToo: BOOL, desc: EventDesc], TakeCutBuffer: PROC [buffer: ATOM, key: CARD, data: ROPE]], et1, et: EventTime, mp: MousePosition, allTime, allMouse, printNow, printET: BOOL] = { et0: EventTime ~ et1.Sub[RET.SmallConsCC[0, 1]]; Print: PROC [ab: ActionBody] = { et ¬ et0.Add[RET.SmallConsCC[0, ab.eventTime]]; SELECT ab.kind FROM $EventTime, $TimeIsPassing => IF NOT allTime THEN RETURN; $IntegerPosition => {mp ¬ [ab.x, ab.y, NARROW[ab.display]]; IF NOT allMouse THEN RETURN}; $Position => {mp ¬ [ab.rx, ab.ry, NARROW[ab.display]]; IF NOT allMouse THEN RETURN}; $FakePosition => {mp.display ¬ NARROW[ab.display]; IF NOT allMouse THEN RETURN}; $Key, $AllUp, $KeyStillDown, $Enter, $Exit, $Ref => NULL; $TimeOut => ERROR; ENDCASE => ERROR; IF printNow THEN TRUSTED { PrintEventTime[to, RET.ReadEventTime[], FALSE]; to.PutRope[" "]; }; IF printET OR ab.kind=$EventTime OR NOT allTime THEN { PrintEventTime[to, et]; to.PutRope[" "]}; IF NOT allMouse THEN { PrintMousePosition[to, mp]; to.PutRope[" "]}; PrintAction[to, ab]; to.PutRope["\n"]; CedarProcess.CheckAbort[]; RETURN}; Repaint: PROC ~ {to.PutRope["PaintEverything\n"]}; TakeTimeReply: PROC [org, mid: EventTime, descToo: BOOL, desc: EventDesc] ~ {to.PutRope["TimeReply\n"]}; TakeCutBuffer: PROC [buffer: ATOM, key: CARD, data: ROPE] ~ {to.PutF["CutBuffer \"%q\" %g = \"%q\"\n", [atom[buffer]], [cardinal[key]], [rope[data]] ]}; Produce[Print, Repaint, TakeTimeReply, TakeCutBuffer]; RETURN}; SpyOnStream: PUBLIC PROC [to, producer: IO.STREAM, allTime, allMouse: BOOL] = { et1: EventTime ~ RET.ReadEventTime[].Sub[RET.SmallConsII[24*3600, 0]]; Produce: PROC [Consume: PROC [ActionBody], Repaint: PROC, TakeTimeReply: PROC [org, mid: EventTime, descToo: BOOL, desc: EventDesc], TakeCutBuffer: PROC [buffer: ATOM, key: CARD, data: ROPE]] ~ { TerminalReceiver.Decode[producer, NIL, et1, 17, Consume, Repaint, TakeTimeReply, TakeCutBuffer, FALSE]; RETURN}; FullSpy[to, Produce, et1, [0, 0], [0, 0, NIL], allTime, allMouse, FALSE, FALSE]; RETURN}; SpyOnCreek: PUBLIC PROC [to: IO.STREAM, increek: UserInput.Handle, stopTime: EventTime ¬ endOfTime, allTime, allMouse: BOOL ¬ FALSE] = { epochGMT: BasicTime.GMT; epochTimeStamp: RelativeTimes.TimeStamp; etE, et1, et0: EventTime; Produce: PROC [Consume: PROC [ActionBody], Repaint: PROC, TakeTimeReply: PROC [org, mid: EventTime, descToo: BOOL, desc: EventDesc], TakeCutBuffer: PROC [buffer: ATOM, key: CARD, data: ROPE]] ~ TRUSTED { DO ab: ActionBody = UserInputGetActions.GetInputActionBody[increek]; Consume[ab]; IF stopTime.Compare[et0.Add[RET.SmallConsCC[0, ab.eventTime]]] CONTINUE]; IF from=NIL THEN RETURN; IF to=NIL THEN to ¬ ViewerIO.CreateViewerStreams[name: Rope.Concat["Input from ", FS.GetName[FS.OpenFileFromStream[from]].fullFName]].out; SpyOnStream[to, from, allTime, allMouse]; RETURN}; WatchCrk: PROC [increek: UserInput.Handle] ~ TRUSTED { gmtH: BasicTime.GMT; msH: INT; etH, et0: EventTime; isHelp: PACKED ARRAY KeyTypes.KeyCode OF BOOL ¬ ALL[FALSE]; lagger: UserInput.Handle ¬ NIL; mapping: KeyMappingTypes.Mapping ¬ UserInputOps.GetMapping[increek]; FOR kc: KeyTypes.KeyCode IN KeyTypes.KeyCode DO n: NAT ~ KeyMapping.CountKeySyms[mapping, kc]; FOR i: NAT IN [0..n) DO IF KeyMapping.GetKeySym[mapping, kc, i] = KeySymsKB.Help THEN isHelp[kc] ¬ TRUE; ENDLOOP; ENDLOOP; [gmtH, msH] ¬ UserInputOps.GetAbsoluteTime[increek, [RelativeTimes.DeltaTime.LAST]]; IF msH<0 THEN {msH ¬ msH+1000; gmtH ¬ gmtH.Update[-1]}; etH ¬ RET.FromEGMT[[gmt: gmtH, usecs: msH*1000]]; et0 ¬ etH.Sub[RET.SmallConsCI[0, RelativeTimes.DeltaTime.LAST]]; DO ab: ActionBody = UserInputGetActions.GetInputActionBody[increek]; IF ab.kind#$Key OR NOT isHelp[ab.keyCode] THEN NULL ELSE IF ab.down THEN { lagger ¬ UserInputOps.Create[]; UserInputLookahead.SaveState[lagger, increek]} ELSE IF lagger#NIL THEN { log: IO.STREAM ~ ViewerIO.CreateViewerStreams["Increek Spy Log"].out; stopTime: EventTime ~ et0.Add[RET.SmallConsCC[0, UserInputOps.GetLatestTime[increek]]]; ViewerOps.CloseViewer[ViewerIO.GetViewerFromStream[log]]; SpyOnCreek[log, lagger, stopTime]; UserInputOps.Close[lagger]; lagger ¬ NIL}; ENDLOOP; }; PrintAction: PUBLIC PROC [to: IO.STREAM, ab: ActionBody] = { to.PutF["[%g, %g[", [integer[ab.deltaTime]], [atom[ab.kind]] ]; SELECT ab.kind FROM $TimeIsPassing => NULL; $EventTime => to.PutF1["%g", [cardinal[ab.eventTime]] ]; $Key, $KeyStillDown => to.PutFL["%g, %g, %g, %g", LIST[[rope[DescribeAtom[NARROW[ab.device]]]], [rope[IF ab.down THEN "dn" ELSE "up"]], [integer[ab.keyCode.ORD]], [integer[ab.preferredSym]]] ]; $AllUp => NULL; $IntegerPosition => to.PutFL["%g, %g, %g, %g", LIST[[rope[DescribeAtom[NARROW[ab.device]]]], [integer[ab.x]], [integer[ab.y]], [rope[DescribeAtom[NARROW[ab.display]]]]] ]; $Position => to.PutFL["%g, %g, %g, %g", LIST[[rope[DescribeAtom[NARROW[ab.device]]]], [real[ab.rx]], [real[ab.ry]], [rope[DescribeAtom[NARROW[ab.display]]]]] ]; $FakePosition, $Enter, $Exit, $Ref => to.PutF["%g, %g", [rope[DescribeAtom[NARROW[ab.device]]]], [rope[DescribeAtom[NARROW[ab.display]]]] ]; $TimeOut => NULL; ENDCASE => NULL; to.PutRope["]]"]; }; DescribeAtom: PROC [a: ATOM] RETURNS [ROPE] ~ { IF a=NIL THEN RETURN ["NIL"]; RETURN IO.PutFR1["$%g", [atom[a]] ]}; PrintEventTime: PUBLIC PROC [to: IO.STREAM, et: EventTime, inclDay: BOOL ¬ TRUE] = { then: BasicTime.ExtendedGMT = RET.ToEGMT[et]; unpacked: BasicTime.Unpacked = BasicTime.Unpack[then.gmt]; IF inclDay THEN to.PutF["%02g/%02g/%02g ", [integer[unpacked.year MOD 100]], [integer[unpacked.month.ORD + 1]], [integer[unpacked.day]]]; to.PutFL["%02g:%02g:%02g.%03g", LIST[[integer[unpacked.hour]], [integer[unpacked.minute]], [integer[unpacked.second]], [cardinal[then.usecs/1000]]] ]; RETURN}; PrintMousePosition: PROC [to: IO.STREAM, mp: MousePosition] = {to.PutF["[%g, %g, %g]", [real[mp.x]], [real[mp.y]], [rope[DescribeAtom[mp.display]]] ]}; TheHandle: PROC RETURNS [UserInput.Handle] ~ { vw: ViewersWorld.Ref ~ ViewersWorldInstance.GetWorld[]; ui: UserInput.Handle ~ ViewersWorld.GetInputHandle[vw]; mycopy: UserInput.Handle ~ UserInputOps.Create[]; UserInputLookahead.SaveState[mycopy, ui]; RETURN [mycopy]}; ForkCrk: PROC ~ TRUSTED {Process.Detach[FORK WatchCrk[TheHandle[]]]}; Commander.Register["PlaySelf", PlaySelfCmd, "(allTime|allMouse)* --- list user input to this Cedar world"]; Commander.Register["ShowTimeByGet", ShowTimeByGet, "--- show user input time (by GetLatestTime) and BasicTime.Now"]; Commander.Register["ShowTimeBySet", ShowTimeBySet, "--- show user input time (by SetAtLatest and GetInputActionBody) and BasicTime.Now"]; END. À TerminalSpyImpl.mesa Copyright Ó 1990, 1992 by Xerox Corporation. All rights reserved. Last tweaked by Mike Spreitzer on July 6, 1992 9:24 am PDT Willie-s, April 23, 1992 12:39 pm PDT Ê –(cedarcode) style•NewlineDelimiter ™codešœ™Kšœ Ïeœ7™BK™:K™%—K˜KšÏk œ3žœžœ˜ÒK˜šÏnœžœž˜Kšžœ3žœžœÃ˜ƒKšžœ ˜K˜—K˜Kšžœžœžœ˜,K˜Kšžœžœžœ˜Kšœ žœ'˜7Kš œžœžœžœ žœ˜9Kšœ žœ˜-K˜šŸ œžœžœ žœžœžœžœžœÏcœ˜zK˜(K˜BK˜6Kšœžœ˜Kšœžœ˜K˜6KšœMžœI˜šK˜Kšžœ˜—K˜šŸ œžœžœ žœžœžœžœžœ œ˜zK˜(K˜BKšœ˜Kšœžœ˜Kšœžœ˜K˜"Kšœ[˜[K˜K˜@KšœMžœI˜šK˜Kšžœ˜ —K˜šŸ œžœžœ žœžœžœžœžœ œ˜xKšœžœžœ˜ K˜