]> git.sesse.net Git - rdpsrv/blob - Xserver/programs/Xserver/mi/midispcur.c
5ea478ea0f37c916aacd0e81d85cc0d4b3c6d254
[rdpsrv] / Xserver / programs / Xserver / mi / midispcur.c
1 /*
2  * midispcur.c
3  *
4  * machine independent cursor display routines
5  */
6
7 /* $XConsortium: midispcur.c,v 5.14 94/04/17 20:27:28 dpw Exp $ */
8
9 /*
10
11 Copyright (c) 1989  X Consortium
12
13 Permission is hereby granted, free of charge, to any person obtaining a copy
14 of this software and associated documentation files (the "Software"), to deal
15 in the Software without restriction, including without limitation the rights
16 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 copies of the Software, and to permit persons to whom the Software is
18 furnished to do so, subject to the following conditions:
19
20 The above copyright notice and this permission notice shall be included in
21 all copies or substantial portions of the Software.
22
23 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
26 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
27 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
28 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29
30 Except as contained in this notice, the name of the X Consortium shall not be
31 used in advertising or otherwise to promote the sale, use or other dealings
32 in this Software without prior written authorization from the X Consortium.
33 */
34
35 #define NEED_EVENTS
36 # include   "X.h"
37 # include   "misc.h"
38 # include   "input.h"
39 # include   "cursorstr.h"
40 # include   "windowstr.h"
41 # include   "regionstr.h"
42 # include   "dixstruct.h"
43 # include   "scrnintstr.h"
44 # include   "servermd.h"
45 # include   "mipointer.h"
46 # include   "misprite.h"
47 # include   "gcstruct.h"
48
49 extern WindowPtr    *WindowTable;
50
51 /* per-screen private data */
52
53 static int      miDCScreenIndex;
54 static unsigned long miDCGeneration = 0;
55
56 static Bool     miDCCloseScreen();
57
58 typedef struct {
59     GCPtr           pSourceGC, pMaskGC;
60     GCPtr           pSaveGC, pRestoreGC;
61     GCPtr           pMoveGC;
62     GCPtr           pPixSourceGC, pPixMaskGC;
63     CloseScreenProcPtr CloseScreen;
64     PixmapPtr       pSave, pTemp;
65 } miDCScreenRec, *miDCScreenPtr;
66
67 /* per-cursor per-screen private data */
68 typedef struct {
69     PixmapPtr           sourceBits;         /* source bits */
70     PixmapPtr           maskBits;           /* mask bits */
71 } miDCCursorRec, *miDCCursorPtr;
72
73 /*
74  * sprite/cursor method table
75  */
76
77 static Bool     miDCRealizeCursor(),        miDCUnrealizeCursor();
78 static Bool     miDCPutUpCursor(),          miDCSaveUnderCursor();
79 static Bool     miDCRestoreUnderCursor(),   miDCMoveCursor();
80 static Bool     miDCChangeSave();
81
82 static miSpriteCursorFuncRec miDCFuncs = {
83     miDCRealizeCursor,
84     miDCUnrealizeCursor,
85     miDCPutUpCursor,
86     miDCSaveUnderCursor,
87     miDCRestoreUnderCursor,
88     miDCMoveCursor,
89     miDCChangeSave,
90 };
91
92 Bool
93 miDCInitialize (pScreen, screenFuncs)
94     ScreenPtr               pScreen;
95     miPointerScreenFuncPtr  screenFuncs;
96 {
97     miDCScreenPtr   pScreenPriv;
98
99     if (miDCGeneration != serverGeneration)
100     {
101         miDCScreenIndex = AllocateScreenPrivateIndex ();
102         if (miDCScreenIndex < 0)
103             return FALSE;
104         miDCGeneration = serverGeneration;
105     }
106     pScreenPriv = (miDCScreenPtr) xalloc (sizeof (miDCScreenRec));
107     if (!pScreenPriv)
108         return FALSE;
109
110     /*
111      * initialize the entire private structure to zeros
112      */
113
114     pScreenPriv->pSourceGC =
115         pScreenPriv->pMaskGC =
116         pScreenPriv->pSaveGC =
117         pScreenPriv->pRestoreGC =
118         pScreenPriv->pMoveGC =
119         pScreenPriv->pPixSourceGC =
120         pScreenPriv->pPixMaskGC = NULL;
121     
122     pScreenPriv->pSave = pScreenPriv->pTemp = NULL;
123
124     pScreenPriv->CloseScreen = pScreen->CloseScreen;
125     pScreen->CloseScreen = miDCCloseScreen;
126     
127     pScreen->devPrivates[miDCScreenIndex].ptr = (pointer) pScreenPriv;
128
129     if (!miSpriteInitialize (pScreen, &miDCFuncs, screenFuncs))
130     {
131         xfree ((pointer) pScreenPriv);
132         return FALSE;
133     }
134     return TRUE;
135 }
136
137 #define tossGC(gc)  (gc ? FreeGC (gc, (GContext) 0) : 0)
138 #define tossPix(pix)    (pix ? (*pScreen->DestroyPixmap) (pix) : TRUE)
139
140 static Bool
141 miDCCloseScreen (index, pScreen)
142     ScreenPtr   pScreen;
143 {
144     miDCScreenPtr   pScreenPriv;
145
146     pScreenPriv = (miDCScreenPtr) pScreen->devPrivates[miDCScreenIndex].ptr;
147     pScreen->CloseScreen = pScreenPriv->CloseScreen;
148     tossGC (pScreenPriv->pSourceGC);
149     tossGC (pScreenPriv->pMaskGC);
150     tossGC (pScreenPriv->pSaveGC);
151     tossGC (pScreenPriv->pRestoreGC);
152     tossGC (pScreenPriv->pMoveGC);
153     tossGC (pScreenPriv->pPixSourceGC);
154     tossGC (pScreenPriv->pPixMaskGC);
155     tossPix (pScreenPriv->pSave);
156     tossPix (pScreenPriv->pTemp);
157     xfree ((pointer) pScreenPriv);
158     return (*pScreen->CloseScreen) (index, pScreen);
159 }
160
161 static Bool
162 miDCRealizeCursor (pScreen, pCursor)
163     ScreenPtr   pScreen;
164     CursorPtr   pCursor;
165 {
166     if (pCursor->bits->refcnt <= 1)
167         pCursor->bits->devPriv[pScreen->myNum] = (pointer)NULL;
168     return TRUE;
169 }
170
171 static miDCCursorPtr
172 miDCRealize (pScreen, pCursor)
173     ScreenPtr   pScreen;
174     CursorPtr   pCursor;
175 {
176     miDCCursorPtr   pPriv;
177     GCPtr           pGC;
178     XID             gcvals[3];
179
180     pPriv = (miDCCursorPtr) xalloc (sizeof (miDCCursorRec));
181     if (!pPriv)
182         return (miDCCursorPtr)NULL;
183     pPriv->sourceBits = (*pScreen->CreatePixmap) (pScreen, pCursor->bits->width, pCursor->bits->height, 1);
184     if (!pPriv->sourceBits)
185     {
186         xfree ((pointer) pPriv);
187         return (miDCCursorPtr)NULL;
188     }
189     pPriv->maskBits =  (*pScreen->CreatePixmap) (pScreen, pCursor->bits->width, pCursor->bits->height, 1);
190     if (!pPriv->maskBits)
191     {
192         (*pScreen->DestroyPixmap) (pPriv->sourceBits);
193         xfree ((pointer) pPriv);
194         return (miDCCursorPtr)NULL;
195     }
196     pCursor->bits->devPriv[pScreen->myNum] = (pointer) pPriv;
197
198     /* create the two sets of bits, clipping as appropriate */
199
200     pGC = GetScratchGC (1, pScreen);
201     if (!pGC)
202     {
203         (void) miDCUnrealizeCursor (pScreen, pCursor);
204         return (miDCCursorPtr)NULL;
205     }
206
207     ValidateGC ((DrawablePtr)pPriv->sourceBits, pGC);
208     (*pGC->ops->PutImage) ((DrawablePtr)pPriv->sourceBits, pGC, 1,
209                            0, 0, pCursor->bits->width, pCursor->bits->height,
210                            0, XYPixmap, (char *)pCursor->bits->source);
211     gcvals[0] = GXand;
212     ChangeGC (pGC, GCFunction, gcvals);
213     ValidateGC ((DrawablePtr)pPriv->sourceBits, pGC);
214     (*pGC->ops->PutImage) ((DrawablePtr)pPriv->sourceBits, pGC, 1,
215                            0, 0, pCursor->bits->width, pCursor->bits->height,
216                            0, XYPixmap, (char *)pCursor->bits->mask);
217
218     /* mask bits -- pCursor->mask & ~pCursor->source */
219     gcvals[0] = GXcopy;
220     ChangeGC (pGC, GCFunction, gcvals);
221     ValidateGC ((DrawablePtr)pPriv->maskBits, pGC);
222     (*pGC->ops->PutImage) ((DrawablePtr)pPriv->maskBits, pGC, 1,
223                            0, 0, pCursor->bits->width, pCursor->bits->height,
224                            0, XYPixmap, (char *)pCursor->bits->mask);
225     gcvals[0] = GXandInverted;
226     ChangeGC (pGC, GCFunction, gcvals);
227     ValidateGC ((DrawablePtr)pPriv->maskBits, pGC);
228     (*pGC->ops->PutImage) ((DrawablePtr)pPriv->maskBits, pGC, 1,
229                            0, 0, pCursor->bits->width, pCursor->bits->height,
230                            0, XYPixmap, (char *)pCursor->bits->source);
231     FreeScratchGC (pGC);
232     return pPriv;
233 }
234
235 static Bool
236 miDCUnrealizeCursor (pScreen, pCursor)
237     ScreenPtr   pScreen;
238     CursorPtr   pCursor;
239 {
240     miDCCursorPtr   pPriv;
241
242     pPriv = (miDCCursorPtr) pCursor->bits->devPriv[pScreen->myNum];
243     if (pPriv && (pCursor->bits->refcnt <= 1))
244     {
245         (*pScreen->DestroyPixmap) (pPriv->sourceBits);
246         (*pScreen->DestroyPixmap) (pPriv->maskBits);
247         xfree ((pointer) pPriv);
248         pCursor->bits->devPriv[pScreen->myNum] = (pointer)NULL;
249     }
250     return TRUE;
251 }
252
253 static void
254 miDCPutBits (pDrawable, pPriv, sourceGC, maskGC, x, y, w, h, source, mask)
255     DrawablePtr     pDrawable;
256     GCPtr           sourceGC, maskGC;
257     int             x, y;
258     unsigned        w, h;
259     miDCCursorPtr   pPriv;
260     unsigned long   source, mask;
261 {
262     XID     gcvals[1];
263
264     if (sourceGC->fgPixel != source)
265     {
266         gcvals[0] = source;
267         DoChangeGC (sourceGC, GCForeground, gcvals, 0);
268     }
269     if (sourceGC->serialNumber != pDrawable->serialNumber)
270         ValidateGC (pDrawable, sourceGC);
271     (*sourceGC->ops->PushPixels) (sourceGC, pPriv->sourceBits, pDrawable, w, h, x, y);
272     if (maskGC->fgPixel != mask)
273     {
274         gcvals[0] = mask;
275         DoChangeGC (maskGC, GCForeground, gcvals, 0);
276     }
277     if (maskGC->serialNumber != pDrawable->serialNumber)
278         ValidateGC (pDrawable, maskGC);
279     (*maskGC->ops->PushPixels) (maskGC, pPriv->maskBits, pDrawable, w, h, x, y);
280 }
281
282 #define EnsureGC(gc,win) (gc || miDCMakeGC(&gc, win))
283
284 static GCPtr
285 miDCMakeGC(ppGC, pWin)
286     GCPtr       *ppGC;
287     WindowPtr   pWin;
288 {
289     GCPtr pGC;
290     int   status;
291     XID   gcvals[2];
292
293     gcvals[0] = IncludeInferiors;
294     gcvals[1] = FALSE;
295     pGC = CreateGC((DrawablePtr)pWin,
296                    GCSubwindowMode|GCGraphicsExposures, gcvals, &status);
297     if (pGC)
298         (*pWin->drawable.pScreen->DrawGuarantee) (pWin, pGC, GuaranteeVisBack);
299     *ppGC = pGC;
300     return pGC;
301 }
302
303 static Bool
304 miDCPutUpCursor (pScreen, pCursor, x, y, source, mask)
305     ScreenPtr       pScreen;
306     CursorPtr       pCursor;
307     int             x, y;
308     unsigned long   source, mask;
309 {
310     miDCScreenPtr   pScreenPriv;
311     miDCCursorPtr   pPriv;
312     WindowPtr       pWin;
313
314     pPriv = (miDCCursorPtr) pCursor->bits->devPriv[pScreen->myNum];
315     if (!pPriv)
316     {
317         pPriv = miDCRealize(pScreen, pCursor);
318         if (!pPriv)
319             return FALSE;
320     }
321     pScreenPriv = (miDCScreenPtr) pScreen->devPrivates[miDCScreenIndex].ptr;
322     pWin = WindowTable[pScreen->myNum];
323     if (!EnsureGC(pScreenPriv->pSourceGC, pWin))
324         return FALSE;
325     if (!EnsureGC(pScreenPriv->pMaskGC, pWin))
326     {
327         FreeGC (pScreenPriv->pSourceGC, (GContext) 0);
328         pScreenPriv->pSourceGC = 0;
329         return FALSE;
330     }
331     miDCPutBits ((DrawablePtr)pWin, pPriv,
332                  pScreenPriv->pSourceGC, pScreenPriv->pMaskGC,
333                  x, y, pCursor->bits->width, pCursor->bits->height,
334                  source, mask);
335     return TRUE;
336 }
337
338 static Bool
339 miDCSaveUnderCursor (pScreen, x, y, w, h)
340     ScreenPtr   pScreen;
341     int         x, y, w, h;
342 {
343     miDCScreenPtr   pScreenPriv;
344     PixmapPtr       pSave;
345     WindowPtr       pWin;
346     GCPtr           pGC;
347
348     pScreenPriv = (miDCScreenPtr) pScreen->devPrivates[miDCScreenIndex].ptr;
349     pSave = pScreenPriv->pSave;
350     pWin = WindowTable[pScreen->myNum];
351     if (!pSave || pSave->drawable.width < w || pSave->drawable.height < h)
352     {
353         if (pSave)
354             (*pScreen->DestroyPixmap) (pSave);
355         pScreenPriv->pSave = pSave =
356                 (*pScreen->CreatePixmap) (pScreen, w, h, pScreen->rootDepth);
357         if (!pSave)
358             return FALSE;
359     }
360     if (!EnsureGC(pScreenPriv->pSaveGC, pWin))
361         return FALSE;
362     pGC = pScreenPriv->pSaveGC;
363     if (pSave->drawable.serialNumber != pGC->serialNumber)
364         ValidateGC ((DrawablePtr) pSave, pGC);
365     (*pGC->ops->CopyArea) ((DrawablePtr) pWin, (DrawablePtr) pSave, pGC,
366                             x, y, w, h, 0, 0);
367     return TRUE;
368 }
369
370 static Bool
371 miDCRestoreUnderCursor (pScreen, x, y, w, h)
372     ScreenPtr   pScreen;
373     int         x, y, w, h;
374 {
375     miDCScreenPtr   pScreenPriv;
376     PixmapPtr       pSave;
377     WindowPtr       pWin;
378     GCPtr           pGC;
379
380     pScreenPriv = (miDCScreenPtr) pScreen->devPrivates[miDCScreenIndex].ptr;
381     pSave = pScreenPriv->pSave;
382     pWin = WindowTable[pScreen->myNum];
383     if (!pSave)
384         return FALSE;
385     if (!EnsureGC(pScreenPriv->pRestoreGC, pWin))
386         return FALSE;
387     pGC = pScreenPriv->pRestoreGC;
388     if (pWin->drawable.serialNumber != pGC->serialNumber)
389         ValidateGC ((DrawablePtr) pWin, pGC);
390     (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC,
391                             0, 0, w, h, x, y);
392     return TRUE;
393 }
394
395 static Bool
396 miDCChangeSave (pScreen, x, y, w, h, dx, dy)
397     ScreenPtr       pScreen;
398     int             x, y, w, h, dx, dy;
399 {
400     miDCScreenPtr   pScreenPriv;
401     PixmapPtr       pSave;
402     WindowPtr       pWin;
403     GCPtr           pGC;
404     int             sourcex, sourcey, destx, desty, copyw, copyh;
405
406     pScreenPriv = (miDCScreenPtr) pScreen->devPrivates[miDCScreenIndex].ptr;
407     pSave = pScreenPriv->pSave;
408     pWin = WindowTable[pScreen->myNum];
409     /*
410      * restore the bits which are about to get trashed
411      */
412     if (!pSave)
413         return FALSE;
414     if (!EnsureGC(pScreenPriv->pRestoreGC, pWin))
415         return FALSE;
416     pGC = pScreenPriv->pRestoreGC;
417     if (pWin->drawable.serialNumber != pGC->serialNumber)
418         ValidateGC ((DrawablePtr) pWin, pGC);
419     /*
420      * copy the old bits to the screen.
421      */
422     if (dy > 0)
423     {
424         (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC,
425                                0, h - dy, w, dy, x + dx, y + h);
426     }
427     else if (dy < 0)
428     {
429         (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC,
430                                0, 0, w, -dy, x + dx, y + dy);
431     }
432     if (dy >= 0)
433     {
434         desty = y + dy;
435         sourcey = 0;
436         copyh = h - dy;
437     }
438     else
439     {
440         desty = y;
441         sourcey = - dy;
442         copyh = h + dy;
443     }
444     if (dx > 0)
445     {
446         (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC,
447                                w - dx, sourcey, dx, copyh, x + w, desty);
448     }
449     else if (dx < 0)
450     {
451         (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC,
452                                0, sourcey, -dx, copyh, x + dx, desty);
453     }
454     if (!EnsureGC(pScreenPriv->pSaveGC, pWin))
455         return FALSE;
456     pGC = pScreenPriv->pSaveGC;
457     if (pSave->drawable.serialNumber != pGC->serialNumber)
458         ValidateGC ((DrawablePtr) pSave, pGC);
459     /*
460      * move the bits that are still valid within the pixmap
461      */
462     if (dx >= 0)
463     {
464         sourcex = 0;
465         destx = dx;
466         copyw = w - dx;
467     }
468     else
469     {
470         destx = 0;
471         sourcex = - dx;
472         copyw = w + dx;
473     }
474     if (dy >= 0)
475     {
476         sourcey = 0;
477         desty = dy;
478         copyh = h - dy;
479     }
480     else
481     {
482         desty = 0;
483         sourcey = -dy;
484         copyh = h + dy;
485     }
486     (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pSave, pGC,
487                            sourcex, sourcey, copyw, copyh, destx, desty);
488     /*
489      * copy the new bits from the screen into the remaining areas of the
490      * pixmap
491      */
492     if (dy > 0)
493     {
494         (*pGC->ops->CopyArea) ((DrawablePtr) pWin, (DrawablePtr) pSave, pGC,
495                                x, y, w, dy, 0, 0);
496     }
497     else if (dy < 0)
498     {
499         (*pGC->ops->CopyArea) ((DrawablePtr) pWin, (DrawablePtr) pSave, pGC,
500                                x, y + h + dy, w, -dy, 0, h + dy);
501     }
502     if (dy >= 0)
503     {
504         desty = dy;
505         sourcey = y + dy;
506         copyh = h - dy;
507     }
508     else
509     {
510         desty = 0;
511         sourcey = y;
512         copyh = h + dy;
513     }
514     if (dx > 0)
515     {
516         (*pGC->ops->CopyArea) ((DrawablePtr) pWin, (DrawablePtr) pSave, pGC,
517                                x, sourcey, dx, copyh, 0, desty);
518     }
519     else if (dx < 0)
520     {
521         (*pGC->ops->CopyArea) ((DrawablePtr) pWin, (DrawablePtr) pSave, pGC,
522                                x + w + dx, sourcey, -dx, copyh, w + dx, desty);
523     }
524     return TRUE;
525 }
526
527 static Bool
528 miDCMoveCursor (pScreen, pCursor, x, y, w, h, dx, dy, source, mask)
529     ScreenPtr       pScreen;
530     CursorPtr       pCursor;
531     int             x, y, w, h, dx, dy;
532     unsigned long   source, mask;
533 {
534     miDCCursorPtr   pPriv;
535     miDCScreenPtr   pScreenPriv;
536     int             status;
537     WindowPtr       pWin;
538     GCPtr           pGC;
539     XID             gcval = FALSE;
540     PixmapPtr       pTemp;
541
542     pPriv = (miDCCursorPtr) pCursor->bits->devPriv[pScreen->myNum];
543     if (!pPriv)
544     {
545         pPriv = miDCRealize(pScreen, pCursor);
546         if (!pPriv)
547             return FALSE;
548     }
549     pScreenPriv = (miDCScreenPtr) pScreen->devPrivates[miDCScreenIndex].ptr;
550     pWin = WindowTable[pScreen->myNum];
551     pTemp = pScreenPriv->pTemp;
552     if (!pTemp ||
553         pTemp->drawable.width != pScreenPriv->pSave->drawable.width ||
554         pTemp->drawable.height != pScreenPriv->pSave->drawable.height)
555     {
556         if (pTemp)
557             (*pScreen->DestroyPixmap) (pTemp);
558         pScreenPriv->pTemp = pTemp = (*pScreen->CreatePixmap)
559             (pScreen, w, h, pScreenPriv->pSave->drawable.depth);
560         if (!pTemp)
561             return FALSE;
562     }
563     if (!pScreenPriv->pMoveGC)
564     {
565         pScreenPriv->pMoveGC = CreateGC ((DrawablePtr)pTemp,
566             GCGraphicsExposures, &gcval, &status);
567         if (!pScreenPriv->pMoveGC)
568             return FALSE;
569     }
570     /*
571      * copy the saved area to a temporary pixmap
572      */
573     pGC = pScreenPriv->pMoveGC;
574     if (pGC->serialNumber != pTemp->drawable.serialNumber)
575         ValidateGC ((DrawablePtr) pTemp, pGC);
576     (*pGC->ops->CopyArea)((DrawablePtr)pScreenPriv->pSave,
577                           (DrawablePtr)pTemp, pGC, 0, 0, w, h, 0, 0);
578     
579     /*
580      * draw the cursor in the temporary pixmap
581      */
582     if (!pScreenPriv->pPixSourceGC)
583     {
584         pScreenPriv->pPixSourceGC = CreateGC ((DrawablePtr)pTemp,
585             GCGraphicsExposures, &gcval, &status);
586         if (!pScreenPriv->pPixSourceGC)
587             return FALSE;
588     }
589     if (!pScreenPriv->pPixMaskGC)
590     {
591         pScreenPriv->pPixMaskGC = CreateGC ((DrawablePtr)pTemp,
592             GCGraphicsExposures, &gcval, &status);
593         if (!pScreenPriv->pPixMaskGC)
594             return FALSE;
595     }
596     miDCPutBits ((DrawablePtr)pTemp, pPriv,
597                  pScreenPriv->pPixSourceGC, pScreenPriv->pPixMaskGC,
598                  dx, dy, pCursor->bits->width, pCursor->bits->height,
599                  source, mask);
600
601     /*
602      * copy the temporary pixmap onto the screen
603      */
604
605     if (!EnsureGC(pScreenPriv->pRestoreGC, pWin))
606         return FALSE;
607     pGC = pScreenPriv->pRestoreGC;
608     if (pWin->drawable.serialNumber != pGC->serialNumber)
609         ValidateGC ((DrawablePtr) pWin, pGC);
610
611     (*pGC->ops->CopyArea) ((DrawablePtr) pTemp, (DrawablePtr) pWin,
612                             pGC,
613                             0, 0, w, h, x, y);
614     return TRUE;
615 }