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