DIRECTORY
DiscoDefs: FROM "DiscoDefs",
DisplayListDefs: FROM "DisplayListDefs",
GraphicsDefs: FROM "GraphicsDefs",
HalftoneDefs: FROM "HalftoneDefs",
InlineDefs: FROM "InlineDefs" USING [COPY,LongMult,LongDiv],
PressDefs: FROM "PressDefs" USING
[MulDiv,SignedMulDiv,ELShowRectangle,ELShowDots,ELShowDotsOpaque,
ELShowCharacters,ELShowObject,PressDotsData],
StrawDefs: FROM "StrawDefs",
SystemDefs: FROM "SystemDefs";

StrawMagnify: PROGRAM IMPORTS DiscoDefs,DisplayListDefs,GraphicsDefs,HalftoneDefs,InlineDefs,
PressDefs,StrawDefs,SystemDefs
EXPORTS StrawDefs =
BEGIN
Mica: TYPE = CARDINAL;
Buttons: TYPE = MACHINE DEPENDENT RECORD
[ KeyPadAndGarbage: [0..10000B),
Mark: BOOLEAN, --TRUE means button up
Select: BOOLEAN,
Draw: BOOLEAN
];
MouseButtons: POINTER TO Buttons = LOOPHOLE[177030B];
CursorX: POINTER TO CARDINAL = LOOPHOLE[426B];
CursorY: POINTER TO CARDINAL = LOOPHOLE[427B];
bitsPerInch: CARDINAL ← 72;

micasPerInch: CARDINAL = 2540;

MagnifyWidth: CARDINAL ← 608/3;
MagnifyHeight: CARDINAL ← 808/3;
AdjustHeight: CARDINAL ← 12;
MagnifyBitsPerInch: CARDINAL ← 192;
AdjustX: CARDINAL ← ((MagnifyWidth-AdjustHeight)/6)*2;
MagnifyListCount: CARDINAL;
MagnifyListMax: CARDINAL ← 0;
MagnifyList: POINTER TO ARRAY[0..0) OF POINTER TO StrawDefs.EntityBox←NIL;
AdjustBox,MagnifyBox: GraphicsDefs.Box;
MagnifySelectionIndex: CARDINAL;
MagnifyX,MagnifyY: CARDINAL;
selectionIndex,selectGray: CARDINAL;
partitions: ARRAY [0..7) OF CARDINAL = [10,72,192,384,723,1270,2540];

MulDivCeiling: PROCEDURE [a,b,c:CARDINAL] RETURNS [CARDINAL] = INLINE
BEGIN
al: LONG CARDINAL ← InlineDefs.LongMult[a,b];
RETURN[InlineDefs.LongDiv[al+c-1,c]];
END;

StartMagnifier: PUBLIC PROCEDURE [Index,Gray: CARDINAL] =
BEGIN OPEN GraphicsDefs;
bm: POINTER TO GraphicsDefs.Bitmap ← @AdjustBox.boxBitmap;
AdjustXMin: CARDINAL ← MagnifyWidth-AdjustHeight;
i: CARDINAL;

selectionIndex ← Index;
selectGray ← Gray;
CreateBox[@MagnifyBox,MagnifyWidth+1,MagnifyHeight+1];
CreateBox[@AdjustBox,MagnifyWidth+1,AdjustHeight+1];
AdjustBox.displayBitmap ← MagnifyBox.displayBitmap ←
GraphicsDefs.GetDefaultBitmapHandle[];
EraseArea[0,0,MagnifyWidth,AdjustHeight,bm];
ReplaceArea[0,0,0,AdjustHeight,bm];
ReplaceArea[0,AdjustHeight,MagnifyWidth,AdjustHeight,bm];
ReplaceArea[MagnifyWidth,AdjustHeight,MagnifyWidth,0,bm];
ReplaceArea[MagnifyWidth,0,0,0,bm];
ReplaceArea[AdjustXMin,0,AdjustXMin,AdjustHeight,bm];

--icons
FOR i IN [0..6) DO
ReplaceArea[(AdjustXMin*i)/6,AdjustHeight/2-i,
(AdjustXMin*(i+1))/6,AdjustHeight/2+i,bm];
ENDLOOP;

ReplaceArea[AdjustXMin+2,2,AdjustXMin+AdjustHeight-2,2,bm];
ReplaceArea[AdjustXMin+AdjustHeight-2,2,
AdjustXMin+AdjustHeight-2,AdjustHeight-2,bm];
ReplaceArea[AdjustXMin+AdjustHeight-2,AdjustHeight-2,
AdjustXMin+2,AdjustHeight-2,bm];
ReplaceArea[AdjustXMin+2,AdjustHeight-2,AdjustXMin+2,2,bm];

XorArea[AdjustX,1,AdjustX,AdjustHeight-1,bm];
ShowMagnifier[];
END;

ModifyMagnifier: PUBLIC PROCEDURE [x,y: CARDINAL] RETURNS [BOOLEAN] =
BEGIN OPEN GraphicsDefs;
AdjustMin: CARDINAL ← AdjustBox.displayX;
AdjustMax: CARDINAL ← AdjustBox.displayX+MagnifyWidth-AdjustHeight;
X,Y,minX,minY: CARDINAL;
bm: POINTER TO Bitmap ← @AdjustBox.boxBitmap;

IF NOT DisplayListDefs.Inside[x,y,@AdjustBox] THEN RETURN[FALSE];
--change magnification
IF x IN [CARDINAL[MAX[0,INTEGER[AdjustBox.displayX]]]..AdjustMax] THEN
BEGIN
Len: CARDINAL ← AdjustMax-AdjustMin;
p: CARDINAL ← ((x-AdjustMin)*6)/Len;
thisPartStart: CARDINAL ← AdjustMin+(Len*p)/6;
thisPartEnd: CARDINAL ← thisPartStart+Len/6;
magnification: CARDINAL ← partitions[p] +
PressDefs.MulDiv[x-thisPartStart,partitions[p+1]-partitions[p],Len/6];
XorArea[AdjustX,1,AdjustX,AdjustHeight-1,bm];
AdjustX ← x-AdjustMin;
XorArea[AdjustX,1,AdjustX,AdjustHeight-1,bm];
SetMagnification[magnification];
ShowMagnifier[];
RETURN [TRUE];
END;
--change size
DO
X ← MAX[16,INTEGER[(x-MagnifyX)*2]];
Y ← MAX[16,INTEGER[(y-MagnifyY)*2]];
minX ← MagnifyX - X/2;
minY ← MagnifyY - Y/2;
XorArea[minX,minY,minX+X,minY+1];
XorArea[minX+X,minY,minX+X+1,minY+Y];
XorArea[minX+X+1,minY+Y,minX,minY+Y];
XorArea[minX,minY+Y+1,minX,minY];

XorArea[minX,minY,minX+X,minY+1];
XorArea[minX+X,minY,minX+X+1,minY+Y];
XorArea[minX+X+1,minY+Y,minX,minY+Y];
XorArea[minX,minY+Y+1,minX,minY];
IF MouseButtons.Mark THEN EXIT;
x ← CursorX↑;
y ← CursorY↑;
ENDLOOP;
StopMagnifier[];
AdjustX ← PressDefs.MulDiv[AdjustX,X-AdjustHeight,MagnifyWidth-AdjustHeight];
SetMagnifierSize[X,Y];
StartMagnifier[selectionIndex,selectGray];
RETURN [TRUE];
END;

ShowMagnifier: PUBLIC PROCEDURE =
BEGIN
i: CARDINAL;
--screen coords of source to be magnified
srcWidth: CARDINAL ← PressDefs.MulDiv[MagnifyWidth,bitsPerInch,MagnifyBitsPerInch];
srcHeight: CARDINAL ← PressDefs.MulDiv[MagnifyHeight,bitsPerInch,MagnifyBitsPerInch];
xMin: INTEGER ← MagnifyX - srcWidth/2;
xMax: INTEGER ← xMin + srcWidth;
yMin: INTEGER ← MagnifyY - srcHeight/2;
yMax: INTEGER ← yMin + srcHeight;
b: POINTER TO GraphicsDefs.Box;
e: POINTER TO StrawDefs.EntityBox;
srcRect,destRect,micaRect: GraphicsDefs.Rectangle;
bm: POINTER TO GraphicsDefs.Bitmap ← @MagnifyBox.boxBitmap;
displayList: POINTER TO ARRAY [0..0) OF POINTER TO GraphicsDefs.Box ←
DisplayListDefs.GetDisplayListHandle[];
screenHeight: INTEGER ← MagnifyBox.displayBitmap.nLines;
mx,my: INTEGER;
micaHeight,micaWidth,xLeft,yTop: INTEGER;
--precompute fixed values
micaXMin: INTEGER ← mc[MAX[-800,xMin]];
magXMin: INTEGER ← m[xMin];
micaYMin: INTEGER ← mc[screenHeight-MAX[0,yMin]];
magYMin: INTEGER ← m[yMin];
magScreenHeight: INTEGER ← m[screenHeight];
DefaultMagnify: PROCEDURE =
BEGIN
srcRect.x1 ← dc[micaRect.x1];
srcRect.x2 ← dc[micaRect.x2];
srcRect.y1 ← dc[micaRect.y1];
srcRect.y2 ← dc[micaRect.y2];
--there is a generous inclusion test, to allow accurate recomputing from mica
--coords. If the box is one line off the edge, the following error condition may occur
IF srcRect.y2 < srcRect.y1 OR srcRect.x2 < srcRect.x1 THEN RETURN;
destRect.x1 ← mx+mdc[micaRect.x1];
destRect.x2 ← mx+mdc[micaRect.x2];
destRect.y1 ← my+mdc[micaRect.y1];
destRect.y2 ← my+mdc[micaRect.y2];
IF (destRect.x1<0) OR (destRect.y1<0) THEN ERROR;
IF i >= MagnifySelectionIndex THEN
BEGIN
GraphicsDefs.SetGrayLevel[selectGray];
GraphicsDefs.XorGray[0,0,bm.nBits,bm.nLines,bm];
END;
SELECT b.type FROM
gray =>
BEGIN
GraphicsDefs.TransferRectangle[bm,@MagnifyBox.boxBitmap,
@srcRect,@destRect,erase];
GraphicsDefs.SetGrayLevel[b.gray];
GraphicsDefs.TransferRectangle[bm,@MagnifyBox.boxBitmap,
@srcRect,@destRect,paint,andgray];
END;
normal =>
GraphicsDefs.TransferRectangle[bm,@MagnifyBox.boxBitmap,
@srcRect,@destRect,b.function];
ENDCASE => ERROR;
IF i >= MagnifySelectionIndex THEN
BEGIN
GraphicsDefs.SetGrayLevel[selectGray];
GraphicsDefs.XorGray[destRect.x1,destRect.y1,
destRect.x2,destRect.y2,@MagnifyBox.boxBitmap];
GraphicsDefs.XorGray[0,0,bm.nBits,bm.nLines,bm];
END;
END; --default case

MagnifyListCount ← 0;
MagnifySelectionIndex ← selectionIndex;
GraphicsDefs.EraseArea[0,0,MagnifyWidth,MagnifyHeight,bm];

FOR i IN [0..DisplayListDefs.GetDisplayCount[]) DO
b ← displayList[i];
IF i = selectionIndex THEN MagnifySelectionIndex ← MagnifyListCount;
IF INTEGER[b.displayX] > xMax OR INTEGER[b.displayY] > yMax OR
INTEGER[b.displayX + b.boxBitmap.nBits] < xMin OR
INTEGER[b.displayY + b.boxBitmap.nLines] < yMin THEN LOOP;
e ← LOOPHOLE[b];
IF MagnifyListCount >= MagnifyListMax THEN
BEGIN
newList: POINTER TO ARRAY [0..0) OF POINTER TO StrawDefs.EntityBox;
newList ← SystemDefs.AllocateSegment[MagnifyListMax+256];
InlineDefs.COPY[from:MagnifyList,nwords:MagnifyListMax,to:newList];
IF MagnifyList # NIL THEN SystemDefs.FreeSegment[MagnifyList];
MagnifyList ← newList;
MagnifyListMax ← MagnifyListMax+256;
END;
MagnifyList[MagnifyListCount] ← e;
MagnifyListCount ← MagnifyListCount+1;
ENDLOOP;
FOR i IN [0..MagnifyListCount) DO
e ← MagnifyList[i];
b ← @e.Box;
bm ← @b.boxBitmap;

SELECT e.Object.command FROM
PressDefs.ELShowObject=>
BEGIN
micaWidth ← mc[e.Box.boxBitmap.nBits]-1;
micaHeight ← mc[e.Box.boxBitmap.nLines]-1;
xLeft ← e.Object.micaX+e.Object.spaceX;
yTop ← e.Object.micaY+e.Object.spaceY;
END;
PressDefs.ELShowCharacters=>
BEGIN
strike: POINTER TO GraphicsDefs.StrikeFont;
[strike,,,] ← StrawDefs.GetFont[e.Object.font];
micaWidth ← mc[e.Box.boxBitmap.nBits]-1;
micaHeight ← mc[e.Box.boxBitmap.nLines]-1;
xLeft ← e.Object.micaX;
yTop ← e.Object.micaY+mcr[strike.ascent];
END;
ENDCASE=> --ShowDots,ShowRectangle
BEGIN
micaWidth ← e.Object.spaceX;
micaHeight ← e.Object.spaceY;
xLeft ← e.Object.micaX;
yTop ← e.Object.micaY+micaHeight;
END;

--max value of micaXMin,micaYMin is mc[-800]~-28822
--so, overflow on add if nBits or nLines > (10/72)[32767-28222]~631
mx ← micaXMin-xLeft;
micaRect.x1 ← IF micaXMin < xLeft THEN 0 ELSE mx;
mx ← mx+mmc[MagnifyBox.boxBitmap.nBits-1];
micaRect.x2 ← IF mx < 0 THEN micaWidth ELSE MIN[micaWidth,mx];
mx ← mdc[xLeft]-magXMin;
IF mx < 0 THEN micaRect.x1 ← MulDivCeiling[-mx,micasPerInch,MagnifyBitsPerInch];
my ← yTop - micaYMin;
micaRect.y1 ← MAX[0,my];
my ← my+mmc[MagnifyBox.boxBitmap.nLines-1];
micaRect.y2 ← IF my < 0 THEN micaHeight ELSE MIN[micaHeight,my];
my ← (magScreenHeight-mdc[yTop])-magYMin;
IF my < 0 THEN micaRect.y1 ← MulDivCeiling[-my,micasPerInch,MagnifyBitsPerInch];

SELECT e.Object.command FROM
PressDefs.ELShowObject,
PressDefs.ELShowCharacters =>
DefaultMagnify[];
PressDefs.ELShowRectangle =>
BEGIN
x1,y1,x2,y2: INTEGER;

x1 ← mx+mdc[micaRect.x1];
x2 ← mx+mdc[micaRect.x2];
y1 ← my+mdc[micaRect.y1];
y2 ← my+mdc[micaRect.y2];

IF b.type = gray THEN
BEGIN
GraphicsDefs.SetGrayLevel[b.gray];
GraphicsDefs.ReplaceGray[x1,y1,x2,y2,@MagnifyBox.boxBitmap];
END
ELSE GraphicsDefs.ReplaceArea[x1,y1,x2,y2,@MagnifyBox.boxBitmap];
IF i >= MagnifySelectionIndex THEN
BEGIN
GraphicsDefs.SetGrayLevel[selectGray];
GraphicsDefs.XorGray[x1,y1,x2,y2,@MagnifyBox.boxBitmap];
END;
END;
PressDefs.ELShowDots,PressDefs.ELShowDotsOpaque=>
BEGIN
do: POINTER TO StrawDefs.DotObject ← LOOPHOLE[e];
pdd: POINTER TO PressDefs.PressDotsData ← do.DotsData;

IF pdd.nBitsPerPixel # 8 OR pdd.fileName # NIL THEN
BEGIN
DefaultMagnify[];
END
ELSE
BEGIN
sampleVec: ARRAY [0..1000] OF CARDINAL;
pixelRect: GraphicsDefs.Rectangle;
bMode: CARDINAL ← pdd.mode/4;
sMode: CARDINAL ← pdd.mode MOD 4;
normal: BOOLEAN = sMode IN [2..3];
xp,yp,xs,ys: CARDINAL;
pmx: PROCEDURE [p: CARDINAL] RETURNS [m: CARDINAL] = INLINE
BEGIN RETURN [PressDefs.MulDiv[p-xs,pdd.micaWidth,xp]];END;
pmy: PROCEDURE [p: CARDINAL] RETURNS [m: CARDINAL] = INLINE
BEGIN RETURN [PressDefs.MulDiv[p-ys,pdd.micaHeight,yp]];END;
--Micas to Pixels
mpx: PROCEDURE [m: CARDINAL] RETURNS [p: CARDINAL] = INLINE
BEGIN RETURN [PressDefs.MulDiv[m,xp,pdd.micaWidth]+xs];END;
mpy: PROCEDURE [m: CARDINAL] RETURNS [p: CARDINAL] = INLINE
BEGIN RETURN [PressDefs.MulDiv[m,yp,pdd.micaHeight]+ys];END;
--Round up Micas to Pixels
rmpx: PROCEDURE [m: CARDINAL] RETURNS [p: CARDINAL] = INLINE
BEGIN RETURN [MulDivCeiling[m,xp,pdd.micaWidth]+xs];END;
rmpy: PROCEDURE [m: CARDINAL] RETURNS [p: CARDINAL] = INLINE
BEGIN RETURN [MulDivCeiling[m,yp,pdd.micaHeight]+ys];END;

IF normal THEN
BEGIN
xp ← pdd.displayPixels;yp ← pdd.displayLines;
xs ← IF bMode IN [1..2]
THEN pdd.nPixels-(pdd.passPixels+pdd.displayPixels)
ELSE pdd.passPixels;
ys ← IF sMode IN [1..2]
THEN pdd.nLines-(pdd.passLines+pdd.displayLines)
ELSE pdd.passLines;
END
ELSE
BEGIN
yp ← pdd.displayPixels;xp ← pdd.displayLines;
ys ← IF bMode IN [1..2]
THEN pdd.nPixels-(pdd.passPixels+pdd.displayPixels)
ELSE pdd.passPixels;
xs ← IF sMode IN [1..2]
THEN pdd.nLines-(pdd.passLines+pdd.displayLines)
ELSE pdd.passLines;
END;

--calculate SOURCE rectangle in pixels

pixelRect.x1 ← rmpx[micaRect.x1]; --round up
pixelRect.x2 ← mpx[micaRect.x2]; --don’t include this pixel
pixelRect.y1 ← rmpy[micaRect.y1]; --round up
pixelRect.y2 ← mpy[micaRect.y2]; --don’t include this pixel

--and fix up mica rect to lie on real pixel boundaries
micaRect.x1 ← pmx[pixelRect.x1]; --coord of left edge of pixel x1
micaRect.x2 ← pmx[pixelRect.x2]; --coord of right edge of pixel x2-1
micaRect.y1 ← pmy[pixelRect.y1]; --coord of top edge of pixel y1
micaRect.y2 ← pmy[pixelRect.y2]; --coord of bottom edge of pixel y2-1

destRect.x1 ← mx+mdc[micaRect.x1];
destRect.x2 ← mx+mdc[micaRect.x2];
destRect.y1 ← my+mdc[micaRect.y1];
destRect.y2 ← my+mdc[micaRect.y2];
IF (destRect.x1<0) OR (destRect.y1<0) THEN ERROR;

IF pixelRect.x1 < pixelRect.x2 AND
pixelRect.y1 < pixelRect.y2 THEN
BEGIN
dp: DiscoDefs.DiskPosition ← pdd.diskPosition;
IF pdd.opaque THEN GraphicsDefs.EraseArea[destRect.x1,destRect.y1,
destRect.x2-1,destRect.y2-1,@MagnifyBox.boxBitmap];
IF normal THEN
HalftoneDefs.InitHalftone[destRect.x1,destRect.y1,
pixelRect.x2-pixelRect.x1,destRect.x2-destRect.x1,
pdd.min,pdd.max,@MagnifyBox.boxBitmap,
pixelRect.y2-pixelRect.y1,destRect.y2-destRect.y1,pdd.mode]
ELSE HalftoneDefs.InitHalftone[destRect.x1,destRect.y1,
pixelRect.y2-pixelRect.y1,destRect.y2-destRect.y1,
pdd.min,pdd.max,@MagnifyBox.boxBitmap,
pixelRect.x2-pixelRect.x1,destRect.x2-destRect.x1,pdd.mode];

SELECT sMode FROM
0=>THROUGH [0..pixelRect.x1) DO
DiscoDefs.TransferBytes[dp:@dp,
data:NIL,nBytes: pdd.nPixels];
ENDLOOP;
1=>THROUGH [CARDINAL[pixelRect.x2]..pdd.nLines) DO
DiscoDefs.TransferBytes[dp:@dp,
data:NIL,nBytes: pdd.nPixels];
ENDLOOP;
2=>THROUGH [CARDINAL[pixelRect.y2]..pdd.nLines) DO
DiscoDefs.TransferBytes[dp:@dp,
data:NIL,nBytes: pdd.nPixels];
ENDLOOP;
ENDCASE=>THROUGH [0..pixelRect.y1) DO
DiscoDefs.TransferBytes[dp:@dp,
data:NIL,nBytes: pdd.nPixels];
ENDLOOP;
DiscoDefs.TransferBytes[dp:@dp,
data:NIL,nBytes: SELECT bMode FROM
0=> pixelRect.x1,
1=> pdd.nPixels-pixelRect.x2,
2=> pdd.nPixels-pixelRect.y2,
ENDCASE=> pixelRect.y1];

IF normal THEN THROUGH [pixelRect.y1..pixelRect.y2) DO
DiscoDefs.TransferBytes[dp:@dp,
data:LOOPHOLE[@sampleVec],nBytes: pdd.nPixels];
[] ← HalftoneDefs.PrintHalftoneLine[@sampleVec];
ENDLOOP
ELSE THROUGH [pixelRect.x1..pixelRect.x2) DO
DiscoDefs.TransferBytes[dp:@dp,
data:LOOPHOLE[@sampleVec],nBytes: pdd.nPixels];
[] ← HalftoneDefs.PrintHalftoneLine[@sampleVec];
ENDLOOP;
END;
IF i >= MagnifySelectionIndex THEN
BEGIN
GraphicsDefs.SetGrayLevel[selectGray];
GraphicsDefs.XorGray[destRect.x1,destRect.y1,
destRect.x2,destRect.y2,@MagnifyBox.boxBitmap];
END;
END;
END; --end of ShowDots
ENDCASE => ERROR; --unknown display type encountered;
ENDLOOP;

bm ← @MagnifyBox.boxBitmap;
GraphicsDefs.ReplaceArea[0,0,0,MagnifyHeight,bm];
GraphicsDefs.ReplaceArea[0,MagnifyHeight,MagnifyWidth,MagnifyHeight,bm];
GraphicsDefs.ReplaceArea[MagnifyWidth,MagnifyHeight,MagnifyWidth,0,bm];
GraphicsDefs.ReplaceArea[MagnifyWidth,0,0,0,bm];
GraphicsDefs.RemoveBox[@AdjustBox];
GraphicsDefs.MoveBox[@MagnifyBox,MagnifyX-MagnifyWidth/2,
MagnifyY-MagnifyHeight/2];
GraphicsDefs.DisplayBox[@AdjustBox,MagnifyX-MagnifyWidth/2,
MIN[AdjustBox.displayBitmap.nLines-AdjustBox.boxBitmap.nLines-1,
MagnifyY+MagnifyHeight/2]];
END;

StopMagnifier: PUBLIC PROCEDURE =
BEGIN
GraphicsDefs.RemoveBox[@AdjustBox];
GraphicsDefs.ReleaseBox[@AdjustBox];
GraphicsDefs.DestroyBox[@AdjustBox,FALSE];
GraphicsDefs.RemoveBox[@MagnifyBox];
GraphicsDefs.ReleaseBox[@MagnifyBox];
GraphicsDefs.DestroyBox[@MagnifyBox,FALSE];
IF MagnifyList # NIL THEN SystemDefs.FreeSegment[MagnifyList];
MagnifyList ← NIL;
MagnifyListCount ← 0;
MagnifyListMax ← 0;
END;

SetMagnification: PUBLIC PROCEDURE [bitsPerInch: CARDINAL] =
BEGIN
MagnifyBitsPerInch ← bitsPerInch;
END;

--display coord: micas to bits
dc
: PROCEDURE [m: Mica] RETURNS [INTEGER] = INLINE
BEGIN
RETURN[PressDefs.MulDiv[m,bitsPerInch,micasPerInch]];
END;
--with rounding
dcr
: PROCEDURE [m: Mica] RETURNS [INTEGER] = INLINE
BEGIN
RETURN[MulDivCeiling[m,bitsPerInch,micasPerInch]];
END;

--magnified display coord: micas to magnified bits
mdc
: PROCEDURE [m: Mica] RETURNS [INTEGER] = INLINE
BEGIN
RETURN[PressDefs.SignedMulDiv[m,MagnifyBitsPerInch,micasPerInch]];
END;
--mica coord: bits to micas
mc
: PROCEDURE [c: CARDINAL] RETURNS [Mica] = INLINE
BEGIN
RETURN[
PressDefs.SignedMulDiv[c,micasPerInch,bitsPerInch]];
END;
mcr: PROCEDURE [c: CARDINAL] RETURNS [Mica] = INLINE
BEGIN
RETURN[MulDivCeiling[c,micasPerInch,bitsPerInch]];
END;
--magnified mica coord: magnified bits to micas
mmc
: PROCEDURE [c: CARDINAL] RETURNS [Mica] = INLINE
BEGIN
RETURN[
PressDefs.MulDiv[c,micasPerInch,MagnifyBitsPerInch]];
END;
--magnified: bits to magnified bits
m
: PROCEDURE [c: INTEGER] RETURNS [INTEGER] = INLINE
BEGIN
RETURN [PressDefs.SignedMulDiv[c,MagnifyBitsPerInch,bitsPerInch]];
END;

SetMagnifierPosition: PUBLIC PROCEDURE [x,y: Mica] =
BEGIN
MagnifyX ← dc[x];
MagnifyY ← dc[y];
END;

SetMagnifierSize: PUBLIC PROCEDURE [width,height: CARDINAL] =
BEGIN
MagnifyWidth ← width;
MagnifyHeight ← height;
END;

MagToScreenCoords: PUBLIC PROCEDURE[x,y: CARDINAL] RETURNS[rx,ry: CARDINAL] =
BEGIN
mbpi: CARDINAL = MagnifyBitsPerInch;
bpi: CARDINAL = bitsPerInch;
IF (NOT DisplayListDefs.Inside[x,y,@AdjustBox]) AND
DisplayListDefs.Inside[x,y,@MagnifyBox] THEN
RETURN[MagnifyX+PressDefs.SignedMulDiv[x-MagnifyX,bpi,mbpi],
MagnifyY+PressDefs.SignedMulDiv[y-MagnifyY,bpi,mbpi]];
RETURN[x,y];
END;

MagToMicaCoords: PUBLIC PROCEDURE[x,y: CARDINAL] RETURNS[rx,ry: Mica] =
BEGIN OPEN PressDefs;
bpi: CARDINAL = bitsPerInch;
mbpi: CARDINAL = MagnifyBitsPerInch;
mpi: CARDINAL = micasPerInch;
IF (NOT DisplayListDefs.Inside[x,y,@AdjustBox]) AND
DisplayListDefs.Inside[x,y,@MagnifyBox] THEN
RETURN[MulDiv[MagnifyX,mpi,bpi]+SignedMulDiv[x-MagnifyX,mpi,mbpi],
MulDiv[MagnifyY,mpi,bpi]+SignedMulDiv[y-MagnifyY,mpi,mbpi]]
ELSE RETURN[MulDiv[x,mpi,bpi],MulDiv[y,mpi,bpi]];
END;


END.