TerminalReceiverImpl.mesa
Copyright Ó 1990, 1992 by Xerox Corporation. All rights reserved.
Last tweaked by Mike Spreitzer on July 6, 1992 8:56 am PDT
DIRECTORY Atom, CedarProcess, IO, KeyTypes, NetworkStream, RemoteEventTime, RemoteImagerDataTypes, TerminalReceiver, TIPKeyboards, UserInputGetActions;
TerminalReceiverImpl: CEDAR PROGRAM
IMPORTS Atom, CedarProcess, IO, NetworkStream, RemoteEventTime, TIPKeyboards
EXPORTS TerminalReceiver
=
BEGIN OPEN RET:RemoteEventTime, RIDT:RemoteImagerDataTypes, TerminalReceiver;
keysym0: KeyTypes.KeySym ~ [0];
Decode: PUBLIC PROC
[producer, indexSrc: IO.STREAM, et1: EventTime, version: NAT,
Consumer: PROC [ActionBody],
Repaint: PROC,
TakeTimeReply: PROC [org, mid: EventTime, descToo: BOOL, desc: EventDesc],
TakeCutBuffer: PROC [buffer: ATOM, key: CARD, data: ROPE],
adjustTime: BOOL] = {
DecodeProtected[producer, indexSrc, et1, version, Consumer, Repaint, TakeTimeReply, TakeCutBuffer, adjustTime !
IO.Error => <<IF ec = StreamClosed AND stream = producer THEN>> CONTINUE;
IO.EndOfStream => <<IF stream = producer THEN>> CONTINUE;
NetworkStream.Timeout => RESUME];
RETURN};
DecodeProtected: PROC
[producer, indexSrc: IO.STREAM, et1: EventTime, version: NAT,
Consumer: PROC [ActionBody],
Repaint: PROC,
TakeTimeReply: PROC [org, mid: EventTime, descToo: BOOL, desc: EventDesc],
TakeCutBuffer: PROC [buffer: ATOM, key: CARD, data: ROPE],
adjustTime: BOOL] = {
localStart: EventTime ~ RET.ReadEventTime[];
idx0: INT ~ IF indexSrc#NIL THEN indexSrc.GetIndex[] ELSE FIRST[INT];
GetChar: PROC RETURNS [CHAR] = INLINE {RETURN [producer.GetChar[]]};
GetByte: PROC RETURNS [BYTE] = INLINE {RETURN [GetChar[].ORD]};
GetEventTime: PROC RETURNS [EventTime] = {
hi: CARD = GetCard[];
lo: CARDINAL = GetCardinal[];
RETURN [[hi: hi, lo: lo]]};
GetMousePosition: PROC RETURNS [MousePosition] = {
mouseX: INTEGER = GetInteger[];
color: BOOL ¬ FALSE;
mouseY: INTEGER ¬ GetInteger[];
IF mouseY < 0 THEN {color ¬ TRUE; mouseY ¬ mouseY + 32768};
RETURN [[mouseX, color, mouseY-16383]]};
GetCard: PROC RETURNS [CARD] = {
hi: CARDINAL = GetCardinal[];
lo: CARDINAL = GetCardinal[];
RETURN [hi*65536 + lo]};
GetCardinal: PROC RETURNS [CARDINAL] = {
hi: BYTE = GetByte[];
lo: BYTE = GetByte[];
RETURN [CARDINAL[hi]*256 + lo]};
GetInteger: PROC RETURNS [INTEGER] = {
c: CARDINAL ~ GetCardinal[];
IF c <= INT16.LAST THEN RETURN [c];
RETURN [INT[c]-10000H]};
GetTimeAction: PROC RETURNS [et: EventTime] = {
peekB: BYTE ~ producer.PeekChar[].ORD;
IF peekB=RIDT.ActionKind.eventTime.ORD THEN {
b2: BYTE ~ GetByte[];
dt: CARDINAL ~ GetByte[];
IF peekB#b2 OR dt#0 THEN ERROR;
et ¬ GetEventTime[];
RETURN}
ELSE RETURN [localStart]};
GetRope: PROC RETURNS [ROPE] ~ {
len: NAT ~ GetCard[];
RETURN producer.GetRope[len, TRUE]};
nt: EventTime = [0, 0];
remoteStart: EventTime ~ GetTimeAction[];
deltaTime: EventTime ¬ nt;
posns: ARRAY {mouse, pen} OF RECORD [known, color: BOOL, x, y: INT]
¬ ALL[[FALSE, FALSE, 0, 0]];
LogSize: NAT = 32;
log: ARRAY [0..LogSize) OF RECORD [key: BYTE, idx: INT] ¬ ALL[[0, 0]];
logPtr: [0..LogSize) ¬ 0;
ts: INT;
IF adjustTime THEN TRUSTED {
curOffset ¬ deltaTime ¬ RET.Sub[localStart, remoteStart];
}
ELSE curOffset ¬ [0, 0];
deltaTime ¬ deltaTime.Sub[et1].Add[RET.SmallConsCC[0, 1]];
ts ¬ remoteStart.Add[deltaTime].ToSmall[];
Consumer[[$EventTime, [MAX[ts, 0]], 0]];
DO
idx: INT ~ IF indexSrc#NIL THEN indexSrc.GetIndex[] ELSE FIRST[INT];
key: BYTE ~ GetByte[];
CedarProcess.CheckAbort[];
log[logPtr] ¬ [key, idx];
logPtr ¬ (logPtr.SUCC) MOD LogSize;
SELECT key FROM
<= RIDT.ActionKind.LAST.ORD => {kind: RIDT.ActionKind ~ VAL[key];
dt: INT ~ GetByte[];
ots: CARD ~ MAX[ts, 0];
rts: CARD;
ts ¬ ts + dt;
rts ¬ MAX[ts, 0];
SELECT kind FROM
deltaEventTime => {ts ¬ ts + GetCardinal[];
rts ¬ MAX[ts, 0];
Consumer[[$TimeIsPassing, [rts], rts-ots]]};
keyDown, keyUp => {k: BYTE ~ GetByte[];
kc: KeyTypes.KeyCode ~ VAL[k];
Consumer[[$Key, [rts], rts-ots, NIL, NIL, NIL, kind=keyDown, kc, TIPKeyboards.KeySymsFromKeyCode[kc].keySym1]]};
keyStillDown, allUp => NULL;
eventTime => TRUSTED {et: EventTime ¬ GetEventTime[];
ts ¬ MAX[et.Add[deltaTime].ToSmall[], ts];
rts ¬ MAX[ts, 0];
Consumer[[$EventTime, [rts], rts-ots]]};
deltaMouse => {b: BYTE = GetByte[];
hi: NAT = b/16;
lo: NAT = b - hi*16;
posns[mouse].x ¬ posns[mouse].x + hi - 8;
posns[mouse].y ¬ posns[mouse].y + lo - 8;
Consumer[[$IntegerPosition, [rts], rts-ots, NIL, NIL, NIL, FALSE, keycode0, keysym0, posns[mouse].x, posns[mouse].y, posns[mouse].x, posns[mouse].y, ColorToDisplay[posns[mouse].color]]]};
mousePosition => {
[[mouseX: posns[mouse].x, mouseY: posns[mouse].y, color: posns[mouse].color]] ¬ GetMousePosition[];
posns[mouse].known ¬ TRUE;
Consumer[[$IntegerPosition, [rts], rts-ots, NIL, NIL, NIL, FALSE, keycode0, keysym0, posns[mouse].x, posns[mouse].y, posns[mouse].x, posns[mouse].y, ColorToDisplay[posns[mouse].color]]]};
penPosition => [] ¬ GetMousePosition[];
timedOut => Consumer[[$TimeIsPassing, [rts], rts-ots]];
ENDCASE => ERROR;
};
16 => Repaint[];
17 => {org, mid: EventTime;
descToo: BOOL ~ version >= 13;
desc: EventDesc;
[org, mid, desc] ¬ GetTimeReply[producer, descToo];
TakeTimeReply[org, mid, descToo, desc]};
18 => {
bufferR: ROPE ~ GetRope[];
buffer: ATOM ~ Atom.MakeAtom[bufferR];
bkey: CARD ~ GetCard[];
data: ROPE ~ GetRope[];
TakeCutBuffer[buffer, bkey, data]};
ENDCASE => ERROR;
ENDLOOP;
};
curOffset: EventTime;
ColorToDisplay: PROC [color: BOOL] RETURNS [display: ATOM] ~ {
IF color THEN RETURN [$Color] ELSE RETURN [$Main]};
GetTimeReply: PUBLIC PROC [producer: IO.STREAM, descToo: BOOL] RETURNS [org, mid: EventTime, desc: EventDesc] ~ {
GetEventTime: PROC RETURNS [EventTime] = {
hi: CARD = GetCard[];
lo: CARDINAL = GetCardinal[];
RETURN [[hi: hi, lo: lo]]};
GetCard: PROC RETURNS [CARD] = {
hi: CARDINAL = GetCardinal[];
lo: CARDINAL = GetCardinal[];
RETURN [hi*65536 + lo]};
GetCardinal: PROC RETURNS [CARDINAL] = {
hi: BYTE = GetByte[];
lo: BYTE = GetByte[];
RETURN [CARDINAL[hi]*256 + lo]};
GetByte: PROC RETURNS [BYTE] = INLINE {RETURN [producer.GetChar[].ORD]};
dcopy: EventDesc ¬ [mousePosition: [0, FALSE, 0], action: [contents: timedOut[]]];
TRUSTED {
org ¬ GetEventTime[];
mid ¬ GetEventTime[];
IF descToo THEN {
n: INT ~ producer.UnsafeGetBlock[[base: LOOPHOLE[@dcopy], count: BYTES[EventDesc]]];
IF n = BYTES[EventDesc] THEN NULL
ELSE IF producer.EndOf[] THEN ERROR IO.EndOfStream[producer]
ELSE ERROR};
};
desc ¬ dcopy;
RETURN};
END.