DIRECTORY StretchLines, TilerMenu USING [Register], TerminalIO USING [WriteRope, WriteInt, RequestRope, UserSaysYes], CDSequencer USING [Command, ImplementCommand], CD, CDPanel USING [FetchDefaultLevel], TokenIO, CDInline, CDOps USING [AddAnObject], CDCallSpecific USING [CallProc, Register], CDOrient, Rope USING [ROPE, Cat, Equal], Atom, Graphics; StretchLinesImpl: CEDAR PROGRAM IMPORTS Atom, TilerMenu, CD, TerminalIO, CDOps, CDInline, CDCallSpecific, Rope, CDSequencer, TokenIO, CDOrient, CDPanel, Graphics EXPORTS StretchLines = BEGIN OPEN StretchLines; StretchObj: TYPE = REF StretchObjRec; -- an object that can be put in a cell or design StretchObjRec: TYPE = RECORD [ label: Rope.ROPE, type: LineTypes, level: CD.Level -- for blunt lines, the level to be stretched. ]; objAtom: PUBLIC ATOM _ $StretchLine; objsProcs: REF CD.ObjectProcs; myLevel: CD.Level; objHeight: INT = 12; defaultObjWidth: INT = 45; minObjWidth: INT = 2 * CD.lambda; objBaseline: INT = 3; FindLabel: PUBLIC PROC [aptr: CD.ApplicationPtr] RETURNS [Rope.ROPE, LineTypes] = BEGIN st: StretchObj _ NARROW[aptr.ob.specificRef, StretchObj]; RETURN[st.label, st.type]; END; Fetch: PUBLIC PROC [aptr: CD.ApplicationPtr] RETURNS [LineData] = BEGIN markObj: StretchObj = NARROW[aptr.ob.specificRef]; line: LineData; orient: CD.Orientation _ aptr.orientation; IF CDOrient.IncludesMirrorX[orient] THEN { orient _ CDOrient.MirrorX[orient]; -- compiler can't nest these calls!!! orient _ CDOrient.Rotate90[orient]; orient _ CDOrient.Rotate90[orient]; }; line.point _ CDInline.BaseOfAnyRect[CDOrient.MapRect[ itemInCell: [x1: 0, y1: objBaseline, x2: aptr.ob.size.x, y2: objBaseline], cellSize: aptr.ob.size, cellInstOrient: aptr.orientation, cellInstPos: aptr.location]]; line.length _ aptr.ob.size.x; SELECT orient FROM CDOrient.original => line.direction _ up; CDOrient.rotate90 => line.direction _ left; CDOrient.rotate180 => line.direction _ down; CDOrient.rotate270 => line.direction _ right; ENDCASE => ERROR; line.type _ markObj.type; line.label _ markObj.label; line.level _ markObj.level; RETURN[line]; END; OKCommand: PROC [comm: CDSequencer.Command] RETURNS[BOOL] = BEGIN IF comm.pos.x > 10000 OR comm.pos.y > 10000 OR comm.pos.x < -10000 OR comm.pos.y < -10000 THEN BEGIN TerminalIO.WriteRope["Warning: Huge position passed to AlignmentMarks from ChipNDale, maybe the TIP table is screwed up?\n"]; TerminalIO.WriteRope["comm.pos.x ="]; TerminalIO.WriteInt[comm.pos.x]; TerminalIO.WriteRope[" comm.pos.y ="]; TerminalIO.WriteInt[comm.pos.y]; [] _ TerminalIO.RequestRope["\nOperation will be aborted, type return ......"]; RETURN[FALSE]; END; RETURN[TRUE]; END; Place: PUBLIC PROC [into: CD.Design, line: LineData, shift: BOOL _ TRUE] = BEGIN orient: CD.Orientation; obj: CD.ObPtr _ NEW[CD.ObjectDefinition]; p: CD.Position _ [line.point.x, line.point.y]; len: INT _ MAX[minObjWidth, line.length]; markObj: StretchObj _ NEW[StretchObjRec]; markObj.label _ line.label; markObj.type _ line.type; obj.p _ objsProcs; SELECT line.direction FROM up => { orient _ CDOrient.original; IF shift THEN p.y _ p.y - objBaseline; }; down => { orient _ CDOrient.rotate180; IF shift THEN p.y _ p.y - (objHeight - objBaseline); }; left => { orient _ CDOrient.rotate90; IF shift THEN p.x _ p.x - (objHeight - objBaseline); }; right => { orient _ CDOrient.rotate270; IF shift THEN p.x _ p.x - objBaseline; }; ENDCASE => ERROR; IF line.type = blunt THEN { IF line.level # CD.combined THEN markObj.level _ line.level ELSE markObj.level _ CDPanel.FetchDefaultLevel[into]; } ELSE markObj.level _ CD.combined; obj.level _ myLevel; obj.size _ [len, objHeight]; obj.specificRef _ markObj; CDOps.AddAnObject[design: into, ob: obj, location: p, orientation: orient]; END; DrawStretchMark: CD.DrawProc = BEGIN markObj: StretchObj = NARROW[aptr.ob.specificRef]; MoveTo: PROC [x, y: INT, draw: BOOL, aptr: CD.ApplicationPtr, pos: CD.DesignPosition, orient: CD.Orientation, context: Graphics.Context] = BEGIN p: CD.Position; p _ CDInline.AddPoints[CDOrient.MapPosition[ itemInCell: [x1: x, y1: y, x2: x, y2: y], cellSize: aptr.ob.size, cellInstOrient: orient], pos]; IF draw THEN Graphics.DrawTo[context, p.x, p.y] ELSE Graphics.SetCP[context, p.x, p.y]; END; Color: PROC [context: Graphics.Context] = BEGIN MapToReal: PROC[x, y: INT] RETURNS [REAL, REAL] = INLINE BEGIN MapPoint: PROC [p: CD.Position, cellSize: CD.Position, orient: CD.Orientation] RETURNS [CD.Position] = INLINE BEGIN RETURN[CDOrient.MapPosition[ itemInCell: [x1: p.x, y1: p.y, x2: p.x, y2: p.y], cellSize: cellSize, cellInstOrient: orient]]; END; orig: CD.Position; orig _ CDInline.AddPoints[MapPoint[[x, y], aptr.ob.size, orient], pos]; RETURN[orig.x, orig.y]; END; mid: INT _ aptr.ob.size.x / 2; x, y: REAL; path: Graphics.Path _ Graphics.NewPath[size: 8]; IF context = NIL THEN RETURN; [] _ Graphics.SetFat[context, FALSE]; [x, y] _ MapToReal[mid - 2, objBaseline + 0]; Graphics.MoveTo[path, x, y, TRUE]; [x, y] _ MapToReal[mid - 2, objBaseline + 4]; Graphics.LineTo[path, x, y]; [x, y] _ MapToReal[mid - 4, objBaseline + 4]; Graphics.LineTo[path, x, y]; [x, y] _ MapToReal[mid - 0, objBaseline + 8]; Graphics.LineTo[path, x, y]; [x, y] _ MapToReal[mid + 4, objBaseline + 4]; Graphics.LineTo[path, x, y]; [x, y] _ MapToReal[mid + 2, objBaseline + 4]; Graphics.LineTo[path, x, y]; [x, y] _ MapToReal[mid + 2, objBaseline + 0]; Graphics.LineTo[path, x, y]; Graphics.DrawArea[self: context, path: path]; END; Outline: PROC [context: Graphics.Context] = BEGIN right: INT _ aptr.ob.size.x; left: INT _ 0; mid: INT _ aptr.ob.size.x / 2; IF context = NIL THEN RETURN; [] _ Graphics.SetFat[context, FALSE]; MoveTo[left, objBaseline, FALSE, aptr, pos, orient, context]; MoveTo[right, objBaseline, TRUE, aptr, pos, orient, context]; MoveTo[mid - 2, objBaseline + 0, FALSE, aptr, pos, orient, context]; MoveTo[mid - 2, objBaseline + 4, TRUE, aptr, pos, orient, context]; MoveTo[mid - 4, objBaseline + 4, TRUE, aptr, pos, orient, context]; MoveTo[mid - 0, objBaseline + 8, TRUE, aptr, pos, orient, context]; MoveTo[mid + 4, objBaseline + 4, TRUE, aptr, pos, orient, context]; MoveTo[mid + 2, objBaseline + 4, TRUE, aptr, pos, orient, context]; MoveTo[mid + 2, objBaseline + 0, TRUE, aptr, pos, orient, context]; IF NARROW[aptr.ob.specificRef, StretchObj].type = pointed THEN { MoveTo[left + 2, objBaseline + 2, FALSE, aptr, pos, orient, context]; MoveTo[left + 0, objBaseline + 0, TRUE, aptr, pos, orient, context]; MoveTo[left + 2, objBaseline - 2, TRUE, aptr, pos, orient, context]; MoveTo[right - 2, objBaseline + 2, FALSE, aptr, pos, orient, context]; MoveTo[right - 0, objBaseline + 0, TRUE, aptr, pos, orient, context]; MoveTo[right - 2, objBaseline - 2, TRUE, aptr, pos, orient, context]; } ELSE { MoveTo[left + 1, objBaseline + 2, FALSE, aptr, pos, orient, context]; MoveTo[left + 0, objBaseline + 2, TRUE, aptr, pos, orient, context]; MoveTo[left + 0, objBaseline - 2, TRUE, aptr, pos, orient, context]; MoveTo[left + 1, objBaseline - 2, TRUE, aptr, pos, orient, context]; MoveTo[right - 1, objBaseline + 2, FALSE, aptr, pos, orient, context]; MoveTo[right - 0, objBaseline + 2, TRUE, aptr, pos, orient, context]; MoveTo[right - 0, objBaseline - 2, TRUE, aptr, pos, orient, context]; MoveTo[right - 1, objBaseline - 2, TRUE, aptr, pos, orient, context]; }; END; CD.DrawToContext[pr, Color, markObj.level]; CD.DrawToContext[pr, Outline, aptr.ob.level]; END; AddStretchLine: PROC [comm: CDSequencer.Command] = BEGIN line: LineData; IF ~OKCommand[comm] THEN RETURN[]; line.label _ TerminalIO.RequestRope["Enter label for new stretch line: "]; IF TerminalIO.UserSaysYes["Pointed?", "Make this a pointed stretch line?", TRUE] THEN line.type _ pointed ELSE line.type _ blunt; line.point _ comm.pos; line.length _ defaultObjWidth; Place[comm.design, line, FALSE]; END; AddCellLine: PROC [comm: CDSequencer.Command] = BEGIN line: LineData; IF ~OKCommand[comm] THEN RETURN[]; line.label _ TerminalIO.RequestRope["Enter label for new cell stretch line: "]; line.type _ pointed; line.point _ comm.pos; line.length _ defaultObjWidth; Place[comm.design, line, FALSE]; END; AddLayerLine: PROC [comm: CDSequencer.Command] = BEGIN line: LineData; layer: Rope.ROPE _ Atom.GetPName[CD.LevelKey[CDPanel.FetchDefaultLevel[comm.design]]]; line.type _ blunt; IF ~OKCommand[comm] THEN RETURN[]; line.label _ TerminalIO.RequestRope[Rope.Cat["Enter label for new '", layer, "' stretch line: "]]; line.type _ blunt; line.point _ comm.pos; line.length _ defaultObjWidth; Place[comm.design, line, FALSE]; END; WriteStretchLine: CD.InternalWriteProc -- PROC [me: ObPtr] -- = BEGIN markObj: StretchObj = NARROW[me.specificRef]; TokenIO.WriteRope[markObj.label]; IF markObj.type = pointed THEN TokenIO.WriteRope["P"] ELSE TokenIO.WriteRope["B"]; TokenIO.WriteInt[me.size.x]; TokenIO.WriteInt[markObj.level]; END; ReadStretchLine: CD.InternalReadProc -- PROC [] RETURNS [ObPtr] -- = BEGIN obj: CD.ObPtr _ NEW[CD.ObjectDefinition]; markObj: StretchObj _ NEW[StretchObjRec]; obj.p _ objsProcs; obj.specificRef _ markObj; markObj.label _ TokenIO.ReadRope[]; IF Rope.Equal[TokenIO.ReadRope[], "P"] THEN markObj.type _ pointed ELSE markObj.type _ blunt; obj.size.x _ TokenIO.ReadInt[]; markObj.level _ TokenIO.ReadInt[]; obj.level _ myLevel; obj.size.y _ objHeight; RETURN[obj]; END; DescribeStretchLine: CD.DescribeProc -- PROC [me: ObPtr] RETURNS [Rope.ROPE] -- = BEGIN markObj: StretchObj = NARROW[me.specificRef]; IF markObj.type = pointed THEN RETURN[Rope.Cat["Cell stretch line labeled '", markObj.label, "'"]] ELSE RETURN[Rope.Cat["Layer '", Atom.GetPName[CD.LevelKey[markObj.level]], "' stretch line labeled '", markObj.label, "'"]]; END; SetSize: CDCallSpecific.CallProc = BEGIN newLength: CD.DesignNumber _ NARROW[x, REF CD.DesignNumber]^; aptr.ob.size.x _ MAX[minObjWidth, newLength]; repaintMe _ TRUE; END; AdjustSize: CDCallSpecific.CallProc = BEGIN amount: INT; IF x=NIL THEN amount _ CD.lambda ELSE IF ISTYPE [x, REF CD.DesignPosition] THEN { p: CD.DesignPosition _ NARROW[x, REF CD.DesignPosition]^; IF p.x = 0 THEN amount _ p.y ELSE amount _ p.x; } ELSE { done_FALSE; RETURN; }; aptr.ob.size.x _ MAX[minObjWidth, MAX[CD.lambda, aptr.ob.size.x + amount]]; repaintMe _ TRUE; END; Init: PROC[] = BEGIN error: BOOL _ FALSE; tmp: REF CD.ObjectProcs; error _ FALSE; tmp _ CD.RegisterObjectType[objAtom ! CD.Error => {error _ TRUE; CONTINUE}]; IF tmp = NIL THEN error _ TRUE; IF ~error THEN { myLevel _ CD.NewLevel[NIL, $StretchLineLevel]; objsProcs _ tmp; } ELSE { error _ FALSE; objsProcs _ CD.FetchObjectProcs[objAtom! CD.Error => {error _ TRUE; CONTINUE}]; myLevel _ CD.FetchLevel[NIL, $StretchLineLevel ! CD.Error => {error _ TRUE; CONTINUE}]; IF error THEN objsProcs _ NIL; }; IF objsProcs = NIL THEN { TerminalIO.WriteRope["Error: Can't register stretch-line object procs.\n"]; RETURN; }; objsProcs.drawMe _ DrawStretchMark; objsProcs.internalWrite _ WriteStretchLine; objsProcs.internalRead _ ReadStretchLine; objsProcs.describe _ DescribeStretchLine; objsProcs.hasChildren _ FALSE; objsProcs.wireTyped _ FALSE; CDCallSpecific.Register[$Lengthen, objsProcs, AdjustSize]; CDCallSpecific.Register[$Widen, objsProcs, AdjustSize]; CDCallSpecific.Register[$SetLength, objsProcs, SetSize]; CDCallSpecific.Register[$SetWidth, objsProcs, SetSize]; CDSequencer.ImplementCommand[$AddStretchLine, AddStretchLine]; CDSequencer.ImplementCommand[$AddCellLine, AddCellLine]; CDSequencer.ImplementCommand[$AddLayerLine, AddLayerLine]; TilerMenu.Register["Add Cell Stretch Line", $AddCellLine]; TilerMenu.Register["Add Layer Stretch Line", $AddLayerLine]; END; Init[]; END. ฎFile: StretchLinesImpl.mesa Copyright c 1984 by Xerox Corporation. All rights reserved. Created by: Mayo, June 8, 1984 12:40:57 pm PDT Last Edited by: Mayo, July 27, 1984 11:10:26 pm PDT -- Utilities -- Given a ChipNDale application that points to a stretch mark, return its label. -- find the origin of a stretch line relative to the containing cell's origin -- check a command for wierdness as it is possible to screw up the TIP table. -- routines for interactive editing of stretch line -- Place mark. Given point is the left (or lower) endpoint of the mark.r -- PROC [aptr: ApplicationPtr, pos: DesignPosition, orient: Orientation, pr: REF DrawInformation]; -- move to a specified point, with or without drawing a line -- fill in the arrow, a hack since we can't do color except in rectangles rect _ CDInline.MoveRect[CDOrient.MapRect[ itemInCell: [x1: mid - 1, y1: objBaseline + 4, x2: mid + 1, y2: objBaseline + 7], cellSize: aptr.ob.size, cellInstOrient: orient], pos]; pr.drawRect[rect, aptr.ob.level, pr]; rect _ CDInline.MoveRect[CDOrient.MapRect[ itemInCell: [x1: mid - 2, y1: objBaseline, x2: mid + 2, y2: objBaseline + 6], cellSize: aptr.ob.size, cellInstOrient: orient], pos]; pr.drawRect[rect, aptr.ob.level, pr]; rect _ CDInline.MoveRect[CDOrient.MapRect[ itemInCell: [x1: mid - 3, y1: objBaseline + 4, x2: mid + 3, y2: objBaseline + 5], cellSize: aptr.ob.size, cellInstOrient: orient], pos]; pr.drawRect[rect, aptr.ob.level, pr]; -- draw the stretch line { -- use our `Fetch' procedure so we know that it works the same as drawing line: LineData _ Fetch[aptr]; pos1, pos2: CD.Position; pos1 _ pos2 _ line.point; IF line.direction = up OR line.direction = down THEN pos2.x _ pos1.x + line.length ELSE pos2.y _ pos1.y + line.length; Graphics.SetCP[context, pos1.x, pos1.y]; Graphics.DrawTo[context, pos2.x, pos2.y]; }; -- draw direction arrow -- draw arrowheads -- draw square ends -- Top-level command routines -- Main body ส˜– "Cedar" stylešœ™Jšœ ฯmœ1™J˜š  œžœAžœžœž˜sšžœ˜Jšœ1˜1Jšœ-˜-—Jšžœ˜J™—J˜JšœG˜GJšžœ˜Jšžœ˜J˜—Jšœžœ˜Jšœžœ˜ J˜0Jšžœ žœžœžœ˜Jšœžœ˜%J™IJšœ-˜-Jšœžœ˜"Jšœ-˜-Jšœ˜Jšœ-˜-Jšœ˜Jšœ-˜-Jšœ˜Jšœ-˜-Jšœ˜Jšœ-˜-Jšœ˜Jšœ-˜-Jšœ˜Jšœ-˜-šœ*™*JšœQ™QJšœ6™6—Jšœ%™%šœ*™*JšœM™MJšœ6™6—Jšœ%™%šœ*™*JšœQ™QJšœ6™6—Jšœ%™%Jšžœ˜—J˜š œžœž˜1Jšœžœ˜Jšœžœ˜Jšœžœ˜Jšžœ žœžœžœ˜Jšœžœ˜%J™Jšœžœ˜=Jšœžœ˜=šœŸI™LJ™Jšœ žœ ™J™šžœžœž™4J™—šž™J™—Jšœ(™(Jšœ)™)J™—J™Jšœ!žœ˜DJšœ!žœ˜CJšœ!žœ˜CJšœ!žœ˜CJšœ!žœ˜CJšœ!žœ˜CJšœ!žœ˜Cšžœžœ1ž˜@J™Jšœ"žœ˜EJšœ"žœ˜DJšœ"žœ˜DJšœ#žœ˜FJšœ#žœ˜EJšœ#žœ˜EJ˜—šž˜J™Jšœ"žœ˜EJšœ"žœ˜DJšœ"žœ˜DJšœ"žœ˜DJšœ#žœ˜FJšœ#žœ˜EJšœ#žœ˜EJšœ#žœ˜EJ˜—Jšžœ˜—J˜Jšžœ)˜+Jšžœ+˜-Jšžœ˜J˜—š œžœž˜8J˜Jšžœžœžœ˜"JšœJ˜JšžœIžœž˜UJ˜—šž˜J˜—J˜Jšœ˜Jšœžœ˜ Jšžœ˜—J˜š  œžœž˜5J˜Jšžœžœžœ˜"JšœO˜OJ˜J˜Jšœ˜Jšœžœ˜ Jšžœ˜—J˜š  œžœž˜6J˜Jšœ žœžœ3˜VJ˜Jšžœžœžœ˜"Jšœb˜bJ˜J˜Jšœ˜Jšœžœ˜ Jšžœ˜—J˜šกœžœŸœž˜EJšœžœ˜-Jšœ!˜!šžœž˜Jšœ˜—šž˜Jšœ˜—J˜Jšœ ˜ Jšžœ˜J˜—šกœžœŸœž˜JJšœžœ žœžœ˜)Jšœžœ˜)Jšœ˜J˜Jšœ#˜#šžœ%ž˜+Jšœ˜—šž˜Jšœ˜—Jšœ˜Jšœ"˜"J˜Jšœ˜Jšžœ˜ Jšžœ˜J˜—š กœžœŸะckŸ ขŸขŸœž˜WJšœžœ˜-šžœžœ˜Jšžœ=˜C—šžœ˜Jšžœ#žœM˜x—Jšžœ˜—J˜š œž˜(Jš œ žœžœžœžœ˜=Jšœžœ˜-Jšœ žœ˜Jšžœ˜J˜—šก œž˜+Jšœžœ˜ šžœžœžœ˜Jšœ žœ˜—š žœžœžœžœžœžœ˜0Jš œžœžœžœžœ˜9šžœ ž˜J˜ —šž˜J˜ —J˜—šžœ˜Jšœžœ˜ Jšžœ˜Jšœ˜—Jšœžœžœžœ#˜KJšœ žœ˜Jšžœ˜J˜J˜——J™J™™J˜š œžœž˜Jšœžœžœ˜Jšœžœžœ ˜Jšœžœ˜Jš œžœžœžœžœ˜LJšžœžœžœ žœ˜šžœžœ˜Jšœ žœ žœ˜.Jšœ˜Jšœ˜—šžœ˜Jšœžœ˜Jš œ žœžœžœžœ˜OJš œ žœ žœžœžœžœ˜WJšžœžœ žœ˜J˜—šžœ žœžœ˜J˜LJšžœ˜J˜—Jšœ#˜#Jšœ+˜+Jšœ)˜)Jšœ)˜)Jšœžœ˜Jšœžœ˜Jšœ:˜:Jšœ7˜7Jšœ8˜8Jšœ7˜7Jšœ>˜>Jšœ8˜8Jšœ:˜:Jšœ:˜:Jšœ<˜