4.4BSD/usr/src/contrib/X11R5-hp300/mit/server/ddx/hpbsd/hpcursor.c

Compare this file to the similar file:
Show the results in this format:

/* $XConsortium: hpcursor.c,v 1.5 88/09/06 15:26:07 jim Exp $ */
/*
 * hpcursor.c : hp soft cursor routines
 * C Durland, C Amacher
 */

/*
Copyright (c) 1986, 1987 by Hewlett-Packard Company
Copyright (c) 1986, 1987 by the Massachusetts Institute of Technology

Permission to use, copy, modify, and distribute this
software and its documentation for any purpose and without
fee is hereby granted, provided that the above copyright
notice appear in all copies and that both that copyright
notice and this permission notice appear in supporting
documentation, and that the name of M.I.T. not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.

HEWLETT-PACKARD MAKES NO WARRANTY OF ANY KIND WITH REGARD
TO THIS SOFWARE, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
PURPOSE.  Hewlett-Packard shall not be liable for errors 
contained herein or direct, indirect, special, incidental or 
consequential damages in connection with the furnishing, 
performance, or use of this material.

This software is not subject to any license of the American
Telephone and Telegraph Company or of the Regents of the
University of California.
*/

#define NEED_EVENTS	/* hack hack hack */

#include <stdio.h>
#include "X.h"
#include "Xproto.h"
#include "servermd.h"
#include "scrnintstr.h"
#include "cursorstr.h"
#include "hppriv.h"
#include "resource.h"
#include "inputstr.h"
#include "hpext.h"
#include "hildef.h"
#include "XHPproto.h"

extern int lastEventTime;
extern HPInputDevice *hpPointer;

#define MAXCX 64	/* max cursor rectangle width */
#define MAXCY 64	/* max cursor rectangle height */

static Bool	hpRealizeCursor(), hpUnrealizeCursor(), hpDisplayCursor();
static void	hpPointerNonInterestBox(), hpRecolorCursor();

extern Bool	hpSetCursorPosition();
extern void	hpCursorLimits(), hpConstrainCursor();

#ifdef XTESTEXT1
/*
 * defined in xtestext1di.c
 */
extern int	on_steal_input;
/*
 * defined in xtestext1di.c
 */
extern short	xtest_mousex;
/*
 * defined in xtestext1di.c
 */
extern short	xtest_mousey;
#endif /* XTESTEXT1 */

	/* restore screen from off screen mem */
static void
hpCursorOff(pScreen)
     ScreenPtr pScreen;
{
    register hpPrivScreenPtr cfb = getPrivScreenPtr(pScreen);

    if (cfb->cstate == CURSOR_OFF) return;

    cfb->cstate = CURSOR_OFF;
    (*cfb->MoveBits)(pScreen, ~0, GXcopy,
		     cfb->ssaveX,cfb->ssaveY,
		     cfb->saved.x1,cfb->saved.y1, cfb->w,cfb->h);
}

	/* copy area cursor covers to off screen mem, copy cursor to screen */
static void
hpCursorOn(pScreen, dx, dy)
     ScreenPtr pScreen;
     register int dx, dy;	/* the cursor hot spot */
{
    register hpPrivScreenPtr cfb = getPrivScreenPtr(pScreen);
    register int
	srcx = cfb->srcX, srcy = cfb->srcY,
	maskx = cfb->maskX, masky = cfb->maskY,
	w, h;

    if (cfb->cstate == CURSOR_ON) return; /* else cursor is offscreen */

    dx -= cfb->hoffX; dy -= cfb->hoffY;	/* hotspot to upper left corner */
		/* clip cursor rectangle */
    w = min(cfb->width,  pScreen->width -dx);
    h = min(cfb->height, pScreen->height -dy);
    if (dx<0) { srcx -= dx; maskx -= dx; w += dx; dx = 0; }
    if (dy<0) { srcy -= dy; masky -= dy; h += dy; dy = 0; }

    (*cfb->MoveBits)(pScreen, ~0, GXcopy,	/* save screen area */
		     dx,dy, cfb->ssaveX,cfb->ssaveY, w,h);
    cfb->saved.x1 = dx; cfb->saved.y1 = dy;
    cfb->saved.x2 = dx + w; cfb->saved.y2 = dy + h;
    cfb->w = w; cfb->h = h;

	/* mask out cursor shape, put cursor in hole */
    (*cfb->MoveBits)(pScreen, ~0, GXand, maskx,masky, dx,dy, w,h);
    (*cfb->MoveBits)(pScreen, ~0, GXor, srcx,srcy, dx,dy, w,h);

    cfb->cstate = CURSOR_ON;	/* cursor is on screen */
}

	/* move screen cursor hotspot to (hotX,hotY) from wherever it is */
static void
hpMoveMouse(pScreen, hotX,hotY, forceit)
     ScreenPtr pScreen; 
     register int hotX, hotY;
     int forceit;
{
#ifdef XTESTEXT1
    if (on_steal_input)
    {
	/*
	 * only call if the mouse position has actually moved
	 */
	if ((hotX != xtest_mousex) || (hotY != xtest_mousey))
	{
	    XTestStealMotionData((hotX - xtest_mousex),
				 (hotY - xtest_mousey),
				 MOUSE,
				 xtest_mousex,
				 xtest_mousey);
	}
    }
#endif /* XTESTEXT1 */

    if (forceit)
	hpCursorOff(pScreen);
    if (0<=hotX && 0<=hotY && hotX<pScreen->width && hotY<pScreen->height)
	hpCursorOn(pScreen, hotX,hotY);
}

extern void hpSpriteFindColors();

#define tcXY(x,y) /* address of offscreen mem */ \
	(unsigned char *)(cfb->bits +(y)*cfb->stride +(x))

static Bool
hpDisplayCursor(pScreen,pCursor)
     ScreenPtr pScreen;
     CursorPtr pCursor;
{
    register hpPrivScreenPtr cfb = getPrivScreenPtr(pScreen);
    register unsigned char *ctr, *mtr, *ptr, *qtr, z, startbit;
    register short int x,y, w,h;
    int xstart, ystart;
    Pixel fgcolor, bgcolor;

    w = pCursor->bits->width;
    h = pCursor->bits->height;
	/* scale cursor if bigger than max */
    cfb->width = min(w,MAXCX); cfb->height = min(h,MAXCY);
    xstart = (w<=MAXCX) ?
	0 : pCursor->bits->xhot - MAXCX + ((w - pCursor->bits->xhot)*MAXCX)/w;
    startbit = 0x80>>(xstart%8);
    cfb->hoffX = pCursor->bits->xhot - xstart;
    xstart /= 8;
    ystart = (h<=MAXCY) ?
	0 : pCursor->bits->yhot - MAXCY + ((h - pCursor->bits->yhot)*MAXCY)/h;
    cfb->hoffY = pCursor->bits->yhot - ystart;

	/* convert colors to display specific colors */
    hpSpriteFindColors(pScreen, pCursor, &fgcolor, &bgcolor);
    SET_REGISTERS_FOR_WRITING(pScreen,~0,GXcopy);	  /* setup hardware */
	/* bytes in each row of pixmaps (including padding) */
    w = (w+BITMAP_SCANLINE_PAD-1)/BITMAP_SCANLINE_PAD*(BITMAP_SCANLINE_PAD/8);
    for (y=0; y<cfb->height; y++)
    {
	ptr = pCursor->bits->source + w*(ystart+y) + xstart;
	qtr = pCursor->bits->mask + w*(ystart+y) + xstart;
	ctr = tcXY(cfb->srcX, y+cfb->srcY); /* address of offscreen cursor */
	mtr = tcXY(cfb->maskX,y+cfb->maskY); /* address of offscreen cursor mask */
	for (z = startbit, x=0; x<cfb->width; x++)
	{
	    /* cursor mask: all planes = xor(or(all planes)) */
	    *mtr++ = (*qtr & z) ? 0 : 0xFF;
	    /* squeeze cursor through mask */
	    *ctr++ = (*qtr & z) ? ((*ptr & z) ? fgcolor : bgcolor) : 0;
	    if ((z>>=1)==0)
	    {
		z = 0x80; ptr++; qtr++;
	    }
	}
    }
    hpMoveMouse(pScreen, hpPointer->coords[0],hpPointer->coords[1], 1);
    return TRUE;
}

static Bool
hpmDisplayCursor(pScreen,pCursor)
     ScreenPtr pScreen;
     CursorPtr pCursor;
{
    register hpPrivScreenPtr cfb = getPrivScreenPtr(pScreen);
    register unsigned char *ctr, *mtr, *ptr, *qtr, z, z1, startbit;
    register short int x,y, w,h;
    int xstart, ystart;
    Pixel fgcolor, bgcolor;

    w = pCursor->bits->width;
    h = pCursor->bits->height;
	/* scale cursor if bigger than max */
    cfb->width = min(w,MAXCX); cfb->height = min(h,MAXCY);
    xstart = (w<=MAXCX) ?
	0 : pCursor->bits->xhot - MAXCX + ((w - pCursor->bits->xhot)*MAXCX)/w;
    startbit = 0x80>>(xstart%8);
    cfb->hoffX = pCursor->bits->xhot - xstart;
    xstart /= 8;
    ystart = (h<=MAXCY) ?
	0 : pCursor->bits->yhot - MAXCY + ((h - pCursor->bits->yhot)*MAXCY)/h;
    cfb->hoffY = pCursor->bits->yhot - ystart;

	/* convert colors to display specific colors */
    hpSpriteFindColors(pScreen, pCursor, &fgcolor, &bgcolor);
    fgcolor = (fgcolor == 0) ? 0 : 0xFF;
    bgcolor = (bgcolor == 0) ? 0 : 0xFF;
    /* SET_REGISTERS_FOR_WRITING(pScreen,~0,GXcopy);	  /* setup hardware */
	/* bytes in each row of pixmaps (including padding) */
    w = (w+BITMAP_SCANLINE_PAD-1)/BITMAP_SCANLINE_PAD*(BITMAP_SCANLINE_PAD/8);
    for (y=0; y<cfb->height; y++)
    {
	ptr = pCursor->bits->source + w*(ystart+y) + xstart;
	qtr = pCursor->bits->mask + w*(ystart+y) + xstart;
	ctr = tcXY(cfb->srcX/8, y+cfb->srcY); /* address of offscreen cursor */
	mtr = tcXY(cfb->maskX/8,y+cfb->maskY); /* address of offscreen cursor mask */
	for (z = startbit, x=0; x<cfb->width; x+=8)
	{
	    *mtr = *ctr = 0;
	    for (z1=0x80; z1>0; z1>>=1)
	    {
		/* cursor mask: all planes = xor(or(all planes)) */
		*mtr |= ((*qtr & z) ? 0 : 0xFF) & z1;
		/* squeeze cursor through mask */
		*ctr |= ((*qtr & z) ? ((*ptr & z) ? fgcolor : bgcolor) : 0) & z1;
		if ((z>>=1)==0)
		{
		    z = 0x80; ptr++; qtr++;
		}
	    }
	    mtr++; ctr++;
	}
    }
    hpMoveMouse(pScreen, hpPointer->coords[0],hpPointer->coords[1], 1);
    return TRUE;
}

extern Bool hpSpriteInitialize();

Bool
hpInitCursor(pScreen, scrn_depth) 
     ScreenPtr pScreen;
     int scrn_depth;
{
    register hpPrivScreenPtr cfb = getPrivScreenPtr(pScreen);
    hpChunk *chunkie;

    cfb->MoveMouse = hpMoveMouse; cfb->CursorOff = hpCursorOff;
    cfb->cstate = CURSOR_OFF;
	/* allocate 3 max size cursor retangles: 
	 * cursor, cursor mask and screen save area
	 */
    chunkie = hpBufAlloc(pScreen, MAXCX,MAXCY);		/* save area */
    cfb->ssaveX = chunkie->x; cfb->ssaveY = chunkie->y;
    chunkie = hpBufAlloc(pScreen, MAXCX,MAXCY);		/* cursor */
    cfb->srcX = chunkie->x; cfb->srcY = chunkie->y;
    chunkie = hpBufAlloc(pScreen, MAXCX,MAXCY);		/* mask */
    cfb->maskX = chunkie->x; cfb->maskY = chunkie->y;

	/* create a dummy cursor to avoid trashing screen */
    cfb->hoffX = 0; cfb->hoffY = 0; cfb->width = 1; cfb->height = 1;

    pScreen->RealizeCursor = hpRealizeCursor;
    pScreen->UnrealizeCursor = hpUnrealizeCursor;
    if (scrn_depth == 1)
	pScreen->DisplayCursor = hpmDisplayCursor;
    else
	pScreen->DisplayCursor = hpDisplayCursor;
    pScreen->SetCursorPosition = hpSetCursorPosition;
    pScreen->CursorLimits = hpCursorLimits;
    pScreen->PointerNonInterestBox = hpPointerNonInterestBox;
    pScreen->ConstrainCursor = hpConstrainCursor;
    pScreen->RecolorCursor = hpRecolorCursor;

    return hpSpriteInitialize (pScreen);
}

static Bool
hpRealizeCursor(pScreen,pCursor)
     ScreenPtr pScreen; CursorPtr pCursor;
{
    return TRUE;
}

static Bool
hpUnrealizeCursor(pScreen,pCursor)
     ScreenPtr pScreen; CursorPtr pCursor;
{
    return TRUE;
}

	/* hpRecolorCursor -- Change the color of a cursor
	 * Do this by creating a new cursor that has the new colors
	 */
static void 
hpRecolorCursor(pScreen, pCursor, displayed)
     ScreenPtr pScreen; /* Screen for which the cursor is to be recolored */
     CursorPtr pCursor; /* Cursor to recolor */
     Bool displayed;	/* True if pCursor being displayed now */
{
    if (displayed) 
	(void) hpDisplayCursor(pScreen, pCursor);
}

/*
 * hpPointerNonInterestBox --
 *	Set up things to ignore uninteresting mouse events. Sorry.
 */
static void 
hpPointerNonInterestBox(pScreen,pBox)
     ScreenPtr pScreen;
     BoxPtr    pBox;	    /* Box outside of which motions are boring */
{
}