-- BoxerImpl.mesa
-- Last changed by Doug Wyatt, September 22, 1980 5:32 PM

DIRECTORY
Boxer,
Vector USING [Vec, Add, Sub],
Area USING [Rec, Handle, Rectangle],
Memory USING [NewZone];

BoxerImpl: PROGRAM
IMPORTS Memory,Vector,Area
EXPORTS Boxer SHARES Boxer = {
OPEN Boxer;

zone: UNCOUNTED ZONE = Memory.NewZone["BoxerImpl"];

Data: PUBLIC TYPE = Area.Rec;
DataRef: TYPE = LONG POINTER TO Data;

iprocs: LONG POINTER TO READONLY Procs = zone.NEW[Procs = [
Put: IPut,
Include: IInclude,
Expand: CExpand,
Rectangle: CRectangle,
Copy: CCopy,
Free: CFree
]];

procs: LONG POINTER TO READONLY Procs = zone.NEW[Procs = [
Put: CPut,
Include: CInclude,
Expand: CExpand,
Rectangle: CRectangle,
Copy: CCopy,
Free: CFree
]];

sinkprocs: LONG POINTER TO READONLY Procs = zone.NEW[Procs = [
Put: SPut,
Include: SInclude,
Expand: SExpand,
Rectangle: SRectangle,
Copy: SCopy,
Free: SFree
]];

-- Procedures for creating a Boxer object

sink: PUBLIC Handle ← zone.NEW[Object ← [procs: sinkprocs, data: NIL]];

New: PUBLIC PROC RETURNS[Handle] = {
d: DataRef=zone.NEW[Data ← [ll: [0,0], ur: [0,0]]];
RETURN[zone.NEW[Object ← [procs: iprocs, data: d]]];
};

-- Operations on a Boxer

IPut: PROC[self: Handle, v: Vector.Vec] = {
d: DataRef=self.data;
d.ll←d.ur←v; self.procs←procs;
};

CPut: PROC[self: Handle, v: Vector.Vec] = {
d: DataRef=self.data;
IF v.x<d.ll.x THEN d.ll.x←v.x
ELSE IF v.x>d.ur.x THEN d.ur.x←v.x;
IF v.y<d.ll.y THEN d.ll.y←v.y
ELSE IF v.y>d.ur.y THEN d.ur.y←v.y;
};

SPut: PROC[self: Handle, v: Vector.Vec] = {
};

IInclude: PROC[self: Handle, area: Area.Handle] = {
d: DataRef=self.data;
d↑←Area.Rectangle[area];
self.procs←procs;
};

CInclude: PROC[self: Handle, area: Area.Handle] = {
d: DataRef=self.data;
r: Area.Rec=Area.Rectangle[area];
IF r.ll.x<d.ll.x THEN d.ll.x←r.ll.x;
IF r.ll.y<d.ll.y THEN d.ll.y←r.ll.y;
IF r.ur.x>d.ur.x THEN d.ur.x←r.ur.x;
IF r.ur.y>d.ur.y THEN d.ur.y←r.ur.y;
};

SInclude: PROC[self: Handle, area: Area.Handle] = {
};

CExpand: PROC[self: Handle, slop: REAL] = {
d: DataRef=self.data;
v: Vector.Vec=[slop,slop];
d.ll←Vector.Sub[d.ll,v];
d.ur←Vector.Add[d.ur,v];
};

SExpand: PROC[self: Handle, slop: REAL] = {
};

CRectangle: PROC[self: Handle] RETURNS[Area.Rec] = {
d: DataRef=self.data;
RETURN[d↑];
};

SRectangle: PROC[self: Handle] RETURNS[Area.Rec] = {
RETURN[[[0,0],[0,0]]];
};

CCopy: PROC[self: Handle] RETURNS[Handle] = {
d: DataRef=self.data;
dd: DataRef=zone.NEW[Data ← d↑];
RETURN[zone.NEW[Object ← [procs: self.procs, data: dd]]];
};

SCopy: PROC[self: Handle] RETURNS[Handle] = {
RETURN[sink];
};

CFree: PROC[self: Handle] = {
d: DataRef←self.data;
zone.FREE[@d]; zone.FREE[@self];
};

SFree: PROC[self: Handle] = {
};

}.