DIRECTORY Atom, BasicTime, BiScrollers, Convert, Feedback, GGActive, GGBasicTypes, GGControlPanelTypes, GGCoreOps, GGCoreTypes, GGEmbedTypes, GGEvent, GGFont, GGInterfaceTypes, GGModelTypes, GGSlice, GGState, GGTransform, GGUserInput, GGUserProfile, GGWindow, GGWorld, Imager, ImagerTransformation, InputFocus, IO, List, Menus, Process, Real, RealFns, RefTab, Rope, SlackProcess, TIPUser, UserProfile, Vector2, ViewerClasses, ViewerTools; GGUserImpl: CEDAR MONITOR IMPORTS Atom, BasicTime, BiScrollers, Convert, Feedback, GGActive, GGCoreOps, GGEvent, GGFont, GGSlice, GGState, GGTransform, GGUserInput, GGWindow, ImagerTransformation, InputFocus, IO, List, Process, RealFns, RefTab, Rope, SlackProcess, UserProfile, ViewerTools EXPORTS GGInterfaceTypes, GGUserInput, GGUserProfile = BEGIN Camera: TYPE = GGModelTypes.Camera; ControlsObj: PUBLIC TYPE = GGControlPanelTypes.ControlsObj; -- exported to GGInterfaceTypes EmbedDataObj: PUBLIC TYPE = GGEmbedTypes.EmbedDataObj; -- exported to GGInterfaceTypes Event: TYPE = GGCoreTypes.Event; EventListt: TYPE = GGCoreTypes.EventListt; External: TYPE = GGUserInput.External; ExternalRec: TYPE = GGUserInput.ExternalRec; FeatureData: TYPE = GGModelTypes.FeatureData; FontData: TYPE = GGModelTypes.FontData; GGData: TYPE = GGInterfaceTypes.GGData; Point: TYPE = GGBasicTypes.Point; RawInputHandlerProc: TYPE = GGUserInput.RawInputHandlerProc; Scene: TYPE = GGModelTypes.Scene; SlackHandle: TYPE = SlackProcess.SlackHandle; Slice: TYPE = GGModelTypes.Slice; SliceDescriptor: TYPE = GGModelTypes.SliceDescriptor; Transformation: TYPE = ImagerTransformation.Transformation; UserInputProc: TYPE = GGUserInput.UserInputProc; VEC: TYPE = Imager.VEC; Viewer: TYPE = ViewerClasses.Viewer; Problem: PUBLIC SIGNAL [msg: Rope.ROPE] = Feedback.Problem; externalCV: CONDITION; WaitExternal: PUBLIC ENTRY PROC [External] = { WAIT externalCV; }; BroadcastExternal: PUBLIC ENTRY PROC [External] = { BROADCAST externalCV; }; NotifyExternal: PUBLIC ENTRY PROC [External] = { NOTIFY externalCV; }; EventNotify: PUBLIC PROC [clientData: REF ANY, event: LIST OF REF ANY] = { ggData: GGData _ NARROW[clientData]; ProcessAndQueueEvent[event, ggData]; }; UnQueuedEventNotify: PUBLIC PROC [clientData: REF ANY, event: LIST OF REF ANY] = { ggData: GGData ~ NARROW[clientData]; atom: ATOM ~ NARROW[event.first]; regEvent: RegisteredEvent ~ FetchAction[atom]; IF regEvent=NIL THEN { NotYetImplementedMessage[atom, ggData]; } ELSE { event _ GetAnyArguments[event, regEvent, ggData]; TRUSTED {Process.Detach[FORK regEvent.eventProc[ggData, event] ]; }; }; }; PlayAction: PUBLIC PROC [clientData: REF ANY, event: LIST OF REF ANY] = { ggData: GGData _ NARROW[clientData]; IF event.first = $Version OR event.first = $Store OR event.first = $Save OR event.first = $ToIP OR event.first = $ToIPScreen OR event.first = $ToIPLit OR event.first = $IPToTioga OR event.first = $IPToTiogaBordered OR event.first = $IPToTiogaFit OR event.first = $IPToTiogaBorderedAndFit OR event.first = $IPToTiogaAlt OR event.first = $StuffToTioga OR event.first = $StuffToFile OR event.first = $MergeFromTioga OR event.first = $StuffToTiogaBordered OR event.first = $StuffToFileAlt OR event.first = $GrabFromTioga OR event.first = $StuffToTiogaFit OR event.first = $GetFromTioga OR event.first = $StuffToTiogaBorderedAndFit OR event.first = $MergeFromGargoyle OR event.first = $StuffToTiogaAlt THEN RETURN; ProcessAndQueueEvent[event, ggData]; }; gRawInputHandler: GGUserInput.RawInputHandlerProc _ DefaultRawInputHandler; DefaultRawInputHandler: PROC [self: Viewer, ggData: GGData, input: LIST OF REF ANY] = { rawInput: GGActive.RawInput ~ GGActive.NarrowRawInput[input]; event: LIST OF REF ANY ~ GGActive.ParseEvent[ggData.parseInfo, rawInput]; IF event # NIL THEN self.class.notify[self, event]; -- self is the BiScroller }; InputNotify: PUBLIC PROC [self: Viewer, input: LIST OF REF] = { ggData: GGData _ NARROW[BiScrollers.ClientDataOfViewer[self]]; IF GGActive.IsRawInput[input] THEN { -- raw input gRawInputHandler[self, ggData, input]; } ELSE { InputFocus.SetInputFocus[ggData.controls.actionArea]; ProcessAndQueueEvent[input, ggData]; }; }; BiScrollerInputNotify: PUBLIC BiScrollers.BSUserActionProc = { ggData: GGData _ NARROW[BiScrollers.ClientDataOf[bs]]; ProcessAndQueueEvent[input, ggData]; }; finishText: LIST OF REF ANY ~ LIST[$SawTextFinish]; finishMouse: LIST OF REF ANY ~ LIST[$SawMouseFinish]; ProcessAndQueueEvent: PROC [event: LIST OF REF ANY, ggData: GGData] = { IF ggData.embed.beingBorn THEN RETURN; -- don't handle events while the window is being created WITH event.first SELECT FROM refChar: REF CHAR => { myRefChar: REF CHAR ~ NEW[CHAR _ refChar^]; event _ LIST[$AddChar, myRefChar]; }; atom: ATOM => { regEvent: RegisteredEvent ~ FetchAction[atom]; IF regEvent=NIL THEN NotYetImplementedMessage[atom, ggData] ELSE { atomName: Rope.ROPE ~ Atom.GetPName[atom]; startAction: BOOL ~ Rope.Equal[Rope.Substr[atomName, 0, 5], "Start", TRUE]; IF startAction THEN QueueInput[ggData, finishText]; -- need this before selection changes IF regEvent.causeMouseEventsToComplete THEN QueueInput[ggData, finishMouse]; event _ GetAnyArguments[event, regEvent, ggData]; IF atom = $OneScroll THEN { x, y: INTEGER _ 0; IF event.rest # NIL THEN { WITH event.rest.first SELECT FROM i: REF INTEGER => x _ i^; ENDCASE; IF event.rest.rest # NIL THEN { WITH event.rest.rest.first SELECT FROM i: REF INTEGER => y _ i^; ENDCASE; }; }; ggData.embed.scrollDue _ ggData.embed.scrollDue.PostTranslate[[x, y]]; } ELSE IF atom = $OneZoom THEN { x: INTEGER _ 0; fx, scalar: REAL; viewport: Imager.Rectangle _ GGState.GetViewport[ggData]; origin: Point _ [viewport.w/2.0, viewport.h/2.0]; IF event.rest # NIL THEN { WITH event.rest.first SELECT FROM i: REF INTEGER => x _ i^; ENDCASE; }; fx _ x; -- convert to float scalar _ RealFns.Power[2.0, fx/50.0]; -- fifty clicks of the track ball gives a factor of two ggData.embed.scrollDue _ ggData.embed.scrollDue.Concat[GGTransform.ScaleAboutPoint[origin, scalar]]; }; }; }; ENDCASE => ERROR; QueueInput[ggData, event, NIL]; }; Timestamp: TYPE = REF TimestampObj; TimestampObj: TYPE = RECORD [ startTime: CARD32 ]; timeQueue: BOOL _ FALSE; QueueInput: PROC [ggData: GGData, event: LIST OF REF ANY, optimizeHint: REF ANY _ NIL] ~ { handle: SlackHandle ~ ggData.slackHandle; GGEvent.PrintAllInput[ggData, event]; -- KAP IF timeQueue THEN event _ List.Nconc1[event, NEW[TimestampObj _ [NowInMilliseconds[]]] ]; -- for timing how much time is spent on the queue SlackProcess.QueueAction[handle, Dispatch, event, ggData, optimizeHint]; }; GetAnyArguments: PROC [event: LIST OF REF ANY, regEvent: RegisteredEvent, ggData: GGData] RETURNS [newEvent: LIST OF REF ANY] = { atom: ATOM _ NARROW[event.first]; SELECT regEvent.argType FROM none => newEvent _ event; rope => newEvent _ CheckForSelectedRope[atom, event]; rope2 => newEvent _ CheckForSelectedRope2[atom, event]; refReal => newEvent _ CheckForSelectedReal[atom, event]; refInt => newEvent _ CheckForSelectedInt[atom, event]; refCard => newEvent _ CheckForSelectedCard[atom, event]; refExt => newEvent _ CheckForActualExt[atom, event]; ENDCASE => ERROR; }; RegisterRawInputHandler: PUBLIC PROC [rawInputHandler: RawInputHandlerProc] = { gRawInputHandler _ rawInputHandler; }; NowInMilliseconds: PROC RETURNS [CARD32] = { RETURN[(BasicTime.PulsesToMicroseconds[BasicTime.GetClockPulses[]]+500)/1000]; }; PrintUserTrace: PROC [ggData: GGInterfaceTypes.GGData, eventProc: GGUserInput.UserInputProc, event: LIST OF REF ANY] ~ { procName: Rope.ROPE _ "?"; moduleName: Rope.ROPE _ "?"; thisArgName: Rope.ROPE; allArgs: Rope.ROPE; FOR list: LIST OF REF ANY _ event, list.rest UNTIL list = NIL DO thisArgName _ IO.PutFR["%g", [refAny[list.first]] ]; IF allArgs = NIL THEN allArgs _ thisArgName ELSE allArgs _ Rope.Cat[allArgs, ", ", thisArgName]; ENDLOOP; Feedback.PutF[ggData.router, oneLiner, $Typescript, "%g.%g[%g]", [rope[moduleName]], [rope[procName]], [rope[allArgs]] ]; }; Dispatch: PROC [clientData: REF ANY, inputAction: REF] = { ggData: GGData ~ NARROW[clientData]; atom: ATOM; startTime, endTime: CARD32; startTimeRef: REF; regEvent: RegisteredEvent; event: LIST OF REF _ NARROW[inputAction]; UpdateCoords: PROC [input: LIST OF REF] RETURNS [o: LIST OF REF] = { i, l: LIST OF REF; FOR i _ input, i.rest WHILE i # NIL DO l _ IF l = NIL THEN o _ CONS[i.first, NIL] ELSE l.rest _ CONS[i.first, NIL]; WITH l.first SELECT FROM z: TIPUser.TIPScreenCoords => { viewerToClient: Transformation _ GGState.GetBiScrollersTransforms[ggData].viewerToClient; l.first _ NEW [Vector2.VEC _ viewerToClient.Transform[[z.mouseX, z.mouseY]]]; }; ENDCASE; ENDLOOP; }; event _ UpdateCoords[event]; -- perform the BiScrollers transform IF timeQueue THEN { startTimeRef _ List.NthElement[event, -1]; WITH startTimeRef SELECT FROM timeStamp: Timestamp => { startTime _ timeStamp.startTime; event _ List.DRemove[startTimeRef, event]; endTime _ NowInMilliseconds[]; }; ENDCASE; }; atom _ NARROW[event.first]; regEvent _ FetchAction[atom]; IF regEvent=NIL THEN NotYetImplementedMessage[atom, ggData] ELSE { IF event.first=$Again THEN { IF NOT GGCoreOps.NoEvents[ggData.lastEvents] THEN { FOR list: LIST OF Event _ ggData.lastEvents.list, list.rest UNTIL list = NIL DO thisEvent: LIST OF REF ANY ~ list.first; thisAtom: ATOM ~ NARROW[thisEvent.first]; thisRegEvent: RegisteredEvent ~ FetchAction[thisAtom]; IF thisRegEvent=NIL THEN NotYetImplementedMessage[thisAtom, ggData] ELSE thisRegEvent.eventProc[ggData, thisEvent]; ENDLOOP; } ELSE {}; -- there is nothing to do again } ELSE { SELECT GetEventClass[atom] FROM select => ggData.justSawSelect _ TRUE; action => { IF ggData.justSawSelect THEN { GGCoreOps.FlushEventListt[ggData.lastEvents]; ggData.justSawSelect _ FALSE; }; GGCoreOps.AppendEvent[event, ggData.lastEvents]; }; suppress => {}; -- $During. Ignore it. neutral => { IF ggData.justSawSelect THEN {} -- this is the during or end of a select operation ELSE GGCoreOps.AppendEvent[event, ggData.lastEvents]; }; ENDCASE => ERROR; IF GGUserInput.GetUserTraceOn[] THEN PrintUserTrace[ggData, regEvent.eventProc, event]; regEvent.eventProc[ggData, event]; }; }; }; EventClass: TYPE = {select, neutral, action, suppress}; GetEventClass: PROC [atom: ATOM] RETURNS [eventClass: EventClass] = { IF ( atom = $During OR atom = $GuardUp OR atom = $MouseUp OR atom = $AllUp OR atom = $SawTextFinish OR atom = $SawMouseFinish ) THEN RETURN [neutral]; IF ( atom = $StartSelectWithBox OR atom = $StartSelectJoint OR atom = $StartExtSelectJoint OR atom = $StartSelectSegment OR atom = $StartExtSelectSegment OR atom = $StartSelectTrajectory OR atom = $StartExtSelectTrajectory OR atom = $StartSelectTopLevel OR atom = $StartExtSelectTopLevel OR atom = $StartExtendSelection OR atom = $StartDeselectJoint OR atom = $StartDeselectSegment OR atom = $StartDeselectTrajectory OR atom = $StartDeselectTopLevel OR atom = $CycleSelection OR atom = $AreaSelectNew OR atom = $AreaSelectNewAndDelete OR atom = $SelectAll OR atom = $AreaSelectDegenerate OR atom = $SelectCoincident OR atom = $SelectUnseeableSegs OR atom = $SelectUnseeableObjs ) THEN RETURN [select]; IF ( atom = $StartCaretPos OR atom = $StartAdd OR atom = $StartBox OR atom = $StartDrag OR atom = $StartCopyAndDrag OR atom = $StartRotate OR atom = $StartScale OR atom = $StartSixPoint ) THEN RETURN [action]; RETURN [action]; }; NotYetImplementedMessage: PROC [atom: ATOM, ggData: GGData] = { Feedback.Append[ggData.router, begin, $Warning, "User event "]; Feedback.Append[ggData.router, middle, $Warning, Atom.GetPName[atom]]; Feedback.Append[ggData.router, end, $Warning, " is not yet implemented"]; }; CheckForSelectedRope: PROC [atom: ATOM, event: LIST OF REF ANY] RETURNS [newAction: LIST OF REF ANY] = { IF event.rest = NIL THEN { -- interactive call r: Rope.ROPE _ ViewerTools.GetSelectionContents[]; newAction _ LIST[atom, r]; } ELSE IF ISTYPE[event.rest.first, REF TEXT] THEN { -- TIP table call newAction _ CONS[atom, CONS[Rope.FromRefText[NARROW[event.rest.first]], event.rest.rest]]; } ELSE newAction _ event; -- SessionLog call }; CheckForSelectedRope2: PROC [atom: ATOM, event: LIST OF REF ANY] RETURNS [newAction: LIST OF REF ANY] = { IF event.rest = NIL THEN ERROR; IF event.rest.rest = NIL THEN { -- interactive call r: Rope.ROPE _ ViewerTools.GetSelectionContents[]; newAction _ LIST[atom, event.rest.first, r]; } ELSE IF ISTYPE[event.rest.rest.first, REF TEXT] THEN { -- TIP table call newAction _ LIST[atom, event.rest.first, Rope.FromRefText[NARROW[event.rest.rest.first]], event.rest.rest.rest]; } ELSE newAction _ event; -- SessionLog call }; CheckForSelectedReal: PROC [atom: ATOM, event: LIST OF REF ANY] RETURNS [newAction: LIST OF REF ANY] = { rope: Rope.ROPE; real: REAL; IF event.rest = NIL THEN { -- interactive call rope _ ViewerTools.GetSelectionContents[]; real _ Convert.RealFromRope[rope ! Convert.Error => {real _ Real.LargestNumber; CONTINUE}]; newAction _ LIST[atom, NEW[REAL _ real]]; } ELSE IF ISTYPE[event.rest.first, REF TEXT] THEN { -- TIP table call rope _ Rope.FromRefText[NARROW[event.rest.first]]; real _ Convert.RealFromRope[rope ! Convert.Error => {real _ Real.LargestNumber; CONTINUE}]; newAction _ LIST[atom, NEW[REAL _ real]]; } ELSE newAction _ event; -- SessionLog call }; CheckForSelectedCard: PROC [atom: ATOM, event: LIST OF REF ANY] RETURNS [newAction: LIST OF REF ANY] = { rope: Rope.ROPE; card: CARD; IF event.rest = NIL THEN { -- interactive call rope _ ViewerTools.GetSelectionContents[]; card _ IO.GetCard[IO.RIS[rope] ! IO.EndOfStream, IO.Error => {card _ LAST[CARD]; CONTINUE}]; newAction _ LIST[atom, NEW[CARD _ card]]; } ELSE IF ISTYPE[event.rest.first, REF CARD] THEN { -- TIP table call or SessionLog call newAction _ event; } ELSE ERROR; }; CheckForSelectedInt: PROC [atom: ATOM, event: LIST OF REF ANY] RETURNS [newAction: LIST OF REF ANY] = { rope: Rope.ROPE; int: INT; IF event.rest = NIL THEN { -- interactive call rope _ ViewerTools.GetSelectionContents[]; int _ IO.GetInt[IO.RIS[rope] ! IO.EndOfStream, IO.Error => {int _ LAST[INT]; CONTINUE}]; newAction _ LIST[atom, NEW[INT _ int]]; } ELSE { WITH event.rest.first SELECT FROM int: REF INT => newAction _ event; -- TIP table call or SessionLog call card: REF CARD => newAction _ List.Append[LIST[atom, NEW[INT _ card^]], event.rest.rest]; -- type coersion ENDCASE => ERROR; }; }; CheckForActualExt: PROC [atom: ATOM, event: LIST OF REF ANY] RETURNS [newAction: LIST OF REF ANY] = { IF event.rest=NIL OR NOT ISTYPE[event.rest.first, REF GGUserInput.ExternalRec] THEN ERROR; newAction _ event; }; RegisteredEvent: TYPE = REF RegisteredEventObj; RegisteredEventObj: TYPE = RECORD [ eventProc: UserInputProc, argType: GGUserInput.ArgumentType, causeMouseEventsToComplete: BOOL ]; RegisterAction: PUBLIC PROC [atom: ATOM, eventProc: UserInputProc, argType: GGUserInput.ArgumentType, causeMouseEventsToComplete: BOOL _ TRUE, ensureUnique: BOOL _ TRUE] = { regEvent: RegisteredEvent _ NEW[RegisteredEventObj _ [eventProc, argType, causeMouseEventsToComplete]]; notAlreadyRegistered: BOOLEAN _ RefTab.Insert[eventTable, atom, regEvent]; IF NOT notAlreadyRegistered THEN IF ensureUnique THEN SIGNAL Problem[msg: IO.PutFR["Event %g was already registered in Gargoyle's event table.", [rope[Atom.GetPName[atom]]]]] ELSE [] _ RefTab.Replace[eventTable, atom, regEvent]; -- register again }; FetchAction: PROC [atom: ATOM] RETURNS [RegisteredEvent] ~ { WITH RefTab.Fetch[eventTable, atom].val SELECT FROM regEvent: RegisteredEvent => RETURN[regEvent]; ENDCASE => RETURN[NIL]; }; LookAtProfile: PUBLIC UserProfile.ProfileChangedProc = { gravExtent: REAL; -- in inches defaultHistorySize: INT; heuristics: BOOL _ UserProfile.Boolean[key: "Gargoyle.Heuristics", default: FALSE]; quickClickMode: BOOL _ UserProfile.Boolean[key: "Gargoyle.QuickClickEnable", default: FALSE]; useLatestIPVersion: BOOL _ UserProfile.Boolean[key: "Gargoyle.UseLatestIPVersion", default: FALSE]; autoOpenTypescript: BOOL _ UserProfile.Boolean[key: "Gargoyle.AutoOpenTypescript", default: TRUE]; autoOpenHistory: BOOL _ UserProfile.Boolean[key: "Gargoyle.AutoOpenHistory", default: TRUE]; autoScriptingOn: BOOL _ UserProfile.Boolean[key: "Gargoyle.AutoScriptingOn", default: FALSE]; separateControlPanel: BOOL _ UserProfile.Boolean[key: "Gargoyle.SeparateControlPanel", default: FALSE]; defaultIncludeIPBy: Rope.ROPE _ UserProfile.Token[key: "Gargoyle.DefaultIncludeIPBy", default: "Reference"]; holdThatTiger: BOOL _ UserProfile.Boolean[key: "Gargoyle.HoldThatTiger", default: FALSE]; newBoxesUnfilled: BOOL _ UserProfile.Boolean[key: "Gargoyle.NewBoxesUnfilled", default: FALSE]; defaultHistorySize _ Convert.IntFromRope[UserProfile.Token[key: "Gargoyle.DefaultHistorySize", default: "40"] ! Convert.Error => IF reason = syntax THEN {defaultHistorySize _ -1; CONTINUE;} ELSE REJECT]; gravExtent _ Convert.RealFromRope[UserProfile.Token[key: "Gargoyle.GravityExtent", default: "-1.0"] ! Convert.Error => IF reason = syntax THEN {gravExtent _ -1.0; CONTINUE;} ELSE REJECT]; IF gravExtent=-1.0 THEN gravExtent _ 25.0/72.0; IF defaultHistorySize<1 THEN defaultHistorySize _ IF defaultHistorySize=0 THEN 1 ELSE 40; SetDefaultHeuristics[on: heuristics]; SetDefaultGravityExtent[inches: gravExtent]; GGState.SetQuickClickMode[quickClickMode]; SetDefaultUseLatestIPVersion[useLatestIPVersion]; SetAutoOpenTypescript[autoOpenTypescript]; SetAutoOpenHistory[autoOpenHistory]; SetDefaultHistorySize[defaultHistorySize]; SetAutoScriptingOn[autoScriptingOn]; SetSeparateControlPanel[separateControlPanel]; SetHoldThatTiger[holdThatTiger]; SetNewBoxesUnfilled[newBoxesUnfilled]; SetDefaultIncludeIPByValue[Rope.Equal[defaultIncludeIPBy, "Value", FALSE]]; BEGIN -- set the default default font description: Rope.ROPE _ UserProfile.Token[key: "Gargoyle.DefaultDefaultFont", default: NIL]; descriptionStream: IO.STREAM; defaultFont: FontData; IF description = NIL THEN description _ "xerox/xc1-2-2/helvetica [r1: 0.0 s: [10.0 10.0] r2: 0.0] 1.0 1.0"; descriptionStream _ IO.RIS[description]; defaultFont _ GGFont.ParseFontData[inStream: descriptionStream, literalP: TRUE, transformP: TRUE, storedSizeP: TRUE, designSizeP: TRUE]; SetDefaultDefaultFont[defaultFont]; END; IF reason#firstTime THEN GGWindow.InitIcons[]; -- don't do this on first registering this proc }; MasterData: TYPE = REF MasterDataObj; MasterDataObj: TYPE = RECORD [ defaultGravityExtent: REAL _ 25.0, -- in screen dots defaultHeuristics: BOOL _ TRUE, objectsBeingCopied: LIST OF REF ANY, -- for copying objects from viewer to viewer, defaultDefaultFont: FontData, autoOpenTypescript: BOOL _ TRUE, autoOpenHistory: BOOL _ TRUE, defaultHistorySize: INT _ 40, autoScriptingOn: BOOL _ TRUE, separateControlPanel: BOOL _ FALSE, defaultIncludeIPByValue: BOOL _ FALSE, holdThatTiger: BOOL _ FALSE, newBoxesUnfilled: BOOL _ FALSE, turboOn: BOOL _ FALSE, userTraceOn: BOOL _ FALSE ]; SetUserTraceOn: PUBLIC PROC [on: BOOL] = { masterData.userTraceOn _ on; }; GetUserTraceOn: PUBLIC PROC RETURNS [on: BOOL] = { on _ masterData.userTraceOn; }; SetDefaultHeuristics: PUBLIC PROC [on: BOOL] = { masterData.defaultHeuristics _ on; }; GetDefaultHeuristics: PUBLIC PROC RETURNS [on: BOOL] = { on _ masterData.defaultHeuristics; }; SetDefaultGravityExtent: PUBLIC PROC [inches: REAL] = { masterData.defaultGravityExtent _ inches*72.0; }; GetDefaultGravityExtent: PUBLIC PROC RETURNS [screenDots: REAL] = { screenDots _ masterData.defaultGravityExtent; }; SetDefaultUseLatestIPVersion: PUBLIC PROC [useLatestIPVersion: BOOL] = { GGSlice.SetDefaultUseLatestIPVersion[useLatestIPVersion]; }; GetDefaultUseLatestIPVersion: PUBLIC PROC [] RETURNS [useLatestIPVersion: BOOL] = { RETURN[GGSlice.GetDefaultUseLatestIPVersion[]]; }; SetDefaultDefaultFont: PUBLIC PROC [font: FontData] = { masterData.defaultDefaultFont _ font; }; GetDefaultDefaultFont: PUBLIC PROC RETURNS [font: FontData] = { font _ masterData.defaultDefaultFont; }; SetAutoOpenTypescript: PUBLIC PROC [autoOpenTypescript: BOOL] = { masterData.autoOpenTypescript _ autoOpenTypescript; }; GetAutoOpenTypescript: PUBLIC PROC [] RETURNS [autoOpenTypescript: BOOL] = { autoOpenTypescript _ masterData.autoOpenTypescript; }; SetAutoOpenHistory: PUBLIC PROC [autoOpenHistory: BOOL] = { masterData.autoOpenHistory _ autoOpenHistory; }; GetAutoOpenHistory: PUBLIC PROC [] RETURNS [autoOpenHistory: BOOL] = { autoOpenHistory _ masterData.autoOpenHistory; }; SetDefaultHistorySize: PUBLIC PROC [defaultHistorySize: INT] = { masterData.defaultHistorySize _ defaultHistorySize; }; GetDefaultHistorySize: PUBLIC PROC RETURNS [defaultHistorySize: INT] = { defaultHistorySize _ masterData.defaultHistorySize; }; SetAutoScriptingOn: PUBLIC PROC [autoScriptingOn: BOOL] = { masterData.autoScriptingOn _ autoScriptingOn; }; GetAutoScriptingOn: PUBLIC PROC [] RETURNS [autoScriptingOn: BOOL] = { autoScriptingOn _ masterData.autoScriptingOn; }; SetSeparateControlPanel: PUBLIC PROC [separateControlPanel: BOOL] = { masterData.separateControlPanel _ separateControlPanel; }; GetSeparateControlPanel: PUBLIC PROC [] RETURNS [separateControlPanel: BOOL] = { separateControlPanel _ masterData.separateControlPanel; }; SetDefaultIncludeIPByValue: PUBLIC PROC [defaultIncludeIPByValue: BOOL] = { masterData.defaultIncludeIPByValue _ defaultIncludeIPByValue; }; GetDefaultIncludeIPByValue: PUBLIC PROC [] RETURNS [defaultIncludeIPByValue: BOOL] = { defaultIncludeIPByValue _ masterData.defaultIncludeIPByValue; }; SetHoldThatTiger: PUBLIC PROC [holdThatTiger: BOOL] = { masterData.holdThatTiger _ holdThatTiger; }; GetHoldThatTiger: PUBLIC PROC [] RETURNS [holdThatTiger: BOOL] = { holdThatTiger _ masterData.holdThatTiger; }; SetNewBoxesUnfilled: PUBLIC PROC [newBoxesUnfilled: BOOL] = { masterData.newBoxesUnfilled _ newBoxesUnfilled; }; GetNewBoxesUnfilled: PUBLIC PROC [] RETURNS [newBoxesUnfilled: BOOL] = { newBoxesUnfilled _ masterData.newBoxesUnfilled; }; masterData: MasterData; eventTable: RefTab.Ref; masterData _ NEW[MasterDataObj]; UserProfile.CallWhenProfileChanges[LookAtProfile]; eventTable _ RefTab.Create[255]; END. δGGUserImpl.mesa Contents: Routines for reading the Gargoyle entries in the user profile and setting Gargoyle options. Also, procedures which handle user actions (menu buttons and mouse events). Copyright Σ 1986, 1989 by Xerox Corporation. All rights reserved. Pier, August 19, 1991 12:19 pm PDT Kurlander August 24, 1986 1:00:26 pm PDT Bier, February 19, 1992 4:16 pm PST Goodisman, August 11, 1989 4:59:38 pm PDT Doug Wyatt, December 20, 1989 4:29:29 pm PST ExternalRec is used by applications external to Gargoyle to return results to those applications. Clients should call EventNotify with a registered external proc name and a REF to an ExternalRec on a two-element event list. Client should then call WaitExternal in a loop checking their particular "valid" bit. Gargoyle completes the desired action, puts results in "results", and sets "valid" to TRUE. Gargoyle external procs will call BroadcastExternal when actions complete. Before the Queue (done by InputNotifier, Menu Process or Playback Process) From Buttons and Menus Used by several menu classes as the procedure to call when a menu click occurs. Used by several menu classes as the procedure to call when a menu click occurs. From Playback Scripts Regular Input Notification Called by the TIP table machinery when an action is received from mouse or keyboard. Self is an ActionArea. Problem: If a gargoyle scene changes from active to inactive due to a queued action, the length of the queue will determine when Gargoyle gets the input focus. PROC [bs: BiScroller, input: LORA]; An action has been received from BiScroller (e.g. from the ScrollBar). The event will be in one of two forms: 1) LIST[REF CHAR]. 2) LIST[ATOM, ... ]. Need our own copy of the ref and char, because the system reuses the storage. DKW: Yecch! Maybe the RegisteredEvent could contain this information. DKW: REF VEC values come from Biscrollers, which treats them as immutable, so the following is unnecessary. Maybe this code is left over from pre-Biscrollers days; TIPScreenCoords values straight from TIP are mutable, and would have to be copied. none => { tail: LIST OF REF ANY; Copy all of the VECs since the TIP table reuses the storage. tail _ newEvent _ CONS[event.first, NIL]; FOR list: LIST OF REF ANY _ event.rest, list.rest UNTIL list = NIL DO IF ISTYPE[list.first, REF VEC] THEN { mousePlace: REF VEC _ NARROW[list.first]; tail.rest _ CONS[NEW[VEC _ [mousePlace.x, mousePlace.y]], NIL]; } ELSE tail.rest _ CONS[list.first, NIL]; tail _ tail.rest; ENDLOOP; }; After the Queue (Done by SlackProcess) procTV: AMTypes.TV _ AMBridge.TVForProc[eventProc]; moduleTV: AMTypes.TV _ AMTypes.GlobalParent[procTV]; procName: Rope.ROPE _ AMTypes.TVToName[procTV]; moduleName: Rope.ROPE _ AMTypes.TVToName[moduleTV]; v: REF Vector2.VEC => { viewerToClient: Transformation _ GGState.GetBiScrollersTransforms[ggData].viewerToClient; l.first _ NEW [Vector2.VEC _ viewerToClient.Transform[v^]]; }; CodeTimer.SetIntMilliseconds[$TimeOnQueue, startTime, endTime, $Gargoyle]; -- will be uncommented following the next source-shared CodeTimer release. IF ( -- oops. You can't suppress all of the Durings. You must not suppress the last one for a given operation. Yuk. atom = $During ) THEN RETURN [suppress]; Utility Routines Expect a rope as the second argument. If the event has already been registered and ensureUnique is true, an error will be signalled. If the event has been registered and ensureUnique is FALSE, the action will be reregistered. GGUserProfile [reason: UserProfile.ProfileChangeReason] formerly "xerox/pressfonts/helvetica-mrr [r1: 0.0 s: [10.0 10.0] r2: 0.0] 1.0 1.0" No matter how many Gargoyle viewers are present, there is only one MasterData. When a new viewer is created, should heuristics be turned on? When a new viewer is created, should heuristics be turned on? When a new viewer is created, how strong should its gravity be? When a new viewer is created, how strong should its gravity be? interval _ CodeTimer.CreateInterval[$UserInput]; CodeTimer.AddInt[interval, $Gargoyle]; Κ•NewlineDelimiter – "cedar" style˜Icodešœ™šΟnœ«™³KšœB™BKšœ"™"Kšœ%Οk™(K™$K™)K™,—K™šž ˜ Jšœ­žœ}˜¬K˜—š œžœž˜Jšžœ°žœN˜‡Kšžœ0ž˜šžœžœŸ ˜1Kšœ&˜&K˜—šžœ˜šœ Οb œ˜5Kšœ˜™Ÿ—Kšœ$˜$K˜—K˜K˜—šœžœ!˜>Kšžœžœ™#KšœF™FKšœžœ˜6Kšœ$˜$K˜K˜—Kš œ žœžœžœžœžœ˜3š œ žœžœžœžœžœ˜5K˜—K˜š œžœ žœžœžœžœ˜G™&Jšœžœžœžœ™Jšœžœžœ™—JšžœžœžœŸ8˜_šžœ žœž˜šœ žœžœ˜KšœM™MKš œ žœžœžœžœ ˜+Kšœžœ˜"K˜—šœžœ˜Kšœ.˜.Kšžœ žœžœ'˜;šžœ˜Kšœžœ˜*šœ žœ4žœ˜KKšœE™E—šžœ ž˜Kšœ Ÿ%˜E—šžœ%ž˜+Kšœ ˜ —Jšœ1˜1šžœžœ˜Kšœžœ˜šžœžœžœ˜šžœžœž˜!Kšœžœžœ ˜Kšžœ˜—šžœžœžœ˜šžœžœž˜&Kšœžœžœ ˜Kšžœ˜—K˜—K˜—KšœF˜FJ˜—šžœžœžœ˜Kšœžœ˜Kšœ žœ˜Kšœ9˜9Kšœ1˜1šžœžœžœ˜šžœžœž˜!Kšœžœžœ ˜Kšžœ˜—K˜—KšœŸ˜Kšœ&Ÿ7˜]Kšœd˜dJ˜—J˜—J˜—Jšžœžœ˜—Kšœžœ˜K˜K˜—Kšœ žœžœ˜#šœžœžœ˜Kšœ ž˜K˜K˜—Kšœ žœžœ˜š œžœžœžœžœžœžœžœžœ˜ZJšœ)˜)J˜Kšœ&Ÿ˜,Kšžœ žœžœ*Ÿ1˜‹JšœH˜HK˜K˜—šœžœ žœžœžœžœ-žœ žœžœžœžœ˜Kšœžœžœ˜!šžœž˜šœ˜KšœžœΒΟeœ&™χ—™ Kš œžœžœžœžœ™K™