Implemented the IDC_HAND cursor.
[wine] / graphics / x11drv / graphics.c
1 /*
2  * X11 graphics driver graphics functions
3  *
4  * Copyright 1993,1994 Alexandre Julliard
5  */
6
7 /*
8  * FIXME: none of these functions obey the GM_ADVANCED
9  * graphics mode
10  */
11
12 #include "config.h"
13
14 #include <X11/Intrinsic.h>
15
16 #include "ts_xlib.h"
17 #include "ts_xutil.h"
18
19 #include <math.h>
20 #ifdef HAVE_FLOAT_H
21 # include <float.h>
22 #endif
23 #include <stdlib.h>
24 #ifndef PI
25 #define PI M_PI
26 #endif
27 #include <string.h>
28
29 #include "x11drv.h"
30 #include "x11font.h"
31 #include "bitmap.h"
32 #include "gdi.h"
33 #include "dc.h"
34 #include "callback.h"
35 #include "metafile.h"
36 #include "palette.h"
37 #include "color.h"
38 #include "region.h"
39 #include "debugtools.h"
40
41 DEFAULT_DEBUG_CHANNEL(graphics);
42
43 #define ABS(x)    ((x)<0?(-(x)):(x))
44
45   /* ROP code to GC function conversion */
46 const int X11DRV_XROPfunction[16] =
47 {
48     GXclear,        /* R2_BLACK */
49     GXnor,          /* R2_NOTMERGEPEN */
50     GXandInverted,  /* R2_MASKNOTPEN */
51     GXcopyInverted, /* R2_NOTCOPYPEN */
52     GXandReverse,   /* R2_MASKPENNOT */
53     GXinvert,       /* R2_NOT */
54     GXxor,          /* R2_XORPEN */
55     GXnand,         /* R2_NOTMASKPEN */
56     GXand,          /* R2_MASKPEN */
57     GXequiv,        /* R2_NOTXORPEN */
58     GXnoop,         /* R2_NOP */
59     GXorInverted,   /* R2_MERGENOTPEN */
60     GXcopy,         /* R2_COPYPEN */
61     GXorReverse,    /* R2_MERGEPENNOT */
62     GXor,           /* R2_MERGEPEN */
63     GXset           /* R2_WHITE */
64 };
65
66
67 /***********************************************************************
68  *           X11DRV_SetupGCForPatBlt
69  *
70  * Setup the GC for a PatBlt operation using current brush.
71  * If fMapColors is TRUE, X pixels are mapped to Windows colors.
72  * Return FALSE if brush is BS_NULL, TRUE otherwise.
73  */
74 BOOL X11DRV_SetupGCForPatBlt( DC * dc, GC gc, BOOL fMapColors )
75 {
76     XGCValues val;
77     unsigned long mask;
78     Pixmap pixmap = 0;
79     X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
80
81     if (physDev->brush.style == BS_NULL) return FALSE;
82     if (physDev->brush.pixel == -1)
83     {
84         /* Special case used for monochrome pattern brushes.
85          * We need to swap foreground and background because
86          * Windows does it the wrong way...
87          */
88         val.foreground = physDev->backgroundPixel;
89         val.background = physDev->textPixel;
90     }
91     else
92     {
93         val.foreground = physDev->brush.pixel;
94         val.background = physDev->backgroundPixel;
95     }
96     if (fMapColors && X11DRV_PALETTE_XPixelToPalette)
97     {
98         val.foreground = X11DRV_PALETTE_XPixelToPalette[val.foreground];
99         val.background = X11DRV_PALETTE_XPixelToPalette[val.background];
100     }
101
102     val.function = X11DRV_XROPfunction[dc->w.ROPmode-1];
103     /*
104     ** Let's replace GXinvert by GXxor with (black xor white)
105     ** This solves the selection color and leak problems in excel
106     ** FIXME : Let's do that only if we work with X-pixels, not with Win-pixels
107     */
108     if (val.function == GXinvert)
109         {
110         val.foreground = BlackPixelOfScreen(X11DRV_GetXScreen()) ^ WhitePixelOfScreen(X11DRV_GetXScreen());
111         val.function = GXxor;
112         }
113     val.fill_style = physDev->brush.fillStyle;
114     switch(val.fill_style)
115     {
116     case FillStippled:
117     case FillOpaqueStippled:
118         if (dc->w.backgroundMode==OPAQUE) val.fill_style = FillOpaqueStippled;
119         val.stipple = physDev->brush.pixmap;
120         mask = GCStipple;
121         break;
122
123     case FillTiled:
124         if (fMapColors && X11DRV_PALETTE_XPixelToPalette)
125         {
126             register int x, y;
127             XImage *image;
128             EnterCriticalSection( &X11DRV_CritSection );
129             pixmap = XCreatePixmap( display, X11DRV_GetXRootWindow(), 
130                                     8, 8, X11DRV_GetDepth() );
131             image = XGetImage( display, physDev->brush.pixmap, 0, 0, 8, 8,
132                                AllPlanes, ZPixmap );
133             for (y = 0; y < 8; y++)
134                 for (x = 0; x < 8; x++)
135                     XPutPixel( image, x, y,
136                                X11DRV_PALETTE_XPixelToPalette[XGetPixel( image, x, y)] );
137             XPutImage( display, pixmap, gc, image, 0, 0, 0, 0, 8, 8 );
138             XDestroyImage( image );
139             LeaveCriticalSection( &X11DRV_CritSection );
140             val.tile = pixmap;
141         }
142         else val.tile = physDev->brush.pixmap;
143         mask = GCTile;
144         break;
145
146     default:
147         mask = 0;
148         break;
149     }
150     val.ts_x_origin = dc->w.DCOrgX + dc->w.brushOrgX;
151     val.ts_y_origin = dc->w.DCOrgY + dc->w.brushOrgY;
152     val.fill_rule = (dc->w.polyFillMode==WINDING) ? WindingRule : EvenOddRule;
153     TSXChangeGC( display, gc, 
154                GCFunction | GCForeground | GCBackground | GCFillStyle |
155                GCFillRule | GCTileStipXOrigin | GCTileStipYOrigin | mask,
156                &val );
157     if (pixmap) TSXFreePixmap( display, pixmap );
158     return TRUE;
159 }
160
161
162 /***********************************************************************
163  *           X11DRV_SetupGCForBrush
164  *
165  * Setup physDev->gc for drawing operations using current brush.
166  * Return FALSE if brush is BS_NULL, TRUE otherwise.
167  */
168 BOOL X11DRV_SetupGCForBrush( DC * dc )
169 {
170     X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
171     return X11DRV_SetupGCForPatBlt( dc, physDev->gc, FALSE );
172 }
173
174
175 /***********************************************************************
176  *           X11DRV_SetupGCForPen
177  *
178  * Setup physDev->gc for drawing operations using current pen.
179  * Return FALSE if pen is PS_NULL, TRUE otherwise.
180  */
181 BOOL X11DRV_SetupGCForPen( DC * dc )
182 {
183     XGCValues val;
184     X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
185
186     if (physDev->pen.style == PS_NULL) return FALSE;
187
188     switch (dc->w.ROPmode)
189     {
190     case R2_BLACK :
191         val.foreground = BlackPixelOfScreen( X11DRV_GetXScreen() );
192         val.function = GXcopy;
193         break;
194     case R2_WHITE :
195         val.foreground = WhitePixelOfScreen( X11DRV_GetXScreen() );
196         val.function = GXcopy;
197         break;
198     case R2_XORPEN :
199         val.foreground = physDev->pen.pixel;
200         /* It is very unlikely someone wants to XOR with 0 */
201         /* This fixes the rubber-drawings in paintbrush */
202         if (val.foreground == 0)
203             val.foreground = BlackPixelOfScreen( X11DRV_GetXScreen() )
204                             ^ WhitePixelOfScreen( X11DRV_GetXScreen() );
205         val.function = GXxor;
206         break;
207     default :
208         val.foreground = physDev->pen.pixel;
209         val.function   = X11DRV_XROPfunction[dc->w.ROPmode-1];
210     }
211     val.background = physDev->backgroundPixel;
212     val.fill_style = FillSolid;
213     if ((physDev->pen.width <= 1) &&
214         (physDev->pen.style != PS_SOLID) &&
215         (physDev->pen.style != PS_INSIDEFRAME))
216     {
217         TSXSetDashes( display, physDev->gc, 0, physDev->pen.dashes,
218                       physDev->pen.dash_len );
219         val.line_style = (dc->w.backgroundMode == OPAQUE) ?
220                               LineDoubleDash : LineOnOffDash;
221     }
222     else val.line_style = LineSolid;
223     val.line_width = physDev->pen.width;
224     if (val.line_width <= 1) {
225         val.cap_style = CapNotLast;
226     } else {
227         switch (physDev->pen.endcap)
228         {
229         case PS_ENDCAP_SQUARE:
230             val.cap_style = CapProjecting;
231             break;
232         case PS_ENDCAP_FLAT:
233             val.cap_style = CapButt;
234             break;
235         case PS_ENDCAP_ROUND:
236         default:
237             val.cap_style = CapRound;
238         }
239     }
240     switch (physDev->pen.linejoin)
241     {
242     case PS_JOIN_BEVEL:
243         val.join_style = JoinBevel;
244         break;
245     case PS_JOIN_MITER:
246         val.join_style = JoinMiter;
247         break;
248     case PS_JOIN_ROUND:
249     default:
250         val.join_style = JoinRound;
251     }
252     TSXChangeGC( display, physDev->gc, 
253                GCFunction | GCForeground | GCBackground | GCLineWidth |
254                GCLineStyle | GCCapStyle | GCJoinStyle | GCFillStyle, &val );
255     return TRUE;
256 }
257
258
259 /***********************************************************************
260  *           X11DRV_SetupGCForText
261  *
262  * Setup physDev->gc for text drawing operations.
263  * Return FALSE if the font is null, TRUE otherwise.
264  */
265 BOOL X11DRV_SetupGCForText( DC * dc )
266 {
267     X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
268     XFontStruct* xfs = XFONT_GetFontStruct( physDev->font );
269
270     if( xfs )
271     {
272         XGCValues val;
273
274         val.function   = GXcopy;  /* Text is always GXcopy */
275         val.foreground = physDev->textPixel;
276         val.background = physDev->backgroundPixel;
277         val.fill_style = FillSolid;
278         val.font       = xfs->fid;
279
280         TSXChangeGC( display, physDev->gc,
281                    GCFunction | GCForeground | GCBackground | GCFillStyle |
282                    GCFont, &val );
283         return TRUE;
284     } 
285     WARN("Physical font failure\n" );
286     return FALSE;
287 }
288
289 /***********************************************************************
290  *           X11DRV_LineTo
291  */
292 BOOL
293 X11DRV_LineTo( DC *dc, INT x, INT y )
294 {
295     X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
296
297     if (X11DRV_SetupGCForPen( dc )) {
298         /* Update the pixmap from the DIB section */
299         X11DRV_DIB_UpdateDIBSection(dc, FALSE);
300         TSXDrawLine(display, physDev->drawable, physDev->gc, 
301                   dc->w.DCOrgX + XLPTODP( dc, dc->w.CursPosX ),
302                   dc->w.DCOrgY + YLPTODP( dc, dc->w.CursPosY ),
303                   dc->w.DCOrgX + XLPTODP( dc, x ),
304                   dc->w.DCOrgY + YLPTODP( dc, y ) );
305         /* Update the DIBSection from the pixmap */
306         X11DRV_DIB_UpdateDIBSection(dc, TRUE); 
307     }
308     return TRUE;
309 }
310
311
312
313 /***********************************************************************
314  *           X11DRV_DrawArc
315  *
316  * Helper functions for Arc(), Chord() and Pie().
317  * 'lines' is the number of lines to draw: 0 for Arc, 1 for Chord, 2 for Pie.
318  *
319  */
320 static BOOL
321 X11DRV_DrawArc( DC *dc, INT left, INT top, INT right,
322                 INT bottom, INT xstart, INT ystart,
323                 INT xend, INT yend, INT lines )
324 {
325     INT xcenter, ycenter, istart_angle, idiff_angle;
326     INT width, oldwidth, oldendcap;
327     double start_angle, end_angle;
328     XPoint points[4];
329     X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
330     BOOL update = FALSE;
331
332     left   = XLPTODP( dc, left );
333     top    = YLPTODP( dc, top );
334     right  = XLPTODP( dc, right );
335     bottom = YLPTODP( dc, bottom );
336     xstart = XLPTODP( dc, xstart );
337     ystart = YLPTODP( dc, ystart );
338     xend   = XLPTODP( dc, xend );
339     yend   = YLPTODP( dc, yend );
340
341     if (right < left) { INT tmp = right; right = left; left = tmp; }
342     if (bottom < top) { INT tmp = bottom; bottom = top; top = tmp; }
343     if ((left == right) || (top == bottom)
344             ||(lines && ((right-left==1)||(bottom-top==1)))) return TRUE;
345
346     oldwidth = width = physDev->pen.width;
347     oldendcap = physDev->pen.endcap;
348     if (!width) width = 1;
349     if(physDev->pen.style == PS_NULL) width = 0;
350
351     if ((physDev->pen.style == PS_INSIDEFRAME))
352     {
353         if (2*width > (right-left)) width=(right-left + 1)/2;
354         if (2*width > (bottom-top)) width=(bottom-top + 1)/2;
355         left   += width / 2;
356         right  -= (width - 1) / 2;
357         top    += width / 2;
358         bottom -= (width - 1) / 2;
359     }
360     if(width == 0) width = 1; /* more accurate */
361     physDev->pen.width = width;
362     physDev->pen.endcap = PS_ENDCAP_SQUARE;
363
364     xcenter = (right + left) / 2;
365     ycenter = (bottom + top) / 2;
366     start_angle = atan2( (double)(ycenter-ystart)*(right-left),
367                          (double)(xstart-xcenter)*(bottom-top) );
368     end_angle   = atan2( (double)(ycenter-yend)*(right-left),
369                          (double)(xend-xcenter)*(bottom-top) );
370     if ((xstart==xend)&&(ystart==yend))
371       { /* A lazy program delivers xstart=xend=ystart=yend=0) */
372         start_angle = 0;
373         end_angle = 2* PI;
374       }
375     else /* notorious cases */
376       if ((start_angle == PI)&&( end_angle <0))
377         start_angle = - PI;
378     else
379       if ((end_angle == PI)&&( start_angle <0))
380         end_angle = - PI;
381     istart_angle = (INT)(start_angle * 180 * 64 / PI + 0.5);
382     idiff_angle  = (INT)((end_angle - start_angle) * 180 * 64 / PI + 0.5);
383     if (idiff_angle <= 0) idiff_angle += 360 * 64;
384
385     /* Update the pixmap from the DIB section */
386     X11DRV_DIB_UpdateDIBSection(dc, FALSE);
387
388       /* Fill arc with brush if Chord() or Pie() */
389
390     if ((lines > 0) && X11DRV_SetupGCForBrush( dc )) {
391         TSXSetArcMode( display, physDev->gc,
392                        (lines==1) ? ArcChord : ArcPieSlice);
393         TSXFillArc( display, physDev->drawable, physDev->gc,
394                  dc->w.DCOrgX + left, dc->w.DCOrgY + top,
395                  right-left-1, bottom-top-1, istart_angle, idiff_angle );
396         update = TRUE;
397     }
398
399       /* Draw arc and lines */
400
401     if (X11DRV_SetupGCForPen( dc )){
402         TSXDrawArc( display, physDev->drawable, physDev->gc,
403                 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
404                 right-left-1, bottom-top-1, istart_angle, idiff_angle );
405         if (lines) {
406             /* use the truncated values */
407             start_angle=(double)istart_angle*PI/64./180.;
408             end_angle=(double)(istart_angle+idiff_angle)*PI/64./180.;
409             /* calculate the endpoints and round correctly */
410             points[0].x = (int) floor(dc->w.DCOrgX + (right+left)/2.0 +
411                     cos(start_angle) * (right-left-width*2+2) / 2. + 0.5);
412             points[0].y = (int) floor(dc->w.DCOrgY + (top+bottom)/2.0 -
413                     sin(start_angle) * (bottom-top-width*2+2) / 2. + 0.5);
414             points[1].x = (int) floor(dc->w.DCOrgX + (right+left)/2.0 +
415                     cos(end_angle) * (right-left-width*2+2) / 2. + 0.5);
416             points[1].y = (int) floor(dc->w.DCOrgY + (top+bottom)/2.0 -
417                     sin(end_angle) * (bottom-top-width*2+2) / 2. + 0.5);
418                     
419             /* OK this stuff is optimized for Xfree86 
420              * which is probably the most used server by
421              * wine users. Other X servers will not 
422              * display correctly. (eXceed for instance)
423              * so if you feel you must change make sure that
424              * you either use Xfree86 or seperate your changes 
425              * from these (compile switch or whatever)
426              */
427             if (lines == 2) {
428                 INT dx1,dy1;
429                 points[3] = points[1];
430                 points[1].x = dc->w.DCOrgX + xcenter;
431                 points[1].y = dc->w.DCOrgY + ycenter;
432                 points[2] = points[1];
433                 dx1=points[1].x-points[0].x;
434                 dy1=points[1].y-points[0].y;
435                 if(((top-bottom) | -2) == -2)
436                     if(dy1>0) points[1].y--;
437                 if(dx1<0) {
438                     if (((-dx1)*64)<=ABS(dy1)*37) points[0].x--;
439                     if(((-dx1*9))<(dy1*16)) points[0].y--;
440                     if( dy1<0 && ((dx1*9)) < (dy1*16)) points[0].y--;
441                 } else {
442                     if(dy1 < 0)  points[0].y--;
443                     if(((right-left) | -2) == -2) points[1].x--;
444                 }
445                 dx1=points[3].x-points[2].x;
446                 dy1=points[3].y-points[2].y;
447                 if(((top-bottom) | -2 ) == -2)
448                     if(dy1 < 0) points[2].y--;
449                 if( dx1<0){ 
450                     if( dy1>0) points[3].y--;
451                     if(((right-left) | -2) == -2 ) points[2].x--;
452                 }else {
453                     points[3].y--;
454                     if( dx1 * 64 < dy1 * -37 ) points[3].x--;
455                 }
456                 lines++;
457             }
458             TSXDrawLines( display, physDev->drawable, physDev->gc,
459                 points, lines+1, CoordModeOrigin );
460         }
461         update = TRUE;
462     }
463
464     /* Update the DIBSection of the pixmap */
465     if (update) X11DRV_DIB_UpdateDIBSection(dc, TRUE);
466
467     physDev->pen.width = oldwidth;
468     physDev->pen.endcap = oldendcap;
469     return TRUE;
470 }
471
472
473 /***********************************************************************
474  *           X11DRV_Arc
475  */
476 BOOL
477 X11DRV_Arc( DC *dc, INT left, INT top, INT right, INT bottom,
478             INT xstart, INT ystart, INT xend, INT yend )
479 {
480     return X11DRV_DrawArc( dc, left, top, right, bottom,
481                            xstart, ystart, xend, yend, 0 );
482 }
483
484
485 /***********************************************************************
486  *           X11DRV_Pie
487  */
488 BOOL
489 X11DRV_Pie( DC *dc, INT left, INT top, INT right, INT bottom,
490             INT xstart, INT ystart, INT xend, INT yend )
491 {
492     return X11DRV_DrawArc( dc, left, top, right, bottom,
493                            xstart, ystart, xend, yend, 2 );
494 }
495
496 /***********************************************************************
497  *           X11DRV_Chord
498  */
499 BOOL
500 X11DRV_Chord( DC *dc, INT left, INT top, INT right, INT bottom,
501               INT xstart, INT ystart, INT xend, INT yend )
502 {
503     return X11DRV_DrawArc( dc, left, top, right, bottom,
504                            xstart, ystart, xend, yend, 1 );
505 }
506
507
508 /***********************************************************************
509  *           X11DRV_Ellipse
510  */
511 BOOL
512 X11DRV_Ellipse( DC *dc, INT left, INT top, INT right, INT bottom )
513 {
514     INT width, oldwidth;
515     X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
516     BOOL update = FALSE;
517
518     left   = XLPTODP( dc, left );
519     top    = YLPTODP( dc, top );
520     right  = XLPTODP( dc, right );
521     bottom = YLPTODP( dc, bottom );
522     if ((left == right) || (top == bottom)) return TRUE;
523
524     if (right < left) { INT tmp = right; right = left; left = tmp; }
525     if (bottom < top) { INT tmp = bottom; bottom = top; top = tmp; }
526     
527     oldwidth = width = physDev->pen.width;
528     if (!width) width = 1;
529     if(physDev->pen.style == PS_NULL) width = 0;
530
531     if ((physDev->pen.style == PS_INSIDEFRAME))
532     {
533         if (2*width > (right-left)) width=(right-left + 1)/2;
534         if (2*width > (bottom-top)) width=(bottom-top + 1)/2;
535         left   += width / 2;
536         right  -= (width - 1) / 2;
537         top    += width / 2;
538         bottom -= (width - 1) / 2;
539     }
540     if(width == 0) width = 1; /* more accurate */
541     physDev->pen.width = width;
542
543     /* Update the pixmap from the DIB section */
544     X11DRV_DIB_UpdateDIBSection(dc, FALSE);
545
546     if (X11DRV_SetupGCForBrush( dc ))
547     {
548         TSXFillArc( display, physDev->drawable, physDev->gc,
549                   dc->w.DCOrgX + left, dc->w.DCOrgY + top,
550                   right-left-1, bottom-top-1, 0, 360*64 );
551         update = TRUE;
552     }
553     if (X11DRV_SetupGCForPen( dc ))
554     {
555         TSXDrawArc( display, physDev->drawable, physDev->gc,
556                   dc->w.DCOrgX + left, dc->w.DCOrgY + top,
557                   right-left-1, bottom-top-1, 0, 360*64 );
558         update = TRUE;
559     }
560
561     /* Update the DIBSection from the pixmap */
562     if (update) X11DRV_DIB_UpdateDIBSection(dc, TRUE);
563     
564     physDev->pen.width = oldwidth;
565     return TRUE;
566 }
567
568
569 /***********************************************************************
570  *           X11DRV_Rectangle
571  */
572 BOOL
573 X11DRV_Rectangle(DC *dc, INT left, INT top, INT right, INT bottom)
574 {
575     INT width, oldwidth, oldjoinstyle;
576     X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
577     BOOL update = FALSE;
578
579     TRACE("(%d %d %d %d)\n", 
580         left, top, right, bottom);
581
582     left   = XLPTODP( dc, left );
583     top    = YLPTODP( dc, top );
584     right  = XLPTODP( dc, right );
585     bottom = YLPTODP( dc, bottom );
586
587     if ((left == right) || (top == bottom)) return TRUE;
588
589     if (right < left) { INT tmp = right; right = left; left = tmp; }
590     if (bottom < top) { INT tmp = bottom; bottom = top; top = tmp; }
591
592     oldwidth = width = physDev->pen.width;
593     if (!width) width = 1;
594     if(physDev->pen.style == PS_NULL) width = 0;
595
596     if ((physDev->pen.style == PS_INSIDEFRAME))
597     {
598         if (2*width > (right-left)) width=(right-left + 1)/2;
599         if (2*width > (bottom-top)) width=(bottom-top + 1)/2;
600         left   += width / 2;
601         right  -= (width - 1) / 2;
602         top    += width / 2;
603         bottom -= (width - 1) / 2;
604     }
605     if(width == 1) width = 0;
606     physDev->pen.width = width;
607     oldjoinstyle = physDev->pen.linejoin;
608     if(physDev->pen.type != PS_GEOMETRIC)
609         physDev->pen.linejoin = PS_JOIN_MITER;
610
611     /* Update the pixmap from the DIB section */
612     X11DRV_DIB_UpdateDIBSection(dc, FALSE);
613     
614     if ((right > left + width) && (bottom > top + width))
615         if (X11DRV_SetupGCForBrush( dc ))
616         {
617             TSXFillRectangle( display, physDev->drawable, physDev->gc,
618                             dc->w.DCOrgX + left + (width + 1) / 2,
619                             dc->w.DCOrgY + top + (width + 1) / 2,
620                             right-left-width-1, bottom-top-width-1);
621             update = TRUE;
622         }
623     if (X11DRV_SetupGCForPen( dc ))
624     {
625         TSXDrawRectangle( display, physDev->drawable, physDev->gc,
626                         dc->w.DCOrgX + left, dc->w.DCOrgY + top,
627                         right-left-1, bottom-top-1 );
628         update = TRUE;
629     }
630
631     /* Update the DIBSection from the pixmap */
632     if (update) X11DRV_DIB_UpdateDIBSection(dc, TRUE);
633    
634     physDev->pen.width = oldwidth;
635     physDev->pen.linejoin = oldjoinstyle;
636     return TRUE;
637 }
638
639 /***********************************************************************
640  *           X11DRV_RoundRect
641  */
642 BOOL
643 X11DRV_RoundRect( DC *dc, INT left, INT top, INT right,
644                   INT bottom, INT ell_width, INT ell_height )
645 {
646     INT width, oldwidth, oldendcap;
647     X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
648     BOOL update = FALSE;
649
650     TRACE("(%d %d %d %d  %d %d\n", 
651         left, top, right, bottom, ell_width, ell_height);
652
653     left   = XLPTODP( dc, left );
654     top    = YLPTODP( dc, top );
655     right  = XLPTODP( dc, right );
656     bottom = YLPTODP( dc, bottom );
657
658     if ((left == right) || (top == bottom))
659         return TRUE;
660
661     /* Make sure ell_width and ell_height are >= 1 otherwise XDrawArc gets
662        called with width/height < 0 */
663     ell_width  = max(abs( ell_width * dc->vportExtX / dc->wndExtX ), 1);
664     ell_height = max(abs( ell_height * dc->vportExtY / dc->wndExtY ), 1);
665
666     /* Fix the coordinates */
667
668     if (right < left) { INT tmp = right; right = left; left = tmp; }
669     if (bottom < top) { INT tmp = bottom; bottom = top; top = tmp; }
670
671     oldwidth = width = physDev->pen.width;
672     oldendcap = physDev->pen.endcap;
673     if (!width) width = 1;
674     if(physDev->pen.style == PS_NULL) width = 0;
675
676     if ((physDev->pen.style == PS_INSIDEFRAME))
677     {
678         if (2*width > (right-left)) width=(right-left + 1)/2;
679         if (2*width > (bottom-top)) width=(bottom-top + 1)/2;
680         left   += width / 2;
681         right  -= (width - 1) / 2;
682         top    += width / 2;
683         bottom -= (width - 1) / 2;
684     }
685     if(width == 0) width = 1;
686     physDev->pen.width = width;
687     physDev->pen.endcap = PS_ENDCAP_SQUARE;
688
689     /* Update the pixmap from the DIB section */
690     X11DRV_DIB_UpdateDIBSection(dc, FALSE);
691  
692     if (X11DRV_SetupGCForBrush( dc ))
693     {
694         if (ell_width > (right-left) )
695             if (ell_height > (bottom-top) )
696                     TSXFillArc( display, physDev->drawable, physDev->gc,
697                                 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
698                                 right - left - 1, bottom - top - 1,
699                                 0, 360 * 64 );
700             else{
701                     TSXFillArc( display, physDev->drawable, physDev->gc,
702                                 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
703                                 right - left - 1, ell_height, 0, 180 * 64 );
704                     TSXFillArc( display, physDev->drawable, physDev->gc,
705                                 dc->w.DCOrgX + left,
706                                 dc->w.DCOrgY + bottom - ell_height - 1,
707                                 right - left - 1, ell_height, 180 * 64,
708                                 180 * 64 );
709            }
710         else if (ell_height > (bottom-top) ){
711                 TSXFillArc( display, physDev->drawable, physDev->gc,
712                       dc->w.DCOrgX + left, dc->w.DCOrgY + top,
713                       ell_width, bottom - top - 1, 90 * 64, 180 * 64 );
714                 TSXFillArc( display, physDev->drawable, physDev->gc,
715                       dc->w.DCOrgX + right - ell_width -1, dc->w.DCOrgY + top,
716                       ell_width, bottom - top - 1, 270 * 64, 180 * 64 );
717         }else{
718                 TSXFillArc( display, physDev->drawable, physDev->gc,
719                       dc->w.DCOrgX + left, dc->w.DCOrgY + top,
720                       ell_width, ell_height, 90 * 64, 90 * 64 );
721                 TSXFillArc( display, physDev->drawable, physDev->gc,
722                       dc->w.DCOrgX + left,
723                       dc->w.DCOrgY + bottom - ell_height - 1,
724                       ell_width, ell_height, 180 * 64, 90 * 64 );
725                 TSXFillArc( display, physDev->drawable, physDev->gc,
726                       dc->w.DCOrgX + right - ell_width - 1,
727                       dc->w.DCOrgY + bottom - ell_height - 1,
728                       ell_width, ell_height, 270 * 64, 90 * 64 );
729                 TSXFillArc( display, physDev->drawable, physDev->gc,
730                       dc->w.DCOrgX + right - ell_width - 1,
731                       dc->w.DCOrgY + top,
732                       ell_width, ell_height, 0, 90 * 64 );
733         }
734         if (ell_width < right - left)
735         {
736             TSXFillRectangle( display, physDev->drawable, physDev->gc,
737                             dc->w.DCOrgX + left + (ell_width + 1) / 2,
738                             dc->w.DCOrgY + top + 1,
739                             right - left - ell_width - 1,
740                             (ell_height + 1) / 2 - 1);
741             TSXFillRectangle( display, physDev->drawable, physDev->gc,
742                             dc->w.DCOrgX + left + (ell_width + 1) / 2,
743                             dc->w.DCOrgY + bottom - (ell_height) / 2 - 1,
744                             right - left - ell_width - 1,
745                             (ell_height) / 2 );
746         }
747         if  (ell_height < bottom - top)
748         {
749             TSXFillRectangle( display, physDev->drawable, physDev->gc,
750                             dc->w.DCOrgX + left + 1,
751                             dc->w.DCOrgY + top + (ell_height + 1) / 2,
752                             right - left - 2,
753                             bottom - top - ell_height - 1);
754         }
755         update = TRUE;
756     }
757     /* FIXME: this could be done with on X call
758      * more efficient and probably more correct
759      * on any X server: XDrawArcs will draw
760      * straight horizontal and vertical lines
761      * if width or height are zero.
762      *
763      * BTW this stuff is optimized for an Xfree86 server
764      * read the comments inside the X11DRV_DrawArc function
765      */
766     if (X11DRV_SetupGCForPen(dc)) {
767         if (ell_width > (right-left) )
768             if (ell_height > (bottom-top) )
769                 TSXDrawArc( display, physDev->drawable, physDev->gc,
770                       dc->w.DCOrgX + left, dc->w.DCOrgY + top,
771                       right - left - 1, bottom -top - 1, 0 , 360 * 64 );
772             else{
773                 TSXDrawArc( display, physDev->drawable, physDev->gc,
774                       dc->w.DCOrgX + left, dc->w.DCOrgY + top,
775                       right - left - 1, ell_height - 1, 0 , 180 * 64 );
776                 TSXDrawArc( display, physDev->drawable, physDev->gc,
777                       dc->w.DCOrgX + left, 
778                       dc->w.DCOrgY + bottom - ell_height,
779                       right - left - 1, ell_height - 1, 180 * 64 , 180 * 64 );
780             }
781         else if (ell_height > (bottom-top) ){
782                 TSXDrawArc( display, physDev->drawable, physDev->gc,
783                       dc->w.DCOrgX + left, dc->w.DCOrgY + top,
784                       ell_width - 1 , bottom - top - 1, 90 * 64 , 180 * 64 );
785                 TSXDrawArc( display, physDev->drawable, physDev->gc,
786                       dc->w.DCOrgX + right - ell_width, 
787                       dc->w.DCOrgY + top,
788                       ell_width - 1 , bottom - top - 1, 270 * 64 , 180 * 64 );
789         }else{
790             TSXDrawArc( display, physDev->drawable, physDev->gc,
791                       dc->w.DCOrgX + left, dc->w.DCOrgY + top,
792                       ell_width - 1, ell_height - 1, 90 * 64, 90 * 64 );
793             TSXDrawArc( display, physDev->drawable, physDev->gc,
794                       dc->w.DCOrgX + left, dc->w.DCOrgY + bottom - ell_height,
795                       ell_width - 1, ell_height - 1, 180 * 64, 90 * 64 );
796             TSXDrawArc( display, physDev->drawable, physDev->gc,
797                       dc->w.DCOrgX + right - ell_width,
798                       dc->w.DCOrgY + bottom - ell_height,
799                       ell_width - 1, ell_height - 1, 270 * 64, 90 * 64 );
800             TSXDrawArc( display, physDev->drawable, physDev->gc,
801                       dc->w.DCOrgX + right - ell_width, dc->w.DCOrgY + top,
802                       ell_width - 1, ell_height - 1, 0, 90 * 64 );
803         }
804         if (ell_width < right - left)
805         {
806             TSXDrawLine( display, physDev->drawable, physDev->gc, 
807                dc->w.DCOrgX + left + ell_width / 2,
808                        dc->w.DCOrgY + top,
809                dc->w.DCOrgX + right - (ell_width+1) / 2,
810                        dc->w.DCOrgY + top);
811             TSXDrawLine( display, physDev->drawable, physDev->gc, 
812                dc->w.DCOrgX + left + ell_width / 2 ,
813                        dc->w.DCOrgY + bottom - 1,
814                dc->w.DCOrgX + right - (ell_width+1)/ 2,
815                        dc->w.DCOrgY + bottom - 1);
816         }
817         if (ell_height < bottom - top)
818         {
819             TSXDrawLine( display, physDev->drawable, physDev->gc, 
820                        dc->w.DCOrgX + right - 1,
821                dc->w.DCOrgY + top + ell_height / 2,
822                        dc->w.DCOrgX + right - 1,
823                dc->w.DCOrgY + bottom - (ell_height+1) / 2);
824             TSXDrawLine( display, physDev->drawable, physDev->gc, 
825                        dc->w.DCOrgX + left,
826                dc->w.DCOrgY + top + ell_height / 2,
827                        dc->w.DCOrgX + left,
828                dc->w.DCOrgY + bottom - (ell_height+1) / 2);
829         }
830         update = TRUE;
831     }
832     
833     /* Update the DIBSection from the pixmap */
834     if (update) X11DRV_DIB_UpdateDIBSection(dc, TRUE);
835
836     physDev->pen.width = oldwidth;
837     physDev->pen.endcap = oldendcap;
838     return TRUE;
839 }
840
841
842 /***********************************************************************
843  *           X11DRV_SetPixel
844  */
845 COLORREF
846 X11DRV_SetPixel( DC *dc, INT x, INT y, COLORREF color )
847 {
848     Pixel pixel;
849     X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
850     
851     x = dc->w.DCOrgX + XLPTODP( dc, x );
852     y = dc->w.DCOrgY + YLPTODP( dc, y );
853     pixel = X11DRV_PALETTE_ToPhysical( dc, color );
854     
855     TSXSetForeground( display, physDev->gc, pixel );
856     TSXSetFunction( display, physDev->gc, GXcopy );
857     TSXDrawPoint( display, physDev->drawable, physDev->gc, x, y );
858
859     /* inefficient but simple... */
860
861     /* FIXME: the DIBSection pixel should be updated too */
862     
863     return X11DRV_PALETTE_ToLogical(pixel);
864 }
865
866
867 /***********************************************************************
868  *           X11DRV_GetPixel
869  */
870 COLORREF
871 X11DRV_GetPixel( DC *dc, INT x, INT y )
872 {
873     static Pixmap pixmap = 0;
874     XImage * image;
875     int pixel;
876     X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
877
878     x = dc->w.DCOrgX + XLPTODP( dc, x );
879     y = dc->w.DCOrgY + YLPTODP( dc, y );
880     EnterCriticalSection( &X11DRV_CritSection );
881     if (dc->w.flags & DC_MEMORY)
882     {
883         image = XGetImage( display, physDev->drawable, x, y, 1, 1,
884                            AllPlanes, ZPixmap );
885     }
886     else
887     {
888         /* If we are reading from the screen, use a temporary copy */
889         /* to avoid a BadMatch error */
890         if (!pixmap) pixmap = XCreatePixmap( display, X11DRV_GetXRootWindow(),
891                                              1, 1, dc->w.bitsPerPixel );
892         XCopyArea( display, physDev->drawable, pixmap, BITMAP_colorGC,
893                    x, y, 1, 1, 0, 0 );
894         image = XGetImage( display, pixmap, 0, 0, 1, 1, AllPlanes, ZPixmap );
895     }
896     pixel = XGetPixel( image, 0, 0 );
897     XDestroyImage( image );
898     LeaveCriticalSection( &X11DRV_CritSection );
899     
900     return X11DRV_PALETTE_ToLogical(pixel);
901 }
902
903
904 /***********************************************************************
905  *           X11DRV_PaintRgn
906  */
907 BOOL
908 X11DRV_PaintRgn( DC *dc, HRGN hrgn )
909 {
910     RECT box;
911     HRGN tmpVisRgn, prevVisRgn;
912     HDC  hdc = dc->hSelf; /* FIXME: should not mix dc/hdc this way */
913     X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
914
915     if (!(tmpVisRgn = CreateRectRgn( 0, 0, 0, 0 ))) return FALSE;
916
917       /* Transform region into device co-ords */
918     if (  !REGION_LPTODP( hdc, tmpVisRgn, hrgn )
919         || OffsetRgn( tmpVisRgn, dc->w.DCOrgX, dc->w.DCOrgY ) == ERROR) {
920         DeleteObject( tmpVisRgn );
921         return FALSE;
922     }
923
924       /* Modify visible region */
925     if (!(prevVisRgn = SaveVisRgn16( hdc ))) {
926         DeleteObject( tmpVisRgn );
927         return FALSE;
928     }
929     CombineRgn( tmpVisRgn, prevVisRgn, tmpVisRgn, RGN_AND );
930     SelectVisRgn16( hdc, tmpVisRgn );
931     DeleteObject( tmpVisRgn );
932
933       /* Fill the region */
934
935     GetRgnBox( dc->w.hGCClipRgn, &box );
936     if (X11DRV_SetupGCForBrush( dc ))
937     {
938         /* Update the pixmap from the DIB section */
939         X11DRV_DIB_UpdateDIBSection(dc, FALSE);
940
941         TSXFillRectangle( display, physDev->drawable, physDev->gc,
942                           box.left, box.top,
943                           box.right-box.left, box.bottom-box.top );
944     
945         /* Update the DIBSection from the pixmap */
946         X11DRV_DIB_UpdateDIBSection(dc, TRUE);
947     }
948
949       /* Restore the visible region */
950
951     RestoreVisRgn16( hdc );
952     return TRUE;
953 }
954
955 /**********************************************************************
956  *          X11DRV_Polyline
957  */
958 BOOL
959 X11DRV_Polyline( DC *dc, const POINT* pt, INT count )
960 {
961     INT oldwidth;
962     register int i;
963     XPoint *points;
964     X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
965
966     if((oldwidth = physDev->pen.width) == 0) physDev->pen.width = 1;
967
968     if (!(points = HeapAlloc( GetProcessHeap(), 0, sizeof(XPoint) * count )))
969     {
970         WARN("No memory to convert POINTs to XPoints!\n");
971         return FALSE;
972     }
973     for (i = 0; i < count; i++)
974     {
975         points[i].x = dc->w.DCOrgX + XLPTODP( dc, pt[i].x );
976         points[i].y = dc->w.DCOrgY + YLPTODP( dc, pt[i].y );
977     }
978
979     if (X11DRV_SetupGCForPen ( dc ))
980     {
981         /* Update the pixmap from the DIB section */
982         X11DRV_DIB_UpdateDIBSection(dc, FALSE);
983  
984         TSXDrawLines( display, physDev->drawable, physDev->gc,
985            points, count, CoordModeOrigin );
986
987         /* Update the DIBSection from the pixmap */
988         X11DRV_DIB_UpdateDIBSection(dc, TRUE);
989     }
990
991     HeapFree( GetProcessHeap(), 0, points );
992     physDev->pen.width = oldwidth;
993     return TRUE;
994 }
995
996
997 /**********************************************************************
998  *          X11DRV_Polygon
999  */
1000 BOOL
1001 X11DRV_Polygon( DC *dc, const POINT* pt, INT count )
1002 {
1003     register int i;
1004     XPoint *points;
1005     X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
1006     BOOL update = FALSE;
1007
1008     if (!(points = HeapAlloc( GetProcessHeap(), 0, sizeof(XPoint) * (count+1) )))
1009     {
1010         WARN("No memory to convert POINTs to XPoints!\n");
1011         return FALSE;
1012     }
1013     for (i = 0; i < count; i++)
1014     {
1015         points[i].x = dc->w.DCOrgX + XLPTODP( dc, pt[i].x );
1016         points[i].y = dc->w.DCOrgY + YLPTODP( dc, pt[i].y );
1017     }
1018     points[count] = points[0];
1019
1020     /* Update the pixmap from the DIB section */
1021     X11DRV_DIB_UpdateDIBSection(dc, FALSE);
1022  
1023     if (X11DRV_SetupGCForBrush( dc ))
1024     {
1025         TSXFillPolygon( display, physDev->drawable, physDev->gc,
1026                      points, count+1, Complex, CoordModeOrigin);
1027         update = TRUE;
1028     }
1029     if (X11DRV_SetupGCForPen ( dc ))
1030     {
1031         TSXDrawLines( display, physDev->drawable, physDev->gc,
1032                    points, count+1, CoordModeOrigin );
1033         update = TRUE;
1034     }
1035    
1036     /* Update the DIBSection from the pixmap */
1037     if (update) X11DRV_DIB_UpdateDIBSection(dc, TRUE);
1038
1039     HeapFree( GetProcessHeap(), 0, points );
1040     return TRUE;
1041 }
1042
1043
1044 /**********************************************************************
1045  *          X11DRV_PolyPolygon
1046  */
1047 BOOL 
1048 X11DRV_PolyPolygon( DC *dc, const POINT* pt, const INT* counts, UINT polygons)
1049 {
1050     HRGN hrgn;
1051     X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
1052
1053     /* FIXME: The points should be converted to device coords before */
1054     /* creating the region. */
1055
1056     hrgn = CreatePolyPolygonRgn( pt, counts, polygons, dc->w.polyFillMode );
1057     X11DRV_PaintRgn( dc, hrgn );
1058     DeleteObject( hrgn );
1059
1060       /* Draw the outline of the polygons */
1061
1062     if (X11DRV_SetupGCForPen ( dc ))
1063     {
1064         int i, j, max = 0;
1065         XPoint *points;
1066
1067         /* Update the pixmap from the DIB section */
1068         X11DRV_DIB_UpdateDIBSection(dc, FALSE);
1069  
1070         for (i = 0; i < polygons; i++) if (counts[i] > max) max = counts[i];
1071         if (!(points = HeapAlloc( GetProcessHeap(), 0, sizeof(XPoint) * (max+1) )))
1072         {
1073             WARN("No memory to convert POINTs to XPoints!\n");
1074             return FALSE;
1075         }
1076         for (i = 0; i < polygons; i++)
1077         {
1078             for (j = 0; j < counts[i]; j++)
1079             {
1080                 points[j].x = dc->w.DCOrgX + XLPTODP( dc, pt->x );
1081                 points[j].y = dc->w.DCOrgY + YLPTODP( dc, pt->y );
1082                 pt++;
1083             }
1084             points[j] = points[0];
1085             TSXDrawLines( display, physDev->drawable, physDev->gc,
1086                         points, j + 1, CoordModeOrigin );
1087         }
1088         
1089         /* Update the DIBSection of the dc's bitmap */
1090         X11DRV_DIB_UpdateDIBSection(dc, TRUE);
1091
1092         HeapFree( GetProcessHeap(), 0, points );
1093     }
1094     return TRUE;
1095 }
1096
1097
1098 /**********************************************************************
1099  *          X11DRV_PolyPolyline
1100  */
1101 BOOL 
1102 X11DRV_PolyPolyline( DC *dc, const POINT* pt, const DWORD* counts, DWORD polylines )
1103 {
1104     X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
1105     
1106     if (X11DRV_SetupGCForPen ( dc ))
1107     {
1108         int i, j, max = 0;
1109         XPoint *points;
1110
1111         /* Update the pixmap from the DIB section */
1112         X11DRV_DIB_UpdateDIBSection(dc, FALSE);
1113  
1114         for (i = 0; i < polylines; i++) if (counts[i] > max) max = counts[i];
1115         if (!(points = HeapAlloc( GetProcessHeap(), 0, sizeof(XPoint) * max )))
1116         {
1117             WARN("No memory to convert POINTs to XPoints!\n");
1118             return FALSE;
1119         }
1120         for (i = 0; i < polylines; i++)
1121         {
1122             for (j = 0; j < counts[i]; j++)
1123             {
1124                 points[j].x = dc->w.DCOrgX + XLPTODP( dc, pt->x );
1125                 points[j].y = dc->w.DCOrgY + YLPTODP( dc, pt->y );
1126                 pt++;
1127             }
1128             TSXDrawLines( display, physDev->drawable, physDev->gc,
1129                           points, j, CoordModeOrigin );
1130         }
1131         
1132         /* Update the DIBSection of the dc's bitmap */
1133         X11DRV_DIB_UpdateDIBSection(dc, TRUE);
1134
1135         HeapFree( GetProcessHeap(), 0, points );
1136     }
1137     return TRUE;
1138 }
1139
1140
1141 /**********************************************************************
1142  *          X11DRV_InternalFloodFill
1143  *
1144  * Internal helper function for flood fill.
1145  * (xorg,yorg) is the origin of the X image relative to the drawable.
1146  * (x,y) is relative to the origin of the X image.
1147  */
1148 static void X11DRV_InternalFloodFill(XImage *image, DC *dc,
1149                                      int x, int y,
1150                                      int xOrg, int yOrg,
1151                                      Pixel pixel, WORD fillType )
1152 {
1153     X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
1154     int left, right;
1155
1156 #define TO_FLOOD(x,y)  ((fillType == FLOODFILLBORDER) ? \
1157                         (XGetPixel(image,x,y) != pixel) : \
1158                         (XGetPixel(image,x,y) == pixel))
1159
1160     if (!TO_FLOOD(x,y)) return;
1161
1162       /* Find left and right boundaries */
1163
1164     left = right = x;
1165     while ((left > 0) && TO_FLOOD( left-1, y )) left--;
1166     while ((right < image->width) && TO_FLOOD( right, y )) right++;
1167     XFillRectangle( display, physDev->drawable, physDev->gc,
1168                     xOrg + left, yOrg + y, right-left, 1 );
1169
1170       /* Set the pixels of this line so we don't fill it again */
1171
1172     for (x = left; x < right; x++)
1173     {
1174         if (fillType == FLOODFILLBORDER) XPutPixel( image, x, y, pixel );
1175         else XPutPixel( image, x, y, ~pixel );
1176     }
1177
1178       /* Fill the line above */
1179
1180     if (--y >= 0)
1181     {
1182         x = left;
1183         while (x < right)
1184         {
1185             while ((x < right) && !TO_FLOOD(x,y)) x++;
1186             if (x >= right) break;
1187             while ((x < right) && TO_FLOOD(x,y)) x++;
1188             X11DRV_InternalFloodFill(image, dc, x-1, y,
1189                                      xOrg, yOrg, pixel, fillType );
1190         }
1191     }
1192
1193       /* Fill the line below */
1194
1195     if ((y += 2) < image->height)
1196     {
1197         x = left;
1198         while (x < right)
1199         {
1200             while ((x < right) && !TO_FLOOD(x,y)) x++;
1201             if (x >= right) break;
1202             while ((x < right) && TO_FLOOD(x,y)) x++;
1203             X11DRV_InternalFloodFill(image, dc, x-1, y,
1204                                      xOrg, yOrg, pixel, fillType );
1205         }
1206     }
1207 #undef TO_FLOOD    
1208 }
1209
1210
1211 /**********************************************************************
1212  *          X11DRV_DoFloodFill
1213  *
1214  * Main flood-fill routine.
1215  *
1216  * The Xlib critical section must be entered before calling this function.
1217  */
1218
1219 struct FloodFill_params
1220 {
1221     DC      *dc;
1222     INT    x;
1223     INT    y;
1224     COLORREF color;
1225     UINT   fillType;
1226 };
1227
1228 static BOOL X11DRV_DoFloodFill( const struct FloodFill_params *params )
1229 {
1230     XImage *image;
1231     RECT rect;
1232     DC *dc = params->dc;
1233     X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
1234
1235     if (GetRgnBox( dc->w.hGCClipRgn, &rect ) == ERROR) return FALSE;
1236
1237     if (!(image = XGetImage( display, physDev->drawable,
1238                              rect.left,
1239                              rect.top,
1240                              rect.right - rect.left,
1241                              rect.bottom - rect.top,
1242                              AllPlanes, ZPixmap ))) return FALSE;
1243
1244     if (X11DRV_SetupGCForBrush( dc ))
1245     {
1246         /* Update the pixmap from the DIB section */
1247         X11DRV_DIB_UpdateDIBSection(dc, FALSE);
1248  
1249           /* ROP mode is always GXcopy for flood-fill */
1250         XSetFunction( display, physDev->gc, GXcopy );
1251         X11DRV_InternalFloodFill(image, dc,
1252                                  XLPTODP(dc,params->x) + dc->w.DCOrgX - rect.left,
1253                                  YLPTODP(dc,params->y) + dc->w.DCOrgY - rect.top,
1254                                  rect.left,
1255                                  rect.top,
1256                                  X11DRV_PALETTE_ToPhysical( dc, params->color ),
1257                                  params->fillType );
1258         
1259         /* Update the DIBSection of the dc's bitmap */
1260         X11DRV_DIB_UpdateDIBSection(dc, TRUE);
1261     }
1262
1263     XDestroyImage( image );
1264     return TRUE;
1265 }
1266
1267
1268 /**********************************************************************
1269  *          X11DRV_ExtFloodFill
1270  */
1271 BOOL
1272 X11DRV_ExtFloodFill( DC *dc, INT x, INT y, COLORREF color,
1273                      UINT fillType )
1274 {
1275     BOOL result;
1276     struct FloodFill_params params;
1277
1278     TRACE("X11DRV_ExtFloodFill %d,%d %06lx %d\n",
1279                       x, y, color, fillType );
1280
1281     params.dc = dc;
1282     params.x = x;
1283     params.y = y;
1284     params.color = color;
1285     params.fillType = fillType;
1286
1287     if (!PtVisible( dc->hSelf, x, y )) return FALSE;
1288     EnterCriticalSection( &X11DRV_CritSection );
1289     result = CALL_LARGE_STACK( X11DRV_DoFloodFill, &params );
1290     LeaveCriticalSection( &X11DRV_CritSection );
1291     return result;
1292 }
1293
1294 /**********************************************************************
1295  *          X11DRV_SetBkColor
1296  */
1297 COLORREF
1298 X11DRV_SetBkColor( DC *dc, COLORREF color )
1299 {
1300     X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
1301     COLORREF oldColor;
1302
1303     oldColor = dc->w.backgroundColor;
1304     dc->w.backgroundColor = color;
1305
1306     physDev->backgroundPixel = X11DRV_PALETTE_ToPhysical( dc, color );
1307
1308     return oldColor;
1309 }
1310
1311 /**********************************************************************
1312  *          X11DRV_SetTextColor
1313  */
1314 COLORREF
1315 X11DRV_SetTextColor( DC *dc, COLORREF color )
1316 {
1317     X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
1318     COLORREF oldColor;
1319
1320     oldColor = dc->w.textColor;
1321     dc->w.textColor = color;
1322
1323     physDev->textPixel = X11DRV_PALETTE_ToPhysical( dc, color );
1324
1325     return oldColor;
1326 }
1327
1328 /***********************************************************************
1329  *           X11DRV_GetDCOrgEx
1330  */
1331 BOOL X11DRV_GetDCOrgEx( DC *dc, LPPOINT lpp )
1332 {
1333     if (!(dc->w.flags & DC_MEMORY))
1334     {
1335        X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *) dc->physDev;
1336        Window root;
1337        int w, h, border, depth;
1338
1339        /* FIXME: this is not correct for managed windows */
1340        TSXGetGeometry( display, physDev->drawable, &root,
1341                        (int*)&lpp->x, (int*)&lpp->y, &w, &h, &border, &depth );
1342     }
1343     else lpp->x = lpp->y = 0;
1344     return TRUE;
1345 }
1346