DIRECTORY Atom, CD, CDBasics, CDCells, CDDrawQueue, CDEvents, CDInstances, CDIO, CDOps, CDOrient, CDProperties, CDRects, CDSimpleOps, CDValue, HashTable, Process, Rope USING [ROPE], SafeStorage, TerminalIO, UserProfile; CDOpsImpl: CEDAR MONITOR IMPORTS Atom, CD, CDBasics, CDCells, CDDrawQueue, CDEvents, CDInstances, CDIO, CDOps, CDOrient, CDProperties, CDRects, CDSimpleOps, CDValue, HashTable, Process, SafeStorage, TerminalIO, UserProfile EXPORTS CDOps SHARES CD = BEGIN createEvent: CDEvents.EventRegistration=CDEvents.RegisterEventType[$CreateNewDesign]; resetDesignEvent: CDEvents.EventRegistration=CDEvents.RegisterEventType[$ResetDesign]; delayedKey: REF _ NEW[INT]; DelRec: TYPE = RECORD [ delayedList: LIST OF Remember_NIL, length: INT _ 0 ]; GetDelRec: PROC [design: CD.Design] RETURNS [REF DelRec] = BEGIN x: REF _ CDValue.Fetch[boundTo: design, key: delayedKey, propagation: design]; IF x#NIL AND ISTYPE[x, REF DelRec] THEN RETURN [NARROW[x]] ELSE { dr: REF DelRec = NEW[DelRec_[NIL]]; CDValue.Store[design, delayedKey, dr]; RETURN [dr] } END; Remember: TYPE = RECORD [area: CD.Rect, clear: BOOL]; InternalResetDesign: PROC[design: CD.Design] = BEGIN dummy: CD.Object _ CDCells.CreateEmptyCell[]; dummy.size _ CDBasics.highposition; design.cdDirectoryPriv _ HashTable.Create[101, HashTable.RopeEqual, HashTable.HashRope]; design^.actual _ LIST[CD.PushRec[ dummyCell: CDInstances.NewInst[ob: dummy], mightReplace: NIL, specific: NARROW[dummy.specificRef], deletedList: NIL]]; END; CreateDesign: PUBLIC PROC [technology: CD.Technology] RETURNS [design: CD.Design] = BEGIN IF technology=NIL THEN ERROR CD.Error[callingError, "NIL technology"]; design _ NEW[CD.DesignRec_[ properties: CD.InitPropRef[], technology: technology, reserved: NEW[LONG POINTER _ NIL] --type has no property write proc ]]; IF finalizing THEN SafeStorage.EnableFinalization[design]; InternalResetDesign[design]; -- must not cause redraw since event not yet processed [] _ CDEvents.ProcessEvent[createEvent, design]; END; ResetDesign: PUBLIC PROC [design: CD.Design] = BEGIN InternalResetDesign[design]; [] _ CDEvents.ProcessEvent[resetDesignEvent, design]; CDValue.Store[design, delayedKey, NIL]; Redraw[design]; END; RemoveInstance: PUBLIC PROC [design: CD.Design, inst: CD.Instance, draw: BOOL_TRUE] = BEGIN il: CD.InstanceList _ CDOps.InstList[design]; IF il#NIL THEN IF il.first=inst THEN CDOps.SetInstList[design, il.rest] ELSE FOR l: CD.InstanceList _ il, l.rest WHILE l.rest#NIL DO IF l.rest.first=inst THEN {l.rest_l.rest.rest; EXIT} ENDLOOP; IF draw THEN DelayedRedraw[design, CDInstances.InstRectO[inst]]; END; SelectNewMode: PROC[design: CD.Design] RETURNS [BOOL] = BEGIN mode: INT = CDValue.FetchInt[boundTo: design, key: $CDxSelectNewMode, propagation: technology, ifNotFound: 0]; RETURN [mode=1] END; IncludeObjectI: PUBLIC PROC[design: CD.Design, ob: CD.Object, location: CD.Position, orientation: CD.Orientation] = BEGIN inst: CD.Instance; IF ob#NIL THEN { inst _ CDInstances.NewInstI[ob: ob, location: location, orientation: orientation ]; IF SelectNewMode[design] THEN { CDSimpleOps.DeselectAll[design]; inst.selected _ TRUE; }; IncludeInstance[design, inst]; } END; IncludeInstance: PUBLIC PROC [design: CD.Design, inst: CD.Instance, draw: BOOL_TRUE] = BEGIN IF inst=NIL THEN ERROR CD.Error[callingError, "Include of NIL application"]; IF inst.ob=NIL THEN ERROR CD.Error[callingError, "Include application with NIL object"]; CDOps.SetInstList[design, CONS[inst, CDOps.InstList[design]]]; IF draw THEN DelayedRedraw[design, CDInstances.InstRectO[inst], TRUE]; END; IncludeInstanceList: PUBLIC PROC [design: CD.Design, il: CD.InstanceList, draw: BOOL_TRUE] = BEGIN FOR list: CD.InstanceList _ il, list.rest WHILE list#NIL DO IncludeInstance[design, list.first, draw]; ENDLOOP; END; Redraw: PUBLIC PROC [design: CD.Design, r: CD.Rect_CDOps.all, eraseFirst: BOOL_TRUE] = BEGIN CDDrawQueue.InsertDrawCommand[design, CDDrawQueue.Request[IF eraseFirst THEN $redraw ELSE $draw, r]]; END; CheckForShorten: PROC [dl: REF DelRec] = INLINE { IF dl.length>20 THEN { clear: BOOL _ FALSE; r: CD.Rect _ CDBasics.empty; FOR lst: LIST OF Remember _ dl.delayedList, lst.rest WHILE lst#NIL DO clear _ clear OR lst.first.clear; r _ CDBasics.Surround[r, lst.first.area] ENDLOOP; dl.delayedList _ LIST[Remember[area: r, clear: clear]]; dl.length _ 1 }; }; DelayedRedraw: PUBLIC ENTRY PROC [design: CD.Design, r: CD.Rect, eraseFirst: BOOL_TRUE] = BEGIN ENABLE UNWIND => NULL; IF design#NIL THEN { dl: REF DelRec = GetDelRec[design]; IF dl.delayedList=NIL THEN { dl.delayedList _ LIST[Remember[area: r, clear: eraseFirst]]; dl.length _ 1 } ELSE { list: LIST OF Remember _ dl.delayedList; DO IF CDBasics.Intersect[list.first.area, r] THEN { IF CDBasics.Inside[r, list.first.area] THEN { list.first.clear _ list.first.clear OR eraseFirst; RETURN } ELSE IF CDBasics.Inside[list.first.area, r] THEN { remember: LIST OF Remember _ list; eraseFirst _ list.first.clear OR eraseFirst; list.first.area _ r; WHILE list.rest#NIL DO IF CDBasics.Inside[list.rest.first.area, r] THEN { eraseFirst _ list.rest.first.clear OR eraseFirst; list.rest _ list.rest.rest; --does not change list -> keeps assertion3 dl.length _ dl.length-1; } ELSE list _ list.rest --since list.rest#NIL -> keeps assertion3 ENDLOOP; remember.first.clear _ eraseFirst; RETURN } }; IF list.rest#NIL THEN list_list.rest ELSE { list.rest _ LIST[Remember[area: r, clear: eraseFirst]]; dl.length _ dl.length+1; CheckForShorten[dl]; RETURN } ENDLOOP; } --of dl.delayedList#NIL } --of design#NIL END; DoTheDelayedRedraws: PUBLIC ENTRY PROC [design: CD.Design] = BEGIN ENABLE UNWIND => NULL; sq: REF DelRec = GetDelRec[design]; UNTIL sq.delayedList=NIL DO CDDrawQueue.InsertDrawCommand[design, CDDrawQueue.Request[(IF sq.delayedList.first.clear THEN $redraw ELSE $draw), sq.delayedList.first.area]]; sq.delayedList _ sq.delayedList.rest ENDLOOP; sq.length _ 0; END; DrawDesign: PUBLIC PROC[design: CD.Design, pr: CD.DrawRef] = BEGIN FOR w: LIST OF CD.PushRec _ design^.actual, w.rest WHILE w#NIL DO IF pr.stopFlag^ THEN EXIT; pr.drawChild[w.first.dummyCell, [0, 0], CDOrient.original, pr]; ENDLOOP; END; RedrawInstance: PUBLIC PROC[design: CD.Design, inst: CD.Instance_NIL, erase: BOOL_TRUE] = BEGIN IF inst#NIL THEN DelayedRedraw[design, CDInstances.InstRectO[inst], erase] ELSE DelayedRedraw[design, CDBasics.universe, erase] END; QuickDrawDesign: PUBLIC PROC[design: CD.Design, pr: CD.DrawRef] = BEGIN SomeCommon: PROC[ob: CD.Object, pos: CD.Position, orient: CD.Orientation, pr: CD.DrawRef] RETURNS [BOOLEAN] = INLINE BEGIN RETURN CDBasics.Intersect[CDOrient.RectAt[pos, ob.size, orient], pr.interestClip] END; DrawAndShowSelectionList: PROC [list: CD.InstanceList, pr: CD.DrawRef] = INLINE BEGIN FOR w: CD.InstanceList _ list, w.rest WHILE w#NIL DO IF SomeCommon[w.first.ob, w.first.location, w.first.orientation, pr] THEN { IF pr.stopFlag^ THEN EXIT; w.first.ob.class.quickDrawMe[w.first, w.first.location, w.first.orientation, pr]; IF w.first.selected THEN w.first.ob.class.showMeSelected[w.first, w.first.location, w.first.orientation, pr]; }; ENDLOOP; END; QuickDrawPushedCell: PROC [cp: CD.CellPtr, pr: CD.DrawRef] = INLINE BEGIN IF pr.borders AND cp.drawBorder THEN pr.drawOutLine[cp.ir, CD.outlineLayer, pr]; FOR w: CD.InstanceList _ cp.contents, w.rest WHILE w#NIL DO IF SomeCommon[w.first.ob, w.first.location, w.first.orientation, pr] THEN { IF pr.stopFlag^ THEN EXIT; w.first.ob.class.quickDrawMe[w.first, w.first.location, w.first.orientation, pr]; } ENDLOOP; END; pr.setGround[pr: pr, pushedOut: FALSE]; DrawAndShowSelectionList[CDOps.InstList[design], pr]; IF design^.actual.rest#NIL THEN { pr.drawOutLine[design^.actual.first.specific.ir, CD.outlineLayer, pr]; IF pr.environment THEN { pr.setGround[pr: pr, pushedOut: TRUE]; FOR w: LIST OF CD.PushRec _ design^.actual.rest, w.rest WHILE w#NIL DO IF pr.stopFlag^ THEN EXIT; QuickDrawPushedCell[w.first.specific, pr]; ENDLOOP; }; } END; PointedInstance: PUBLIC PROC [design: CD.Design, pos: CD.Position] RETURNS [CD.Instance] = BEGIN RETURN [ CDInstances.InstanceAt[CDOps.InstList[design], pos] ]; END; SelectedInstance: PUBLIC PROC [design: CD.Design] RETURNS [first: CD.Instance_NIL, multiple: BOOL_FALSE] = BEGIN FOR w: CD.InstanceList _ CDOps.InstList[design], w.rest WHILE w#NIL DO IF w.first.selected THEN IF first=NIL THEN first_w.first ELSE {multiple_TRUE; RETURN} ENDLOOP; END; ObjectInfo: PUBLIC PROC[ob: CD.Object] RETURNS [Rope.ROPE] = BEGIN IF ob=NIL THEN RETURN ["nil object"] ELSE IF ob.class.describe#NIL THEN RETURN [ob.class.describe[ob]] ELSE RETURN [Atom.GetPName[ob.class.objectType]] END; LayerName: PUBLIC PROC[lev: CD.Layer] RETURNS [Rope.ROPE] = BEGIN uniqueKey: ATOM = CD.LayerKey[lev]; IF uniqueKey=NIL THEN RETURN ["bad layer"]; RETURN [Atom.GetPName[uniqueKey]] END; ReOrderInstance: PUBLIC PROC [design: CD.Design, inst: CD.Instance] = BEGIN il: CD.InstanceList _ CDOps.InstList[design]; found: BOOL _ FALSE; IF inst=NIL THEN ERROR CD.Error[callingError, "Reorder of NIL application"]; WHILE il#NIL AND il.first=inst DO {found_TRUE; il _ il.rest} ENDLOOP; IF il=NIL THEN { IF found THEN il_LIST[inst] ELSE ERROR CD.Error[callingError, "Reorder of application not in design"]; } ELSE FOR l: CD.InstanceList _ il, l.rest DO WHILE l.rest#NIL AND l.rest.first=inst DO {found_TRUE; l.rest _ l.rest.rest} ENDLOOP; IF l.rest=NIL THEN { IF found THEN l.rest _ LIST[inst] ELSE ERROR CD.Error[callingError, "Reorder of application not contained in design"]; EXIT } ENDLOOP; CDOps.SetInstList[design, il]; END; DrawCollected: PROC [inst: CD.Instance, pos: CD.Position, orient: CD.Orientation, pr: CD.DrawRef] = BEGIN pr.drawRect[CDOrient.RectAt[pos, inst.ob.size, orient], CD.errorLayer, pr] END; ReadCollected: CD.InternalReadProc --PROC [] RETURNS [Object]-- = BEGIN sz: CD.Position = CDIO.ReadPos[]; ob: CD.Object = CDRects.CreateRect[sz, CD.errorLayer]; r: Rope.ROPE = "*design of this object has been destroyed; bug in creator program\n"; CDProperties.PutObjectProp[ob, $SignalName, r]; TerminalIO.WriteRope[r]; RETURN [ob] END; WriteCollected: CD.InternalWriteProc -- PROC [me: Object] -- = BEGIN CDIO.WritePos[CD.InterestSize[me]]; TerminalIO.WriteRope["*write object which has been destroyed\n"]; END; gCollectedClass: CD.ObjectClass = CD.RegisterObjectClass[$GCollected, [ drawMe: DrawCollected, quickDrawMe: DrawCollected, internalRead: ReadCollected, internalWrite: WriteCollected, description: "garbage object; design has been destroyed" ]]; DestroyEachObject: HashTable.EachPairAction = BEGIN WITH value SELECT FROM ob: CD.Object => IF ob.class=NIL OR ob.class.inDirectory THEN { ob.class _ gCollectedClass; ob.layer _ CD.errorLayer; ob.specificRef _ NIL; ob.properties _ NIL; }; ENDCASE => NULL; END; FinalizeDesign: PROC [d: CD.Design] = BEGIN d.properties _ NIL; IF d.cdDirectoryPriv#NIL AND CDValue.Fetch[d, $KeepObjects]=NIL THEN [] _ NARROW[d.cdDirectoryPriv, HashTable.Table].Pairs[DestroyEachObject]; WHILE d.actual#NIL DO d.actual.first.dummyCell.properties _ NIL; IF d.actual.first.mightReplace#NIL THEN d.actual.first.mightReplace.properties _ NIL; d.actual.first.deletedList _ NIL; d.actual _ d.actual.rest; ENDLOOP; d.cdDirectoryPriv _ NIL; d.cdValuePriv _ NIL; d.cdSequencerPriv _ NIL; d.cdDrawQueuePriv _ NIL; END; FinalizerProcess: PROC[fooFQ: SafeStorage.FinalizationQueue] = BEGIN DO d: CD.Design = NARROW[SafeStorage.FQNext[fooFQ]]; FinalizeDesign[d]; ENDLOOP END; finalizing: BOOL = UserProfile.Boolean["ChipNDale.DoFinalization", TRUE]; IF finalizing THEN { fooFQ: SafeStorage.FinalizationQueue = SafeStorage.NewFQ[]; SafeStorage.EstablishFinalization[CODE[CD.DesignRec], 0, fooFQ]; TRUSTED {Process.Detach[FORK FinalizerProcess[fooFQ]]}; }; CDValue.RegisterKey[$KeepObjects]; END. θCDOpsImpl.mesa (part of ChipNDale) Copyright c 1983, 1986 by Xerox Corporation. All rights reserved. by Christian Jacobi, July 12, 1983 10:56 am last edited by Christian Jacobi, May 22, 1986 5:11:56 pm PDT Last Edited by: Jacobi June 6, 1986 12:07:30 pm PDT --is local since it does not cause a redraw --ASSERTION1: {list#NIL} --ASSERTION2: {no list rectangle is completely covered by an other one} --r is contained somewhere; we dont include it --it is unlikely that a small area is cleared and a big one not --assertion2 => no other elements could be removed --r contains an element; we remove this element and all others -- which are contained in r --it is unlikely that a small area is cleared and a big one not --remove all other element contained in r; to maintain assertion2 assert3: list#NIL -- drawDesign --first: returns ref to any selected application if there is one or more, otherwise nil. --multiple: more than one application is selected --on return: design has exactly one occurrence of inst, and it is at the end. --(includes inst if necessary and removes double occurences) -- l#NIL AND l.first#inst holds at this point -- Finalization -- -- designs are finalized to break circularities involving objects or instances Κ˜codešœ(™(Kšœ Οmœ7™BKšœ-™-Kšœ=™=K™3—K˜šΟk ˜ Kšœ˜Kšžœ˜Kšœ ˜ K˜Kšœ ˜ K˜ K˜ Kšœ˜Kšœ˜K˜ Kšœ ˜ Kšœ˜Kšœ ˜ Kšœ˜Kšœ ˜ Kšœž˜ Kšœžœžœ˜Kšœ ˜ Kšœ ˜ Kšœ ˜ —K˜šΠln œžœžœ˜Kšžœžœ·˜ΕKšžœ˜ Kšžœžœ˜ —Kšž˜K˜UK˜VKšœ žœžœžœ˜K˜šœžœžœ˜Kšœ žœžœ žœ˜"Kšœžœ˜K˜—K˜š Οn œžœ žœ žœžœ ˜:Kšž˜KšœžœH˜NKšžœžœžœžœžœ žœžœžœ˜:šžœ˜Kšœžœ žœ žœ˜#Kšœ&˜&Kšžœ˜ K˜—Kšžœ˜K˜—Kš œ žœžœžœžœ˜5K˜š œžœ žœ ˜/Kšœ+™+Kšž˜Kšœžœ$˜-Kšœ#˜#KšœX˜Xšœžœžœ ˜!Kšœ*˜*Kšœžœ˜Kšœ žœ˜$Kšœ žœ˜—Kšžœ˜—K˜š   œžœžœžœ žœ žœ ˜SKšž˜Kš žœ žœžœžœžœ'˜Fšœ žœžœ ˜Kšœ žœ˜Kšœ˜Kš œ žœžœžœžœΟc!˜CKšœ˜—Kšžœ žœ(˜:Kšœ‘6˜SK˜1Kšžœ˜—K˜š  œžœžœ žœ ˜.Kšž˜Kšœ˜K˜6Kšœ"žœ˜'Kšœ˜Kšžœ˜K˜—š œžœžœ žœžœžœžœ˜UKšž˜Kšœžœ'˜-šžœžœžœ˜Kšžœžœ#˜8šž˜š žœžœžœžœž˜7Kšžœžœžœ˜4Kšžœ˜———Kšžœžœ4˜@Kšžœ˜—K˜š   œžœ žœ žœžœ˜7Kšž˜Kšœžœe˜nKšžœ ˜Kšžœ˜—K˜š œžœžœ žœ žœžœžœ˜sKšž˜Kšœžœ ˜šžœžœžœ˜KšœS˜Sšžœžœ˜Kšœ ˜ Kšœžœ˜K˜—Kšœ˜K˜—Kšžœ˜K˜—š  œž œ žœžœžœžœ˜VKšž˜Kš žœžœžœžœžœ3˜LKš žœ žœžœžœžœ<˜XKšœžœ ˜>Kšžœžœ4žœ˜FKšžœ˜—K˜š œžœžœ žœ žœžœžœ˜\Kšž˜š žœžœžœžœž˜;Kšœ*˜*Kšž˜—Kšžœ˜—K˜š œžœžœ žœ žœžœžœ˜VKšž˜Kšœ:žœ žœ žœ ˜eKšžœ˜K˜—K˜š œžœžœ žœ˜1šžœžœ˜Kšœžœžœ˜Kšœžœ˜š žœžœžœ%žœžœž˜EKšœžœ˜!Kšœ(˜(Kšžœ˜—Kšœžœ"˜7Kšœ ˜ K˜—K˜—K˜š  œžœžœžœ žœ žœžœžœ˜Yšž˜Kšžœžœžœ˜—šžœžœžœ˜Kšœžœ˜#šžœžœžœ˜Kšœžœ'˜=Kšœ ˜ Kšœ˜—šžœ˜Kšœžœžœ˜(šž˜Kšœ™KšœG™Gšžœ(žœ˜0šžœ%žœ˜.K™.Kšœ?™?Kšœ$žœ ˜2Kšœ2™2Kšž˜K˜—šžœžœ%žœ˜2K™>K™Kšœ?™?Kšœ žœžœ˜"Kšœžœ ˜,Kšœ˜KšœA™Ašžœ žœž˜Kšœ™šžœ*žœ˜2Kšœ#žœ ˜1Kšœ‘*˜FKšœ˜K˜—Kšžœ‘)˜?Kšžœ˜—Kšœ"˜"Kšž˜K˜—K˜—Kšžœ žœžœ˜$šžœ˜Kšœ žœ'˜7Kšœ˜Kšœ˜Kšž˜K˜—Kšžœ˜—Kšœ‘˜—Kšœ‘˜—Kšžœ˜—K˜š  œžœžœžœ žœ ˜<šž˜Kšžœžœžœ˜—Kšœžœ˜#šžœžœž˜Kšœ:žœžœ žœ%˜Kšœ$˜$Kšžœ˜—Kšœ˜Kšžœ˜—K˜š   œžœžœ žœ žœ ˜Kšž˜Kšœžœ˜#KšœA˜AKšžœ˜—K˜šœžœžœ#˜GKšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ8˜8Kšœ˜—K™š’œ˜.Kšž˜šžœžœž˜š œžœ žœ žœžœžœ˜?Kšœ˜Kšœ žœ ˜Kšœžœ˜Kšœžœ˜Kšœ˜—Kšžœžœ˜—Kšžœ˜—K˜š œžœžœ ˜&Kšž˜Kšœžœ˜š žœžœžœ žœž˜DKšœžœ>˜I—šžœ žœž˜Kšœ&žœ˜*Kšžœžœžœ*žœ˜UKšœžœ˜!Kšœ˜Kšžœ˜—Kšœžœ˜Kšœžœ˜Kšœžœ˜Kšœžœ˜Kšžœ˜—K˜š œžœ(˜>Kšž˜šž˜Kšœžœ˜1Kšœ˜Kšž˜—Kšžœ˜—K˜Kšœ žœ3žœ˜Išžœ žœ˜Kšœ;˜;Kšœ"žœžœ˜@Kšžœžœ˜7K˜—Kšœ"˜"Kšžœ˜K˜K˜—…—.E