<> <> <> <> DIRECTORY CD, CDBasics, CDBasicsInline, CDIO, CDLayers, CDPrivate, CDProperties, CDRects, CDOps, CDValue, LRUCache, Rope, SafeStorage, TokenIO; CDRectsAndLayersImpl: CEDAR MONITOR IMPORTS CD, CDBasics, CDBasicsInline, CDIO, CDLayers, CDOps, CDPrivate, CDProperties, CDValue, LRUCache, Rope, SafeStorage EXPORTS CDRects, CDLayers SHARES CD = BEGIN <<--CDRects>> bareRectClass: PUBLIC CD.ObjectClass; wellRectClass: PUBLIC CD.ObjectClass; dummy: CD.RectSpecific = SafeStorage.GetPermanentZone[].NEW[CD.RectRep _ [filler: NIL]]; lruCache: LRUCache.Handle = LRUCache.Create[255, CDPrivate.Hash, CDPrivate.Equal]; freeOb: CD.Object _ NIL; --always rect GiveOb: ENTRY PROC [] RETURNS [ob: CD.Object] = INLINE { ENABLE UNWIND => NULL; ob _ freeOb; freeOb _ NIL; IF ob=NIL THEN ob _ NEW[CD.ObjectRep_[specific: dummy]]; ob.class _ bareRectClass; }; CreateRectProc: TYPE = PROC [size: CD.Position, l: CD.Layer] RETURNS [CD.Object] _ NIL; createRectArray: REF ARRAY CD.Layer OF CreateRectProc = SafeStorage.GetPermanentZone[].NEW[ARRAY CD.Layer OF CreateRectProc]; <<--initialized by default>> CreateRect: PUBLIC PROC [size: CD.Position, l: CD.Layer] RETURNS [ob: CD.Object] = { IF createRectArray[l]=NIL THEN { <<--don't cache a second time..>> ob _ CreateWellRect[size, l] } ELSE { used: REF; insert: BOOL; ob _ createRectArray[l][size, l]; [insert: insert, used: used] _ LRUCache.Include[lruCache, ob]; IF ~insert THEN ob _ NARROW[used]; <<--otherwise do not remember object on freeOb! we don't know its class >> ob.immutable _ TRUE; }; }; HangExtensionsOn: PROC[on: CD.ObjectClass] = { IF on.newLayer=NIL THEN on.newLayer _ ChangeLayer }; UseForCreateRect: PUBLIC PROC [layer: CD.Layer, createRect: PROC [size: CD.Position, l: CD.Layer] RETURNS [CD.Object], hangExtensionsOn: CD.ObjectClass ] = { IF createRect=NIL THEN createRect _ IF CDLayers.layerData[layer].well=CD.undefLayer THEN CreateBareRect ELSE CreateWellRect; createRectArray[layer] _ createRect; IF hangExtensionsOn#NIL THEN HangExtensionsOn[hangExtensionsOn]; CDProperties.PutLayerProp[onto: layer, prop: $CDxRectCreation, val: $CDxUser]; }; CreateBareRect: PUBLIC PROC [size: CD.Position, l: CD.Layer] RETURNS [ob: CD.Object] = { used: REF; insert: BOOL; ob _ GiveOb[]; ob.bbox _ CDPrivate.MinBBox[size]; ob.layer _ l; [insert: insert, used: used] _ LRUCache.Include[lruCache, ob]; IF ~insert THEN {freeOb _ ob; ob _ NARROW[used]}; ob.immutable _ TRUE; }; CreateWellRect: PROC [size: CD.Position, l: CD.Layer] RETURNS [ob: CD.Object] = { used: REF; insert: BOOL; wellSurround: INT _ 0; ir: CD.Rect _ CDPrivate.MinBBox[size]; ob _ GiveOb[]; IF CDLayers.layerData[l].well#CD.undefLayer THEN { wellSurround _ CDLayers.layerData[l].wSurr; ob.class _ wellRectClass }; ob.bbox _ CDBasics.Extend[ir, wellSurround]; ob.layer _ l; [insert: insert, used: used] _ LRUCache.Include[lruCache, ob]; IF ~insert THEN {freeOb _ ob; ob _ NARROW[used]}; ob.immutable _ TRUE; }; InitRects: PROC [] = { bareRectClass _ CD.RegisterObjectClass[$Rect, [ drawMe: DrawMeForRects, quickDrawMe: DrawMeForRects, internalRead: ReadRect, internalWrite: WriteRect, newLayer: ChangeLayer, describe: Describe, wireTyped: TRUE ]]; HangExtensionsOn[bareRectClass]; wellRectClass _ CD.RegisterObjectClass[$WellRect, [ drawMe: DrawWellRect, interestRect: InsideWellRect, quickDrawMe: DrawWellRect, internalRead: ReadRect, internalWrite: WriteRect, newLayer: ChangeLayer, describe: Describe, wireTyped: TRUE ]]; HangExtensionsOn[wellRectClass]; [] _ CD.RegisterObjectClass[$SaveRect, [internalRead: ReadRect]];--old stuff }; Describe: CD.DescribeProc = { RETURN [Rope.Concat["rect ", CDOps.LayerRope[ob.layer]]] }; DrawMeForRects: CD.DrawProc = { pr.drawRect[pr, CDBasicsInline.MapRect[ob.bbox, trans], ob.layer] }; DrawWellRect: CD.DrawProc = { r: CD.Rect = CDBasicsInline.MapRect[ob.bbox, trans]; pr.drawRect[pr, CDBasics.Extend[r, -CDLayers.layerData[ob.layer].wSurr], CDLayers.layerData[ob.layer].paint]; pr.drawRect[pr, r, CDLayers.layerData[ob.layer].well]; }; InsideWellRect: PROC [ob: CD.Object] RETURNS [CD.Rect] = { RETURN [CDBasics.Extend[ob.bbox, -CDLayers.layerData[ob.layer].wSurr]] }; ChangeLayer: CD.ChangeLayerProc = { newOb: CD.Object _ CreateRect[CD.InterestSize[inst.ob], layer]; IF newOb#NIL THEN inst.ob _ newOb; RETURN [newOb#NIL]; }; WriteRect: CD.InternalWriteProc = { CDIO.WritePos[h, CD.InterestSize[ob]]; CDIO.WriteLayer[h, ob.layer]; }; ReadRect: CD.InternalReadProc = { sz: CD.Position = CDIO.ReadPos[h]; l: CD.Layer = CDIO.ReadLayer[h]; ob: CD.Object = CreateRect[sz, l]; RETURN [ob] }; <<--CDLayers>> LayerData: TYPE = CDLayers.LayerData; DesignNotifyProc: TYPE = CDLayers.DesignNotifyProc; LayerNotifyProc: TYPE = CDLayers.LayerNotifyProc; LayerRec: TYPE = RECORD [w: CD.Number, use: CD.Layer]; GetLayerRec: PROC [design: REF, layer: CD.Layer] RETURNS [REF LayerRec] = { ENABLE UNWIND => NULL; WITH CDValue.Fetch[design, CDPrivate.layers[layer].globalUniqueKey, design] SELECT FROM lr: REF LayerRec => RETURN [lr]; ENDCASE => { lr: REF LayerRec _ NEW[LayerRec]; WITH design SELECT FROM d: CD.Design => lr^ _ GetLayerRec[d.technology, layer]^; t: CD.Technology => lr^ _ GetLayerRec[NIL, layer]^; ENDCASE => lr^ _ [w: 0, use: layer]; [] _ CDValue.StoreConditional[design, CDPrivate.layers[layer].globalUniqueKey, lr]; RETURN [GetLayerRec[design, layer]]; --recursion prevents concurrency problems }; }; CurrentLayer: PUBLIC PROC [design: CD.Design] RETURNS [CD.Layer] = { RETURN [CDValue.FetchInt[design, $CurrentLayer, technology]] }; LayerWidth: PUBLIC PROC [design: CD.Design, layer: CD.Layer] RETURNS [CD.Number] = { RETURN [GetLayerRec[design, layer].w] }; PlaceholderToAbstract: PUBLIC PROC [design: CD.Design, layer: CD.Layer] RETURNS [CD.Layer] = { IF lData[layer].kind=placeholder THEN RETURN [GetLayerRec[design, layer].use]; RETURN [layer]; }; SetCurrentLayer: PUBLIC PROC [design: REF, layer: CD.Layer] = { CDValue.StoreInt[boundTo: design, key: $CurrentLayer, value: layer]; WITH design SELECT FROM d: CD.Design => FOR list: LIST OF DesignNotifyProc _ layerProcList, list.rest WHILE list#NIL DO list.first[d]; ENDLOOP; ENDCASE => NULL; }; <<--design can exceptionally be a technology to set default values>> <<--reserve call for CDPanelImpl; otherwise CDPanel gets fooled>> SetLayerWidth: PUBLIC PROC [design: REF, layer: CD.Layer, width: CD.Number] = { GetLayerRec[design, layer].w _ width; WITH design SELECT FROM d: CD.Design => FOR list: LIST OF LayerNotifyProc _ widthProcList, list.rest WHILE list#NIL DO list.first[d, layer]; ENDLOOP; ENDCASE => NULL; }; SetPlaceholderToAbstract: PUBLIC PROC [design: REF, placeholder, abstract: CD.Layer] = { IF lData[placeholder].kind#placeholder THEN ERROR; GetLayerRec[design, placeholder].use _ abstract; WITH design SELECT FROM d: CD.Design => FOR list: LIST OF LayerNotifyProc _ placeholderProcList, list.rest WHILE list#NIL DO list.first[d, placeholder]; ENDLOOP; ENDCASE => NULL; }; MakeAbstract: PUBLIC PROC [abstract: CD.Layer, paint: CD.Layer _ CD.undefLayer, well: CD.Layer _ CD.undefLayer, wSurr: BYTE _ 0] = { IF well#CD.undefLayer AND lData[well].kind#paint THEN ERROR; lData[abstract] _ [kind: abstract, paint: paint, well: well, wSurr: wSurr]; }; MakePlaceholder: PUBLIC PROC [placeholder: CD.Layer, defaultsTo: CD.Layer] = { lData[placeholder] _ [kind: placeholder, paint: CD.errorLayer, well: CD.undefLayer, wSurr: 0]; GetLayerRec[NIL, placeholder].use _ defaultsTo; }; MakePaint: PUBLIC PROC [layer: CD.Layer] = { lData[layer] _ [kind: paint, paint: layer, well: CD.undefLayer, wSurr: 0]; GetLayerRec[NIL, layer].use _ layer; }; MakeSuppressIR: PUBLIC PROC [layer: CD.Layer, suppressIR: BOOL _ TRUE] = { lData[layer].suppressIR _ suppressIR; }; RegisterNotifiers: PUBLIC ENTRY PROC [layer: DesignNotifyProc_NIL, width: LayerNotifyProc_NIL, placeholder: LayerNotifyProc_NIL] = { ENABLE UNWIND => NULL; IF layer#NIL THEN layerProcList _ CONS[layer, layerProcList]; IF width#NIL THEN widthProcList _ CONS[width, widthProcList]; IF placeholder#NIL THEN placeholderProcList _ CONS[placeholder, placeholderProcList]; }; lData: REF ARRAY CD.Layer OF LayerData = NEW[ARRAY CD.Layer OF LayerData]; layerData: PUBLIC REF READONLY ARRAY CD.Layer OF LayerData = lData; layerProcList: LIST OF DesignNotifyProc _ NIL; widthProcList: LIST OF LayerNotifyProc _ NIL; placeholderProcList: LIST OF LayerNotifyProc _ NIL; InitLayers: PROC [] = { CDValue.RegisterKey[key: $CurrentLayer]; FOR l: CD.Layer IN CD.Layer DO lData[l] _ [kind: placeholder, paint: CD.commentLayer, well: CD.undefLayer, wSurr: 0]; [] _ CDValue.RegisterKey[CDPrivate.layers[l].globalUniqueKey]; ENDLOOP; }; <<>> InitLayers[]; InitRects[]; END.