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