<> <> <<>> <<>> 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 REF _ NIL] = { 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 REF _ NIL; 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.