<<>> <> <> <> DIRECTORY Buttons, CommanderOps, Convert, CtBasic, CtDispatch, CtMisc, CtViewer, Imager, ImagerSample, KeyNames, KeyTypes, Process, Rope, SF, ViewerClasses, ViewerOps, ViewerTools; CtCopyCommandImpl: CEDAR PROGRAM IMPORTS Buttons, CommanderOps, Convert, CtBasic, CtDispatch, CtMisc, CtViewer, KeyNames, Process, SF, ViewerOps, ViewerTools ~ BEGIN <> SampleMaps: TYPE ~ CtBasic.SampleMaps; Mouse: TYPE ~ CtViewer.Mouse; Box: TYPE ~ ImagerSample.Box; Vec: TYPE ~ ImagerSample.Vec; ROPE: TYPE ~ Rope.ROPE; Viewer: TYPE ~ ViewerClasses.Viewer; ViewerClassRec: TYPE ~ ViewerClasses.ViewerClassRec; <> Data: TYPE ~ REF DataRep; DataRep: TYPE ~ RECORD [ cmd: CtDispatch.CmdHandle, image: Viewer, box: Box, store: BOOL ¬ TRUE, source: SampleMaps ¬ NIL ]; usage: ROPE ~ "Ct Copy []: copy src to dest"; CtCopy: CtDispatch.CtProc ~ { ENABLE Convert.Error => GOTO ConvertError; args: CommanderOps.ArgumentVector ¬ CommanderOps.Parse[cmd]; SELECT args.argc FROM 1 => { v: Viewer ¬ ViewerOps.FindViewer["Ct Copy"]; d: Data ¬ IF v = NIL THEN NEW[DataRep] ELSE NARROW[v.data]; d.cmd ¬ cmd; IF v = NIL THEN -- fork, since we're being called from within a PaintProc. TRUSTED {Process.Detach[FORK MakeCopier[d]]}; affect ¬ [[0, 0], [0, 0]]; CtViewer.RegisterMouse[d.image ¬ viewer, MouseProc, d] }; 7 => { x0: INT ¬ Convert.IntFromRope[args[1]]; y0: INT ¬ Convert.IntFromRope[args[2]]; x1: INT ¬ Convert.IntFromRope[args[3]]; y1: INT ¬ Convert.IntFromRope[args[4]]; w: INT ¬ Convert.IntFromRope[args[5]]; h: INT ¬ Convert.IntFromRope[args[6]]; CtBasic.CopyClippedMaps[maps, maps, [[y0,x0], [y0+h,x0+w]], [[y1,x1], [y1+h,x1+w]]]; affect ¬ [[y1, x1], [y1+h, x1+w]]; }; ENDCASE => error ¬ "incorrect # arguments"; EXITS ConvertError => error ¬ "conversion error"; }; MakeCopier: PROC [d: Data] ~ { parent: Viewer ¬ ViewerOps.CreateViewer[flavor: $CtCopy, info: [openHeight: 34, name: "Ct Copy", data: d, scrollable: FALSE, column: right, iconic: TRUE]]; ViewerOps.OpenIcon[parent]; ViewerTools.SetContents[ViewerTools.MakeNewTextViewer[ info: [scrollable: FALSE, parent: parent, border: FALSE, wx: 40, wy: 0, ww: 400, wh: 17]], "Left: pick source, Middle: copy, Right: nasty copy"]; Buttons.SetDisplayStyle[Buttons.Create[ [parent: parent, name: "On ", wx: 5, wy: 3], Toggle, d], $WhiteOnBlack]; }; Toggle: Buttons.ButtonProc ~ { d: Data ¬ NARROW[clientData]; CtMisc.ButtonToggle[parent]; IF CtMisc.ButtonOn[parent] THEN CtViewer.RegisterMouse[d.image, MouseProc, d] ELSE CtViewer.UnregisterMouse[d.image, MouseProc]; }; MouseProc: CtViewer.MouseProc ~ { d: Data ¬ NARROW[clientData]; IF mouse.state # down THEN RETURN; IF mouse.button = left THEN { d.box ¬ CtViewer.GetBoundingBox[viewer, [mouse.pos.y, mouse.pos.x],, upperLeft]; d.store ¬ TRUE; } ELSE CtViewer.DoWithViewer[d.image, Copy, d]; }; Copy: CtViewer.ViewerProc ~ { Poll: CtViewer.PollProc ~ { old ¬ new; new ¬ [[pos.y, pos.x], [pos.y+size.s, pos.x+size.f]]; shift ¬ SF.Sub[new.min, old.min]; IF NOT once THEN {CtBasic.CopyClippedMaps[maps, temp, new, new]; once ¬ TRUE}; SELECT TRUE FROM CtViewer.KeyDown[middleMouse] => NiceCopy[]; CtViewer.KeyDown[rightMouse] => NastyCopy[]; ENDCASE; }; NastyCopy: PROC ~ { CtBasic.CopyClippedMaps[d.source, maps, d.source.box, new]; temp ¬ CtBasic.ShiftMaps[temp, shift]; }; NiceCopy: PROC ~ { DisjointCopy: PROC ~ { CtBasic.CopyClippedMaps[temp, maps, temp.box, old]; temp ¬ CtBasic.ShiftMaps[temp, shift]; CtBasic.CopyClippedMaps[maps, temp, new, new]; CtBasic.CopyClippedMaps[d.source, maps, d.source.box, new]; }; IF SF.Disjoint[old, new] THEN DisjointCopy[] ELSE { src: Vec; old1, old2, new1, new2: Box; SELECT TRUE FROM shift.f < 0 AND shift.s < 0 => { src ¬ [old.min.s, old.min.f]; old1 ¬ [[new.max.s, old.min.f], old.max]; old2 ¬ [[old.min.s, new.max.f], [new.max.s, old.max.f]]; new1 ¬ [new.min, old2.min]; new2 ¬ [[old.min.s, new.min.f], old1.min]; }; shift.f < 0 AND shift.s >= 0 => { src ¬ [new.min.s, old.min.f]; old1 ¬ [old.min, [new.min.s, old.max.f]]; old2 ¬ [[new.min.s, new.max.f], old.max]; new1 ¬ [[old.max.s, new.min.f], new.max]; new2 ¬ [new.min, [old.max.s, old.min.f]]; }; shift.f >= 0 AND shift.s < 0 => { src ¬ [old.min.s, new.min.f]; old1 ¬ [[new.max.s, old.min.f], old.max]; old2 ¬ [old.min, [new.max.s, new.min.f]]; new1 ¬ [new.min, [old.min.s, new.max.f]]; new2 ¬ [[old.min.s, old.max.f], new.max]; }; shift.f >= 0 AND shift.s >= 0 => { src ¬ [new.min.s, new.min.f]; old1 ¬ [old.min, [new.min.s, old.max.f]]; old2 ¬ [[new.min.s, old.min.f], [old.max.s, new.min.f]]; new1 ¬ [old2.max, new.max]; new2 ¬ [old1.max, [old.max.s, new.max.f]]; }; ENDCASE; CtBasic.CopyClippedMaps[temp, maps, old1, old1]; CtBasic.CopyClippedMaps[temp, maps, old2, old2]; CtBasic.MoveMaps[temp, src, SF.Sub[src, shift], SF.Sub[SF.Size[temp.box], [ABS[shift.s], ABS[shift.f]]]]; temp ¬ CtBasic.ShiftMaps[temp, shift]; CtBasic.CopyClippedMaps[maps, temp, new1, new1]; CtBasic.CopyClippedMaps[maps, temp, new2, new2]; CtBasic.CopyClippedMaps[d.source, maps, d.source.box, new]; }; }; middleMouse: KeyTypes.KeySym ¬ KeyNames.KeySymFromName["MiddleMouse"]; rightMouse: KeyTypes.KeySym ¬ KeyNames.KeySymFromName["RightMouse"]; d: Data ¬ NARROW[clientData]; once: BOOL ¬ FALSE; old, new: Box ¬ d.box; size, shift: Vec ¬ SF.Size[d.box]; temp: SampleMaps ¬ CtBasic.CopyOfMaps[maps, d.box.min.f, d.box.min.s, size.f, size.s]; IF d.store THEN { d.source ¬ CtBasic.CopyOfMaps[maps, d.box.min.f, d.box.min.s, size.f, size.s]; d.store ¬ FALSE; }; CtViewer.DoWhileMouseDown[viewer, Poll]; IF NOT CtViewer.MouseInViewer[viewer] THEN CtBasic.CopyClippedMaps[temp, maps, temp.box, old]; }; Destroy: ViewerClasses.DestroyProc ~ { CtViewer.UnregisterMouse[NARROW[self.data, Data].image, MouseProc]; }; <> <> <> <> <> <> <> <<};>> <> <> <> <<};>> <> ViewerOps.RegisterViewerClass[$CtCopy, NEW[ViewerClasses.ViewerClassRec¬[destroy:Destroy]]]; CtDispatch.RegisterCtOp["Copying:", NIL, NIL]; CtDispatch.RegisterCtOp["Copy", CtCopy, usage]; END. <<>> <<>>