DIRECTORY CedarProcess, Commander, FeedbackTypes, GGBasicTypes, GGCoreTypes, GGEvent, GGHistoryTypes, GGHistoryTypesOpaque, GGInterfaceTypes, GGModelTypes, GGMUserProfile, GGOutline, GGScene, GGSelect, GGSliceOps, GGUtility, IO, RefTab, Rope, UserProfile; GGUtilityImplC: CEDAR PROGRAM IMPORTS CedarProcess, Commander, GGScene, GGSelect, GGSliceOps, GGUtility, IO, RefTab, Rope, UserProfile EXPORTS GGHistoryTypes, GGUtility, GGMUserProfile = BEGIN Change: PUBLIC TYPE = GGHistoryTypesOpaque.Change; MsgRouter: TYPE = FeedbackTypes.MsgRouter; FontData: TYPE = GGModelTypes.FontData; GGData: TYPE = GGInterfaceTypes.GGData; GravityType: TYPE = GGInterfaceTypes.GravityType; HistoryEvent: TYPE = GGHistoryTypes.HistoryEvent; Line: TYPE = GGCoreTypes.Line; OverlapOrder: TYPE = GGUtility.OverlapOrder; Point: TYPE = GGBasicTypes.Point; Scene: TYPE = GGScene.Scene; Slice: TYPE = GGModelTypes.Slice; SliceDescriptor: TYPE = GGModelTypes.SliceDescriptor; SliceGenerator: TYPE = GGModelTypes.SliceGenerator; Traj: TYPE = GGModelTypes.Traj; Vector: TYPE = GGBasicTypes.Vector; SequenceSubst: PUBLIC PROC [new, old: GGModelTypes.Sequence, expr: LIST OF GGModelTypes.Sequence] RETURNS [head: LIST OF GGModelTypes.Sequence _ NIL] = { tail, cons: LIST OF GGModelTypes.Sequence _ NIL; first: GGModelTypes.Sequence _ NIL; WHILE expr # NIL DO first _ expr.first; cons _ LIST[IF first = old THEN new ELSE first]; IF tail = NIL THEN head _ cons ELSE tail.rest _ cons; tail _ cons; expr _ expr.rest; ENDLOOP; }; OrderedSelectionList: PUBLIC PROC [ggData: GGData, order: OverlapOrder, andSelectEntire: BOOL _ FALSE] RETURNS [list: LIST OF Slice] = { scene: Scene _ ggData.scene; DoAddSliceToList: PROC [slice: Slice] RETURNS [done: BOOL _ FALSE] = { IF GGSelect.IsSelectedInPart[slice, scene, normal] THEN { list _ CONS[slice, list]; IF andSelectEntire THEN GGSelect.SelectEntireSlice[slice, scene, normal]; }; }; [] _ GGScene.WalkSlices[scene, first, DoAddSliceToList]; IF order=decr THEN list _ ReverseList[list]; }; ReverseList: PROC [list: LIST OF Slice] RETURNS [val: LIST OF Slice] = { val _ NIL; UNTIL list = NIL DO val _ CONS[list.first, val]; list _ list.rest; ENDLOOP; RETURN[val]; }; masterData: MasterData; MasterData: TYPE = REF MasterDataObj; MasterDataObj: TYPE = RECORD [ turboOn: BOOL _ FALSE, junk: BOOL _ FALSE -- records in Impls with one field kick up an Interpreter bug ]; LookAtProfile: PUBLIC UserProfile.ProfileChangedProc = { turboOn: BOOL _ UserProfile.Boolean[key: "Gargoyle.TurboOn", default: FALSE]; SetTurboOn[turboOn]; }; SetTurboOn: PUBLIC PROC [sense: BOOL] = { masterData.turboOn _ sense; }; GetTurboOn: PUBLIC PROC RETURNS [sense: BOOL] = { sense _ masterData.turboOn; }; GGTurboOn: Commander.CommandProc = { SetTurboOn[TRUE]; cmd.out.PutRope["Gargoyle turbo shape caching turned on."]; }; GGTurboOff: Commander.CommandProc = { SetTurboOn[FALSE]; cmd.out.PutRope["Gargoyle turbo shape caching turned off."]; }; RestoreSceneClean: PUBLIC PROC [scene: Scene, virginList: LIST OF Slice, virginMap: RefTab.Ref] = { found: BOOL _ FALSE; virginScene: Scene; restoredPtr: LIST OF Slice; restoredList: LIST OF Slice; [restoredList, restoredPtr] _ GGUtility.StartSliceList[]; FOR sliceList: LIST OF Slice _ virginList, sliceList.rest UNTIL sliceList = NIL DO original: REF _ NIL; nextSlice: Slice _ sliceList.first; -- candidate slice for new scene [found, original] _ RefTab.Fetch[virginMap, nextSlice]; -- is candidate mapped to original ? IF found THEN { originalSlice: Slice _ NARROW[original, Slice]; -- get original storage. May be trashed GGSliceOps.Restore[from: nextSlice, to: originalSlice]; nextSlice _ originalSlice; -- get ready to store }; nextSlice.parent _ NIL; -- in case it was a hole previously [restoredList, restoredPtr] _ GGUtility.AddSlice[nextSlice, restoredList, restoredPtr]; ENDLOOP; virginScene _ GGScene.CreateScene[restoredList]; -- fresh scene GGScene.SetScene[from: virginScene, to: scene]; -- wipes out selections in scene }; CopySceneClean: PUBLIC PROC [scene: Scene, copyAll: BOOL _ FALSE] RETURNS [virginList: LIST OF Slice, virginMap: RefTab.Ref] = { ENABLE ABORTED => {IF virginMap#NIL THEN RefTab.Erase[virginMap]}; CopyWithSelections: PROC [slice: Slice] RETURNS [copy: Slice] = { IF doSelections THEN GGSelect.SaveSelectionsInSliceAllClasses[slice, NIL]; -- scene argument no longer used copy _ GGSliceOps.Copy[slice].first; -- copy entire slice IF NOT RefTab.Insert[x: virginMap, key: copy, val: slice] THEN ERROR; }; virginPtr: LIST OF Slice; sceneList: LIST OF Slice _ GGScene.ListSlices[scene, first]; IF sceneList#NIL THEN { CedarProcess.CheckAbort[]; -- check self for aborted virginMap _ RefTab.Create[]; [virginList, virginPtr] _ GGUtility.StartSliceList[]; FOR sliceList: LIST OF Slice _ sceneList, sliceList.rest UNTIL sliceList = NIL DO slice: Slice _ sliceList.first; [virginList, virginPtr] _ GGUtility.AddSlice[IF copyAll OR GGSelect.IsSelectedInPart[slice, scene, normal] THEN CopyWithSelections[slice] ELSE slice, virginList, virginPtr]; CedarProcess.CheckAbort[]; -- check self for aborted ENDLOOP; }; }; UnlinkError: SIGNAL = CODE; UnlinkCapturedScene: PUBLIC PROC [historyEvent: HistoryEvent] = { IF historyEvent#NIL AND NOT Rope.Equal[historyEvent.name, "advance", FALSE] THEN SIGNAL UnlinkError; -- debugging check IF historyEvent#NIL AND historyEvent.subevents#NIL AND historyEvent.subevents.first#NIL THEN { found: BOOL _ FALSE; captureRef: REF Change _ historyEvent.subevents.first.historyData; captureData: REF Change.capture _ NARROW[captureRef]; FOR sliceList: LIST OF Slice _ captureData.virginData, sliceList.rest UNTIL sliceList = NIL DO found _ RefTab.Fetch[captureData.virginMap, sliceList.first].found; IF found AND doUnlink THEN GGSliceOps.Unlink[sliceList.first]; -- ASSERT: this slice appears only on the clean list and can be unlinked sliceList.first_NIL; ENDLOOP; IF captureData.virginMap#NIL THEN RefTab.Erase[captureData.virginMap]; }; }; doSelections: BOOL _ TRUE; doUnlink: BOOL _ TRUE; Init: PROC [] = { masterData _ NEW[MasterDataObj]; UserProfile.CallWhenProfileChanges[LookAtProfile]; Commander.Register["GGTurboOn", GGTurboOn, "turns on Imager.Object caching to speed up Gargoyle refresh on black and white displays"]; Commander.Register["GGTurboOff", GGTurboOff, "turns off Imager.Object caching to speed up Gargoyle refresh on black and white displays"]; }; Init[]; END.  GGUtilityImplC.mesa Copyright Σ 1987 by Xerox Corporation. All rights reserved. Pier, August 18, 1988 12:37:57 pm PDT Bier, August 29, 1990 0:02 am PDT traverse the scene.entities from beginning (back) to end (front) For GGMUserProfile [reason: UserProfile.ProfileChangeReason] Utilities for undo/history restores scene.entities to its original state as specified by the virginList and virginMap overlay original storage with virgin data from virginList traverse the scene entities from beginning (back) to end (front), making a copy of the scene list from unselected slices AND copies of selected slices. Also, return a RefTab that maps the copies onto their originals. Used by history code. Calls must be properly synchronized by the caller to allow unambiguous traversal of the scene. Κ–˜code™K™