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
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]]]<equal THEN EXIT;
ENDLOOP;
};
[epochGMT, epochTimeStamp] ¬ UserInputOpsExtras.GetEpochTimes[increek];
to.PutF["Epoch GMT = %g, TimeStamp = %g.\n", [time[epochGMT]], [cardinal[epochTimeStamp]] ];
etE ¬ RET.FromEGMT[[gmt: epochGMT, usecs: 0]];
et0 ¬ etE.Sub[RET.SmallConsCC[0, epochTimeStamp]];
et1 ¬ et0.Add[RET.SmallConsCC[0, 1]];
to.PutRope["TimeStamp 0 = "];
PrintEventTime[to, et0];
to.PutRope[".\n"];
FullSpy[to, Produce, et1, et0.Add[RET.SmallConsCC[0, UserInputOps.GetTime[increek]]], [0, 0, NIL], allTime, allMouse, TRUE, TRUE];
RETURN};
SpyOnFile:
PROC [fileName:
ROPE, to:
IO.
STREAM ¬
NIL, allTime, allMouse:
BOOL ¬
FALSE] ~ {
from: IO.STREAM ¬ NIL;
from ¬ FS.StreamOpen[fileName !FS.Error => 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.