Magnifier.mesa; Written by S. McGregor
Last Edited by: McGregor, July 18, 1983 9:17 am
Last Edited by: Beach, October 4, 1983 3:38 pm
DIRECTORY
BitBlt USING [AlignedBBTable, BITBLT, BBptr, BBTableSpace],
Buttons,
Cursors USING [SetCursor],
CGScreen USING [Bits],
Environment USING [BitAddress],
InputFocus,
Mopcodes,
Process,
TIPUser,
UserTerminal,
ViewerLocks USING [LockViewerTree, ReleaseViewerTree],
ViewerClasses,
ViewerSpecs USING [screenH, screenW];
Magnifier:
PROGRAM
IMPORTS BitBlt, Buttons, Cursors, CGScreen, InputFocus, Process, TIPUser, UserTerminal, ViewerLocks
SHARES ViewerLocks = BEGIN OPEN Mopcodes;
pMask: REF; -- pointer to mask bits (0 => opaque, 1 => transparent)
pImage: REF; -- pointer to image bits (0 => white, 1 => black)
pSaved: REF; -- pointer to screen bits (0 => white, 1 => black)
pRaster: CARDINAL; -- words per line
pWidth: CARDINAL; -- width in bits
pHeight: CARDINAL; -- height in lines
pX, pY: INTEGER; -- last position
lock: BOOL; -- viewer paints locked out
magnify: BOOL ← FALSE;
magX, magY, magW, magH: CARDINAL;
AllocateBitmap:
PROC [nWords:
CARDINAL]
RETURNS [
REF] =
INLINE
BEGIN
Words: TYPE = RECORD[SEQUENCE COMPUTED CARDINAL OF CARDINAL];
RETURN[NEW[Words[nWords]]];
END;
MagnifyRegion:
PROC [leftX, topY, widthInWords, height:
CARDINAL] =
BEGIN
magnify ← TRUE;
magX ← leftX;
magY ← topY;
magW ← widthInWords;
magH ← height;
END;
NewPicture:
PROC [mask:
REF, image:
REF, raster, width, height, screenX, screenY:
CARDINAL, lockPainting:
BOOL ←
TRUE] =
BEGIN
pMask ← mask;
pImage ← image;
pSaved ← AllocateBitmap[raster*height];
pRaster ← raster;
pWidth ← width;
pHeight ← height;
pX ← MIN[screenX, ViewerSpecs.screenW-width];
screenY ← ViewerSpecs.screenH-screenY; -- invert conversion
pY ← MIN[screenY, ViewerSpecs.screenH-height];
lock ← lockPainting;
ComputeScreenPoint[];
sfsp.dst ← [LOOPHOLE[pSaved],,0];
sfsp.dstBpl ← pRaster*16;
sfsp.width ← pWidth;
sfsp.height ← pHeight;
itsp.srcDesc.srcBpl ← pRaster*16;
itsp.width ← pWidth;
itsp.height ← pHeight;
Cursors.SetCursor[blank];
IF lock THEN ViewerLocks.LockViewerTree[];
BLTImageToScreen[];
END;
MovePicture:
PROC [screenX, screenY:
CARDINAL] =
BEGIN
BLTSavedToScreen[];
pX ← MIN[screenX, ViewerSpecs.screenW-pWidth];
screenY ← ViewerSpecs.screenH-screenY; -- invert conversion
pY ← MIN[screenY, ViewerSpecs.screenH-pHeight];
ComputeScreenPoint[];
BLTImageToScreen[];
END;
TakeDownPicture:
PROC =
BEGIN
BLTSavedToScreen[];
IF lock THEN ViewerLocks.ReleaseViewerTree[];
Cursors.SetCursor[textPointer];
pMask ← pImage ← pSaved ← NIL;
magnify ← FALSE;
END;
ComputeScreenPoint:
PROC =
INLINE
BEGIN
screenPoint.word ← screen + (LONG[pY]*(ViewerSpecs.screenW/16)) + (LONG[pX]/16);
screenPoint.bit ← pX MOD 16;
END;
screen: LONG POINTER ← CGScreen.Bits[].base;
screenPoint: Environment.BitAddress;
sfsTable, itsTable: BitBlt.BBTableSpace;
sfsp: BitBlt.BBptr ← BitBlt.AlignedBBTable[@sfsTable];
itsp: BitBlt.BBptr ← BitBlt.AlignedBBTable[@itsTable];
Pair: TYPE = ARRAY [0..1] OF CARDINAL;
PairPtr: TYPE = LONG POINTER TO Pair;
Get8:
PROC [ptr:
LONG
POINTER, start:
CARDINAL]
RETURNS [word:
CARDINAL] =
INLINE {
dist: INTEGER = CardinalAnd[start,15];
pp: PairPtr = LOOPHOLE[ptr, PairPtr] + start / 16;
RETURN [
CardinalOr[
CardinalShiftLeft[pp[0], dist],
CardinalShiftLeft[pp[1], dist-16]]
/ 256];
};
Put16:
PROC [ptr:
LONG
POINTER, start:
CARDINAL, word:
CARDINAL] =
INLINE {
dist: INTEGER = CardinalAnd[start,15];
pp: PairPtr = LOOPHOLE[ptr, PairPtr] + start / 16;
pp[0] ← CardinalOr[
CardinalShiftRight[word, dist],
CardinalAnd[pp[0], CardinalShiftLeft[177777B, 16-dist]]];
pp[1] ← CardinalOr[
CardinalShiftLeft[word, 16-dist],
CardinalAnd[pp[1], CardinalShiftRight[177777B, dist]]];
};
CardinalShiftLeft:
PROC
[word: CARDINAL, dist: INTEGER] RETURNS [CARDINAL] = MACHINE CODE {
Mopcodes.zSHIFT;
};
CardinalShiftRight:
PROC
[word: CARDINAL, dist: INTEGER] RETURNS [CARDINAL] = MACHINE CODE {
Mopcodes.zNEG;
Mopcodes.zSHIFT;
};
CardinalOr:
PROC [word1,word2:
CARDINAL]
RETURNS [
CARDINAL] =
MACHINE
CODE {
Mopcodes.zOR;
};
CardinalAnd:
PROC [word1,word2:
CARDINAL]
RETURNS [
CARDINAL] =
MACHINE
CODE {
Mopcodes.zAND;
};
BLTImageToScreen:
PROC =
BEGIN
itsp.dst ← sfsp.src ← screenPoint;
BitBlt.BITBLT[sfsp]; -- save screen
IF magnify
THEN
BEGIN
screenAdd: LONG CARDINAL ← (magY+magH/4)*pRaster + magX/16;
imageAdd: LONG CARDINAL ← magY*pRaster + magX/16;
fetchOffset: CARDINAL = magX+magW*16/4;
screen: LONG POINTER = LOOPHOLE[pSaved];
image: LONG POINTER = LOOPHOLE[pImage];
THROUGH [0..magH/2)
DO
FOR i:
CARDINAL
IN [0..magW)
DO
word: CARDINAL = twoPower[Get8[screen+screenAdd, fetchOffset+(8*i)]];
xOff: CARDINAL = magX+(16*i);
Put16[image+imageAdd, xOff, word];
Put16[image+imageAdd+pRaster, xOff, word];
ENDLOOP;
screenAdd ← screenAdd + pRaster;
imageAdd ← imageAdd + (2*pRaster);
ENDLOOP;
END;
IF pMask#
NIL
THEN
BEGIN
itsp.src ← [LOOPHOLE[pMask],,0];
itsp.flags.dstFunc ← and;
BitBlt.BITBLT[itsp];
itsp.flags.dstFunc ← or;
END;
itsp.src ← [LOOPHOLE[pImage],,0];
BitBlt.BITBLT[itsp];
itsp.flags.dstFunc ← null;
END;
BLTSavedToScreen:
PROC =
INLINE
BEGIN
itsp.dst ← screenPoint;
itsp.src ← [LOOPHOLE[pSaved],,0];
BitBlt.BITBLT[itsp];
END;
twoPower: ARRAY [0..256) OF CARDINAL;
BuildTwoPower:
PROC =
BEGIN
scan: INTEGER;
p: POINTER TO PACKED ARRAY [0..8) OF BOOL ← LOOPHOLE[@scan];
p2: POINTER TO PACKED ARRAY [0..16) OF BOOL ← LOOPHOLE[@twoPower];
FOR i:
INTEGER
IN [0..256)
DO
scan ← i;
FOR j:
INTEGER
IN [0..8)
DO
p2[j*2] ← p[j];
p2[j*2+1] ← p[j];
ENDLOOP;
p2 ← p2+1;
ENDLOOP;
END;
magnifier: REF ARRAY [0..256) OF UNSPECIFIED ← LOOPHOLE[AllocateBitmap[256]];
magnifier2: REF ARRAY [0..512) OF UNSPECIFIED ← LOOPHOLE[AllocateBitmap[512]];
Start: Buttons.ButtonProc =
TRUSTED
BEGIN
InputFocus.SetInputFocus[];
InputFocus.CaptureButtons[Notify, myTIPTable];
IF mouseButton#red
THEN
BEGIN
MagnifyRegion[1, 1, 7, 62];
NewPicture[NIL, magnifier2, 8, 114, 64, 300, 300];
END
ELSE
BEGIN
MagnifyRegion[1, 1, 3, 62];
NewPicture[NIL, magnifier, 4, 50, 64, 300, 300];
END;
Process.Detach[FORK DoIt[]];
END;
Notify: ViewerClasses.NotifyProc =
TRUSTED {};
-- NOP
myTIPTable: TIPUser.TIPTable ← TIPUser.InstantiateNewTIPTable["Magnifier.tip"]; -- Known NOP
fudge: CARDINAL ← 150; -- fudge for retrace synch
DoIt:
PROCEDURE =
BEGIN
mouseBitsRec:
TYPE =
MACHINE
DEPENDENT
RECORD [
-- mouse buttons are inverted
fill: [0..8192), red: BOOL, blue: BOOL, yellow: BOOL];
mouseP: LONG POINTER TO mouseBitsRec = LOOPHOLE[UserTerminal.keyboard];
mouse: UserTerminal.Coordinate;
Process.SetPriority[3];
UNTIL ~mouseP.red
DO
wait: CARDINAL;
UserTerminal.WaitForScanLine[
SELECT wait ← pY+fudge
FROM
>808 => 0,
ENDCASE => wait];
IF UserTerminal.cursor^ # mouse
THEN
BEGIN
mouse ← UserTerminal.cursor^;
MovePicture[mouse.x, 808-mouse.y];
END;
ENDLOOP;
TakeDownPicture[];
InputFocus.ReleaseButtons[];
END;
sfsp.flags.disjoint ← TRUE;
sfsp.flags.disjointItems ← TRUE;
sfsp.srcDesc.srcBpl ← ViewerSpecs.screenW;
itsp.flags.disjoint ← TRUE;
itsp.flags.disjointItems ← TRUE;
itsp.dstBpl ← ViewerSpecs.screenW;
BuildTwoPower[];
magnifier[0] ← magnifier[1] ← magnifier[2] ← 177777B;
magnifier[252] ← magnifier[253] ← magnifier[254] ← 177777B;
magnifier[3] ← 140000B;
magnifier[255] ← 140000B;
FOR i:
INTEGER
IN [0..248/4)
DO
magnifier[i*4+4] ← 100000B;
magnifier[i*4+7] ← 040000B;
ENDLOOP;
FOR i:
INTEGER
IN [0..6]
DO
magnifier2[i] ← 177777B;
magnifier2[i+504] ← 177777B;
ENDLOOP;
magnifier2[7] ← magnifier2[511] ← 140000B;
FOR i:
INTEGER
IN [0..62)
DO
magnifier2[i*8+8] ← 100000B;
magnifier2[i*8+15] ← 040000B;
ENDLOOP;
[] ← Buttons.Create[[name: "Magnifier"], Start];
END.