panoramiXprocs.c revision 25da500f
1/*****************************************************************
2Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
3Permission is hereby granted, free of charge, to any person obtaining a copy
4of this software and associated documentation files (the "Software"), to deal
5in the Software without restriction, including without limitation the rights
6to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7copies of the Software.
8
9The above copyright notice and this permission notice shall be included in
10all copies or substantial portions of the Software.
11
12THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
15DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
16BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
17WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
18IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19
20Except as contained in this notice, the name of Digital Equipment Corporation
21shall not be used in advertising or otherwise to promote the sale, use or other
22dealings in this Software without prior written authorization from Digital
23Equipment Corporation.
24******************************************************************/
25
26/* Massively rewritten by Mark Vojkovich <markv@valinux.com> */
27
28#ifdef HAVE_DIX_CONFIG_H
29#include <dix-config.h>
30#endif
31
32#include <stdio.h>
33#include <X11/X.h>
34#include <X11/Xproto.h>
35#include "windowstr.h"
36#include "dixfontstr.h"
37#include "gcstruct.h"
38#include "colormapst.h"
39#include "scrnintstr.h"
40#include "opaque.h"
41#include "inputstr.h"
42#include "migc.h"
43#include "misc.h"
44#include "dixstruct.h"
45#include "panoramiX.h"
46#include "panoramiXsrv.h"
47#include "resource.h"
48#include "panoramiXh.h"
49
50#define XINERAMA_IMAGE_BUFSIZE (256*1024)
51#define INPUTONLY_LEGAL_MASK (CWWinGravity | CWEventMask | \
52                              CWDontPropagate | CWOverrideRedirect | CWCursor )
53
54int
55PanoramiXCreateWindow(ClientPtr client)
56{
57    PanoramiXRes *parent, *newWin;
58    PanoramiXRes *backPix = NULL;
59    PanoramiXRes *bordPix = NULL;
60    PanoramiXRes *cmap = NULL;
61
62    REQUEST(xCreateWindowReq);
63    int pback_offset = 0, pbord_offset = 0, cmap_offset = 0;
64    int result, len, j;
65    int orig_x, orig_y;
66    XID orig_visual, tmp;
67    Bool parentIsRoot;
68
69    REQUEST_AT_LEAST_SIZE(xCreateWindowReq);
70
71    len = client->req_len - bytes_to_int32(sizeof(xCreateWindowReq));
72    if (Ones(stuff->mask) != len)
73        return BadLength;
74
75    result = dixLookupResourceByType((void **) &parent, stuff->parent,
76                                     XRT_WINDOW, client, DixWriteAccess);
77    if (result != Success)
78        return result;
79
80    if (stuff->class == CopyFromParent)
81        stuff->class = parent->u.win.class;
82
83    if ((stuff->class == InputOnly) && (stuff->mask & (~INPUTONLY_LEGAL_MASK)))
84        return BadMatch;
85
86    if ((Mask) stuff->mask & CWBackPixmap) {
87        pback_offset = Ones((Mask) stuff->mask & (CWBackPixmap - 1));
88        tmp = *((CARD32 *) &stuff[1] + pback_offset);
89        if ((tmp != None) && (tmp != ParentRelative)) {
90            result = dixLookupResourceByType((void **) &backPix, tmp,
91                                             XRT_PIXMAP, client, DixReadAccess);
92            if (result != Success)
93                return result;
94        }
95    }
96    if ((Mask) stuff->mask & CWBorderPixmap) {
97        pbord_offset = Ones((Mask) stuff->mask & (CWBorderPixmap - 1));
98        tmp = *((CARD32 *) &stuff[1] + pbord_offset);
99        if (tmp != CopyFromParent) {
100            result = dixLookupResourceByType((void **) &bordPix, tmp,
101                                             XRT_PIXMAP, client, DixReadAccess);
102            if (result != Success)
103                return result;
104        }
105    }
106    if ((Mask) stuff->mask & CWColormap) {
107        cmap_offset = Ones((Mask) stuff->mask & (CWColormap - 1));
108        tmp = *((CARD32 *) &stuff[1] + cmap_offset);
109        if (tmp != CopyFromParent) {
110            result = dixLookupResourceByType((void **) &cmap, tmp,
111                                             XRT_COLORMAP, client,
112                                             DixReadAccess);
113            if (result != Success)
114                return result;
115        }
116    }
117
118    if (!(newWin = malloc(sizeof(PanoramiXRes))))
119        return BadAlloc;
120
121    newWin->type = XRT_WINDOW;
122    newWin->u.win.visibility = VisibilityNotViewable;
123    newWin->u.win.class = stuff->class;
124    newWin->u.win.root = FALSE;
125    panoramix_setup_ids(newWin, client, stuff->wid);
126
127    if (stuff->class == InputOnly)
128        stuff->visual = CopyFromParent;
129    orig_visual = stuff->visual;
130    orig_x = stuff->x;
131    orig_y = stuff->y;
132    parentIsRoot = (stuff->parent == screenInfo.screens[0]->root->drawable.id)
133        || (stuff->parent == screenInfo.screens[0]->screensaver.wid);
134    FOR_NSCREENS_BACKWARD(j) {
135        stuff->wid = newWin->info[j].id;
136        stuff->parent = parent->info[j].id;
137        if (parentIsRoot) {
138            stuff->x = orig_x - screenInfo.screens[j]->x;
139            stuff->y = orig_y - screenInfo.screens[j]->y;
140        }
141        if (backPix)
142            *((CARD32 *) &stuff[1] + pback_offset) = backPix->info[j].id;
143        if (bordPix)
144            *((CARD32 *) &stuff[1] + pbord_offset) = bordPix->info[j].id;
145        if (cmap)
146            *((CARD32 *) &stuff[1] + cmap_offset) = cmap->info[j].id;
147        if (orig_visual != CopyFromParent)
148            stuff->visual = PanoramiXTranslateVisualID(j, orig_visual);
149        result = (*SavedProcVector[X_CreateWindow]) (client);
150        if (result != Success)
151            break;
152    }
153
154    if (result == Success)
155        AddResource(newWin->info[0].id, XRT_WINDOW, newWin);
156    else
157        free(newWin);
158
159    return result;
160}
161
162int
163PanoramiXChangeWindowAttributes(ClientPtr client)
164{
165    PanoramiXRes *win;
166    PanoramiXRes *backPix = NULL;
167    PanoramiXRes *bordPix = NULL;
168    PanoramiXRes *cmap = NULL;
169
170    REQUEST(xChangeWindowAttributesReq);
171    int pback_offset = 0, pbord_offset = 0, cmap_offset = 0;
172    int result, len, j;
173    XID tmp;
174
175    REQUEST_AT_LEAST_SIZE(xChangeWindowAttributesReq);
176
177    len = client->req_len - bytes_to_int32(sizeof(xChangeWindowAttributesReq));
178    if (Ones(stuff->valueMask) != len)
179        return BadLength;
180
181    result = dixLookupResourceByType((void **) &win, stuff->window,
182                                     XRT_WINDOW, client, DixWriteAccess);
183    if (result != Success)
184        return result;
185
186    if ((win->u.win.class == InputOnly) &&
187        (stuff->valueMask & (~INPUTONLY_LEGAL_MASK)))
188        return BadMatch;
189
190    if ((Mask) stuff->valueMask & CWBackPixmap) {
191        pback_offset = Ones((Mask) stuff->valueMask & (CWBackPixmap - 1));
192        tmp = *((CARD32 *) &stuff[1] + pback_offset);
193        if ((tmp != None) && (tmp != ParentRelative)) {
194            result = dixLookupResourceByType((void **) &backPix, tmp,
195                                             XRT_PIXMAP, client, DixReadAccess);
196            if (result != Success)
197                return result;
198        }
199    }
200    if ((Mask) stuff->valueMask & CWBorderPixmap) {
201        pbord_offset = Ones((Mask) stuff->valueMask & (CWBorderPixmap - 1));
202        tmp = *((CARD32 *) &stuff[1] + pbord_offset);
203        if (tmp != CopyFromParent) {
204            result = dixLookupResourceByType((void **) &bordPix, tmp,
205                                             XRT_PIXMAP, client, DixReadAccess);
206            if (result != Success)
207                return result;
208        }
209    }
210    if ((Mask) stuff->valueMask & CWColormap) {
211        cmap_offset = Ones((Mask) stuff->valueMask & (CWColormap - 1));
212        tmp = *((CARD32 *) &stuff[1] + cmap_offset);
213        if (tmp != CopyFromParent) {
214            result = dixLookupResourceByType((void **) &cmap, tmp,
215                                             XRT_COLORMAP, client,
216                                             DixReadAccess);
217            if (result != Success)
218                return result;
219        }
220    }
221
222    FOR_NSCREENS_BACKWARD(j) {
223        stuff->window = win->info[j].id;
224        if (backPix)
225            *((CARD32 *) &stuff[1] + pback_offset) = backPix->info[j].id;
226        if (bordPix)
227            *((CARD32 *) &stuff[1] + pbord_offset) = bordPix->info[j].id;
228        if (cmap)
229            *((CARD32 *) &stuff[1] + cmap_offset) = cmap->info[j].id;
230        result = (*SavedProcVector[X_ChangeWindowAttributes]) (client);
231    }
232
233    return result;
234}
235
236int
237PanoramiXDestroyWindow(ClientPtr client)
238{
239    PanoramiXRes *win;
240    int result, j;
241
242    REQUEST(xResourceReq);
243
244    REQUEST_SIZE_MATCH(xResourceReq);
245
246    result = dixLookupResourceByType((void **) &win, stuff->id, XRT_WINDOW,
247                                     client, DixDestroyAccess);
248    if (result != Success)
249        return result;
250
251    FOR_NSCREENS_BACKWARD(j) {
252        stuff->id = win->info[j].id;
253        result = (*SavedProcVector[X_DestroyWindow]) (client);
254        if (result != Success)
255            break;
256    }
257
258    /* Since ProcDestroyWindow is using FreeResource, it will free
259       our resource for us on the last pass through the loop above */
260
261    return result;
262}
263
264int
265PanoramiXDestroySubwindows(ClientPtr client)
266{
267    PanoramiXRes *win;
268    int result, j;
269
270    REQUEST(xResourceReq);
271
272    REQUEST_SIZE_MATCH(xResourceReq);
273
274    result = dixLookupResourceByType((void **) &win, stuff->id, XRT_WINDOW,
275                                     client, DixDestroyAccess);
276    if (result != Success)
277        return result;
278
279    FOR_NSCREENS_BACKWARD(j) {
280        stuff->id = win->info[j].id;
281        result = (*SavedProcVector[X_DestroySubwindows]) (client);
282        if (result != Success)
283            break;
284    }
285
286    /* DestroySubwindows is using FreeResource which will free
287       our resources for us on the last pass through the loop above */
288
289    return result;
290}
291
292int
293PanoramiXChangeSaveSet(ClientPtr client)
294{
295    PanoramiXRes *win;
296    int result, j;
297
298    REQUEST(xChangeSaveSetReq);
299
300    REQUEST_SIZE_MATCH(xChangeSaveSetReq);
301
302    result = dixLookupResourceByType((void **) &win, stuff->window,
303                                     XRT_WINDOW, client, DixReadAccess);
304    if (result != Success)
305        return result;
306
307    FOR_NSCREENS_BACKWARD(j) {
308        stuff->window = win->info[j].id;
309        result = (*SavedProcVector[X_ChangeSaveSet]) (client);
310        if (result != Success)
311            break;
312    }
313
314    return result;
315}
316
317int
318PanoramiXReparentWindow(ClientPtr client)
319{
320    PanoramiXRes *win, *parent;
321    int result, j;
322    int x, y;
323    Bool parentIsRoot;
324
325    REQUEST(xReparentWindowReq);
326
327    REQUEST_SIZE_MATCH(xReparentWindowReq);
328
329    result = dixLookupResourceByType((void **) &win, stuff->window,
330                                     XRT_WINDOW, client, DixWriteAccess);
331    if (result != Success)
332        return result;
333
334    result = dixLookupResourceByType((void **) &parent, stuff->parent,
335                                     XRT_WINDOW, client, DixWriteAccess);
336    if (result != Success)
337        return result;
338
339    x = stuff->x;
340    y = stuff->y;
341    parentIsRoot = (stuff->parent == screenInfo.screens[0]->root->drawable.id)
342        || (stuff->parent == screenInfo.screens[0]->screensaver.wid);
343    FOR_NSCREENS_BACKWARD(j) {
344        stuff->window = win->info[j].id;
345        stuff->parent = parent->info[j].id;
346        if (parentIsRoot) {
347            stuff->x = x - screenInfo.screens[j]->x;
348            stuff->y = y - screenInfo.screens[j]->y;
349        }
350        result = (*SavedProcVector[X_ReparentWindow]) (client);
351        if (result != Success)
352            break;
353    }
354
355    return result;
356}
357
358int
359PanoramiXMapWindow(ClientPtr client)
360{
361    PanoramiXRes *win;
362    int result, j;
363
364    REQUEST(xResourceReq);
365
366    REQUEST_SIZE_MATCH(xResourceReq);
367
368    result = dixLookupResourceByType((void **) &win, stuff->id,
369                                     XRT_WINDOW, client, DixReadAccess);
370    if (result != Success)
371        return result;
372
373    FOR_NSCREENS_FORWARD(j) {
374        stuff->id = win->info[j].id;
375        result = (*SavedProcVector[X_MapWindow]) (client);
376        if (result != Success)
377            break;
378    }
379
380    return result;
381}
382
383int
384PanoramiXMapSubwindows(ClientPtr client)
385{
386    PanoramiXRes *win;
387    int result, j;
388
389    REQUEST(xResourceReq);
390
391    REQUEST_SIZE_MATCH(xResourceReq);
392
393    result = dixLookupResourceByType((void **) &win, stuff->id,
394                                     XRT_WINDOW, client, DixReadAccess);
395    if (result != Success)
396        return result;
397
398    FOR_NSCREENS_FORWARD(j) {
399        stuff->id = win->info[j].id;
400        result = (*SavedProcVector[X_MapSubwindows]) (client);
401        if (result != Success)
402            break;
403    }
404
405    return result;
406}
407
408int
409PanoramiXUnmapWindow(ClientPtr client)
410{
411    PanoramiXRes *win;
412    int result, j;
413
414    REQUEST(xResourceReq);
415
416    REQUEST_SIZE_MATCH(xResourceReq);
417
418    result = dixLookupResourceByType((void **) &win, stuff->id,
419                                     XRT_WINDOW, client, DixReadAccess);
420    if (result != Success)
421        return result;
422
423    FOR_NSCREENS_FORWARD(j) {
424        stuff->id = win->info[j].id;
425        result = (*SavedProcVector[X_UnmapWindow]) (client);
426        if (result != Success)
427            break;
428    }
429
430    return result;
431}
432
433int
434PanoramiXUnmapSubwindows(ClientPtr client)
435{
436    PanoramiXRes *win;
437    int result, j;
438
439    REQUEST(xResourceReq);
440
441    REQUEST_SIZE_MATCH(xResourceReq);
442
443    result = dixLookupResourceByType((void **) &win, stuff->id,
444                                     XRT_WINDOW, client, DixReadAccess);
445    if (result != Success)
446        return result;
447
448    FOR_NSCREENS_FORWARD(j) {
449        stuff->id = win->info[j].id;
450        result = (*SavedProcVector[X_UnmapSubwindows]) (client);
451        if (result != Success)
452            break;
453    }
454
455    return result;
456}
457
458int
459PanoramiXConfigureWindow(ClientPtr client)
460{
461    PanoramiXRes *win;
462    PanoramiXRes *sib = NULL;
463    WindowPtr pWin;
464    int result, j, len, sib_offset = 0, x = 0, y = 0;
465    int x_offset = -1;
466    int y_offset = -1;
467
468    REQUEST(xConfigureWindowReq);
469
470    REQUEST_AT_LEAST_SIZE(xConfigureWindowReq);
471
472    len = client->req_len - bytes_to_int32(sizeof(xConfigureWindowReq));
473    if (Ones(stuff->mask) != len)
474        return BadLength;
475
476    /* because we need the parent */
477    result = dixLookupResourceByType((void **) &pWin, stuff->window,
478                                     RT_WINDOW, client, DixWriteAccess);
479    if (result != Success)
480        return result;
481
482    result = dixLookupResourceByType((void **) &win, stuff->window,
483                                     XRT_WINDOW, client, DixWriteAccess);
484    if (result != Success)
485        return result;
486
487    if ((Mask) stuff->mask & CWSibling) {
488        XID tmp;
489
490        sib_offset = Ones((Mask) stuff->mask & (CWSibling - 1));
491        if ((tmp = *((CARD32 *) &stuff[1] + sib_offset))) {
492            result = dixLookupResourceByType((void **) &sib, tmp, XRT_WINDOW,
493                                             client, DixReadAccess);
494            if (result != Success)
495                return result;
496        }
497    }
498
499    if (pWin->parent && ((pWin->parent == screenInfo.screens[0]->root) ||
500                         (pWin->parent->drawable.id ==
501                          screenInfo.screens[0]->screensaver.wid))) {
502        if ((Mask) stuff->mask & CWX) {
503            x_offset = 0;
504            x = *((CARD32 *) &stuff[1]);
505        }
506        if ((Mask) stuff->mask & CWY) {
507            y_offset = (x_offset == -1) ? 0 : 1;
508            y = *((CARD32 *) &stuff[1] + y_offset);
509        }
510    }
511
512    /* have to go forward or you get expose events before
513       ConfigureNotify events */
514    FOR_NSCREENS_FORWARD(j) {
515        stuff->window = win->info[j].id;
516        if (sib)
517            *((CARD32 *) &stuff[1] + sib_offset) = sib->info[j].id;
518        if (x_offset >= 0)
519            *((CARD32 *) &stuff[1] + x_offset) = x - screenInfo.screens[j]->x;
520        if (y_offset >= 0)
521            *((CARD32 *) &stuff[1] + y_offset) = y - screenInfo.screens[j]->y;
522        result = (*SavedProcVector[X_ConfigureWindow]) (client);
523        if (result != Success)
524            break;
525    }
526
527    return result;
528}
529
530int
531PanoramiXCirculateWindow(ClientPtr client)
532{
533    PanoramiXRes *win;
534    int result, j;
535
536    REQUEST(xCirculateWindowReq);
537
538    REQUEST_SIZE_MATCH(xCirculateWindowReq);
539
540    result = dixLookupResourceByType((void **) &win, stuff->window,
541                                     XRT_WINDOW, client, DixWriteAccess);
542    if (result != Success)
543        return result;
544
545    FOR_NSCREENS_FORWARD(j) {
546        stuff->window = win->info[j].id;
547        result = (*SavedProcVector[X_CirculateWindow]) (client);
548        if (result != Success)
549            break;
550    }
551
552    return result;
553}
554
555int
556PanoramiXGetGeometry(ClientPtr client)
557{
558    xGetGeometryReply rep;
559    DrawablePtr pDraw;
560    int rc;
561
562    REQUEST(xResourceReq);
563
564    REQUEST_SIZE_MATCH(xResourceReq);
565    rc = dixLookupDrawable(&pDraw, stuff->id, client, M_ANY, DixGetAttrAccess);
566    if (rc != Success)
567        return rc;
568
569    rep = (xGetGeometryReply) {
570        .type = X_Reply,
571        .sequenceNumber = client->sequence,
572        .length = 0,
573        .root = screenInfo.screens[0]->root->drawable.id,
574        .depth = pDraw->depth,
575        .width = pDraw->width,
576        .height = pDraw->height,
577        .x = 0,
578        .y = 0,
579        .borderWidth = 0
580    };
581
582    if (stuff->id == rep.root) {
583        xWindowRoot *root = (xWindowRoot *)
584            (ConnectionInfo + connBlockScreenStart);
585
586        rep.width = root->pixWidth;
587        rep.height = root->pixHeight;
588    }
589    else if (WindowDrawable(pDraw->type)) {
590        WindowPtr pWin = (WindowPtr) pDraw;
591
592        rep.x = pWin->origin.x - wBorderWidth(pWin);
593        rep.y = pWin->origin.y - wBorderWidth(pWin);
594        if ((pWin->parent == screenInfo.screens[0]->root) ||
595            (pWin->parent->drawable.id ==
596             screenInfo.screens[0]->screensaver.wid)) {
597            rep.x += screenInfo.screens[0]->x;
598            rep.y += screenInfo.screens[0]->y;
599        }
600        rep.borderWidth = pWin->borderWidth;
601    }
602
603    WriteReplyToClient(client, sizeof(xGetGeometryReply), &rep);
604    return Success;
605}
606
607int
608PanoramiXTranslateCoords(ClientPtr client)
609{
610    INT16 x, y;
611
612    REQUEST(xTranslateCoordsReq);
613    int rc;
614    WindowPtr pWin, pDst;
615    xTranslateCoordsReply rep;
616
617    REQUEST_SIZE_MATCH(xTranslateCoordsReq);
618    rc = dixLookupWindow(&pWin, stuff->srcWid, client, DixReadAccess);
619    if (rc != Success)
620        return rc;
621    rc = dixLookupWindow(&pDst, stuff->dstWid, client, DixReadAccess);
622    if (rc != Success)
623        return rc;
624    rep = (xTranslateCoordsReply) {
625        .type = X_Reply,
626        .sequenceNumber = client->sequence,
627        .length = 0,
628        .sameScreen = xTrue,
629        .child = None
630    };
631
632    if ((pWin == screenInfo.screens[0]->root) ||
633        (pWin->drawable.id == screenInfo.screens[0]->screensaver.wid)) {
634        x = stuff->srcX - screenInfo.screens[0]->x;
635        y = stuff->srcY - screenInfo.screens[0]->y;
636    }
637    else {
638        x = pWin->drawable.x + stuff->srcX;
639        y = pWin->drawable.y + stuff->srcY;
640    }
641    pWin = pDst->firstChild;
642    while (pWin) {
643        BoxRec box;
644
645        if ((pWin->mapped) &&
646            (x >= pWin->drawable.x - wBorderWidth(pWin)) &&
647            (x < pWin->drawable.x + (int) pWin->drawable.width +
648             wBorderWidth(pWin)) &&
649            (y >= pWin->drawable.y - wBorderWidth(pWin)) &&
650            (y < pWin->drawable.y + (int) pWin->drawable.height +
651             wBorderWidth(pWin))
652            /* When a window is shaped, a further check
653             * is made to see if the point is inside
654             * borderSize
655             */
656            && (!wBoundingShape(pWin) ||
657                RegionContainsPoint(wBoundingShape(pWin),
658                                    x - pWin->drawable.x,
659                                    y - pWin->drawable.y, &box))
660            ) {
661            rep.child = pWin->drawable.id;
662            pWin = (WindowPtr) NULL;
663        }
664        else
665            pWin = pWin->nextSib;
666    }
667    rep.dstX = x - pDst->drawable.x;
668    rep.dstY = y - pDst->drawable.y;
669    if ((pDst == screenInfo.screens[0]->root) ||
670        (pDst->drawable.id == screenInfo.screens[0]->screensaver.wid)) {
671        rep.dstX += screenInfo.screens[0]->x;
672        rep.dstY += screenInfo.screens[0]->y;
673    }
674
675    WriteReplyToClient(client, sizeof(xTranslateCoordsReply), &rep);
676    return Success;
677}
678
679int
680PanoramiXCreatePixmap(ClientPtr client)
681{
682    PanoramiXRes *refDraw, *newPix;
683    int result, j;
684
685    REQUEST(xCreatePixmapReq);
686
687    REQUEST_SIZE_MATCH(xCreatePixmapReq);
688    client->errorValue = stuff->pid;
689
690    result = dixLookupResourceByClass((void **) &refDraw, stuff->drawable,
691                                      XRC_DRAWABLE, client, DixReadAccess);
692    if (result != Success)
693        return (result == BadValue) ? BadDrawable : result;
694
695    if (!(newPix = malloc(sizeof(PanoramiXRes))))
696        return BadAlloc;
697
698    newPix->type = XRT_PIXMAP;
699    newPix->u.pix.shared = FALSE;
700    panoramix_setup_ids(newPix, client, stuff->pid);
701
702    FOR_NSCREENS_BACKWARD(j) {
703        stuff->pid = newPix->info[j].id;
704        stuff->drawable = refDraw->info[j].id;
705        result = (*SavedProcVector[X_CreatePixmap]) (client);
706        if (result != Success)
707            break;
708    }
709
710    if (result == Success)
711        AddResource(newPix->info[0].id, XRT_PIXMAP, newPix);
712    else
713        free(newPix);
714
715    return result;
716}
717
718int
719PanoramiXFreePixmap(ClientPtr client)
720{
721    PanoramiXRes *pix;
722    int result, j;
723
724    REQUEST(xResourceReq);
725
726    REQUEST_SIZE_MATCH(xResourceReq);
727
728    client->errorValue = stuff->id;
729
730    result = dixLookupResourceByType((void **) &pix, stuff->id, XRT_PIXMAP,
731                                     client, DixDestroyAccess);
732    if (result != Success)
733        return result;
734
735    FOR_NSCREENS_BACKWARD(j) {
736        stuff->id = pix->info[j].id;
737        result = (*SavedProcVector[X_FreePixmap]) (client);
738        if (result != Success)
739            break;
740    }
741
742    /* Since ProcFreePixmap is using FreeResource, it will free
743       our resource for us on the last pass through the loop above */
744
745    return result;
746}
747
748int
749PanoramiXCreateGC(ClientPtr client)
750{
751    PanoramiXRes *refDraw;
752    PanoramiXRes *newGC;
753    PanoramiXRes *stip = NULL;
754    PanoramiXRes *tile = NULL;
755    PanoramiXRes *clip = NULL;
756
757    REQUEST(xCreateGCReq);
758    int tile_offset = 0, stip_offset = 0, clip_offset = 0;
759    int result, len, j;
760    XID tmp;
761
762    REQUEST_AT_LEAST_SIZE(xCreateGCReq);
763
764    client->errorValue = stuff->gc;
765    len = client->req_len - bytes_to_int32(sizeof(xCreateGCReq));
766    if (Ones(stuff->mask) != len)
767        return BadLength;
768
769    result = dixLookupResourceByClass((void **) &refDraw, stuff->drawable,
770                                      XRC_DRAWABLE, client, DixReadAccess);
771    if (result != Success)
772        return (result == BadValue) ? BadDrawable : result;
773
774    if ((Mask) stuff->mask & GCTile) {
775        tile_offset = Ones((Mask) stuff->mask & (GCTile - 1));
776        if ((tmp = *((CARD32 *) &stuff[1] + tile_offset))) {
777            result = dixLookupResourceByType((void **) &tile, tmp, XRT_PIXMAP,
778                                             client, DixReadAccess);
779            if (result != Success)
780                return result;
781        }
782    }
783    if ((Mask) stuff->mask & GCStipple) {
784        stip_offset = Ones((Mask) stuff->mask & (GCStipple - 1));
785        if ((tmp = *((CARD32 *) &stuff[1] + stip_offset))) {
786            result = dixLookupResourceByType((void **) &stip, tmp, XRT_PIXMAP,
787                                             client, DixReadAccess);
788            if (result != Success)
789                return result;
790        }
791    }
792    if ((Mask) stuff->mask & GCClipMask) {
793        clip_offset = Ones((Mask) stuff->mask & (GCClipMask - 1));
794        if ((tmp = *((CARD32 *) &stuff[1] + clip_offset))) {
795            result = dixLookupResourceByType((void **) &clip, tmp, XRT_PIXMAP,
796                                             client, DixReadAccess);
797            if (result != Success)
798                return result;
799        }
800    }
801
802    if (!(newGC = malloc(sizeof(PanoramiXRes))))
803        return BadAlloc;
804
805    newGC->type = XRT_GC;
806    panoramix_setup_ids(newGC, client, stuff->gc);
807
808    FOR_NSCREENS_BACKWARD(j) {
809        stuff->gc = newGC->info[j].id;
810        stuff->drawable = refDraw->info[j].id;
811        if (tile)
812            *((CARD32 *) &stuff[1] + tile_offset) = tile->info[j].id;
813        if (stip)
814            *((CARD32 *) &stuff[1] + stip_offset) = stip->info[j].id;
815        if (clip)
816            *((CARD32 *) &stuff[1] + clip_offset) = clip->info[j].id;
817        result = (*SavedProcVector[X_CreateGC]) (client);
818        if (result != Success)
819            break;
820    }
821
822    if (result == Success)
823        AddResource(newGC->info[0].id, XRT_GC, newGC);
824    else
825        free(newGC);
826
827    return result;
828}
829
830int
831PanoramiXChangeGC(ClientPtr client)
832{
833    PanoramiXRes *gc;
834    PanoramiXRes *stip = NULL;
835    PanoramiXRes *tile = NULL;
836    PanoramiXRes *clip = NULL;
837
838    REQUEST(xChangeGCReq);
839    int tile_offset = 0, stip_offset = 0, clip_offset = 0;
840    int result, len, j;
841    XID tmp;
842
843    REQUEST_AT_LEAST_SIZE(xChangeGCReq);
844
845    len = client->req_len - bytes_to_int32(sizeof(xChangeGCReq));
846    if (Ones(stuff->mask) != len)
847        return BadLength;
848
849    result = dixLookupResourceByType((void **) &gc, stuff->gc, XRT_GC,
850                                     client, DixReadAccess);
851    if (result != Success)
852        return result;
853
854    if ((Mask) stuff->mask & GCTile) {
855        tile_offset = Ones((Mask) stuff->mask & (GCTile - 1));
856        if ((tmp = *((CARD32 *) &stuff[1] + tile_offset))) {
857            result = dixLookupResourceByType((void **) &tile, tmp, XRT_PIXMAP,
858                                             client, DixReadAccess);
859            if (result != Success)
860                return result;
861        }
862    }
863    if ((Mask) stuff->mask & GCStipple) {
864        stip_offset = Ones((Mask) stuff->mask & (GCStipple - 1));
865        if ((tmp = *((CARD32 *) &stuff[1] + stip_offset))) {
866            result = dixLookupResourceByType((void **) &stip, tmp, XRT_PIXMAP,
867                                             client, DixReadAccess);
868            if (result != Success)
869                return result;
870        }
871    }
872    if ((Mask) stuff->mask & GCClipMask) {
873        clip_offset = Ones((Mask) stuff->mask & (GCClipMask - 1));
874        if ((tmp = *((CARD32 *) &stuff[1] + clip_offset))) {
875            result = dixLookupResourceByType((void **) &clip, tmp, XRT_PIXMAP,
876                                             client, DixReadAccess);
877            if (result != Success)
878                return result;
879        }
880    }
881
882    FOR_NSCREENS_BACKWARD(j) {
883        stuff->gc = gc->info[j].id;
884        if (tile)
885            *((CARD32 *) &stuff[1] + tile_offset) = tile->info[j].id;
886        if (stip)
887            *((CARD32 *) &stuff[1] + stip_offset) = stip->info[j].id;
888        if (clip)
889            *((CARD32 *) &stuff[1] + clip_offset) = clip->info[j].id;
890        result = (*SavedProcVector[X_ChangeGC]) (client);
891        if (result != Success)
892            break;
893    }
894
895    return result;
896}
897
898int
899PanoramiXCopyGC(ClientPtr client)
900{
901    PanoramiXRes *srcGC, *dstGC;
902    int result, j;
903
904    REQUEST(xCopyGCReq);
905
906    REQUEST_SIZE_MATCH(xCopyGCReq);
907
908    result = dixLookupResourceByType((void **) &srcGC, stuff->srcGC, XRT_GC,
909                                     client, DixReadAccess);
910    if (result != Success)
911        return result;
912
913    result = dixLookupResourceByType((void **) &dstGC, stuff->dstGC, XRT_GC,
914                                     client, DixWriteAccess);
915    if (result != Success)
916        return result;
917
918    FOR_NSCREENS(j) {
919        stuff->srcGC = srcGC->info[j].id;
920        stuff->dstGC = dstGC->info[j].id;
921        result = (*SavedProcVector[X_CopyGC]) (client);
922        if (result != Success)
923            break;
924    }
925
926    return result;
927}
928
929int
930PanoramiXSetDashes(ClientPtr client)
931{
932    PanoramiXRes *gc;
933    int result, j;
934
935    REQUEST(xSetDashesReq);
936
937    REQUEST_FIXED_SIZE(xSetDashesReq, stuff->nDashes);
938
939    result = dixLookupResourceByType((void **) &gc, stuff->gc, XRT_GC,
940                                     client, DixWriteAccess);
941    if (result != Success)
942        return result;
943
944    FOR_NSCREENS_BACKWARD(j) {
945        stuff->gc = gc->info[j].id;
946        result = (*SavedProcVector[X_SetDashes]) (client);
947        if (result != Success)
948            break;
949    }
950
951    return result;
952}
953
954int
955PanoramiXSetClipRectangles(ClientPtr client)
956{
957    PanoramiXRes *gc;
958    int result, j;
959
960    REQUEST(xSetClipRectanglesReq);
961
962    REQUEST_AT_LEAST_SIZE(xSetClipRectanglesReq);
963
964    result = dixLookupResourceByType((void **) &gc, stuff->gc, XRT_GC,
965                                     client, DixWriteAccess);
966    if (result != Success)
967        return result;
968
969    FOR_NSCREENS_BACKWARD(j) {
970        stuff->gc = gc->info[j].id;
971        result = (*SavedProcVector[X_SetClipRectangles]) (client);
972        if (result != Success)
973            break;
974    }
975
976    return result;
977}
978
979int
980PanoramiXFreeGC(ClientPtr client)
981{
982    PanoramiXRes *gc;
983    int result, j;
984
985    REQUEST(xResourceReq);
986
987    REQUEST_SIZE_MATCH(xResourceReq);
988
989    result = dixLookupResourceByType((void **) &gc, stuff->id, XRT_GC,
990                                     client, DixDestroyAccess);
991    if (result != Success)
992        return result;
993
994    FOR_NSCREENS_BACKWARD(j) {
995        stuff->id = gc->info[j].id;
996        result = (*SavedProcVector[X_FreeGC]) (client);
997        if (result != Success)
998            break;
999    }
1000
1001    /* Since ProcFreeGC is using FreeResource, it will free
1002       our resource for us on the last pass through the loop above */
1003
1004    return result;
1005}
1006
1007int
1008PanoramiXClearToBackground(ClientPtr client)
1009{
1010    PanoramiXRes *win;
1011    int result, j, x, y;
1012    Bool isRoot;
1013
1014    REQUEST(xClearAreaReq);
1015
1016    REQUEST_SIZE_MATCH(xClearAreaReq);
1017
1018    result = dixLookupResourceByType((void **) &win, stuff->window,
1019                                     XRT_WINDOW, client, DixWriteAccess);
1020    if (result != Success)
1021        return result;
1022
1023    x = stuff->x;
1024    y = stuff->y;
1025    isRoot = win->u.win.root;
1026    FOR_NSCREENS_BACKWARD(j) {
1027        stuff->window = win->info[j].id;
1028        if (isRoot) {
1029            stuff->x = x - screenInfo.screens[j]->x;
1030            stuff->y = y - screenInfo.screens[j]->y;
1031        }
1032        result = (*SavedProcVector[X_ClearArea]) (client);
1033        if (result != Success)
1034            break;
1035    }
1036
1037    return result;
1038}
1039
1040/*
1041    For Window to Pixmap copies you're screwed since each screen's
1042    pixmap will look like what it sees on its screen.  Unless the
1043    screens overlap and the window lies on each, the two copies
1044    will be out of sync.  To remedy this we do a GetImage and PutImage
1045    in place of the copy.  Doing this as a single Image isn't quite
1046    correct since it will include the obscured areas but we will
1047    have to fix this later. (MArk).
1048*/
1049
1050int
1051PanoramiXCopyArea(ClientPtr client)
1052{
1053    int j, result, srcx, srcy, dstx, dsty, width, height;
1054    PanoramiXRes *gc, *src, *dst;
1055    Bool srcIsRoot = FALSE;
1056    Bool dstIsRoot = FALSE;
1057    Bool srcShared, dstShared;
1058
1059    REQUEST(xCopyAreaReq);
1060
1061    REQUEST_SIZE_MATCH(xCopyAreaReq);
1062
1063    result = dixLookupResourceByClass((void **) &src, stuff->srcDrawable,
1064                                      XRC_DRAWABLE, client, DixReadAccess);
1065    if (result != Success)
1066        return (result == BadValue) ? BadDrawable : result;
1067
1068    srcShared = IS_SHARED_PIXMAP(src);
1069
1070    result = dixLookupResourceByClass((void **) &dst, stuff->dstDrawable,
1071                                      XRC_DRAWABLE, client, DixWriteAccess);
1072    if (result != Success)
1073        return (result == BadValue) ? BadDrawable : result;
1074
1075    dstShared = IS_SHARED_PIXMAP(dst);
1076
1077    if (dstShared && srcShared)
1078        return (*SavedProcVector[X_CopyArea]) (client);
1079
1080    result = dixLookupResourceByType((void **) &gc, stuff->gc, XRT_GC,
1081                                     client, DixReadAccess);
1082    if (result != Success)
1083        return result;
1084
1085    if ((dst->type == XRT_WINDOW) && dst->u.win.root)
1086        dstIsRoot = TRUE;
1087    if ((src->type == XRT_WINDOW) && src->u.win.root)
1088        srcIsRoot = TRUE;
1089
1090    srcx = stuff->srcX;
1091    srcy = stuff->srcY;
1092    dstx = stuff->dstX;
1093    dsty = stuff->dstY;
1094    width = stuff->width;
1095    height = stuff->height;
1096    if ((dst->type == XRT_PIXMAP) && (src->type == XRT_WINDOW)) {
1097        DrawablePtr drawables[MAXSCREENS];
1098        DrawablePtr pDst;
1099        GCPtr pGC;
1100        char *data;
1101        int pitch, rc;
1102
1103        FOR_NSCREENS(j) {
1104            rc = dixLookupDrawable(drawables + j, src->info[j].id, client, 0,
1105                                   DixGetAttrAccess);
1106            if (rc != Success)
1107                return rc;
1108            drawables[j]->pScreen->SourceValidate(drawables[j], 0, 0,
1109                                                  drawables[j]->width,
1110                                                  drawables[j]->height,
1111                                                  IncludeInferiors);
1112        }
1113
1114        pitch = PixmapBytePad(width, drawables[0]->depth);
1115        if (!(data = calloc(height, pitch)))
1116            return BadAlloc;
1117
1118        XineramaGetImageData(drawables, srcx, srcy, width, height, ZPixmap, ~0,
1119                             data, pitch, srcIsRoot);
1120
1121        FOR_NSCREENS_BACKWARD(j) {
1122            stuff->gc = gc->info[j].id;
1123            VALIDATE_DRAWABLE_AND_GC(dst->info[j].id, pDst, DixWriteAccess);
1124            if (drawables[0]->depth != pDst->depth) {
1125                client->errorValue = stuff->dstDrawable;
1126                free(data);
1127                return BadMatch;
1128            }
1129
1130            (*pGC->ops->PutImage) (pDst, pGC, pDst->depth, dstx, dsty,
1131                                   width, height, 0, ZPixmap, data);
1132            if (dstShared)
1133                break;
1134        }
1135        free(data);
1136
1137        if (pGC->graphicsExposures) {
1138            RegionRec rgn;
1139            int dx, dy;
1140            BoxRec sourceBox;
1141
1142            dx = drawables[0]->x;
1143            dy = drawables[0]->y;
1144            if (srcIsRoot) {
1145                dx += screenInfo.screens[0]->x;
1146                dy += screenInfo.screens[0]->y;
1147            }
1148
1149            sourceBox.x1 = min(srcx + dx, 0);
1150            sourceBox.y1 = min(srcy + dy, 0);
1151            sourceBox.x2 = max(sourceBox.x1 + width, 32767);
1152            sourceBox.y2 = max(sourceBox.y1 + height, 32767);
1153
1154            RegionInit(&rgn, &sourceBox, 1);
1155
1156            /* subtract the (screen-space) clips of the source drawables */
1157            FOR_NSCREENS(j) {
1158                ScreenPtr screen = screenInfo.screens[j];
1159                RegionPtr sd;
1160
1161                if (pGC->subWindowMode == IncludeInferiors)
1162                    sd = NotClippedByChildren((WindowPtr)drawables[j]);
1163                else
1164                    sd = &((WindowPtr)drawables[j])->clipList;
1165
1166                if (srcIsRoot)
1167                    RegionTranslate(&rgn, -screen->x, -screen->y);
1168
1169                RegionSubtract(&rgn, &rgn, sd);
1170
1171                if (srcIsRoot)
1172                    RegionTranslate(&rgn, screen->x, screen->y);
1173
1174                if (pGC->subWindowMode == IncludeInferiors)
1175                    RegionDestroy(sd);
1176            }
1177
1178            /* -dx/-dy to get back to dest-relative, plus request offsets */
1179            RegionTranslate(&rgn, -dx + dstx, -dy + dsty);
1180
1181            /* intersect with gc clip; just one screen is fine because pixmap */
1182            RegionIntersect(&rgn, &rgn, pGC->pCompositeClip);
1183
1184            /* and expose */
1185            SendGraphicsExpose(client, &rgn, dst->info[0].id, X_CopyArea, 0);
1186            RegionUninit(&rgn);
1187        }
1188    }
1189    else {
1190        DrawablePtr pDst = NULL, pSrc = NULL;
1191        GCPtr pGC = NULL;
1192        RegionRec totalReg;
1193        int rc;
1194
1195        RegionNull(&totalReg);
1196        FOR_NSCREENS_BACKWARD(j) {
1197            RegionPtr pRgn;
1198
1199            stuff->dstDrawable = dst->info[j].id;
1200            stuff->srcDrawable = src->info[j].id;
1201            stuff->gc = gc->info[j].id;
1202            if (srcIsRoot) {
1203                stuff->srcX = srcx - screenInfo.screens[j]->x;
1204                stuff->srcY = srcy - screenInfo.screens[j]->y;
1205            }
1206            if (dstIsRoot) {
1207                stuff->dstX = dstx - screenInfo.screens[j]->x;
1208                stuff->dstY = dsty - screenInfo.screens[j]->y;
1209            }
1210
1211            VALIDATE_DRAWABLE_AND_GC(stuff->dstDrawable, pDst, DixWriteAccess);
1212
1213            if (stuff->dstDrawable != stuff->srcDrawable) {
1214                rc = dixLookupDrawable(&pSrc, stuff->srcDrawable, client, 0,
1215                                       DixReadAccess);
1216                if (rc != Success)
1217                    return rc;
1218
1219                if ((pDst->pScreen != pSrc->pScreen) ||
1220                    (pDst->depth != pSrc->depth)) {
1221                    client->errorValue = stuff->dstDrawable;
1222                    return BadMatch;
1223                }
1224            }
1225            else
1226                pSrc = pDst;
1227
1228            pRgn = (*pGC->ops->CopyArea) (pSrc, pDst, pGC,
1229                                          stuff->srcX, stuff->srcY,
1230                                          stuff->width, stuff->height,
1231                                          stuff->dstX, stuff->dstY);
1232            if (pGC->graphicsExposures && pRgn) {
1233                if (srcIsRoot) {
1234                    RegionTranslate(pRgn,
1235                                    screenInfo.screens[j]->x,
1236                                    screenInfo.screens[j]->y);
1237                }
1238                RegionAppend(&totalReg, pRgn);
1239                RegionDestroy(pRgn);
1240            }
1241
1242            if (dstShared)
1243                break;
1244        }
1245
1246        if (pGC->graphicsExposures) {
1247            Bool overlap;
1248
1249            RegionValidate(&totalReg, &overlap);
1250            SendGraphicsExpose(client, &totalReg, stuff->dstDrawable,
1251                               X_CopyArea, 0);
1252            RegionUninit(&totalReg);
1253        }
1254    }
1255
1256    return Success;
1257}
1258
1259int
1260PanoramiXCopyPlane(ClientPtr client)
1261{
1262    int j, srcx, srcy, dstx, dsty, rc;
1263    PanoramiXRes *gc, *src, *dst;
1264    Bool srcIsRoot = FALSE;
1265    Bool dstIsRoot = FALSE;
1266    Bool srcShared, dstShared;
1267    DrawablePtr psrcDraw, pdstDraw = NULL;
1268    GCPtr pGC = NULL;
1269    RegionRec totalReg;
1270
1271    REQUEST(xCopyPlaneReq);
1272
1273    REQUEST_SIZE_MATCH(xCopyPlaneReq);
1274
1275    rc = dixLookupResourceByClass((void **) &src, stuff->srcDrawable,
1276                                  XRC_DRAWABLE, client, DixReadAccess);
1277    if (rc != Success)
1278        return (rc == BadValue) ? BadDrawable : rc;
1279
1280    srcShared = IS_SHARED_PIXMAP(src);
1281
1282    rc = dixLookupResourceByClass((void **) &dst, stuff->dstDrawable,
1283                                  XRC_DRAWABLE, client, DixWriteAccess);
1284    if (rc != Success)
1285        return (rc == BadValue) ? BadDrawable : rc;
1286
1287    dstShared = IS_SHARED_PIXMAP(dst);
1288
1289    if (dstShared && srcShared)
1290        return (*SavedProcVector[X_CopyPlane]) (client);
1291
1292    rc = dixLookupResourceByType((void **) &gc, stuff->gc, XRT_GC,
1293                                 client, DixReadAccess);
1294    if (rc != Success)
1295        return rc;
1296
1297    if ((dst->type == XRT_WINDOW) && dst->u.win.root)
1298        dstIsRoot = TRUE;
1299    if ((src->type == XRT_WINDOW) && src->u.win.root)
1300        srcIsRoot = TRUE;
1301
1302    srcx = stuff->srcX;
1303    srcy = stuff->srcY;
1304    dstx = stuff->dstX;
1305    dsty = stuff->dstY;
1306
1307    RegionNull(&totalReg);
1308    FOR_NSCREENS_BACKWARD(j) {
1309        RegionPtr pRgn;
1310
1311        stuff->dstDrawable = dst->info[j].id;
1312        stuff->srcDrawable = src->info[j].id;
1313        stuff->gc = gc->info[j].id;
1314        if (srcIsRoot) {
1315            stuff->srcX = srcx - screenInfo.screens[j]->x;
1316            stuff->srcY = srcy - screenInfo.screens[j]->y;
1317        }
1318        if (dstIsRoot) {
1319            stuff->dstX = dstx - screenInfo.screens[j]->x;
1320            stuff->dstY = dsty - screenInfo.screens[j]->y;
1321        }
1322
1323        VALIDATE_DRAWABLE_AND_GC(stuff->dstDrawable, pdstDraw, DixWriteAccess);
1324        if (stuff->dstDrawable != stuff->srcDrawable) {
1325            rc = dixLookupDrawable(&psrcDraw, stuff->srcDrawable, client, 0,
1326                                   DixReadAccess);
1327            if (rc != Success)
1328                return rc;
1329
1330            if (pdstDraw->pScreen != psrcDraw->pScreen) {
1331                client->errorValue = stuff->dstDrawable;
1332                return BadMatch;
1333            }
1334        }
1335        else
1336            psrcDraw = pdstDraw;
1337
1338        if (stuff->bitPlane == 0 || (stuff->bitPlane & (stuff->bitPlane - 1)) ||
1339            (stuff->bitPlane > (1L << (psrcDraw->depth - 1)))) {
1340            client->errorValue = stuff->bitPlane;
1341            return BadValue;
1342        }
1343
1344        pRgn = (*pGC->ops->CopyPlane) (psrcDraw, pdstDraw, pGC,
1345                                       stuff->srcX, stuff->srcY,
1346                                       stuff->width, stuff->height,
1347                                       stuff->dstX, stuff->dstY,
1348                                       stuff->bitPlane);
1349        if (pGC->graphicsExposures && pRgn) {
1350            RegionAppend(&totalReg, pRgn);
1351            RegionDestroy(pRgn);
1352        }
1353
1354        if (dstShared)
1355            break;
1356    }
1357
1358    if (pGC->graphicsExposures) {
1359        Bool overlap;
1360
1361        RegionValidate(&totalReg, &overlap);
1362        SendGraphicsExpose(client, &totalReg, stuff->dstDrawable,
1363                           X_CopyPlane, 0);
1364        RegionUninit(&totalReg);
1365    }
1366
1367    return Success;
1368}
1369
1370int
1371PanoramiXPolyPoint(ClientPtr client)
1372{
1373    PanoramiXRes *gc, *draw;
1374    int result, npoint, j;
1375    xPoint *origPts;
1376    Bool isRoot;
1377
1378    REQUEST(xPolyPointReq);
1379
1380    REQUEST_AT_LEAST_SIZE(xPolyPointReq);
1381
1382    result = dixLookupResourceByClass((void **) &draw, stuff->drawable,
1383                                      XRC_DRAWABLE, client, DixWriteAccess);
1384    if (result != Success)
1385        return (result == BadValue) ? BadDrawable : result;
1386
1387    if (IS_SHARED_PIXMAP(draw))
1388        return (*SavedProcVector[X_PolyPoint]) (client);
1389
1390    result = dixLookupResourceByType((void **) &gc, stuff->gc, XRT_GC,
1391                                     client, DixReadAccess);
1392    if (result != Success)
1393        return result;
1394
1395    isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root;
1396    npoint = bytes_to_int32((client->req_len << 2) - sizeof(xPolyPointReq));
1397    if (npoint > 0) {
1398        origPts = xallocarray(npoint, sizeof(xPoint));
1399        memcpy((char *) origPts, (char *) &stuff[1], npoint * sizeof(xPoint));
1400        FOR_NSCREENS_FORWARD(j) {
1401
1402            if (j)
1403                memcpy(&stuff[1], origPts, npoint * sizeof(xPoint));
1404
1405            if (isRoot) {
1406                int x_off = screenInfo.screens[j]->x;
1407                int y_off = screenInfo.screens[j]->y;
1408
1409                if (x_off || y_off) {
1410                    xPoint *pnts = (xPoint *) &stuff[1];
1411                    int i =
1412                        (stuff->coordMode == CoordModePrevious) ? 1 : npoint;
1413
1414                    while (i--) {
1415                        pnts->x -= x_off;
1416                        pnts->y -= y_off;
1417                        pnts++;
1418                    }
1419                }
1420            }
1421
1422            stuff->drawable = draw->info[j].id;
1423            stuff->gc = gc->info[j].id;
1424            result = (*SavedProcVector[X_PolyPoint]) (client);
1425            if (result != Success)
1426                break;
1427        }
1428        free(origPts);
1429        return result;
1430    }
1431    else
1432        return Success;
1433}
1434
1435int
1436PanoramiXPolyLine(ClientPtr client)
1437{
1438    PanoramiXRes *gc, *draw;
1439    int result, npoint, j;
1440    xPoint *origPts;
1441    Bool isRoot;
1442
1443    REQUEST(xPolyLineReq);
1444
1445    REQUEST_AT_LEAST_SIZE(xPolyLineReq);
1446
1447    result = dixLookupResourceByClass((void **) &draw, stuff->drawable,
1448                                      XRC_DRAWABLE, client, DixWriteAccess);
1449    if (result != Success)
1450        return (result == BadValue) ? BadDrawable : result;
1451
1452    if (IS_SHARED_PIXMAP(draw))
1453        return (*SavedProcVector[X_PolyLine]) (client);
1454
1455    result = dixLookupResourceByType((void **) &gc, stuff->gc, XRT_GC,
1456                                     client, DixReadAccess);
1457    if (result != Success)
1458        return result;
1459
1460    isRoot = IS_ROOT_DRAWABLE(draw);
1461    npoint = bytes_to_int32((client->req_len << 2) - sizeof(xPolyLineReq));
1462    if (npoint > 0) {
1463        origPts = xallocarray(npoint, sizeof(xPoint));
1464        memcpy((char *) origPts, (char *) &stuff[1], npoint * sizeof(xPoint));
1465        FOR_NSCREENS_FORWARD(j) {
1466
1467            if (j)
1468                memcpy(&stuff[1], origPts, npoint * sizeof(xPoint));
1469
1470            if (isRoot) {
1471                int x_off = screenInfo.screens[j]->x;
1472                int y_off = screenInfo.screens[j]->y;
1473
1474                if (x_off || y_off) {
1475                    xPoint *pnts = (xPoint *) &stuff[1];
1476                    int i =
1477                        (stuff->coordMode == CoordModePrevious) ? 1 : npoint;
1478
1479                    while (i--) {
1480                        pnts->x -= x_off;
1481                        pnts->y -= y_off;
1482                        pnts++;
1483                    }
1484                }
1485            }
1486
1487            stuff->drawable = draw->info[j].id;
1488            stuff->gc = gc->info[j].id;
1489            result = (*SavedProcVector[X_PolyLine]) (client);
1490            if (result != Success)
1491                break;
1492        }
1493        free(origPts);
1494        return result;
1495    }
1496    else
1497        return Success;
1498}
1499
1500int
1501PanoramiXPolySegment(ClientPtr client)
1502{
1503    int result, nsegs, i, j;
1504    PanoramiXRes *gc, *draw;
1505    xSegment *origSegs;
1506    Bool isRoot;
1507
1508    REQUEST(xPolySegmentReq);
1509
1510    REQUEST_AT_LEAST_SIZE(xPolySegmentReq);
1511
1512    result = dixLookupResourceByClass((void **) &draw, stuff->drawable,
1513                                      XRC_DRAWABLE, client, DixWriteAccess);
1514    if (result != Success)
1515        return (result == BadValue) ? BadDrawable : result;
1516
1517    if (IS_SHARED_PIXMAP(draw))
1518        return (*SavedProcVector[X_PolySegment]) (client);
1519
1520    result = dixLookupResourceByType((void **) &gc, stuff->gc, XRT_GC,
1521                                     client, DixReadAccess);
1522    if (result != Success)
1523        return result;
1524
1525    isRoot = IS_ROOT_DRAWABLE(draw);
1526
1527    nsegs = (client->req_len << 2) - sizeof(xPolySegmentReq);
1528    if (nsegs & 4)
1529        return BadLength;
1530    nsegs >>= 3;
1531    if (nsegs > 0) {
1532        origSegs = xallocarray(nsegs, sizeof(xSegment));
1533        memcpy((char *) origSegs, (char *) &stuff[1], nsegs * sizeof(xSegment));
1534        FOR_NSCREENS_FORWARD(j) {
1535
1536            if (j)
1537                memcpy(&stuff[1], origSegs, nsegs * sizeof(xSegment));
1538
1539            if (isRoot) {
1540                int x_off = screenInfo.screens[j]->x;
1541                int y_off = screenInfo.screens[j]->y;
1542
1543                if (x_off || y_off) {
1544                    xSegment *segs = (xSegment *) &stuff[1];
1545
1546                    for (i = nsegs; i--; segs++) {
1547                        segs->x1 -= x_off;
1548                        segs->x2 -= x_off;
1549                        segs->y1 -= y_off;
1550                        segs->y2 -= y_off;
1551                    }
1552                }
1553            }
1554
1555            stuff->drawable = draw->info[j].id;
1556            stuff->gc = gc->info[j].id;
1557            result = (*SavedProcVector[X_PolySegment]) (client);
1558            if (result != Success)
1559                break;
1560        }
1561        free(origSegs);
1562        return result;
1563    }
1564    else
1565        return Success;
1566}
1567
1568int
1569PanoramiXPolyRectangle(ClientPtr client)
1570{
1571    int result, nrects, i, j;
1572    PanoramiXRes *gc, *draw;
1573    Bool isRoot;
1574    xRectangle *origRecs;
1575
1576    REQUEST(xPolyRectangleReq);
1577
1578    REQUEST_AT_LEAST_SIZE(xPolyRectangleReq);
1579
1580    result = dixLookupResourceByClass((void **) &draw, stuff->drawable,
1581                                      XRC_DRAWABLE, client, DixWriteAccess);
1582    if (result != Success)
1583        return (result == BadValue) ? BadDrawable : result;
1584
1585    if (IS_SHARED_PIXMAP(draw))
1586        return (*SavedProcVector[X_PolyRectangle]) (client);
1587
1588    result = dixLookupResourceByType((void **) &gc, stuff->gc, XRT_GC,
1589                                     client, DixReadAccess);
1590    if (result != Success)
1591        return result;
1592
1593    isRoot = IS_ROOT_DRAWABLE(draw);
1594
1595    nrects = (client->req_len << 2) - sizeof(xPolyRectangleReq);
1596    if (nrects & 4)
1597        return BadLength;
1598    nrects >>= 3;
1599    if (nrects > 0) {
1600        origRecs = xallocarray(nrects, sizeof(xRectangle));
1601        memcpy((char *) origRecs, (char *) &stuff[1],
1602               nrects * sizeof(xRectangle));
1603        FOR_NSCREENS_FORWARD(j) {
1604
1605            if (j)
1606                memcpy(&stuff[1], origRecs, nrects * sizeof(xRectangle));
1607
1608            if (isRoot) {
1609                int x_off = screenInfo.screens[j]->x;
1610                int y_off = screenInfo.screens[j]->y;
1611
1612                if (x_off || y_off) {
1613                    xRectangle *rects = (xRectangle *) &stuff[1];
1614
1615                    for (i = nrects; i--; rects++) {
1616                        rects->x -= x_off;
1617                        rects->y -= y_off;
1618                    }
1619                }
1620            }
1621
1622            stuff->drawable = draw->info[j].id;
1623            stuff->gc = gc->info[j].id;
1624            result = (*SavedProcVector[X_PolyRectangle]) (client);
1625            if (result != Success)
1626                break;
1627        }
1628        free(origRecs);
1629        return result;
1630    }
1631    else
1632        return Success;
1633}
1634
1635int
1636PanoramiXPolyArc(ClientPtr client)
1637{
1638    int result, narcs, i, j;
1639    PanoramiXRes *gc, *draw;
1640    Bool isRoot;
1641    xArc *origArcs;
1642
1643    REQUEST(xPolyArcReq);
1644
1645    REQUEST_AT_LEAST_SIZE(xPolyArcReq);
1646
1647    result = dixLookupResourceByClass((void **) &draw, stuff->drawable,
1648                                      XRC_DRAWABLE, client, DixWriteAccess);
1649    if (result != Success)
1650        return (result == BadValue) ? BadDrawable : result;
1651
1652    if (IS_SHARED_PIXMAP(draw))
1653        return (*SavedProcVector[X_PolyArc]) (client);
1654
1655    result = dixLookupResourceByType((void **) &gc, stuff->gc, XRT_GC,
1656                                     client, DixReadAccess);
1657    if (result != Success)
1658        return result;
1659
1660    isRoot = IS_ROOT_DRAWABLE(draw);
1661
1662    narcs = (client->req_len << 2) - sizeof(xPolyArcReq);
1663    if (narcs % sizeof(xArc))
1664        return BadLength;
1665    narcs /= sizeof(xArc);
1666    if (narcs > 0) {
1667        origArcs = xallocarray(narcs, sizeof(xArc));
1668        memcpy((char *) origArcs, (char *) &stuff[1], narcs * sizeof(xArc));
1669        FOR_NSCREENS_FORWARD(j) {
1670
1671            if (j)
1672                memcpy(&stuff[1], origArcs, narcs * sizeof(xArc));
1673
1674            if (isRoot) {
1675                int x_off = screenInfo.screens[j]->x;
1676                int y_off = screenInfo.screens[j]->y;
1677
1678                if (x_off || y_off) {
1679                    xArc *arcs = (xArc *) &stuff[1];
1680
1681                    for (i = narcs; i--; arcs++) {
1682                        arcs->x -= x_off;
1683                        arcs->y -= y_off;
1684                    }
1685                }
1686            }
1687            stuff->drawable = draw->info[j].id;
1688            stuff->gc = gc->info[j].id;
1689            result = (*SavedProcVector[X_PolyArc]) (client);
1690            if (result != Success)
1691                break;
1692        }
1693        free(origArcs);
1694        return result;
1695    }
1696    else
1697        return Success;
1698}
1699
1700int
1701PanoramiXFillPoly(ClientPtr client)
1702{
1703    int result, count, j;
1704    PanoramiXRes *gc, *draw;
1705    Bool isRoot;
1706    DDXPointPtr locPts;
1707
1708    REQUEST(xFillPolyReq);
1709
1710    REQUEST_AT_LEAST_SIZE(xFillPolyReq);
1711
1712    result = dixLookupResourceByClass((void **) &draw, stuff->drawable,
1713                                      XRC_DRAWABLE, client, DixWriteAccess);
1714    if (result != Success)
1715        return (result == BadValue) ? BadDrawable : result;
1716
1717    if (IS_SHARED_PIXMAP(draw))
1718        return (*SavedProcVector[X_FillPoly]) (client);
1719
1720    result = dixLookupResourceByType((void **) &gc, stuff->gc, XRT_GC,
1721                                     client, DixReadAccess);
1722    if (result != Success)
1723        return result;
1724
1725    isRoot = IS_ROOT_DRAWABLE(draw);
1726
1727    count = bytes_to_int32((client->req_len << 2) - sizeof(xFillPolyReq));
1728    if (count > 0) {
1729        locPts = xallocarray(count, sizeof(DDXPointRec));
1730        memcpy((char *) locPts, (char *) &stuff[1],
1731               count * sizeof(DDXPointRec));
1732        FOR_NSCREENS_FORWARD(j) {
1733
1734            if (j)
1735                memcpy(&stuff[1], locPts, count * sizeof(DDXPointRec));
1736
1737            if (isRoot) {
1738                int x_off = screenInfo.screens[j]->x;
1739                int y_off = screenInfo.screens[j]->y;
1740
1741                if (x_off || y_off) {
1742                    DDXPointPtr pnts = (DDXPointPtr) &stuff[1];
1743                    int i = (stuff->coordMode == CoordModePrevious) ? 1 : count;
1744
1745                    while (i--) {
1746                        pnts->x -= x_off;
1747                        pnts->y -= y_off;
1748                        pnts++;
1749                    }
1750                }
1751            }
1752
1753            stuff->drawable = draw->info[j].id;
1754            stuff->gc = gc->info[j].id;
1755            result = (*SavedProcVector[X_FillPoly]) (client);
1756            if (result != Success)
1757                break;
1758        }
1759        free(locPts);
1760        return result;
1761    }
1762    else
1763        return Success;
1764}
1765
1766int
1767PanoramiXPolyFillRectangle(ClientPtr client)
1768{
1769    int result, things, i, j;
1770    PanoramiXRes *gc, *draw;
1771    Bool isRoot;
1772    xRectangle *origRects;
1773
1774    REQUEST(xPolyFillRectangleReq);
1775
1776    REQUEST_AT_LEAST_SIZE(xPolyFillRectangleReq);
1777
1778    result = dixLookupResourceByClass((void **) &draw, stuff->drawable,
1779                                      XRC_DRAWABLE, client, DixWriteAccess);
1780    if (result != Success)
1781        return (result == BadValue) ? BadDrawable : result;
1782
1783    if (IS_SHARED_PIXMAP(draw))
1784        return (*SavedProcVector[X_PolyFillRectangle]) (client);
1785
1786    result = dixLookupResourceByType((void **) &gc, stuff->gc, XRT_GC,
1787                                     client, DixReadAccess);
1788    if (result != Success)
1789        return result;
1790
1791    isRoot = IS_ROOT_DRAWABLE(draw);
1792
1793    things = (client->req_len << 2) - sizeof(xPolyFillRectangleReq);
1794    if (things & 4)
1795        return BadLength;
1796    things >>= 3;
1797    if (things > 0) {
1798        origRects = xallocarray(things, sizeof(xRectangle));
1799        memcpy((char *) origRects, (char *) &stuff[1],
1800               things * sizeof(xRectangle));
1801        FOR_NSCREENS_FORWARD(j) {
1802
1803            if (j)
1804                memcpy(&stuff[1], origRects, things * sizeof(xRectangle));
1805
1806            if (isRoot) {
1807                int x_off = screenInfo.screens[j]->x;
1808                int y_off = screenInfo.screens[j]->y;
1809
1810                if (x_off || y_off) {
1811                    xRectangle *rects = (xRectangle *) &stuff[1];
1812
1813                    for (i = things; i--; rects++) {
1814                        rects->x -= x_off;
1815                        rects->y -= y_off;
1816                    }
1817                }
1818            }
1819
1820            stuff->drawable = draw->info[j].id;
1821            stuff->gc = gc->info[j].id;
1822            result = (*SavedProcVector[X_PolyFillRectangle]) (client);
1823            if (result != Success)
1824                break;
1825        }
1826        free(origRects);
1827        return result;
1828    }
1829    else
1830        return Success;
1831}
1832
1833int
1834PanoramiXPolyFillArc(ClientPtr client)
1835{
1836    PanoramiXRes *gc, *draw;
1837    Bool isRoot;
1838    int result, narcs, i, j;
1839    xArc *origArcs;
1840
1841    REQUEST(xPolyFillArcReq);
1842
1843    REQUEST_AT_LEAST_SIZE(xPolyFillArcReq);
1844
1845    result = dixLookupResourceByClass((void **) &draw, stuff->drawable,
1846                                      XRC_DRAWABLE, client, DixWriteAccess);
1847    if (result != Success)
1848        return (result == BadValue) ? BadDrawable : result;
1849
1850    if (IS_SHARED_PIXMAP(draw))
1851        return (*SavedProcVector[X_PolyFillArc]) (client);
1852
1853    result = dixLookupResourceByType((void **) &gc, stuff->gc, XRT_GC,
1854                                     client, DixReadAccess);
1855    if (result != Success)
1856        return result;
1857
1858    isRoot = IS_ROOT_DRAWABLE(draw);
1859
1860    narcs = (client->req_len << 2) - sizeof(xPolyFillArcReq);
1861    if (narcs % sizeof(xArc))
1862        return BadLength;
1863    narcs /= sizeof(xArc);
1864    if (narcs > 0) {
1865        origArcs = xallocarray(narcs, sizeof(xArc));
1866        memcpy((char *) origArcs, (char *) &stuff[1], narcs * sizeof(xArc));
1867        FOR_NSCREENS_FORWARD(j) {
1868
1869            if (j)
1870                memcpy(&stuff[1], origArcs, narcs * sizeof(xArc));
1871
1872            if (isRoot) {
1873                int x_off = screenInfo.screens[j]->x;
1874                int y_off = screenInfo.screens[j]->y;
1875
1876                if (x_off || y_off) {
1877                    xArc *arcs = (xArc *) &stuff[1];
1878
1879                    for (i = narcs; i--; arcs++) {
1880                        arcs->x -= x_off;
1881                        arcs->y -= y_off;
1882                    }
1883                }
1884            }
1885
1886            stuff->drawable = draw->info[j].id;
1887            stuff->gc = gc->info[j].id;
1888            result = (*SavedProcVector[X_PolyFillArc]) (client);
1889            if (result != Success)
1890                break;
1891        }
1892        free(origArcs);
1893        return result;
1894    }
1895    else
1896        return Success;
1897}
1898
1899int
1900PanoramiXPutImage(ClientPtr client)
1901{
1902    PanoramiXRes *gc, *draw;
1903    Bool isRoot;
1904    int j, result, orig_x, orig_y;
1905
1906    REQUEST(xPutImageReq);
1907
1908    REQUEST_AT_LEAST_SIZE(xPutImageReq);
1909
1910    result = dixLookupResourceByClass((void **) &draw, stuff->drawable,
1911                                      XRC_DRAWABLE, client, DixWriteAccess);
1912    if (result != Success)
1913        return (result == BadValue) ? BadDrawable : result;
1914
1915    if (IS_SHARED_PIXMAP(draw))
1916        return (*SavedProcVector[X_PutImage]) (client);
1917
1918    result = dixLookupResourceByType((void **) &gc, stuff->gc, XRT_GC,
1919                                     client, DixReadAccess);
1920    if (result != Success)
1921        return result;
1922
1923    isRoot = IS_ROOT_DRAWABLE(draw);
1924
1925    orig_x = stuff->dstX;
1926    orig_y = stuff->dstY;
1927    FOR_NSCREENS_BACKWARD(j) {
1928        if (isRoot) {
1929            stuff->dstX = orig_x - screenInfo.screens[j]->x;
1930            stuff->dstY = orig_y - screenInfo.screens[j]->y;
1931        }
1932        stuff->drawable = draw->info[j].id;
1933        stuff->gc = gc->info[j].id;
1934        result = (*SavedProcVector[X_PutImage]) (client);
1935        if (result != Success)
1936            break;
1937    }
1938    return result;
1939}
1940
1941int
1942PanoramiXGetImage(ClientPtr client)
1943{
1944    DrawablePtr drawables[MAXSCREENS];
1945    DrawablePtr pDraw;
1946    PanoramiXRes *draw;
1947    xGetImageReply xgi;
1948    Bool isRoot;
1949    char *pBuf;
1950    int i, x, y, w, h, format, rc;
1951    Mask plane = 0, planemask;
1952    int linesDone, nlines, linesPerBuf;
1953    long widthBytesLine, length;
1954
1955    REQUEST(xGetImageReq);
1956
1957    REQUEST_SIZE_MATCH(xGetImageReq);
1958
1959    if ((stuff->format != XYPixmap) && (stuff->format != ZPixmap)) {
1960        client->errorValue = stuff->format;
1961        return BadValue;
1962    }
1963
1964    rc = dixLookupResourceByClass((void **) &draw, stuff->drawable,
1965                                  XRC_DRAWABLE, client, DixReadAccess);
1966    if (rc != Success)
1967        return (rc == BadValue) ? BadDrawable : rc;
1968
1969    if (draw->type == XRT_PIXMAP)
1970        return (*SavedProcVector[X_GetImage]) (client);
1971
1972    rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0, DixReadAccess);
1973    if (rc != Success)
1974        return rc;
1975
1976    if (!((WindowPtr) pDraw)->realized)
1977        return BadMatch;
1978
1979    x = stuff->x;
1980    y = stuff->y;
1981    w = stuff->width;
1982    h = stuff->height;
1983    format = stuff->format;
1984    planemask = stuff->planeMask;
1985
1986    isRoot = IS_ROOT_DRAWABLE(draw);
1987
1988    if (isRoot) {
1989        /* check for being onscreen */
1990        if (x < 0 || x + w > PanoramiXPixWidth ||
1991            y < 0 || y + h > PanoramiXPixHeight)
1992            return BadMatch;
1993    }
1994    else {
1995        /* check for being onscreen and inside of border */
1996        if (screenInfo.screens[0]->x + pDraw->x + x < 0 ||
1997            screenInfo.screens[0]->x + pDraw->x + x + w > PanoramiXPixWidth ||
1998            screenInfo.screens[0]->y + pDraw->y + y < 0 ||
1999            screenInfo.screens[0]->y + pDraw->y + y + h > PanoramiXPixHeight ||
2000            x < -wBorderWidth((WindowPtr) pDraw) ||
2001            x + w > wBorderWidth((WindowPtr) pDraw) + (int) pDraw->width ||
2002            y < -wBorderWidth((WindowPtr) pDraw) ||
2003            y + h > wBorderWidth((WindowPtr) pDraw) + (int) pDraw->height)
2004            return BadMatch;
2005    }
2006
2007    drawables[0] = pDraw;
2008    FOR_NSCREENS_FORWARD_SKIP(i) {
2009        rc = dixLookupDrawable(drawables + i, draw->info[i].id, client, 0,
2010                               DixGetAttrAccess);
2011        if (rc != Success)
2012            return rc;
2013    }
2014    FOR_NSCREENS_FORWARD(i) {
2015        drawables[i]->pScreen->SourceValidate(drawables[i], 0, 0,
2016                                              drawables[i]->width,
2017                                              drawables[i]->height,
2018                                              IncludeInferiors);
2019    }
2020
2021    xgi = (xGetImageReply) {
2022        .type = X_Reply,
2023        .sequenceNumber = client->sequence,
2024        .visual = wVisual(((WindowPtr) pDraw)),
2025        .depth = pDraw->depth
2026    };
2027    if (format == ZPixmap) {
2028        widthBytesLine = PixmapBytePad(w, pDraw->depth);
2029        length = widthBytesLine * h;
2030
2031    }
2032    else {
2033        widthBytesLine = BitmapBytePad(w);
2034        plane = ((Mask) 1) << (pDraw->depth - 1);
2035        /* only planes asked for */
2036        length = widthBytesLine * h * Ones(planemask & (plane | (plane - 1)));
2037
2038    }
2039
2040    xgi.length = bytes_to_int32(length);
2041
2042    if (widthBytesLine == 0 || h == 0)
2043        linesPerBuf = 0;
2044    else if (widthBytesLine >= XINERAMA_IMAGE_BUFSIZE)
2045        linesPerBuf = 1;
2046    else {
2047        linesPerBuf = XINERAMA_IMAGE_BUFSIZE / widthBytesLine;
2048        if (linesPerBuf > h)
2049            linesPerBuf = h;
2050    }
2051    if (!(pBuf = xallocarray(linesPerBuf, widthBytesLine)))
2052        return BadAlloc;
2053
2054    WriteReplyToClient(client, sizeof(xGetImageReply), &xgi);
2055
2056    if (linesPerBuf == 0) {
2057        /* nothing to do */
2058    }
2059    else if (format == ZPixmap) {
2060        linesDone = 0;
2061        while (h - linesDone > 0) {
2062            nlines = min(linesPerBuf, h - linesDone);
2063
2064            if (pDraw->depth == 1)
2065                memset(pBuf, 0, nlines * widthBytesLine);
2066
2067            XineramaGetImageData(drawables, x, y + linesDone, w, nlines,
2068                                 format, planemask, pBuf, widthBytesLine,
2069                                 isRoot);
2070
2071            WriteToClient(client, (int) (nlines * widthBytesLine), pBuf);
2072            linesDone += nlines;
2073        }
2074    }
2075    else {                      /* XYPixmap */
2076        for (; plane; plane >>= 1) {
2077            if (planemask & plane) {
2078                linesDone = 0;
2079                while (h - linesDone > 0) {
2080                    nlines = min(linesPerBuf, h - linesDone);
2081
2082                    memset(pBuf, 0, nlines * widthBytesLine);
2083
2084                    XineramaGetImageData(drawables, x, y + linesDone, w,
2085                                         nlines, format, plane, pBuf,
2086                                         widthBytesLine, isRoot);
2087
2088                    WriteToClient(client, (int)(nlines * widthBytesLine), pBuf);
2089
2090                    linesDone += nlines;
2091                }
2092            }
2093        }
2094    }
2095    free(pBuf);
2096    return Success;
2097}
2098
2099/* The text stuff should be rewritten so that duplication happens
2100   at the GlyphBlt level.  That is, loading the font and getting
2101   the glyphs should only happen once */
2102
2103int
2104PanoramiXPolyText8(ClientPtr client)
2105{
2106    PanoramiXRes *gc, *draw;
2107    Bool isRoot;
2108    int result, j;
2109    int orig_x, orig_y;
2110
2111    REQUEST(xPolyTextReq);
2112
2113    REQUEST_AT_LEAST_SIZE(xPolyTextReq);
2114
2115    result = dixLookupResourceByClass((void **) &draw, stuff->drawable,
2116                                      XRC_DRAWABLE, client, DixWriteAccess);
2117    if (result != Success)
2118        return (result == BadValue) ? BadDrawable : result;
2119
2120    if (IS_SHARED_PIXMAP(draw))
2121        return (*SavedProcVector[X_PolyText8]) (client);
2122
2123    result = dixLookupResourceByType((void **) &gc, stuff->gc, XRT_GC,
2124                                     client, DixReadAccess);
2125    if (result != Success)
2126        return result;
2127
2128    isRoot = IS_ROOT_DRAWABLE(draw);
2129
2130    orig_x = stuff->x;
2131    orig_y = stuff->y;
2132    FOR_NSCREENS_BACKWARD(j) {
2133        stuff->drawable = draw->info[j].id;
2134        stuff->gc = gc->info[j].id;
2135        if (isRoot) {
2136            stuff->x = orig_x - screenInfo.screens[j]->x;
2137            stuff->y = orig_y - screenInfo.screens[j]->y;
2138        }
2139        result = (*SavedProcVector[X_PolyText8]) (client);
2140        if (result != Success)
2141            break;
2142    }
2143    return result;
2144}
2145
2146int
2147PanoramiXPolyText16(ClientPtr client)
2148{
2149    PanoramiXRes *gc, *draw;
2150    Bool isRoot;
2151    int result, j;
2152    int orig_x, orig_y;
2153
2154    REQUEST(xPolyTextReq);
2155
2156    REQUEST_AT_LEAST_SIZE(xPolyTextReq);
2157
2158    result = dixLookupResourceByClass((void **) &draw, stuff->drawable,
2159                                      XRC_DRAWABLE, client, DixWriteAccess);
2160    if (result != Success)
2161        return (result == BadValue) ? BadDrawable : result;
2162
2163    if (IS_SHARED_PIXMAP(draw))
2164        return (*SavedProcVector[X_PolyText16]) (client);
2165
2166    result = dixLookupResourceByType((void **) &gc, stuff->gc, XRT_GC,
2167                                     client, DixReadAccess);
2168    if (result != Success)
2169        return result;
2170
2171    isRoot = IS_ROOT_DRAWABLE(draw);
2172
2173    orig_x = stuff->x;
2174    orig_y = stuff->y;
2175    FOR_NSCREENS_BACKWARD(j) {
2176        stuff->drawable = draw->info[j].id;
2177        stuff->gc = gc->info[j].id;
2178        if (isRoot) {
2179            stuff->x = orig_x - screenInfo.screens[j]->x;
2180            stuff->y = orig_y - screenInfo.screens[j]->y;
2181        }
2182        result = (*SavedProcVector[X_PolyText16]) (client);
2183        if (result != Success)
2184            break;
2185    }
2186    return result;
2187}
2188
2189int
2190PanoramiXImageText8(ClientPtr client)
2191{
2192    int result, j;
2193    PanoramiXRes *gc, *draw;
2194    Bool isRoot;
2195    int orig_x, orig_y;
2196
2197    REQUEST(xImageTextReq);
2198
2199    REQUEST_FIXED_SIZE(xImageTextReq, stuff->nChars);
2200
2201    result = dixLookupResourceByClass((void **) &draw, stuff->drawable,
2202                                      XRC_DRAWABLE, client, DixWriteAccess);
2203    if (result != Success)
2204        return (result == BadValue) ? BadDrawable : result;
2205
2206    if (IS_SHARED_PIXMAP(draw))
2207        return (*SavedProcVector[X_ImageText8]) (client);
2208
2209    result = dixLookupResourceByType((void **) &gc, stuff->gc, XRT_GC,
2210                                     client, DixReadAccess);
2211    if (result != Success)
2212        return result;
2213
2214    isRoot = IS_ROOT_DRAWABLE(draw);
2215
2216    orig_x = stuff->x;
2217    orig_y = stuff->y;
2218    FOR_NSCREENS_BACKWARD(j) {
2219        stuff->drawable = draw->info[j].id;
2220        stuff->gc = gc->info[j].id;
2221        if (isRoot) {
2222            stuff->x = orig_x - screenInfo.screens[j]->x;
2223            stuff->y = orig_y - screenInfo.screens[j]->y;
2224        }
2225        result = (*SavedProcVector[X_ImageText8]) (client);
2226        if (result != Success)
2227            break;
2228    }
2229    return result;
2230}
2231
2232int
2233PanoramiXImageText16(ClientPtr client)
2234{
2235    int result, j;
2236    PanoramiXRes *gc, *draw;
2237    Bool isRoot;
2238    int orig_x, orig_y;
2239
2240    REQUEST(xImageTextReq);
2241
2242    REQUEST_FIXED_SIZE(xImageTextReq, stuff->nChars << 1);
2243
2244    result = dixLookupResourceByClass((void **) &draw, stuff->drawable,
2245                                      XRC_DRAWABLE, client, DixWriteAccess);
2246    if (result != Success)
2247        return (result == BadValue) ? BadDrawable : result;
2248
2249    if (IS_SHARED_PIXMAP(draw))
2250        return (*SavedProcVector[X_ImageText16]) (client);
2251
2252    result = dixLookupResourceByType((void **) &gc, stuff->gc, XRT_GC,
2253                                     client, DixReadAccess);
2254    if (result != Success)
2255        return result;
2256
2257    isRoot = IS_ROOT_DRAWABLE(draw);
2258
2259    orig_x = stuff->x;
2260    orig_y = stuff->y;
2261    FOR_NSCREENS_BACKWARD(j) {
2262        stuff->drawable = draw->info[j].id;
2263        stuff->gc = gc->info[j].id;
2264        if (isRoot) {
2265            stuff->x = orig_x - screenInfo.screens[j]->x;
2266            stuff->y = orig_y - screenInfo.screens[j]->y;
2267        }
2268        result = (*SavedProcVector[X_ImageText16]) (client);
2269        if (result != Success)
2270            break;
2271    }
2272    return result;
2273}
2274
2275int
2276PanoramiXCreateColormap(ClientPtr client)
2277{
2278    PanoramiXRes *win, *newCmap;
2279    int result, j, orig_visual;
2280
2281    REQUEST(xCreateColormapReq);
2282
2283    REQUEST_SIZE_MATCH(xCreateColormapReq);
2284
2285    result = dixLookupResourceByType((void **) &win, stuff->window,
2286                                     XRT_WINDOW, client, DixReadAccess);
2287    if (result != Success)
2288        return result;
2289
2290    if (!(newCmap = malloc(sizeof(PanoramiXRes))))
2291        return BadAlloc;
2292
2293    newCmap->type = XRT_COLORMAP;
2294    panoramix_setup_ids(newCmap, client, stuff->mid);
2295
2296    orig_visual = stuff->visual;
2297    FOR_NSCREENS_BACKWARD(j) {
2298        stuff->mid = newCmap->info[j].id;
2299        stuff->window = win->info[j].id;
2300        stuff->visual = PanoramiXTranslateVisualID(j, orig_visual);
2301        result = (*SavedProcVector[X_CreateColormap]) (client);
2302        if (result != Success)
2303            break;
2304    }
2305
2306    if (result == Success)
2307        AddResource(newCmap->info[0].id, XRT_COLORMAP, newCmap);
2308    else
2309        free(newCmap);
2310
2311    return result;
2312}
2313
2314int
2315PanoramiXFreeColormap(ClientPtr client)
2316{
2317    PanoramiXRes *cmap;
2318    int result, j;
2319
2320    REQUEST(xResourceReq);
2321
2322    REQUEST_SIZE_MATCH(xResourceReq);
2323
2324    client->errorValue = stuff->id;
2325
2326    result = dixLookupResourceByType((void **) &cmap, stuff->id, XRT_COLORMAP,
2327                                     client, DixDestroyAccess);
2328    if (result != Success)
2329        return result;
2330
2331    FOR_NSCREENS_BACKWARD(j) {
2332        stuff->id = cmap->info[j].id;
2333        result = (*SavedProcVector[X_FreeColormap]) (client);
2334        if (result != Success)
2335            break;
2336    }
2337
2338    /* Since ProcFreeColormap is using FreeResource, it will free
2339       our resource for us on the last pass through the loop above */
2340
2341    return result;
2342}
2343
2344int
2345PanoramiXCopyColormapAndFree(ClientPtr client)
2346{
2347    PanoramiXRes *cmap, *newCmap;
2348    int result, j;
2349
2350    REQUEST(xCopyColormapAndFreeReq);
2351
2352    REQUEST_SIZE_MATCH(xCopyColormapAndFreeReq);
2353
2354    client->errorValue = stuff->srcCmap;
2355
2356    result = dixLookupResourceByType((void **) &cmap, stuff->srcCmap,
2357                                     XRT_COLORMAP, client,
2358                                     DixReadAccess | DixWriteAccess);
2359    if (result != Success)
2360        return result;
2361
2362    if (!(newCmap = malloc(sizeof(PanoramiXRes))))
2363        return BadAlloc;
2364
2365    newCmap->type = XRT_COLORMAP;
2366    panoramix_setup_ids(newCmap, client, stuff->mid);
2367
2368    FOR_NSCREENS_BACKWARD(j) {
2369        stuff->srcCmap = cmap->info[j].id;
2370        stuff->mid = newCmap->info[j].id;
2371        result = (*SavedProcVector[X_CopyColormapAndFree]) (client);
2372        if (result != Success)
2373            break;
2374    }
2375
2376    if (result == Success)
2377        AddResource(newCmap->info[0].id, XRT_COLORMAP, newCmap);
2378    else
2379        free(newCmap);
2380
2381    return result;
2382}
2383
2384int
2385PanoramiXInstallColormap(ClientPtr client)
2386{
2387    REQUEST(xResourceReq);
2388    int result, j;
2389    PanoramiXRes *cmap;
2390
2391    REQUEST_SIZE_MATCH(xResourceReq);
2392
2393    client->errorValue = stuff->id;
2394
2395    result = dixLookupResourceByType((void **) &cmap, stuff->id, XRT_COLORMAP,
2396                                     client, DixReadAccess);
2397    if (result != Success)
2398        return result;
2399
2400    FOR_NSCREENS_BACKWARD(j) {
2401        stuff->id = cmap->info[j].id;
2402        result = (*SavedProcVector[X_InstallColormap]) (client);
2403        if (result != Success)
2404            break;
2405    }
2406    return result;
2407}
2408
2409int
2410PanoramiXUninstallColormap(ClientPtr client)
2411{
2412    REQUEST(xResourceReq);
2413    int result, j;
2414    PanoramiXRes *cmap;
2415
2416    REQUEST_SIZE_MATCH(xResourceReq);
2417
2418    client->errorValue = stuff->id;
2419
2420    result = dixLookupResourceByType((void **) &cmap, stuff->id, XRT_COLORMAP,
2421                                     client, DixReadAccess);
2422    if (result != Success)
2423        return result;
2424
2425    FOR_NSCREENS_BACKWARD(j) {
2426        stuff->id = cmap->info[j].id;
2427        result = (*SavedProcVector[X_UninstallColormap]) (client);
2428        if (result != Success)
2429            break;
2430    }
2431    return result;
2432}
2433
2434int
2435PanoramiXAllocColor(ClientPtr client)
2436{
2437    int result, j;
2438    PanoramiXRes *cmap;
2439
2440    REQUEST(xAllocColorReq);
2441
2442    REQUEST_SIZE_MATCH(xAllocColorReq);
2443
2444    client->errorValue = stuff->cmap;
2445
2446    result = dixLookupResourceByType((void **) &cmap, stuff->cmap,
2447                                     XRT_COLORMAP, client, DixWriteAccess);
2448    if (result != Success)
2449        return result;
2450
2451    FOR_NSCREENS_BACKWARD(j) {
2452        stuff->cmap = cmap->info[j].id;
2453        result = (*SavedProcVector[X_AllocColor]) (client);
2454        if (result != Success)
2455            break;
2456    }
2457    return result;
2458}
2459
2460int
2461PanoramiXAllocNamedColor(ClientPtr client)
2462{
2463    int result, j;
2464    PanoramiXRes *cmap;
2465
2466    REQUEST(xAllocNamedColorReq);
2467
2468    REQUEST_FIXED_SIZE(xAllocNamedColorReq, stuff->nbytes);
2469
2470    client->errorValue = stuff->cmap;
2471
2472    result = dixLookupResourceByType((void **) &cmap, stuff->cmap,
2473                                     XRT_COLORMAP, client, DixWriteAccess);
2474    if (result != Success)
2475        return result;
2476
2477    FOR_NSCREENS_BACKWARD(j) {
2478        stuff->cmap = cmap->info[j].id;
2479        result = (*SavedProcVector[X_AllocNamedColor]) (client);
2480        if (result != Success)
2481            break;
2482    }
2483    return result;
2484}
2485
2486int
2487PanoramiXAllocColorCells(ClientPtr client)
2488{
2489    int result, j;
2490    PanoramiXRes *cmap;
2491
2492    REQUEST(xAllocColorCellsReq);
2493
2494    REQUEST_SIZE_MATCH(xAllocColorCellsReq);
2495
2496    client->errorValue = stuff->cmap;
2497
2498    result = dixLookupResourceByType((void **) &cmap, stuff->cmap,
2499                                     XRT_COLORMAP, client, DixWriteAccess);
2500    if (result != Success)
2501        return result;
2502
2503    FOR_NSCREENS_BACKWARD(j) {
2504        stuff->cmap = cmap->info[j].id;
2505        result = (*SavedProcVector[X_AllocColorCells]) (client);
2506        if (result != Success)
2507            break;
2508    }
2509    return result;
2510}
2511
2512int
2513PanoramiXAllocColorPlanes(ClientPtr client)
2514{
2515    int result, j;
2516    PanoramiXRes *cmap;
2517
2518    REQUEST(xAllocColorPlanesReq);
2519
2520    REQUEST_SIZE_MATCH(xAllocColorPlanesReq);
2521
2522    client->errorValue = stuff->cmap;
2523
2524    result = dixLookupResourceByType((void **) &cmap, stuff->cmap,
2525                                     XRT_COLORMAP, client, DixWriteAccess);
2526    if (result != Success)
2527        return result;
2528
2529    FOR_NSCREENS_BACKWARD(j) {
2530        stuff->cmap = cmap->info[j].id;
2531        result = (*SavedProcVector[X_AllocColorPlanes]) (client);
2532        if (result != Success)
2533            break;
2534    }
2535    return result;
2536}
2537
2538int
2539PanoramiXFreeColors(ClientPtr client)
2540{
2541    int result, j;
2542    PanoramiXRes *cmap;
2543
2544    REQUEST(xFreeColorsReq);
2545
2546    REQUEST_AT_LEAST_SIZE(xFreeColorsReq);
2547
2548    client->errorValue = stuff->cmap;
2549
2550    result = dixLookupResourceByType((void **) &cmap, stuff->cmap,
2551                                     XRT_COLORMAP, client, DixWriteAccess);
2552    if (result != Success)
2553        return result;
2554
2555    FOR_NSCREENS_BACKWARD(j) {
2556        stuff->cmap = cmap->info[j].id;
2557        result = (*SavedProcVector[X_FreeColors]) (client);
2558    }
2559    return result;
2560}
2561
2562int
2563PanoramiXStoreColors(ClientPtr client)
2564{
2565    int result, j;
2566    PanoramiXRes *cmap;
2567
2568    REQUEST(xStoreColorsReq);
2569
2570    REQUEST_AT_LEAST_SIZE(xStoreColorsReq);
2571
2572    client->errorValue = stuff->cmap;
2573
2574    result = dixLookupResourceByType((void **) &cmap, stuff->cmap,
2575                                     XRT_COLORMAP, client, DixWriteAccess);
2576    if (result != Success)
2577        return result;
2578
2579    FOR_NSCREENS_BACKWARD(j) {
2580        stuff->cmap = cmap->info[j].id;
2581        result = (*SavedProcVector[X_StoreColors]) (client);
2582        if (result != Success)
2583            break;
2584    }
2585    return result;
2586}
2587
2588int
2589PanoramiXStoreNamedColor(ClientPtr client)
2590{
2591    int result, j;
2592    PanoramiXRes *cmap;
2593
2594    REQUEST(xStoreNamedColorReq);
2595
2596    REQUEST_FIXED_SIZE(xStoreNamedColorReq, stuff->nbytes);
2597
2598    client->errorValue = stuff->cmap;
2599
2600    result = dixLookupResourceByType((void **) &cmap, stuff->cmap,
2601                                     XRT_COLORMAP, client, DixWriteAccess);
2602    if (result != Success)
2603        return result;
2604
2605    FOR_NSCREENS_BACKWARD(j) {
2606        stuff->cmap = cmap->info[j].id;
2607        result = (*SavedProcVector[X_StoreNamedColor]) (client);
2608        if (result != Success)
2609            break;
2610    }
2611    return result;
2612}
2613