2003-11-14 16:54:54 +01:00
|
|
|
/*
|
|
|
|
* misprite.c
|
|
|
|
*
|
|
|
|
* machine independent software sprite routines
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
Copyright 1989, 1998 The Open Group
|
|
|
|
|
|
|
|
Permission to use, copy, modify, distribute, and sell this software and its
|
|
|
|
documentation for any purpose is hereby granted without fee, provided that
|
|
|
|
the above copyright notice appear in all copies and that both that
|
|
|
|
copyright notice and this permission notice appear in supporting
|
|
|
|
documentation.
|
|
|
|
|
|
|
|
The above copyright notice and this permission notice shall be included in
|
|
|
|
all copies or substantial portions of the Software.
|
|
|
|
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
|
|
|
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
|
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
|
|
|
|
Except as contained in this notice, the name of The Open Group shall not be
|
|
|
|
used in advertising or otherwise to promote the sale, use or other dealings
|
|
|
|
in this Software without prior written authorization from The Open Group.
|
|
|
|
*/
|
2006-11-17 05:40:37 +01:00
|
|
|
#ifdef MPX
|
|
|
|
/*
|
|
|
|
* MPX additions:
|
|
|
|
* Copyright © 2006 Peter Hutterer
|
|
|
|
* License see above.
|
|
|
|
* Author: Peter Hutterer <peter@cs.unisa.edu.au>
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
#endif
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2005-08-21 21:29:55 +02:00
|
|
|
#ifdef HAVE_DIX_CONFIG_H
|
|
|
|
#include <dix-config.h>
|
|
|
|
#endif
|
|
|
|
|
2005-04-20 14:25:48 +02:00
|
|
|
# include <X11/X.h>
|
|
|
|
# include <X11/Xproto.h>
|
2003-11-14 16:54:54 +01:00
|
|
|
# include "misc.h"
|
|
|
|
# include "pixmapstr.h"
|
|
|
|
# include "input.h"
|
|
|
|
# include "mi.h"
|
|
|
|
# include "cursorstr.h"
|
2005-07-03 09:02:09 +02:00
|
|
|
# include <X11/fonts/font.h>
|
2003-11-14 16:54:54 +01:00
|
|
|
# include "scrnintstr.h"
|
|
|
|
# include "colormapst.h"
|
|
|
|
# include "windowstr.h"
|
|
|
|
# include "gcstruct.h"
|
|
|
|
# include "mipointer.h"
|
|
|
|
# include "mispritest.h"
|
|
|
|
# include "dixfontstr.h"
|
2005-07-03 09:02:09 +02:00
|
|
|
# include <X11/fonts/fontstruct.h>
|
|
|
|
|
2003-11-14 17:49:22 +01:00
|
|
|
#ifdef RENDER
|
|
|
|
# include "mipict.h"
|
|
|
|
#endif
|
2004-08-07 03:23:07 +02:00
|
|
|
# include "damage.h"
|
|
|
|
|
2006-11-17 08:33:43 +01:00
|
|
|
#ifdef MPX
|
|
|
|
# include "inputstr.h" /* for MAX_DEVICES */
|
|
|
|
#endif
|
|
|
|
|
2004-08-07 03:23:07 +02:00
|
|
|
#define SPRITE_DEBUG_ENABLE 0
|
|
|
|
#if SPRITE_DEBUG_ENABLE
|
|
|
|
#define SPRITE_DEBUG(x) ErrorF x
|
|
|
|
#else
|
|
|
|
#define SPRITE_DEBUG(x)
|
|
|
|
#endif
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* screen wrappers
|
|
|
|
*/
|
|
|
|
|
|
|
|
static int miSpriteScreenIndex;
|
|
|
|
static unsigned long miSpriteGeneration = 0;
|
|
|
|
|
2003-11-14 17:49:22 +01:00
|
|
|
static Bool miSpriteCloseScreen(int i, ScreenPtr pScreen);
|
|
|
|
static void miSpriteGetImage(DrawablePtr pDrawable, int sx, int sy,
|
|
|
|
int w, int h, unsigned int format,
|
|
|
|
unsigned long planemask, char *pdstLine);
|
|
|
|
static void miSpriteGetSpans(DrawablePtr pDrawable, int wMax,
|
|
|
|
DDXPointPtr ppt, int *pwidth, int nspans,
|
|
|
|
char *pdstStart);
|
|
|
|
static void miSpriteSourceValidate(DrawablePtr pDrawable, int x, int y,
|
|
|
|
int width, int height);
|
2004-08-07 03:23:07 +02:00
|
|
|
static void miSpriteCopyWindow (WindowPtr pWindow,
|
|
|
|
DDXPointRec ptOldOrg,
|
|
|
|
RegionPtr prgnSrc);
|
2003-11-14 17:49:22 +01:00
|
|
|
static void miSpriteBlockHandler(int i, pointer blockData,
|
|
|
|
pointer pTimeout,
|
|
|
|
pointer pReadMask);
|
|
|
|
static void miSpriteInstallColormap(ColormapPtr pMap);
|
|
|
|
static void miSpriteStoreColors(ColormapPtr pMap, int ndef,
|
|
|
|
xColorItem *pdef);
|
|
|
|
|
|
|
|
static void miSpriteSaveDoomedAreas(WindowPtr pWin,
|
|
|
|
RegionPtr pObscured, int dx,
|
|
|
|
int dy);
|
2006-11-20 08:28:30 +01:00
|
|
|
static void miSpriteComputeSaved(miCursorInfoPtr pDevCursor,
|
|
|
|
ScreenPtr pScreen);
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
#define SCREEN_PROLOGUE(pScreen, field)\
|
|
|
|
((pScreen)->field = \
|
|
|
|
((miSpriteScreenPtr) (pScreen)->devPrivates[miSpriteScreenIndex].ptr)->field)
|
|
|
|
|
2005-12-29 21:54:08 +01:00
|
|
|
#define SCREEN_EPILOGUE(pScreen, field)\
|
|
|
|
((pScreen)->field = miSprite##field)
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* pointer-sprite method table
|
|
|
|
*/
|
|
|
|
|
2006-11-17 05:40:37 +01:00
|
|
|
static Bool miSpriteRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
|
|
|
|
CursorPtr pCursor);
|
|
|
|
static Bool miSpriteUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
|
|
|
|
CursorPtr pCursor);
|
|
|
|
static void miSpriteSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
|
|
|
|
CursorPtr pCursor, int x, int y);
|
|
|
|
static void miSpriteMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
|
|
|
|
int x, int y);
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2006-02-15 20:05:55 +01:00
|
|
|
_X_EXPORT miPointerSpriteFuncRec miSpritePointerFuncs = {
|
2003-11-14 16:54:54 +01:00
|
|
|
miSpriteRealizeCursor,
|
|
|
|
miSpriteUnrealizeCursor,
|
|
|
|
miSpriteSetCursor,
|
|
|
|
miSpriteMoveCursor,
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* other misc functions
|
|
|
|
*/
|
|
|
|
|
2006-11-20 08:28:30 +01:00
|
|
|
static void miSpriteRemoveCursor(miCursorInfoPtr pDevCursor,
|
|
|
|
ScreenPtr pScreen);
|
|
|
|
static void miSpriteRestoreCursor(miCursorInfoPtr pDevCursor,
|
|
|
|
ScreenPtr pScreen);
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2004-08-07 03:23:07 +02:00
|
|
|
static void
|
|
|
|
miSpriteReportDamage (DamagePtr pDamage, RegionPtr pRegion, void *closure)
|
|
|
|
{
|
|
|
|
ScreenPtr pScreen = closure;
|
|
|
|
miSpriteScreenPtr pScreenPriv;
|
|
|
|
|
|
|
|
pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
|
|
|
|
|
2006-11-20 03:40:07 +01:00
|
|
|
if (pScreenPriv->cp->isUp &&
|
|
|
|
RECT_IN_REGION (pScreen, pRegion, &pScreenPriv->cp->saved) != rgnOUT)
|
2004-08-07 03:23:07 +02:00
|
|
|
{
|
|
|
|
SPRITE_DEBUG(("Damage remove\n"));
|
2006-11-20 08:28:30 +01:00
|
|
|
miSpriteRemoveCursor (pScreenPriv->cp, pScreen);
|
2004-08-07 03:23:07 +02:00
|
|
|
}
|
2006-11-21 01:56:21 +01:00
|
|
|
|
|
|
|
#ifdef MPX
|
|
|
|
{
|
|
|
|
int mpCursorIdx = 0;
|
|
|
|
while (mpCursorIdx < MAX_DEVICES)
|
|
|
|
{
|
|
|
|
miCursorInfoPtr pMPCursor = &pScreenPriv->mpCursors[mpCursorIdx];
|
|
|
|
|
|
|
|
if (pMPCursor->isUp &&
|
|
|
|
RECT_IN_REGION (pScreen, pRegion, &pMPCursor->saved) != rgnOUT)
|
|
|
|
{
|
|
|
|
SPRITE_DEBUG(("Damage remove MPX\n"));
|
|
|
|
miSpriteRemoveCursor(pMPCursor, pScreen);
|
|
|
|
}
|
|
|
|
mpCursorIdx++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
2004-08-07 03:23:07 +02:00
|
|
|
}
|
|
|
|
|
2003-11-14 16:54:54 +01:00
|
|
|
/*
|
|
|
|
* miSpriteInitialize -- called from device-dependent screen
|
|
|
|
* initialization proc after all of the function pointers have
|
|
|
|
* been stored in the screen structure.
|
|
|
|
*/
|
|
|
|
|
|
|
|
Bool
|
|
|
|
miSpriteInitialize (pScreen, cursorFuncs, screenFuncs)
|
|
|
|
ScreenPtr pScreen;
|
|
|
|
miSpriteCursorFuncPtr cursorFuncs;
|
|
|
|
miPointerScreenFuncPtr screenFuncs;
|
|
|
|
{
|
2006-11-17 08:33:43 +01:00
|
|
|
#ifdef MPX
|
|
|
|
int mpCursorIdx = 0;
|
|
|
|
#endif
|
2004-08-07 03:23:07 +02:00
|
|
|
miSpriteScreenPtr pScreenPriv;
|
2003-11-14 16:54:54 +01:00
|
|
|
VisualPtr pVisual;
|
|
|
|
|
2004-08-07 03:23:07 +02:00
|
|
|
if (!DamageSetup (pScreen))
|
|
|
|
return FALSE;
|
|
|
|
|
2003-11-14 16:54:54 +01:00
|
|
|
if (miSpriteGeneration != serverGeneration)
|
|
|
|
{
|
|
|
|
miSpriteScreenIndex = AllocateScreenPrivateIndex ();
|
|
|
|
if (miSpriteScreenIndex < 0)
|
|
|
|
return FALSE;
|
|
|
|
miSpriteGeneration = serverGeneration;
|
|
|
|
}
|
2004-08-07 03:23:07 +02:00
|
|
|
|
|
|
|
pScreenPriv = (miSpriteScreenPtr) xalloc (sizeof (miSpriteScreenRec));
|
|
|
|
if (!pScreenPriv)
|
2003-11-14 16:54:54 +01:00
|
|
|
return FALSE;
|
2004-08-07 03:23:07 +02:00
|
|
|
|
|
|
|
pScreenPriv->pDamage = DamageCreate (miSpriteReportDamage,
|
|
|
|
(DamageDestroyFunc) 0,
|
|
|
|
DamageReportRawRegion,
|
|
|
|
TRUE,
|
|
|
|
pScreen,
|
|
|
|
(void *) pScreen);
|
|
|
|
|
2003-11-14 16:54:54 +01:00
|
|
|
if (!miPointerInitialize (pScreen, &miSpritePointerFuncs, screenFuncs,TRUE))
|
|
|
|
{
|
2004-08-07 03:23:07 +02:00
|
|
|
xfree ((pointer) pScreenPriv);
|
2003-11-14 16:54:54 +01:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
for (pVisual = pScreen->visuals;
|
|
|
|
pVisual->vid != pScreen->rootVisual;
|
|
|
|
pVisual++)
|
|
|
|
;
|
2004-08-07 03:23:07 +02:00
|
|
|
pScreenPriv->pVisual = pVisual;
|
|
|
|
pScreenPriv->CloseScreen = pScreen->CloseScreen;
|
|
|
|
pScreenPriv->GetImage = pScreen->GetImage;
|
|
|
|
pScreenPriv->GetSpans = pScreen->GetSpans;
|
|
|
|
pScreenPriv->SourceValidate = pScreen->SourceValidate;
|
|
|
|
|
|
|
|
pScreenPriv->CopyWindow = pScreen->CopyWindow;
|
|
|
|
|
|
|
|
pScreenPriv->SaveDoomedAreas = pScreen->SaveDoomedAreas;
|
|
|
|
|
|
|
|
pScreenPriv->InstallColormap = pScreen->InstallColormap;
|
|
|
|
pScreenPriv->StoreColors = pScreen->StoreColors;
|
|
|
|
|
|
|
|
pScreenPriv->BlockHandler = pScreen->BlockHandler;
|
|
|
|
|
2006-11-20 03:40:07 +01:00
|
|
|
pScreenPriv->cp = (miCursorInfoPtr)xalloc(sizeof(miCursorInfoRec));
|
|
|
|
pScreenPriv->cp->pCursor = NULL;
|
|
|
|
pScreenPriv->cp->x = 0;
|
|
|
|
pScreenPriv->cp->y = 0;
|
|
|
|
pScreenPriv->cp->isUp = FALSE;
|
|
|
|
pScreenPriv->cp->shouldBeUp = FALSE;
|
|
|
|
pScreenPriv->cp->pCacheWin = NullWindow;
|
|
|
|
pScreenPriv->cp->isInCacheWin = FALSE;
|
|
|
|
pScreenPriv->cp->checkPixels = TRUE;
|
|
|
|
pScreenPriv->cp->pInstalledMap = NULL;
|
|
|
|
pScreenPriv->cp->pColormap = NULL;
|
|
|
|
pScreenPriv->cp->colors[SOURCE_COLOR].red = 0;
|
|
|
|
pScreenPriv->cp->colors[SOURCE_COLOR].green = 0;
|
|
|
|
pScreenPriv->cp->colors[SOURCE_COLOR].blue = 0;
|
|
|
|
pScreenPriv->cp->colors[MASK_COLOR].red = 0;
|
|
|
|
pScreenPriv->cp->colors[MASK_COLOR].green = 0;
|
|
|
|
pScreenPriv->cp->colors[MASK_COLOR].blue = 0;
|
|
|
|
|
2004-08-07 03:23:07 +02:00
|
|
|
pScreenPriv->funcs = cursorFuncs;
|
|
|
|
pScreen->devPrivates[miSpriteScreenIndex].ptr = (pointer) pScreenPriv;
|
2003-11-14 17:49:22 +01:00
|
|
|
|
2003-11-14 16:54:54 +01:00
|
|
|
pScreen->CloseScreen = miSpriteCloseScreen;
|
|
|
|
pScreen->GetImage = miSpriteGetImage;
|
|
|
|
pScreen->GetSpans = miSpriteGetSpans;
|
|
|
|
pScreen->SourceValidate = miSpriteSourceValidate;
|
2004-08-07 03:23:07 +02:00
|
|
|
|
2003-11-14 16:54:54 +01:00
|
|
|
pScreen->CopyWindow = miSpriteCopyWindow;
|
2004-08-07 03:23:07 +02:00
|
|
|
|
2003-11-14 16:54:54 +01:00
|
|
|
pScreen->SaveDoomedAreas = miSpriteSaveDoomedAreas;
|
2004-08-07 03:23:07 +02:00
|
|
|
|
|
|
|
pScreen->InstallColormap = miSpriteInstallColormap;
|
|
|
|
pScreen->StoreColors = miSpriteStoreColors;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2004-08-07 03:23:07 +02:00
|
|
|
pScreen->BlockHandler = miSpriteBlockHandler;
|
|
|
|
|
2006-11-17 08:33:43 +01:00
|
|
|
#ifdef MPX
|
|
|
|
/* alloc and zero memory for all MPX cursors */
|
|
|
|
pScreenPriv->mpCursors = (miCursorInfoPtr)xalloc(MAX_DEVICES * sizeof(miCursorInfoRec));
|
|
|
|
while (mpCursorIdx < MAX_DEVICES)
|
|
|
|
{
|
|
|
|
miCursorInfoPtr cursor = &(pScreenPriv->mpCursors[mpCursorIdx]);
|
|
|
|
|
2006-11-21 01:56:21 +01:00
|
|
|
cursor->id = mpCursorIdx;
|
2006-11-17 08:33:43 +01:00
|
|
|
cursor->pCursor = NULL;
|
|
|
|
cursor->x = 0;
|
|
|
|
cursor->y = 0;
|
|
|
|
cursor->isUp = FALSE;
|
|
|
|
cursor->shouldBeUp = FALSE;
|
|
|
|
cursor->pCacheWin = NullWindow;
|
2006-11-20 03:40:07 +01:00
|
|
|
cursor->isInCacheWin = FALSE;
|
|
|
|
cursor->checkPixels = TRUE;
|
|
|
|
cursor->pInstalledMap = NULL;
|
|
|
|
cursor->pColormap = NULL;
|
|
|
|
cursor->colors[SOURCE_COLOR].red = 0;
|
|
|
|
cursor->colors[SOURCE_COLOR].green = 0;
|
|
|
|
cursor->colors[SOURCE_COLOR].blue = 0;
|
|
|
|
cursor->colors[MASK_COLOR].red = 0;
|
|
|
|
cursor->colors[MASK_COLOR].green = 0;
|
|
|
|
cursor->colors[MASK_COLOR].blue = 0;
|
2006-11-17 08:33:43 +01:00
|
|
|
|
|
|
|
mpCursorIdx++;
|
|
|
|
}
|
2006-11-21 01:56:21 +01:00
|
|
|
|
|
|
|
/* virtual core pointer has id 1, we might as well save the memory */
|
|
|
|
xfree(pScreenPriv->cp);
|
|
|
|
pScreenPriv->cp = &(pScreenPriv->mpCursors[1]);
|
2006-11-17 08:33:43 +01:00
|
|
|
#endif
|
|
|
|
|
2003-11-14 16:54:54 +01:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Screen wrappers
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* CloseScreen wrapper -- unwrap everything, free the private data
|
|
|
|
* and call the wrapped function
|
|
|
|
*/
|
|
|
|
|
|
|
|
static Bool
|
|
|
|
miSpriteCloseScreen (i, pScreen)
|
2003-11-14 17:49:22 +01:00
|
|
|
int i;
|
2003-11-14 16:54:54 +01:00
|
|
|
ScreenPtr pScreen;
|
|
|
|
{
|
|
|
|
miSpriteScreenPtr pScreenPriv;
|
|
|
|
|
|
|
|
pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
|
|
|
|
|
|
|
|
pScreen->CloseScreen = pScreenPriv->CloseScreen;
|
|
|
|
pScreen->GetImage = pScreenPriv->GetImage;
|
|
|
|
pScreen->GetSpans = pScreenPriv->GetSpans;
|
|
|
|
pScreen->SourceValidate = pScreenPriv->SourceValidate;
|
|
|
|
pScreen->BlockHandler = pScreenPriv->BlockHandler;
|
|
|
|
pScreen->InstallColormap = pScreenPriv->InstallColormap;
|
|
|
|
pScreen->StoreColors = pScreenPriv->StoreColors;
|
|
|
|
|
|
|
|
pScreen->SaveDoomedAreas = pScreenPriv->SaveDoomedAreas;
|
2006-11-20 08:28:30 +01:00
|
|
|
miSpriteIsUpFALSE (pScreenPriv->cp, pScreen, pScreenPriv);
|
2004-08-07 03:23:07 +02:00
|
|
|
DamageDestroy (pScreenPriv->pDamage);
|
2006-11-20 08:28:30 +01:00
|
|
|
|
|
|
|
#ifdef MPX
|
|
|
|
xfree((pointer)(pScreenPriv->mpCursors));
|
|
|
|
#endif
|
2004-08-07 03:23:07 +02:00
|
|
|
|
2003-11-14 16:54:54 +01:00
|
|
|
xfree ((pointer) pScreenPriv);
|
|
|
|
|
|
|
|
return (*pScreen->CloseScreen) (i, pScreen);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
miSpriteGetImage (pDrawable, sx, sy, w, h, format, planemask, pdstLine)
|
|
|
|
DrawablePtr pDrawable;
|
|
|
|
int sx, sy, w, h;
|
|
|
|
unsigned int format;
|
|
|
|
unsigned long planemask;
|
|
|
|
char *pdstLine;
|
|
|
|
{
|
|
|
|
ScreenPtr pScreen = pDrawable->pScreen;
|
|
|
|
miSpriteScreenPtr pScreenPriv;
|
|
|
|
|
|
|
|
SCREEN_PROLOGUE (pScreen, GetImage);
|
|
|
|
|
|
|
|
pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
|
|
|
|
|
|
|
|
if (pDrawable->type == DRAWABLE_WINDOW &&
|
2006-11-20 03:40:07 +01:00
|
|
|
pScreenPriv->cp->isUp &&
|
|
|
|
ORG_OVERLAP(&pScreenPriv->cp->saved,pDrawable->x,pDrawable->y,
|
|
|
|
sx, sy, w, h))
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2004-08-07 03:23:07 +02:00
|
|
|
SPRITE_DEBUG (("GetImage remove\n"));
|
2006-11-20 08:28:30 +01:00
|
|
|
miSpriteRemoveCursor (pScreenPriv->cp, pScreen);
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
2006-11-20 08:28:30 +01:00
|
|
|
#ifdef MPX
|
|
|
|
/* check for MPX cursors in the target region */
|
|
|
|
if (pDrawable->type == DRAWABLE_WINDOW)
|
|
|
|
{
|
|
|
|
int mpCursorIdx = 0;
|
|
|
|
while (mpCursorIdx < MAX_DEVICES)
|
|
|
|
{
|
|
|
|
miCursorInfoPtr pMPCursor = &pScreenPriv->mpCursors[mpCursorIdx];
|
|
|
|
if (pMPCursor->isUp &&
|
|
|
|
ORG_OVERLAP(&pMPCursor->saved,pDrawable->x,pDrawable->y,
|
|
|
|
sx, sy, w, h))
|
|
|
|
{
|
|
|
|
SPRITE_DEBUG("GetImage remove MPX\n");
|
|
|
|
}
|
|
|
|
miSpriteRemoveCursor(pMPCursor, pScreen);
|
|
|
|
mpCursorIdx++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2003-11-14 16:54:54 +01:00
|
|
|
(*pScreen->GetImage) (pDrawable, sx, sy, w, h,
|
|
|
|
format, planemask, pdstLine);
|
|
|
|
|
2005-12-29 21:54:08 +01:00
|
|
|
SCREEN_EPILOGUE (pScreen, GetImage);
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
miSpriteGetSpans (pDrawable, wMax, ppt, pwidth, nspans, pdstStart)
|
|
|
|
DrawablePtr pDrawable;
|
|
|
|
int wMax;
|
|
|
|
DDXPointPtr ppt;
|
|
|
|
int *pwidth;
|
|
|
|
int nspans;
|
|
|
|
char *pdstStart;
|
|
|
|
{
|
|
|
|
ScreenPtr pScreen = pDrawable->pScreen;
|
|
|
|
miSpriteScreenPtr pScreenPriv;
|
|
|
|
|
|
|
|
SCREEN_PROLOGUE (pScreen, GetSpans);
|
|
|
|
|
|
|
|
pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
|
|
|
|
|
2006-11-20 03:40:07 +01:00
|
|
|
if (pDrawable->type == DRAWABLE_WINDOW && pScreenPriv->cp->isUp)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
|
|
|
register DDXPointPtr pts;
|
|
|
|
register int *widths;
|
|
|
|
register int nPts;
|
|
|
|
register int xorg,
|
|
|
|
yorg;
|
|
|
|
|
|
|
|
xorg = pDrawable->x;
|
|
|
|
yorg = pDrawable->y;
|
|
|
|
|
|
|
|
for (pts = ppt, widths = pwidth, nPts = nspans;
|
|
|
|
nPts--;
|
|
|
|
pts++, widths++)
|
|
|
|
{
|
2006-11-20 03:40:07 +01:00
|
|
|
if (SPN_OVERLAP(&pScreenPriv->cp->saved,pts->y+yorg,
|
2003-11-14 16:54:54 +01:00
|
|
|
pts->x+xorg,*widths))
|
|
|
|
{
|
2004-08-07 03:23:07 +02:00
|
|
|
SPRITE_DEBUG (("GetSpans remove\n"));
|
2006-11-20 08:28:30 +01:00
|
|
|
miSpriteRemoveCursor (pScreenPriv->cp, pScreen);
|
2003-11-14 16:54:54 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-11-20 08:28:30 +01:00
|
|
|
#ifdef MPX
|
|
|
|
if (pDrawable->type == DRAWABLE_WINDOW)
|
|
|
|
{
|
|
|
|
|
|
|
|
int mpCursorIdx = 0;
|
|
|
|
|
|
|
|
while(mpCursorIdx < MAX_DEVICES)
|
|
|
|
{
|
|
|
|
miCursorInfoPtr pMPCursor = &pScreenPriv->mpCursors[mpCursorIdx];
|
|
|
|
register DDXPointPtr pts;
|
|
|
|
register int *widths;
|
|
|
|
register int nPts;
|
|
|
|
register int xorg,
|
|
|
|
yorg;
|
|
|
|
xorg = pDrawable->x;
|
|
|
|
yorg = pDrawable->y;
|
|
|
|
|
|
|
|
for (pts = ppt, widths = pwidth, nPts = nspans;
|
|
|
|
nPts--;
|
|
|
|
pts++, widths++)
|
|
|
|
{
|
|
|
|
if (SPN_OVERLAP(&pMPCursor->saved,pts->y+yorg,
|
|
|
|
pts->x+xorg,*widths))
|
|
|
|
{
|
|
|
|
SPRITE_DEBUG (("GetSpans remove\n"));
|
|
|
|
miSpriteRemoveCursor (pMPCursor, pScreen);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
mpCursorIdx++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2003-11-14 16:54:54 +01:00
|
|
|
(*pScreen->GetSpans) (pDrawable, wMax, ppt, pwidth, nspans, pdstStart);
|
|
|
|
|
2005-12-29 21:54:08 +01:00
|
|
|
SCREEN_EPILOGUE (pScreen, GetSpans);
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
miSpriteSourceValidate (pDrawable, x, y, width, height)
|
|
|
|
DrawablePtr pDrawable;
|
|
|
|
int x, y, width, height;
|
|
|
|
{
|
|
|
|
ScreenPtr pScreen = pDrawable->pScreen;
|
|
|
|
miSpriteScreenPtr pScreenPriv;
|
|
|
|
|
|
|
|
SCREEN_PROLOGUE (pScreen, SourceValidate);
|
|
|
|
|
|
|
|
pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
|
|
|
|
|
2006-11-20 03:40:07 +01:00
|
|
|
if (pDrawable->type == DRAWABLE_WINDOW && pScreenPriv->cp->isUp &&
|
|
|
|
ORG_OVERLAP(&pScreenPriv->cp->saved, pDrawable->x, pDrawable->y,
|
2003-11-14 16:54:54 +01:00
|
|
|
x, y, width, height))
|
|
|
|
{
|
2004-08-07 03:23:07 +02:00
|
|
|
SPRITE_DEBUG (("SourceValidate remove\n"));
|
2006-11-20 08:28:30 +01:00
|
|
|
miSpriteRemoveCursor (pScreenPriv->cp, pScreen);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef MPX
|
|
|
|
if (pDrawable->type == DRAWABLE_WINDOW)
|
|
|
|
{
|
|
|
|
int mpCursorIdx = 0;
|
|
|
|
while (mpCursorIdx < MAX_DEVICES)
|
|
|
|
{
|
|
|
|
miCursorInfoPtr pMPCursor = &pScreenPriv->mpCursors[mpCursorIdx];
|
|
|
|
if (pMPCursor->isUp && ORG_OVERLAP(&pMPCursor->saved,
|
|
|
|
pDrawable->x, pDrawable->y, x, y, width, height))
|
|
|
|
{
|
|
|
|
SPRITE_DEBUG(("SourceValidate remove MPX\n"));
|
|
|
|
miSpriteRemoveCursor(pMPCursor, pScreen);
|
|
|
|
}
|
|
|
|
mpCursorIdx++;
|
|
|
|
}
|
|
|
|
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
2006-11-20 08:28:30 +01:00
|
|
|
#endif
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
if (pScreen->SourceValidate)
|
|
|
|
(*pScreen->SourceValidate) (pDrawable, x, y, width, height);
|
|
|
|
|
2005-12-29 21:54:08 +01:00
|
|
|
SCREEN_EPILOGUE (pScreen, SourceValidate);
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
2004-08-07 03:23:07 +02:00
|
|
|
static void
|
|
|
|
miSpriteCopyWindow (WindowPtr pWindow, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2004-08-07 03:23:07 +02:00
|
|
|
ScreenPtr pScreen = pWindow->drawable.pScreen;
|
|
|
|
miSpriteScreenPtr pScreenPriv;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2004-08-07 03:23:07 +02:00
|
|
|
SCREEN_PROLOGUE (pScreen, CopyWindow);
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2004-08-07 03:23:07 +02:00
|
|
|
pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
|
|
|
|
/*
|
|
|
|
* Damage will take care of destination check
|
|
|
|
*/
|
2006-11-20 03:40:07 +01:00
|
|
|
if (pScreenPriv->cp->isUp &&
|
|
|
|
RECT_IN_REGION (pScreen, prgnSrc, &pScreenPriv->cp->saved) != rgnOUT)
|
2004-08-07 03:23:07 +02:00
|
|
|
{
|
|
|
|
SPRITE_DEBUG (("CopyWindow remove\n"));
|
2006-11-20 08:28:30 +01:00
|
|
|
miSpriteRemoveCursor (pScreenPriv->cp, pScreen);
|
2004-08-07 03:23:07 +02:00
|
|
|
}
|
2006-11-20 08:28:30 +01:00
|
|
|
#ifdef MPX
|
|
|
|
{
|
|
|
|
int mpCursorIdx = 0;
|
|
|
|
while (mpCursorIdx < MAX_DEVICES)
|
|
|
|
{
|
|
|
|
miCursorInfoPtr pMPCursor = &pScreenPriv->mpCursors[mpCursorIdx];
|
|
|
|
|
|
|
|
if (pMPCursor->isUp && RECT_IN_REGION (pScreen, prgnSrc,
|
|
|
|
&pMPCursor->saved) != rgnOUT)
|
|
|
|
|
|
|
|
{
|
|
|
|
SPRITE_DEBUG(("CopyWindow remove MPX\n"));
|
|
|
|
miSpriteRemoveCursor(pMPCursor, pScreen);
|
|
|
|
}
|
|
|
|
mpCursorIdx++;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
#endif
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2004-08-07 03:23:07 +02:00
|
|
|
(*pScreen->CopyWindow) (pWindow, ptOldOrg, prgnSrc);
|
2005-12-29 21:54:08 +01:00
|
|
|
SCREEN_EPILOGUE (pScreen, CopyWindow);
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
miSpriteBlockHandler (i, blockData, pTimeout, pReadmask)
|
|
|
|
int i;
|
|
|
|
pointer blockData;
|
2003-11-14 17:49:22 +01:00
|
|
|
pointer pTimeout;
|
2003-11-14 16:54:54 +01:00
|
|
|
pointer pReadmask;
|
|
|
|
{
|
|
|
|
ScreenPtr pScreen = screenInfo.screens[i];
|
|
|
|
miSpriteScreenPtr pPriv;
|
|
|
|
|
|
|
|
pPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
|
|
|
|
|
|
|
|
SCREEN_PROLOGUE(pScreen, BlockHandler);
|
|
|
|
|
|
|
|
(*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask);
|
|
|
|
|
2005-12-29 21:54:08 +01:00
|
|
|
SCREEN_EPILOGUE(pScreen, BlockHandler);
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2006-11-20 03:40:07 +01:00
|
|
|
if (!pPriv->cp->isUp && pPriv->cp->shouldBeUp)
|
2004-08-07 03:23:07 +02:00
|
|
|
{
|
|
|
|
SPRITE_DEBUG (("BlockHandler restore\n"));
|
2006-11-20 08:28:30 +01:00
|
|
|
miSpriteRestoreCursor (pPriv->cp, pScreen);
|
2004-08-07 03:23:07 +02:00
|
|
|
}
|
2006-11-20 08:28:30 +01:00
|
|
|
|
|
|
|
#ifdef MPX
|
|
|
|
{
|
|
|
|
int mpCursorIdx = 0;
|
|
|
|
while (mpCursorIdx < MAX_DEVICES)
|
|
|
|
{
|
|
|
|
miCursorInfoPtr pMPCursor = &pPriv->mpCursors[mpCursorIdx];
|
|
|
|
if (!pMPCursor->isUp && pMPCursor->shouldBeUp)
|
|
|
|
{
|
|
|
|
SPRITE_DEBUG (("BlockHandler restore MPX\n"));
|
|
|
|
miSpriteRestoreCursor (pMPCursor, pScreen);
|
|
|
|
}
|
|
|
|
|
|
|
|
mpCursorIdx++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
miSpriteInstallColormap (pMap)
|
|
|
|
ColormapPtr pMap;
|
|
|
|
{
|
|
|
|
ScreenPtr pScreen = pMap->pScreen;
|
|
|
|
miSpriteScreenPtr pPriv;
|
|
|
|
|
|
|
|
pPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
|
|
|
|
|
|
|
|
SCREEN_PROLOGUE(pScreen, InstallColormap);
|
|
|
|
|
|
|
|
(*pScreen->InstallColormap) (pMap);
|
|
|
|
|
2005-12-29 21:54:08 +01:00
|
|
|
SCREEN_EPILOGUE(pScreen, InstallColormap);
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2006-11-20 03:40:07 +01:00
|
|
|
pPriv->cp->pInstalledMap = pMap;
|
|
|
|
if (pPriv->cp->pColormap != pMap)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2006-11-20 03:40:07 +01:00
|
|
|
pPriv->cp->checkPixels = TRUE;
|
|
|
|
if (pPriv->cp->isUp)
|
2006-11-20 08:28:30 +01:00
|
|
|
miSpriteRemoveCursor (pPriv->cp, pScreen);
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
2006-11-20 08:28:30 +01:00
|
|
|
|
|
|
|
#ifdef MPX
|
|
|
|
{
|
|
|
|
int mpCursorIdx = 0;
|
|
|
|
while (mpCursorIdx < MAX_DEVICES)
|
|
|
|
{
|
|
|
|
miCursorInfoPtr pMPCursor = &pPriv->mpCursors[mpCursorIdx];
|
|
|
|
pMPCursor->pInstalledMap = pMap;
|
|
|
|
if (pMPCursor->pColormap != pMap)
|
|
|
|
{
|
|
|
|
pMPCursor->checkPixels = TRUE;
|
|
|
|
if (pMPCursor->isUp)
|
|
|
|
miSpriteRemoveCursor(pMPCursor, pScreen);
|
|
|
|
}
|
|
|
|
mpCursorIdx++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
miSpriteStoreColors (pMap, ndef, pdef)
|
|
|
|
ColormapPtr pMap;
|
|
|
|
int ndef;
|
|
|
|
xColorItem *pdef;
|
|
|
|
{
|
|
|
|
ScreenPtr pScreen = pMap->pScreen;
|
|
|
|
miSpriteScreenPtr pPriv;
|
|
|
|
int i;
|
|
|
|
int updated;
|
|
|
|
VisualPtr pVisual;
|
|
|
|
|
|
|
|
pPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
|
|
|
|
|
|
|
|
SCREEN_PROLOGUE(pScreen, StoreColors);
|
|
|
|
|
|
|
|
(*pScreen->StoreColors) (pMap, ndef, pdef);
|
|
|
|
|
2005-12-29 21:54:08 +01:00
|
|
|
SCREEN_EPILOGUE(pScreen, StoreColors);
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2006-11-20 03:40:07 +01:00
|
|
|
if (pPriv->cp->pColormap == pMap)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
|
|
|
updated = 0;
|
|
|
|
pVisual = pMap->pVisual;
|
|
|
|
if (pVisual->class == DirectColor)
|
|
|
|
{
|
|
|
|
/* Direct color - match on any of the subfields */
|
|
|
|
|
2003-11-14 17:49:22 +01:00
|
|
|
#define MaskMatch(a,b,mask) (((a) & (pVisual->mask)) == ((b) & (pVisual->mask)))
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2006-11-20 08:28:30 +01:00
|
|
|
#define UpdateDAC(dev, plane,dac,mask) {\
|
|
|
|
if (MaskMatch (dev->colors[plane].pixel,pdef[i].pixel,mask)) {\
|
|
|
|
dev->colors[plane].dac = pdef[i].dac; \
|
2003-11-14 16:54:54 +01:00
|
|
|
updated = 1; \
|
|
|
|
} \
|
|
|
|
}
|
|
|
|
|
2006-11-20 08:28:30 +01:00
|
|
|
#define CheckDirect(dev, plane) \
|
|
|
|
UpdateDAC(dev, plane,red,redMask) \
|
|
|
|
UpdateDAC(dev, plane,green,greenMask) \
|
|
|
|
UpdateDAC(dev, plane,blue,blueMask)
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
for (i = 0; i < ndef; i++)
|
|
|
|
{
|
2006-11-20 08:28:30 +01:00
|
|
|
CheckDirect (pPriv->cp, SOURCE_COLOR)
|
|
|
|
CheckDirect (pPriv->cp, MASK_COLOR)
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* PseudoColor/GrayScale - match on exact pixel */
|
|
|
|
for (i = 0; i < ndef; i++)
|
|
|
|
{
|
2006-11-20 03:40:07 +01:00
|
|
|
if (pdef[i].pixel == pPriv->cp->colors[SOURCE_COLOR].pixel)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2006-11-20 03:40:07 +01:00
|
|
|
pPriv->cp->colors[SOURCE_COLOR] = pdef[i];
|
2003-11-14 16:54:54 +01:00
|
|
|
if (++updated == 2)
|
|
|
|
break;
|
|
|
|
}
|
2006-11-20 03:40:07 +01:00
|
|
|
if (pdef[i].pixel == pPriv->cp->colors[MASK_COLOR].pixel)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2006-11-20 03:40:07 +01:00
|
|
|
pPriv->cp->colors[MASK_COLOR] = pdef[i];
|
2003-11-14 16:54:54 +01:00
|
|
|
if (++updated == 2)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (updated)
|
|
|
|
{
|
2006-11-20 03:40:07 +01:00
|
|
|
pPriv->cp->checkPixels = TRUE;
|
|
|
|
if (pPriv->cp->isUp)
|
2006-11-20 08:28:30 +01:00
|
|
|
miSpriteRemoveCursor (pPriv->cp, pScreen);
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
}
|
2006-11-20 08:28:30 +01:00
|
|
|
|
|
|
|
#ifdef MPX
|
|
|
|
{
|
|
|
|
int mpCursorIdx = 0;
|
|
|
|
|
|
|
|
while (mpCursorIdx < MAX_DEVICES)
|
|
|
|
{
|
|
|
|
miCursorInfoPtr pMPCursor = &pPriv->mpCursors[mpCursorIdx];
|
|
|
|
|
|
|
|
if (pPriv->cp->pColormap == pMap)
|
|
|
|
{
|
|
|
|
updated = 0;
|
|
|
|
pVisual = pMap->pVisual;
|
|
|
|
if (pVisual->class == DirectColor)
|
|
|
|
{
|
|
|
|
for (i = 0; i < ndef; i++)
|
|
|
|
{
|
|
|
|
CheckDirect (pMPCursor, SOURCE_COLOR)
|
|
|
|
CheckDirect (pMPCursor, MASK_COLOR)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* PseudoColor/GrayScale - match on exact pixel */
|
|
|
|
for (i = 0; i < ndef; i++)
|
|
|
|
{
|
|
|
|
if (pdef[i].pixel ==
|
|
|
|
pMPCursor->colors[SOURCE_COLOR].pixel)
|
|
|
|
{
|
|
|
|
pMPCursor->colors[SOURCE_COLOR] = pdef[i];
|
|
|
|
if (++updated == 2)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (pdef[i].pixel ==
|
|
|
|
pMPCursor->colors[MASK_COLOR].pixel)
|
|
|
|
{
|
|
|
|
pMPCursor->colors[MASK_COLOR] = pdef[i];
|
|
|
|
if (++updated == 2)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (updated)
|
|
|
|
{
|
|
|
|
pMPCursor->checkPixels = TRUE;
|
|
|
|
if (pMPCursor->isUp)
|
|
|
|
miSpriteRemoveCursor (pMPCursor, pScreen);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
mpCursorIdx++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2006-11-20 08:28:30 +01:00
|
|
|
miSpriteFindColors (miCursorInfoPtr pDevCursor, ScreenPtr pScreen)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
|
|
|
CursorPtr pCursor;
|
|
|
|
xColorItem *sourceColor, *maskColor;
|
|
|
|
|
2006-11-20 08:28:30 +01:00
|
|
|
pCursor = pDevCursor->pCursor;
|
|
|
|
sourceColor = &pDevCursor->colors[SOURCE_COLOR];
|
|
|
|
maskColor = &pDevCursor->colors[MASK_COLOR];
|
|
|
|
if (pDevCursor->pColormap != pDevCursor->pInstalledMap ||
|
2003-11-14 16:54:54 +01:00
|
|
|
!(pCursor->foreRed == sourceColor->red &&
|
|
|
|
pCursor->foreGreen == sourceColor->green &&
|
|
|
|
pCursor->foreBlue == sourceColor->blue &&
|
|
|
|
pCursor->backRed == maskColor->red &&
|
|
|
|
pCursor->backGreen == maskColor->green &&
|
|
|
|
pCursor->backBlue == maskColor->blue))
|
|
|
|
{
|
2006-11-20 08:28:30 +01:00
|
|
|
pDevCursor->pColormap = pDevCursor->pInstalledMap;
|
2003-11-14 16:54:54 +01:00
|
|
|
sourceColor->red = pCursor->foreRed;
|
|
|
|
sourceColor->green = pCursor->foreGreen;
|
|
|
|
sourceColor->blue = pCursor->foreBlue;
|
2006-11-20 08:28:30 +01:00
|
|
|
FakeAllocColor (pDevCursor->pColormap, sourceColor);
|
2003-11-14 16:54:54 +01:00
|
|
|
maskColor->red = pCursor->backRed;
|
|
|
|
maskColor->green = pCursor->backGreen;
|
|
|
|
maskColor->blue = pCursor->backBlue;
|
2006-11-20 08:28:30 +01:00
|
|
|
FakeAllocColor (pDevCursor->pColormap, maskColor);
|
2003-11-14 16:54:54 +01:00
|
|
|
/* "free" the pixels right away, don't let this confuse you */
|
2006-11-20 08:28:30 +01:00
|
|
|
FakeFreeColor(pDevCursor->pColormap, sourceColor->pixel);
|
|
|
|
FakeFreeColor(pDevCursor->pColormap, maskColor->pixel);
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
2006-11-20 08:28:30 +01:00
|
|
|
|
|
|
|
pDevCursor->checkPixels = FALSE;
|
|
|
|
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* BackingStore wrappers
|
|
|
|
*/
|
|
|
|
|
|
|
|
static void
|
|
|
|
miSpriteSaveDoomedAreas (pWin, pObscured, dx, dy)
|
|
|
|
WindowPtr pWin;
|
|
|
|
RegionPtr pObscured;
|
|
|
|
int dx, dy;
|
|
|
|
{
|
|
|
|
ScreenPtr pScreen;
|
|
|
|
miSpriteScreenPtr pScreenPriv;
|
|
|
|
BoxRec cursorBox;
|
|
|
|
|
|
|
|
pScreen = pWin->drawable.pScreen;
|
|
|
|
|
|
|
|
SCREEN_PROLOGUE (pScreen, SaveDoomedAreas);
|
|
|
|
|
|
|
|
pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
|
2006-11-20 03:40:07 +01:00
|
|
|
if (pScreenPriv->cp->isUp)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2006-11-20 03:40:07 +01:00
|
|
|
cursorBox = pScreenPriv->cp->saved;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
if (dx || dy)
|
|
|
|
{
|
|
|
|
cursorBox.x1 += dx;
|
|
|
|
cursorBox.y1 += dy;
|
|
|
|
cursorBox.x2 += dx;
|
|
|
|
cursorBox.y2 += dy;
|
|
|
|
}
|
|
|
|
if (RECT_IN_REGION( pScreen, pObscured, &cursorBox) != rgnOUT)
|
2006-11-20 08:28:30 +01:00
|
|
|
miSpriteRemoveCursor (pScreenPriv->cp, pScreen);
|
|
|
|
}
|
|
|
|
#ifdef MPX
|
|
|
|
{
|
|
|
|
int mpCursorIdx = 0;
|
|
|
|
while (mpCursorIdx < MAX_DEVICES)
|
|
|
|
{
|
|
|
|
miCursorInfoPtr pMPCursor = &pScreenPriv->mpCursors[mpCursorIdx];
|
|
|
|
|
|
|
|
if (pMPCursor->isUp)
|
|
|
|
{
|
|
|
|
cursorBox = pMPCursor->saved;
|
|
|
|
|
|
|
|
if (dx || dy)
|
|
|
|
{
|
|
|
|
cursorBox.x1 += dx;
|
|
|
|
cursorBox.y1 += dy;
|
|
|
|
cursorBox.x2 += dx;
|
|
|
|
cursorBox.y2 += dy;
|
|
|
|
}
|
|
|
|
if (RECT_IN_REGION( pScreen, pObscured, &cursorBox) != rgnOUT)
|
|
|
|
miSpriteRemoveCursor (pMPCursor, pScreen);
|
|
|
|
}
|
|
|
|
mpCursorIdx++;
|
|
|
|
}
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
2006-11-20 08:28:30 +01:00
|
|
|
#endif
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
(*pScreen->SaveDoomedAreas) (pWin, pObscured, dx, dy);
|
|
|
|
|
2005-12-29 21:54:08 +01:00
|
|
|
SCREEN_EPILOGUE (pScreen, SaveDoomedAreas);
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2004-08-07 03:23:07 +02:00
|
|
|
* miPointer interface routines
|
2003-11-14 16:54:54 +01:00
|
|
|
*/
|
|
|
|
|
2004-08-07 03:23:07 +02:00
|
|
|
#define SPRITE_PAD 8
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2004-08-07 03:23:07 +02:00
|
|
|
static Bool
|
2006-11-17 05:40:37 +01:00
|
|
|
miSpriteRealizeCursor (pDev, pScreen, pCursor)
|
|
|
|
DeviceIntPtr pDev;
|
2004-08-07 03:23:07 +02:00
|
|
|
ScreenPtr pScreen;
|
|
|
|
CursorPtr pCursor;
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2004-08-07 03:23:07 +02:00
|
|
|
miSpriteScreenPtr pScreenPriv;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
|
2006-11-20 03:40:07 +01:00
|
|
|
if (pCursor == pScreenPriv->cp->pCursor)
|
|
|
|
pScreenPriv->cp->checkPixels = TRUE;
|
2006-11-20 08:28:30 +01:00
|
|
|
#ifdef MPX
|
|
|
|
{
|
|
|
|
int mpCursorIdx = 0;
|
|
|
|
while (mpCursorIdx < MAX_DEVICES)
|
|
|
|
{
|
|
|
|
miCursorInfoPtr pMPCursor = &pScreenPriv->mpCursors[mpCursorIdx];
|
|
|
|
|
|
|
|
if (pCursor == pMPCursor->pCursor)
|
|
|
|
pMPCursor->checkPixels = TRUE;
|
|
|
|
|
|
|
|
mpCursorIdx++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2004-08-07 03:23:07 +02:00
|
|
|
return (*pScreenPriv->funcs->RealizeCursor) (pScreen, pCursor);
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
2004-08-07 03:23:07 +02:00
|
|
|
static Bool
|
2006-11-17 05:40:37 +01:00
|
|
|
miSpriteUnrealizeCursor (pDev, pScreen, pCursor)
|
|
|
|
DeviceIntPtr pDev;
|
2004-08-07 03:23:07 +02:00
|
|
|
ScreenPtr pScreen;
|
|
|
|
CursorPtr pCursor;
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2004-08-07 03:23:07 +02:00
|
|
|
miSpriteScreenPtr pScreenPriv;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
|
2004-08-07 03:23:07 +02:00
|
|
|
return (*pScreenPriv->funcs->UnrealizeCursor) (pScreen, pCursor);
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2006-11-17 05:40:37 +01:00
|
|
|
miSpriteSetCursor (pDev, pScreen, pCursor, x, y)
|
|
|
|
DeviceIntPtr pDev;
|
2004-08-07 03:23:07 +02:00
|
|
|
ScreenPtr pScreen;
|
|
|
|
CursorPtr pCursor;
|
|
|
|
int x;
|
|
|
|
int y;
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
|
|
|
miSpriteScreenPtr pScreenPriv;
|
|
|
|
|
|
|
|
pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
|
2006-11-20 08:28:30 +01:00
|
|
|
miCursorInfoPtr pointer = pScreenPriv->cp;
|
|
|
|
#ifdef MPX
|
|
|
|
if (IsMPDev(pDev))
|
|
|
|
pointer = &pScreenPriv->mpCursors[pDev->id];
|
|
|
|
#endif
|
|
|
|
|
2004-08-07 03:23:07 +02:00
|
|
|
if (!pCursor)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2006-11-20 08:28:30 +01:00
|
|
|
pointer->shouldBeUp = FALSE;
|
|
|
|
if (pointer->isUp)
|
|
|
|
miSpriteRemoveCursor (pointer, pScreen);
|
|
|
|
pointer->pCursor = 0;
|
2004-08-07 03:23:07 +02:00
|
|
|
return;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
2006-11-20 08:28:30 +01:00
|
|
|
pointer->shouldBeUp = TRUE;
|
|
|
|
if (pointer->x == x &&
|
|
|
|
pointer->y == y &&
|
|
|
|
pointer->pCursor == pCursor &&
|
|
|
|
!pointer->checkPixels)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2004-08-07 03:23:07 +02:00
|
|
|
return;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
2006-11-20 08:28:30 +01:00
|
|
|
pointer->x = x;
|
|
|
|
pointer->y = y;
|
|
|
|
pointer->pCacheWin = NullWindow;
|
|
|
|
if (pointer->checkPixels || pointer->pCursor != pCursor)
|
2004-08-07 03:23:07 +02:00
|
|
|
{
|
2006-11-20 08:28:30 +01:00
|
|
|
pointer->pCursor = pCursor;
|
|
|
|
miSpriteFindColors (pointer, pScreen);
|
2004-08-07 03:23:07 +02:00
|
|
|
}
|
2006-11-20 08:28:30 +01:00
|
|
|
if (pointer->isUp) {
|
|
|
|
#if 0
|
|
|
|
/* FIXME: Disabled for MPX, should be rewritten */
|
2004-08-07 03:23:07 +02:00
|
|
|
int sx, sy;
|
|
|
|
/*
|
|
|
|
* check to see if the old saved region
|
|
|
|
* encloses the new sprite, in which case we use
|
|
|
|
* the flicker-free MoveCursor primitive.
|
|
|
|
*/
|
2006-11-20 08:28:30 +01:00
|
|
|
sx = pointer->x - (int)pCursor->bits->xhot;
|
|
|
|
sy = pointer->y - (int)pCursor->bits->yhot;
|
|
|
|
if (sx + (int) pCursor->bits->width >= pointer->saved.x1 &&
|
|
|
|
sx < pointer->saved.x2 &&
|
|
|
|
sy + (int) pCursor->bits->height >= pointer->saved.y1 &&
|
|
|
|
sy < pointer->saved.y2 &&
|
2004-08-07 03:23:07 +02:00
|
|
|
(int) pCursor->bits->width + (2 * SPRITE_PAD) ==
|
2006-11-20 08:28:30 +01:00
|
|
|
pointer->saved.x2 - pointer->saved.x1 &&
|
2004-08-07 03:23:07 +02:00
|
|
|
(int) pCursor->bits->height + (2 * SPRITE_PAD) ==
|
2006-11-20 08:28:30 +01:00
|
|
|
pointer->saved.y2 - pointer->saved.y1
|
2004-08-07 03:23:07 +02:00
|
|
|
)
|
|
|
|
{
|
|
|
|
DamageDrawInternal (pScreen, TRUE);
|
|
|
|
miSpriteIsUpFALSE (pScreen, pScreenPriv);
|
2006-11-20 08:28:30 +01:00
|
|
|
if (!(sx >= pointer->saved.x1 &&
|
|
|
|
sx + (int)pCursor->bits->width < pointer->saved.x2
|
|
|
|
&& sy >= pointer->saved.y1 &&
|
2006-11-20 03:40:07 +01:00
|
|
|
sy + (int)pCursor->bits->height <
|
2006-11-20 08:28:30 +01:00
|
|
|
pointer->saved.y2))
|
2006-11-20 03:40:07 +01:00
|
|
|
{
|
2004-08-07 03:23:07 +02:00
|
|
|
int oldx1, oldy1, dx, dy;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2006-11-20 08:28:30 +01:00
|
|
|
oldx1 = pointer->saved.x1;
|
|
|
|
oldy1 = pointer->saved.y1;
|
2003-11-14 16:54:54 +01:00
|
|
|
dx = oldx1 - (sx - SPRITE_PAD);
|
|
|
|
dy = oldy1 - (sy - SPRITE_PAD);
|
2006-11-20 08:28:30 +01:00
|
|
|
pointer->saved.x1 -= dx;
|
|
|
|
pointer->saved.y1 -= dy;
|
|
|
|
pointer->saved.x2 -= dx;
|
|
|
|
pointer->saved.y2 -= dy;
|
2003-11-14 16:54:54 +01:00
|
|
|
(void) (*pScreenPriv->funcs->ChangeSave) (pScreen,
|
2006-11-20 08:28:30 +01:00
|
|
|
pointer->saved.x1,
|
|
|
|
pointer->saved.y1,
|
|
|
|
pointer->saved.x2 -
|
|
|
|
pointer->saved.x1,
|
|
|
|
pointer->saved.y2 -
|
|
|
|
pointer->saved.y1,
|
2003-11-14 16:54:54 +01:00
|
|
|
dx, dy);
|
|
|
|
}
|
|
|
|
(void) (*pScreenPriv->funcs->MoveCursor) (pScreen, pCursor,
|
2006-11-20 08:28:30 +01:00
|
|
|
pointer->saved.x1,
|
|
|
|
pointer->saved.y1,
|
|
|
|
pointer->saved.x2 -
|
|
|
|
pointer->saved.x1,
|
|
|
|
pointer->saved.y2 -
|
|
|
|
pointer->saved.y1,
|
|
|
|
sx - pointer->saved.x1,
|
|
|
|
sy - pointer->saved.y1,
|
|
|
|
pointer->colors[SOURCE_COLOR].pixel,
|
|
|
|
pointer->colors[MASK_COLOR].pixel);
|
2004-08-07 03:23:07 +02:00
|
|
|
miSpriteIsUpTRUE (pScreen, pScreenPriv);
|
|
|
|
DamageDrawInternal (pScreen, FALSE);
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
else
|
2006-11-20 08:28:30 +01:00
|
|
|
#endif
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2004-08-07 03:23:07 +02:00
|
|
|
SPRITE_DEBUG (("SetCursor remove\n"));
|
2006-11-20 08:28:30 +01:00
|
|
|
miSpriteRemoveCursor (pointer, pScreen);
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
}
|
2006-11-20 08:28:30 +01:00
|
|
|
|
|
|
|
if (!pointer->isUp && pointer->pCursor)
|
2004-08-07 03:23:07 +02:00
|
|
|
{
|
|
|
|
SPRITE_DEBUG (("SetCursor restore\n"));
|
2006-11-20 08:28:30 +01:00
|
|
|
miSpriteRestoreCursor (pointer, pScreen);
|
2004-08-07 03:23:07 +02:00
|
|
|
}
|
2006-11-20 08:28:30 +01:00
|
|
|
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2006-11-17 05:40:37 +01:00
|
|
|
miSpriteMoveCursor (pDev, pScreen, x, y)
|
|
|
|
DeviceIntPtr pDev;
|
2003-11-14 16:54:54 +01:00
|
|
|
ScreenPtr pScreen;
|
|
|
|
int x, y;
|
|
|
|
{
|
|
|
|
miSpriteScreenPtr pScreenPriv;
|
2006-11-17 08:33:43 +01:00
|
|
|
CursorPtr pCursor;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
|
2006-11-20 03:40:07 +01:00
|
|
|
pCursor = pScreenPriv->cp->pCursor;
|
2006-11-20 08:28:30 +01:00
|
|
|
|
2006-11-17 08:33:43 +01:00
|
|
|
#ifdef MPX
|
|
|
|
if (IsMPDev(pDev))
|
|
|
|
pCursor = pScreenPriv->mpCursors[pDev->id].pCursor;
|
|
|
|
#endif
|
|
|
|
miSpriteSetCursor (pDev, pScreen, pCursor, x, y);
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* undraw/draw cursor
|
|
|
|
*/
|
|
|
|
|
|
|
|
static void
|
2006-11-20 08:28:30 +01:00
|
|
|
miSpriteRemoveCursor (pDevCursor, pScreen)
|
|
|
|
miCursorInfoPtr pDevCursor;
|
2003-11-14 16:54:54 +01:00
|
|
|
ScreenPtr pScreen;
|
|
|
|
{
|
|
|
|
miSpriteScreenPtr pScreenPriv;
|
|
|
|
|
2004-08-07 03:23:07 +02:00
|
|
|
DamageDrawInternal (pScreen, TRUE);
|
2003-11-14 16:54:54 +01:00
|
|
|
pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
|
2006-11-20 08:28:30 +01:00
|
|
|
miSpriteIsUpFALSE (pDevCursor, pScreen, pScreenPriv);
|
|
|
|
pDevCursor->pCacheWin = NullWindow;
|
2006-11-21 04:30:46 +01:00
|
|
|
if (!(*pScreenPriv->funcs->RestoreUnderCursor) (pDevCursor->id,
|
|
|
|
pScreen,
|
2006-11-20 08:28:30 +01:00
|
|
|
pDevCursor->saved.x1,
|
|
|
|
pDevCursor->saved.y1,
|
|
|
|
pDevCursor->saved.x2 -
|
|
|
|
pDevCursor->saved.x1,
|
|
|
|
pDevCursor->saved.y2 -
|
|
|
|
pDevCursor->saved.y1))
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2006-11-20 08:28:30 +01:00
|
|
|
miSpriteIsUpTRUE (pDevCursor, pScreen, pScreenPriv);
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
2004-08-07 03:23:07 +02:00
|
|
|
DamageDrawInternal (pScreen, FALSE);
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Called from the block handler, restores the cursor
|
|
|
|
* before waiting for something to do.
|
|
|
|
*/
|
|
|
|
|
|
|
|
static void
|
2006-11-20 08:28:30 +01:00
|
|
|
miSpriteRestoreCursor (pDevCursor, pScreen)
|
|
|
|
miCursorInfoPtr pDevCursor;
|
2003-11-14 16:54:54 +01:00
|
|
|
ScreenPtr pScreen;
|
|
|
|
{
|
|
|
|
miSpriteScreenPtr pScreenPriv;
|
|
|
|
int x, y;
|
|
|
|
CursorPtr pCursor;
|
|
|
|
|
2004-08-07 03:23:07 +02:00
|
|
|
DamageDrawInternal (pScreen, TRUE);
|
2006-11-20 08:28:30 +01:00
|
|
|
miSpriteComputeSaved (pDevCursor, pScreen);
|
2003-11-14 16:54:54 +01:00
|
|
|
pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
|
2006-11-20 08:28:30 +01:00
|
|
|
pCursor = pDevCursor->pCursor;
|
|
|
|
x = pDevCursor->x - (int)pCursor->bits->xhot;
|
|
|
|
y = pDevCursor->y - (int)pCursor->bits->yhot;
|
2006-11-21 04:30:46 +01:00
|
|
|
if ((*pScreenPriv->funcs->SaveUnderCursor) (pDevCursor->id,
|
|
|
|
pScreen,
|
2006-11-20 08:28:30 +01:00
|
|
|
pDevCursor->saved.x1,
|
|
|
|
pDevCursor->saved.y1,
|
|
|
|
pDevCursor->saved.x2 -
|
|
|
|
pDevCursor->saved.x1,
|
|
|
|
pDevCursor->saved.y2 -
|
|
|
|
pDevCursor->saved.y1))
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2006-11-20 08:28:30 +01:00
|
|
|
if (pDevCursor->checkPixels)
|
|
|
|
miSpriteFindColors (pDevCursor, pScreen);
|
2006-11-21 04:30:46 +01:00
|
|
|
if ((*pScreenPriv->funcs->PutUpCursor) (pDevCursor->id, pScreen,
|
|
|
|
pCursor, x, y,
|
2006-11-20 08:28:30 +01:00
|
|
|
pDevCursor->colors[SOURCE_COLOR].pixel,
|
|
|
|
pDevCursor->colors[MASK_COLOR].pixel))
|
2004-08-07 03:23:07 +02:00
|
|
|
{
|
2006-11-20 08:28:30 +01:00
|
|
|
miSpriteIsUpTRUE (pDevCursor, pScreen, pScreenPriv);
|
2004-08-07 03:23:07 +02:00
|
|
|
}
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
2004-08-07 03:23:07 +02:00
|
|
|
DamageDrawInternal (pScreen, FALSE);
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* compute the desired area of the screen to save
|
|
|
|
*/
|
|
|
|
|
|
|
|
static void
|
2006-11-20 08:28:30 +01:00
|
|
|
miSpriteComputeSaved (pDevCursor, pScreen)
|
|
|
|
miCursorInfoPtr pDevCursor;
|
2003-11-14 16:54:54 +01:00
|
|
|
ScreenPtr pScreen;
|
|
|
|
{
|
|
|
|
miSpriteScreenPtr pScreenPriv;
|
|
|
|
int x, y, w, h;
|
|
|
|
int wpad, hpad;
|
|
|
|
CursorPtr pCursor;
|
|
|
|
|
|
|
|
pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
|
2006-11-20 08:28:30 +01:00
|
|
|
pCursor = pDevCursor->pCursor;
|
|
|
|
x = pDevCursor->x - (int)pCursor->bits->xhot;
|
|
|
|
y = pDevCursor->y - (int)pCursor->bits->yhot;
|
2003-11-14 16:54:54 +01:00
|
|
|
w = pCursor->bits->width;
|
|
|
|
h = pCursor->bits->height;
|
|
|
|
wpad = SPRITE_PAD;
|
|
|
|
hpad = SPRITE_PAD;
|
2006-11-20 08:28:30 +01:00
|
|
|
pDevCursor->saved.x1 = x - wpad;
|
|
|
|
pDevCursor->saved.y1 = y - hpad;
|
|
|
|
pDevCursor->saved.x2 = pDevCursor->saved.x1 + w + wpad * 2;
|
|
|
|
pDevCursor->saved.y2 = pDevCursor->saved.y1 + h + hpad * 2;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|