File: AlignmentMarksImpl.mesa   
Copyright © 1984 by Xerox Corporation. All rights reserved.
Created by: Bob Mayo, June 8, 1984 12:28:34 pm PDT
Last Edited by: Mayo, November 5, 1984 6:46:29 pm PST
Last Edited by: Jacobi, December 19, 1984 8:56:02 pm PST
DIRECTORY
AlignmentMarks,
CDMenus USING [CreateEntry],
TerminalIO USING [WriteRope, RequestRope],
CDSequencer USING [Command, ImplementCommand],
CD,
TokenIO USING [ReadRope, WriteRope, ReadInt, WriteInt],
CDBasics USING [AddPoints, SubPoints],
CDOps USING [IncludeApplication],
CDOrient USING [MapPoint],
CDApplications USING [NewApplicationI],
Rope USING [ROPE, Concat, Equal],
Graphics USING [Context, MoveTo, LineTo, DrawArea, NewPath, Path],
Real USING [Fix];
AlignmentMarksImpl: CEDAR PROGRAM    
IMPORTS CDMenus, CD, TerminalIO, CDOps, CDBasics, Rope, CDSequencer, TokenIO, CDOrient, CDApplications, Graphics, Real EXPORTS AlignmentMarks =  
BEGIN OPEN AlignmentMarks;
MarkObj: TYPE = REF MarkObjRec;  -- an object that can be put in a cell or design
MarkObjRec: TYPE = RECORD [
name: Rope.ROPE
];
versionNumber: INT ~ 1;  -- version of file format for alignment marks
objAtom: PUBLIC ATOM ← $AlignmentMark;
myLevel: CD.Level;
objsProcs: REF CD.ObjectProcs;
arrowSize: INT = 2 * CD.lambda;
-- Utilities
AptrToMark: PUBLIC PROC [aptr: CD.ApplicationPtr] RETURNS [REF Mark] = BEGIN
mark: REF Mark ← NEW[Mark];
IF aptr.ob.p.objectType # objAtom THEN RETURN[NIL];
mark.name ← NARROW[aptr.ob.specificRef, MarkObj].name;
mark.pos ← CDBasics.AddPoints[
CDOrient.MapPoint[
pointInCell: [x: 0, y: 0],
cellSize: aptr.ob.size, cellInstOrient: aptr.orientation],
aptr.location];
RETURN[mark];
END;
-- Make an application for a mark, but don't place it
MakeMarkAptr: PUBLIC PROC [mark: Mark, orient: CD.Orientation ← CD.original] RETURNS [CD.ApplicationPtr]= BEGIN
aptr: CD.ApplicationPtr;
pos: CD.Position ← mark.pos;
obj: CD.ObPtr ← NEW[CD.ObjectDefinition];
markObj: MarkObj ← NEW[MarkObjRec];
markObj.name ← mark.name;
obj.p ← objsProcs;
obj.size ← [arrowSize, arrowSize];
obj.specificRef ← markObj;
obj.level ← myLevel;
aptrCDApplications.NewApplicationI[obj, pos, orient];
-- adjust location of mark for the orientation
aptr.location ← CDBasics.SubPoints[aptr.location, CDBasics.SubPoints[AptrToMark[aptr].pos, aptr.location]];
RETURN[aptr];
END;
FindList: PUBLIC PROC [ob: CD.ObPtr] RETURNS [LIST OF Mark] = BEGIN
list: CD.ApplicationList;
marks: LIST OF Mark ← NIL;
SELECT ob.p.objectType FROM
$Cell => list ← NARROW[ob.specificRef, CD.CellPtr].contents;
ENDCASE => RETURN[NIL];
FOR a: CD.ApplicationList ← list, a.rest WHILE a # NIL DO
IF a.first.ob.p.objectType = objAtom THEN {
marks ← CONS[AptrToMark[a.first]^, marks];
};
ENDLOOP;
RETURN[marks];
END;
Find: PUBLIC PROC [ob: CD.ObPtr, name: Rope.ROPE] RETURNS [REF Mark] = BEGIN
FOR a: LIST OF Mark ← FindList[ob], a.rest WHILE a # NIL DO
IF Rope.Equal[a.first.name, name] THEN {
RETURN[NEW[Mark ← a.first]];
};
ENDLOOP;
RETURN[NIL];
END;
-- routines for interactive editing of marks
-- Place a mark into a design.
Place: PUBLIC PROC [into: CD.Design, mark: Mark, orient: CD.Orientation ← CD.original] = BEGIN
CDOps.IncludeApplication[into, MakeMarkAptr[mark, orient]];
END;
DrawAlignMark: CD.DrawProc = BEGIN
-- PROC [aptr: ApplicationPtr, pos: DesignPosition, orient: Orientation, pr: REF DrawInformation];
DrawArrow: PROC [context: Graphics.Context] =
BEGIN
-- apply an orientation to a point
MapPoint: PROC [p: CD.Position, cellSize: CD.Position, orient: CD.Orientation] RETURNS [CD.Position] = INLINE BEGIN
RETURN[CDOrient.MapPoint[
pointInCell: p,
cellSize: cellSize,
cellInstOrient: orient]];
END;
MapReal: PROC[x, y: REAL] RETURNS [xi, yi: INT] = INLINE BEGIN
orig: CD.Position;
orig.x ← Real.Fix[x]; orig.y ← Real.Fix[y];
orig ← CDBasics.AddPoints[MapPoint[orig, aptr.ob.size, orient], pos];
RETURN[orig.x, orig.y];
END;
RealPoint: TYPE = RECORD [x: REAL, y: REAL];
RealPointArray8: TYPE = ARRAY NAT[0..8) OF RealPoint;
x, y: INT;
sx1, sx2, sy1, sy2: INT;
arrow: RealPointArray8 ← [ [0,0], [0,0.75], [0.25,0.5], [0.75,1], [1,0.75], [0.5,0.25], [0.75,0], [0,0] ];
path: Graphics.Path ← Graphics.NewPath[size: 8];
IF context = NIL THEN RETURN;
-- draw the arrow
[sx1, sy1] ← MapReal[0.0, 0.0];
[sx2, sy2] ← MapReal[arrowSize, arrowSize];
[x, y] ← MapReal[arrow[0].x * arrowSize, arrow[0].y * arrowSize];
Graphics.MoveTo[path, x, y, TRUE];
FOR i: INT IN [1..8) DO
[x, y] ← MapReal[arrow[i].x * arrowSize, arrow[i].y * arrowSize];
Graphics.LineTo[path, x , y];
ENDLOOP;
Graphics.DrawArea[self: context, path: path];
END;
-- draw the arrow & name
CD.DrawToContext[pr, DrawArrow, aptr.ob.level];
CD.DrawToContext[pr, DrawName, aptr.ob.level];
END;
AddAlignMark: PROC [comm: CDSequencer.Command] = BEGIN
mark: Mark;
mark.name ← TerminalIO.RequestRope["Enter name of new alignment mark: "];
mark.pos ← comm.pos;
Place[comm.design, mark];
END;
WriteMark: CD.InternalWriteProc -- PROC [me: ObPtr] -- = BEGIN
markObj: MarkObj = NARROW[me.specificRef];
TokenIO.WriteInt[versionNumber];
TokenIO.WriteRope[markObj.name];
END;
ReadMark: CD.InternalReadProc -- PROC [] RETURNS [ObPtr] -- = BEGIN
obj: CD.ObPtr ← NEW[CD.ObjectDefinition];
markObj: MarkObj ← NEW[MarkObjRec];
version: INT;
obj.p ← objsProcs;
obj.size ← [arrowSize, arrowSize];
obj.specificRef ← markObj;
obj.level ← myLevel;
version ← TokenIO.ReadInt[];
SELECT version FROM
1 => markObj.name ← TokenIO.ReadRope[];
ENDCASE => TerminalIO.WriteRope["File contained an unknown version of Alignment Marks\n"];
RETURN[obj];
END;
DescribeMark: CD.DescribeProc -- PROC [me: ObPtr] RETURNS [Rope.ROPE] -- = BEGIN
markObj: MarkObj = NARROW[me.specificRef];
RETURN[Rope.Concat["alignment mark ", markObj.name]];
END;
-- Top-level command routines
Init: PROC[] = BEGIN
error: BOOLFALSE;
tmp: REF CD.ObjectProcs ← NIL;
tmp ← CD.RegisterObjectType[objAtom ! CD.Error => error ← TRUE];
IF tmp = NIL THEN error ← TRUE;
IF ~error THEN {
myLevel ← CD.NewLevel[NIL, $AlignMarkLevel];
objsProcs ← tmp;
}
ELSE {
error ← FALSE;
objsProcs ← CD.FetchObjectProcs[objAtom! CD.Error => {error ← TRUE; CONTINUE}];
myLevel ← CD.FetchLevel[NIL, $AlignMarkLevel ! CD.Error => {error ← TRUE; CONTINUE}];
IF error THEN objsProcs ← NIL;
};
IF objsProcs = NIL THEN {
TerminalIO.WriteRope["Error: Can't register alignment-mark object procs.\n"];
RETURN;
};
objsProcs.drawMe ← DrawAlignMark;
objsProcs.internalWrite ← WriteMark;
objsProcs.internalRead ← ReadMark;
objsProcs.describe ← DescribeMark;
objsProcs.inDirectory ← FALSE;
objsProcs.wireTyped ← FALSE;
CDSequencer.ImplementCommand[$AddAlignMark, AddAlignMark];
CDMenus.CreateEntry[menu: $ModuleMenu, entry: "Add Alignment Mark", key: $AddAlignMark];
END;
-- Main body
Init[];
END.