CtCopyCommandImpl.mesa
Copyright Ó 1985, 1992 by Xerox Corporation. All rights reserved.
Bloomenthal, April 15, 1993 2:00 pm PDT
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
Types
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;
Copy Command
Data:     TYPE ~ REF DataRep;
DataRep:   TYPE ~ RECORD [
cmd:      CtDispatch.CmdHandle,
image:     Viewer,
box:      Box,
store:      BOOL ¬ TRUE,
source:     SampleMaps ¬ NIL
];
usage: ROPE ~ "Ct Copy [<x0 y0 (src) x1 y1 (dest) w h>]: 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];
};
Simple: CtMisc.MouseProc ~ {
This is a simpler template for a copy operation (and also pre-PCedar!):
Action: PROC ~ {
d.temp ← CtBasic.ShiftMaps[d.temp, SF.Sub[[mouse.pos.y, mouse.pos.x], d.temp.box.min]];
CtBasic.CopyClippedMaps[d.cd, d.temp, d.temp.box, d.temp.box];
d.new ← [[mouse.pos.y, mouse.pos.x], [mouse.pos.y+d.size.s, mouse.pos.x+d.size.f]];
CtBasic.CopyClippedMaps[d.source, d.cd, d.source.box, d.new];
};
d: Data ← NARROW[clientData];
IF mouse.state # up AND mouse.button # left
THEN Terminal.ModifyColorFrame[d.vt, Action, 0, 0, d.cd.w, d.cd.h];
};
Start Code
ViewerOps.RegisterViewerClass[$CtCopy, NEW[ViewerClasses.ViewerClassRec¬[destroy:Destroy]]];
CtDispatch.RegisterCtOp["Copying:", NIL,  NIL];
CtDispatch.RegisterCtOp["Copy",  CtCopy, usage];
END.