CDRectsImpl.mesa (part of ChipNDale)
Copyright © 1983, 1986 by Xerox Corporation. All rights reserved.
Christian Jacobi, June 24, 1983 4:58 pm
Last Edited by: Christian Jacobi, August 25, 1986 11:50:51 am PDT
DIRECTORY
CD,
CDBasics,
CDCallSpecific,
CDIO,
CDInstances,
CDOrient,
CDPrivate,
CDProperties,
CDRects,
CDLayers,
CDOps,
LRUCache,
Rope,
SafeStorage;
CDRectsImpl: CEDAR MONITOR
IMPORTS CD, CDCallSpecific, CDBasics, CDInstances, CDIO, CDOrient, CDOps, CDPrivate, CDProperties, CDLayers, LRUCache, Rope, SafeStorage
EXPORTS CDRects
SHARES CD =
BEGIN
dummyRectPtr: CD.RectPtr = SafeStorage.GetPermanentZone[].NEW[CD.RectRep ← [filler: NIL]];
lruQueue: LRUCache.Handle ← LRUCache.Create[255, CDPrivate.Hash, Equal];
free: CD.Object ← NIL; --always bare rect
GiveOb: ENTRY PROC [] RETURNS [ob: CD.Object] = INLINE {
ob ← free; free ← NIL;
IF ob=NIL THEN ob ← NEW[CD.ObjectRep←[class: bareRectClass, specificRef: dummyRectPtr]];
};
Equal: PROC[x, y: REF] RETURNS [BOOL] = {
ob1: CD.Object = NARROW[x];
ob2: CD.Object = NARROW[y];
RETURN [ob1.class=ob2.class AND ob1.size=ob2.size AND ob1.layer=ob2.layer]
};
CreateRectProc: TYPE = PROC [size: CD.Position, l: CD.Layer] RETURNS [CD.Object] ← CreateBareRect;
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]=CreateBareRect THEN {
--don't cache a secod time..
ob ← CreateBareRect[size, l]
}
ELSE {
used: REF; insert: BOOL;
ob ← createRectArray[l][size, l];
[insert: insert, used: used] ← LRUCache.Include[lruQueue, ob];
IF ~insert THEN ob ← NARROW[used];
--otherwise do not remember object on free! we don't know its class
};
};
HangExtensionsOn: PROC[on: CD.ObjectClass] = {
CDCallSpecific.Register[$Lengthen, on, Lengthen];
CDCallSpecific.Register[$Default, on, Defaulten];
CDCallSpecific.Register[$ChangeLayer, on, ChangeLayer];
};
UseAsCreateRect: PUBLIC PROC [l: CD.Layer,
createRect: PROC [size: CD.Position, l: CD.Layer] RETURNS [CD.Object],
hangExtensionsOn: CD.ObjectClass
] = {
IF createRect=NIL THEN createRect ← CreateBareRect;
createRectArray[l] ← createRect;
IF hangExtensionsOn#NIL THEN HangExtensionsOn[hangExtensionsOn];
CDProperties.PutLayerProp[onto: l, prop: $CDxRectCreation, val: $CDxUser];
};
CreateBareRect: PUBLIC PROC [size: CD.Position, l: CD.Layer] RETURNS [ob: CD.Object] = {
used: REF; insert: BOOL;
ob ← GiveOb[];
ob.size ← CDBasics.MaxPoint[size, [1, 1]]; ob.layer ← l;
[insert: insert, used: used] ← LRUCache.Include[lruQueue, ob];
IF ~insert THEN {
free ← ob;
ob ← NARROW[used];
};
};
bareRectClass: PUBLIC CD.ObjectClass;
oldSaveRectClass: CD.ObjectClass; --for compatibility only
Init: PROC [] = {
bareRectClass ← CD.RegisterObjectClass[$Rect, [
drawMe: DrawMeForRects,
quickDrawMe: DrawMeForRects,
internalRead: ReadRect,
internalWrite: WriteRect,
describe: Describe,
wireTyped: TRUE
]];
HangExtensionsOn[bareRectClass];
oldSaveRectClass ← CD.RegisterObjectClass[$SaveRect, [internalRead: ReadRect]];
};
Describe: PROC[me: CD.Object] RETURNS [Rope.ROPE] = {
RETURN [Rope.Concat["rect ", CDOps.LayerName[me.layer]]]
};
DrawMeForRects: PROC [inst: CD.Instance, pos: CD.Position, orient: CD.Orientation,
pr: CD.DrawRef] = {
pr.drawRect[CDOrient.RectAt[pos, inst.ob.size, orient], inst.ob.layer, pr]
};
ChangeLayer: CDCallSpecific.CallProc = {
new: CD.Instance;
layer: CD.Layer ← WITH x SELECT FROM
lr: CDPrivate.LayerRef => lr.number,
ENDCASE => CDLayers.CurrentLayer[design];
new ← CDInstances.NewInstI[
ob: CreateRect[CD.InterestSize[inst.ob], layer],
location: CDBasics.BaseOfRect[CDInstances.InstRectI[inst]],
orientation: inst.orientation
];
repaintMe ← TRUE;
inst.ob ← new.ob;
inst.location ← new.location;
};
Lengthen: CDCallSpecific.CallProc = {
sz: CD.Position ← CD.InterestSize[inst.ob];
amount: CD.Position;
IF x=NIL THEN amount ← [0, design.technology.lambda]
ELSE IF ISTYPE [x, REF CD.Position] THEN amount ← NARROW[x, REF CD.Position]^
ELSE {done←FALSE; RETURN};
sz ← CDBasics.AddPoints[sz, amount];
IF sz.x<=0 OR sz.y<=0 THEN {done ← FALSE; RETURN};
inst.ob ← CreateRect[sz, inst.ob.layer];
repaintMe ← TRUE;
};
Defaulten: CDCallSpecific.CallProc = {
sz: CD.Position ← CD.InterestSize[inst.ob];
w: CD.Number ← CDLayers.LayerWidth[design, inst.ob.layer];
IF w<=0 THEN {done ← FALSE; RETURN};
sz.x ← w;
inst.ob ← CreateRect[sz, inst.ob.layer];
repaintMe ←TRUE;
};
SetLength: CDCallSpecific.CallProc = {
newLength: CD.Number ← NARROW[x, REF CD.Number]^;
sz: CD.Position ← inst.ob.size;
IF sz.y<sz.x THEN sz.x ← newLength
ELSE sz.y ← newLength;
inst.ob ← CreateRect[sz, inst.ob.layer];
repaintMe ← TRUE;
};
SetWidth: CDCallSpecific.CallProc = {
newWidth: CD.Number ← NARROW[x, REF CD.Number]^;
sz: CD.Position ← inst.ob.size;
IF sz.y>sz.x THEN sz.x ← newWidth
ELSE sz.y ← newWidth;
inst.ob ← CreateRect[sz, inst.ob.layer];
repaintMe ← TRUE;
};
WriteRect: CD.InternalWriteProc -- PROC [me: Object] -- = {
CDIO.WritePos[CD.InterestSize[me]];
CDIO.WriteLayer[me.layer];
};
ReadRect: CD.InternalReadProc --PROC [] RETURNS [Object]-- = {
sz: CD.Position = CDIO.ReadPos[];
l: CD.Layer = CDIO.ReadLayer[];
ob: CD.Object = CreateRect[sz, l];
RETURN [ob]
};
Init[];
END.