<> <> <> DIRECTORY Process USING [Detach], List USING [Assoc, PutAssoc, AList], ProcessProps USING [AddPropList, GetPropList], MenuDefs USING [OverWhichItem, HighlightMenuItem, ClearMenuItem, IsOverItem, BugItem, MenuItemHandle], CursorDefs USING [SetCursor], OpDefs USING [CopyObjects, MoveObjects, DeleteControlPoint, PlaceControlPoint, DeselectObjects, SelectObjects], GriffinDefs USING [ShowUserMessage, UserMessage], GriffinGrid USING [Grid], ViewerClasses USING [Viewer], GriffinViewer USING [GetViewer], PointDefs USING [ScrPt], GriffinInputDefs; GriffinInput: CEDAR MONITOR IMPORTS Process, MenuDefs, CursorDefs, GriffinDefs, OpDefs, GriffinViewer, List, ProcessProps, GriffinGrid EXPORTS GriffinInputDefs = BEGIN OPEN GriffinInputDefs; StartInputHandler: PUBLIC PROC RETURNS [InputEventProc] = TRUSTED { wd: REF ANY _ List.Assoc[key: $WorkingDirectory, aList: ProcessProps.GetPropList[]]; viewer _ GriffinViewer.GetViewer[]; Process.Detach[FORK WorkingProcess[wd]]; RETURN[NewEventProc]}; InputEventRef: TYPE = REF InputEventRec; InputEventRec: TYPE = RECORD[next: InputEventRef, input: InputEvent]; events: RECORD [first,last: InputEventRef _ NIL]; --incoming events condition: CONDITION; NewEventProc: ENTRY InputEventProc = { new: InputEventRef _ NEW[InputEventRec _ [next: NIL, input: event]]; IF events.last=NIL THEN events.first_ new ELSE events.last.next _ new; events.last _ new; NOTIFY condition; }; WaitAndCopy: ENTRY PROCEDURE RETURNS [InputEvent] = { copy: InputEvent; IF events.first=NIL THEN WAIT condition; copy _ events.first.input; events.first _ events.first.next; IF events.first = NIL THEN events.last _ NIL; RETURN[copy]; }; WorkingProcess: PROCEDURE[wd: REF ANY] = { inner: SAFE PROC = { DO HandleInputEvent[WaitAndCopy[]]; --WaitAndCopy is monitored ENDLOOP; }; list: List.AList ~ List.PutAssoc[key: $WorkingDirectory, val: wd, aList: NIL]; ProcessProps.AddPropList[list, inner]; }; <> downStroke: GriffinInputDefs.InputEvent; item: MenuDefs.MenuItemHandle _ NIL; mouseDown: BOOLEAN _ FALSE; overSameItem: BOOLEAN _ FALSE; aborted: BOOLEAN _ FALSE; viewer: ViewerClasses.Viewer; HandleInputEvent: InputEventProc = BEGIN ENABLE GriffinDefs.UserMessage => BEGIN GriffinDefs.ShowUserMessage[string]; AbortCleanup; CONTINUE; END; up,down: PointDefs.ScrPt; SELECT event.type FROM red,yellow,blue => BEGIN downStroke _ event; mouseDown _ TRUE; overSameItem _ TRUE; item _ MenuDefs.OverWhichItem[event.pt]; IF item # NIL THEN MenuDefs.HighlightMenuItem[item]; END; abort => BEGIN aborted_TRUE; AbortCleanup; CursorDefs.SetCursor[abortCursor]; END; up=> BEGIN IF aborted THEN BEGIN aborted_FALSE; AbortCleanup; RETURN END; CursorDefs.SetCursor[busyCursor]; mouseDown _ FALSE; overSameItem _ FALSE; down _ downStroke.pt; up _ event.pt; <> IF item # NIL THEN --downstroke was over menu BEGIN IF MenuDefs.IsOverItem[up, item] THEN MenuDefs.BugItem[item]; MenuDefs.ClearMenuItem[item]; CursorDefs.SetCursor[pointingCursor]; item _ NIL; RETURN END; SELECT downStroke.type FROM red => BEGIN down _ GriffinGrid.Grid[down]; up _ GriffinGrid.Grid[up]; IF event.shifted THEN OpDefs.CopyObjects[down,up] ELSE OpDefs.MoveObjects[down,up]; END; yellow => BEGIN down _ GriffinGrid.Grid[down]; up _ GriffinGrid.Grid[up]; IF item = NIL THEN IF event.shifted THEN OpDefs.DeleteControlPoint[down,up] ELSE OpDefs.PlaceControlPoint[up]; END; blue => IF item = NIL THEN IF event.shifted THEN OpDefs.DeselectObjects[down,up] ELSE OpDefs.SelectObjects[down,up]; ENDCASE; item _ NIL; CursorDefs.SetCursor[pointingCursor]; END; newPosition => IF mouseDown AND item # NIL THEN IF MenuDefs.IsOverItem[event.pt, item] THEN BEGIN IF ~ overSameItem THEN MenuDefs.HighlightMenuItem[item]; overSameItem _ TRUE; END ELSE BEGIN IF overSameItem THEN MenuDefs.ClearMenuItem[item]; overSameItem _ FALSE; END; keyStroke => BEGIN GriffinDefs.ShowUserMessage["Use the Caption menu in the Edit menus"]; END; ENDCASE; END; AbortCleanup: PROCEDURE = BEGIN CursorDefs.SetCursor[pointingCursor]; IF item # NIL THEN MenuDefs.ClearMenuItem[item]; item _ NIL; mouseDown _ FALSE; overSameItem _ FALSE; END; END.