<> <> <> <> <> <> <> <> <<>> 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] = { <> <<1) LIST[REF CHAR].>> <<2) LIST[ATOM, ... ].>> 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] = { <> <> <<) THEN RETURN [suppress];>> 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 = { <<[reason: UserProfile.ProfileChangeReason]>> 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.