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