<> <> <> <> DIRECTORY CD, CDAtomicObjects, CDCells, CDRects, CDTexts, CDSymbolicObjects, CMosB, CMosBWellDifImpl, Convert, Core, CoreIO, CoreProperties, CoreGeometry, GList, HashTable, Rope; CoreGeometryIOImpl: CEDAR PROGRAM IMPORTS CD, CDAtomicObjects, CDCells, CDRects, CDSymbolicObjects, CDTexts, CMosB, CMosBWellDifImpl, Convert, CoreIO, CoreProperties, GList, HashTable, Rope SHARES CDCells, CDRects, CDTexts, CDSymbolicObjects, CoreGeometry, CMosBWellDifImpl = BEGIN OPEN CoreIO; <> <> <> <> <> <> <> <> <> objectClassRegistry: HashTable.Table _ HashTable.Create[]; ObjectClassData: TYPE = REF ObjectClassDataRec; ObjectClassDataRec: TYPE = RECORD [ write: ObjectClassWriteProc _ NIL, read: ObjectClassReadProc _ NIL]; ObjectClassWriteProc: TYPE = PROC [h: Handle, me: CD.Object]; ObjectClassReadProc: TYPE = PROC [h: Handle] RETURNS [obj: CD.Object]; RegisterObjectClass: PROC [objectClass: CD.ObjectClass, write: ObjectClassWriteProc, read: ObjectClassReadProc] = { data: ObjectClassData _ NEW[ObjectClassDataRec _ [write, read]]; IF write=NIL OR read=NIL THEN ERROR; -- if only one NIL then invariant for object write/read is broken [] _ HashTable.Store[objectClassRegistry, objectClass.objectType, data]; }; <> WriteInstance: PROC [h: Handle, instance: CD.Instance] = { WriteObject[h, instance.ob]; WritePosition[h, instance.location]; WriteInt[h, instance.orientation]; WriteCDProperties[h, instance.properties]; }; ReadInstance: PROC [h: Handle] RETURNS [instance: CD.Instance] = { instance _ NEW [CD.InstanceRep _ [ob: NIL]]; instance.ob _ ReadObject[h]; instance.location _ ReadPosition[h]; instance.orientation _ ReadInt[h]; instance.properties _ ReadCDProperties[h]; }; WriteInstanceList: PROC [h: Handle, instances: LIST OF CD.Instance] = { WriteInt[h, GList.Length[instances]]; WHILE instances#NIL DO WriteInstance[h, instances.first]; instances _ instances.rest; ENDLOOP; }; ReadInstanceList: PROC [h: Handle] RETURNS [instances: LIST OF CD.Instance _ NIL] = { THROUGH [1 .. ReadInt[h]] DO instances _ CONS [ReadInstance[h], instances]; ENDLOOP; }; objectsAtom: ATOM = RegisterProperty[$CoreGeometryIOObjects, WriteObjectsProp, ReadObjectsProp]; <<>> <> <<>> WriteObjectsProp: PropWriteProc = { WriteHashTable[h, NARROW[value], WriteObjectIDPair]; }; <<>> WriteObjectIDPair: HashWriteProc = { id: ROPE _ NARROW[key]; object: CD.Object _ NARROW[value]; WriteID[h, id]; WriteObject[h, object]; }; ReadObjectsProp: PropReadProc = { value _ ReadHashTable[h, ReadObjectIDPair, HashTable.RopeEqual, HashTable.HashRope]; }; ReadObjectIDPair: HashReadProc = { key _ ReadID[h]; value _ ReadObject[h]; }; < Rope ID] is stored on the handle under the key objectsAtom>> <> WriteObject: PROC [h: Handle, obj: CD.Object] = { objects: HashTable.Table _ NARROW [CoreProperties.GetProp[h.properties, objectsAtom]]; objectID: ROPE _ NIL; IF objects=NIL THEN { objects _ HashTable.Create[]; h.properties _ CoreProperties.PutProp[h.properties, objectsAtom, objects]; }; objectID _ NARROW [HashTable.Fetch[objects, obj].value]; IF objectID=NIL THEN { classData: ObjectClassData _ NARROW[HashTable.Fetch[objectClassRegistry, obj.class.objectType].value]; objectID _ Rope.Cat["O", Convert.RopeFromInt[from: HashTable.GetSize[objects], base: 16, showRadix: FALSE]]; IF NOT HashTable.Insert[objects, obj, objectID] THEN ERROR; WriteID[h, objectID]; WriteAtom[h, obj.class.objectType]; IF classData=NIL THEN { IF CDAtomicObjects.IsAtomicOb[obj] THEN { WritePosition[h, CD.InterestSize[obj]]; WriteLayer[h, obj.layer]; } ELSE ERROR; -- no write proc and not atomic } ELSE classData.write[h, obj]; WriteCDProperties[h, obj.properties]; } ELSE WriteID[h, objectID]; }; < CD.Object] is stored on the handle under the key objectsAtom>> ReadObject: PROC [h: Handle] RETURNS [obj: CD.Object] = { objects: HashTable.Table _ NARROW [CoreProperties.GetProp[h.properties, objectsAtom]]; objectID: ROPE; IF objects=NIL THEN { objects _ HashTable.Create[equal: HashTable.RopeEqual, hash: HashTable.HashRope]; h.properties _ CoreProperties.PutProp[h.properties, objectsAtom, objects]; }; objectID _ ReadID[h]; IF Rope.Fetch[objectID]#'O THEN ERROR; obj _ NARROW [HashTable.Fetch[objects, objectID].value]; IF obj=NIL THEN { classAtom: ATOM _ ReadAtom[h]; classData: ObjectClassData _ NARROW[HashTable.Fetch[objectClassRegistry, classAtom].value]; IF classData=NIL THEN { pos: CD.Position _ ReadPosition[h]; layer: CD.Layer _ ReadLayer[h]; obj _ CDAtomicObjects.CreateAtomicOb[classAtom, pos, CMosB.cmosB, layer]; } ELSE obj _ classData.read[h]; obj.properties _ ReadCDProperties[h]; IF NOT HashTable.Insert[objects, objectID, obj] THEN ERROR; }; }; WritePosition: PROC [h: Handle, position: CD.Position] = { WriteInt[h, position.x]; WriteInt[h, position.y]; }; ReadPosition: PROC [h: Handle] RETURNS [position: CD.Position] = { position.x _ ReadInt[h]; position.y _ ReadInt[h]; }; WriteLayer: PROC [h: Handle, layer: CD.Layer] = { WriteInt[h, layer]; }; ReadLayer: PROC [h: Handle] RETURNS [layer: CD.Layer] = { layer _ ReadInt[h]; }; WriteCDProperties: PROC [h: Handle, properties: CD.PropList] = { props: Core.Properties _ NIL; WHILE properties#NIL DO IF ISTYPE [properties.first.key, ATOM] THEN props _ CoreProperties.PutProp[props, NARROW [properties.first.key], properties.first.val]; properties _ properties.rest; ENDLOOP; WriteProperties[h, props]; }; ReadCDProperties: PROC [h: Handle] RETURNS [properties: CD.PropList _ NIL] = { Consume: PROC [key: ATOM, val: REF] = { properties _ CONS [[key, val], properties]; }; CoreProperties.Enumerate[ReadProperties[h], Consume]; }; WriteRect: PROC [h: Handle, rect: CD.Rect] = { WriteInt[h, rect.x1]; WriteInt[h, rect.y1]; WriteInt[h, rect.x2]; WriteInt[h, rect.y2]; }; ReadRect: PROC [h: Handle] RETURNS [rect: CD.Rect] = { rect.x1 _ ReadInt[h]; rect.y1 _ ReadInt[h]; rect.x2 _ ReadInt[h]; rect.y2 _ ReadInt[h]; }; <> <> <> <<>> <> <> < {WriteInt[h, 1]; WriteInstance[h, instance]};>> < {>> <> <> <<};>> < ERROR; -- hack!>> <<};>> <> <> <> <> <> <<};>> <<>> GeometryPropWrite: PropWriteProc = { WriteInstanceList[h, NARROW [value]]; }; GeometryPropRead: PropReadProc = {value _ ReadInstanceList[h]}; InstancePropWrite: PropWriteProc = {WriteInstance[h, NARROW [value]]}; InstancePropRead: PropReadProc = {value _ ReadInstance[h]}; <> <> <> WriteRectangle: ObjectClassWriteProc = { WritePosition[h, CD.InterestSize[me]]; WriteLayer[h, me.layer]; }; ReadRectangle: ObjectClassReadProc = { sz: CD.Position = ReadPosition[h]; l: CD.Layer = ReadLayer[h]; ob: CD.Object = CDRects.CreateRect[sz, l]; RETURN [ob] }; <> WriteCell: ObjectClassWriteProc = { cellPtr: CD.CellPtr _ NARROW [me.specificRef]; WritePosition[h, me.size]; WriteInstanceList[h, cellPtr.contents]; WriteRect[h, cellPtr.ir]; WriteRope[h, cellPtr.name]; WriteInt[h, LOOPHOLE[cellPtr.simplifyOn]]; WriteRect[h, cellPtr.dIr]; WriteAtom[h, IF cellPtr.drawBorder THEN $TRUE ELSE $FALSE]; WriteAtom[h, IF cellPtr.useDIr THEN $TRUE ELSE $FALSE]; }; ReadCell: ObjectClassReadProc = { cellPtr: CD.CellPtr _ NEW [CD.CellRep]; obj _ NEW [CD.ObjectRep _ [class: CDCells.cellClass]]; obj.size _ ReadPosition[h]; cellPtr.contents _ ReadInstanceList[h]; cellPtr.ir _ ReadRect[h]; cellPtr.name _ ReadRope[h]; cellPtr.simplifyOn _ LOOPHOLE[ReadInt[h]]; cellPtr.dIr _ ReadRect[h]; cellPtr.drawBorder _ ReadAtom[h]=$TRUE; cellPtr.useDIr _ ReadAtom[h]=$TRUE; obj.specificRef _ cellPtr; }; <> WriteMark: ObjectClassWriteProc = { }; ReadMark: ObjectClassReadProc = { RETURN[CDSymbolicObjects.CreateMark[]]; }; WritePinOrSegment: ObjectClassWriteProc = { WritePosition[h, me.size]; }; ReadPin: ObjectClassReadProc = { RETURN [CDSymbolicObjects.CreatePin[ReadPosition[h]]] }; ReadSegment: ObjectClassReadProc = { p: CD.Position _ ReadPosition[h]; RETURN [CDSymbolicObjects.CreateSegment[p.y, p.x]] }; <> WriteFlipText: ObjectClassWriteProc = { text: CDTexts.TextPtr _ NARROW [me.specificRef]; WriteRope[h, text.text]; WriteRope[h, text.cdFont.supposedName]; WriteInt[h, text.cdFont.scaleI]; }; ReadFlipText: ObjectClassReadProc = { text: ROPE _ ReadRope[h]; fontName: ROPE _ ReadRope[h]; scale: INT _ ReadInt[h]; font: CDTexts.CDFont _ CDTexts.MakeFont[fontName, scale]; obj _ CDTexts.CreateText[text, font]; }; <> Register: PROC [decoration: CoreGeometry.Decoration] = { <<[] _ RegisterProperty[decoration.irProp, RectPropWrite, RectPropRead];>> <<[] _ RegisterProperty[decoration.pinsProp, PinsPropWrite, PinsPropRead];>> [] _ RegisterProperty[decoration.geometryProp, GeometryPropWrite, GeometryPropRead]; [] _ RegisterProperty[decoration.transfProp, InstancePropWrite, InstancePropRead]; }; RegisterObjectClass[CDRects.bareRectClass, WriteRectangle, ReadRectangle]; RegisterObjectClass[CDCells.cellClass, WriteCell, ReadCell]; RegisterObjectClass[CDSymbolicObjects.markClass, WriteMark, ReadMark]; RegisterObjectClass[CDSymbolicObjects.pinClass, WritePinOrSegment, ReadPin]; RegisterObjectClass[CDSymbolicObjects.segmentClass, WritePinOrSegment, ReadSegment]; RegisterObjectClass[CMosBWellDifImpl.wndifClass, WriteRectangle, ReadRectangle]; RegisterObjectClass[CMosBWellDifImpl.wpdifClass, WriteRectangle, ReadRectangle]; RegisterObjectClass[CDTexts.textClass, WriteFlipText, ReadFlipText]; END.