GriffinInputImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Created by: Maureen Stone February 2, 1983 5:53 pm
Edited by: Maureen Stone February 2, 1983 5:53 pm
Last Edited by: Ken Pier, November 13, 1985 4:42:45 pm PST
DIRECTORY
GriffinData USING [DataRec],
GriffinGrid USING [Grid],
GriffinInput USING [InputData, InputEvent, InputEventProc, InputEventRec, InputEventRef],
GriffinKernel USING [DataRec],
GriffinMenu USING [BugItem, ClearMenuItem, HighlightMenuItem, IsOverItem, MenuItemHandle, OverWhichItem],
GriffinObject USING [CopyObjects, DeleteControlPoint, DeselectObjects, MoveObjects, PlaceControlPoint, SelectObjects],
GriffinPoint USING [ScrPt],
GriffinUserMessage USING [ShowUserMessage, UserMessage],
GriffinViewer USING [SetCursor],
List USING [AList, Assoc, PutAssoc],
Process USING [Detach],
ProcessProps USING [AddPropList, GetPropList];
GriffinInputImpl: CEDAR MONITOR
IMPORTS GriffinGrid, GriffinMenu, GriffinObject, GriffinUserMessage, GriffinViewer, List, Process, ProcessProps
EXPORTS GriffinInput, GriffinKernel = BEGIN
Data: TYPE = REF DataRec;
DataRec: PUBLIC TYPE = GriffinData.DataRec;
InputEventRef: TYPE = GriffinInput.InputEventRef;
InputEventRec: TYPE = GriffinInput.InputEventRec;
condition: CONDITION;
events: RECORD [first, last: InputEventRef ← NIL]; --incoming events
downStroke: GriffinInput.InputEvent;
item: GriffinMenu.MenuItemHandle ← NIL;
mouseDown: BOOLEANFALSE;
overSameItem: BOOLEANFALSE;
aborted: BOOLEANFALSE;
viewer: ViewerClasses.Viewer;
NewEventProc: ENTRY GriffinInput.InputEventProc = { --PROC [data: Data, event: InputEvent]
ENABLE UNWIND => NULL;
nData: Data ← data; -- need to do this to bind opaque/concrete datas
new: InputEventRef ← NEW[InputEventRec ← [next: NIL, input: event]];
IF nData.inputData.lastEvent=NIL THEN nData.inputData.firstEvent ← new
ELSE nData.inputData.lastEvent.next ← new;
nData.inputData.lastEvent ← new;
NOTIFY nData.inputData.condition;
};
StartInputHandler: PUBLIC PROC [data: Data] RETURNS [GriffinInput.InputEventProc] = TRUSTED {
wd: REF ANY ← List.Assoc[key: $WorkingDirectory, aList: ProcessProps.GetPropList[]];
Process.Detach[FORK WorkingProcess[data, wd]];
RETURN[NewEventProc]
};
WaitAndCopy: ENTRY PROC [data: Data] RETURNS [GriffinInput.InputEvent] = {
ENABLE UNWIND => NULL;
copy: GriffinInput.InputEvent;
nData: Data ← data; -- need to do this to bind opaque/concrete datas
IF nData.inputData.firstEvent=NIL THEN WAIT nData.inputData.condition;
copy ← nData.inputData.firstEvent.input;
nData.inputData.firstEvent ← nData.inputData.firstEvent.next;
IF nData.inputData.firstEvent = NIL THEN nData.inputData.lastEvent ← NIL;
RETURN[copy];
};
WorkingProcess: PROC [data: Data, wd: REF ANY] = {
inner: SAFE PROC = {
DO
HandleInputEvent[data: data, event: WaitAndCopy[data]]; --WaitAndCopy is monitored
ENDLOOP;
};
list: List.AList = List.PutAssoc[key: $WorkingDirectory, val: wd, aList: NIL];
ProcessProps.AddPropList[list, inner]; --this adds list to the process prop list for the duration of the call to inner
};
HandleInputEvent: GriffinInput.InputEventProc = { --PROC [data: Data, event: InputEvent]
nData: Data ← data; -- need to do this to bind opaque/concrete datas
{ -- to put nData in the scope of the following ENABLE
ENABLE GriffinUserMessage.UserMessage => {
GriffinUserMessage.ShowUserMessage[nData, string];
AbortCleanup[nData.inputData];
CONTINUE;
};
up, down: GriffinPoint.ScrPt;
newItem: GriffinMenu.MenuItemHandle ← NIL;
SELECT event.type FROM
red, yellow, blue => {
nData.inputData.downStroke ← event;
nData.inputData.mouseDown ← TRUE;
nData.inputData.overSameItem ← TRUE;
nData.inputData.menuItem ← GriffinMenu.OverWhichItem[nData, event.pt];
IF nData.inputData.menuItem # NIL THEN GriffinMenu.HighlightMenuItem[nData.inputData.menuItem];
};
abort => {
nData.inputData.aborted ← TRUE;
AbortCleanup[nData.inputData];
GriffinViewer.SetCursor[abortCursor];
};
up => {
IF nData.inputData.aborted THEN {
nData.inputData.aborted ← FALSE;
AbortCleanup[nData.inputData];
RETURN;
};
GriffinViewer.SetCursor[busyCursor];
nData.inputData.mouseDown ← FALSE;
nData.inputData.overSameItem ← FALSE;
down ← nData.inputData.downStroke.pt;
up ← event.pt;
IF (newItem ← nData.inputData.menuItem) # NIL THEN { --downstroke was over menu
IF GriffinMenu.IsOverItem[up, newItem] THEN GriffinMenu.BugItem[newItem];
GriffinMenu.ClearMenuItem[newItem];
GriffinViewer.SetCursor[pointingCursor];
nData.inputData.menuItem ← NIL;
RETURN;
};
SELECT nData.inputData.downStroke.type FROM
red => { -- ctrl forces move/copy to grid point
IF ~event.ctrl THEN down ← GriffinGrid.Grid[nData, down];
up ← GriffinGrid.Grid[nData, up];
IF event.shift THEN GriffinObject.CopyObjects[nData, down, up, FALSE]
ELSE GriffinObject.MoveObjects[nData, down, up, FALSE];
};
yellow => { -- ctrl ignores gridding
IF ~event.ctrl THEN {
down ← GriffinGrid.Grid[nData, down];
up ← GriffinGrid.Grid[nData, up];
};
IF nData.inputData.menuItem = NIL THEN IF event.shift
THEN GriffinObject.DeleteControlPoint[nData, down, up]
ELSE GriffinObject.PlaceControlPoint[nData, up];
};
blue =>
IF nData.inputData.menuItem = NIL THEN IF event.shift
THEN GriffinObject.DeselectObjects[nData, down, up]
ELSE GriffinObject.SelectObjects[nData, down, up];
ENDCASE;
nData.inputData.menuItem ← NIL;
GriffinViewer.SetCursor[pointingCursor];
};
newPosition =>
IF nData.inputData.mouseDown AND (newItem ← nData.inputData.menuItem) # NIL
THEN IF GriffinMenu.IsOverItem[event.pt, newItem]
THEN {
IF ~ nData.inputData.overSameItem THEN GriffinMenu.HighlightMenuItem[newItem];
nData.inputData.overSameItem ← TRUE;
}
ELSE {
IF nData.inputData.overSameItem THEN GriffinMenu.ClearMenuItem[newItem];
nData.inputData.overSameItem ← FALSE;
};
ENDCASE;
};
};
AbortCleanup: PROC [inputData: REF GriffinInput.InputData] = {
GriffinViewer.SetCursor[pointingCursor];
IF inputData.menuItem # NIL THEN GriffinMenu.ClearMenuItem[inputData.menuItem];
inputData.menuItem ← NIL;
inputData.mouseDown ← FALSE;
inputData.overSameItem ← FALSE;
};
END.