File: IPTopStackOpsImpl.mesa
Last Edited by: CSChow, January 27, 1985 6:25:01 am PST
DIRECTORY
CDOrient,
RefStack,
IPCoTab,
IPCTG,
IPTop,
IPTopOpRecs,
IPEditPrimitives,
IPTopOpsPrivate,
IPTopOps;
IPTopStackOpsImpl: CEDAR PROGRAM
IMPORTS RefStack, IPCoTab, IPTop, IPEditPrimitives, IPTopOpsPrivate, IPTopOps
EXPORTS IPTopOps = BEGIN OPEN TOR: IPTopOpRecs, EP: IPEditPrimitives, CoTab: IPCoTab, CTG: IPCTG, Top: IPTop, IPTopOps;
UndoStackEmpty: PUBLIC ERROR = CODE;
StackSize: PUBLIC PROC[top: Top.Ref] RETURNS [NAT] = {RETURN [top.undoStack.Size]}; --StackSize--
ResetStacks: PUBLIC PROC[top: Top.Ref] = {top.undoStack.Reset; top.redoStack.Reset}; --ResetStacks--
GetTrack: PUBLIC PROC[top: Top.Ref, after: NAT] RETURNS [LIST OF REF] ={RETURN [RefStack.Copy[top.redoStack, after]]}; --GetTrack--
Undo: PUBLIC PROC[top: Top.Ref, n: NAT] RETURNS [prevTrack: LIST OF REFNIL] = {
THROUGH [0..n) DO
prevTrack ← CONS[Undo1[top], prevTrack];
ENDLOOP;
}; --Undo--
Undo1: PUBLIC PROC[top: Top.Ref] RETURNS [REF]={
opRec: REF ← RefStack.Pop1[top.undoStack ! RefStack.RStackUnderflow => GOTO reSignal];
UndoDiscrmOpRec[top, opRec];
RETURN [RefStack.Pop1[top.redoStack]];
EXITS
reSignal => ERROR UndoStackEmpty}; --Undo1--
Redo: PUBLIC PROC[top: Top.Ref, track: LIST OF REF] ={
WHILE track # NIL DO
Redo1[top, track.first];
track ← track.rest;
ENDLOOP;}; --Redo--
Redo1: PUBLIC PROC[top: Top.Ref, step: REF] ={
[] ← RedoDiscrmOpRec[top, step, TRUE]
}; --Redo1--
--##Private Procedures##--
UndoDiscrmOpRec: PROC [top: Top.Ref, opRec: REF] = {
IF opRec = NIL THEN RETURN;
WITH opRec SELECT FROM
bc: TOR.IRBreakCross => {top.ReActivateChannel[bc.newCh1];
EP.BreakCross[bc.refCh, bc.chToBreak, bc.newCh1]};
fc: TOR.IRFormCross => {EP.FormCross[fc.refCh, fc.negCh, fc.posCh];
top.DestroyChannel[fc.posCh]; };
ic: TOR.IRInsertCo1 => {top.ReActivateChannel[ic.newCh1];
CoTab.ReActivateComponent[ic.co];
[] ← EP.InsertCo1[ic.co, ic.chToSplit, ic.negBnd, ic.posBnd, ic.sideToOpHint, ic.newCh1]};
rc: TOR.IRRemoveCo1 => {
top.DestroyChannel[EP.RemoveCo1[rc.co, rc.shrinkDirectn, rc.sideToClHint].sideCh];
CoTab.DeActivateComponent[rc.co];};
ic: TOR.IRInsertCo2 => {top.ReActivateChannel[ic.newCh1];
CoTab.ReActivateComponent[ic.co];
[] ← EP.InsertCo2[ic.co, ic.chToSplit, ic.negBnd, ic.posBnd, ic.sideToOpHint, ic.newCh1]};
rc: TOR.IRRemoveCo2 => {
top.DestroyChannel[EP.RemoveCo2[rc.co, rc.shrinkDirectn, rc.sideToClHint].sideCh];
CoTab.DeActivateComponent[rc.co];};
fz: TOR.IRFormZ => {top.ReActivateChannel[fz.newCh1]; top.ReActivateChannel[fz.newCh2];
EP.FormZ[fz.refCh, fz.negComp, fz.posComp, fz.zType, fz.newCh1, fz.newCh2]};
rz: TOR.IRRemoveZ =>{
top.DestroyChannel[EP.RemoveZ[rz.zSpine].posCh];
top.DestroyChannel[rz.zSpine];};
lt: TOR.IRLtoT => {top.DestroyChannel[EP.LtoT[lt.refCh, lt.whichEnd].posCh]};
tl: TOR.IRTtoL => {top.ReActivateChannel[tl.newCh1];
EP.TtoL[tl.refCh, tl.whichEnd, tl.lType, tl.endCo, tl.newCh1]};
fk: TOR.IRFlexKnee =>{top.ReActivateChannel[fk.newCh1];
EP.FlexKnee[fk.leg, fk.floor, fk.whichEnd, fk.whichDirection, fk.newCh1]};
ek: TOR.IRExtendKnee =>{[] ← EP.ExtendKnee[ek.shin];
top.DestroyChannel[ek.shin]};
scc: REF TOR.IRSetCoCornerSpRec => [] ← IPTopOpsPrivate.SetCoCornerSp[scc.co, scc.corner, scc.cornerSpace];
or: TOR.ROrient => [] ← Orient[top, or.co, or.operation];
sc: TOR.RSetComponent => [] ← SetComponent[top, sc.co, sc.active, sc.atPosition];
tc: TOR.RMoveComponent => [] ← MoveComponent[top, tc.co, tc.by];
sc: TOR.RSwapComponents => [] ← SwapComponents[top, sc.comp1, sc.comp2];
scs: TOR.RSetCompShape => [] ← SetCompShape[top, scs.comp, scs.shape, scs.chkArgs, FALSE];
icac: TOR.IRInsertCoAtCorner => {top.ReActivateChannel[icac.newHCh1];
top.ReActivateChannel[icac.newVCh1];
CoTab.ReActivateComponent[icac.co];
EP.InsertCoAtCorner[icac.host, icac.co, icac.corner, icac.newHCh1, icac.newVCh1]};
rcac: TOR.IRRemoveCoAtCorner =>{co: CoTab.Component;
hCh, vCh: CTG.Channel;
[co, hCh, vCh] ← EP.RemoveCoAtCorner[rcac.host, rcac.corner];
top.DestroyChannel[hCh];
top.DestroyChannel[vCh];
CoTab.DeActivateComponent[co];};
cc2: TOR.IRCreateComp2 => []← IPCoTab.CreateComponent2[top.coTab, NIL, cc2.comp.shape, cc2.comp.active, cc2.orient, cc2.origin, cc2.comp];
dc2: TOR.IRDestroyComp2 =>[]←IPCoTab.DestroyComponent2[top.coTab, dc2.comp];
com: TOR.RComposite =>
WHILE com # NIL DO UndoDiscrmOpRec[top, com.first]; com ← com.rest ENDLOOP;
ENDCASE => ERROR;
}; --UndoDiscrmOpRec--
RedoDiscrmOpRec: PROC [top: Top.Ref, opRec: REF, keepTrack: BOOL] RETURNS [ir: TOR.RAny] = {
IF opRec = NIL THEN {
IF keepTrack THEN PushStacks[top, NIL, NIL];
RETURN [NIL]};
WITH opRec SELECT FROM
bc: TOR.FRBreakCross => RETURN [BreakCross[top, bc.refCh, bc.chToBreak, keepTrack].ir];
fc: TOR.FRFormCross => RETURN [FormCross[top, fc.ch1, fc.ch2, keepTrack].ir];
fz: TOR.FRFormZ => RETURN [FormZ[top, fz.comp1, fz.comp2, fz.zType, keepTrack].ir];
rz: TOR.FRRemoveZ => RETURN [RemoveZ[top, rz.zSpine, keepTrack].ir];
lt: TOR.FRLtoT => RETURN [LtoT[top, lt.ch, lt.whichEnd, keepTrack].ir];
tl: TOR.FRTtoL => RETURN [TtoL[top, tl.co, tl.ch, tl.lType, keepTrack].ir];
fk: TOR.FRFlexKnee => RETURN [FlexKnee [top, fk.leg, fk.floor, fk.whichEnd, keepTrack].ir];
ek: TOR.FRExtendKnee => RETURN [ExtendKnee [top, ek.shin, keepTrack].ir];
ft: TOR.FRFlipT => RETURN[FlipT[top, ft.chToBend, ft.attachTo, ft.whichEnd, keepTrack].ir];
g1: TOR.FRGrow1 => RETURN [Grow1 [top, g1.co, g1.host, g1.hostCorner, keepTrack].ir];
s1: TOR.FRShrink1 => RETURN [IPTopOpsPrivate.Shrink1 [top, s1.co, keepTrack].ir];
ic: TOR.FRInsertCo => RETURN [IPTopOpsPrivate.InsertCo [top, ic.co, ic.chToSplit, ic.negBnd, ic.posBnd, ic.sideHint, ic.whichFirstHint, keepTrack].ir];
rc: TOR.FRRemoveCo => RETURN [IPTopOpsPrivate.RemoveCo [top, rc.co, rc.shrinkDirectn, keepTrack].ir];
or: TOR.ROrient => RETURN [Orient[top, or.co, or.operation, keepTrack].ir];
sc: TOR.RSetComponent => RETURN [SetComponent[top, sc.co, sc.active, sc.atPosition, keepTrack].ir];
tc: TOR.RMoveComponent => RETURN [MoveComponent[top, tc.co, tc.by, keepTrack].ir];
sc: TOR.RSwapComponents => RETURN [SwapComponents[top, sc.comp1, sc.comp2, keepTrack].ir];
sc: TOR.FRSpawnComps => RETURN [SpawnComps[top, sc.comp, NIL, NIL, [], [], sc.splitDirection, sc.chkArgs, keepTrack, sc.negChild, sc.posChild].ir];
scs: TOR.RSetCompShape => RETURN [SetCompShape[top, scs.comp, scs.shape, scs.chkArgs, keepTrack].ir];
com: TOR.RComposite => {l: LIST OF REFNIL;
FOR comRev: TOR.RComposite ← LReverse[com], comRev.rest UNTIL comRev = NIL DO
l ← CONS[RedoDiscrmOpRec[top, comRev.first, FALSE], l];
ENDLOOP;
IF keepTrack THEN PushStacks[top, com, l];
RETURN [l]};
ENDCASE => ERROR;
}; --RedoDiscrmOpRec--
LReverse: PROC [list: LIST OF REF] RETURNS[val: LIST OF REF] = INLINE{
val ← NIL;
UNTIL list = NIL DO
val ← CONS[list.first, val];
list ← list.rest;
ENDLOOP;
RETURN[val];
}; -- LReverse--
END.