<<>> <> <> <> <> <<>> DIRECTORY DeviceClassTypes, DeviceTypes, FastTRAPDevice, Rope; FastTRAPDeviceImpl: CEDAR PROGRAM IMPORTS EXPORTS FastTRAPDevice, DeviceTypes = BEGIN Device: TYPE = DeviceTypes.Device; DeviceObj: TYPE = DeviceTypes.DeviceObj; DeviceClass: PUBLIC TYPE = DeviceClassTypes.DeviceClass; DeviceClassObj: PUBLIC TYPE = DeviceClassTypes.DeviceClassObj; DeviceState: TYPE = DeviceTypes.DeviceState; DeviceStateObj: TYPE = DeviceTypes.DeviceStateObj; DeviceStateChange: TYPE = DeviceTypes.DeviceStateChange; DeviceStateChangeObj: TYPE = DeviceTypes.DeviceStateChangeObj; KeyName: TYPE = FastTRAPDevice.KeyName; ROPE: TYPE = Rope.ROPE; FastTRAPData: TYPE = REF FastTRAPDataObj; FastTRAPDataObj: TYPE = RECORD [ name: ROPE ]; FastTRAPState: TYPE = REF FastTRAPStateObj; FastTRAPStateObj: TYPE = RECORD [ wheel: INTEGER, x, y: INTEGER, -- trackball coordinates buttonDown: ARRAY KeyName OF BOOL ]; fastTRAPClass: DeviceClass ¬ NEW[DeviceClassObj ¬ [$FastTRAP, GetFastTRAPState]]; <> GetFastTRAPState: DeviceClassTypes.GetDeviceStateProc = { <> state ¬ AllocateState[device]; }; CreateFastTRAP: PUBLIC PROC [name: Rope.ROPE] RETURNS [device: Device] = { <> data: FastTRAPData ¬ NEW[FastTRAPDataObj ¬ [name: name]]; device ¬ NEW[DeviceObj]; device.class ¬ fastTRAPClass; device.data ¬ data; device.name ¬ name; }; AllocateState: PUBLIC PROC [device: Device] RETURNS [deviceState: DeviceState] = { <> state: FastTRAPState ¬ NEW[FastTRAPStateObj ¬ [wheel: 0, x: 0, y: 0, buttonDown: [FALSE, FALSE, FALSE]]]; deviceState ¬ NEW[DeviceStateObj]; deviceState.class ¬ device.class; deviceState.state ¬ state; }; <<>> CopyState: PROC [deviceState: DeviceState] RETURNS [copy: DeviceState] = { old: FastTRAPState ¬ NARROW[deviceState.state]; state: FastTRAPState ¬ NEW[FastTRAPStateObj ¬ [wheel: old.wheel, x: old.x, y: old.y, buttonDown: old.buttonDown]]; copy ¬ NEW[DeviceStateObj]; copy.class ¬ deviceState.class; copy.state ¬ state; }; <> buttonDownChange: ARRAY KeyName OF ARRAY BOOL OF DeviceStateChange; trackballChange: ARRAY [-4..4] OF ARRAY [-4..4] OF DeviceStateChange; wheelChange: ARRAY [-4..4] OF DeviceStateChange; Init: PROC = { buttonDownChange[left][FALSE] ¬ KeyChangeCreate[left, FALSE]; buttonDownChange[left][TRUE] ¬ KeyChangeCreate[left, TRUE]; buttonDownChange[middle][FALSE] ¬ KeyChangeCreate[middle, FALSE]; buttonDownChange[middle][TRUE] ¬ KeyChangeCreate[middle, TRUE]; buttonDownChange[right][FALSE] ¬ KeyChangeCreate[right, FALSE]; buttonDownChange[right][TRUE] ¬ KeyChangeCreate[right, TRUE]; FOR i: INT IN [-4..4] DO FOR j: INT IN [-4..4] DO trackballChange[i][j] ¬ TrackballChangeCreate[i, j]; ENDLOOP; wheelChange[i] ¬ WheelChangeCreate[i]; ENDLOOP; }; KeyChange: PUBLIC PROC [key: KeyName, down: BOOL] RETURNS [change: DeviceStateChange] = { change ¬ buttonDownChange[key][down]; }; TrackballChange: PUBLIC PROC [deltaX, deltaY: INTEGER] RETURNS [change: DeviceStateChange] = { IF deltaX IN [-4..4] AND deltaY IN [-4..4] THEN change ¬ trackballChange[deltaX][deltaY] ELSE { change ¬ TrackballChangeCreate[deltaX, deltaY]; }; }; ThumbwheelChange: PUBLIC PROC [delta: INTEGER] RETURNS [change: DeviceStateChange] = { IF delta IN [-4..4] THEN change ¬ wheelChange[delta] ELSE { change ¬ WheelChangeCreate[delta]; }; }; KeyChangeCreate: PROC [key: KeyName, down: BOOL] RETURNS [dsChange: DeviceStateChange] ~ { change: FastTRAPChange ¬ NEW[FastTRAPChangeObj]; change.type ¬ key; change.key ¬ key; change.down ¬ down; dsChange ¬ NEW[DeviceStateChangeObj]; dsChange.class ¬ fastTRAPClass; dsChange.change ¬ change; }; TrackballChangeCreate: PROC [deltaX, deltaY: INTEGER] RETURNS [dsChange: DeviceStateChange] ~ { change: FastTRAPChange ¬ NEW[FastTRAPChangeObj]; change.type ¬ trackball; change.deltaX ¬ deltaX; change.deltaY ¬ deltaY; dsChange ¬ NEW[DeviceStateChangeObj]; dsChange.class ¬ fastTRAPClass; dsChange.change ¬ change; }; WheelChangeCreate: PROC [delta: INTEGER] RETURNS [dsChange: DeviceStateChange] ~ { change: FastTRAPChange ¬ NEW[FastTRAPChangeObj]; change.type ¬ wheel; change.deltaX ¬ delta; dsChange ¬ NEW[DeviceStateChangeObj]; dsChange.class ¬ fastTRAPClass; dsChange.change ¬ change; }; FastTRAPChange: TYPE = REF FastTRAPChangeObj; FastTRAPChangeObj: TYPE = RECORD [ type: ChangeType, key: KeyName ¬ left, down: BOOL, deltaX, deltaY: INTEGER ¬ 0 ]; ChangeType: TYPE = {key, trackball, wheel}; StateAfterChange: PUBLIC PROC [deviceState: DeviceState, change: DeviceStateChange] RETURNS [newDeviceState: DeviceState] = { ftChange: FastTRAPChange ¬ NARROW[change.change]; SELECT ftChange.type FROM key => newDeviceState ¬ KeyMotion[deviceState, ftChange.key, ftChange.down]; trackball => newDeviceState ¬ TrackballMotion[deviceState, ftChange.deltaX, ftChange.deltaY]; wheel => newDeviceState ¬ ThumbwheelMotion[deviceState, ftChange.deltaX]; ENDCASE => ERROR; }; ExpandedChange: TYPE = FastTRAPDevice.ExpandedChange; UnpackChange: PUBLIC PROC [change: DeviceStateChange] RETURNS [expanded: ExpandedChange] = { ftChange: FastTRAPChange ¬ NARROW[change.change]; SELECT ftChange.type FROM key => expanded ¬ [key[ftChange.key, ftChange.down]]; trackball => expanded ¬ [trackball[ftChange.deltaX, ftChange.deltaY]]; wheel => expanded ¬ [wheel[ftChange.deltaX]]; ENDCASE => ERROR; }; <> KeyMotion: PUBLIC PROC [deviceState: DeviceState, key: KeyName, down: BOOL] RETURNS [newDeviceState: DeviceState] = { newDeviceState ¬ CopyState[deviceState]; NARROW[newDeviceState.state, FastTRAPState].buttonDown[key] ¬ down; }; TrackballMotion: PUBLIC PROC [deviceState: DeviceState, deltaX, deltaY: INTEGER] RETURNS [newDeviceState: DeviceState] = { newState, oldState: FastTRAPState; newDeviceState ¬ CopyState[deviceState]; newState ¬ NARROW[newDeviceState.state]; oldState ¬ NARROW[deviceState.state]; newState.x ¬ oldState.x + deltaX; newState.y ¬ oldState.y + deltaY; }; ThumbwheelMotion: PUBLIC PROC [deviceState: DeviceState, delta: INTEGER] RETURNS [newDeviceState: DeviceState] = { newDeviceState ¬ CopyState[deviceState]; NARROW[newDeviceState.state, FastTRAPState].wheel ¬ NARROW[deviceState.state, FastTRAPState].wheel + delta; }; <> <<>> IsDown: PUBLIC PROC [deviceState: DeviceState, key: KeyName] RETURNS [BOOL] = { state: FastTRAPState ¬ NARROW[deviceState.state]; RETURN[state.buttonDown[key]]; }; GetTrackball: PUBLIC PROC [deviceState: DeviceState] RETURNS [x, y: INTEGER] = { state: FastTRAPState ¬ NARROW[deviceState.state]; x ¬ state.x; y ¬ state.y; }; GetThumbwheel: PUBLIC PROC [deviceState: DeviceState] RETURNS [wheel: INTEGER] = { state: FastTRAPState ¬ NARROW[deviceState.state]; wheel ¬ state.wheel; }; Init[]; END.