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