-- FastMouse.mesa
-- Revised by McGregor: June 24, 1983 4:54 pm
-- Revised by Randy Gobbel: 10-May-83 9:56:34
-- Written by: CharlieLevy
Last Edited by: Beach, September 1, 1983 2:08 pm
Last Edited by: Spreitzer, November 18, 1984 4:13:53 pm PST
Revised by: Crow, February 15, 1984 2:32:48 pm PST for Cedar 5.1
DIRECTORY
Commander USING [Handle, Register],
Terminal USING [Current, Position, GetMousePosition, SetMousePosition, WaitForBWVerticalRetrace, Virtual],
Interminal USING [GetMousePosition],
IO USING [EndOf, GetTokenRope, RIS, SkipWhitespace, STREAM],
Process USING [SetPriority, priorityClient3],
PrincOpsUtils USING [VERSION],
UserProfile USING [ProfileChangedProc, Number, Token, CallWhenProfileChanges],
Rope USING [Equal, ROPE];
FastMouse:
CEDAR
MONITOR
IMPORTS Commander, Terminal, Interminal, IO, Process, PrincOpsUtils, UserProfile, Rope
~ BEGIN
ROPE: TYPE = Rope.ROPE;
mouseProcess: PROCESS ← NIL;
vt: Terminal.Virtual;
position, prevPosition: Terminal.Position;
width: NAT;
height: NAT;
cursorInColorDisplay: BOOLEAN ← FALSE;
speedUpLinear: BOOLEAN ← TRUE; -- Acceleration law (linear or squared)
threshold: INTEGER ← 2;
ampxTen: INTEGER ← 15;
enabled: BOOL ← TRUE;
shouldRun: BOOL ← TRUE;
running: BOOL ← FALSE;
ShouldRun:
ENTRY
PROC
RETURNS [run:
BOOL] = {
IF NOT (run ← shouldRun) THEN RETURN;
IF running THEN RETURN [FALSE];
running ← TRUE;
};
NoteNotRunning: ENTRY PROC = {running ← FALSE};
DoradoMouseProcess:
PROCEDURE =
BEGIN
IF
NOT ShouldRun[]
THEN
RETURN;
{ENABLE UNWIND => NoteNotRunning[];
Process.SetPriority[Process.priorityClient3]; -- this priority is one below fault handlers
vt ← Terminal.Current[];
prevPosition ← Terminal.GetMousePosition[vt];
width ← vt.bwWidth;
height ← vt.bwHeight;
WHILE shouldRun
DO
amp, xDelta, yDelta: INTEGER;
Terminal.WaitForBWVerticalRetrace[vt];
position ← Terminal.GetMousePosition[vt];
IF prevPosition = position THEN LOOP;
TRUSTED {
IF cursorInColorDisplay # Interminal.GetMousePosition[].color
THEN {
prevPosition ← position;
cursorInColorDisplay ← Interminal.GetMousePosition[].color;
IF cursorInColorDisplay
THEN { width ← vt.colorWidth; height ← vt.colorHeight; }
ELSE { width ← vt.bwWidth; height ← vt.bwHeight; };
LOOP;
};
};
xDelta ← position.x - prevPosition.x;
yDelta ← position.y - prevPosition.y;
amp ← MAX[ ABS[xDelta], ABS[yDelta] ];
IF amp > threshold
THEN {
IF speedUpLinear
THEN position ← [
-- linear law speedup
MAX[ MIN[ position.x + (xDelta * ampxTen / 10), width], 0],
MAX[ MIN[ position.y + (yDelta * ampxTen / 10), height], 0] ]
ELSE position ← [
-- square law speedup
MAX[ MIN[ position.x + (xDelta * amp / threshold), width], 0],
MAX[ MIN[ position.y + (yDelta * amp / threshold), height], 0] ];
Terminal.SetMousePosition[vt, position];
};
prevPosition ← position;
ENDLOOP;
};
NoteNotRunning[];
END; -- DoradoMouseProcess
DandelionMouseProcess:
PROCEDURE =
BEGIN
IF
NOT ShouldRun[]
THEN
RETURN;
{ENABLE UNWIND => NoteNotRunning[];
Process.SetPriority[Process.priorityClient3]; -- this priority is one below fault handlers
vt ← Terminal.Current[];
prevPosition ← Terminal.GetMousePosition[vt];
width ← vt.bwWidth;
height ← vt.bwHeight;
WHILE shouldRun
DO
amp, xDelta, yDelta: INTEGER;
Terminal.WaitForBWVerticalRetrace[vt];
position ← Terminal.GetMousePosition[vt];
IF prevPosition = position THEN LOOP;
xDelta ← position.x - prevPosition.x;
yDelta ← position.y - prevPosition.y;
amp ← MAX[ ABS[xDelta], ABS[yDelta] ];
IF amp > threshold THEN {
IF speedUpLinear
THEN position ← [ -- linear law speedup
MAX[ MIN[ position.x + (xDelta + xDelta/2), width], 0],
MAX[ MIN[ position.y + (yDelta + yDelta/2), height], 0] ]
ELSE position ← [ -- square law speedup
MAX[ MIN[ position.x + (xDelta * amp / threshold), width], 0],
MAX[ MIN[ position.y + (yDelta * amp / threshold), height], 0] ];
Terminal.SetMousePosition[vt, position];
};
prevPosition ← position;
ENDLOOP;
};
NoteNotRunning[];
END; -- MouseProcess
FastMouseCmd:
PROC [cmd: Commander.Handle]
RETURNS [result:
REF
ANY ←
NIL, msg:
ROPE ←
NIL]
-- Commander.CommandProc-- =
BEGIN
in: IO.STREAM ← IO.RIS[cmd.commandLine];
ok, on: BOOL ← FALSE;
[] ← in.SkipWhitespace[];
IF
NOT in.EndOf[]
THEN {
arg: ROPE ← in.GetTokenRope[].token;
[] ← in.SkipWhitespace[];
IF NOT in.EndOf[] THEN NULL
ELSE IF arg.Equal["on", FALSE] THEN {ok ← TRUE; on ← TRUE}
ELSE IF arg.Equal["off", FALSE] THEN {ok ← TRUE; on ← FALSE};
};
IF ok
THEN {enabled ← on; HandleChange[]}
ELSE {result ← $Failure; msg ← "Usage: FastMouse on|off"}
END;
ProcessProfile: UserProfile.ProfileChangedProc =
TRUSTED
BEGIN
enableToken: ROPE ← UserProfile.Token["FastMouse.Enabled", "UNSPECIFIED"];
IF enableToken.Equal["TRUE"] THEN enabled ← TRUE ELSE
IF enableToken.Equal["FALSE"] THEN enabled ← FALSE;
threshold ← UserProfile.Number["FastMouse.Threshold", 2];
ampxTen ← UserProfile.Number["FastMouse.AmpxTen", 15];
speedUpLinear ← Rope.Equal[UserProfile.Token["FastMouse.SpeedUp", "linear"], "linear"];
HandleChange[];
END;
HandleChange:
ENTRY
PROC = {
shouldRun ← enabled;
IF shouldRun
AND
NOT running
THEN
SELECT PrincOpsUtils.
VERSION[].machineType
FROM
dorado => mouseProcess ← FORK DoradoMouseProcess[];
dandelion => mouseProcess ← FORK DandelionMouseProcess[];
dolphin => mouseProcess ← FORK DoradoMouseProcess[];
ENDCASE;
};
Init:
PROCEDURE =
BEGIN
UserProfile.CallWhenProfileChanges[ProcessProfile];
Commander.Register[key: "FastMouse", proc: FastMouseCmd, doc: "Turn mouse speedup on or off"];
END;
Init[];
END.