CDRectsAndLayersImpl.mesa (part of ChipNDale)
Copyright © 1983, 1987 by Xerox Corporation. All rights reserved.
Created by: Christian Jacobi, June 24, 1983 4:58 pm
Last edited by: Christian Jacobi, April 1, 1987 5:25:38 pm PST
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: BOOLTRUE] = {
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.