DIRECTORY CD, CDBasics, CDCells, CDDefaultProcs, CDDirectory, CDErrors, CDOps, CDProperties, CDRects, RefTab, Rope, TerminalIO; CDErrorsImpl: CEDAR PROGRAM IMPORTS CD, CDBasics, CDCells, CDDefaultProcs, CDDirectory, CDProperties, CDOps, CDRects, RefTab, Rope, TerminalIO EXPORTS CDErrors = BEGIN IgnoreContext: CD.DrawContextProc = {}; InstancePredicate: TYPE = CDErrors.InstancePredicate; WhereFound: TYPE = {itself, cell, design, none}; foundAndStop: SIGNAL = CODE; foundInFirstPlace: SIGNAL = CODE; MyDevice: TYPE = RECORD [ seen: RefTab.Ref, searchOb: CD.Object, found: BOOL_FALSE, trans: CD.Transformation_[[0, 0], original], cell: CD.Object_NIL, --is not a cell but any object able to display errors cellFound: BOOL_FALSE, cellTrans: CD.Transformation_[[0, 0], original] ]; MyDrawChild: CD.DrawProc = { device: REF MyDevice = NARROW[pr.devicePrivate]; IF RefTab.Insert[device.seen, ob, $x] THEN { IF ob=device.searchOb THEN { device.trans _ trans; device.found _ TRUE; SIGNAL foundInFirstPlace; RETURN }; ob.class.drawMe[pr: pr, ob: ob, trans: trans, readOnlyInstProps: readOnlyInstProps! foundInFirstPlace => { IF ob.class.showsErrors THEN { device.cell _ ob; device.cellTrans _ trans; device.cellFound _ TRUE; ERROR foundAndStop; --this signal is not an error, but we will not resume it }; REJECT } ]; }; }; FindAnInstance: PROC [design: CD.Design, ob: CD.Object] RETURNS [where: WhereFound _ none, cell: CD.Object_NIL, pos: CD.Position_[0, 0], orientation: CD.Orientation_original] = { failed: BOOL _ FALSE; myDrawRef: REF CD.DrawInformation; myDevice: REF MyDevice _ NEW[MyDevice _ [searchOb: ob, seen: RefTab.Create[]]]; IF ob=NIL THEN RETURN [where _ design]; IF ob.class.showsErrors THEN RETURN [where _ itself, cell _ ob]; myDrawRef _ CD.CreateDrawRef[[ design: design, interestClip: CDBasics.universe, drawChild: MyDrawChild, drawRect: CDDefaultProcs.IgnoreRect, drawContext: IgnoreContext, devicePrivate: myDevice ]]; CDOps.DrawDesign[design, myDrawRef ! foundAndStop, foundInFirstPlace => CONTINUE; ]; IF myDevice.found THEN { IF myDevice.cellFound AND ~CDCells.IsDummyCell[myDevice.cell] THEN { r: CD.Rect; cell _ myDevice.cell; where _ WhereFound[cell]; r _ CDBasics.DeMapRect[myDevice.searchOb.bbox, myDevice.trans]; pos _ CDBasics.BaseOfRect[r]; orientation _ CDBasics.DecomposeOrient[itemInWorld: myDevice.trans.orient, cellInWorld: myDevice.cellTrans.orient].itemInCell; } ELSE { where _ WhereFound[design]; pos _ myDevice.trans.off; orientation _ myDevice.trans.orient; } } }; FancyClip: PROC [r: CD.Rect, into: CD.Object, msg: Rope.ROPE] RETURNS [cr: CD.Rect, text: Rope.ROPE] = { EasyChangeAbleRect: PROC [ob: CD.Object] RETURNS [CD.Rect] = { WITH ob.specific SELECT FROM cp: CD.CellSpecific => RETURN [ob.bbox] ENDCASE => NULL; RETURN [ob.bbox] }; text _ msg; cr _ r; IF into#NIL THEN { ir: CD.Rect _ EasyChangeAbleRect[into]; cr _ CDBasics.Intersection[cr, ir]; IF ~CDBasics.NonEmpty[cr] THEN { text _ Rope.Concat[msg, "(outside object)"]; IF cr.x1>=cr.x2 THEN { --x dimension problem IF cr.x1>=ir.x2 THEN {cr.x2 _ ir.x2; cr.x1 _ MAX[ir.x1, ir.x2-(ir.x2-ir.x1)/16-2]} ELSE {cr.x1 _ ir.x1; cr.x2 _ MIN[ir.x2, ir.x1+(ir.x2-ir.x1)/8+2]} }; IF cr.y1<=cr.y2 THEN { IF cr.y1>ir.y2 THEN {cr.y2 _ ir.y2; cr.y1 _ MAX[ir.y1, ir.y2-(ir.y2-ir.y1)/16-2]} ELSE {cr.y1 _ ir.y1; cr.y2 _ MIN[ir.y2, ir.y1+(ir.y2-ir.y1)/8+2]} }; IF ~CDBasics.NonEmpty[cr] THEN cr _ ir; }; }; }; IncludeMessage: PUBLIC PROC [design: CD.Design, ob: CD.Object, rect: CD.Rect, message: Rope.ROPE_NIL, owner: ATOM_NIL] RETURNS [done: BOOL_TRUE, into: CD.Object_NIL, inst: CD.Instance_NIL] = { mappedRect: CD.Rect; where: WhereFound; cell: CD.Object; pos: CD.Position; orientation: CD.Orientation; from: Rope.ROPE _ NIL; IF design=NIL OR ~CDBasics.NonEmpty[rect] THEN RETURN [done_FALSE]; [where: where, cell: cell, pos: pos, orientation: orientation] _ FindAnInstance[design, ob]; IF where=none THEN RETURN [done_FALSE] ELSE IF where=itself THEN {mappedRect _ rect; into _ ob} ELSE { cellRep: REF; IF where=design THEN {mappedRect _ rect; cellRep _ $design} ELSE IF cell#NIL THEN { mappedRect _ CDBasics.MapRect[rect, [pos, orientation]]; cellRep _ CDDirectory.Name[cell, design]; into _ cell; IF cellRep=NIL THEN {cellRep _ $design; into _ NIL}; } ELSE ERROR; IF ob#NIL AND ob.class.composed THEN { x: REF = CDProperties.GetObjectProp[ob, hasErrorsInOtherCellsKey]; IF x=NIL THEN CDProperties.PutObjectProp[ob, hasErrorsInOtherCellsKey, cellRep] ELSE IF x#$many AND x#cellRep THEN { IF ~ISTYPE[x, Rope.ROPE] OR ~Rope.Equal[NARROW[x, Rope.ROPE], CDDirectory.Name[ob, design]] THEN CDProperties.PutObjectProp[ob, hasErrorsInOtherCellsKey, $many] } }; IF ob#NIL THEN { from _ CDDirectory.Name[ob, design]; IF from=NIL THEN from _ CD.Describe[ob, NIL, design]; message _ Rope.Cat[message, " [local to ", from, "]"]; } }; IF where#design THEN [mappedRect, message] _ FancyClip[mappedRect, cell, message]; IF cell=NIL OR (~cell.immutable AND CDCells.IsCell[cell]) THEN { inst _ CDCells.IncludeOb[design: design, cell: cell, ob: CDRects.CreateRect[CDBasics.SizeOfRect[mappedRect], CD.errorLayer], trans: [CDBasics.BaseOfRect[mappedRect], original], mode: dontResize ].newInst; CDOps.Redraw[design, (IF cell=NIL THEN mappedRect ELSE CDBasics.universe)]; IF owner#NIL THEN CDProperties.PutInstanceProp[inst, ownerKey, owner]; IF message#NIL THEN CDProperties.PutInstanceProp[inst, messageKey, message]; IF from#NIL THEN CDProperties.PutInstanceProp[inst, showErrorsForOtherKey, from]; } ELSE TerminalIO.PutRope["can't display error message in immutable object\n"]; }; EqualXR: PROC [x: REF, r: Rope.ROPE] RETURNS [BOOL] = INLINE { WITH x SELECT FROM xr: Rope.ROPE => RETURN [Rope.Equal[xr, r]]; ENDCASE => RETURN [x=r] --both NIL }; RemFromCellOrTopLevel: PROC [design: CD.Design, owner: ATOM, cell: CD.Object, removeIt: InstancePredicate, restricted: Rope.ROPE_NIL, all: BOOL_FALSE] RETURNS [others: BOOL] = { redraw: BOOL_FALSE; removeList: CD.InstanceList _ NIL; countAll, countRemove: INT _ 0; EachInst: CDCells.InstEnumerator = { IF ~IsError[inst.ob] THEN RETURN; countAll _ countAll+1; IF owner=NIL OR owner=CDProperties.GetInstanceProp[inst, ownerKey] THEN { IF all OR EqualXR[CDProperties.GetInstanceProp[inst, showErrorsForOtherKey], restricted] THEN { IF cell#NIL OR ~inst.selected THEN { --dont remove selected messages IF removeIt=NIL OR removeIt[inst] THEN { countRemove _ countRemove+1; removeList _ CONS[inst, removeList] } } } } }; IF cell=NIL THEN cell _ CDOps.PushedTopCell[design]; IF CDCells.IsCell[cell] THEN { [] _ CDCells.EnumerateInstances[cell, EachInst]; IF removeList#NIL AND cell.immutable THEN { TerminalIO.PutRope["can't remove error message from immutable object\n"]; }; FOR list: CD.InstanceList _ removeList, list.rest WHILE list#NIL DO [] _ CDCells.RemoveInstance[design, cell, list.first, doit] ENDLOOP; }; IF countRemove>0 AND cell#NIL THEN CDOps.Redraw[design]; others _ countAll#countRemove; }; RemoveMessages: PUBLIC PROC [design: CD.Design, ob: CD.Object, owner: ATOM, alsoOthers: BOOL, removeIt: InstancePredicate] = { RemoveMessFromEveryWhere: PROC [restricted: Rope.ROPE_NIL] RETURNS [others: BOOL_ FALSE] = { EachOb: CDDirectory.EachObjectProc = { IF CDCells.IsCell[me] THEN others _ others OR RemFromCellOrTopLevel[design, owner, me, removeIt, restricted]; }; [] _ CDDirectory.EnumerateDesign[design, EachOb]; others _ others OR RemFromCellOrTopLevel[design, owner, NIL, removeIt, restricted]; }; IF ob=NIL OR CDCells.IsCell[ob] THEN [] _ RemFromCellOrTopLevel[design, owner, ob, removeIt, NIL, alsoOthers] ELSE IF ob.class.composed THEN { others: BOOL _ TRUE; -- found error messages of other owners x: REF = CDProperties.GetObjectProp[ob, hasErrorsInOtherCellsKey]; IF x#NIL THEN { obName: Rope.ROPE = CDDirectory.Name[ob, design]; IF x=$design THEN others _ RemFromCellOrTopLevel[design, owner, NIL, removeIt, obName] ELSE WITH x SELECT FROM r: Rope.ROPE => { other: CD.Object _ CDDirectory.Fetch[design, r].object; IF other#NIL AND CDCells.IsCell[other] THEN others _ RemFromCellOrTopLevel[design, owner, other, removeIt, obName] }; ENDCASE => others _ RemoveMessFromEveryWhere[obName]; IF owner=NIL OR ~others THEN CDProperties.PutObjectProp[ob, hasErrorsInOtherCellsKey, NIL]; }; } ELSE [] _ RemoveMessFromEveryWhere[CD.Describe[ob]]; }; RemoveAllMessages: PUBLIC PROC [design: CD.Design, owner: ATOM, removeIt: InstancePredicate] = { EachOb: CDDirectory.EachObjectProc = { IF CDCells.IsCell[me] THEN [] _ RemFromCellOrTopLevel[design, owner, me, removeIt, NIL, TRUE] }; [] _ CDDirectory.EnumerateDesign[design, EachOb]; [] _ RemFromCellOrTopLevel[design, owner, NIL, removeIt, NIL, TRUE]; }; IsError: PROC [ob: CD.Object] RETURNS [BOOL] = INLINE { RETURN [ob.layer=CD.errorLayer AND ob.class.wireTyped] }; messageKey: PUBLIC ATOM _ $SignalName; ownerKey: ATOM = $ErrorOwner; hasErrorsInOtherCellsKey: ATOM = $showErrorsElseWhere; showErrorsForOtherKey: ATOM = $showErrorsForOthers; [] _ CDProperties.RegisterProperty[hasErrorsInOtherCellsKey, $chj]; [] _ CDProperties.RegisterProperty[showErrorsForOtherKey, $chj]; [] _ CDProperties.RegisterProperty[ownerKey, $chj]; END.  CDErrorsImpl.mesa (part of ChipNDale) Copyright c 1985, 1986, 1987 by Xerox Corporation. All rights reserved. Created by Christian Jacobi, March 1, 1985 9:40:12 am PST Last edited by: Christian Jacobi, June 5, 1987 6:59:49 pm PDT Needs some redesign to be able to deal with immutable objects --PROC [inst: CD.Instance] RETURNS [yes: BOOL_TRUE]; --cell is not a cell but any object able to display errors --get an instance --mapp the error rectangle --make ob pointing to errormessage places if of any value and possible --include the error rectangle --properties --all: whether we want restricted to be applied --restricted: whether only messages with Name(origin)=restricted will be removed --to improve, handle innerrect crap, removing and repositioning inside Κ Š˜codešœ,™,Kšœ Οmœ=™HKšœ;™;K™=K™K™=K˜—šΟk ˜ Kšžœ˜Kšœ ˜ Kšœ˜Kšœ˜Kšœ ˜ Kšœ ˜ Kšœ˜Kšœ ˜ Kšœ˜Kšœ˜Kšœ˜Kšœ ˜ —K˜šΟn œžœž˜Kšžœžœh˜rKšžœ ˜—Kšž˜K˜KšŸ œžœ˜'K˜šœžœ˜5Kšœ4™4—K˜Kšœ žœ ˜0K˜Kšœžœžœ˜Kšœžœžœ˜!K˜šœ žœžœ˜Kšœ˜Kšœ žœ˜Kšœžœžœ˜Kšœžœ#˜,KšœžœžœΟc5˜JKšœ žœžœ˜Kšœ žœ"˜/Kšœ˜—K˜šΟb œžœ ˜Kšœžœ žœ˜0šžœ$žœ˜,šžœžœ˜Kšœ˜Kšœžœ˜Kšžœ˜Kšž˜K˜—šœT˜Tšœ˜šžœžœ˜Kšœ˜Kšœ˜Kšœžœ˜Kšžœ 8˜LKšœ˜—Kšž˜Kšœ˜—Kšœ˜—K˜—Kšœ˜—K˜šŸœžœ žœ žœ žœ"žœžœžœžœ˜²Kšœ:™:Kšœžœžœ˜Kšœ žœžœ˜"Kšœ žœ žœ3˜OKšžœžœžœžœ˜'Kšžœžœžœ˜@šœ žœ˜Kšœ˜Kšœ ˜ Kšœ˜Kšœ$˜$Kšœ˜Kšœ˜Kšœ˜—šœ$˜$Kšœ%žœ˜.Kšœ˜—šžœžœ˜šžœžœ%žœ˜DKšœžœ˜ Kšœ˜Kšœ˜Kšœ?˜?Kšœ˜Kšœ~˜~K˜—šžœ˜Kšœ˜Kšœ˜Kšœ$˜$K˜—Kšœ˜—Kšœ˜—K˜šŸ œžœžœ žœžœžœžœžœ˜hK˜š Ÿœžœžœ žœžœ ˜>šžœ žœž˜Kšœžœžœ ˜'Kšžœžœ˜—Kšžœ ˜K˜—K˜Kšœ ˜ Kšœ˜šžœžœžœ˜Kšœžœ!˜'Kšœ#˜#šžœžœ˜ Kšœ,˜,šžœžœ ˜,Kšžœžœžœ"˜RKšžœžœ!˜AK˜—šžœžœ˜Kšžœ žœžœ"˜QKšžœžœ!˜AK˜—Kšžœžœ ˜'K˜—K˜—Kšœ˜—K˜š"Πbnœžœžœ žœ žœžœžœžœ žœžœžœžœžœžœžœžœ žœ˜ΐKšœ žœ˜Kšœ˜Kšœžœ˜Kšœžœ ˜Kšœ žœ ˜Kšœ žœžœ˜Kš žœžœžœžœžœžœ˜CKšœ™Kšœ\˜\Kšœ™Kšžœ žœžœžœ˜&Kšžœžœžœ ˜9šžœ˜Kšœ žœ˜Kšžœžœ(˜<šžœžœžœžœ˜Kšœ8˜8Kšœ)˜)Kšœ ˜ Kšžœ žœžœžœ˜4K˜—Kšžœžœ˜ KšœF™Fšžœžœžœžœ˜'Kšœžœ<˜BKšžœžœžœB˜Ošžœžœ žœ žœ˜$šžœžœ žœžœ žœ žœ!žœ˜aKšœ@˜@—K˜—K˜—šžœžœžœ˜Kšœ$˜$Kš žœžœžœžœžœ ˜5Kšœ6˜6K˜—K˜—Kšžœžœ>˜RKšœ™š žœžœžœžœžœ˜@šœ)˜)Kšœ ˜ Kšœ8žœ˜HKšœ3˜3Kšœ˜Kšœ ˜ —Kš œžœžœžœ žœ˜KKš  ™ Kšžœžœžœ5˜FKšžœ žœžœ9˜LKšžœžœžœA˜QK˜—KšžœI˜MKšœ˜—K˜šŸœžœžœ žœžœžœžœ˜>šžœžœž˜Kšœ žœžœ˜,Kšžœžœ  ˜#—Kšœ˜—K˜šŸœžœ žœžœžœ7žœžœžœžœžœ žœ˜±Kš /™/Kš P™PKšœžœžœ˜Kšœ žœžœ˜"Kšœžœ˜šŸœ˜$Kšžœžœžœ˜"Kšœ˜šžœžœžœ4žœ˜JšžœžœPžœ˜_š žœžœžœžœ ˜Dšžœ žœžœžœ˜)Kšœ˜Kšœ žœ˜$Kšœ˜—K˜—K˜—K˜—K˜—Kšžœžœžœ$˜4Kš F™Fšžœžœ˜Kšœ0˜0šžœ žœžœžœ˜+KšœI˜IK˜—š žœžœ&žœžœž˜CKšœ;˜;Kšžœ˜—K˜—Kšžœžœžœžœ˜8Kšœ˜Kšœ˜K˜—šŸœžœžœ žœ žœžœžœ"˜~K˜šŸœžœžœžœžœ žœžœ˜\šŸœ ˜&šžœžœ˜Kšœžœ@˜R—Kšœ˜—Kšœ1˜1Kšœžœ&žœ˜SKšœ˜K˜—Kš žœžœžœžœ9žœ ˜mšžœžœžœ˜!Kšœžœžœ (˜—Kšœ˜—Kšœ˜—Kšžœ0˜4Kšœ˜—K˜š Ÿœžœžœ žœžœ"˜`šŸœ ˜&šžœžœ˜Kšœ8žœžœ˜B—Kšœ˜—Kšœ1˜1Kšœ*žœ žœžœ˜DKšœ˜K˜—š Ÿœžœžœ žœžœžœ˜7Kšžœ žœ žœ˜6Kšœ˜—K˜Kšœ žœžœ˜'Kšœ žœ˜Kšœžœ˜7Kšœžœ˜4KšœC˜CKšœ@˜@Kšœ3˜3Kšžœ˜K˜K˜K˜—…—#Μ3b