134 lines
3.1 KiB
C
134 lines
3.1 KiB
C
|
#include "u.h"
|
||
|
#include "../port/lib.h"
|
||
|
#include "mem.h"
|
||
|
#include "dat.h"
|
||
|
#include "fns.h"
|
||
|
#include "../port/error.h"
|
||
|
|
||
|
#define Image IMAGE
|
||
|
#include <draw.h>
|
||
|
#include <memdraw.h>
|
||
|
#include <cursor.h>
|
||
|
#include "screen.h"
|
||
|
|
||
|
extern Memimage* gscreen;
|
||
|
|
||
|
/*
|
||
|
* Software cursor.
|
||
|
*/
|
||
|
static Memimage* swback; /* screen under cursor */
|
||
|
static Memimage* swimg; /* cursor image */
|
||
|
static Memimage* swmask; /* cursor mask */
|
||
|
static Memimage* swimg1;
|
||
|
static Memimage* swmask1;
|
||
|
|
||
|
static Point swoffset;
|
||
|
static Rectangle swrect; /* screen rectangle in swback */
|
||
|
static Point swvispt; /* actual cursor location */
|
||
|
static int swvisible; /* is the cursor visible? */
|
||
|
|
||
|
/*
|
||
|
* called with drawlock locked for us, most of the time.
|
||
|
* kernel prints at inopportune times might mean we don't
|
||
|
* hold the lock, but memimagedraw is now reentrant so
|
||
|
* that should be okay: worst case we get cursor droppings.
|
||
|
*/
|
||
|
void
|
||
|
swcursorhide(void)
|
||
|
{
|
||
|
if(swvisible == 0)
|
||
|
return;
|
||
|
if(swback == nil || gscreen == nil)
|
||
|
return;
|
||
|
swvisible = 0;
|
||
|
memimagedraw(gscreen, swrect, swback, ZP, memopaque, ZP, S);
|
||
|
flushmemscreen(swrect);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
swcursoravoid(Rectangle r)
|
||
|
{
|
||
|
if(swvisible && rectXrect(r, swrect)){
|
||
|
swcursorhide();
|
||
|
mouseredraw(); /* schedule cursor redraw after we release drawlock */
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void
|
||
|
swcursordraw(Point p)
|
||
|
{
|
||
|
if(swvisible)
|
||
|
return;
|
||
|
if(swback == nil || swimg1 == nil || swmask1 == nil || gscreen == nil)
|
||
|
return;
|
||
|
assert(!canqlock(&drawlock));
|
||
|
swvispt = addpt(swoffset, p);
|
||
|
swrect = rectaddpt(Rect(0,0,16,16), swvispt);
|
||
|
memimagedraw(swback, swback->r, gscreen, swvispt, memopaque, ZP, S);
|
||
|
memimagedraw(gscreen, swrect, swimg1, ZP, swmask1, ZP, SoverD);
|
||
|
flushmemscreen(swrect);
|
||
|
swvisible = 1;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
swcursorload(Cursor *curs)
|
||
|
{
|
||
|
uchar *ip, *mp;
|
||
|
int i, j, set, clr;
|
||
|
|
||
|
if(swimg == nil || swmask == nil || swimg1 == nil || swmask1 == nil)
|
||
|
return;
|
||
|
/*
|
||
|
* Build cursor image and mask.
|
||
|
* Image is just the usual cursor image
|
||
|
* but mask is a transparent alpha mask.
|
||
|
*
|
||
|
* The 16x16x8 memimages do not have
|
||
|
* padding at the end of their scan lines.
|
||
|
*/
|
||
|
ip = byteaddr(swimg, ZP);
|
||
|
mp = byteaddr(swmask, ZP);
|
||
|
for(i=0; i<32; i++){
|
||
|
set = curs->set[i];
|
||
|
clr = curs->clr[i];
|
||
|
for(j=0x80; j; j>>=1){
|
||
|
*ip++ = set&j ? 0x00 : 0xFF;
|
||
|
*mp++ = (clr|set)&j ? 0xFF : 0x00;
|
||
|
}
|
||
|
}
|
||
|
swoffset = curs->offset;
|
||
|
memimagedraw(swimg1, swimg1->r, swimg, ZP, memopaque, ZP, S);
|
||
|
memimagedraw(swmask1, swmask1->r, swmask, ZP, memopaque, ZP, S);
|
||
|
|
||
|
mouseredraw();
|
||
|
}
|
||
|
|
||
|
void
|
||
|
swcursorinit(void)
|
||
|
{
|
||
|
if(gscreen == nil)
|
||
|
return;
|
||
|
|
||
|
if(swback){
|
||
|
freememimage(swback);
|
||
|
freememimage(swmask);
|
||
|
freememimage(swmask1);
|
||
|
freememimage(swimg);
|
||
|
freememimage(swimg1);
|
||
|
}
|
||
|
swback = allocmemimage(Rect(0,0,32,32), gscreen->chan);
|
||
|
swmask = allocmemimage(Rect(0,0,16,16), GREY8);
|
||
|
swmask1 = allocmemimage(Rect(0,0,16,16), GREY1);
|
||
|
swimg = allocmemimage(Rect(0,0,16,16), GREY8);
|
||
|
swimg1 = allocmemimage(Rect(0,0,16,16), GREY1);
|
||
|
if(swback == nil || swmask == nil || swmask1 == nil || swimg == nil || swimg1 == nil){
|
||
|
print("software cursor: allocmemimage fails\n");
|
||
|
return;
|
||
|
}
|
||
|
memfillcolor(swback, DTransparent);
|
||
|
memfillcolor(swmask, DOpaque);
|
||
|
memfillcolor(swmask1, DOpaque);
|
||
|
memfillcolor(swimg, DBlack);
|
||
|
memfillcolor(swimg1, DBlack);
|
||
|
}
|