-- File CIFVersatecControl.mesa
-- Written by Martin Newell, June 1980
-- Last updated: July 21, 1981 2:40 PM by Pasco

DIRECTORY

CIFControlDefs: FROM "CIFControlDefs" USING [DrawCIF],
CIFDevicesDefs: FROM "CIFDevicesDefs" USING [DeviceDescriptor, DeviceDescriptorRecord,
RegisterDevice, GetCIFOutDevice],
CIFOutputDefs: FROM "CIFOutputDefs" USING [SetSorting],
CIFUtilitiesDefs: FROM "CIFUtilitiesDefs" USING [Rectangle,
SetClipRectangle, GetClipRectangle, SetUniformView, DrawClipRectangle,
SetDisplayContext, GetDisplayContext, MoveTo, DrawTo, MapRectangle],
CIFVersatecScanDefs: FROM "CIFVersatecScanDefs" USING[InitVersatecScan,
VersatecScanConvert, AddToEdgeList],
CIFVersatecTypeDefs: FROM "CIFVersatecTypeDefs" USING [Edge],
CIFVersatecUtilsDefs: FROM "CIFVersatecUtilsDefs" USING[VersatecMakeEdge,
OutputStripesUntil, InitVersatecOut, FinishVersatecOut,
LoadStipple, VStripeWidth],
FileOpDefs: FROM "FileOpDefs" USING[SetUserAndPassword, StoreFile,
FileOpFailed],
Graphics: FROM "Graphics" USING [DisplayContext, NewContext, PushContext, PopContext, CopyContext, Scale],
IntDefs: FROM "IntDefs" USING[ILastBB],
IODefs: FROM "IODefs" USING [WriteString, WriteLine, WriteDecimal],
JaMFnsDefs: FROM "JaMFnsDefs" USING [PopInteger,
PopString],
OsStaticDefs: FROM "OsStaticDefs" USING [OsStatics],
Real: FROM "Real" USING [Fix, FixC],
StringDefs: FROM "StringDefs" USING[AppendChar, AppendString, AppendDecimal,
BcplToMesaString];

CIFVersatecControl: PROGRAM
IMPORTS CIFControlDefs, CIFDevicesDefs, CIFOutputDefs, CIFUtilitiesDefs, CIFVersatecScanDefs, CIFVersatecUtilsDefs, FileOpDefs, Graphics, IntDefs, IODefs, JaMFnsDefs, Real, StringDefs =

BEGIN OPEN CIFControlDefs, CIFDevicesDefs, CIFOutputDefs, CIFUtilitiesDefs, CIFVersatecTypeDefs, CIFVersatecScanDefs, CIFVersatecUtilsDefs, FileOpDefs, Graphics, IntDefs, IODefs, JaMFnsDefs, OsStaticDefs, Real, StringDefs;


-- Versatec procedures

VersatecDeviceRecord: DeviceDescriptorRecord ← [
next:NIL,
name:"versatec",
deviceSelect: VersatecSelect,
deviceDrawFrame: VersatecDrawFrame,
deviceSetScale: VersatecSetScale,
deviceSetClipRegion: VersatecSetClipRegion,
deviceOutput: VersatecOutput,
deviceLayer: VersatecLayer,
deviceLoadLayer: VersatecLoadLayer,
deviceRectangle: VersatecRectangle,
deviceStartPoly: VersatecStartPoly,
devicePolyVertex: VersatecPolyVertex,
deviceEndPoly: VersatecEndPoly,
--
deviceTrapezoid: VersatecTrapezoid,
deviceText: VersatecText
];

VersatecSelect: PROCEDURE RETURNS[BOOLEAN] =
BEGIN --expects <nstrips> (INTEGER)
NStrips ← PopInteger[];
VersatecSetClipRegion[GetClipRectangle[]];
RETURN[TRUE];
END;

VersatecDrawFrame: PROCEDURE =
BEGIN
r: Rectangle ← GetClipRectangle[];
DrawClipRectangle[];
BEGIN OPEN r; --show pages
width: REAL ← (urx-llx)/NStrips;
x: REAL ← llx;
THROUGH [1..NStrips) DO
x ← x + width;
MoveTo[x,lly];
DrawTo[x,ury];
ENDLOOP;
END;
END;

VersatecSetScale: PROCEDURE [factor: REAL] =
BEGIN
dc: DisplayContext ← GetDisplayContext[];
PopContext[dc];
PushContext[dc];
Scale[dc, [factor,factor]];
END;

VersatecSetClipRegion: PROCEDURE [rt: Rectangle] =
BEGIN
SetClipRectangle[rt];
END;

VersatecOutput: PROCEDURE =
--expects <first last fileName>
-- Generate strips [first..last]
BEGIN
fileName: STRING ← [100];
i,first,last: CARDINAL;
PopString[fileName];
last ← PopInteger[];
first ← PopInteger[];
FOR i IN [MinMax[1,first,NStrips]..MinMax[1,last,NStrips]] DO
OutVersatecStrip[fileName,i];
ENDLOOP;
END;

OutVersatecStrip: PROCEDURE[fileName: STRING, strip: CARDINAL] =
-- Generate single strip
BEGIN
width,x,vtop: REAL;
saveContext: DisplayContext ← GetDisplayContext[];
r,ru,vr: Rectangle;
pageName: STRING ← [50];

r ← GetClipRectangle[]; --whole region in CIF units
width ← (r.urx-r.llx)/NStrips; --width of single strip
x ← r.llx + width*(strip - 1); --x coord of left of strip
-- draw strip [x,r.lly, x+width,r.ury]
ru ← [llx: x, lly: r.lly, urx: x+width, ury: r.ury];
PushContext[versatecContext];
SetDisplayContext[versatecContext];
vr ← versatecClipRectangle;
-- adjust lly to give correct shape
vr.lly ← vr.ury - (vr.urx-vr.llx)*(r.ury-r.lly)/width;
SetClipRectangle[vr];
SetUniformView[ru,vr];
vtop ← MapRectangle[ru,versatecContext,identityContext].ury;
pageName.length ← 0;
AppendString[pageName,fileName];
AppendChar[pageName,’-];
AppendDecimal[pageName,strip];
AppendString[pageName,".bits"];
VersatecStart[pageName, strip, FixC[vtop+1]];
DrawCIF[Fix[ru.llx],Fix[ru.urx],Fix[ru.lly],Fix[ru.ury]];
VersatecEnd[pageName, vtop];
SetDisplayContext[saveContext];
PopContext[versatecContext];
SetClipRectangle[r];
END;

VersatecStart: PROCEDURE[pageName: STRING, strip, height: CARDINAL] =
BEGIN
WriteString["Strip "];
WriteDecimal[strip];
WriteString[". Bits File: "];
WriteLine[pageName];
localName.length ← 0;
IF pageName[0]=’[
THENBEGIN
AppendString[localName,localFileBufferName];
WriteString["...buffered on "];
WriteLine[localFileBufferName];
END
ELSEAppendString[localName,pageName];
SetSorting[decy];
VersatecCurrentLayer ← 7; --i.e. not set
InitVersatecScan[];
InitVersatecOut[localName, height];
END;

localName: STRING ← [50]; --in global frame since press shares it

VersatecEnd: PROCEDURE [pageName: STRING, ymax: REAL] =
BEGIN
FinishVersatecOut[ymax];
--check if need to write it to a file server
IF pageName[0]=’[
THENBEGIN
ENABLE FileOpFailed =>
BEGIN
WriteString[" ---Store failed: "];
WriteLine[reason];
CONTINUE;
END;
user: STRING ← [40];
password: STRING ← [40];
WriteString["Transferring "];
WriteString[localFileBufferName];
WriteString[" to "];
WriteLine[pageName];
BcplToMesaString[OsStatics↑.UserName,user];
BcplToMesaString[OsStatics↑.UserPassword,password];
SetUserAndPassword[user,password];
StoreFile[localFileBufferName,pageName,binary];
END;
END;

VersatecLayer: PROCEDURE [layer: CARDINAL] =
--used to trigger scan conversion up to bottom of object about to be received
BEGIN
l,r,b,t: LONG INTEGER;
bottom: REAL;
rec: Rectangle;
[l,r,b,t] ← ILastBB[]; --in chip coordinates
--kludge - need bottom of current object in Versatec coords
rec ← MapRectangle[[l,b,r,t], versatecContext, identityContext];
bottom ← MIN[rec.lly,rec.ury]-1; -- -1 to be on safe side
OutputStripesUntil[bottom];
VersatecScanConvert[bottom, FALSE];
VersatecCurrentLayer ← layer;
END;

VersatecLoadLayer: PROCEDURE[layer:CARDINAL, v0,v1,v2,v3: CARDINAL] =
BEGIN
LoadStipple[layer, v0,v1,v2,v3];
END;

VersatecText: PROCEDURE[text: STRING, x,y: REAL] =
BEGIN
--***ignored for now***
END;


--Private procedures--

VersatecRectangle: PROCEDURE [r: Rectangle] =
--make two edges of appropriate types
BEGIN
edge: Edge;
edge ← VersatecMakeEdge[r.llx,r.lly, r.llx,r.ury, TRUE];
IF edge#NIL THEN AddToEdgeList[VersatecCurrentLayer,
edge];
edge ← VersatecMakeEdge[r.urx,r.lly, r.urx,r.ury, FALSE];
IF edge#NIL THEN AddToEdgeList[VersatecCurrentLayer,
edge];
END;

x0,y0: REAL;
xs,ys: REAL;

VersatecStartPoly: PROCEDURE [x,y: REAL] =
BEGIN
x0 ← xs ← x;
y0 ← ys ← y;
END;

VersatecPolyVertex: PROCEDURE [x,y: REAL] =
BEGIN
edge: Edge ← NIL;
SELECT TRUE FROM
y>ys=> edge ← VersatecMakeEdge[xs,ys, x,y,FALSE];
y<ys=> edge ← VersatecMakeEdge[x,y, xs,ys,TRUE];
ENDCASE;
IF edge#NIL THEN AddToEdgeList[VersatecCurrentLayer,
edge];
xs ← x;
ys ← y;
END;

VersatecEndPoly: PROCEDURE =
BEGIN
VersatecPolyVertex[x0,y0];
END;

MinMax: PROCEDURE[lower,value,upper: CARDINAL] RETURNS[CARDINAL] =
BEGIN
RETURN[MIN[MAX[lower,value],upper]];
END;


--Versatec parameters
NStrips: CARDINAL ← 1;
--testing: versatecClipRectangle: Rectangle ← [llx: 0, lly: 1, urx: 500, ury: 500];
versatecClipRectangle: Rectangle ← [llx: 10, lly: -10, urx: VStripeWidth-10, ury: -10];
--height will be modified when used
identityContext: DisplayContext ←
NewContext[GetCIFOutDevice[]];
versatecContext: DisplayContext ← CopyContext[identityContext];

VersatecCurrentLayer: CARDINAL;

localFileBufferName: STRING ← "CIF.bits$";

--set up context
Scale[versatecContext, [1,-1]]; --to make y increase on sort

RegisterDevice[@VersatecDeviceRecord];

END.