CDOpsImpl.mesa (part of Chipndale)
by Christian Jacobi July 12, 1983 10:56 am
last edited by Christian Jacobi February 16, 1984 1:57 pm
DIRECTORY
Atom,
CD,
CDApplications,
CDCommands,
CDCells,
CDDraw,
CDEvents,
CDInline,
CDOps,
CDOrient,
CDValue,
Rope USING [ROPE],
SymTab;
CDOpsImpl: CEDAR MONITOR
IMPORTS Atom, CDApplications, CDCells, CDCommands, CDDraw, CDEvents, CDInline, CDOps, CDOrient, CDValue, SymTab
EXPORTS CD, CDOps =
BEGIN
createEvent: CDEvents.EventRegistration=CDEvents.RegisterEventType[$CreateNewDesign];
resetDesignEvent: CDEvents.EventRegistration=CDEvents.RegisterEventType[$ResetDesign];
SequencerDesignPrivate: PUBLIC TYPE = RECORD [
delayedList: LIST OF REF Remember←NIL
];
Remember: TYPE = RECORD [area: CD.DesignRect, clear: BOOL];
InternalResetDesign: PROC[design: CD.Design] =
--is local since it does not cause a redraw
BEGIN
dummy: CD.ObPtr ← CDCells.CreateEmptyCell[];
design.cellDirectory ← SymTab.Create[];
design.seqPrivate ← NEW[SequencerDesignPrivate ← [delayedList: NIL]];
design^.actual ← LIST[CD.PushRec[
dummyCell: CDApplications.NewApplication[ob: dummy],
mightReplace: NIL,
specific: NARROW[dummy.specificRef]
]];
END;
CreateDesign: PUBLIC PROC [technology: CD.Technology] RETURNS [design: CD.Design] =
BEGIN
design ← NEW[CD.DesignRec];
design.technology ← technology;
InternalResetDesign[design]; -- must not cause redraw since event not yet processed
[] ← CDEvents.ProcessEvent[createEvent, design];
END;
ResetDesign: PUBLIC PROC [design: CD.Design] =
BEGIN
InternalResetDesign[design];
[] ← CDEvents.ProcessEvent[resetDesignEvent, design];
Redraw[design]
END;
RemoveApplication: PUBLIC PROC [design: CD.Design, aptr: CD.ApplicationPtr, draw: BOOLTRUE] =
BEGIN
al: CD.ApplicationList ← CDOps.AppList[design];
IF al#NIL THEN
IF al.first=aptr THEN CDOps.SetAppList[design, al.rest]
ELSE
FOR l: CD.ApplicationList ← al, l.rest WHILE l.rest#NIL DO
IF l.rest.first=aptr THEN {l.rest←l.rest.rest; EXIT}
ENDLOOP;
IF draw THEN DelayedRedraw[design, CDApplications.ApplicationRect[aptr]];
END;
SelectNewMode: PROC[design: CD.Design] RETURNS [BOOL] =
BEGIN
mode: INT = CDValue.FetchInt[boundTo: design, key: $CDxSelectNewMode, propagation: technology, ifNotFound: 0];
RETURN [mode=1]
END;
AddAnObject: PUBLIC PROC[design: CD.Design, ob: CD.ObPtr, location: CD.DesignPosition, orientation: CD.Orientation] =
BEGIN
aptr: CD.ApplicationPtr;
IF ob#NIL THEN {
aptr ← CDApplications.NewApplication[
ob: ob,
location: location,
orientation: orientation
];
IF SelectNewMode[design] THEN {
CDCommands.DeselectAll[design];
aptr.selected ← TRUE;
};
IncludeApplication[design, aptr];
}
END;
IncludeApplication: PUBLIC PROC [design: CD.Design, aptr: CD.ApplicationPtr, draw: BOOLTRUE] =
BEGIN
CDOps.SetAppList[design, CONS[aptr, CDOps.AppList[design]]];
IF draw THEN DelayedRedraw[design, CDApplications.ApplicationRect[aptr], TRUE];
END;
IncludeApplicationList: PUBLIC PROC [design: CD.Design, al: CD.ApplicationList, draw: BOOLTRUE] =
BEGIN
FOR list: CD.ApplicationList ← al, list.rest WHILE list#NIL DO
IncludeApplication[design, list.first, draw];
ENDLOOP;
END;
InternalAddAnObject: PROC[design: CD.Design, ob: CD.ObPtr, location: CD.DesignPosition, orientation: CD.Orientation, properties: CD.Properties←NIL] RETURNS [CD.ApplicationPtr] =
BEGIN
aptr: CD.ApplicationPtr = CDApplications.NewApplication[
ob: ob,
location: location,
orientation: orientation,
properties: properties
];
IncludeApplication[design, aptr, FALSE];
RETURN [aptr]
END;
Redraw: PUBLIC PROC [design: CD.Design, r: CD.DesignRect�Ops.all, eraseFirst: BOOLTRUE] =
BEGIN
CDDraw.InsertCommandAll[design,
CDDraw.Comm[cmd: rect, erase: eraseFirst, rect: r, ref: NIL]];
END;
DelayedRedraw: PUBLIC ENTRY PROC [design: CD.Design, r: CD.DesignRect, eraseFirst: BOOLTRUE] =
BEGIN
IF design#NIL THEN {
rem: REF Remember ← NEW[Remember←Remember[area: r, clear: eraseFirst]];
dl: REF SequencerDesignPrivate ← design.seqPrivate;
dl.delayedList ← CONS[rem, dl.delayedList]
}
END;
DoTheDelayedRedraws: PUBLIC ENTRY PROC [design: CD.Design] =
BEGIN
sq: REF SequencerDesignPrivate ← design.seqPrivate;
UNTIL sq.delayedList=NIL DO
CDDraw.InsertCommandAll[design, CDDraw.Comm[
cmd: rect,
erase: sq.delayedList.first.clear,
rect: sq.delayedList.first.area,
ref: NIL
]];
sq.delayedList ← sq.delayedList.rest
ENDLOOP;
END;
DrawDesign: PUBLIC PROC[design: CD.Design, pr: CD.DrawRef] =
BEGIN
SomeCommon: PROC[ob: CD.ObPtr, pos: CD.DesignPosition, orient: CD.Orientation,
pr: CD.DrawRef] RETURNS [BOOLEAN] =
INLINE BEGIN
RETURN CDInline.Intersect[CDOrient.RectAt[pos, ob.size, orient], pr.worldClip]
END;
DrawAndShowSelectionList: PROC [list: CD.ApplicationList, pr: CD.DrawRef] =
BEGIN
FOR w: CD.ApplicationList ← list, w.rest WHILE w#NIL DO
IF SomeCommon[w.first.ob, w.first.location, w.first.orientation, pr] THEN
BEGIN
IF pr.stopFlag^ THEN EXIT;
w.first.ob.p.drawMe[w.first, w.first.location, w.first.orientation, pr];
IF w.first.selected THEN
w.first.ob.p.showMeSelected[w.first, w.first.location, w.first.orientation, pr];
END;
ENDLOOP;
END;
-- drawDesign
DrawAndShowSelectionList[CDOps.AppList[design], pr];
IF pr.suppressOutsidePushedCell THEN RETURN;
FOR w: LIST OF CD.PushRec ← design^.actual.rest, w.rest WHILE w#NIL DO
IF pr.stopFlag^ THEN EXIT;
pr.pushLevel ← pr.pushLevel+1;
w.first.dummyCell.ob.p.drawMe[w.first.dummyCell, [0, 0], CDOrient.original, pr];
ENDLOOP;
END;
PointedApplication: PUBLIC PROC [design: CD.Design, pos: CD.DesignPosition]
RETURNS [CD.ApplicationPtr] =
BEGIN
RETURN [ CDApplications.AplicationAt[CDOps.AppList[design], pos] ];
END;
SelectedApplication: PUBLIC PROC [design: CD.Design]
RETURNS [first: CD.ApplicationPtr←NIL, multiple: BOOL�LSE] =
--first: returns ref to any selected application if there is one or more, otherwise nil.
--multiple: more than one application is selected
BEGIN
FOR w: CD.ApplicationList ← CDOps.AppList[design], w.rest WHILE w#NIL DO
IF w.first.selected THEN
IF first=NIL THEN first←w.first
ELSE {multiple←TRUE; RETURN}
ENDLOOP;
END;
Info: PUBLIC PROC[ob: CD.ObPtr] RETURNS [Rope.ROPE] =
BEGIN
IF ob.p.describe#NIL THEN RETURN [ob.p.describe[ob]]
ELSE RETURN [Atom.GetPName[ob.p.objectType]]
END;
ReOrderApplication: PUBLIC PROC [design: CD.Design, aptr: CD.ApplicationPtr] =
--on return: design has exactly one occurrence of aptr, and it is at the end.
--(includes aptr if necessary and removes double occurences)
BEGIN
al: CD.ApplicationList ← CDOps.AppList[design];
WHILE al#NIL AND al.first=aptr DO al ← al.rest ENDLOOP;
IF al=NIL THEN al←LIST[aptr]
ELSE
FOR l: CD.ApplicationList ← al, l.rest DO
-- l#NIL AND l.first#aptr holds at this point
WHILE l.rest#NIL AND l.rest.first=aptr DO l.rest ← l.rest.rest ENDLOOP;
IF l.rest=NIL THEN {l.rest ← LIST[aptr]; EXIT}
ENDLOOP;
CDOps.SetAppList[design, al];
END;
END.