DIRECTORY
DisplayListDefs: FROM "DisplayListDefs",
GraphicsDefs: FROM "GraphicsDefs",
InlineDefs: FROM "InlineDefs" USING [COPY],
SystemDefs: FROM "SystemDefs" USING [AllocateSegment,FreeSegment];

DisplayList: PROGRAM IMPORTS GraphicsDefs, InlineDefs, SystemDefs EXPORTS DisplayListDefs =
BEGIN

displayCount: CARDINAL ← 0;
displayListMax: CARDINAL ← 0;
displayListIncrement: CARDINAL = 1024;
displayList: POINTER TO ARRAY [0..0) OF POINTER TO GraphicsDefs.Box ← NIL;

MakeLongPointer
: PROCEDURE [ptr: POINTER,bank: CARDINAL] RETURNS [LONG POINTER] = MACHINE CODE BEGIN END;

GetDisplayListHandle: PUBLIC PROCEDURE RETURNS [POINTER TO ARRAY [0..0) OF POINTER TO GraphicsDefs.Box] =
BEGIN
RETURN[displayList];
END;

ResetDisplayCount: PUBLIC PROCEDURE [nItems: CARDINAL ← 0] =
BEGIN
displayCount ← nItems;
END;

GetDisplayCount: PUBLIC PROCEDURE RETURNS [CARDINAL] =
BEGIN
RETURN[displayCount];
END;

AddDisplayItem: PUBLIC PROCEDURE[B: POINTER TO GraphicsDefs.Box] =
BEGIN
IF displayCount >= displayListMax THEN
BEGIN
newDisplayList: POINTER TO ARRAY [0..0) OF POINTER TO GraphicsDefs.Box;
newDisplayList ← SystemDefs.AllocateSegment[displayListMax+displayListIncrement];
InlineDefs.COPY[from: displayList,
nwords: displayListMax+displayListIncrement,
to: newDisplayList];
IF displayList # NIL THEN SystemDefs.FreeSegment[displayList];
displayList ← newDisplayList;
displayListMax ← displayListMax+displayListIncrement;
END;
displayList[displayCount] ← B;
displayCount ← displayCount+1;
END;

DeleteDisplayItem: PUBLIC PROCEDURE [B: POINTER TO GraphicsDefs.Box] =
BEGIN
i,j: CARDINAL;
FOR i IN [0..displayCount) DO
IF displayList[i] = B THEN
BEGIN
FOR j IN [i+1..displayCount) DO
displayList[j-1] ← displayList[j];
ENDLOOP;
displayCount ← displayCount-1;
IF B.savedBits # NIL THEN GraphicsDefs.RemoveBox[B]
ELSE
BEGIN
ReDisplay[B];
B.displayed ← FALSE;
END;
EXIT;
END;
ENDLOOP;
END;

ReDisplay: PUBLIC PROCEDURE [B: POINTER TO GraphicsDefs.Box] =
BEGIN
i: CARDINAL;

GraphicsDefs.ReleaseBox[B];

--IF B.displayed THEN
BEGIN
Screen: POINTER TO GraphicsDefs.Bitmap ←
GraphicsDefs.GetDefaultBitmapHandle[];
ScreenRect: GraphicsDefs.Rectangle ←
[MAX[INTEGER[B.displayX],0],MAX[INTEGER[B.displayY],0],
MIN[B.displayX + B.boxBitmap.nBits - 1,Screen.nBits-1],
MIN[B.displayY + B.boxBitmap.nLines - 1,Screen.nLines-1]
];
GraphicsDefs.EraseArea[ScreenRect.x1,ScreenRect.y1,ScreenRect.x2,ScreenRect.y2];
--and regenerate everyone else
FOR i IN [0..displayCount) DO
IF displayList[i].displayed AND Intersection[B,displayList[i]] THEN
BEGIN
C: POINTER TO GraphicsDefs.Box ← displayList[i];
srcRect: GraphicsDefs.Rectangle;
destRect: GraphicsDefs.Rectangle;

destRect.x1 ← MAX[INTEGER[C.displayX],ScreenRect.x1];
destRect.y1 ← MAX[INTEGER[C.displayY],ScreenRect.y1];
destRect.x2 ← MIN[C.displayX + C.boxBitmap.nBits - 1,ScreenRect.x2];
destRect.y2 ← MIN[C.displayY + C.boxBitmap.nLines - 1,ScreenRect.y2];

srcRect.x1 ← destRect.x1 - C.displayX;
srcRect.y1 ← destRect.y1 - C.displayY;
srcRect.x2 ← srcRect.x1 + (destRect.x2 - destRect.x1);
srcRect.y2 ← srcRect.y1 + (destRect.y2 - destRect.y1);
IF C.type = gray THEN
BEGIN
GraphicsDefs.TransferRectangle[@C.boxBitmap,Screen,
@srcRect,@destRect,erase];
GraphicsDefs.SetGrayLevel[C.gray];
GraphicsDefs.TransferRectangle[@C.boxBitmap,Screen,
@srcRect,@destRect,paint,andgray];
END
ELSE GraphicsDefs.TransferRectangle[@C.boxBitmap,Screen,
@srcRect,@destRect,C.function];
END;
ENDLOOP;
END;
END;

Intersection: PUBLIC PROCEDURE[b1,b2: POINTER TO GraphicsDefs.Box] RETURNS [BOOLEAN] =
BEGIN
x1: CARDINAL ← MAX[0,INTEGER[b1.displayX]];
x2: CARDINAL ← MAX[0,INTEGER[b2.displayX]];
x1a: CARDINAL ← b1.displayX + b1.boxBitmap.nBits - 1;
x2a: CARDINAL ← b2.displayX + b2.boxBitmap.nBits - 1;
y1: CARDINAL ← MAX[0,INTEGER[b1.displayY]];
y2: CARDINAL ← MAX[0,INTEGER[b2.displayY]];
y1a: CARDINAL ← b1.displayY + b1.boxBitmap.nLines - 1;
y2a: CARDINAL ← b2.displayY + b2.boxBitmap.nLines - 1;

IF x1a < x2 OR y1a < y2 THEN RETURN [FALSE];
IF x2a < x1 OR y2a < y1 THEN RETURN [FALSE];
RETURN [TRUE];
END;

Inside: PUBLIC PROCEDURE[x,y: CARDINAL,b: POINTER TO GraphicsDefs.Box] RETURNS [BOOLEAN] =
BEGIN
x1: CARDINAL ← MAX[0,INTEGER[b.displayX]];
x1a: CARDINAL ← b.displayX + b.boxBitmap.nBits - 1;
y1: CARDINAL ← MAX[0,INTEGER[b.displayY]];
y1a: CARDINAL ← b.displayY + b.boxBitmap.nLines - 1;

RETURN [ x IN [x1..x1a] AND y IN [y1..y1a] ];
END;

END.