-- Compiler Refresh/n
-- m.stone January 29, 1981 4:45 PM

DIRECTORY
GriffinDefs: FROM "GriffinDefs",
ObjectDefs: FROM "ObjectDefs",
ScreenDefs: FROM "ScreenDefs",
PointDefs: FROM "PointDefs",
RefreshDefs: FROM "RefreshDefs",
XFormDefs: FROM "XFormDefs",
GriffinStartDefs: FROM "GriffinStartDefs",
MergeDefs: FROM "MergeDefs",
GriffinMemoryDefs: FROM "GriffinMemoryDefs";

Refresh: PROGRAM
IMPORTS ObjectDefs,ScreenDefs,GriffinMemoryDefs, MergeDefs
EXPORTS RefreshDefs,GriffinStartDefs =
BEGIN OPEN ObjectDefs,PointDefs,GriffinMemoryDefs;
Frame: TYPE = POINTER TO FrameType;
FrameType: TYPE = RECORD
[next: Frame,
back: Frame,
tl,br: ScrPt,
obj: ObjectHandle,
useNext: BOOLEAN];
newFrameH,newFrameT,bFrameH,bFrameT,tFrameH,tFrameT: Frame ← NIL;

EraseAndSave: PUBLIC PROCEDURE[obj: ObjectHandle]=
BEGIN
tl,br: ScrPt;
IF obj=NIL THEN RETURN;
tl ← obj.tl;
br ← obj.br;
IF obj.objectType#token AND obj.objectType#menu THEN BEGIN
tl ← [tl[X]-selW,tl[Y]-selW];
br ← [br[X]+selW,br[Y]+selW];
END;
EraseAndSaveBox[tl,br];
END;

EraseAndSaveBox: PUBLIC PROCEDURE[tl,br: ScrPt]=
BEGIN
ScreenDefs.EraseBox[tl,br];
[tl,br] ← ScreenDefs.ClipToScreen[tl,br];
IF br[X]>=tl[X] AND br[Y]>=tl[Y] THEN AddFrame[tl,br,newFrameT];
END;

PlotAndMark: PUBLIC PROCEDURE[obj: ObjectHandle]=
BEGIN
newframe: Frame ← NIL;
IF obj=NIL THEN RETURN;
IF ~obj.validEncoding THEN ObjectDefs.PlotOneObject[obj,write];
newframe ← MakeBox[obj.tl,obj.br,obj];
newframe.useNext ← TRUE;
newframe.obj ← obj;
END;

MarkBox: PUBLIC PROCEDURE[tl,br: ScrPt, obj: ObjectHandle]=
BEGIN
newframe: Frame ← NIL;
IF obj=NIL THEN RETURN;
newframe ← MakeBox[tl,br,obj];
newframe.obj ← obj;
END;

MakeBox: PROCEDURE[tl,br: ScrPt, obj: ObjectHandle] RETURNS[newFrame: Frame]=
BEGIN
IF obj=NIL THEN RETURN[NIL];
--space for select token
IF obj.objectType=shape OR obj.objectType=caption THEN BEGIN
tl ← [tl[X]-selW,tl[Y]-selW];
br ← [br[X]+selW,br[Y]+selW];
END;
[tl,br] ← ScreenDefs.ClipToScreen[tl,br];
IF br[X]>=tl[X] AND br[Y]>=tl[Y] THEN AddFrame[tl,br,newFrameT];
RETURN[newFrameT.back];
END;

EraseAndSaveAllCPs: PUBLIC PROCEDURE=
BEGIN
EraseCPs: ObjectDefs.ObjectProc = BEGIN
WITH token: obj SELECT FROM
token=> IF token.tokenType=CP OR token.tokenType=open THEN EraseAndSave[obj];
ENDCASE;
END;
ObjectDefs.ForAllVisibleObjects[EraseCPs];
END;

RestoreScreen: PUBLIC PROCEDURE=
BEGIN
frame,tptr: Frame;
area: MergeDefs.AreaDescriptor ← MergeDefs.AreaCreate[];
saveBox: PROC [tl,br: ScrPt, z: INTEGER] = {
--
ScreenDefs.EraseBox[tl,br];
AddFrame[tl,br,bFrameT];
};
frame ← newFrameH.next;
UNTIL frame=newFrameT DO
IF frame.obj=NIL THEN {
MergeDefs.AreaNewBox[area,frame.tl,frame.br,0];
frame ← DeleteFrame[frame]}
ELSE frame ← frame.next;
ENDLOOP;
MergeDefs.AreaGenerate[area,saveBox];
MergeDefs.AreaDestroy[area];
--now have non-intersecting set of erase frames
--clip the overlapping areas and add outside pieces to eraseFrames
frame ← newFrameH.next;
UNTIL frame=newFrameT DO
tptr ← frame.next;--ClipAndAdd deletes
ClipAndAdd[frame];
frame ← tptr;
ENDLOOP;
--bFrameH is the head of all the areas to be cleaned up
YSort[bFrameH,bFrameT];
FOR frame← bFrameH.next, frame←frame.next UNTIL frame=bFrameT DO
IF frame.obj=NIL THEN ReplotBox[frame.tl,frame.br]
ELSE ReplotBoxFromObject[frame.tl,frame.br,frame.obj];
ENDLOOP;
frame ← bFrameH.next;
UNTIL frame=bFrameT DO
frame ← DeleteFrame[frame];
ENDLOOP;
END;

--take the new frame and compare it to the list headed by bFrameH
--take outside pieces and add them to bFrameH
ClipAndAdd: PROC [frame: Frame, start: Frame ← bFrameH.next] = {
rover: Frame ← NIL;
FOR rover ← start, rover.next UNTIL rover=bFrameT DO
SELECT TRUE FROM
Inside[frame,rover] => {frame ← DeleteFrame[frame]; RETURN};
Outside[frame,rover] => LOOP;
--now have to clip the frame against rover, then Clip and add all the pieces
ENDCASE => {
ClipBox[frame,rover];--returns a list and Deletes frame
FOR frame ← tFrameT.back, tFrameT.back UNTIL frame=tFrameH DO
ClipAndAdd[frame,rover];
ENDLOOP;
RETURN;
};
ENDLOOP;
--if we get here, frame did not intersect anything. Add it to bFrameH
AddFrameH[frame.tl,frame.br,bFrameH];
frame ← DeleteFrame[frame];
RETURN;
};

ClipBox: PROC[frame,clipper: Frame] = {
DO SELECT TRUE FROM
Inside[frame,clipper] => {[] ← DeleteFrame[frame]; EXIT};
frame.tl[Y]<clipper.tl[Y] => {
AddFrameH[frame.tl,[frame.br[X],clipper.tl[Y]-1], tFrameH];
frame.tl[Y] ← clipper.tl[Y];
};
frame.br[Y]>clipper.br[Y] => {
AddFrameH[[frame.tl[X],clipper.br[Y]+1], frame.br, tFrameH];
frame.br[Y] ← clipper.br[Y];
};
ENDCASE => SELECT TRUE FROM
frame.tl[X]<clipper.tl[X] => {
AddFrameH[frame.tl,[clipper.tl[X]-1,frame.br[Y]], tFrameH];
frame.tl[X] ← clipper.tl[X];
};
frame.br[X]>clipper.br[X] => {
AddFrameH[[clipper.br[X]+1,frame.tl[Y]],frame.br, tFrameH];
frame.br[X] ← clipper.br[X];
};
ENDCASE;
ENDLOOP;
YSort[tFrameH,tFrameT];
};

YSort: PROC[head,tail: Frame] = {
--sort in Y
rover: Frame ← NIL;
switches: INTEGER;
DO
switches ← 0; rover ← head.next;
UNTIL rover=tail DO
IF rover.tl[Y]>rover.next.tl[Y] THEN {
Switch[rover,rover.next];
switches ← switches+1;}
ELSE rover ← rover.next;
ENDLOOP;
IF switches=0 THEN EXIT;
ENDLOOP;
};

Inside: PROC[frame,clipper: Frame] RETURNS [BOOLEAN] = INLINE {
RETURN[PointInside[frame.tl,clipper.tl,clipper.br] AND
PointInside[frame.br,clipper.tl,clipper.br]];
};

PointInside: PROC[pt,tl,br: ScrPt] RETURNS [BOOLEAN] = INLINE {
RETURN[pt[X] IN [tl[X]..br[X]] AND pt[Y] IN [tl[Y]..br[Y]]];
};

Outside: PROC[frame,clipper: Frame] RETURNS [BOOLEAN] = INLINE {
RETURN[frame.tl[Y]>clipper.br[Y] OR frame.br[Y]<clipper.tl[Y]
OR frame.tl[X]>clipper.br[X] OR frame.br[X]<clipper.tl[X]];
};

Switch: PROCEDURE[left,right: Frame]=
BEGIN
left.back.next ← right;
right.next.back ← left;
right.back ← left.back;
left.next ← right.next;
left.back ← right;
right.next ← left;
END;

AddFrameH: PROCEDURE[tl,br: ScrPt,head: Frame]=
BEGIN
newframe: Frame ← Allocate[SIZE[FrameType]] ;
newframe↑ ← [head.next,head,tl,br,NIL,FALSE];
newframe.next.back ← newframe;
head.next ← newframe;
END;

AddFrame: PROCEDURE[tl,br: ScrPt,tail: Frame]=
BEGIN
newframe: Frame ← Allocate[SIZE[FrameType]] ;
newframe↑ ← [tail,tail.back,tl,br,NIL,FALSE];
newframe.back.next ← newframe;
tail.back ← newframe;
END;

DeleteFrame: PROCEDURE[frame: Frame] RETURNS[next: Frame] =
BEGIN
frame.next.back ← frame.back;
frame.back.next ← frame.next;
next ← frame.next;
Free[frame];
END;

InitHeadTail: PROCEDURE RETURNS [head,tail: Frame]=
BEGIN
head ← Allocate[SIZE[FrameType]] ;
tail ← Allocate[SIZE[FrameType]] ;
head↑ ← [tail,NIL,[0,0],[0,0],NIL,FALSE];
tail↑ ← [NIL,head,[808,808],[808,808],NIL,FALSE];
END;

[newFrameH,newFrameT] ← InitHeadTail[];
[bFrameH,bFrameT] ← InitHeadTail[];
[tFrameH,tFrameT] ← InitHeadTail[];
END.