1/*
2
3Copyright 1993 by Davor Matic
4
5Permission to use, copy, modify, distribute, and sell this software
6and its documentation for any purpose is hereby granted without fee,
7provided that the above copyright notice appear in all copies and that
8both that copyright notice and this permission notice appear in
9supporting documentation.  Davor Matic makes no representations about
10the suitability of this software for any purpose.  It is provided "as
11is" without express or implied warranty.
12
13*/
14
15#ifdef HAVE_XNEST_CONFIG_H
16#include <xnest-config.h>
17#endif
18
19#include <X11/X.h>
20#include <X11/Xproto.h>
21#include "regionstr.h"
22#include <X11/fonts/fontstruct.h>
23#include "gcstruct.h"
24#include "scrnintstr.h"
25#include "windowstr.h"
26#include "pixmapstr.h"
27#include "region.h"
28#include "servermd.h"
29
30#include "Xnest.h"
31
32#include "Display.h"
33#include "Screen.h"
34#include "XNGC.h"
35#include "XNFont.h"
36#include "GCOps.h"
37#include "Drawable.h"
38#include "Visual.h"
39
40void
41xnestFillSpans(DrawablePtr pDrawable, GCPtr pGC, int nSpans, xPoint * pPoints,
42               int *pWidths, int fSorted)
43{
44    ErrorF("xnest warning: function xnestFillSpans not implemented\n");
45}
46
47void
48xnestSetSpans(DrawablePtr pDrawable, GCPtr pGC, char *pSrc,
49              xPoint * pPoints, int *pWidths, int nSpans, int fSorted)
50{
51    ErrorF("xnest warning: function xnestSetSpans not implemented\n");
52}
53
54void
55xnestGetSpans(DrawablePtr pDrawable, int maxWidth, DDXPointPtr pPoints,
56              int *pWidths, int nSpans, char *pBuffer)
57{
58    ErrorF("xnest warning: function xnestGetSpans not implemented\n");
59}
60
61void
62xnestQueryBestSize(int class, unsigned short *pWidth, unsigned short *pHeight,
63                   ScreenPtr pScreen)
64{
65    unsigned int width, height;
66
67    width = *pWidth;
68    height = *pHeight;
69
70    XQueryBestSize(xnestDisplay, class,
71                   xnestDefaultWindows[pScreen->myNum],
72                   width, height, &width, &height);
73
74    *pWidth = width;
75    *pHeight = height;
76}
77
78void
79xnestPutImage(DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y,
80              int w, int h, int leftPad, int format, char *pImage)
81{
82    XImage *ximage;
83
84    ximage = XCreateImage(xnestDisplay, xnestDefaultVisual(pDrawable->pScreen),
85                          depth, format, leftPad, (char *) pImage,
86                          w, h, BitmapPad(xnestDisplay),
87                          (format == ZPixmap) ?
88                          PixmapBytePad(w, depth) : BitmapBytePad(w + leftPad));
89
90    if (ximage) {
91        XPutImage(xnestDisplay, xnestDrawable(pDrawable), xnestGC(pGC),
92                  ximage, 0, 0, x, y, w, h);
93        XFree(ximage);
94    }
95}
96
97static int
98xnestIgnoreErrorHandler (Display     *dpy,
99                         XErrorEvent *event)
100{
101    return False; /* return value is ignored */
102}
103
104void
105xnestGetImage(DrawablePtr pDrawable, int x, int y, int w, int h,
106              unsigned int format, unsigned long planeMask, char *pImage)
107{
108    XImage *ximage;
109    int length;
110    int (*old_handler)(Display*, XErrorEvent*);
111
112    /* we may get BadMatch error when xnest window is minimized */
113    XSync(xnestDisplay, False);
114    old_handler = XSetErrorHandler (xnestIgnoreErrorHandler);
115
116    ximage = XGetImage(xnestDisplay, xnestDrawable(pDrawable),
117                       x, y, w, h, planeMask, format);
118    XSetErrorHandler(old_handler);
119
120    if (ximage) {
121        length = ximage->bytes_per_line * ximage->height;
122
123        memmove(pImage, ximage->data, length);
124
125        XDestroyImage(ximage);
126    }
127}
128
129static Bool
130xnestBitBlitPredicate(Display * dpy, XEvent * event, char *args)
131{
132    return event->type == GraphicsExpose || event->type == NoExpose;
133}
134
135static RegionPtr
136xnestBitBlitHelper(GCPtr pGC)
137{
138    if (!pGC->graphicsExposures)
139        return NullRegion;
140    else {
141        XEvent event;
142        RegionPtr pReg, pTmpReg;
143        BoxRec Box;
144        Bool pending, overlap;
145
146        pReg = RegionCreate(NULL, 1);
147        pTmpReg = RegionCreate(NULL, 1);
148        if (!pReg || !pTmpReg)
149            return NullRegion;
150
151        pending = True;
152        while (pending) {
153            XIfEvent(xnestDisplay, &event, xnestBitBlitPredicate, NULL);
154
155            switch (event.type) {
156            case NoExpose:
157                pending = False;
158                break;
159
160            case GraphicsExpose:
161                Box.x1 = event.xgraphicsexpose.x;
162                Box.y1 = event.xgraphicsexpose.y;
163                Box.x2 = event.xgraphicsexpose.x + event.xgraphicsexpose.width;
164                Box.y2 = event.xgraphicsexpose.y + event.xgraphicsexpose.height;
165                RegionReset(pTmpReg, &Box);
166                RegionAppend(pReg, pTmpReg);
167                pending = event.xgraphicsexpose.count;
168                break;
169            }
170        }
171
172        RegionDestroy(pTmpReg);
173        RegionValidate(pReg, &overlap);
174        return pReg;
175    }
176}
177
178RegionPtr
179xnestCopyArea(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable,
180              GCPtr pGC, int srcx, int srcy, int width, int height,
181              int dstx, int dsty)
182{
183    XCopyArea(xnestDisplay,
184              xnestDrawable(pSrcDrawable), xnestDrawable(pDstDrawable),
185              xnestGC(pGC), srcx, srcy, width, height, dstx, dsty);
186
187    return xnestBitBlitHelper(pGC);
188}
189
190RegionPtr
191xnestCopyPlane(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable,
192               GCPtr pGC, int srcx, int srcy, int width, int height,
193               int dstx, int dsty, unsigned long plane)
194{
195    XCopyPlane(xnestDisplay,
196               xnestDrawable(pSrcDrawable), xnestDrawable(pDstDrawable),
197               xnestGC(pGC), srcx, srcy, width, height, dstx, dsty, plane);
198
199    return xnestBitBlitHelper(pGC);
200}
201
202void
203xnestPolyPoint(DrawablePtr pDrawable, GCPtr pGC, int mode, int nPoints,
204               DDXPointPtr pPoints)
205{
206    XDrawPoints(xnestDisplay, xnestDrawable(pDrawable), xnestGC(pGC),
207                (XPoint *) pPoints, nPoints, mode);
208}
209
210void
211xnestPolylines(DrawablePtr pDrawable, GCPtr pGC, int mode, int nPoints,
212               DDXPointPtr pPoints)
213{
214    XDrawLines(xnestDisplay, xnestDrawable(pDrawable), xnestGC(pGC),
215               (XPoint *) pPoints, nPoints, mode);
216}
217
218void
219xnestPolySegment(DrawablePtr pDrawable, GCPtr pGC, int nSegments,
220                 xSegment * pSegments)
221{
222    XDrawSegments(xnestDisplay, xnestDrawable(pDrawable), xnestGC(pGC),
223                  (XSegment *) pSegments, nSegments);
224}
225
226void
227xnestPolyRectangle(DrawablePtr pDrawable, GCPtr pGC, int nRectangles,
228                   xRectangle *pRectangles)
229{
230    XDrawRectangles(xnestDisplay, xnestDrawable(pDrawable), xnestGC(pGC),
231                    (XRectangle *) pRectangles, nRectangles);
232}
233
234void
235xnestPolyArc(DrawablePtr pDrawable, GCPtr pGC, int nArcs, xArc * pArcs)
236{
237    XDrawArcs(xnestDisplay, xnestDrawable(pDrawable), xnestGC(pGC),
238              (XArc *) pArcs, nArcs);
239}
240
241void
242xnestFillPolygon(DrawablePtr pDrawable, GCPtr pGC, int shape, int mode,
243                 int nPoints, DDXPointPtr pPoints)
244{
245    XFillPolygon(xnestDisplay, xnestDrawable(pDrawable), xnestGC(pGC),
246                 (XPoint *) pPoints, nPoints, shape, mode);
247}
248
249void
250xnestPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nRectangles,
251                  xRectangle *pRectangles)
252{
253    XFillRectangles(xnestDisplay, xnestDrawable(pDrawable), xnestGC(pGC),
254                    (XRectangle *) pRectangles, nRectangles);
255}
256
257void
258xnestPolyFillArc(DrawablePtr pDrawable, GCPtr pGC, int nArcs, xArc * pArcs)
259{
260    XFillArcs(xnestDisplay, xnestDrawable(pDrawable), xnestGC(pGC),
261              (XArc *) pArcs, nArcs);
262}
263
264int
265xnestPolyText8(DrawablePtr pDrawable, GCPtr pGC, int x, int y, int count,
266               char *string)
267{
268    int width;
269
270    XDrawString(xnestDisplay, xnestDrawable(pDrawable), xnestGC(pGC),
271                x, y, string, count);
272
273    width = XTextWidth(xnestFontStruct(pGC->font), string, count);
274
275    return width + x;
276}
277
278int
279xnestPolyText16(DrawablePtr pDrawable, GCPtr pGC, int x, int y, int count,
280                unsigned short *string)
281{
282    int width;
283
284    XDrawString16(xnestDisplay, xnestDrawable(pDrawable), xnestGC(pGC),
285                  x, y, (XChar2b *) string, count);
286
287    width = XTextWidth16(xnestFontStruct(pGC->font), (XChar2b *) string, count);
288
289    return width + x;
290}
291
292void
293xnestImageText8(DrawablePtr pDrawable, GCPtr pGC, int x, int y, int count,
294                char *string)
295{
296    XDrawImageString(xnestDisplay, xnestDrawable(pDrawable), xnestGC(pGC),
297                     x, y, string, count);
298}
299
300void
301xnestImageText16(DrawablePtr pDrawable, GCPtr pGC, int x, int y, int count,
302                 unsigned short *string)
303{
304    XDrawImageString16(xnestDisplay, xnestDrawable(pDrawable), xnestGC(pGC),
305                       x, y, (XChar2b *) string, count);
306}
307
308void
309xnestImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x, int y,
310                   unsigned int nGlyphs, CharInfoPtr * pCharInfo,
311                   void *pGlyphBase)
312{
313    ErrorF("xnest warning: function xnestImageGlyphBlt not implemented\n");
314}
315
316void
317xnestPolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x, int y,
318                  unsigned int nGlyphs, CharInfoPtr * pCharInfo,
319                  void *pGlyphBase)
320{
321    ErrorF("xnest warning: function xnestPolyGlyphBlt not implemented\n");
322}
323
324void
325xnestPushPixels(GCPtr pGC, PixmapPtr pBitmap, DrawablePtr pDst,
326                int width, int height, int x, int y)
327{
328    /* only works for solid bitmaps */
329    if (pGC->fillStyle == FillSolid) {
330        XSetStipple(xnestDisplay, xnestGC(pGC), xnestPixmap(pBitmap));
331        XSetTSOrigin(xnestDisplay, xnestGC(pGC), x, y);
332        XSetFillStyle(xnestDisplay, xnestGC(pGC), FillStippled);
333        XFillRectangle(xnestDisplay, xnestDrawable(pDst),
334                       xnestGC(pGC), x, y, width, height);
335        XSetFillStyle(xnestDisplay, xnestGC(pGC), FillSolid);
336    }
337    else
338        ErrorF("xnest warning: function xnestPushPixels not implemented\n");
339}
340