]> git.sesse.net Git - rdpsrv/blob - Xserver/programs/Xserver/mi/misprite.c
Support RDP5 logon packets.
[rdpsrv] / Xserver / programs / Xserver / mi / misprite.c
1 /*
2  * misprite.c
3  *
4  * machine independent software sprite routines
5  */
6
7 /* $XConsortium: misprite.c,v 5.47 94/04/17 20:27:53 dpw Exp $ */
8 /* $XFree86: xc/programs/Xserver/mi/misprite.c,v 3.0 1996/08/25 14:13:56 dawes Exp $ */
9
10 /*
11
12 Copyright (c) 1989  X Consortium
13
14 Permission is hereby granted, free of charge, to any person obtaining a copy
15 of this software and associated documentation files (the "Software"), to deal
16 in the Software without restriction, including without limitation the rights
17 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
18 copies of the Software, and to permit persons to whom the Software is
19 furnished to do so, subject to the following conditions:
20
21 The above copyright notice and this permission notice shall be included in
22 all copies or substantial portions of the Software.
23
24 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
27 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
28 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30
31 Except as contained in this notice, the name of the X Consortium shall not be
32 used in advertising or otherwise to promote the sale, use or other dealings
33 in this Software without prior written authorization from the X Consortium.
34 */
35
36 # include   "X.h"
37 # include   "Xproto.h"
38 # include   "misc.h"
39 # include   "pixmapstr.h"
40 # include   "input.h"
41 # include   "mi.h"
42 # include   "cursorstr.h"
43 # include   "font.h"
44 # include   "scrnintstr.h"
45 # include   "colormapst.h"
46 # include   "windowstr.h"
47 # include   "gcstruct.h"
48 # include   "mipointer.h"
49 # include   "mispritest.h"
50 # include   "dixfontstr.h"
51 # include   "fontstruct.h"
52
53 /*
54  * screen wrappers
55  */
56
57 static int  miSpriteScreenIndex;
58 static unsigned long miSpriteGeneration = 0;
59
60 static Bool         miSpriteCloseScreen();
61 static void         miSpriteGetImage();
62 static void         miSpriteGetSpans();
63 static void         miSpriteSourceValidate();
64 static Bool         miSpriteCreateGC();
65 static void         miSpriteBlockHandler();
66 static void         miSpriteInstallColormap();
67 static void         miSpriteStoreColors();
68
69 static void         miSpritePaintWindowBackground();
70 static void         miSpritePaintWindowBorder();
71 static void         miSpriteCopyWindow();
72 static void         miSpriteClearToBackground();
73
74 static void         miSpriteSaveDoomedAreas();
75 static RegionPtr    miSpriteRestoreAreas();
76 static void         miSpriteComputeSaved();
77
78 #define SCREEN_PROLOGUE(pScreen, field)\
79   ((pScreen)->field = \
80    ((miSpriteScreenPtr) (pScreen)->devPrivates[miSpriteScreenIndex].ptr)->field)
81
82 #define SCREEN_EPILOGUE(pScreen, field, wrapper)\
83     ((pScreen)->field = wrapper)
84
85 /*
86  * GC func wrappers
87  */
88
89 static int  miSpriteGCIndex;
90
91 static void miSpriteValidateGC (),  miSpriteCopyGC ();
92 static void miSpriteDestroyGC(),    miSpriteChangeGC();
93 static void miSpriteChangeClip(),   miSpriteDestroyClip();
94 static void miSpriteCopyClip();
95
96 static GCFuncs  miSpriteGCFuncs = {
97     miSpriteValidateGC,
98     miSpriteChangeGC,
99     miSpriteCopyGC,
100     miSpriteDestroyGC,
101     miSpriteChangeClip,
102     miSpriteDestroyClip,
103     miSpriteCopyClip,
104 };
105
106 #define GC_FUNC_PROLOGUE(pGC)                                   \
107     miSpriteGCPtr   pGCPriv =                                   \
108         (miSpriteGCPtr) (pGC)->devPrivates[miSpriteGCIndex].ptr;\
109     (pGC)->funcs = pGCPriv->wrapFuncs;                          \
110     if (pGCPriv->wrapOps)                                       \
111         (pGC)->ops = pGCPriv->wrapOps;
112
113 #define GC_FUNC_EPILOGUE(pGC)                                   \
114     pGCPriv->wrapFuncs = (pGC)->funcs;                          \
115     (pGC)->funcs = &miSpriteGCFuncs;                            \
116     if (pGCPriv->wrapOps)                                       \
117     {                                                           \
118         pGCPriv->wrapOps = (pGC)->ops;                          \
119         (pGC)->ops = &miSpriteGCOps;                            \
120     }
121
122 /*
123  * GC op wrappers
124  */
125
126 static void         miSpriteFillSpans(),        miSpriteSetSpans();
127 static void         miSpritePutImage();
128 static RegionPtr    miSpriteCopyArea(),         miSpriteCopyPlane();
129 static void         miSpritePolyPoint(),        miSpritePolylines();
130 static void         miSpritePolySegment(),      miSpritePolyRectangle();
131 static void         miSpritePolyArc(),          miSpriteFillPolygon();
132 static void         miSpritePolyFillRect(),     miSpritePolyFillArc();
133 static int          miSpritePolyText8(),        miSpritePolyText16();
134 static void         miSpriteImageText8(),       miSpriteImageText16();
135 static void         miSpriteImageGlyphBlt(),    miSpritePolyGlyphBlt();
136 static void         miSpritePushPixels();
137 #ifdef NEED_LINEHELPER
138 static void         miSpriteLineHelper();
139 #endif
140
141 static GCOps miSpriteGCOps = {
142     miSpriteFillSpans,      miSpriteSetSpans,       miSpritePutImage,   
143     miSpriteCopyArea,       miSpriteCopyPlane,      miSpritePolyPoint,
144     miSpritePolylines,      miSpritePolySegment,    miSpritePolyRectangle,
145     miSpritePolyArc,        miSpriteFillPolygon,    miSpritePolyFillRect,
146     miSpritePolyFillArc,    miSpritePolyText8,      miSpritePolyText16,
147     miSpriteImageText8,     miSpriteImageText16,    miSpriteImageGlyphBlt,
148     miSpritePolyGlyphBlt,   miSpritePushPixels
149 #ifdef NEED_LINEHELPER
150     , miSpriteLineHelper
151 #endif
152 };
153
154 /*
155  * testing only -- remove cursor for every draw.  Eventually,
156  * each draw operation will perform a bounding box check against
157  * the saved cursor area
158  */
159
160 #define GC_SETUP_CHEAP(pDrawable)                                   \
161     miSpriteScreenPtr   pScreenPriv = (miSpriteScreenPtr)           \
162         (pDrawable)->pScreen->devPrivates[miSpriteScreenIndex].ptr; \
163
164 #define GC_SETUP(pDrawable, pGC)                                    \
165     GC_SETUP_CHEAP(pDrawable)                                       \
166     miSpriteGCPtr       pGCPrivate = (miSpriteGCPtr)                \
167         (pGC)->devPrivates[miSpriteGCIndex].ptr;                    \
168     GCFuncs *oldFuncs = pGC->funcs;
169
170 #define GC_SETUP_AND_CHECK(pDrawable, pGC)                          \
171     GC_SETUP(pDrawable, pGC);                                       \
172     if (GC_CHECK((WindowPtr)pDrawable))                             \
173         miSpriteRemoveCursor (pDrawable->pScreen);
174     
175 #define GC_CHECK(pWin)                                              \
176     (pScreenPriv->isUp &&                                           \
177         (pScreenPriv->pCacheWin == pWin ?                           \
178             pScreenPriv->isInCacheWin : (                           \
179             (pScreenPriv->pCacheWin = (pWin)),                      \
180             (pScreenPriv->isInCacheWin =                            \
181                 (pWin)->drawable.x < pScreenPriv->saved.x2 &&       \
182                 pScreenPriv->saved.x1 < (pWin)->drawable.x +        \
183                                     (int) (pWin)->drawable.width && \
184                 (pWin)->drawable.y < pScreenPriv->saved.y2 &&       \
185                 pScreenPriv->saved.y1 < (pWin)->drawable.y +        \
186                                     (int) (pWin)->drawable.height &&\
187                 RECT_IN_REGION((pWin)->drawable.pScreen, &(pWin)->borderClip, \
188                         &pScreenPriv->saved) != rgnOUT))))
189
190 #define GC_OP_PROLOGUE(pGC) { \
191     (pGC)->funcs = pGCPrivate->wrapFuncs; \
192     (pGC)->ops = pGCPrivate->wrapOps; \
193     }
194
195 #define GC_OP_EPILOGUE(pGC) { \
196     pGCPrivate->wrapOps = (pGC)->ops; \
197     (pGC)->funcs = oldFuncs; \
198     (pGC)->ops = &miSpriteGCOps; \
199     }
200
201 /*
202  * pointer-sprite method table
203  */
204
205 static Bool miSpriteRealizeCursor (),   miSpriteUnrealizeCursor ();
206 static void miSpriteSetCursor (),       miSpriteMoveCursor ();
207
208 miPointerSpriteFuncRec miSpritePointerFuncs = {
209     miSpriteRealizeCursor,
210     miSpriteUnrealizeCursor,
211     miSpriteSetCursor,
212     miSpriteMoveCursor,
213 };
214
215 /*
216  * other misc functions
217  */
218
219 static void miSpriteRemoveCursor (),    miSpriteRestoreCursor();
220
221 /*
222  * miSpriteInitialize -- called from device-dependent screen
223  * initialization proc after all of the function pointers have
224  * been stored in the screen structure.
225  */
226
227 Bool
228 miSpriteInitialize (pScreen, cursorFuncs, screenFuncs)
229     ScreenPtr               pScreen;
230     miSpriteCursorFuncPtr   cursorFuncs;
231     miPointerScreenFuncPtr  screenFuncs;
232 {
233     miSpriteScreenPtr   pPriv;
234     VisualPtr           pVisual;
235     
236     if (miSpriteGeneration != serverGeneration)
237     {
238         miSpriteScreenIndex = AllocateScreenPrivateIndex ();
239         if (miSpriteScreenIndex < 0)
240             return FALSE;
241         miSpriteGeneration = serverGeneration;
242         miSpriteGCIndex = AllocateGCPrivateIndex ();
243     }
244     if (!AllocateGCPrivate(pScreen, miSpriteGCIndex, sizeof(miSpriteGCRec)))
245         return FALSE;
246     pPriv = (miSpriteScreenPtr) xalloc (sizeof (miSpriteScreenRec));
247     if (!pPriv)
248         return FALSE;
249     if (!miPointerInitialize (pScreen, &miSpritePointerFuncs, screenFuncs,TRUE))
250     {
251         xfree ((pointer) pPriv);
252         return FALSE;
253     }
254     for (pVisual = pScreen->visuals;
255          pVisual->vid != pScreen->rootVisual;
256          pVisual++)
257         ;
258     pPriv->pVisual = pVisual;
259     pPriv->CloseScreen = pScreen->CloseScreen;
260     pPriv->GetImage = pScreen->GetImage;
261     pPriv->GetSpans = pScreen->GetSpans;
262     pPriv->SourceValidate = pScreen->SourceValidate;
263     pPriv->CreateGC = pScreen->CreateGC;
264     pPriv->BlockHandler = pScreen->BlockHandler;
265     pPriv->InstallColormap = pScreen->InstallColormap;
266     pPriv->StoreColors = pScreen->StoreColors;
267
268     pPriv->PaintWindowBackground = pScreen->PaintWindowBackground;
269     pPriv->PaintWindowBorder = pScreen->PaintWindowBorder;
270     pPriv->CopyWindow = pScreen->CopyWindow;
271     pPriv->ClearToBackground = pScreen->ClearToBackground;
272
273     pPriv->SaveDoomedAreas = pScreen->SaveDoomedAreas;
274     pPriv->RestoreAreas = pScreen->RestoreAreas;
275
276     pPriv->pCursor = NULL;
277     pPriv->x = 0;
278     pPriv->y = 0;
279     pPriv->isUp = FALSE;
280     pPriv->shouldBeUp = FALSE;
281     pPriv->pCacheWin = NullWindow;
282     pPriv->isInCacheWin = FALSE;
283     pPriv->checkPixels = TRUE;
284     pPriv->pInstalledMap = NULL;
285     pPriv->pColormap = NULL;
286     pPriv->funcs = cursorFuncs;
287     pPriv->colors[SOURCE_COLOR].red = 0;
288     pPriv->colors[SOURCE_COLOR].green = 0;
289     pPriv->colors[SOURCE_COLOR].blue = 0;
290     pPriv->colors[MASK_COLOR].red = 0;
291     pPriv->colors[MASK_COLOR].green = 0;
292     pPriv->colors[MASK_COLOR].blue = 0;
293     pScreen->devPrivates[miSpriteScreenIndex].ptr = (pointer) pPriv;
294     pScreen->CloseScreen = miSpriteCloseScreen;
295     pScreen->GetImage = miSpriteGetImage;
296     pScreen->GetSpans = miSpriteGetSpans;
297     pScreen->SourceValidate = miSpriteSourceValidate;
298     pScreen->CreateGC = miSpriteCreateGC;
299     pScreen->BlockHandler = miSpriteBlockHandler;
300     pScreen->InstallColormap = miSpriteInstallColormap;
301     pScreen->StoreColors = miSpriteStoreColors;
302
303     pScreen->PaintWindowBackground = miSpritePaintWindowBackground;
304     pScreen->PaintWindowBorder = miSpritePaintWindowBorder;
305     pScreen->CopyWindow = miSpriteCopyWindow;
306     pScreen->ClearToBackground = miSpriteClearToBackground;
307
308     pScreen->SaveDoomedAreas = miSpriteSaveDoomedAreas;
309     pScreen->RestoreAreas = miSpriteRestoreAreas;
310
311     return TRUE;
312 }
313
314 /*
315  * Screen wrappers
316  */
317
318 /*
319  * CloseScreen wrapper -- unwrap everything, free the private data
320  * and call the wrapped function
321  */
322
323 static Bool
324 miSpriteCloseScreen (i, pScreen)
325     ScreenPtr   pScreen;
326 {
327     miSpriteScreenPtr   pScreenPriv;
328
329     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
330
331     pScreen->CloseScreen = pScreenPriv->CloseScreen;
332     pScreen->GetImage = pScreenPriv->GetImage;
333     pScreen->GetSpans = pScreenPriv->GetSpans;
334     pScreen->SourceValidate = pScreenPriv->SourceValidate;
335     pScreen->CreateGC = pScreenPriv->CreateGC;
336     pScreen->BlockHandler = pScreenPriv->BlockHandler;
337     pScreen->InstallColormap = pScreenPriv->InstallColormap;
338     pScreen->StoreColors = pScreenPriv->StoreColors;
339
340     pScreen->PaintWindowBackground = pScreenPriv->PaintWindowBackground;
341     pScreen->PaintWindowBorder = pScreenPriv->PaintWindowBorder;
342     pScreen->CopyWindow = pScreenPriv->CopyWindow;
343     pScreen->ClearToBackground = pScreenPriv->ClearToBackground;
344
345     pScreen->SaveDoomedAreas = pScreenPriv->SaveDoomedAreas;
346     pScreen->RestoreAreas = pScreenPriv->RestoreAreas;
347
348     xfree ((pointer) pScreenPriv);
349
350     return (*pScreen->CloseScreen) (i, pScreen);
351 }
352
353 static void
354 miSpriteGetImage (pDrawable, sx, sy, w, h, format, planemask, pdstLine)
355     DrawablePtr     pDrawable;
356     int             sx, sy, w, h;
357     unsigned int    format;
358     unsigned long   planemask;
359     char            *pdstLine;
360 {
361     ScreenPtr       pScreen = pDrawable->pScreen;
362     miSpriteScreenPtr    pScreenPriv;
363     
364     SCREEN_PROLOGUE (pScreen, GetImage);
365
366     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
367
368     if (pDrawable->type == DRAWABLE_WINDOW &&
369         pScreenPriv->isUp &&
370         ORG_OVERLAP(&pScreenPriv->saved,pDrawable->x,pDrawable->y, sx, sy, w, h))
371     {
372         miSpriteRemoveCursor (pScreen);
373     }
374
375     (*pScreen->GetImage) (pDrawable, sx, sy, w, h,
376                           format, planemask, pdstLine);
377
378     SCREEN_EPILOGUE (pScreen, GetImage, miSpriteGetImage);
379 }
380
381 static void
382 miSpriteGetSpans (pDrawable, wMax, ppt, pwidth, nspans, pdstStart)
383     DrawablePtr pDrawable;
384     int         wMax;
385     DDXPointPtr ppt;
386     int         *pwidth;
387     int         nspans;
388     char        *pdstStart;
389 {
390     ScreenPtr               pScreen = pDrawable->pScreen;
391     miSpriteScreenPtr       pScreenPriv;
392     
393     SCREEN_PROLOGUE (pScreen, GetSpans);
394
395     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
396
397     if (pDrawable->type == DRAWABLE_WINDOW && pScreenPriv->isUp)
398     {
399         register DDXPointPtr    pts;
400         register int            *widths;
401         register int            nPts;
402         register int            xorg,
403                                 yorg;
404
405         xorg = pDrawable->x;
406         yorg = pDrawable->y;
407
408         for (pts = ppt, widths = pwidth, nPts = nspans;
409              nPts--;
410              pts++, widths++)
411         {
412             if (SPN_OVERLAP(&pScreenPriv->saved,pts->y+yorg,
413                              pts->x+xorg,*widths))
414             {
415                 miSpriteRemoveCursor (pScreen);
416                 break;
417             }
418         }
419     }
420
421     (*pScreen->GetSpans) (pDrawable, wMax, ppt, pwidth, nspans, pdstStart);
422
423     SCREEN_EPILOGUE (pScreen, GetSpans, miSpriteGetSpans);
424 }
425
426 static void
427 miSpriteSourceValidate (pDrawable, x, y, width, height)
428     DrawablePtr pDrawable;
429     int         x, y, width, height;
430 {
431     ScreenPtr               pScreen = pDrawable->pScreen;
432     miSpriteScreenPtr       pScreenPriv;
433     
434     SCREEN_PROLOGUE (pScreen, SourceValidate);
435
436     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
437
438     if (pDrawable->type == DRAWABLE_WINDOW && pScreenPriv->isUp &&
439         ORG_OVERLAP(&pScreenPriv->saved, pDrawable->x, pDrawable->y,
440                     x, y, width, height))
441     {
442         miSpriteRemoveCursor (pScreen);
443     }
444
445     if (pScreen->SourceValidate)
446         (*pScreen->SourceValidate) (pDrawable, x, y, width, height);
447
448     SCREEN_EPILOGUE (pScreen, SourceValidate, miSpriteSourceValidate);
449 }
450
451 static Bool
452 miSpriteCreateGC (pGC)
453     GCPtr   pGC;
454 {
455     ScreenPtr       pScreen = pGC->pScreen;
456     Bool            ret;
457     miSpriteGCPtr   pPriv;
458
459     SCREEN_PROLOGUE (pScreen, CreateGC);
460     
461     pPriv = (miSpriteGCPtr)pGC->devPrivates[miSpriteGCIndex].ptr;
462
463     ret = (*pScreen->CreateGC) (pGC);
464
465     pPriv->wrapOps = NULL;
466     pPriv->wrapFuncs = pGC->funcs;
467     pGC->funcs = &miSpriteGCFuncs;
468
469     SCREEN_EPILOGUE (pScreen, CreateGC, miSpriteCreateGC);
470
471     return ret;
472 }
473
474 static void
475 miSpriteBlockHandler (i, blockData, pTimeout, pReadmask)
476     int i;
477     pointer     blockData;
478     OSTimePtr   pTimeout;
479     pointer     pReadmask;
480 {
481     ScreenPtr           pScreen = screenInfo.screens[i];
482     miSpriteScreenPtr   pPriv;
483
484     pPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
485
486     SCREEN_PROLOGUE(pScreen, BlockHandler);
487     
488     (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask);
489
490     SCREEN_EPILOGUE(pScreen, BlockHandler, miSpriteBlockHandler);
491
492     if (!pPriv->isUp && pPriv->shouldBeUp)
493         miSpriteRestoreCursor (pScreen);
494 }
495
496 static void
497 miSpriteInstallColormap (pMap)
498     ColormapPtr pMap;
499 {
500     ScreenPtr           pScreen = pMap->pScreen;
501     miSpriteScreenPtr   pPriv;
502
503     pPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
504
505     SCREEN_PROLOGUE(pScreen, InstallColormap);
506     
507     (*pScreen->InstallColormap) (pMap);
508
509     SCREEN_EPILOGUE(pScreen, InstallColormap, miSpriteInstallColormap);
510
511     pPriv->pInstalledMap = pMap;
512     if (pPriv->pColormap != pMap)
513     {
514         pPriv->checkPixels = TRUE;
515         if (pPriv->isUp)
516             miSpriteRemoveCursor (pScreen);
517     }
518 }
519
520 static void
521 miSpriteStoreColors (pMap, ndef, pdef)
522     ColormapPtr pMap;
523     int         ndef;
524     xColorItem  *pdef;
525 {
526     ScreenPtr           pScreen = pMap->pScreen;
527     miSpriteScreenPtr   pPriv;
528     int                 i;
529     int                 updated;
530     VisualPtr           pVisual;
531
532     pPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
533
534     SCREEN_PROLOGUE(pScreen, StoreColors);
535     
536     (*pScreen->StoreColors) (pMap, ndef, pdef);
537
538     SCREEN_EPILOGUE(pScreen, StoreColors, miSpriteStoreColors);
539
540     if (pPriv->pColormap == pMap)
541     {
542         updated = 0;
543         pVisual = pMap->pVisual;
544         if (pVisual->class == DirectColor)
545         {
546             /* Direct color - match on any of the subfields */
547
548 #define MaskMatch(a,b,mask) ((a) & (pVisual->mask) == (b) & (pVisual->mask))
549
550 #define UpdateDAC(plane,dac,mask) {\
551     if (MaskMatch (pPriv->colors[plane].pixel,pdef[i].pixel,mask)) {\
552         pPriv->colors[plane].dac = pdef[i].dac; \
553         updated = 1; \
554     } \
555 }
556
557 #define CheckDirect(plane) \
558             UpdateDAC(plane,red,redMask) \
559             UpdateDAC(plane,green,greenMask) \
560             UpdateDAC(plane,blue,blueMask)
561
562             for (i = 0; i < ndef; i++)
563             {
564                 CheckDirect (SOURCE_COLOR)
565                 CheckDirect (MASK_COLOR)
566             }
567         }
568         else
569         {
570             /* PseudoColor/GrayScale - match on exact pixel */
571             for (i = 0; i < ndef; i++)
572             {
573                 if (pdef[i].pixel == pPriv->colors[SOURCE_COLOR].pixel)
574                 {
575                     pPriv->colors[SOURCE_COLOR] = pdef[i];
576                     if (++updated == 2)
577                         break;
578                 }
579                 if (pdef[i].pixel == pPriv->colors[MASK_COLOR].pixel)
580                 {
581                     pPriv->colors[MASK_COLOR] = pdef[i];
582                     if (++updated == 2)
583                         break;
584                 }
585             }
586         }
587         if (updated)
588         {
589             pPriv->checkPixels = TRUE;
590             if (pPriv->isUp)
591                 miSpriteRemoveCursor (pScreen);
592         }
593     }
594 }
595
596 static void
597 miSpriteFindColors (pScreen)
598     ScreenPtr   pScreen;
599 {
600     miSpriteScreenPtr   pScreenPriv = (miSpriteScreenPtr)
601                             pScreen->devPrivates[miSpriteScreenIndex].ptr;
602     CursorPtr           pCursor;
603     xColorItem          *sourceColor, *maskColor;
604
605     pCursor = pScreenPriv->pCursor;
606     sourceColor = &pScreenPriv->colors[SOURCE_COLOR];
607     maskColor = &pScreenPriv->colors[MASK_COLOR];
608     if (pScreenPriv->pColormap != pScreenPriv->pInstalledMap ||
609         !(pCursor->foreRed == sourceColor->red &&
610           pCursor->foreGreen == sourceColor->green &&
611           pCursor->foreBlue == sourceColor->blue &&
612           pCursor->backRed == maskColor->red &&
613           pCursor->backGreen == maskColor->green &&
614           pCursor->backBlue == maskColor->blue))
615     {
616         pScreenPriv->pColormap = pScreenPriv->pInstalledMap;
617         sourceColor->red = pCursor->foreRed;
618         sourceColor->green = pCursor->foreGreen;
619         sourceColor->blue = pCursor->foreBlue;
620         FakeAllocColor (pScreenPriv->pColormap, sourceColor);
621         maskColor->red = pCursor->backRed;
622         maskColor->green = pCursor->backGreen;
623         maskColor->blue = pCursor->backBlue;
624         FakeAllocColor (pScreenPriv->pColormap, maskColor);
625         /* "free" the pixels right away, don't let this confuse you */
626         FakeFreeColor(pScreenPriv->pColormap, sourceColor->pixel);
627         FakeFreeColor(pScreenPriv->pColormap, maskColor->pixel);
628     }
629     pScreenPriv->checkPixels = FALSE;
630 }
631
632 /*
633  * BackingStore wrappers
634  */
635
636 static void
637 miSpriteSaveDoomedAreas (pWin, pObscured, dx, dy)
638     WindowPtr   pWin;
639     RegionPtr   pObscured;
640     int         dx, dy;
641 {
642     ScreenPtr           pScreen;
643     miSpriteScreenPtr   pScreenPriv;
644     BoxRec              cursorBox;
645
646     pScreen = pWin->drawable.pScreen;
647     
648     SCREEN_PROLOGUE (pScreen, SaveDoomedAreas);
649
650     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
651     if (pScreenPriv->isUp)
652     {
653         cursorBox = pScreenPriv->saved;
654
655         if (dx || dy)
656         {
657             cursorBox.x1 += dx;
658             cursorBox.y1 += dy;
659             cursorBox.x2 += dx;
660             cursorBox.y2 += dy;
661         }
662         if (RECT_IN_REGION( pScreen, pObscured, &cursorBox) != rgnOUT)
663             miSpriteRemoveCursor (pScreen);
664     }
665
666     (*pScreen->SaveDoomedAreas) (pWin, pObscured, dx, dy);
667
668     SCREEN_EPILOGUE (pScreen, SaveDoomedAreas, miSpriteSaveDoomedAreas);
669 }
670
671 static RegionPtr
672 miSpriteRestoreAreas (pWin, prgnExposed)
673     WindowPtr   pWin;
674     RegionPtr   prgnExposed;
675 {
676     ScreenPtr           pScreen;
677     miSpriteScreenPtr   pScreenPriv;
678     RegionPtr           result;
679
680     pScreen = pWin->drawable.pScreen;
681     
682     SCREEN_PROLOGUE (pScreen, RestoreAreas);
683
684     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
685     if (pScreenPriv->isUp)
686     {
687         if (RECT_IN_REGION( pScreen, prgnExposed, &pScreenPriv->saved) != rgnOUT)
688             miSpriteRemoveCursor (pScreen);
689     }
690
691     result = (*pScreen->RestoreAreas) (pWin, prgnExposed);
692
693     SCREEN_EPILOGUE (pScreen, RestoreAreas, miSpriteRestoreAreas);
694
695     return result;
696 }
697
698 /*
699  * Window wrappers
700  */
701
702 static void
703 miSpritePaintWindowBackground (pWin, pRegion, what)
704     WindowPtr   pWin;
705     RegionPtr   pRegion;
706     int         what;
707 {
708     ScreenPtr       pScreen;
709     miSpriteScreenPtr    pScreenPriv;
710
711     pScreen = pWin->drawable.pScreen;
712
713     SCREEN_PROLOGUE (pScreen, PaintWindowBackground);
714
715     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
716     if (pScreenPriv->isUp)
717     {
718         /*
719          * If the cursor is on the same screen as the window, check the
720          * region to paint for the cursor and remove it as necessary
721          */
722         if (RECT_IN_REGION( pScreen, pRegion, &pScreenPriv->saved) != rgnOUT)
723             miSpriteRemoveCursor (pScreen);
724     }
725
726     (*pScreen->PaintWindowBackground) (pWin, pRegion, what);
727
728     SCREEN_EPILOGUE (pScreen, PaintWindowBackground, miSpritePaintWindowBackground);
729 }
730
731 static void
732 miSpritePaintWindowBorder (pWin, pRegion, what)
733     WindowPtr   pWin;
734     RegionPtr   pRegion;
735     int         what;
736 {
737     ScreenPtr       pScreen;
738     miSpriteScreenPtr    pScreenPriv;
739
740     pScreen = pWin->drawable.pScreen;
741
742     SCREEN_PROLOGUE (pScreen, PaintWindowBorder);
743
744     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
745     if (pScreenPriv->isUp)
746     {
747         /*
748          * If the cursor is on the same screen as the window, check the
749          * region to paint for the cursor and remove it as necessary
750          */
751         if (RECT_IN_REGION( pScreen, pRegion, &pScreenPriv->saved) != rgnOUT)
752             miSpriteRemoveCursor (pScreen);
753     }
754
755     (*pScreen->PaintWindowBorder) (pWin, pRegion, what);
756
757     SCREEN_EPILOGUE (pScreen, PaintWindowBorder, miSpritePaintWindowBorder);
758 }
759
760 static void
761 miSpriteCopyWindow (pWin, ptOldOrg, pRegion)
762     WindowPtr   pWin;
763     DDXPointRec ptOldOrg;
764     RegionPtr   pRegion;
765 {
766     ScreenPtr       pScreen;
767     miSpriteScreenPtr    pScreenPriv;
768     BoxRec          cursorBox;
769     int             dx, dy;
770
771     pScreen = pWin->drawable.pScreen;
772
773     SCREEN_PROLOGUE (pScreen, CopyWindow);
774
775     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
776     if (pScreenPriv->isUp)
777     {
778         /*
779          * check both the source and the destination areas.  The given
780          * region is source relative, so offset the cursor box by
781          * the delta position
782          */
783         cursorBox = pScreenPriv->saved;
784         dx = pWin->drawable.x - ptOldOrg.x;
785         dy = pWin->drawable.y - ptOldOrg.y;
786         cursorBox.x1 -= dx;
787         cursorBox.x2 -= dx;
788         cursorBox.y1 -= dy;
789         cursorBox.y2 -= dy;
790         if (RECT_IN_REGION( pScreen, pRegion, &pScreenPriv->saved) != rgnOUT ||
791             RECT_IN_REGION( pScreen, pRegion, &cursorBox) != rgnOUT)
792             miSpriteRemoveCursor (pScreen);
793     }
794
795     (*pScreen->CopyWindow) (pWin, ptOldOrg, pRegion);
796
797     SCREEN_EPILOGUE (pScreen, CopyWindow, miSpriteCopyWindow);
798 }
799
800 static void
801 miSpriteClearToBackground (pWin, x, y, w, h, generateExposures)
802     WindowPtr pWin;
803     short x,y;
804     unsigned short w,h;
805     Bool generateExposures;
806 {
807     ScreenPtr           pScreen;
808     miSpriteScreenPtr   pScreenPriv;
809     int                 realw, realh;
810
811     pScreen = pWin->drawable.pScreen;
812
813     SCREEN_PROLOGUE (pScreen, ClearToBackground);
814
815     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
816     if (GC_CHECK(pWin))
817     {
818         if (!(realw = w))
819             realw = (int) pWin->drawable.width - x;
820         if (!(realh = h))
821             realh = (int) pWin->drawable.height - y;
822         if (ORG_OVERLAP(&pScreenPriv->saved, pWin->drawable.x, pWin->drawable.y,
823                         x, y, realw, realh))
824         {
825             miSpriteRemoveCursor (pScreen);
826         }
827     }
828
829     (*pScreen->ClearToBackground) (pWin, x, y, w, h, generateExposures);
830
831     SCREEN_EPILOGUE (pScreen, ClearToBackground, miSpriteClearToBackground);
832 }
833
834 /*
835  * GC Func wrappers
836  */
837
838 static void
839 miSpriteValidateGC (pGC, changes, pDrawable)
840     GCPtr       pGC;
841     Mask        changes;
842     DrawablePtr pDrawable;
843 {
844     GC_FUNC_PROLOGUE (pGC);
845
846     (*pGC->funcs->ValidateGC) (pGC, changes, pDrawable);
847     
848     pGCPriv->wrapOps = NULL;
849     if (pDrawable->type == DRAWABLE_WINDOW && ((WindowPtr) pDrawable)->viewable)
850     {
851         WindowPtr   pWin;
852         RegionPtr   pRegion;
853
854         pWin = (WindowPtr) pDrawable;
855         pRegion = &pWin->clipList;
856         if (pGC->subWindowMode == IncludeInferiors)
857             pRegion = &pWin->borderClip;
858         if (REGION_NOTEMPTY(pDrawable->pScreen, pRegion))
859             pGCPriv->wrapOps = pGC->ops;
860     }
861
862     GC_FUNC_EPILOGUE (pGC);
863 }
864
865 static void
866 miSpriteChangeGC (pGC, mask)
867     GCPtr           pGC;
868     unsigned long   mask;
869 {
870     GC_FUNC_PROLOGUE (pGC);
871
872     (*pGC->funcs->ChangeGC) (pGC, mask);
873     
874     GC_FUNC_EPILOGUE (pGC);
875 }
876
877 static void
878 miSpriteCopyGC (pGCSrc, mask, pGCDst)
879     GCPtr           pGCSrc, pGCDst;
880     unsigned long   mask;
881 {
882     GC_FUNC_PROLOGUE (pGCDst);
883
884     (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst);
885     
886     GC_FUNC_EPILOGUE (pGCDst);
887 }
888
889 static void
890 miSpriteDestroyGC (pGC)
891     GCPtr   pGC;
892 {
893     GC_FUNC_PROLOGUE (pGC);
894
895     (*pGC->funcs->DestroyGC) (pGC);
896     
897     GC_FUNC_EPILOGUE (pGC);
898 }
899
900 static void
901 miSpriteChangeClip (pGC, type, pvalue, nrects)
902     GCPtr   pGC;
903     int         type;
904     pointer     pvalue;
905     int         nrects;
906 {
907     GC_FUNC_PROLOGUE (pGC);
908
909     (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects);
910
911     GC_FUNC_EPILOGUE (pGC);
912 }
913
914 static void
915 miSpriteCopyClip(pgcDst, pgcSrc)
916     GCPtr pgcDst, pgcSrc;
917 {
918     GC_FUNC_PROLOGUE (pgcDst);
919
920     (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc);
921
922     GC_FUNC_EPILOGUE (pgcDst);
923 }
924
925 static void
926 miSpriteDestroyClip(pGC)
927     GCPtr       pGC;
928 {
929     GC_FUNC_PROLOGUE (pGC);
930
931     (* pGC->funcs->DestroyClip)(pGC);
932
933     GC_FUNC_EPILOGUE (pGC);
934 }
935
936 /*
937  * GC Op wrappers
938  */
939
940 static void
941 miSpriteFillSpans(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted)
942     DrawablePtr pDrawable;
943     GCPtr       pGC;
944     int         nInit;                  /* number of spans to fill */
945     DDXPointPtr pptInit;                /* pointer to list of start points */
946     int         *pwidthInit;            /* pointer to list of n widths */
947     int         fSorted;
948 {
949     GC_SETUP(pDrawable, pGC);
950
951     if (GC_CHECK((WindowPtr) pDrawable))
952     {
953         register DDXPointPtr    pts;
954         register int            *widths;
955         register int            nPts;
956
957         for (pts = pptInit, widths = pwidthInit, nPts = nInit;
958              nPts--;
959              pts++, widths++)
960         {
961              if (SPN_OVERLAP(&pScreenPriv->saved,pts->y,pts->x,*widths))
962              {
963                  miSpriteRemoveCursor (pDrawable->pScreen);
964                  break;
965              }
966         }
967     }
968
969     GC_OP_PROLOGUE (pGC);
970
971     (*pGC->ops->FillSpans) (pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted);
972
973     GC_OP_EPILOGUE (pGC);
974 }
975
976 static void
977 miSpriteSetSpans(pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted)
978     DrawablePtr         pDrawable;
979     GCPtr               pGC;
980     char                *psrc;
981     register DDXPointPtr ppt;
982     int                 *pwidth;
983     int                 nspans;
984     int                 fSorted;
985 {
986     GC_SETUP(pDrawable, pGC);
987
988     if (GC_CHECK((WindowPtr) pDrawable))
989     {
990         register DDXPointPtr    pts;
991         register int            *widths;
992         register int            nPts;
993
994         for (pts = ppt, widths = pwidth, nPts = nspans;
995              nPts--;
996              pts++, widths++)
997         {
998              if (SPN_OVERLAP(&pScreenPriv->saved,pts->y,pts->x,*widths))
999              {
1000                  miSpriteRemoveCursor(pDrawable->pScreen);
1001                  break;
1002              }
1003         }
1004     }
1005
1006     GC_OP_PROLOGUE (pGC);
1007
1008     (*pGC->ops->SetSpans) (pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted);
1009
1010     GC_OP_EPILOGUE (pGC);
1011 }
1012
1013 static void
1014 miSpritePutImage(pDrawable, pGC, depth, x, y, w, h, leftPad, format, pBits)
1015     DrawablePtr   pDrawable;
1016     GCPtr         pGC;
1017     int           depth;
1018     int           x;
1019     int           y;
1020     int           w;
1021     int           h;
1022     int           format;
1023     char          *pBits;
1024 {
1025     GC_SETUP(pDrawable, pGC);
1026
1027     if (GC_CHECK((WindowPtr) pDrawable))
1028     {
1029         if (ORG_OVERLAP(&pScreenPriv->saved,pDrawable->x,pDrawable->y,
1030                         x,y,w,h))
1031         {
1032             miSpriteRemoveCursor (pDrawable->pScreen);
1033         }
1034     }
1035
1036     GC_OP_PROLOGUE (pGC);
1037
1038     (*pGC->ops->PutImage) (pDrawable, pGC, depth, x, y, w, h, leftPad, format, pBits);
1039
1040     GC_OP_EPILOGUE (pGC);
1041 }
1042
1043 static RegionPtr
1044 miSpriteCopyArea (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty)
1045     DrawablePtr   pSrc;
1046     DrawablePtr   pDst;
1047     GCPtr         pGC;
1048     int           srcx;
1049     int           srcy;
1050     int           w;
1051     int           h;
1052     int           dstx;
1053     int           dsty;
1054 {
1055     RegionPtr rgn;
1056
1057     GC_SETUP(pDst, pGC);
1058
1059     /* check destination/source overlap. */
1060     if (GC_CHECK((WindowPtr) pDst) &&
1061          (ORG_OVERLAP(&pScreenPriv->saved,pDst->x,pDst->y,dstx,dsty,w,h) ||
1062           ((pDst == pSrc) &&
1063            ORG_OVERLAP(&pScreenPriv->saved,pSrc->x,pSrc->y,srcx,srcy,w,h))))
1064     {
1065         miSpriteRemoveCursor (pDst->pScreen);
1066     }
1067  
1068     GC_OP_PROLOGUE (pGC);
1069
1070     rgn = (*pGC->ops->CopyArea) (pSrc, pDst, pGC, srcx, srcy, w, h,
1071                                  dstx, dsty);
1072
1073     GC_OP_EPILOGUE (pGC);
1074
1075     return rgn;
1076 }
1077
1078 static RegionPtr
1079 miSpriteCopyPlane (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty, plane)
1080     DrawablePtr   pSrc;
1081     DrawablePtr   pDst;
1082     register GCPtr pGC;
1083     int           srcx,
1084                   srcy;
1085     int           w,
1086                   h;
1087     int           dstx,
1088                   dsty;
1089     unsigned long  plane;
1090 {
1091     RegionPtr rgn;
1092
1093     GC_SETUP(pDst, pGC);
1094
1095     /*
1096      * check destination/source for overlap.
1097      */
1098     if (GC_CHECK((WindowPtr) pDst) &&
1099         (ORG_OVERLAP(&pScreenPriv->saved,pDst->x,pDst->y,dstx,dsty,w,h) ||
1100          ((pDst == pSrc) &&
1101           ORG_OVERLAP(&pScreenPriv->saved,pSrc->x,pSrc->y,srcx,srcy,w,h))))
1102     {
1103         miSpriteRemoveCursor (pDst->pScreen);
1104     }
1105
1106     GC_OP_PROLOGUE (pGC);
1107
1108     rgn = (*pGC->ops->CopyPlane) (pSrc, pDst, pGC, srcx, srcy, w, h,
1109                                   dstx, dsty, plane);
1110
1111     GC_OP_EPILOGUE (pGC);
1112
1113     return rgn;
1114 }
1115
1116 static void
1117 miSpritePolyPoint (pDrawable, pGC, mode, npt, pptInit)
1118     DrawablePtr pDrawable;
1119     GCPtr       pGC;
1120     int         mode;           /* Origin or Previous */
1121     int         npt;
1122     xPoint      *pptInit;
1123 {
1124     xPoint      t;
1125     int         n;
1126     BoxRec      cursor;
1127     register xPoint *pts;
1128
1129     GC_SETUP (pDrawable, pGC);
1130
1131     if (npt && GC_CHECK((WindowPtr) pDrawable))
1132     {
1133         cursor.x1 = pScreenPriv->saved.x1 - pDrawable->x;
1134         cursor.y1 = pScreenPriv->saved.y1 - pDrawable->y;
1135         cursor.x2 = pScreenPriv->saved.x2 - pDrawable->x;
1136         cursor.y2 = pScreenPriv->saved.y2 - pDrawable->y;
1137
1138         if (mode == CoordModePrevious)
1139         {
1140             t.x = 0;
1141             t.y = 0;
1142             for (pts = pptInit, n = npt; n--; pts++)
1143             {
1144                 t.x += pts->x;
1145                 t.y += pts->y;
1146                 if (cursor.x1 <= t.x && t.x <= cursor.x2 &&
1147                     cursor.y1 <= t.y && t.y <= cursor.y2)
1148                 {
1149                     miSpriteRemoveCursor (pDrawable->pScreen);
1150                     break;
1151                 }
1152             }
1153         }
1154         else
1155         {
1156             for (pts = pptInit, n = npt; n--; pts++)
1157             {
1158                 if (cursor.x1 <= pts->x && pts->x <= cursor.x2 &&
1159                     cursor.y1 <= pts->y && pts->y <= cursor.y2)
1160                 {
1161                     miSpriteRemoveCursor (pDrawable->pScreen);
1162                     break;
1163                 }
1164             }
1165         }
1166     }
1167
1168     GC_OP_PROLOGUE (pGC);
1169
1170     (*pGC->ops->PolyPoint) (pDrawable, pGC, mode, npt, pptInit);
1171
1172     GC_OP_EPILOGUE (pGC);
1173 }
1174
1175 static void
1176 miSpritePolylines (pDrawable, pGC, mode, npt, pptInit)
1177     DrawablePtr   pDrawable;
1178     GCPtr         pGC;
1179     int           mode;
1180     int           npt;
1181     DDXPointPtr   pptInit;
1182 {
1183     BoxPtr  cursor;
1184     register DDXPointPtr pts;
1185     int     n;
1186     int     x, y, x1, y1, x2, y2;
1187     int     lw;
1188     int     extra;
1189
1190     GC_SETUP (pDrawable, pGC);
1191
1192     if (npt && GC_CHECK((WindowPtr) pDrawable))
1193     {
1194         cursor = &pScreenPriv->saved;
1195         lw = pGC->lineWidth;
1196         x = pptInit->x + pDrawable->x;
1197         y = pptInit->y + pDrawable->y;
1198
1199         if (npt == 1)
1200         {
1201             extra = lw >> 1;
1202             if (LINE_OVERLAP(cursor, x, y, x, y, extra))
1203                 miSpriteRemoveCursor (pDrawable->pScreen);
1204         }
1205         else
1206         {
1207             extra = lw >> 1;
1208             /*
1209              * mitered joins can project quite a way from
1210              * the line end; the 11 degree miter limit limits
1211              * this extension to 10.43 * lw / 2, rounded up
1212              * and converted to int yields 6 * lw
1213              */
1214             if (pGC->joinStyle == JoinMiter)
1215                 extra = 6 * lw;
1216             else if (pGC->capStyle == CapProjecting)
1217                 extra = lw;
1218             for (pts = pptInit + 1, n = npt - 1; n--; pts++)
1219             {
1220                 x1 = x;
1221                 y1 = y;
1222                 if (mode == CoordModeOrigin)
1223                 {
1224                     x2 = pDrawable->x + pts->x;
1225                     y2 = pDrawable->y + pts->y;
1226                 }
1227                 else
1228                 {
1229                     x2 = x + pts->x;
1230                     y2 = y + pts->y;
1231                 }
1232                 x = x2;
1233                 y = y2;
1234                 LINE_SORT(x1, y1, x2, y2);
1235                 if (LINE_OVERLAP(cursor, x1, y1, x2, y2, extra))
1236                 {
1237                     miSpriteRemoveCursor (pDrawable->pScreen);
1238                     break;
1239                 }
1240             }
1241         }
1242     }
1243     GC_OP_PROLOGUE (pGC);
1244
1245     (*pGC->ops->Polylines) (pDrawable, pGC, mode, npt, pptInit);
1246
1247     GC_OP_EPILOGUE (pGC);
1248 }
1249
1250 static void
1251 miSpritePolySegment(pDrawable, pGC, nseg, pSegs)
1252     DrawablePtr pDrawable;
1253     GCPtr       pGC;
1254     int         nseg;
1255     xSegment    *pSegs;
1256 {
1257     int     n;
1258     register xSegment *segs;
1259     BoxPtr  cursor;
1260     int     x1, y1, x2, y2;
1261     int     extra;
1262
1263     GC_SETUP(pDrawable, pGC);
1264
1265     if (nseg && GC_CHECK((WindowPtr) pDrawable))
1266     {
1267         cursor = &pScreenPriv->saved;
1268         extra = pGC->lineWidth >> 1;
1269         if (pGC->capStyle == CapProjecting)
1270             extra = pGC->lineWidth;
1271         for (segs = pSegs, n = nseg; n--; segs++)
1272         {
1273             x1 = segs->x1 + pDrawable->x;
1274             y1 = segs->y1 + pDrawable->y;
1275             x2 = segs->x2 + pDrawable->x;
1276             y2 = segs->y2 + pDrawable->y;
1277             LINE_SORT(x1, y1, x2, y2);
1278             if (LINE_OVERLAP(cursor, x1, y1, x2, y2, extra))
1279             {
1280                 miSpriteRemoveCursor (pDrawable->pScreen);
1281                 break;
1282             }
1283         }
1284     }
1285
1286     GC_OP_PROLOGUE (pGC);
1287
1288     (*pGC->ops->PolySegment) (pDrawable, pGC, nseg, pSegs);
1289
1290     GC_OP_EPILOGUE (pGC);
1291 }
1292
1293 static void
1294 miSpritePolyRectangle(pDrawable, pGC, nrects, pRects)
1295     DrawablePtr pDrawable;
1296     GCPtr       pGC;
1297     int         nrects;
1298     xRectangle  *pRects;
1299 {
1300     register xRectangle *rects;
1301     BoxPtr  cursor;
1302     int     lw;
1303     int     n;
1304     int     x1, y1, x2, y2;
1305     
1306     GC_SETUP (pDrawable, pGC);
1307
1308     if (GC_CHECK((WindowPtr) pDrawable))
1309     {
1310         lw = pGC->lineWidth >> 1;
1311         cursor = &pScreenPriv->saved;
1312         for (rects = pRects, n = nrects; n--; rects++)
1313         {
1314             x1 = rects->x + pDrawable->x;
1315             y1 = rects->y + pDrawable->y;
1316             x2 = x1 + (int)rects->width;
1317             y2 = y1 + (int)rects->height;
1318             if (LINE_OVERLAP(cursor, x1, y1, x2, y1, lw) ||
1319                 LINE_OVERLAP(cursor, x2, y1, x2, y2, lw) ||
1320                 LINE_OVERLAP(cursor, x1, y2, x2, y2, lw) ||
1321                 LINE_OVERLAP(cursor, x1, y1, x1, y2, lw))
1322             {
1323                 miSpriteRemoveCursor (pDrawable->pScreen);
1324                 break;
1325             }
1326         }
1327     }
1328
1329     GC_OP_PROLOGUE (pGC);
1330
1331     (*pGC->ops->PolyRectangle) (pDrawable, pGC, nrects, pRects);
1332
1333     GC_OP_EPILOGUE (pGC);
1334 }
1335
1336 static void
1337 miSpritePolyArc(pDrawable, pGC, narcs, parcs)
1338     DrawablePtr pDrawable;
1339     register GCPtr      pGC;
1340     int         narcs;
1341     xArc        *parcs;
1342 {
1343     BoxPtr  cursor;
1344     int     lw;
1345     int     n;
1346     register xArc *arcs;
1347     
1348     GC_SETUP (pDrawable, pGC);
1349
1350     if (GC_CHECK((WindowPtr) pDrawable))
1351     {
1352         lw = pGC->lineWidth >> 1;
1353         cursor = &pScreenPriv->saved;
1354         for (arcs = parcs, n = narcs; n--; arcs++)
1355         {
1356             if (ORG_OVERLAP (cursor, pDrawable->x, pDrawable->y,
1357                              arcs->x - lw, arcs->y - lw,
1358                              (int) arcs->width + pGC->lineWidth,
1359                              (int) arcs->height + pGC->lineWidth))
1360             {
1361                 miSpriteRemoveCursor (pDrawable->pScreen);
1362                 break;
1363             }
1364         }
1365     }
1366
1367     GC_OP_PROLOGUE (pGC);
1368
1369     (*pGC->ops->PolyArc) (pDrawable, pGC, narcs, parcs);
1370
1371     GC_OP_EPILOGUE (pGC);
1372 }
1373
1374 static void
1375 miSpriteFillPolygon(pDrawable, pGC, shape, mode, count, pPts)
1376     register DrawablePtr pDrawable;
1377     register GCPtr      pGC;
1378     int                 shape, mode;
1379     int                 count;
1380     DDXPointPtr         pPts;
1381 {
1382     int x, y, minx, miny, maxx, maxy;
1383     register DDXPointPtr pts;
1384     int n;
1385
1386     GC_SETUP (pDrawable, pGC);
1387
1388     if (count && GC_CHECK((WindowPtr) pDrawable))
1389     {
1390         x = pDrawable->x;
1391         y = pDrawable->y;
1392         pts = pPts;
1393         minx = maxx = pts->x;
1394         miny = maxy = pts->y;
1395         pts++;
1396         n = count - 1;
1397
1398         if (mode == CoordModeOrigin)
1399         {
1400             for (; n--; pts++)
1401             {
1402                 if (pts->x < minx)
1403                     minx = pts->x;
1404                 else if (pts->x > maxx)
1405                     maxx = pts->x;
1406                 if (pts->y < miny)
1407                     miny = pts->y;
1408                 else if (pts->y > maxy)
1409                     maxy = pts->y;
1410             }
1411             minx += x;
1412             miny += y;
1413             maxx += x;
1414             maxy += y;
1415         }
1416         else
1417         {
1418             x += minx;
1419             y += miny;
1420             minx = maxx = x;
1421             miny = maxy = y;
1422             for (; n--; pts++)
1423             {
1424                 x += pts->x;
1425                 y += pts->y;
1426                 if (x < minx)
1427                     minx = x;
1428                 else if (x > maxx)
1429                     maxx = x;
1430                 if (y < miny)
1431                     miny = y;
1432                 else if (y > maxy)
1433                     maxy = y;
1434             }
1435         }
1436         if (BOX_OVERLAP(&pScreenPriv->saved,minx,miny,maxx,maxy))
1437             miSpriteRemoveCursor (pDrawable->pScreen);
1438     }
1439
1440     GC_OP_PROLOGUE (pGC);
1441
1442     (*pGC->ops->FillPolygon) (pDrawable, pGC, shape, mode, count, pPts);
1443
1444     GC_OP_EPILOGUE (pGC);
1445 }
1446
1447 static void
1448 miSpritePolyFillRect(pDrawable, pGC, nrectFill, prectInit)
1449     DrawablePtr pDrawable;
1450     GCPtr       pGC;
1451     int         nrectFill;      /* number of rectangles to fill */
1452     xRectangle  *prectInit;     /* Pointer to first rectangle to fill */
1453 {
1454     GC_SETUP(pDrawable, pGC);
1455
1456     if (GC_CHECK((WindowPtr) pDrawable))
1457     {
1458         register int        nRect;
1459         register xRectangle *pRect;
1460         register int        xorg, yorg;
1461
1462         xorg = pDrawable->x;
1463         yorg = pDrawable->y;
1464
1465         for (nRect = nrectFill, pRect = prectInit; nRect--; pRect++) {
1466             if (ORGRECT_OVERLAP(&pScreenPriv->saved,xorg,yorg,pRect)){
1467                 miSpriteRemoveCursor(pDrawable->pScreen);
1468                 break;
1469             }
1470         }
1471     }
1472
1473     GC_OP_PROLOGUE (pGC);
1474
1475     (*pGC->ops->PolyFillRect) (pDrawable, pGC, nrectFill, prectInit);
1476
1477     GC_OP_EPILOGUE (pGC);
1478 }
1479
1480 static void
1481 miSpritePolyFillArc(pDrawable, pGC, narcs, parcs)
1482     DrawablePtr pDrawable;
1483     GCPtr       pGC;
1484     int         narcs;
1485     xArc        *parcs;
1486 {
1487     GC_SETUP(pDrawable, pGC);
1488
1489     if (GC_CHECK((WindowPtr) pDrawable))
1490     {
1491         register int    n;
1492         BoxPtr          cursor;
1493         register xArc *arcs;
1494
1495         cursor = &pScreenPriv->saved;
1496
1497         for (arcs = parcs, n = narcs; n--; arcs++)
1498         {
1499             if (ORG_OVERLAP(cursor, pDrawable->x, pDrawable->y,
1500                             arcs->x, arcs->y,
1501                             (int) arcs->width, (int) arcs->height))
1502             {
1503                 miSpriteRemoveCursor (pDrawable->pScreen);
1504                 break;
1505             }
1506         }
1507     }
1508
1509     GC_OP_PROLOGUE (pGC);
1510
1511     (*pGC->ops->PolyFillArc) (pDrawable, pGC, narcs, parcs);
1512
1513     GC_OP_EPILOGUE (pGC);
1514 }
1515
1516 /*
1517  * general Poly/Image text function.  Extract glyph information,
1518  * compute bounding box and remove cursor if it is overlapped.
1519  */
1520
1521 static Bool
1522 miSpriteTextOverlap (pDraw, font, x, y, n, charinfo, imageblt, w, cursorBox)
1523     DrawablePtr   pDraw;
1524     FontPtr       font;
1525     int           x, y;
1526     unsigned int  n;
1527     CharInfoPtr   *charinfo;
1528     Bool          imageblt;
1529     unsigned int  w;
1530     BoxPtr        cursorBox;
1531 {
1532     ExtentInfoRec extents;
1533
1534     x += pDraw->x;
1535     y += pDraw->y;
1536
1537     if (FONTMINBOUNDS(font,characterWidth) >= 0)
1538     {
1539         /* compute an approximate (but covering) bounding box */
1540         if (!imageblt || (charinfo[0]->metrics.leftSideBearing < 0))
1541             extents.overallLeft = charinfo[0]->metrics.leftSideBearing;
1542         else
1543             extents.overallLeft = 0;
1544         if (w)
1545             extents.overallRight = w - charinfo[n-1]->metrics.characterWidth;
1546         else
1547             extents.overallRight = FONTMAXBOUNDS(font,characterWidth)
1548                                     * (n - 1);
1549         if (imageblt && (charinfo[n-1]->metrics.characterWidth >
1550                          charinfo[n-1]->metrics.rightSideBearing))
1551             extents.overallRight += charinfo[n-1]->metrics.characterWidth;
1552         else
1553             extents.overallRight += charinfo[n-1]->metrics.rightSideBearing;
1554         if (imageblt && FONTASCENT(font) > FONTMAXBOUNDS(font,ascent))
1555             extents.overallAscent = FONTASCENT(font);
1556         else
1557             extents.overallAscent = FONTMAXBOUNDS(font, ascent);
1558         if (imageblt && FONTDESCENT(font) > FONTMAXBOUNDS(font,descent))
1559             extents.overallDescent = FONTDESCENT(font);
1560         else
1561             extents.overallDescent = FONTMAXBOUNDS(font,descent);
1562         if (!BOX_OVERLAP(cursorBox,
1563                          x + extents.overallLeft,
1564                          y - extents.overallAscent,
1565                          x + extents.overallRight,
1566                          y + extents.overallDescent))
1567             return FALSE;
1568         else if (imageblt && w)
1569             return TRUE;
1570         /* if it does overlap, fall through and compute exactly, because
1571          * taking down the cursor is expensive enough to make this worth it
1572          */
1573     }
1574     QueryGlyphExtents(font, charinfo, n, &extents);
1575     if (imageblt)
1576     {
1577         if (extents.overallWidth > extents.overallRight)
1578             extents.overallRight = extents.overallWidth;
1579         if (extents.overallWidth < extents.overallLeft)
1580             extents.overallLeft = extents.overallWidth;
1581         if (extents.overallLeft > 0)
1582             extents.overallLeft = 0;
1583         if (extents.fontAscent > extents.overallAscent)
1584             extents.overallAscent = extents.fontAscent;
1585         if (extents.fontDescent > extents.overallDescent)
1586             extents.overallDescent = extents.fontDescent;
1587     }
1588     return (BOX_OVERLAP(cursorBox,
1589                         x + extents.overallLeft,
1590                         y - extents.overallAscent,
1591                         x + extents.overallRight,
1592                         y + extents.overallDescent));
1593 }
1594
1595 /*
1596  * values for textType:
1597  */
1598 #define TT_POLY8   0
1599 #define TT_IMAGE8  1
1600 #define TT_POLY16  2
1601 #define TT_IMAGE16 3
1602
1603 static int 
1604 miSpriteText (pDraw, pGC, x, y, count, chars, fontEncoding, textType, cursorBox)
1605     DrawablePtr     pDraw;
1606     GCPtr           pGC;
1607     int             x,
1608                     y;
1609     unsigned long    count;
1610     char            *chars;
1611     FontEncoding    fontEncoding;
1612     Bool            textType;
1613     BoxPtr          cursorBox;
1614 {
1615     CharInfoPtr *charinfo;
1616     register CharInfoPtr *info;
1617     unsigned long i;
1618     unsigned int  n;
1619     int           w;
1620     void          (*drawFunc)();
1621
1622     Bool imageblt;
1623
1624     imageblt = (textType == TT_IMAGE8) || (textType == TT_IMAGE16);
1625
1626     charinfo = (CharInfoPtr *) ALLOCATE_LOCAL(count * sizeof(CharInfoPtr));
1627     if (!charinfo)
1628         return x;
1629
1630     GetGlyphs(pGC->font, count, (unsigned char *)chars,
1631               fontEncoding, &i, charinfo);
1632     n = (unsigned int)i;
1633     w = 0;
1634     if (!imageblt)
1635         for (info = charinfo; i--; info++)
1636             w += (*info)->metrics.characterWidth;
1637
1638     if (n != 0) {
1639         if (miSpriteTextOverlap(pDraw, pGC->font, x, y, n, charinfo, imageblt, w, cursorBox))
1640             miSpriteRemoveCursor(pDraw->pScreen);
1641
1642 #ifdef AVOID_GLYPHBLT
1643         /*
1644          * On displays like Apollos, which do not optimize the GlyphBlt functions because they
1645          * convert fonts to their internal form in RealizeFont and optimize text directly, we
1646          * want to invoke the text functions here, not the GlyphBlt functions.
1647          */
1648         switch (textType)
1649         {
1650         case TT_POLY8:
1651             drawFunc = (void (*)())pGC->ops->PolyText8;
1652             break;
1653         case TT_IMAGE8:
1654             drawFunc = pGC->ops->ImageText8;
1655             break;
1656         case TT_POLY16:
1657             drawFunc = (void (*)())pGC->ops->PolyText16;
1658             break;
1659         case TT_IMAGE16:
1660             drawFunc = pGC->ops->ImageText16;
1661             break;
1662         }
1663         (*drawFunc) (pDraw, pGC, x, y, (int) count, chars);
1664 #else /* don't AVOID_GLYPHBLT */
1665         /*
1666          * On the other hand, if the device does use GlyphBlt ultimately to do text, we
1667          * don't want to slow it down by invoking the text functions and having them call
1668          * GetGlyphs all over again, so we go directly to the GlyphBlt functions here.
1669          */
1670         drawFunc = imageblt ? pGC->ops->ImageGlyphBlt : pGC->ops->PolyGlyphBlt;
1671         (*drawFunc) (pDraw, pGC, x, y, n, charinfo, FONTGLYPHS(pGC->font));
1672 #endif /* AVOID_GLYPHBLT */
1673     }
1674     DEALLOCATE_LOCAL(charinfo);
1675     return x + w;
1676 }
1677
1678 static int
1679 miSpritePolyText8(pDrawable, pGC, x, y, count, chars)
1680     DrawablePtr pDrawable;
1681     GCPtr       pGC;
1682     int         x, y;
1683     int         count;
1684     char        *chars;
1685 {
1686     int ret;
1687
1688     GC_SETUP (pDrawable, pGC);
1689
1690     GC_OP_PROLOGUE (pGC);
1691
1692     if (GC_CHECK((WindowPtr) pDrawable))
1693         ret = miSpriteText (pDrawable, pGC, x, y, (unsigned long)count, chars,
1694                             Linear8Bit, TT_POLY8, &pScreenPriv->saved);
1695     else
1696         ret = (*pGC->ops->PolyText8) (pDrawable, pGC, x, y, count, chars);
1697
1698     GC_OP_EPILOGUE (pGC);
1699     return ret;
1700 }
1701
1702 static int
1703 miSpritePolyText16(pDrawable, pGC, x, y, count, chars)
1704     DrawablePtr pDrawable;
1705     GCPtr       pGC;
1706     int         x, y;
1707     int         count;
1708     unsigned short *chars;
1709 {
1710     int ret;
1711
1712     GC_SETUP(pDrawable, pGC);
1713
1714     GC_OP_PROLOGUE (pGC);
1715
1716     if (GC_CHECK((WindowPtr) pDrawable))
1717         ret = miSpriteText (pDrawable, pGC, x, y, (unsigned long)count,
1718                             (char *)chars,
1719                             FONTLASTROW(pGC->font) == 0 ?
1720                             Linear16Bit : TwoD16Bit, TT_POLY16, &pScreenPriv->saved);
1721     else
1722         ret = (*pGC->ops->PolyText16) (pDrawable, pGC, x, y, count, chars);
1723
1724     GC_OP_EPILOGUE (pGC);
1725     return ret;
1726 }
1727
1728 static void
1729 miSpriteImageText8(pDrawable, pGC, x, y, count, chars)
1730     DrawablePtr pDrawable;
1731     GCPtr       pGC;
1732     int         x, y;
1733     int         count;
1734     char        *chars;
1735 {
1736     GC_SETUP(pDrawable, pGC);
1737
1738     GC_OP_PROLOGUE (pGC);
1739
1740     if (GC_CHECK((WindowPtr) pDrawable))
1741         (void) miSpriteText (pDrawable, pGC, x, y, (unsigned long)count,
1742                              chars, Linear8Bit, TT_IMAGE8, &pScreenPriv->saved);
1743     else
1744         (*pGC->ops->ImageText8) (pDrawable, pGC, x, y, count, chars);
1745
1746     GC_OP_EPILOGUE (pGC);
1747 }
1748
1749 static void
1750 miSpriteImageText16(pDrawable, pGC, x, y, count, chars)
1751     DrawablePtr pDrawable;
1752     GCPtr       pGC;
1753     int         x, y;
1754     int         count;
1755     unsigned short *chars;
1756 {
1757     GC_SETUP(pDrawable, pGC);
1758
1759     GC_OP_PROLOGUE (pGC);
1760
1761     if (GC_CHECK((WindowPtr) pDrawable))
1762         (void) miSpriteText (pDrawable, pGC, x, y, (unsigned long)count,
1763                              (char *)chars,
1764                             FONTLASTROW(pGC->font) == 0 ?
1765                             Linear16Bit : TwoD16Bit, TT_IMAGE16, &pScreenPriv->saved);
1766     else
1767         (*pGC->ops->ImageText16) (pDrawable, pGC, x, y, count, chars);
1768
1769     GC_OP_EPILOGUE (pGC);
1770 }
1771
1772 static void
1773 miSpriteImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase)
1774     DrawablePtr pDrawable;
1775     GCPtr       pGC;
1776     int         x, y;
1777     unsigned int nglyph;
1778     CharInfoPtr *ppci;          /* array of character info */
1779     pointer     pglyphBase;     /* start of array of glyphs */
1780 {
1781     GC_SETUP(pDrawable, pGC);
1782
1783     GC_OP_PROLOGUE (pGC);
1784
1785     if (GC_CHECK((WindowPtr) pDrawable) &&
1786         miSpriteTextOverlap (pDrawable, pGC->font, x, y, nglyph, ppci, TRUE, 0, &pScreenPriv->saved))
1787     {
1788         miSpriteRemoveCursor(pDrawable->pScreen);
1789     }
1790     (*pGC->ops->ImageGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
1791
1792     GC_OP_EPILOGUE (pGC);
1793 }
1794
1795 static void
1796 miSpritePolyGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase)
1797     DrawablePtr pDrawable;
1798     GCPtr       pGC;
1799     int         x, y;
1800     unsigned int nglyph;
1801     CharInfoPtr *ppci;          /* array of character info */
1802     pointer     pglyphBase;     /* start of array of glyphs */
1803 {
1804     GC_SETUP (pDrawable, pGC);
1805
1806     GC_OP_PROLOGUE (pGC);
1807
1808     if (GC_CHECK((WindowPtr) pDrawable) &&
1809         miSpriteTextOverlap (pDrawable, pGC->font, x, y, nglyph, ppci, FALSE, 0, &pScreenPriv->saved))
1810     {
1811         miSpriteRemoveCursor(pDrawable->pScreen);
1812     }
1813     (*pGC->ops->PolyGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
1814
1815     GC_OP_EPILOGUE (pGC);
1816 }
1817
1818 static void
1819 miSpritePushPixels(pGC, pBitMap, pDrawable, w, h, x, y)
1820     GCPtr       pGC;
1821     PixmapPtr   pBitMap;
1822     DrawablePtr pDrawable;
1823     int         w, h, x, y;
1824 {
1825     GC_SETUP(pDrawable, pGC);
1826
1827     if (GC_CHECK((WindowPtr) pDrawable) &&
1828         ORG_OVERLAP(&pScreenPriv->saved,pDrawable->x,pDrawable->y,x,y,w,h))
1829     {
1830         miSpriteRemoveCursor (pDrawable->pScreen);
1831     }
1832
1833     GC_OP_PROLOGUE (pGC);
1834
1835     (*pGC->ops->PushPixels) (pGC, pBitMap, pDrawable, w, h, x, y);
1836
1837     GC_OP_EPILOGUE (pGC);
1838 }
1839
1840 #ifdef NEED_LINEHELPER
1841 /*
1842  * I don't expect this routine will ever be called, as the GC
1843  * will have been unwrapped for the line drawing
1844  */
1845
1846 static void
1847 miSpriteLineHelper()
1848 {
1849     FatalError("miSpriteLineHelper called\n");
1850 }
1851 #endif
1852
1853 /*
1854  * miPointer interface routines
1855  */
1856
1857 #define SPRITE_PAD  8
1858
1859 static Bool
1860 miSpriteRealizeCursor (pScreen, pCursor)
1861     ScreenPtr   pScreen;
1862     CursorPtr   pCursor;
1863 {
1864     miSpriteScreenPtr   pScreenPriv;
1865
1866     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
1867     if (pCursor == pScreenPriv->pCursor)
1868         pScreenPriv->checkPixels = TRUE;
1869     return (*pScreenPriv->funcs->RealizeCursor) (pScreen, pCursor);
1870 }
1871
1872 static Bool
1873 miSpriteUnrealizeCursor (pScreen, pCursor)
1874     ScreenPtr   pScreen;
1875     CursorPtr   pCursor;
1876 {
1877     miSpriteScreenPtr   pScreenPriv;
1878
1879     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
1880     return (*pScreenPriv->funcs->UnrealizeCursor) (pScreen, pCursor);
1881 }
1882
1883 static void
1884 miSpriteSetCursor (pScreen, pCursor, x, y)
1885     ScreenPtr   pScreen;
1886     CursorPtr   pCursor;
1887 {
1888     miSpriteScreenPtr   pScreenPriv;
1889
1890     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
1891     pScreenPriv->shouldBeUp = TRUE;
1892     if (pScreenPriv->x == x &&
1893         pScreenPriv->y == y &&
1894         pScreenPriv->pCursor == pCursor &&
1895         !pScreenPriv->checkPixels)
1896     {
1897         return;
1898     }
1899     if (!pCursor)
1900     {
1901         pScreenPriv->shouldBeUp = FALSE;
1902         if (pScreenPriv->isUp)
1903             miSpriteRemoveCursor (pScreen);
1904         pScreenPriv->pCursor = 0;
1905         return;
1906     }
1907     pScreenPriv->x = x;
1908     pScreenPriv->y = y;
1909     pScreenPriv->pCacheWin = NullWindow;
1910     if (pScreenPriv->checkPixels || pScreenPriv->pCursor != pCursor)
1911     {
1912         pScreenPriv->pCursor = pCursor;
1913         miSpriteFindColors (pScreen);
1914     }
1915     if (pScreenPriv->isUp) {
1916         int     sx, sy;
1917         /*
1918          * check to see if the old saved region
1919          * encloses the new sprite, in which case we use
1920          * the flicker-free MoveCursor primitive.
1921          */
1922         sx = pScreenPriv->x - (int)pCursor->bits->xhot;
1923         sy = pScreenPriv->y - (int)pCursor->bits->yhot;
1924         if (sx + (int) pCursor->bits->width >= pScreenPriv->saved.x1 &&
1925             sx < pScreenPriv->saved.x2 &&
1926             sy + (int) pCursor->bits->height >= pScreenPriv->saved.y1 &&
1927             sy < pScreenPriv->saved.y2 &&
1928             (int) pCursor->bits->width + (2 * SPRITE_PAD) ==
1929                 pScreenPriv->saved.x2 - pScreenPriv->saved.x1 &&
1930             (int) pCursor->bits->height + (2 * SPRITE_PAD) ==
1931                 pScreenPriv->saved.y2 - pScreenPriv->saved.y1
1932             )
1933         {
1934             pScreenPriv->isUp = FALSE;
1935             if (!(sx >= pScreenPriv->saved.x1 &&
1936                   sx + (int)pCursor->bits->width < pScreenPriv->saved.x2 &&
1937                   sy >= pScreenPriv->saved.y1 &&
1938                   sy + (int)pCursor->bits->height < pScreenPriv->saved.y2))
1939             {
1940                 int oldx1, oldy1, dx, dy;
1941
1942                 oldx1 = pScreenPriv->saved.x1;
1943                 oldy1 = pScreenPriv->saved.y1;
1944                 dx = oldx1 - (sx - SPRITE_PAD);
1945                 dy = oldy1 - (sy - SPRITE_PAD);
1946                 pScreenPriv->saved.x1 -= dx;
1947                 pScreenPriv->saved.y1 -= dy;
1948                 pScreenPriv->saved.x2 -= dx;
1949                 pScreenPriv->saved.y2 -= dy;
1950                 (void) (*pScreenPriv->funcs->ChangeSave) (pScreen,
1951                                 pScreenPriv->saved.x1,
1952                                 pScreenPriv->saved.y1,
1953                                 pScreenPriv->saved.x2 - pScreenPriv->saved.x1,
1954                                 pScreenPriv->saved.y2 - pScreenPriv->saved.y1,
1955                                 dx, dy);
1956             }
1957             (void) (*pScreenPriv->funcs->MoveCursor) (pScreen, pCursor,
1958                                   pScreenPriv->saved.x1,
1959                                   pScreenPriv->saved.y1,
1960                                   pScreenPriv->saved.x2 - pScreenPriv->saved.x1,
1961                                   pScreenPriv->saved.y2 - pScreenPriv->saved.y1,
1962                                   sx - pScreenPriv->saved.x1,
1963                                   sy - pScreenPriv->saved.y1,
1964                                   pScreenPriv->colors[SOURCE_COLOR].pixel,
1965                                   pScreenPriv->colors[MASK_COLOR].pixel);
1966             pScreenPriv->isUp = TRUE;
1967         }
1968         else
1969         {
1970             miSpriteRemoveCursor (pScreen);
1971         }
1972     }
1973     if (!pScreenPriv->isUp && pScreenPriv->pCursor)
1974         miSpriteRestoreCursor (pScreen);
1975 }
1976
1977 static void
1978 miSpriteMoveCursor (pScreen, x, y)
1979     ScreenPtr   pScreen;
1980     int         x, y;
1981 {
1982     miSpriteScreenPtr   pScreenPriv;
1983
1984     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
1985     miSpriteSetCursor (pScreen, pScreenPriv->pCursor, x, y);
1986 }
1987
1988 /*
1989  * undraw/draw cursor
1990  */
1991
1992 static void
1993 miSpriteRemoveCursor (pScreen)
1994     ScreenPtr   pScreen;
1995 {
1996     miSpriteScreenPtr   pScreenPriv;
1997
1998     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
1999     pScreenPriv->isUp = FALSE;
2000     pScreenPriv->pCacheWin = NullWindow;
2001     if (!(*pScreenPriv->funcs->RestoreUnderCursor) (pScreen,
2002                                          pScreenPriv->saved.x1,
2003                                          pScreenPriv->saved.y1,
2004                                          pScreenPriv->saved.x2 - pScreenPriv->saved.x1,
2005                                          pScreenPriv->saved.y2 - pScreenPriv->saved.y1))
2006     {
2007         pScreenPriv->isUp = TRUE;
2008     }
2009 }
2010
2011 /*
2012  * Called from the block handler, restores the cursor
2013  * before waiting for something to do.
2014  */
2015
2016 static void
2017 miSpriteRestoreCursor (pScreen)
2018     ScreenPtr   pScreen;
2019 {
2020     miSpriteScreenPtr   pScreenPriv;
2021     int                 x, y;
2022     CursorPtr           pCursor;
2023
2024     miSpriteComputeSaved (pScreen);
2025     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
2026     pCursor = pScreenPriv->pCursor;
2027     x = pScreenPriv->x - (int)pCursor->bits->xhot;
2028     y = pScreenPriv->y - (int)pCursor->bits->yhot;
2029     if ((*pScreenPriv->funcs->SaveUnderCursor) (pScreen,
2030                                       pScreenPriv->saved.x1,
2031                                       pScreenPriv->saved.y1,
2032                                       pScreenPriv->saved.x2 - pScreenPriv->saved.x1,
2033                                       pScreenPriv->saved.y2 - pScreenPriv->saved.y1))
2034     {
2035         if (pScreenPriv->checkPixels)
2036             miSpriteFindColors (pScreen);
2037         if ((*pScreenPriv->funcs->PutUpCursor) (pScreen, pCursor, x, y,
2038                                   pScreenPriv->colors[SOURCE_COLOR].pixel,
2039                                   pScreenPriv->colors[MASK_COLOR].pixel))
2040             pScreenPriv->isUp = TRUE;
2041     }
2042 }
2043
2044 /*
2045  * compute the desired area of the screen to save
2046  */
2047
2048 static void
2049 miSpriteComputeSaved (pScreen)
2050     ScreenPtr   pScreen;
2051 {
2052     miSpriteScreenPtr   pScreenPriv;
2053     int             x, y, w, h;
2054     int             wpad, hpad;
2055     CursorPtr       pCursor;
2056
2057     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
2058     pCursor = pScreenPriv->pCursor;
2059     x = pScreenPriv->x - (int)pCursor->bits->xhot;
2060     y = pScreenPriv->y - (int)pCursor->bits->yhot;
2061     w = pCursor->bits->width;
2062     h = pCursor->bits->height;
2063     wpad = SPRITE_PAD;
2064     hpad = SPRITE_PAD;
2065     pScreenPriv->saved.x1 = x - wpad;
2066     pScreenPriv->saved.y1 = y - hpad;
2067     pScreenPriv->saved.x2 = pScreenPriv->saved.x1 + w + wpad * 2;
2068     pScreenPriv->saved.y2 = pScreenPriv->saved.y1 + h + hpad * 2;
2069 }