-- 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[]; }.