-- ColorCursorImpl.mesa
-- Last changed by Maureen Stone, June 9, 1982 4:47 pm
DIRECTORY
ColorDisplay USING[width,height,curmode, Coordinate, CursorArray, Mode, CursorMode, disconnected, baseA, wplA, baseB, wplB],
DriverStartChain USING [Start],
BitBlt USING [BBTableSpace, BitBltTablePtr, AlignedBBTable, SrcFunc, DstFunc, BITBLT, BitAddress],
ColorDisplayFace USING [displayType],
SpecialSpace USING [MakeResident],
Space USING[Create, defaultBase, virtualMemory, Handle, Map, nullHandle,defaultWindow,LongPointer];
ColorCursorImpl: MONITOR
IMPORTS SpecialSpace, Space, BitBlt, ColorDisplay, ColorDisplayFace, OtherDrivers: DriverStartChain
EXPORTS DriverStartChain, ColorDisplay = {
OPEN ColorDisplay;
--like UserTerminal.mesa
cursorPosition: PUBLIC LONG POINTER TO Coordinate=@currentCursor;
currentCursor: Coordinate;
cursorWidth: PUBLIC INTEGER←16; --defined as 16 for now
cursorHeight: PUBLIC INTEGER←16; --defined as 16 for now
template: CursorArray ← ALL[0];
bbspace: BitBlt.BBTableSpace;
bb: BitBlt.BitBltTablePtr ← BitBlt.AlignedBBTable[@bbspace];
space: Space.Handle ← Space.nullHandle;
sourceA: LONG POINTER ← NIL;
backupA: LONG POINTER ← NIL;
sourceB: LONG POINTER ← NIL;
backupB: LONG POINTER ← NIL;
wplSrcA: CARDINAL = 16;
wplSrcB: CARDINAL = 8;
ppw,bpp: CARDINAL;
srcfunc: BitBlt.SrcFunc ← complement;
dstfunc: BitBlt.DstFunc ← and;
xMax,yMax: INTEGER ← 0;
bltX,bltY: INT ← 0;
bltW,bltH: CARDINAL ← 0;
setupMode: Mode ← disconnected;
validBackup: BOOLEAN ← FALSE;
lock: BOOLEAN ← FALSE;
NotifyCursor: PUBLIC ENTRY PROC = {Setup[]};
SetCursorMode: PUBLIC ENTRY PROC [mode: CursorMode] = {
IF mode = zeros THEN {srcfunc ← complement; dstfunc ← and}
ELSE {srcfunc ← null; dstfunc ← or};
IF curmode=disconnected THEN RETURN;
SetCursorInternal[cursorPosition↑];
};
SetCursorPattern: PUBLIC ENTRY PROC [cursorPattern: CursorArray] = {
template ← cursorPattern;
Setup[];
};
GetCursorPattern: PUBLIC ENTRY PROCEDURE RETURNS [cursorPattern: CursorArray] = {
RETURN[template];
};
SetCursorPosition: PUBLIC ENTRY PROCEDURE [newMousePosition: Coordinate] = {
IF curmode=disconnected THEN RETURN;
IF newMousePosition=cursorPosition↑ THEN RETURN; --will not display unless mouse has moved
SetCursorInternal[newMousePosition];
};
SetCursorInternal: INTERNAL PROCEDURE [newMousePosition: Coordinate] = {
x: INTEGER ← newMousePosition.x;
y: INTEGER ← newMousePosition.y;
xoff,yoff: INTEGER ← 0;
HideInternal[]; --restore the display
cursorPosition↑ ← newMousePosition;
IF lock THEN RETURN; --cursor is locked during a scanline write
IF x<=-cursorWidth OR y<=-cursorHeight OR x>xMax OR y>yMax THEN RETURN; --way off the screen
bltX ←x; bltY ← y;
bltW ← cursorWidth; bltH ← cursorHeight;
IF x<0 THEN {xoff ← ABS[x]; bltW ← cursorWidth-xoff; bltX ← 0};
IF y<0 THEN {yoff ← ABS[y]; bltH ← cursorHeight-yoff; bltY ← 0};
IF x>xMax-cursorWidth THEN bltW ← xMax-x;
IF y>yMax-cursorWidth THEN bltH ← yMax-y;
bb.flags.srcFunc ← null;
bb.flags.dstFunc ← null;
ToA[backupA]; --save the bits under the cursor
IF curmode.full THEN ToB[backupB]; --save the bits under the cursor
validBackup ← TRUE;
bb.flags.srcFunc ← srcfunc;
bb.flags.dstFunc ← dstfunc;
FromA[sourceA,xoff,yoff]; --Put the cursor in
IF curmode.full THEN
FromB[sourceB,xoff,yoff]; --Put the cursor in
};
HideCursor: PUBLIC ENTRY PROC = {
IF curmode=disconnected THEN RETURN;
HideInternal[];
};
HideInternal: INTERNAL PROC = {
IF ~validBackup THEN RETURN;
validBackup ← FALSE; --conventional to invalidate the backup cache
bb.flags.srcFunc ← null;
bb.flags.dstFunc ← null;
FromA[backupA]; --restore the bits under the cursor
IF curmode.full THEN FromB[backupB];
};
RestoreCursor: PUBLIC ENTRY PROC = {
--assume if the backup cache is valid, the cursor is actually already showing
IF curmode=disconnected THEN RETURN;
IF ~validBackup THEN SetCursorInternal[cursorPosition↑];
};
SetLock: PUBLIC ENTRY PROC = {lock ← TRUE};
ClearLock: PUBLIC ENTRY PROC = {lock ← FALSE};
FromA: INTERNAL PROC [buffer: LONG POINTER, xoff,yoff: CARDINAL ← 0] = INLINE {
bb.dst.word ← baseA + bltY*wplA + bltX/ppw;
bb.dst.bit ← (bltX MOD ppw)*bpp;
bb.dstBpl ← wplA*16;
bb.src.word ← buffer + yoff*wplSrcA + xoff/ppw;
bb.src.bit ← (xoff MOD ppw)*bpp;
bb.srcDesc.srcBpl ← wplSrcA*16;
bb.width ← bltW*bpp;
bb.height ← bltH;
BitBlt.BITBLT[bb]; --from an A Buffer to the framebuffer
};
ToA: INTERNAL PROC [buffer: LONG POINTER] = INLINE {
bb.dst ← [word: buffer, bit: 0];
bb.dstBpl ← wplSrcA*16;
bb.src.word ← baseA + bltY*wplA + bltX/ppw;
bb.src.bit ← (bltX MOD ppw)*bpp;
bb.srcDesc.srcBpl ← wplA*16;
bb.width ← bltW*bpp;
bb.height ← bltH;
BitBlt.BITBLT[bb]; --from the framebuffer to an A buffer
};
FromB: INTERNAL PROC [buffer: LONG POINTER, xoff,yoff: CARDINAL ← 0] = INLINE {
bb.dst.word ← baseB + bltY*wplB + bltX/2;
bb.dst.bit ← (bltX MOD 2)*8;
bb.dstBpl ← wplB*16;
bb.src.word ← buffer + yoff*wplSrcB + xoff/2;
bb.src.bit ← (xoff MOD 2)*8;
bb.srcDesc.srcBpl ← wplSrcB*16;
bb.width ← bltW*8;
bb.height ← bltH;
BitBlt.BITBLT[bb]; --from a B buffer to the framebuffer
};
ToB: INTERNAL PROC [buffer: LONG POINTER] = INLINE {
bb.src.word ← baseB + bltY*wplB + bltX/2;
bb.src.bit ← (bltX MOD 2)*8;
bb.srcDesc.srcBpl ← wplB*16;
bb.dst ← [word: buffer, bit: 0];
bb.dstBpl ← wplSrcB*16;
bb.width ← bltW*8;
bb.height ← bltH;
BitBlt.BITBLT[bb]; --from the framebuffer to a B buffer
};
Setup: INTERNAL PROC = {
IF curmode=disconnected THEN RETURN;
HideInternal[];
xMax ← ColorDisplay.width;
yMax ← ColorDisplay.height;
setupMode ← curmode;
IF curmode.full THEN {
bpp ← 8; ppw ← 2;
ExpandBitmap[sourceB,wplSrcB];
bpp ← 16; ppw ← 1;
}
ELSE {bpp ← curmode.bitsPerPixelA; ppw ← 16/bpp};
--need to convert the 1 bit/pixel template to a bpp source
ExpandBitmap[sourceA,wplSrcA];
validBackup ← FALSE; --invalidate the caches
};
ExpandBitmap: INTERNAL PROC [buffer: LONG POINTER, wpl: CARDINAL] = {
bb.src.word ← BASE[template];
bb.src.bit ← 0;
bb.srcDesc.srcBpl ← 16;
bb.dst.word ← buffer;
bb.dst.bit ← 0;
bb.dstBpl ← wpl*16;
bb.width ← 1;
bb.height ← 16;
bb.flags.srcFunc ← null;
bb.flags.dstFunc ← null;
FOR i: NAT IN [0..16) DO
FOR j: NAT IN [0..bpp) DO
BitBlt.BITBLT[bb]; --write one column
bb.dst ← AddOne[bb.dst];
ENDLOOP;
bb.src ← AddOne[bb.src];
ENDLOOP;
};
AddOne: INTERNAL PROC[address: BitBlt.BitAddress] RETURNS[BitBlt.BitAddress] = {
IF address.bit<15 THEN address.bit ← address.bit+1
ELSE {address.bit ← 0; address.word ← address.word+1};
RETURN[address];
};
Init: PROC = {
space ← Space.Create[size: 3, parent: Space.virtualMemory, base: Space.defaultBase];
Space.Map[space: space, window: Space.defaultWindow];
SpecialSpace.MakeResident[space];
sourceA ← Space.LongPointer[space]; --page 1
backupA ← sourceA+256; --page 2
sourceB ← backupA+256; --first half of page 3
backupB ← sourceB+128; --second half of page 3
bb↑ ← [dst: [word: NIL, bit: 0], dstBpl: 0, src: [word: NIL, bit: 0],
srcDesc: [srcBpl[0]], width: 0, height: 16,
flags: [disjoint: TRUE, gray: FALSE, srcFunc: complement, dstFunc: and]];
};
Start: PUBLIC PROCEDURE = {OtherDrivers.Start[]};
IF ColorDisplayFace.displayType#0 THEN Init[];
}.