Added an unknown VxD error code.
[wine] / graphics / x11drv / dib.c
1 /*
2  * X11DRV device-independent bitmaps
3  *
4  * Copyright 1993,1994  Alexandre Julliard
5  */
6
7 #include "config.h"
8
9 #include "ts_xlib.h"
10 #include "ts_xutil.h"
11 #ifdef HAVE_LIBXXSHM
12 # include "ts_xshm.h"
13 # ifdef HAVE_SYS_SHM_H
14 #  include <sys/shm.h>
15 # endif
16 # ifdef HAVE_SYS_IPC_H
17 #  include <sys/ipc.h>
18 # endif
19 #endif /* defined(HAVE_LIBXXSHM) */
20
21 #include <stdlib.h>
22 #include <string.h>
23 #include "windef.h"
24 #include "bitmap.h"
25 #include "x11drv.h"
26 #include "debugtools.h"
27 #include "gdi.h"
28 #include "color.h"
29 #include "selectors.h"
30 #include "global.h"
31
32 DEFAULT_DEBUG_CHANNEL(bitmap);
33 DECLARE_DEBUG_CHANNEL(x11drv);
34
35 static int ximageDepthTable[32];
36
37 static int XShmErrorFlag = 0;
38
39 /* This structure holds the arguments for DIB_SetImageBits() */
40 typedef struct
41 {
42     struct tagDC   *dc;
43     LPCVOID         bits;
44     XImage         *image;
45     PALETTEENTRY   *palentry;
46     int             lines;
47     DWORD           infoWidth;
48     WORD            depth;
49     WORD            infoBpp;
50     WORD            compression;
51     RGBQUAD        *colorMap;
52     int             nColorMap;
53     Drawable        drawable;
54     GC              gc;
55     int             xSrc;
56     int             ySrc;
57     int             xDest;
58     int             yDest;
59     int             width;
60     int             height;
61     DWORD           rMask;
62     DWORD           gMask;
63     DWORD           bMask;
64     BOOL            useShm;
65     int             dibpitch;
66 } X11DRV_DIB_IMAGEBITS_DESCR;
67
68
69 /***********************************************************************
70  *           X11DRV_DIB_GetXImageWidthBytes
71  *
72  * Return the width of an X image in bytes
73  */
74 inline static int X11DRV_DIB_GetXImageWidthBytes( int width, int depth )
75 {
76     if (!depth || depth > 32) goto error;
77
78     if (!ximageDepthTable[depth-1])
79     {
80         XImage *testimage = XCreateImage( gdi_display, visual, depth,
81                                           ZPixmap, 0, NULL, 1, 1, 32, 20 );
82         if (testimage)
83         {
84             ximageDepthTable[depth-1] = testimage->bits_per_pixel;
85             XDestroyImage( testimage );
86         }
87         else ximageDepthTable[depth-1] = -1;
88     }
89     if (ximageDepthTable[depth-1] != -1)
90         return (4 * ((width * ximageDepthTable[depth-1] + 31) / 32));
91
92  error:
93     WARN( "(%d): Unsupported depth\n", depth );
94     return 4 * width;
95 }
96
97
98 /***********************************************************************
99  *           X11DRV_DIB_CreateXImage
100  *
101  * Create an X image.
102  */
103 XImage *X11DRV_DIB_CreateXImage( int width, int height, int depth )
104 {
105     int width_bytes;
106     XImage *image;
107
108     wine_tsx11_lock();
109     width_bytes = X11DRV_DIB_GetXImageWidthBytes( width, depth );
110     image = XCreateImage( gdi_display, visual, depth, ZPixmap, 0,
111                           calloc( height, width_bytes ),
112                           width, height, 32, width_bytes );
113     wine_tsx11_unlock();
114     return image;
115 }
116
117
118 /***********************************************************************
119  *           X11DRV_DIB_GenColorMap
120  *
121  * Fills the color map of a bitmap palette. Should not be called
122  * for a >8-bit deep bitmap.
123  */
124 int *X11DRV_DIB_GenColorMap( DC *dc, int *colorMapping,
125                              WORD coloruse, WORD depth, BOOL quads,
126                              const void *colorPtr, int start, int end )
127 {
128     int i;
129
130     if (coloruse == DIB_RGB_COLORS)
131     {
132         if (quads)
133         {
134             RGBQUAD * rgb = (RGBQUAD *)colorPtr;
135
136             if (depth == 1)  /* Monochrome */
137                 for (i = start; i < end; i++, rgb++)
138                     colorMapping[i] = (rgb->rgbRed + rgb->rgbGreen +
139                                        rgb->rgbBlue > 255*3/2);
140             else
141                 for (i = start; i < end; i++, rgb++)
142                     colorMapping[i] = X11DRV_PALETTE_ToPhysical( dc, RGB(rgb->rgbRed,
143                                                                 rgb->rgbGreen,
144                                                                 rgb->rgbBlue));
145         }
146         else
147         {
148             RGBTRIPLE * rgb = (RGBTRIPLE *)colorPtr;
149
150             if (depth == 1)  /* Monochrome */
151                 for (i = start; i < end; i++, rgb++)
152                     colorMapping[i] = (rgb->rgbtRed + rgb->rgbtGreen +
153                                        rgb->rgbtBlue > 255*3/2);
154             else
155                 for (i = start; i < end; i++, rgb++)
156                     colorMapping[i] = X11DRV_PALETTE_ToPhysical( dc, RGB(rgb->rgbtRed,
157                                                                rgb->rgbtGreen,
158                                                                rgb->rgbtBlue));
159         }
160     }
161     else  /* DIB_PAL_COLORS */
162     {
163         if (colorPtr) {
164             WORD * index = (WORD *)colorPtr;
165
166             for (i = start; i < end; i++, index++)
167                 colorMapping[i] = X11DRV_PALETTE_ToPhysical( dc, PALETTEINDEX(*index) );
168         } else {
169             for (i = start; i < end; i++)
170                 colorMapping[i] = X11DRV_PALETTE_ToPhysical( dc, PALETTEINDEX(i) );
171         }
172     }
173
174     return colorMapping;
175 }
176
177 /***********************************************************************
178  *           X11DRV_DIB_BuildColorMap
179  *
180  * Build the color map from the bitmap palette. Should not be called
181  * for a >8-bit deep bitmap.
182  */
183 int *X11DRV_DIB_BuildColorMap( DC *dc, WORD coloruse, WORD depth, 
184                                const BITMAPINFO *info, int *nColors )
185 {
186     int colors;
187     BOOL isInfo;
188     const void *colorPtr;
189     int *colorMapping;
190
191     if ((isInfo = (info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))))
192     {
193         colors = info->bmiHeader.biClrUsed;
194         if (!colors) colors = 1 << info->bmiHeader.biBitCount;
195         colorPtr = info->bmiColors;
196     }
197     else  /* assume BITMAPCOREINFO */
198     {
199         colors = 1 << ((BITMAPCOREHEADER *)&info->bmiHeader)->bcBitCount;
200         colorPtr = (WORD *)((BITMAPCOREINFO *)info)->bmciColors;
201     }
202
203     if (colors > 256)
204     {
205         ERR("called with >256 colors!\n");
206         return NULL;
207     }
208
209     /* just so CopyDIBSection doesn't have to create an identity palette */
210     if (coloruse == (WORD)-1) colorPtr = NULL;
211
212     if (!(colorMapping = (int *)HeapAlloc(GetProcessHeap(), 0,
213                                           colors * sizeof(int) ))) 
214         return NULL;
215
216     *nColors = colors;
217     return X11DRV_DIB_GenColorMap( dc, colorMapping, coloruse, depth,
218                                    isInfo, colorPtr, 0, colors);
219 }
220
221
222 /***********************************************************************
223  *           X11DRV_DIB_MapColor
224  */
225 int X11DRV_DIB_MapColor( int *physMap, int nPhysMap, int phys, int oldcol )
226 {
227     int color;
228
229     if ((oldcol < nPhysMap) && (physMap[oldcol] == phys))
230         return oldcol;
231
232     for (color = 0; color < nPhysMap; color++)
233         if (physMap[color] == phys)
234             return color;
235
236     WARN("Strange color %08x\n", phys);
237     return 0;
238 }
239
240
241 /*********************************************************************
242  *         X11DRV_DIB_GetNearestIndex
243  *
244  * Helper for X11DRV_DIB_GetDIBits.
245  * Returns the nearest colour table index for a given RGB.
246  * Nearest is defined by minimizing the sum of the squares.
247  */
248 static INT X11DRV_DIB_GetNearestIndex(RGBQUAD *colormap, int numColors, BYTE r, BYTE g, BYTE b)
249 {
250     INT i, best = -1, diff, bestdiff = -1;
251     RGBQUAD *color;
252
253     for(color = colormap, i = 0; i < numColors; color++, i++) {
254         diff = (r - color->rgbRed) * (r - color->rgbRed) +
255                (g - color->rgbGreen) * (g - color->rgbGreen) +
256                (b - color->rgbBlue) * (b - color->rgbBlue);
257         if(diff == 0)
258             return i;
259         if(best == -1 || diff < bestdiff) {
260             best = i;
261             bestdiff = diff;
262         }
263     }
264     return best;
265 }
266
267 /***********************************************************************
268  *           X11DRV_DIB_SetImageBits_1_Line
269  *
270  * Handles a single line of 1 bit data.
271  */
272 static void X11DRV_DIB_SetImageBits_1_Line(DWORD dstwidth, int left, int *colors,
273                                     XImage *bmpImage, int h, const BYTE *bits)
274 {
275     BYTE pix, extra;
276     DWORD i, x;
277
278     if((extra = (left & 7)) != 0) {
279         left &= ~7;
280         dstwidth += extra;
281     }
282
283     bits += left >> 3;
284
285     /* FIXME: should avoid putting x<left pixels (minor speed issue) */
286     for (i = dstwidth/8, x = left; i > 0; i--)
287     {
288         pix = *bits++;
289         XPutPixel( bmpImage, x++, h, colors[pix >> 7] );
290         XPutPixel( bmpImage, x++, h, colors[(pix >> 6) & 1] );
291         XPutPixel( bmpImage, x++, h, colors[(pix >> 5) & 1] );
292         XPutPixel( bmpImage, x++, h, colors[(pix >> 4) & 1] );
293         XPutPixel( bmpImage, x++, h, colors[(pix >> 3) & 1] );
294         XPutPixel( bmpImage, x++, h, colors[(pix >> 2) & 1] );
295         XPutPixel( bmpImage, x++, h, colors[(pix >> 1) & 1] );
296         XPutPixel( bmpImage, x++, h, colors[pix & 1] );
297     }
298     pix = *bits;
299     switch(dstwidth & 7)
300     {
301     case 7: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
302     case 6: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
303     case 5: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
304     case 4: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
305     case 3: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
306     case 2: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
307     case 1: XPutPixel( bmpImage, x++, h, colors[pix >> 7] );
308     }
309 }
310
311 /***********************************************************************
312  *           X11DRV_DIB_SetImageBits_1
313  *
314  * SetDIBits for a 1-bit deep DIB.
315  */
316 static void X11DRV_DIB_SetImageBits_1( int lines, const BYTE *srcbits,
317                                 DWORD srcwidth, DWORD dstwidth, int left,
318                                 int *colors, XImage *bmpImage, DWORD linebytes)
319 {
320     int h;
321
322     if (lines > 0) {
323         for (h = lines-1; h >=0; h--) {
324             X11DRV_DIB_SetImageBits_1_Line(dstwidth, left, colors, bmpImage, h,
325                                            srcbits);
326             srcbits += linebytes;
327         }
328     } else {
329         lines = -lines;
330         for (h = 0; h < lines; h++) {
331             X11DRV_DIB_SetImageBits_1_Line(dstwidth, left, colors, bmpImage, h,
332                                            srcbits);
333             srcbits += linebytes;
334         }
335     }
336 }
337
338 /***********************************************************************
339  *           X11DRV_DIB_GetImageBits_1
340  *
341  * GetDIBits for a 1-bit deep DIB.
342  */
343 static void X11DRV_DIB_GetImageBits_1( int lines, BYTE *dstbits,
344                                        DWORD dstwidth, DWORD srcwidth,
345                                        RGBQUAD *colors, PALETTEENTRY *srccolors, 
346                                 XImage *bmpImage, DWORD linebytes )
347 {
348     DWORD x;
349     int h;
350     BYTE *bits;
351
352     if (lines < 0 ) {
353         lines = -lines;
354         dstbits = dstbits + linebytes * (lines - 1);
355         linebytes = -linebytes;
356     }
357
358     bits = dstbits;
359
360     switch(bmpImage->depth) {
361
362     case 1:
363        /* ==== monochrome bitmap to monochrome dib ==== */
364     case 4:
365        /* ==== 4 colormap bitmap to monochrome dib ==== */
366        if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
367          { 
368            PALETTEENTRY val;
369
370            for (h = lines - 1; h >= 0; h--) {
371              for (x = 0; x < dstwidth; x++) {
372                val = srccolors[XGetPixel(bmpImage, x, h)];
373                if (!(x&7)) *bits = 0;
374                *bits |= (X11DRV_DIB_GetNearestIndex(colors, 2, 
375                                                     val.peRed,
376                                                     val.peGreen, 
377                                                     val.peBlue) << (7 - (x & 7)));
378                if ((x&7)==7) bits++;
379              }
380              bits = (dstbits += linebytes);
381            }
382          }
383        else goto notsupported;
384        
385        break;
386       
387     case 8:
388       /* ==== 8 colormap bitmap to monochrome dib ==== */
389       if ( bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
390       {
391         BYTE *srcpixel;
392         PALETTEENTRY val;
393
394        for( h = lines- 1; h >= 0; h-- ) {
395           srcpixel = bmpImage->data + (h*bmpImage->bytes_per_line);
396           for( x = 0; x < dstwidth; x++ ) {
397             if (!(x&7)) *bits = 0;
398             val = srccolors[(int)*srcpixel++];
399             *bits |= ( X11DRV_DIB_GetNearestIndex(colors, 2,
400                                                   val.peRed,
401                                                   val.peGreen,
402                                                   val.peBlue) << (7-(x&7)) );
403             if ((x&7)==7) bits++;
404           }
405           bits = (dstbits += linebytes);
406         }
407       }
408       else goto notsupported;
409
410       break;
411       
412     case 15:
413       {
414         LPWORD srcpixel;
415         WORD val;
416         
417         /* ==== 555 BGR bitmap to monochrome dib ==== */
418         if (bmpImage->red_mask == 0x7c00 && bmpImage->blue_mask == 0x1f)
419         {
420           for( h = lines - 1; h >= 0; h--) {
421                 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
422                 for( x = 0; x < dstwidth; x++) {
423                   if (!(x&7)) *bits = 0;
424                   val = *srcpixel++;
425                   *bits |= (X11DRV_DIB_GetNearestIndex( colors, 2, 
426                                                         ((val >> 7) & 0xf8) |
427                                                         ((val >> 12) & 0x7),
428                                                         ((val >> 2) & 0xf8) |
429                                                         ((val >> 7) & 0x3),
430                                                         ((val << 3) & 0xf8) |
431                                                         ((val >> 2) & 0x7) ) << (7-(x&7)) );
432                   if ((x&7)==7) bits++;
433                 }
434                 bits = (dstbits += linebytes);
435             }
436         }
437         /* ==== 555 RGB bitmap to monochrome dib ==== */
438         else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0xf800)
439         {
440             for( h = lines - 1; h >= 0; h--) 
441             {
442                 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
443                 for( x = 0; x < dstwidth; x++) {
444                   if (!(x&1)) *bits = 0;
445                   val = *srcpixel++;
446                   *bits |= (X11DRV_DIB_GetNearestIndex( colors, 2, 
447                                                         ((val << 3) & 0xf8) |
448                                                         ((val >> 2) & 0x7),
449                                                         ((val >> 2) & 0xf8) |
450                                                         ((val >> 7) & 0x3),
451                                                         ((val >> 7) & 0xf8) |
452                                                         ((val >> 12) &  0x7) ) << (7-(x&7)) );
453                   if ((x&7)==7) bits++;
454                 }
455                 bits = (dstbits += linebytes);
456             }
457         }
458         else goto notsupported;
459       }
460       break;
461  
462     case 16:
463       {
464         LPWORD srcpixel;
465         WORD val;
466
467         /* ==== 565 BGR bitmap to monochrome dib ==== */
468         if (bmpImage->red_mask == 0xf800 && bmpImage->blue_mask == 0x001f) 
469         {
470             for( h = lines - 1; h >= 0; h--) 
471             {
472                 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
473                 for( x = 0; x < dstwidth; x++) {
474                   if (!(x&7)) *bits = 0;
475                   val = *srcpixel++;
476                   *bits |= (X11DRV_DIB_GetNearestIndex( colors, 2, 
477                                                         ((val >> 8) & 0xf8) |
478                                                         ((val >> 13) & 0x7),
479                                                         ((val >> 3) & 0xfc) |
480                                                         ((val >> 9) & 0x3),
481                                                         ((val << 3) & 0xf8) |
482                                                         ((val >> 2) & 0x7) ) << (7-(x&7)) );
483                   if ((x&7)==7) bits++;
484                 }
485                 bits = (dstbits += linebytes);
486             }
487         }
488         /* ==== 565 RGB bitmap to monochrome dib ==== */
489         else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0xf800)
490         {
491             for( h = lines - 1; h >= 0; h--) 
492             {
493                 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
494                 for( x = 0; x < dstwidth; x++) {
495                   if (!(x&7)) *bits = 0;
496                   val = *srcpixel++;
497                   *bits |= (X11DRV_DIB_GetNearestIndex( colors, 2, 
498                                                         ((val << 3) & 0xf8) |
499                                                         ((val >> 2) & 0x7),
500                                                         ((val >> 3) & 0xfc) |
501                                                         ((val >> 9) & 0x3),
502                                                         ((val >> 8) & 0xf8) |
503                                                         ((val >> 13) &  0x7) ) << (7-(x&7)) );
504                   if ((x&7)==7) bits++;
505                 }
506                 bits = (dstbits += linebytes);
507             }
508         }
509         else goto notsupported;
510       }
511       break;
512       
513     case 24: 
514     case 32:
515       {
516         BYTE *srcpixel;
517         
518         /* ==== 24/32 BGR bitmap to monochrome dib ==== */
519         if (bmpImage->red_mask == 0xff0000 && bmpImage->blue_mask == 0xff)
520         {        
521           for (h = lines - 1; h >= 0; h--)
522           {
523             srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
524             for (x = 0; x < dstwidth; x++, srcpixel+=4) {
525               if (!(x&7)) *bits = 0;
526               *bits |= (X11DRV_DIB_GetNearestIndex(colors, 2, srcpixel[2] , srcpixel[1], srcpixel[0]) << (7-(x&7)) );
527               if ((x&7)==7) bits++;
528             }
529             bits = (dstbits += linebytes);
530           }
531         } 
532         /* ==== 24/32 RGB bitmap to monochrome dib ==== */
533         else if (bmpImage->red_mask == 0xff && bmpImage->blue_mask == 0xff0000)
534         {
535           for (h = lines - 1; h >= 0; h--)
536           {
537             srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
538             for (x = 0; x < dstwidth; x++, srcpixel+=4) { 
539                        if (!(x & 7)) *bits = 0;
540                        *bits |= (X11DRV_DIB_GetNearestIndex(colors, 2, srcpixel[0] , srcpixel[1], srcpixel[2]) << (7-(x&7)) );
541                        if ((x & 7) == 7) bits++;
542             }
543             bits = (dstbits += linebytes);
544           }
545         }
546         else goto notsupported;
547       }
548       break;
549
550     default: /* ? bit bmp -> monochrome DIB */
551     notsupported:
552       {
553         unsigned long white = (1 << bmpImage->bits_per_pixel) - 1;
554
555         FIXME("from %d bit bitmap with mask R,G,B %x,%x,%x to 1 bit DIB\n",
556               bmpImage->bits_per_pixel, (int)bmpImage->red_mask, 
557               (int)bmpImage->green_mask, (int)bmpImage->blue_mask );
558       
559         for( h = lines - 1; h >= 0; h-- ) {
560           for( x = 0; x < dstwidth; x++ ) {
561             if (!(x&7)) *bits = 0;
562             *bits |= (XGetPixel( bmpImage, x, h) >= white) 
563               << (7 - (x&7));
564             if ((x&7)==7) bits++;
565           }
566           bits = (dstbits += linebytes);
567         }
568       }
569       break;
570     }
571 }
572
573 /***********************************************************************
574  *           X11DRV_DIB_SetImageBits_4
575  *
576  * SetDIBits for a 4-bit deep DIB.
577  */
578 static void X11DRV_DIB_SetImageBits_4( int lines, const BYTE *srcbits,
579                                 DWORD srcwidth, DWORD dstwidth, int left,
580                                 int *colors, XImage *bmpImage, DWORD linebytes)
581 {
582     DWORD i, x;
583     int h;
584     const BYTE *bits = srcbits + (left >> 1);
585   
586     if(left & 1) {
587         left--;
588         dstwidth++;
589     }
590
591     if (lines > 0) {
592         for (h = lines-1; h >= 0; h--) {
593             for (i = dstwidth/2, x = left; i > 0; i--) {
594                 BYTE pix = *bits++;
595                 XPutPixel( bmpImage, x++, h, colors[pix >> 4] );
596                 XPutPixel( bmpImage, x++, h, colors[pix & 0x0f] );
597             }
598             if (dstwidth & 1) XPutPixel( bmpImage, x, h, colors[*bits >> 4] );
599             srcbits += linebytes;
600             bits         = srcbits + (left >> 1);
601         }
602     } else {
603         lines = -lines;
604         for (h = 0; h < lines; h++) {
605             for (i = dstwidth/2, x = left; i > 0; i--) {
606                 BYTE pix = *bits++;
607                 XPutPixel( bmpImage, x++, h, colors[pix >> 4] );
608                 XPutPixel( bmpImage, x++, h, colors[pix & 0x0f] );
609             }
610             if (dstwidth & 1) XPutPixel( bmpImage, x, h, colors[*bits >> 4] );
611             srcbits += linebytes;
612             bits         = srcbits + (left >> 1);
613         }
614     }
615 }
616
617
618
619 /***********************************************************************
620  *           X11DRV_DIB_GetImageBits_4
621  *
622  * GetDIBits for a 4-bit deep DIB.
623  */
624 static void X11DRV_DIB_GetImageBits_4( int lines, BYTE *dstbits,
625                                        DWORD srcwidth, DWORD dstwidth,
626                                        RGBQUAD *colors, PALETTEENTRY *srccolors, 
627                                        XImage *bmpImage, DWORD linebytes )
628 {
629     DWORD x;
630     int h;
631     BYTE *bits;
632     LPBYTE srcpixel;
633
634     if (lines < 0 )
635     {
636        lines = -lines;
637        dstbits = dstbits + ( linebytes * (lines-1) );
638        linebytes = -linebytes;
639     }
640
641     bits = dstbits;
642
643     switch(bmpImage->depth) {
644
645      case 1:
646         /* ==== monochrome bitmap to 4 colormap dib ==== */
647      case 4:
648        /* ==== 4 colormap bitmap to 4 colormap dib ==== */
649        if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
650          {
651            PALETTEENTRY val;
652            
653        for (h = lines-1; h >= 0; h--) {
654              for (x = 0; x < dstwidth; x++) {
655                if (!(x&1)) *bits = 0;
656                val = srccolors[XGetPixel(bmpImage, x, h)];
657                *bits |= (X11DRV_DIB_GetNearestIndex(colors, 16, 
658                                                     val.peRed,
659                                                     val.peGreen, 
660                                                     val.peBlue) << (4-((x&1)<<2)));
661                if ((x&1)==1) bits++;
662            }
663              bits = (dstbits += linebytes);
664        }
665          }
666        else goto notsupported;
667        
668        break;
669       
670     case 8:
671       /* ==== 8 colormap bitmap to 4 colormap dib ==== */
672       if ( bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
673       {
674         PALETTEENTRY val;
675
676         for( h = lines - 1; h >= 0; h-- ) {
677           srcpixel = bmpImage->data + (h*bmpImage->bytes_per_line);
678           for( x = 0; x < dstwidth; x++ ) {
679             if (!(x&1)) *bits = 0;
680             val = srccolors[(int)*srcpixel++];
681             *bits |= ( X11DRV_DIB_GetNearestIndex(colors, 16,
682                                                   val.peRed,
683                                                   val.peGreen,
684                                                   val.peBlue) << (4*(1-(x&1))) );
685             if ((x&1)==1) bits++;
686           }
687           bits = (dstbits += linebytes);
688         }
689       }
690       else goto notsupported;
691
692       break;
693       
694     case 15:
695       {
696         LPWORD srcpixel;
697         WORD val;
698         
699         /* ==== 555 BGR bitmap to 4 colormap dib ==== */
700         if (bmpImage->red_mask == 0x7c00 && bmpImage->blue_mask == 0x1f)
701         {
702           for( h = lines - 1; h >= 0; h--) {
703                 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
704                 for( x = 0; x < dstwidth; x++) {
705                   if (!(x&1)) *bits = 0;
706                   val = *srcpixel++;
707                   *bits |= (X11DRV_DIB_GetNearestIndex( colors, 16, 
708                                                         ((val >> 7) & 0xf8) |
709                                                         ((val >> 12) & 0x7),
710                                                         ((val >> 2) & 0xf8) |
711                                                         ((val >> 7) & 0x3),
712                                                         ((val << 3) & 0xf8) |
713                                                         ((val >> 2) & 0x7) ) << ((1-(x&1))<<2) );
714                   if ((x&1)==1) bits++;
715                 }
716                 bits = (dstbits += linebytes);
717             }
718         }
719         /* ==== 555 RGB bitmap to 4 colormap dib ==== */
720         else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0x7c00)
721         {
722             for( h = lines - 1; h >= 0; h--) 
723             {
724                 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
725                 for( x = 0; x < dstwidth; x++) {
726                   if (!(x&1)) *bits = 0;
727                   val = *srcpixel++;
728                   *bits |= (X11DRV_DIB_GetNearestIndex( colors, 16, 
729                                                         ((val << 3) & 0xf8) |
730                                                         ((val >> 2) & 0x7),
731                                                         ((val >> 2) & 0xfc) |
732                                                         ((val >> 7) & 0x3),
733                                                         ((val >> 7) & 0xf8) |
734                                                         ((val >> 12) &  0x7) ) << ((1-(x&1))<<2) );
735                   if ((x&1)==1) bits++;
736                 }
737                 bits = (dstbits += linebytes);
738             }
739         }
740         else goto notsupported;
741       }
742       break;
743  
744     case 16:
745       {
746         LPWORD srcpixel;
747         WORD val;
748
749         /* ==== 565 BGR bitmap to 4 colormap dib ==== */
750         if (bmpImage->red_mask == 0xf800 && bmpImage->blue_mask == 0x001f) 
751         {
752             for( h = lines - 1; h >= 0; h--) 
753             {
754                 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
755                 for( x = 0; x < dstwidth; x++) {
756                   if (!(x&1)) *bits = 0;
757                   val = *srcpixel++;
758                   *bits |= (X11DRV_DIB_GetNearestIndex( colors, 16, 
759                                                         ((val >> 8) & 0xf8) |
760                                                         ((val >> 13) & 0x7),
761                                                         ((val >> 3) & 0xfc) |
762                                                         ((val >> 9) & 0x3),
763                                                         ((val << 3) & 0xf8) |
764                                                         ((val >> 2) & 0x7) )  << ((1-(x&1))<<2) );
765                   if ((x&1)==1) bits++;
766                 }
767                 bits = (dstbits += linebytes);
768             }
769         }
770         /* ==== 565 RGB bitmap to 4 colormap dib ==== */
771         else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0xf800)
772         {
773             for( h = lines - 1; h >= 0; h--) 
774             {
775                 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
776                 for( x = 0; x < dstwidth; x++) {
777                   if (!(x&1)) *bits = 0;
778                   val = *srcpixel++;
779                   *bits |= (X11DRV_DIB_GetNearestIndex( colors, 16, 
780                                                         ((val << 3) & 0xf8) |
781                                                         ((val >> 2) & 0x7),
782                                                         ((val >> 3) & 0xfc) |
783                                                         ((val >> 9) & 0x3),
784                                                         ((val >> 8) & 0xf8) |
785                                                         ((val >> 13) &  0x7) ) << ((1-(x&1))<<2) );
786                   if ((x&1)==1) bits++;
787                 }
788                 bits = (dstbits += linebytes);
789             }
790         }
791         else goto notsupported;
792       }
793       break;
794       
795     case 24: 
796     case 32:
797       {
798         BYTE *srcpixel;
799         
800         /* ==== 24/32 BGR bitmap to 4 colormap dib ==== */
801         if (bmpImage->red_mask == 0xff0000 && bmpImage->blue_mask == 0xff)
802         {        
803           for (h = lines - 1; h >= 0; h--)
804           {
805             srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
806             for (x = 0; x < dstwidth; x+=2, srcpixel+=8) /* 2 pixels at a time */
807               *bits++ = (X11DRV_DIB_GetNearestIndex(colors, 16, srcpixel[2] , srcpixel[1], srcpixel[0]) << 4) |
808                          X11DRV_DIB_GetNearestIndex(colors, 16, srcpixel[6] , srcpixel[5], srcpixel[4]);
809             bits = (dstbits += linebytes);
810           }
811         } 
812         /* ==== 24/32 RGB bitmap to 4 colormap dib ==== */
813         else if (bmpImage->red_mask == 0xff && bmpImage->blue_mask == 0xff0000)
814         {
815           for (h = lines - 1; h >= 0; h--)
816           {
817             srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
818             for (x = 0; x < dstwidth; x+=2, srcpixel+=8) /* 2 pixels at a time */
819               *bits++ = (X11DRV_DIB_GetNearestIndex(colors, 16, srcpixel[0] , srcpixel[1], srcpixel[2]) << 4) |
820                          X11DRV_DIB_GetNearestIndex(colors, 16, srcpixel[4] , srcpixel[5], srcpixel[6]);
821             bits = (dstbits += linebytes);
822           }
823         }
824         else goto notsupported;
825       }
826       break;
827
828     default: /* ? bit bmp -> 4 bit DIB */
829     notsupported:
830       FIXME("from %d bit bitmap with mask R,G,B %x,%x,%x to 4 bit DIB\n",
831             bmpImage->bits_per_pixel, (int)bmpImage->red_mask, 
832             (int)bmpImage->green_mask, (int)bmpImage->blue_mask );
833       for (h = lines-1; h >= 0; h--) {
834           for (x = 0; x < dstwidth-1; x += 2)
835           {
836               *bits++ = (X11DRV_DIB_MapColor((int *)colors, 16, XGetPixel( bmpImage, x, h ), 0) << 4)
837                   | (X11DRV_DIB_MapColor((int *)colors, 16, XGetPixel( bmpImage, x+1, h ), 0) & 0x0f);
838           }
839           if (dstwidth & 1)
840               *bits = (X11DRV_DIB_MapColor((int *)colors, 16, XGetPixel( bmpImage, x, h ), 0) << 4);
841           bits = (dstbits += linebytes);
842        }
843       break;
844     }
845 }
846
847 /***********************************************************************
848  *           X11DRV_DIB_SetImageBits_RLE4
849  *
850  * SetDIBits for a 4-bit deep compressed DIB.
851  */
852 static void X11DRV_DIB_SetImageBits_RLE4( int lines, const BYTE *bits,
853                                           DWORD width, DWORD dstwidth,
854                                           int left, int *colors,
855                                           XImage *bmpImage )
856 {
857     int x = 0, c, length;
858     const BYTE *begin = bits;
859
860     lines--;
861
862     while ((int)lines >= 0) {
863         length = *bits++;
864         if (length) {   /* encoded */
865             c = *bits++;
866             while (length--) {
867                 if(x >= width) {
868                     x = 0;
869                     if(--lines < 0)
870                         return;
871                 }
872                 XPutPixel(bmpImage, x++, lines, colors[c >>4]);
873                 if (length) {
874                     length--;
875                     if(x >= width) {
876                         x = 0;
877                         if(--lines < 0)
878                             return;
879                     }
880                     XPutPixel(bmpImage, x++, lines, colors[c & 0xf]);
881                 }
882             }
883         } else {
884             length = *bits++;
885             switch (length) {
886             case 0: /* eol */
887                 x = 0;
888                 lines--;
889                 continue;
890
891             case 1: /* eopicture */
892                 return;
893
894             case 2: /* delta */
895                 x += *bits++;
896                 if(x >= width) {
897                    FIXME_(x11drv)("x-delta is too large?\n");
898                    return;
899                 }
900                 lines -= *bits++;
901                 continue;
902
903             default: /* absolute */
904                 while (length--) {
905                     c = *bits++;
906                     if(x >= width) {
907                         x = 0;
908                         if(--lines < 0)
909                             return;
910                     }
911                     XPutPixel(bmpImage, x++, lines, colors[c >> 4]);
912                     if (length) {
913                         length--;
914                         if(x >= width) {
915                             x = 0;
916                             if(--lines < 0)
917                                 return;
918                         }
919                         XPutPixel(bmpImage, x++, lines, colors[c & 0xf]);
920                     }
921                 }
922                 if ((bits - begin) & 1)
923                     bits++;
924             }
925         }
926     }
927 }
928
929
930
931 /***********************************************************************
932  *           X11DRV_DIB_SetImageBits_8
933  *
934  * SetDIBits for an 8-bit deep DIB.
935  */
936 static void X11DRV_DIB_SetImageBits_8( int lines, const BYTE *srcbits,
937                                 DWORD srcwidth, DWORD dstwidth, int left,
938                                 const int *colors, XImage *bmpImage,
939                                 DWORD linebytes )
940 {
941     DWORD x;
942     int h, color;
943     const BYTE *bits;
944
945     dstwidth += left;
946
947     if (lines < 0 )
948     {
949         lines = -lines;
950         srcbits = srcbits + ( linebytes * (lines-1) );
951         linebytes = -linebytes;
952     }
953
954     bits = srcbits + left;
955
956     switch (bmpImage->depth) {
957     case 15:
958     case 16:
959 #if defined(__i386__) && defined(__GNUC__)
960         /* Some X servers might have 32 bit/ 16bit deep pixel */
961         if (lines && (dstwidth!=left) && (bmpImage->bits_per_pixel == 16))
962         {
963             for (h = lines ; h--; ) {
964                 int _cl1,_cl2; /* temp outputs for asm below */
965                 /* Borrowed from DirectDraw */
966                 __asm__ __volatile__(
967                 "xor %%eax,%%eax\n"
968                 "cld\n"
969                 "1:\n"
970                 "    lodsb\n"
971                 "    movw (%%edx,%%eax,4),%%ax\n"
972                 "    stosw\n"
973                 "      xor %%eax,%%eax\n"
974                 "    loop 1b\n"
975                 :"=S" (bits), "=D" (_cl1), "=c" (_cl2)
976                 :"S" (bits),
977                  "D" (bmpImage->data+h*bmpImage->bytes_per_line+left*2),
978                  "c" (dstwidth-left),
979                  "d" (colors)
980                 :"eax", "cc", "memory"
981                 );
982                 bits = (srcbits += linebytes) + left;
983             }
984             return;
985         }
986         break;
987 #endif
988     case 24:
989 #if defined(__i386__) && defined(__GNUC__)
990         if (lines && (dstwidth!=left) && (bmpImage->bits_per_pixel == 32))
991         {
992             for (h = lines ; h--; ) {
993                 int _cl1,_cl2; /* temp outputs for asm below */
994                 /* Borrowed from DirectDraw */
995                 __asm__ __volatile__(
996                 "xor %%eax,%%eax\n"
997                 "cld\n"
998                 "1:\n"
999                 "    lodsb\n"
1000                 "    movl (%%edx,%%eax,4),%%eax\n"
1001                 "    stosl\n"
1002                 "      xor %%eax,%%eax\n"
1003                 "    loop 1b\n"
1004                 :"=S" (bits), "=D" (_cl1), "=c" (_cl2)
1005                 :"S" (bits),
1006                  "D" (bmpImage->data+h*bmpImage->bytes_per_line+left*4),
1007                  "c" (dstwidth-left),
1008                  "d" (colors)
1009                 :"eax", "cc", "memory"
1010                 );
1011                 bits = (srcbits += linebytes) + left;
1012             }
1013             return;
1014         }
1015         break;
1016 #endif
1017     default:
1018         break; /* use slow generic case below */
1019     }
1020
1021     for (h = lines - 1; h >= 0; h--) {
1022         for (x = left; x < dstwidth; x++, bits++) {
1023             color = colors[*bits];          
1024             XPutPixel( bmpImage, x, h, colors[*bits] );
1025         }
1026         bits = (srcbits += linebytes) + left;
1027     }
1028 }
1029
1030 /***********************************************************************
1031  *           X11DRV_DIB_GetImageBits_8
1032  *
1033  * GetDIBits for an 8-bit deep DIB.
1034  */
1035 static void X11DRV_DIB_GetImageBits_8( int lines, BYTE *dstbits,
1036                                        DWORD srcwidth, DWORD dstwidth,
1037                                        RGBQUAD *colors, PALETTEENTRY *srccolors, 
1038                                        XImage *bmpImage, DWORD linebytes )
1039 {
1040     DWORD x;
1041     int h;
1042     BYTE *bits;
1043
1044     if (lines < 0 )
1045     {
1046        lines = -lines;
1047        dstbits = dstbits + ( linebytes * (lines-1) );
1048        linebytes = -linebytes;
1049     }
1050
1051     bits = dstbits;
1052
1053     /* 
1054        Hack for now 
1055        This condition is true when GetImageBits has been called by UpdateDIBSection.
1056        For now, GetNearestIndex is too slow to support 256 colormaps, so we'll just use for
1057        for GetDIBits calls. (In somes cases, in a updateDIBSection, the returned colors are bad too)
1058     */
1059     if (!srccolors) goto updatesection;
1060
1061     switch(bmpImage->depth) {
1062
1063     case 1:
1064         /* ==== monochrome bitmap to 8 colormap dib ==== */
1065     case 4:
1066        /* ==== 4 colormap bitmap to 8 colormap dib ==== */
1067        if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
1068          {
1069            PALETTEENTRY val;
1070
1071     for (h = lines - 1; h >= 0; h--) {
1072              for (x = 0; x < dstwidth; x++) {
1073                val = srccolors[XGetPixel(bmpImage, x, h)];
1074                *bits++ = X11DRV_DIB_GetNearestIndex(colors, 256, val.peRed,
1075                                                     val.peGreen, val.peBlue);
1076              }
1077              bits = (dstbits += linebytes);
1078            }
1079          }
1080        else goto notsupported;
1081        
1082        break;
1083     
1084      case 8:
1085        /* ==== 8 colormap bitmap to 8 colormap dib ==== */
1086        if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
1087          {
1088            BYTE *srcpixel;
1089            PALETTEENTRY val;
1090            
1091            for (h = lines - 1; h >= 0; h--) {
1092              srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
1093              for (x = 0; x < dstwidth; x++) {
1094                val = srccolors[(int)*srcpixel++];
1095                *bits++ = X11DRV_DIB_GetNearestIndex(colors, 256, val.peRed, 
1096                                                     val.peGreen, val.peBlue);
1097              }
1098              bits = (dstbits += linebytes);
1099            }
1100          }
1101        else goto notsupported;
1102        
1103        break;
1104
1105       case 15:
1106       {
1107         LPWORD srcpixel;
1108         WORD val;
1109         
1110         /* ==== 555 BGR bitmap to 8 colormap dib ==== */
1111         if (bmpImage->red_mask == 0x7c00 && bmpImage->blue_mask == 0x001f)
1112         {
1113             for( h = lines - 1; h >= 0; h--) 
1114             {
1115                 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
1116                 for( x = 0; x < dstwidth; x++ )
1117                 {
1118                   val = *srcpixel++;
1119                   *bits++ = X11DRV_DIB_GetNearestIndex( colors, 256, 
1120                                                         ((val >> 7) & 0xf8) |
1121                                                         ((val >> 12) & 0x7),
1122                                                         ((val >> 2) & 0xf8) |
1123                                                         ((val >> 7) & 0x3),
1124                                                         ((val << 3) & 0xf8) |
1125                                                         ((val >> 2) & 0x7) );
1126                 }
1127                 bits = (dstbits += linebytes);
1128             }
1129         }
1130         /* ==== 555 RGB bitmap to 8 colormap dib ==== */
1131         else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0x7c00)
1132         {
1133             for( h = lines - 1; h >= 0; h--) 
1134             {
1135                 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
1136                 for( x = 0; x < dstwidth; x++ )
1137                 {
1138                   val = *srcpixel++;
1139                   *bits++ = X11DRV_DIB_GetNearestIndex( colors, 256, 
1140                                                         ((val << 3) & 0xf8) |
1141                                                         ((val >> 2) & 0x7),
1142                                                         ((val >> 2) & 0xf8) |
1143                                                         ((val >> 7) & 0x3),
1144                                                         ((val >> 7) & 0xf8) |
1145                                                         ((val >> 12) &  0x7) );
1146                 }
1147                 bits = (dstbits += linebytes);
1148             }
1149         }
1150         else goto notsupported;
1151       }
1152       break;
1153
1154       case 16:
1155       {
1156         LPWORD srcpixel;
1157         WORD val;
1158         
1159         /* ==== 565 BGR bitmap to 8 colormap dib ==== */
1160         if (bmpImage->red_mask == 0xf800 && bmpImage->blue_mask == 0x001f)
1161         {
1162             for( h = lines - 1; h >= 0; h--) 
1163             {
1164                 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
1165                 for( x = 0; x < dstwidth; x++ )
1166                 {
1167                   val = *srcpixel++;
1168                   *bits++ = X11DRV_DIB_GetNearestIndex( colors, 256, 
1169                                                         ((val >> 8) & 0xf8) |
1170                                                         ((val >> 13) & 0x7),
1171                                                         ((val >> 3) & 0xfc) |
1172                                                         ((val >> 9) & 0x3),
1173                                                         ((val << 3) & 0xf8) |
1174                                                         ((val >> 2) & 0x7) );
1175                 }
1176                 bits = (dstbits += linebytes);
1177             }
1178         }
1179         /* ==== 565 RGB bitmap to 8 colormap dib ==== */
1180         else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0xf800)
1181         {
1182             for( h = lines - 1; h >= 0; h--) 
1183             {
1184                 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
1185                 for( x = 0; x < dstwidth; x++ )
1186                 {
1187                   val = *srcpixel++;
1188                   *bits++ = X11DRV_DIB_GetNearestIndex( colors, 256, 
1189                                                         ((val << 3) & 0xf8) |
1190                                                         ((val >> 2) & 0x7),
1191                                                         ((val >> 3) & 0x00fc) |
1192                                                         ((val >> 9) & 0x3),
1193                                                         ((val >> 8) & 0x00f8) |
1194                                                         ((val >> 13) &  0x7) );
1195                 }
1196                 bits = (dstbits += linebytes);
1197             }
1198         }
1199         else goto notsupported;
1200       }
1201       break;
1202       
1203       case 24: 
1204       case 32:
1205       {
1206         BYTE *srcpixel;
1207         
1208         /* ==== 24/32 BGR bitmap to 8 colormap dib ==== */
1209         if (bmpImage->red_mask == 0xff0000 && bmpImage->blue_mask == 0xff)
1210         {
1211           for (h = lines - 1; h >= 0; h--)
1212             {
1213               srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
1214               for (x = 0; x < dstwidth; x++, srcpixel+=4)
1215                 *bits++ = X11DRV_DIB_GetNearestIndex(colors, 256, 
1216                                                      srcpixel[2] , srcpixel[1], *srcpixel);
1217               bits = (dstbits += linebytes);
1218             }
1219         }
1220         /* ==== 24/32 RGB bitmap to 8 colormap dib ==== */
1221         else if (bmpImage->red_mask == 0xff && bmpImage->blue_mask == 0xff0000)
1222         {
1223           for (h = lines - 1; h >= 0; h--)
1224             {
1225               srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
1226               for (x = 0; x < dstwidth; x++, srcpixel+=4)
1227                 *bits++ = X11DRV_DIB_GetNearestIndex(colors, 256, 
1228                                                      *srcpixel, srcpixel[1], srcpixel[2]);
1229               bits = (dstbits += linebytes);
1230             }
1231           
1232         }
1233         else goto notsupported;
1234       }
1235       break;
1236
1237     default: /* ? bit bmp -> 8 bit DIB */
1238     notsupported:
1239       FIXME("from %d bit bitmap with mask R,G,B %x,%x,%x to 8 bit DIB\n",
1240             bmpImage->depth, (int)bmpImage->red_mask, 
1241             (int)bmpImage->green_mask, (int)bmpImage->blue_mask );
1242     updatesection:
1243       for (h = lines - 1; h >= 0; h--) {
1244         for (x = 0; x < dstwidth; x++, bits++) {
1245           *bits = X11DRV_DIB_MapColor((int *)colors, 256,
1246                                          XGetPixel( bmpImage, x, h ), *bits);
1247         }
1248         bits = (dstbits += linebytes);
1249       }
1250       break;
1251     }
1252 }
1253
1254 /***********************************************************************
1255  *            X11DRV_DIB_SetImageBits_RLE8
1256  *
1257  * SetDIBits for an 8-bit deep compressed DIB.
1258  *
1259  * This function rewritten 941113 by James Youngman.  WINE blew out when I
1260  * first ran it because my desktop wallpaper is a (large) RLE8 bitmap.  
1261  *
1262  * This was because the algorithm assumed that all RLE8 bitmaps end with the  
1263  * 'End of bitmap' escape code.  This code is very much laxer in what it
1264  * allows to end the expansion.  Possibly too lax.  See the note by 
1265  * case RleDelta.  BTW, MS's documentation implies that a correct RLE8
1266  * bitmap should end with RleEnd, but on the other hand, software exists 
1267  * that produces ones that don't and Windows 3.1 doesn't complain a bit
1268  * about it.
1269  *
1270  * (No) apologies for my English spelling.  [Emacs users: c-indent-level=4].
1271  *                      James A. Youngman <mbcstjy@afs.man.ac.uk>
1272  *                                              [JAY]
1273  */
1274
1275 enum Rle8_EscapeCodes           
1276 {
1277   /* 
1278    * Apologies for polluting your file's namespace...
1279    */
1280   RleEol        = 0,            /* End of line */
1281   RleEnd        = 1,            /* End of bitmap */
1282   RleDelta      = 2             /* Delta */
1283 };
1284   
1285 static void X11DRV_DIB_SetImageBits_RLE8( int lines, const BYTE *bits,
1286                                           DWORD width, DWORD dstwidth,
1287                                           int left, int *colors,
1288                                           XImage *bmpImage )
1289 {
1290     int x;                      /* X-positon on each line.  Increases. */
1291     int line;                   /* Line #.  Starts at lines-1, decreases */
1292     const BYTE *pIn = bits;     /* Pointer to current position in bits */
1293     BYTE length;                /* The length pf a run */
1294     BYTE color_index;           /* index into colors[] as read from bits */
1295     BYTE escape_code;           /* See enum Rle8_EscapeCodes.*/
1296     int color;                  /* value of colour[color_index] */
1297     
1298     if (lines == 0)             /* Let's hope this doesn't happen. */
1299       return;
1300     
1301     /*
1302      * Note that the bitmap data is stored by Windows starting at the
1303      * bottom line of the bitmap and going upwards.  Within each line,
1304      * the data is stored left-to-right.  That's the reason why line
1305      * goes from lines-1 to 0.                  [JAY]
1306      */
1307     
1308     x = 0;
1309     line = lines-1;
1310     do
1311       {
1312           length = *pIn++;
1313           
1314           /* 
1315            * If the length byte is not zero (which is the escape value),
1316            * We have a run of length pixels all the same colour.  The colour 
1317            * index is stored next. 
1318            *
1319            * If the length byte is zero, we need to read the next byte to
1320            * know what to do.                   [JAY]
1321            */
1322           if (length != 0) 
1323             {                                   
1324                 /* 
1325                  * [Run-Length] Encoded mode 
1326                  */
1327                 color_index = (*pIn++); /* Get the colour index. */
1328                 color = colors[color_index];
1329
1330                 while(length--)
1331                   {
1332                     if (x>=dstwidth)
1333                       {
1334                         x=0;
1335                         line--;
1336                       }
1337                     XPutPixel(bmpImage, x++, line, color);
1338                   }
1339             }
1340           else 
1341             {    
1342                 /* 
1343                  * Escape codes (may be an absolute sequence though)
1344                  */
1345                 escape_code = (*pIn++);
1346                 switch(escape_code)
1347                   {
1348                     case RleEol: /* =0, end of line */
1349                       {
1350                           x = 0;  
1351                           line--;  
1352                           break;
1353                       }
1354                       
1355                     case RleEnd: /* =1, end of bitmap */
1356                       {
1357                           /*
1358                            * Not all RLE8 bitmaps end with this 
1359                            * code.  For example, Paint Shop Pro 
1360                            * produces some that don't.  That's (I think)
1361                            * what caused the previous implementation to 
1362                            * fail.                      [JAY]
1363                            */
1364                           line=-1; /* Cause exit from do loop. */
1365                           break;
1366                       }
1367                       
1368                     case RleDelta: /* =2, a delta */
1369                       {
1370                           /* 
1371                            * Note that deltaing to line 0 
1372                            * will cause an exit from the loop, 
1373                            * which may not be what is intended. 
1374                            * The fact that there is a delta in the bits
1375                            * almost certainly implies that there is data
1376                            * to follow.  You may feel that we should 
1377                            * jump to the top of the loop to avoid exiting
1378                            * in this case.  
1379                            *
1380                            * TODO: Decide what to do here in that case. [JAY]
1381                            */
1382                           x     += (*pIn++); 
1383                           line  -= (*pIn++);
1384                           if (line == 0)
1385                             {
1386                               TRACE("Delta to last line of bitmap "
1387                                     "(wrongly?) causes loop exit\n");
1388                             }
1389                           break;
1390                       }
1391                       
1392                     default:    /* >2, switch to absolute mode */
1393                       {
1394                           /* 
1395                            * Absolute Mode 
1396                            */
1397                           length = escape_code;
1398                           while(length--)
1399                             {
1400                                 color_index = (*pIn++);
1401                                 if (x>=dstwidth)
1402                                   {
1403                                     x=0;
1404                                     line--;
1405                                   }
1406                                 XPutPixel(bmpImage, x++, line, 
1407                                           colors[color_index]);
1408                             }
1409                           
1410                           /*
1411                            * If you think for a moment you'll realise that the
1412                            * only time we could ever possibly read an odd
1413                            * number of bytes is when there is a 0x00 (escape),
1414                            * a value >0x02 (absolute mode) and then an odd-
1415                            * length run.  Therefore this is the only place we
1416                            * need to worry about it.  Everywhere else the
1417                            * bytes are always read in pairs.  [JAY]
1418                            */
1419                           if (escape_code & 1) 
1420                             pIn++; /* Throw away the pad byte. */
1421                           break;
1422                       }
1423                   } /* switch (escape_code) : Escape sequence */
1424             }  /* process either an encoded sequence or an escape sequence */
1425           
1426           /* We expect to come here more than once per line. */
1427       } while (line >= 0);  /* Do this until the bitmap is filled */
1428     
1429     /*
1430      * Everybody comes here at the end.
1431      * Check how we exited the loop and print a message if it's a bit odd.
1432      *                                          [JAY]
1433      */
1434     if ( (*(pIn-2) != 0/*escape*/) || (*(pIn-1)!= RleEnd) )
1435       {
1436         TRACE("End-of-bitmap without (strictly) proper escape code.  Last two "
1437               "bytes were: %02X %02X.\n", (int)*(pIn-2),(int)*(pIn-1));
1438       }
1439 }  
1440
1441
1442 /***********************************************************************
1443  *           X11DRV_DIB_SetImageBits_16
1444  *
1445  * SetDIBits for a 16-bit deep DIB.
1446  */
1447 static void X11DRV_DIB_SetImageBits_16( int lines, const BYTE *srcbits,
1448                                  DWORD srcwidth, DWORD dstwidth, int left,
1449                                        DC *dc, DWORD rSrc, DWORD gSrc, DWORD bSrc,
1450                                        XImage *bmpImage, DWORD linebytes )
1451 {
1452     DWORD x;
1453     int h;
1454   
1455     if (lines < 0 )
1456     {
1457         lines = -lines;
1458         srcbits = srcbits + ( linebytes * (lines-1));
1459         linebytes = -linebytes;
1460     }
1461         
1462     switch ( bmpImage->depth )
1463     {
1464         case 15:
1465             /* using same format as XImage */
1466             if (rSrc == bmpImage->red_mask && gSrc == bmpImage->green_mask && bSrc == bmpImage->blue_mask)
1467                 for (h = lines - 1; h >= 0; h--, srcbits += linebytes)
1468                     memcpy ( bmpImage->data + h * bmpImage->bytes_per_line + left*2, srcbits + left*2, dstwidth*2 );
1469             else     /* We need to do a conversion from a 565 dib */
1470             {
1471                 LPDWORD dstpixel, ptr = (LPDWORD)(srcbits + left*2);
1472                 DWORD val;
1473                 int div = dstwidth % 2;
1474
1475                 for (h = lines - 1; h >= 0; h--) {
1476                     dstpixel = (LPDWORD) (bmpImage->data + h * bmpImage->bytes_per_line + left*2);
1477                     for (x = 0; x < dstwidth/2; x++) { /* Do 2 pixels at a time */
1478                         val = *ptr++;
1479                         *dstpixel++ =   ((val >> 1) & 0x7fe07fe0) | (val & 0x001f001f); /* Red & Green & Blue */
1480                     }
1481                     if (div != 0) /* Odd width? */
1482                         *dstpixel = ((*(WORD *)ptr >> 1) & 0x7fe0) | (*(WORD *)ptr & 0x001f);
1483                     ptr = (LPDWORD) ((srcbits += linebytes) + left*2);
1484                 }
1485             }
1486             break;
1487
1488         case 16:
1489             /* using same format as XImage */
1490             if (rSrc == bmpImage->red_mask && gSrc == bmpImage->green_mask && bSrc == bmpImage->blue_mask)
1491                 for (h = lines - 1; h >= 0; h--, srcbits += linebytes)
1492                     memcpy ( bmpImage->data + h * bmpImage->bytes_per_line + left*2, srcbits + left*2, dstwidth*2 );
1493             else     /* We need to do a conversion from a 555 dib */
1494             {
1495                 LPDWORD dstpixel, ptr = (LPDWORD)(srcbits + left*2);
1496                 DWORD val;
1497                 int div = dstwidth % 2;
1498
1499                 for (h = lines - 1; h >= 0; h--) {
1500                     dstpixel = (LPDWORD) (bmpImage->data + h * bmpImage->bytes_per_line + left*2);
1501                     for (x = 0; x < dstwidth/2; x++) { /* Do 2 pixels at a time */
1502                         val = *ptr++;
1503                         *dstpixel++ = ((val << 1) & 0xffc0ffc0) | ((val >> 4) & 0x00200020) | /* Red & Green */
1504                           (val & 0x001f001f);                             /* Blue */
1505                     }
1506                     if (div != 0) /* Odd width? */
1507                         *dstpixel = ((*(WORD *)ptr << 1) & 0xffc0) | ((*(WORD *)ptr >> 4) & 0x0020)
1508                                     | (*(WORD *)ptr & 0x001f);
1509                     ptr = (LPDWORD) ((srcbits += linebytes) + left*2);
1510                 }
1511             }
1512             break;
1513
1514         case 24:
1515         case 32:
1516             {
1517                 DWORD  *dstpixel;
1518                 LPWORD ptr = (LPWORD)srcbits + left;
1519                 DWORD val;
1520
1521                 if (bmpImage->red_mask == 0xff0000 && bmpImage->blue_mask == 0xff)
1522                 {
1523                   if ((rSrc == 0xF800) && (gSrc == 0x07E0) && (bSrc == 0x001F)) {
1524                     /* ==== 555 RGB dib to 24/32 RGB bitmap ==== */
1525                     for (h = lines - 1; h >= 0; h--) {
1526                       dstpixel = (DWORD *) (bmpImage->data + h * bmpImage->bytes_per_line + left*4);
1527                       for (x = 0; x < dstwidth; x++) {
1528                         val = *ptr++;
1529                         *dstpixel++ = ((val << 8) & 0xF80000) | /* Red */
1530                                       ((val << 5) & 0x00FC00) | /* Green */
1531                                       ((val << 3) & 0x0000FF);  /* Blue */
1532                       }
1533                       ptr = (LPWORD)(srcbits += linebytes) + left;
1534                     }
1535                   } else {
1536                     /* ==== 555 BGR dib to 24/32 BGR bitmap ==== */
1537                     for (h = lines - 1; h >= 0; h--) {
1538                       dstpixel = (DWORD *) (bmpImage->data + h * bmpImage->bytes_per_line + left*4);
1539                       for (x = 0; x < dstwidth; x++) {
1540                         
1541                         val = *ptr++;
1542                         *dstpixel++ = ((val << 9) & 0xf80000) | ((val << 4) & 0x070000) | /* Red */
1543                           ((val << 6) & 0x00f800) | ((val << 1) & 0x000700) | /* Green */
1544                           ((val << 3) & 0x0000f8) | ((val >> 2) & 0x000007);      /* Blue */
1545                       }
1546                       ptr = (LPWORD)(srcbits += linebytes) + left;
1547                     }
1548                   }
1549                 }
1550                 /* ==== 555 BGR dib to 24/32 RGB bitmap ==== */
1551                 else if (bmpImage->red_mask == 0xff && bmpImage->blue_mask == 0xff0000)
1552                 {
1553                   for (h = lines - 1; h >= 0; h--) {
1554                     dstpixel = (DWORD *) (bmpImage->data + h * bmpImage->bytes_per_line + left*4);
1555                     for (x = 0; x < dstwidth; x++) {
1556
1557                         val = *ptr++;
1558                         *dstpixel++ = ((val >> 7) & 0x0000f8) | ((val >> 12) & 0x000007) | /* Red */
1559                           ((val << 6) & 0x00f800) | ((val << 1) & 0x000700) | /* Green */
1560                           ((val << 19) & 0xf80000) | ((val >> 14) & 0x070000);      /* Blue */
1561                     }
1562                     ptr = (LPWORD)(srcbits += linebytes) + left;
1563                   }
1564                 }
1565
1566             }
1567             break;
1568
1569         case 1:
1570         case 4:
1571         case 8:
1572             {
1573                 LPWORD ptr = (LPWORD)srcbits + left;
1574                 WORD val;
1575                 int sc1, sc2;
1576
1577                 /* Set color scaling values */
1578                 if ( rSrc == 0x7c00 ) { sc1 = 7; sc2 = 2; }             /* 555 dib */
1579                 else { sc1 = 8; sc2 = 3; }                              /* 565 dib */
1580
1581                 for (h = lines - 1; h >= 0; h--) {
1582                     for (x = left; x < dstwidth+left; x++) {
1583                         val = *ptr++;
1584                         XPutPixel( bmpImage, x, h,
1585                                    X11DRV_PALETTE_ToPhysical(dc, RGB(((val & rSrc) >> sc1),  /* Red */
1586                                                                      ((val & gSrc) >> sc2),  /* Green */
1587                                                                      ((val & bSrc) << 3)))); /* Blue */
1588                     }
1589                     ptr = (LPWORD) (srcbits += linebytes) + left;
1590                 }
1591             }
1592             break;
1593
1594         default:
1595             FIXME("16 bit DIB %d bit bitmap\n", bmpImage->bits_per_pixel);
1596         break;
1597
1598     }
1599 }
1600
1601
1602 /***********************************************************************
1603  *           X11DRV_DIB_GetImageBits_16
1604  *
1605  * GetDIBits for an 16-bit deep DIB.
1606  */
1607 static void X11DRV_DIB_GetImageBits_16( int lines, BYTE *dstbits,
1608                                         DWORD dstwidth, DWORD srcwidth,
1609                                         PALETTEENTRY *srccolors,
1610                                         DWORD rDst, DWORD gDst, DWORD bDst,
1611                                         XImage *bmpImage, DWORD dibpitch )
1612 {
1613     DWORD x;
1614     int h, rsc, gsc;
1615
1616     DWORD linebytes = dibpitch;
1617
1618     if (lines < 0 )
1619     {
1620         lines = -lines;
1621         dstbits = dstbits + ( linebytes * (lines-1));
1622         linebytes = -linebytes;
1623     }
1624
1625     /* Set color scaling values */
1626     if ( rDst == 0x7c00 ) { rsc = 7; gsc = 2; }             /* 555 dib */
1627     else { rsc = 8; gsc = 3; }                              /* 565 dib */
1628
1629     switch ( bmpImage->depth )
1630     {
1631         case 15:
1632             /* using same format as XImage */
1633             if (rDst == bmpImage->red_mask && bDst == bmpImage->blue_mask)
1634                 for (h = lines - 1; h >= 0; h--, dstbits += linebytes)
1635                     memcpy( dstbits, bmpImage->data + h*bmpImage->bytes_per_line, srcwidth*2 );
1636             /* reversed format (BGR <=> RGB) */
1637             else if (rDst == bmpImage->blue_mask && bDst == bmpImage->red_mask)
1638             {
1639                 LPDWORD srcpixel, ptr = (LPDWORD)dstbits;
1640                 DWORD val;
1641                 int div = srcwidth % 2;
1642
1643                 for (h = lines - 1; h >= 0; h--) {
1644                     srcpixel = (LPDWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
1645                     for (x = 0; x < srcwidth/2; x++) {  /* Do 2 pixels at a time */
1646                         val = *srcpixel++;
1647                         *ptr++ = ((val << 10) & 0xf800f800) | (val & 0x03e003e0) |        /* Red & Green */
1648                           ((val >> 10) & 0x001f001f);                                     /* Blue */
1649                     }
1650                     if (div != 0) /* Odd width? */
1651                         *ptr = ((*(WORD *)srcpixel << 1) & 0xffc0) | ((*(WORD *)srcpixel >> 4) & 0x0020) |
1652                                (*(WORD *)srcpixel & 0x001f);
1653                     ptr = (LPDWORD)(dstbits += linebytes);
1654                }
1655            }
1656            else goto notsupported;
1657
1658            break;
1659
1660        case 16:
1661            {
1662            LPDWORD srcpixel, ptr = (LPDWORD)dstbits;
1663            DWORD val;
1664            int div = srcwidth % 2;
1665
1666            /* using same format as XImage */
1667            if (rDst == bmpImage->red_mask && bDst == bmpImage->blue_mask)
1668                for (h = lines - 1; h >= 0; h--, dstbits += linebytes)
1669                    memcpy( dstbits, bmpImage->data + h*bmpImage->bytes_per_line, srcwidth*2 );
1670            /* ==== 565 BGR bitmap to 555 BGR dib ==== */
1671            else if (bmpImage->red_mask == 0xf800 && bmpImage->blue_mask == 0x001f &&
1672                     rDst == 0x7c00 && bDst == 0x001f)
1673            {
1674                for (h = lines - 1; h >= 0; h--) {
1675                    srcpixel = (LPDWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
1676                    for (x = 0; x < srcwidth/2; x++) {  /* Do 2 pixels at a time */
1677                        val = *srcpixel++;
1678                        *ptr++ = ((val >> 1) & 0x7fe07fe0) |                    /* Red & Green */
1679                          (val & 0x001f001f);                                   /* Blue */
1680                    }
1681                    if (div != 0) /* Odd width? */
1682                        *ptr = ((*(WORD *)srcpixel >> 1) & 0x7fe0) | (*(WORD *)srcpixel & 0x001f);
1683                    ptr = (LPDWORD) (dstbits += linebytes);
1684                }
1685            }
1686            /* ==== 565 RGB bitmap to 555 BGR dib ==== */
1687            else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0xf800 &&
1688                     rDst == 0x7c00 && bDst == 0x001f)
1689            {
1690                for (h = lines - 1; h >= 0; h--) {
1691                    srcpixel = (LPDWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
1692                    for (x = 0; x < srcwidth/2; x++) {  /* Do 2 pixels at a time */
1693                        val = *srcpixel++;
1694                        *ptr++ = ((val << 10) & 0x7c007c00) | ((val >> 1) & 0x03e003e0) |   /* Red & Green */
1695                          ((val >> 11) & 0x001f001f);                                       /* Blue */
1696                    }
1697                    if (div != 0) /* Odd width? */
1698                        *ptr = ((*(WORD *)srcpixel >> 1) & 0x7fe0) | (*(WORD *)srcpixel & 0x001f);
1699                    ptr = (LPDWORD) (dstbits += linebytes);
1700                }
1701                }
1702            else goto notsupported;
1703            }
1704            break;
1705
1706        case 24:
1707        case 32:
1708            {
1709                DWORD  *srcpixel;
1710                LPWORD ptr = (LPWORD)dstbits;
1711                DWORD val;
1712
1713                /* ==== 24/32 BGR bitmap ==== */
1714                if (bmpImage->red_mask == 0xff0000 && bmpImage->blue_mask == 0xff)
1715                {
1716                    int rsc2 = 16-rsc, gsc2 = 8-gsc;
1717                    for (h = lines - 1; h >= 0; h--) {
1718                        srcpixel = (DWORD *) (bmpImage->data + h * bmpImage->bytes_per_line);
1719                        for (x = 0; x < srcwidth; x++, ptr++) {
1720                            val = *srcpixel++;
1721                            *ptr = ((val >> rsc2) & rDst) |
1722                                   ((val >> gsc2) & gDst) |
1723                                   ((val >> 3) & bDst);
1724                        }
1725                        ptr = (LPWORD)(dstbits += linebytes);
1726                    }
1727                }
1728                /* ==== 24/32 RGB bitmap ==== */
1729                else if (bmpImage->red_mask == 0xff && bmpImage->blue_mask == 0xff0000)
1730                {
1731                    int gsc2 = 8-gsc;
1732                    for (h = lines - 1; h >= 0; h--) {
1733                        srcpixel = (DWORD *) (bmpImage->data + h * bmpImage->bytes_per_line);
1734                        for (x = 0; x < srcwidth; x++, ptr++) {
1735                            val = *srcpixel++;
1736                            *ptr = ((val << rsc) & rDst) |
1737                                   ((val >> gsc2) & gDst) |
1738                                   ((val >> 19) & bDst);
1739                        }
1740                        ptr = (LPWORD) (dstbits += linebytes);
1741                    }
1742                }
1743                else goto notsupported;
1744            }
1745            break;
1746
1747        case 1:
1748             /* ==== monochrome bitmap ==== */
1749        case 4:
1750             /* ==== 4 colormap bitmap ==== */
1751             if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
1752             {
1753                 LPWORD ptr = (LPWORD)dstbits;
1754                 PALETTEENTRY val;
1755
1756                 for (h = lines - 1; h >= 0; h--) {
1757                   for (x = 0; x < dstwidth; x++) {
1758                     val = srccolors[XGetPixel(bmpImage, x, h)];
1759                     *ptr++ = ((val.peRed << rsc) & rDst) | 
1760                              ((val.peGreen << gsc) & gDst) |
1761                              ((val.peBlue >> 3) & bDst);
1762                   }
1763                   ptr = (LPWORD)(dstbits += linebytes);
1764                 }
1765             }
1766             else goto notsupported;
1767
1768             break;
1769
1770         case 8:
1771             /* ==== 8 colormap bitmap ==== */
1772             if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
1773             {
1774                 LPWORD ptr = (LPWORD)dstbits;
1775                 BYTE *srcpixel;
1776                 PALETTEENTRY val;
1777
1778                for (h = lines - 1; h >= 0; h--) {
1779                   srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
1780                   for (x = 0; x < dstwidth; x++) {
1781                     val = srccolors[(int)*srcpixel++];
1782                     *ptr++ = ((val.peRed << rsc) & rDst) | 
1783                              ((val.peGreen << gsc) & gDst) |
1784                              ((val.peBlue >> 3) & bDst);
1785                    }
1786                   ptr = (LPWORD)(dstbits += linebytes);
1787                }
1788            }
1789             else goto notsupported;
1790
1791            break;
1792
1793        default:
1794        notsupported:
1795             {
1796               BYTE r,g, b;
1797               LPWORD ptr = (LPWORD)dstbits;
1798
1799               FIXME("from %d bit bitmap with mask R,G,B %lx,%lx,%lx to 16 bit DIB %lx,%lx,%lx\n",
1800                     bmpImage->depth, bmpImage->red_mask, 
1801                     bmpImage->green_mask, bmpImage->blue_mask,
1802                     rDst, gDst, bDst);
1803
1804               for (h = lines - 1; h >= 0; h--)
1805                 {
1806                   for (x = 0; x < dstwidth; x++, ptr++)
1807                     {
1808                       COLORREF pixel = X11DRV_PALETTE_ToLogical( XGetPixel( bmpImage, x, h ) );
1809                       r = (BYTE) GetRValue(pixel);
1810                       g = (BYTE) GetGValue(pixel);
1811                       b = (BYTE) GetBValue(pixel);
1812                       *ptr = ( ((r << rsc) & rDst) | ((g << gsc) & gDst) | ((b >> 3) & bDst) );
1813                     }
1814                   ptr = (LPWORD) (dstbits += linebytes);
1815                 }
1816             }
1817            break;
1818    }
1819 }
1820
1821
1822 /***********************************************************************
1823  *           X11DRV_DIB_SetImageBits_24
1824  *
1825  * SetDIBits for a 24-bit deep DIB.
1826  */
1827 static void X11DRV_DIB_SetImageBits_24( int lines, const BYTE *srcbits,
1828                                  DWORD srcwidth, DWORD dstwidth, int left,
1829                                  DC *dc, XImage *bmpImage, DWORD linebytes )
1830 {
1831     DWORD x;
1832     int h;
1833   
1834     if (lines < 0 )
1835     {
1836         lines = -lines;
1837         srcbits = srcbits + linebytes * (lines - 1);
1838         linebytes = -linebytes;
1839     }
1840
1841     switch ( bmpImage->depth )
1842     {
1843         case 24:
1844             {
1845                 if (bmpImage->bits_per_pixel == 24) {
1846                         int dstlinebytes = linebytes;
1847                         BYTE *dstpixel;
1848                         BYTE *ptr = (BYTE *)(srcbits+left*3);
1849
1850                         if (dstlinebytes < 0 ) dstlinebytes = -dstlinebytes;
1851                         dstpixel = bmpImage->data + lines*dstlinebytes + left*3;
1852                         for(h = lines ; h-- ; ) {
1853                                 dstpixel-=dstlinebytes;
1854                                 memcpy(dstpixel,ptr,dstwidth*3);
1855                                 ptr +=linebytes;
1856                         }
1857                         break;
1858                 }
1859             }
1860         case 32:
1861             {
1862                 if( bmpImage->blue_mask == 0xff && bmpImage->red_mask == 0xff0000 )  /* packed BGR to unpacked BGR */
1863                 {
1864                     DWORD *dstpixel, val, buf;
1865                     DWORD *ptr = (DWORD *)(srcbits + left*3);
1866                     BYTE *bits;
1867                     int div = dstwidth % 4;
1868                     int divk;
1869
1870                     for(h = lines - 1; h >= 0; h--)
1871                     {
1872                         dstpixel = (DWORD *) (bmpImage->data + h*bmpImage->bytes_per_line + left*4);
1873
1874                         for (x = 0; x < dstwidth/4; x++) {   /* do 3 dwords source, 4 dwords dest at a time */
1875                             buf = *ptr++;
1876                             *dstpixel++ = buf&0x00ffffff;                  /* b1, g1, r1 */
1877                             val = (buf >> 24);                             /* b2 */
1878                             buf = *ptr++;
1879                             *dstpixel++ = (val | (buf<<8)) &0x00ffffff;    /* g2, r2 */
1880                             val = (buf >> 16);                             /* b3, g3 */
1881                             buf = *ptr++;
1882                             *dstpixel++ = (val | (buf<<16)) &0x00ffffff;   /* r3 */
1883                             *dstpixel++ = (buf >> 8);                      /* b4, g4, r4 */
1884                         }
1885                         for ( divk=div, bits=(BYTE*)ptr; divk>0; divk--, bits+=3 ) /* do remainder */
1886                         {
1887                             *dstpixel++ = *(DWORD*)bits & 0x00ffffff;      /* b, g, r */
1888                         }
1889                         ptr = (DWORD*)((srcbits+=linebytes)+left*3);
1890                     }
1891                 }
1892                 else if( bmpImage->blue_mask == 0xff0000 && bmpImage->red_mask == 0xff )  /* packed BGR to unpacked RGB */
1893                 {
1894                     DWORD *dstpixel, val, buf;
1895                     DWORD *ptr = (DWORD *)(srcbits + left*3);
1896                     BYTE *bits;
1897                     int div = dstwidth % 4;
1898                     int divk;
1899
1900                     for(h = lines - 1; h >= 0; h--)
1901                     {
1902                         dstpixel = (DWORD *) (bmpImage->data + h*bmpImage->bytes_per_line + left*4);
1903
1904                         for (x = 0; x < dstwidth/4; x++) {   /* do 3 dwords source, 4 dwords dest at a time */
1905                             buf = *ptr++;
1906                             *dstpixel++ = ((buf&0xff)<<16) | (buf&0xff00) | ((buf&0xff0000)>>16);  /* b1, g1, r1 */
1907                             val = ((buf&0xff000000)>>8);                                           /* b2 */
1908                             buf = *ptr++;
1909                             *dstpixel++ = val | ((buf&0xff)<<8) | ((buf&0xff00)>>8);               /* g2, r2 */
1910                             val = (buf&0xff0000) | ((buf&0xff000000)>>16);                         /* b3, g3 */
1911                             buf = *ptr++;
1912                             *dstpixel++ = val | (buf&0xff);                                        /* r3 */
1913                             *dstpixel++ = ((buf&0xff00)<<8) | ((buf&0xff0000)>>8) | (buf>>24);     /* b4, g4, r4 */
1914                         }
1915                         for ( divk=div, bits=(BYTE*)ptr; divk>0; divk--, bits+=3 ) /* do remainder */
1916                         {
1917                             buf = *(DWORD*)bits;
1918                             *dstpixel++ = ((buf&0xff)<<16) | (buf&0xff00) | ((buf&0xff0000)>>16);  /* b, g, r */
1919                         }
1920                         ptr = (DWORD*)((srcbits+=linebytes)+left*3);
1921                     }
1922                 }
1923                 else
1924                     goto notsupported;
1925             }
1926             break;
1927
1928         case 15:
1929             {
1930                 if( bmpImage->blue_mask == 0x7c00 && bmpImage->red_mask == 0x1f )   /* BGR888 to RGB555 */
1931                 {
1932                     DWORD  *ptr = (DWORD *)(srcbits + left*3);
1933                     LPBYTE bits;
1934                     LPWORD dstpixel;
1935                     int div = dstwidth % 4;
1936                     int divk;
1937
1938                     for (h = lines - 1; h >= 0; h--) {              /* Do 4 pixels at a time */
1939                         dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line + left*2);
1940                         for (x = 0; x < dstwidth/4; x++, ptr += 3) {
1941                             *dstpixel++ = ((ptr[0] << 7) & 0x7c00)  | ((ptr[0] >> 6) & 0x03e0)  | ((ptr[0] >> 19) & 0x1f);
1942                             *dstpixel++ = ((ptr[0] >> 17) & 0x7c00) | ((ptr[1] << 2) & 0x03e0)  | ((ptr[1] >> 11) & 0x1f);
1943                             *dstpixel++ = ((ptr[1] >> 9) & 0x07c00) | ((ptr[1] >> 22) & 0x03e0) | ((ptr[2] >> 3) & 0x1f);
1944                             *dstpixel++ = ((ptr[2] >> 1) & 0x07c00) | ((ptr[2] >> 14) & 0x03e0) | ((ptr[2] >> 27) & 0x1f);
1945                         }
1946                         for (bits = (LPBYTE)ptr, divk=div; divk > 0; divk--, bits+=3)  /* dstwidth not divisible by 4? */
1947                             *dstpixel++ = (((WORD)bits[0] << 7) & 0x07c00) |
1948                                             (((WORD)bits[1] << 2) & 0x03e0) |
1949                                             (((WORD)bits[2] >> 3) & 0x001f);
1950                         ptr = (DWORD *)((srcbits += linebytes) + left * 3);
1951                     }
1952                 }
1953                 else if( bmpImage->blue_mask == 0x1f && bmpImage->red_mask == 0x7c00 )   /* BGR888 to BGR555 */
1954                 {
1955                     DWORD  *ptr = (DWORD *)(srcbits + left*3);
1956                     LPBYTE bits;
1957                     LPWORD dstpixel;
1958                     int div = dstwidth % 4;
1959                     int divk;
1960
1961                     for (h = lines - 1; h >= 0; h--) {              /* Do 4 pixels at a time */
1962                         dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line + left*2);
1963                         for (x = 0; x < dstwidth/4; x++, ptr += 3) {
1964                             *dstpixel++ = ((ptr[0] >> 3) & 0x1f)  | ((ptr[0] >> 6) & 0x03e0)  | ((ptr[0] >> 9) & 0x7c00);
1965                             *dstpixel++ = ((ptr[0] >> 27) & 0x1f) | ((ptr[1] << 2) & 0x03e0)  | ((ptr[1] >> 1) & 0x7c00);
1966                             *dstpixel++ = ((ptr[1] >> 19) & 0x1f) | ((ptr[1] >> 22) & 0x03e0) | ((ptr[2] << 7) & 0x7c00);
1967                             *dstpixel++ = ((ptr[2] >> 11) & 0x1f) | ((ptr[2] >> 14) & 0x03e0) | ((ptr[2] >> 17) & 0x7c00);
1968                         }
1969                         for (bits = (LPBYTE)ptr, divk=div; divk > 0; divk--, bits+=3)  /* dstwidth not divisible by 4? */
1970                             *dstpixel++ = (((WORD)bits[2] << 7) & 0x07c00) |
1971                                             (((WORD)bits[1] << 2) & 0x03e0) |
1972                                             (((WORD)bits[0] >> 3) & 0x001f);
1973                         ptr = (DWORD *)((srcbits += linebytes) + left * 3);
1974                     }
1975                 }
1976                 else
1977                     goto notsupported;
1978             }
1979             break;
1980
1981         case 16:
1982             {
1983                 DWORD  *ptr = (DWORD *)(srcbits + left*3);
1984                 LPBYTE bits;
1985                 LPWORD dstpixel;
1986                 int div = dstwidth % 4;
1987                 int divk;
1988
1989                 if( bmpImage->blue_mask == 0x001f && bmpImage->red_mask == 0xf800 )    /* BGR888 to BGR565 */
1990                 {
1991                     for (h = lines - 1; h >= 0; h--) {              /* Do 4 pixels at a time */
1992                         dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line + left*2);
1993                         for (x = 0; x < dstwidth/4; x++, ptr += 3) {
1994                             *dstpixel++ = ((ptr[0] >> 3) & 0x1f)  | ((ptr[0] >> 5) & 0x07e0)  | ((ptr[0] >> 8) & 0xf800);
1995                             *dstpixel++ = ((ptr[0] >> 27) & 0x1f) | ((ptr[1] << 3) & 0x07e0)  | (ptr[1] & 0xf800);
1996                             *dstpixel++ = ((ptr[1] >> 19) & 0x1f) | ((ptr[1] >> 21) & 0x07e0) | ((ptr[2] << 8) & 0xf800);
1997                             *dstpixel++ = ((ptr[2] >> 11) & 0x1f) | ((ptr[2] >> 13) & 0x07e0) | ((ptr[2] >> 16) & 0xf800);
1998                         }
1999                         for (   bits = (LPBYTE)ptr, divk=div; divk > 0; divk--, bits+=3)  /* dstwidth is not divisible by 4? */
2000                             *dstpixel++ = (((WORD)bits[2] << 8) & 0xf800) |
2001                                             (((WORD)bits[1] << 3) & 0x07e0) |
2002                                             (((WORD)bits[0] >> 3) & 0x001f);
2003                         ptr = (DWORD *)((srcbits += linebytes) + left * 3);
2004                     }
2005                 }
2006                 else if( bmpImage->blue_mask == 0xf800 && bmpImage->red_mask == 0x001f ) /* BGR888 to RGB565 */
2007                 {
2008                     for (h = lines - 1; h >= 0; h--) {              /* Do 4 pixels at a time */
2009                         dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line + left*2);
2010                         for (x = 0; x < dstwidth/4; x++, ptr += 3) {
2011                             *dstpixel++ = ((ptr[0] << 8) & 0xf800)  | ((ptr[0] >> 5) & 0x07e0)  | ((ptr[0] >> 19) & 0x1f);
2012                             *dstpixel++ = ((ptr[0] >> 16) & 0xf800) | ((ptr[1] << 3) & 0x07e0)  | ((ptr[1] >> 11) & 0x1f);
2013                             *dstpixel++ = ((ptr[1] >> 8) & 0xf800)  | ((ptr[1] >> 21) & 0x07e0) | ((ptr[2] >> 3) & 0x1f);
2014                             *dstpixel++ = (ptr[2] & 0xf800)         | ((ptr[2] >> 13) & 0x07e0) | ((ptr[2] >> 27) & 0x1f);
2015                         }
2016                         for (   bits = (LPBYTE)ptr, divk=div; divk > 0; divk--, bits+=3)  /* dstwidth is not divisible by 4? */
2017                             *dstpixel++ = (((WORD)bits[0] << 8) & 0xf800) |
2018                                             (((WORD)bits[1] << 3) & 0x07e0) |
2019                                             (((WORD)bits[2] >> 3) & 0x001f);
2020                         ptr = (DWORD *)((srcbits += linebytes) + left * 3);
2021                     }
2022                 }
2023                 else
2024                     goto notsupported;
2025             }
2026             break;
2027          
2028         case 1:
2029         case 4:
2030         case 8:
2031             {
2032                 LPBYTE bits = (LPBYTE)srcbits + left*3;
2033
2034                 for (h = lines - 1; h >= 0; h--) {
2035                     for (x = left; x < dstwidth+left; x++, bits+=3)
2036                         XPutPixel( bmpImage, x, h, 
2037                                    X11DRV_PALETTE_ToPhysical(dc, RGB(bits[2], bits[1], bits[0])));
2038                     bits = (LPBYTE)(srcbits += linebytes) + left * 3;
2039                 }
2040             }
2041             break;
2042
2043         default:
2044         notsupported:
2045             FIXME("from 24 bit DIB to %d bit bitmap with mask R,G,B %x,%x,%x\n",
2046                   bmpImage->bits_per_pixel, (int)bmpImage->red_mask, 
2047                   (int)bmpImage->green_mask, (int)bmpImage->blue_mask );
2048             break;
2049     }
2050 }
2051
2052
2053 /***********************************************************************
2054  *           X11DRV_DIB_GetImageBits_24
2055  *
2056  * GetDIBits for an 24-bit deep DIB.
2057  */
2058 static void X11DRV_DIB_GetImageBits_24( int lines, BYTE *dstbits,
2059                                         DWORD dstwidth, DWORD srcwidth,
2060                                         PALETTEENTRY *srccolors,
2061                                         XImage *bmpImage, DWORD linebytes )
2062 {
2063     DWORD x, val;
2064     int h;
2065
2066     if (lines < 0 )
2067     {
2068         lines = -lines;
2069         dstbits = dstbits + ( linebytes * (lines-1) );
2070         linebytes = -linebytes;
2071     }
2072
2073     switch ( bmpImage->depth )
2074     {
2075         case 24:
2076             {
2077                 if (bmpImage->bits_per_pixel == 24) {
2078                         int tocopy = linebytes;
2079                         BYTE *srcpixel;
2080                         BYTE *ptr = (LPBYTE)dstbits;
2081
2082                         if (tocopy < 0 ) tocopy = -tocopy;
2083                         srcpixel = bmpImage->data + lines*tocopy;
2084                         for(h = lines ; h-- ; ) {
2085                                 srcpixel-=tocopy;
2086                                 memcpy(ptr,srcpixel,tocopy);
2087                                 ptr = (LPBYTE)(dstbits+=linebytes);
2088                         }
2089                         break;
2090                 }
2091             }
2092         case 32:
2093             {
2094                     DWORD  *srcpixel, buf;
2095                     LPBYTE bits;
2096             DWORD *ptr=(DWORD *)dstbits;
2097                     int quotient = dstwidth / 4;
2098                     int remainder = dstwidth % 4;
2099                     int remk;
2100
2101             /* ==== 24/32 BGR bitmap to 24 BGR dib==== */
2102             if( bmpImage->blue_mask == 0xff && bmpImage->red_mask == 0xff0000 )
2103             {
2104                     for(h = lines - 1; h >= 0; h--)
2105                     {
2106                   srcpixel = (DWORD *) (bmpImage->data + h * bmpImage->bytes_per_line);
2107
2108                         for (x = 0; x < quotient; x++) {     /* do 4 dwords source, 3 dwords dest at a time */
2109                           buf = ((*srcpixel++)&0x00ffffff);      /* b1, g1, r1*/
2110                           *ptr++ = buf | ((*srcpixel)<<24);      /* b2 */
2111                           buf = ((*srcpixel++>>8)&0x0000ffff);   /* g2, r2 */
2112                           *ptr++ = buf | ((*srcpixel)<<16);      /* b3, g3 */
2113                           buf = ((*srcpixel++>>16)&0x000000ff);  /* r3 */
2114                           *ptr++ = buf | ((*srcpixel++)<<8);     /* b4, g4, r4 */
2115                         }
2116                         for ( remk=remainder, bits=(BYTE*)ptr; remk>0; remk--, bits+=3 ) /* do remainder */
2117                         {
2118                             buf=*srcpixel++;
2119                             *(WORD*)bits = buf;                    /* b, g */
2120                           *(bits+2) = buf>>16;                   /* r */
2121                         }
2122                   ptr = (DWORD*)(dstbits+=linebytes);
2123                     }
2124
2125                 }
2126             /* ==== 24/32 RGB bitmap to 24 BGR dib ==== */
2127             else if( bmpImage->blue_mask == 0xff0000 && bmpImage->red_mask == 0xff )
2128                 {
2129                     for(h = lines - 1; h >= 0; h--)
2130                     {
2131                   srcpixel = (DWORD *) (bmpImage->data + h * bmpImage->bytes_per_line);
2132
2133                         for (x = 0; x < quotient; x++) {     /* do 4 dwords source, 3 dwords dest at a time */
2134                             buf = *srcpixel++;
2135                             val = ((buf&0xff0000)>>16) | (buf&0xff00) | ((buf&0xff)<<16);       /* b1, g1, r1 */
2136                             buf = *srcpixel++;
2137                             *ptr++ = val | ((buf&0xff0000)<<8);                                 /* b2 */
2138                             val = ((buf&0xff00)>>8) | ((buf&0xff)<<8);                          /* g2, r2 */
2139                             buf = *srcpixel++;
2140                             *ptr++ = val | (buf&0xff0000) | ((buf&0xff00)<<16);                 /* b3, g3 */
2141                             val = (buf&0xff);                                                   /* r3 */
2142                             buf = *srcpixel++;
2143                             *ptr++ = val | ((buf&0xff0000)>>8) | ((buf&0xff00)<<8) | (buf<<24); /* b4, g4, r4 */
2144                         }
2145                         for ( remk=remainder, bits=(BYTE*)ptr; remk>0; remk--, bits+=3 ) /* do remainder */
2146                         {
2147                             buf=*srcpixel++;
2148                             *(WORD*)bits = (buf&0xff00) | ((buf&0xff0000)>>16) ;                /* b, g */
2149                             *(bits+2) = buf;                                                    /* r */
2150                         }
2151                   ptr = (DWORD*)(dstbits+=linebytes);
2152                     }
2153                 }
2154             else goto notsupported;
2155             }
2156             break;
2157
2158         case 15:
2159             {
2160                 LPWORD srcpixel;
2161             LPBYTE bits = dstbits;
2162                 WORD val;
2163
2164             /* ==== 555 BGR bitmap to 24 BGR dib ==== */
2165             if( bmpImage->blue_mask == 0x1f && bmpImage->red_mask == 0x7c00 )  
2166                 {
2167                     for (h = lines - 1; h >= 0; h--) {
2168                   srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2169                         for (x = 0; x < srcwidth; x++, bits += 3) {
2170                             val = *srcpixel++;
2171                             bits[2] = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07));           /*Red*/
2172                             bits[1] = (BYTE)(((val >> 2) & 0xf8) | ((val >> 7) & 0x07));            /*Green*/
2173                             bits[0] = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07));            /*Blue*/
2174                         }
2175                   bits = (dstbits += linebytes);
2176                     }
2177                 }
2178             /* ==== 555 RGB bitmap to 24 RGB dib==== */
2179             else if( bmpImage->blue_mask == 0x7c00 && bmpImage->red_mask == 0x1f )
2180                 {
2181                     for (h = lines - 1; h >= 0; h--) {
2182                   srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2183                         for (x = 0; x < srcwidth; x++, bits += 3) {
2184                             val = *srcpixel++;
2185                             bits[0] = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07));           /*Red*/
2186                             bits[1] = (BYTE)(((val >> 2) & 0xf8) | ((val >> 7) & 0x07));            /*Green*/
2187                             bits[2] = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07));            /*Blue*/
2188                         }
2189                   bits = (dstbits += linebytes);
2190                     }
2191                 }
2192             else goto notsupported;
2193             }
2194             break;
2195
2196         case 16:
2197             {
2198                 LPWORD srcpixel;
2199             LPBYTE bits = dstbits;
2200                 WORD val;
2201
2202             /* ==== 565 BGR bitmap to 24 BGR dib ==== */
2203             if( bmpImage->blue_mask == 0x1f && bmpImage->red_mask == 0xf800 )
2204                 {
2205                     for (h = lines - 1; h >= 0; h--) {
2206                   srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2207                         for (x = 0; x < srcwidth; x++, bits += 3) {
2208                             val = *srcpixel++;
2209                             bits[2] = (BYTE)(((val >> 8) & 0xf8) | ((val >> 13) & 0x07));           /*Red*/
2210                             bits[1] = (BYTE)(((val >> 3) & 0xfc) | ((val >> 9) & 0x03));            /*Green*/
2211                             bits[0] = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07));            /*Blue*/
2212                         }
2213                   bits = (dstbits += linebytes);
2214                     }
2215                 }
2216             /* ==== 565 RGB bitmap to 24 BGR dib ==== */
2217             else if( bmpImage->blue_mask == 0xf800 && bmpImage->red_mask == 0x1f )
2218                 {
2219                     for (h = lines - 1; h >= 0; h--) {
2220                   srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2221                         for (x = 0; x < srcwidth; x++, bits += 3) {
2222                             val = *srcpixel++;
2223                             bits[0] = (BYTE)(((val >> 8) & 0xf8) | ((val >> 13) & 0x07));           /*Red*/
2224                             bits[1] = (BYTE)(((val >> 3) & 0xfc) | ((val >> 9) & 0x03));            /*Green*/
2225                             bits[2] = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07));            /*Blue*/
2226                         }
2227                   bits = (dstbits += linebytes);
2228                     }
2229                 }
2230             else  goto notsupported;
2231             }
2232             break;
2233
2234         case 1:
2235             /* ==== monochrome bitmap to 24 BGR dib ==== */
2236         case 4:
2237             /* ==== 4 colormap bitmap to 24 BGR dib ==== */
2238             if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
2239             {
2240                 LPBYTE bits = dstbits;
2241                 PALETTEENTRY val;
2242
2243                 for (h = lines - 1; h >= 0; h--) {
2244                   for (x = 0; x < dstwidth; x++) {
2245                     val = srccolors[XGetPixel(bmpImage, x, h)];
2246                     *bits++ = val.peBlue;
2247                     *bits++ = val.peGreen;
2248                     *bits++ = val.peRed;
2249                   }
2250                   bits = (dstbits += linebytes);
2251                 }
2252             }
2253             else goto notsupported;
2254
2255             break;
2256
2257         case 8:
2258             /* ==== 8 colormap bitmap to 24 BGR dib ==== */
2259             if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask == 0 && srccolors)
2260             {
2261                 BYTE *srcpixel;
2262                 LPBYTE bits = dstbits;
2263                 PALETTEENTRY val;
2264
2265                 for (h = lines - 1; h >= 0; h--) {
2266                   srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
2267                   for (x = 0; x < dstwidth; x++ ) {
2268                     val = srccolors[(int)*srcpixel++];
2269                     *bits++ = val.peBlue;               /*Blue*/
2270                     *bits++ = val.peGreen;              /*Green*/
2271                     *bits++ = val.peRed;                /*Red*/
2272                     }
2273                   bits = (dstbits += linebytes);
2274                 }
2275             }
2276             else goto notsupported;
2277
2278             break;
2279
2280         default:
2281         notsupported:
2282             {
2283               LPBYTE bits = dstbits;
2284
2285             FIXME("from %d bit bitmap with mask R,G,B %x,%x,%x to 24 bit DIB\n",
2286                   bmpImage->depth, (int)bmpImage->red_mask, 
2287                   (int)bmpImage->green_mask, (int)bmpImage->blue_mask );
2288               for (h = lines - 1; h >= 0; h--)
2289                 {
2290                   for (x = 0; x < dstwidth; x++, bits += 3)
2291                     {
2292                       COLORREF pixel = X11DRV_PALETTE_ToLogical( XGetPixel( bmpImage, x, h ) );
2293                       bits[0] = GetBValue(pixel);
2294                       bits[1] = GetGValue(pixel);
2295                       bits[2] = GetRValue(pixel);
2296                     }
2297                   bits = (dstbits += linebytes);
2298                 }
2299             }
2300             break;
2301     }
2302 }
2303
2304
2305 /***********************************************************************
2306  *           X11DRV_DIB_SetImageBits_32
2307  *
2308  * SetDIBits for a 32-bit deep DIB.
2309  */
2310 static void X11DRV_DIB_SetImageBits_32( int lines, const BYTE *srcbits,
2311                                  DWORD srcwidth, DWORD dstwidth, int left,
2312                                         DC *dc, XImage *bmpImage,
2313                                         DWORD linebytes )
2314 {
2315     DWORD x, *ptr;
2316     int h;
2317   
2318     if (lines < 0 )
2319     {
2320        lines = -lines;
2321        srcbits = srcbits + ( linebytes * (lines-1) );
2322        linebytes = -linebytes;
2323     }
2324
2325     ptr = (DWORD *) srcbits + left;
2326
2327     switch ( bmpImage->depth )
2328     {
2329         case 32:
2330             /* ==== 32 BGR dib to 24/32 BGR bitmap ==== */
2331             if (bmpImage->red_mask == 0xff0000 && bmpImage->blue_mask == 0xff) {
2332                 for (h = lines - 1; h >= 0; h--, srcbits+=linebytes) {
2333                     memcpy( bmpImage->data + h * bmpImage->bytes_per_line, srcbits + left*4, dstwidth*4 );
2334                 }
2335             }
2336
2337             /* ==== 32 BGR dib to 24/32 RGB bitmap ==== */
2338             else if (bmpImage->red_mask == 0xff && bmpImage->blue_mask == 0xff0000)
2339             {
2340                 DWORD *dstpixel;
2341
2342                 for (h = lines - 1; h >= 0; h--) {
2343                     dstpixel = (DWORD *) (bmpImage->data + h * bmpImage->bytes_per_line);
2344                     for (x = 0; x < dstwidth; x++, ptr++) {
2345                         *dstpixel++ =   ((*ptr << 16) & 0xff0000) | (*ptr & 0xff00) | ((*ptr >> 16) & 0xff);
2346                     }
2347                     ptr = (DWORD *) (srcbits += linebytes) + left;
2348                 }
2349             }
2350             else goto notsupported;
2351
2352             break;
2353
2354         case 24:
2355             /* ==== 32 BGR dib to 24 (888) BGR bitmap ==== */
2356             /* we need to check that source mask matches destination */
2357             if (bmpImage->bits_per_pixel == 32)
2358             {
2359                 for (h = lines - 1; h >= 0; h--, srcbits+=linebytes) {
2360                     memcpy( bmpImage->data + h * bmpImage->bytes_per_line, srcbits + left*4, dstwidth*4 );
2361                 }
2362             }
2363             else
2364             {
2365                 BYTE  *bptr;
2366
2367                 ptr = (DWORD *) srcbits + left;
2368                 bptr = bmpImage->data;
2369
2370                 for (h = lines - 1; h >= 0; h--) {
2371                     for (x = 0; x < dstwidth; x++) {
2372                          /* *ptr is a 32bit value */
2373                          /* bptr points to first of 3 bytes */
2374                         *bptr++ = (*ptr >> 16) & 0xff;
2375                         *bptr++ = (*ptr >>  8) & 0xff;
2376                         *bptr++ = (*ptr      ) & 0xff;
2377                         ptr++;
2378                     }
2379                     ptr = (DWORD *) (srcbits += linebytes) + left;
2380                 }
2381             }
2382             break;
2383         
2384         case 15:
2385             /* ==== 32 BGR dib to 555 BGR bitmap ==== */
2386             if (bmpImage->red_mask == 0x7c00 && bmpImage->blue_mask == 0x001f) {
2387                 LPWORD  dstpixel;
2388
2389                 for (h = lines - 1; h >= 0; h--) {
2390                     dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2391                     for (x = 0; x < dstwidth; x++, ptr++) {
2392                         *dstpixel++ = (WORD) (((*ptr >> 9) & 0x7c00) | ((*ptr >> 6) & 0x03e0) | ((*ptr >> 3) & 0x001f));
2393                     }
2394                     ptr = (DWORD *) (srcbits += linebytes) + left;
2395                 }
2396             }
2397             /* ==== 32 BGR dib to 555 RGB bitmap ==== */
2398             else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0x7c00)
2399             {
2400                 LPWORD  dstpixel;
2401
2402                 for (h = lines - 1; h >= 0; h--) {
2403                     dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2404                     for (x = 0; x < dstwidth; x++, ptr++) {
2405                         *dstpixel++ = (WORD) (((*ptr << 7) & 0x7c00) | ((*ptr >> 6) & 0x03e0) | ((*ptr >> 19) & 0x001f));
2406                     }
2407                     ptr = (DWORD *) (srcbits += linebytes) + left;
2408                 }
2409             }
2410             else goto notsupported;
2411
2412             break;
2413
2414         case 16:
2415             /* ==== 32 BGR dib to 565 BGR bitmap ==== */
2416             if (bmpImage->red_mask == 0xf800 && bmpImage->blue_mask == 0x001f)
2417             {
2418                 LPWORD  dstpixel;
2419
2420                 for (h = lines - 1; h >= 0; h--) {
2421                     dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2422                     for (x = 0; x < dstwidth; x++, ptr++) {
2423                         *dstpixel++ = (WORD) (((*ptr >> 8) & 0xf800) | ((*ptr >> 5) & 0x07e0) | ((*ptr >> 3) & 0x001f));
2424                     }
2425                     ptr = (DWORD *) (srcbits += linebytes) + left;
2426                 }
2427             }
2428             /* ==== 32 BGR dib to 565 RGB bitmap ==== */
2429             else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0xf800)
2430             {
2431                 LPWORD dstpixel;
2432
2433                 for (h = lines - 1; h >= 0; h--) {
2434                     dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2435                     for (x = 0; x < dstwidth; x++, ptr++) {
2436                         *dstpixel++ = (WORD) (((*ptr << 8) & 0xf800) | ((*ptr >> 5) & 0x07e0) | ((*ptr >> 19) & 0x001f));
2437                     }
2438                     ptr = (DWORD *) (srcbits += linebytes) + left;
2439                 }
2440             }
2441             else goto notsupported;
2442
2443             break;
2444
2445         case 1:
2446         case 4:
2447         case 8:
2448             {
2449                 LPBYTE bits = (LPBYTE)srcbits + left*4;
2450
2451                 for (h = lines - 1; h >= 0; h--) {
2452                     for (x = left; x < dstwidth+left; x++, bits += 4)
2453                         XPutPixel( bmpImage, x, h,
2454                                    X11DRV_PALETTE_ToPhysical(dc, RGB( bits[2],  bits[1], *bits )));
2455                     bits = (LPBYTE)(srcbits += linebytes) + left * 4;
2456                 }
2457             }
2458             break;
2459
2460        default:
2461        notsupported:
2462             FIXME("32 bit DIB %d bit bitmap\n", bmpImage->bits_per_pixel);
2463             break;
2464     }
2465
2466 }
2467
2468 /***********************************************************************
2469  *           X11DRV_DIB_GetImageBits_32
2470  *
2471  * GetDIBits for an 32-bit deep DIB.
2472  */
2473 static void X11DRV_DIB_GetImageBits_32( int lines, BYTE *dstbits,
2474                                         DWORD dstwidth, DWORD srcwidth,
2475                                         PALETTEENTRY *srccolors,
2476                                         XImage *bmpImage, DWORD linebytes )
2477 {
2478     DWORD x;
2479     int h;
2480     BYTE *bits;
2481
2482     DWORD copybytes = srcwidth * 4;
2483
2484     if (lines < 0 )
2485     {
2486         lines = -lines;
2487         dstbits = dstbits + ( linebytes * (lines-1) );
2488         linebytes = -linebytes;
2489     }
2490
2491     bits = dstbits;
2492
2493     switch ( bmpImage->depth )
2494     {
2495         case 32:
2496             /* ==== 24/32 BGR bitmap to 32 BGR dib ==== */
2497             if ( bmpImage->red_mask == 0xff0000 && bmpImage->blue_mask == 0xff )
2498                 for (h = lines - 1; h >= 0; h--, dstbits+=linebytes)
2499                     memcpy( dstbits, bmpImage->data + h*bmpImage->bytes_per_line, copybytes );
2500
2501             /* ==== 24/32 RGB bitmap to 32 BGR dib ==== */
2502             else if ( bmpImage->red_mask == 0xff && bmpImage->blue_mask == 0xff0000 )
2503             {
2504                 LPBYTE srcbits;
2505
2506                 for (h = lines - 1; h >= 0; h--) {
2507                     srcbits = bmpImage->data + h * bmpImage->bytes_per_line;
2508                     for (x = 0; x < dstwidth; x++, bits+=4, srcbits+=2) {
2509                         *(bits + 2) = *srcbits++;
2510                         *(bits + 1) = *srcbits++;
2511                         *bits = *srcbits;
2512                     }
2513                     bits = (dstbits += linebytes);
2514                 }
2515             }
2516             else goto notsupported;
2517             break;
2518
2519         case 24:
2520             /* ==== 24 BGR bitmap to 32 (0888) BGR dib ==== */
2521             /* we need to check that source mask matches destination */
2522             {
2523                 DWORD *srcpixel;
2524                 BYTE  *bptr;
2525                 DWORD srcdata;
2526
2527                 srcpixel = (DWORD *) dstbits;
2528                 bptr = bmpImage->data;
2529
2530                 for (h = lines - 1; h >= 0; h--) {
2531                     for (x = 0; x < dstwidth; x++) {
2532                         /* *srcpixel is a 32bit value */
2533                                                 /* bptr points to first of 3 bytes */
2534                         srcdata = 0;
2535                                                 srcdata = srcdata << 8 | *bptr++;
2536                                                 srcdata = srcdata << 8 | *bptr++;       
2537                         srcdata = srcdata << 8 | *bptr++;       
2538
2539                         *srcpixel++ = srcdata;
2540                     }
2541                     srcpixel = (DWORD *) (dstbits += linebytes);
2542                                 }
2543             }
2544             break;
2545
2546         case 15:
2547             {
2548                 LPWORD srcpixel;
2549                 WORD val;
2550
2551             /* ==== 555 BGR bitmap to 32 BGR dib ==== */
2552             if (bmpImage->red_mask == 0x7c00 && bmpImage->blue_mask == 0x001f)
2553             {
2554               for (h = lines - 1; h >= 0; h--) {
2555                 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2556                 for (x = 0; x < dstwidth; x++, bits+=2) {
2557                   val = *srcpixel++;
2558                   *bits++ = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x03)); /*Blue*/
2559                   *bits++ = (BYTE)(((val >> 2) & 0xfc) | ((val >> 8) & 0x03)); /*Green*/
2560                   *bits = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07));  /*Red*/
2561                 }
2562                 bits = (dstbits += linebytes);
2563               }
2564             }
2565             /* ==== 555 RGB bitmap to 32 BGR dib ==== */
2566             else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0x7c00)
2567             {
2568                 for (h = lines - 1; h >= 0; h--) {
2569                 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2570                 for (x = 0; x < dstwidth; x++, bits+=2) {
2571                         val = *srcpixel++;
2572                   *bits++ = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07));/*Blue*/
2573                   *bits++ = (BYTE)(((val >> 2) & 0xfc) | ((val >> 8) & 0x03)); /*Green*/
2574                   *bits = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x03));   /*Red*/
2575                 }
2576                 bits = (dstbits += linebytes);
2577                     }
2578                 }
2579             else goto notsupported;
2580             }
2581             break;
2582
2583         case 16:
2584             {
2585                 LPWORD srcpixel;
2586                 WORD val;
2587
2588             /* ==== 565 BGR bitmap to 32 BGR dib ==== */
2589             if (bmpImage->red_mask == 0xf800 && bmpImage->blue_mask == 0x001f)
2590             {
2591                 for (h = lines - 1; h >= 0; h--) {
2592                 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2593                 for (x = 0; x < srcwidth; x++, bits+=2) {
2594                         val = *srcpixel++;
2595                   *bits++ = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x03)); /*Blue*/
2596                   *bits++ = (BYTE)(((val >> 3) & 0xfc) | ((val >> 9) & 0x03)); /*Green*/
2597                   *bits = (BYTE)(((val >> 8) & 0xf8) | ((val >> 13) & 0x07));  /*Red*/
2598                 }
2599                 bits = (dstbits += linebytes);
2600               }
2601             }
2602             /* ==== 565 RGB bitmap to 32 BGR dib ==== */
2603             else if (bmpImage->red_mask == 0xf800 && bmpImage->blue_mask == 0x001f)
2604             {
2605               for (h = lines - 1; h >= 0; h--) {
2606                 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2607                 for (x = 0; x < srcwidth; x++, bits+=2) {
2608                   val = *srcpixel++;
2609                   *bits++ = (BYTE)(((val >> 8) & 0xf8) | ((val >> 13) & 0x07));/*Blue*/
2610                   *bits++ = (BYTE)(((val >> 3) & 0xfc) | ((val >> 9) & 0x03)); /*Green*/
2611                   *bits = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x03));   /*Red*/
2612                 }
2613                 bits = (dstbits += linebytes);
2614                     }
2615                 }
2616             else goto notsupported;
2617             }
2618             break;
2619
2620         case 1:
2621             /* ==== monochrome bitmap to 32 BGR dib ==== */
2622         case 4:
2623             /* ==== 4 colormap bitmap to 32 BGR dib ==== */
2624             if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
2625             {
2626                 PALETTEENTRY val;
2627
2628                 for (h = lines - 1; h >= 0; h--) {
2629                   for (x = 0; x < dstwidth; x++) {
2630                     val = srccolors[XGetPixel(bmpImage, x, h)];
2631                     *bits++ = val.peBlue;
2632                     *bits++ = val.peGreen;
2633                     *bits++ = val.peRed;
2634                     *bits++ = 0;
2635                   }
2636                   bits = (dstbits += linebytes);
2637                 }
2638             }
2639             else goto notsupported;
2640
2641             break;
2642
2643         case 8:
2644             /* ==== 8 colormap bitmap to 32 BGR dib ==== */
2645             if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
2646             {
2647                 BYTE *srcpixel;
2648                 PALETTEENTRY val;
2649
2650                 for (h = lines - 1; h >= 0; h--) {
2651                   srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
2652                   for (x = 0; x < dstwidth; x++) {
2653                     val = srccolors[(int)*srcpixel++];
2654                     *bits++ = val.peBlue;               /*Blue*/
2655                     *bits++ = val.peGreen;              /*Green*/
2656                     *bits++ = val.peRed;                /*Red*/
2657                     *bits++ = 0;
2658                     }
2659                   bits = (dstbits += linebytes);
2660                 }
2661             }
2662             else goto notsupported;
2663             break;
2664
2665         default:
2666         notsupported:
2667             FIXME("from %d bit bitmap with mask R,G,B %x,%x,%x to 32 bit DIB\n",
2668                   bmpImage->depth, (int)bmpImage->red_mask, 
2669                   (int)bmpImage->green_mask, (int)bmpImage->blue_mask );
2670             for (h = lines - 1; h >= 0; h--)
2671               {
2672                 for (x = 0; x < dstwidth; x++, bits += 4)
2673                   {
2674                     COLORREF pixel = X11DRV_PALETTE_ToLogical( XGetPixel( bmpImage, x, h ) );
2675                     bits[0] = GetBValue(pixel);
2676                     bits[1] = GetGValue(pixel);
2677                     bits[2] = GetRValue(pixel);
2678                   }
2679                 bits = (dstbits += linebytes);
2680               }
2681             break;
2682     }
2683 }
2684
2685 /***********************************************************************
2686  *           X11DRV_DIB_SetImageBits
2687  *
2688  * Transfer the bits to an X image.
2689  * Helper function for SetDIBits() and SetDIBitsToDevice().
2690  */
2691 static int X11DRV_DIB_SetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr )
2692 {
2693     int lines = descr->lines >= 0 ? descr->lines : -descr->lines;
2694     XImage *bmpImage;
2695
2696     wine_tsx11_lock();
2697     if (descr->image)
2698         bmpImage = descr->image;
2699     else {
2700         bmpImage = XCreateImage( gdi_display, visual, descr->depth, ZPixmap, 0, NULL,
2701                                  descr->infoWidth, lines, 32, 0 );
2702         bmpImage->data = calloc( lines, bmpImage->bytes_per_line );
2703         if(bmpImage->data == NULL) {
2704             ERR("Out of memory!\n");
2705             XDestroyImage( bmpImage );
2706             wine_tsx11_unlock();
2707             return lines;
2708         }
2709     }
2710
2711       /* Transfer the pixels */
2712     switch(descr->infoBpp)
2713     {
2714     case 1:
2715         X11DRV_DIB_SetImageBits_1( descr->lines, descr->bits, descr->infoWidth,
2716                                    descr->width, descr->xSrc, (int *)(descr->colorMap),
2717                                    bmpImage, descr->dibpitch );
2718         break;
2719     case 4:
2720         if (descr->compression) {
2721             XGetSubImage( gdi_display, descr->drawable, descr->xDest, descr->yDest,
2722                           descr->width, descr->height, AllPlanes, ZPixmap, 
2723                           bmpImage, descr->xSrc, descr->ySrc );
2724
2725             X11DRV_DIB_SetImageBits_RLE4( descr->lines, descr->bits,
2726                                           descr->infoWidth, descr->width,
2727                                           descr->xSrc, (int *)(descr->colorMap),
2728                                           bmpImage );
2729         } else
2730             X11DRV_DIB_SetImageBits_4( descr->lines, descr->bits,
2731                                        descr->infoWidth, descr->width,
2732                                        descr->xSrc, (int*)(descr->colorMap),
2733                                        bmpImage, descr->dibpitch );
2734         break;
2735     case 8:
2736         if (descr->compression) {
2737             XGetSubImage( gdi_display, descr->drawable, descr->xDest, descr->yDest,
2738                           descr->width, descr->height, AllPlanes, ZPixmap, 
2739                           bmpImage, descr->xSrc, descr->ySrc );
2740             X11DRV_DIB_SetImageBits_RLE8( descr->lines, descr->bits,
2741                                           descr->infoWidth, descr->width,
2742                                           descr->xSrc, (int *)(descr->colorMap), 
2743                                           bmpImage );
2744         } else
2745             X11DRV_DIB_SetImageBits_8( descr->lines, descr->bits,
2746                                        descr->infoWidth, descr->width,
2747                                        descr->xSrc, (int *)(descr->colorMap),
2748                                        bmpImage, descr->dibpitch );
2749         break;
2750     case 15:
2751     case 16:
2752         X11DRV_DIB_SetImageBits_16( descr->lines, descr->bits,
2753                                     descr->infoWidth, descr->width,
2754                                    descr->xSrc, descr->dc,
2755                                    descr->rMask, descr->gMask, descr->bMask,
2756                                    bmpImage, descr->dibpitch);
2757         break;
2758     case 24:
2759         X11DRV_DIB_SetImageBits_24( descr->lines, descr->bits,
2760                                     descr->infoWidth, descr->width,
2761                                     descr->xSrc, descr->dc, bmpImage,
2762                                     descr->dibpitch);
2763         break;
2764     case 32:
2765         X11DRV_DIB_SetImageBits_32( descr->lines, descr->bits,
2766                                     descr->infoWidth, descr->width,
2767                                    descr->xSrc, descr->dc,
2768                                    bmpImage, descr->dibpitch);
2769         break;
2770     default:
2771         WARN("(%d): Invalid depth\n", descr->infoBpp );
2772         break;
2773     }
2774
2775     TRACE("XPutImage(%ld,%p,%p,%d,%d,%d,%d,%d,%d)\n",
2776      descr->drawable, descr->gc, bmpImage,
2777      descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
2778      descr->width, descr->height);
2779     if (descr->useShm)
2780     {
2781         XShmPutImage( gdi_display, descr->drawable, descr->gc, bmpImage,
2782                       descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
2783                       descr->width, descr->height, FALSE );
2784         XSync( gdi_display, 0 );
2785     }
2786     else
2787         XPutImage( gdi_display, descr->drawable, descr->gc, bmpImage,
2788                    descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
2789                    descr->width, descr->height );
2790
2791     if (!descr->image) XDestroyImage( bmpImage );
2792     wine_tsx11_unlock();
2793     return lines;
2794 }
2795
2796 /***********************************************************************
2797  *           X11DRV_DIB_GetImageBits
2798  *
2799  * Transfer the bits from an X image.
2800  */
2801 static int X11DRV_DIB_GetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr )
2802 {
2803     int lines = descr->lines >= 0 ? descr->lines : -descr->lines;
2804     XImage *bmpImage;
2805
2806     wine_tsx11_lock(); 
2807    if (descr->image)
2808         bmpImage = descr->image;
2809     else {
2810         bmpImage = XCreateImage( gdi_display, visual, descr->depth, ZPixmap, 0, NULL,
2811                                  descr->infoWidth, lines, 32, 0 );
2812         bmpImage->data = calloc( lines, bmpImage->bytes_per_line );
2813         if(bmpImage->data == NULL) {
2814             ERR("Out of memory!\n");
2815             XDestroyImage( bmpImage );
2816             wine_tsx11_unlock();
2817             return lines;
2818         }
2819     }
2820
2821     TRACE("XGetSubImage(%ld,%d,%d,%d,%d,%ld,%d,%p,%d,%d)\n",
2822      descr->drawable, descr->xSrc, descr->ySrc, descr->width,
2823      lines, AllPlanes, ZPixmap, bmpImage, descr->xDest, descr->yDest);
2824     XGetSubImage( gdi_display, descr->drawable, descr->xSrc, descr->ySrc,
2825                   descr->width, lines, AllPlanes, ZPixmap,
2826                   bmpImage, descr->xDest, descr->yDest );
2827
2828       /* Transfer the pixels */
2829     switch(descr->infoBpp)
2830     {
2831     case 1:
2832           X11DRV_DIB_GetImageBits_1( descr->lines,(LPVOID)descr->bits, 
2833                                      descr->infoWidth, descr->width,
2834                                      descr->colorMap, descr->palentry, 
2835                                      bmpImage, descr->dibpitch );
2836        break;
2837
2838     case 4:
2839        if (descr->compression)
2840            FIXME("Compression not yet supported!\n");
2841        else
2842            X11DRV_DIB_GetImageBits_4( descr->lines,(LPVOID)descr->bits, 
2843                                       descr->infoWidth, descr->width, 
2844                                       descr->colorMap, descr->palentry, 
2845                                       bmpImage, descr->dibpitch );
2846        break;
2847
2848     case 8:
2849        if (descr->compression)
2850            FIXME("Compression not yet supported!\n");
2851        else
2852            X11DRV_DIB_GetImageBits_8( descr->lines, (LPVOID)descr->bits,
2853                                       descr->infoWidth, descr->width,
2854                                       descr->colorMap, descr->palentry,
2855                                       bmpImage, descr->dibpitch );
2856        break;
2857     case 15:
2858     case 16:
2859        X11DRV_DIB_GetImageBits_16( descr->lines, (LPVOID)descr->bits,
2860                                    descr->infoWidth,descr->width,
2861                                    descr->palentry,
2862                                    descr->rMask, descr->gMask, descr->bMask,
2863                                    bmpImage, descr->dibpitch );
2864        break;
2865
2866     case 24:
2867        X11DRV_DIB_GetImageBits_24( descr->lines, (LPVOID)descr->bits,
2868                                    descr->infoWidth,descr->width,
2869                                    descr->palentry, bmpImage, descr->dibpitch);
2870        break;
2871
2872     case 32:
2873        X11DRV_DIB_GetImageBits_32( descr->lines, (LPVOID)descr->bits,
2874                                    descr->infoWidth, descr->width,
2875                                    descr->palentry, bmpImage, descr->dibpitch);
2876        break;
2877
2878     default:
2879         WARN("(%d): Invalid depth\n", descr->infoBpp );
2880         break;
2881     }
2882
2883     if (!descr->image) XDestroyImage( bmpImage );
2884     wine_tsx11_unlock();
2885     return lines;
2886 }
2887
2888 /*************************************************************************
2889  *              X11DRV_SetDIBitsToDevice
2890  *
2891  */
2892 INT X11DRV_SetDIBitsToDevice( DC *dc, INT xDest, INT yDest, DWORD cx,
2893                                 DWORD cy, INT xSrc, INT ySrc,
2894                                 UINT startscan, UINT lines, LPCVOID bits,
2895                                 const BITMAPINFO *info, UINT coloruse )
2896 {
2897     X11DRV_DIB_IMAGEBITS_DESCR descr;
2898     DWORD width, oldcy = cy;
2899     INT result;
2900     int height, tmpheight;
2901     X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
2902
2903
2904     if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, 
2905                            &descr.infoBpp, &descr.compression ) == -1)
2906         return 0;
2907     tmpheight = height;
2908     if (height < 0) height = -height;
2909     if (!lines || (startscan >= height)) return 0;
2910     if (startscan + lines > height) lines = height - startscan;
2911     if (ySrc < startscan) ySrc = startscan;
2912     else if (ySrc >= startscan + lines) return 0;
2913     if (xSrc >= width) return 0;
2914     if (ySrc + cy >= startscan + lines) cy = startscan + lines - ySrc;
2915     if (xSrc + cx >= width) cx = width - xSrc;
2916     if (!cx || !cy) return 0;
2917
2918     X11DRV_SetupGCForText( dc );  /* To have the correct colors */
2919     TSXSetFunction(gdi_display, physDev->gc, X11DRV_XROPfunction[dc->ROPmode-1]);
2920
2921     switch (descr.infoBpp)
2922     {
2923        case 1:
2924        case 4:
2925        case 8:
2926                descr.colorMap = (RGBQUAD *)X11DRV_DIB_BuildColorMap( 
2927                                             coloruse == DIB_PAL_COLORS ? dc : NULL, coloruse,
2928                                             dc->bitsPerPixel, info, &descr.nColorMap );
2929                if (!descr.colorMap) return 0;
2930                descr.rMask = descr.gMask = descr.bMask = 0;
2931                break;
2932        case 15:
2933        case 16:
2934                descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0x7c00;
2935                descr.gMask = (descr.compression == BI_BITFIELDS) ?  *((DWORD *)info->bmiColors + 1) : 0x03e0;
2936                descr.bMask = (descr.compression == BI_BITFIELDS) ?  *((DWORD *)info->bmiColors + 2) : 0x001f;
2937                descr.colorMap = 0;
2938                break;
2939
2940        case 24:
2941                descr.rMask = descr.gMask = descr.bMask = 0;
2942                descr.colorMap = 0;
2943                break;
2944
2945        case 32:
2946                descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0xff0000;
2947                descr.gMask = (descr.compression == BI_BITFIELDS) ?  *((DWORD *)info->bmiColors + 1) : 0xff00;
2948                descr.bMask = (descr.compression == BI_BITFIELDS) ?  *((DWORD *)info->bmiColors + 2) : 0xff;
2949                descr.colorMap = 0;
2950                break;
2951     }
2952
2953     descr.dc        = dc;
2954     descr.bits      = bits;
2955     descr.image     = NULL;
2956     descr.palentry  = NULL;
2957     descr.lines     = tmpheight >= 0 ? lines : -lines;
2958     descr.infoWidth = width;
2959     descr.depth     = dc->bitsPerPixel;
2960     descr.drawable  = physDev->drawable;
2961     descr.gc        = physDev->gc;
2962     descr.xSrc      = xSrc;
2963     descr.ySrc      = tmpheight >= 0 ? lines-(ySrc-startscan)-cy+(oldcy-cy) 
2964                                      : ySrc - startscan;
2965     descr.xDest     = dc->DCOrgX + XLPTODP( dc, xDest );
2966     descr.yDest     = dc->DCOrgY + YLPTODP( dc, yDest ) +
2967                                      (tmpheight >= 0 ? oldcy-cy : 0);
2968     descr.width     = cx;
2969     descr.height    = cy;
2970     descr.useShm    = FALSE;
2971     descr.dibpitch  = ((width * descr.infoBpp + 31) &~31) / 8;
2972
2973     result = X11DRV_DIB_SetImageBits( &descr );
2974
2975     if (descr.infoBpp <= 8)
2976        HeapFree(GetProcessHeap(), 0, descr.colorMap);
2977     return result;
2978 }
2979
2980 /***********************************************************************
2981  *           X11DRV_DIB_SetDIBits
2982  */
2983 INT X11DRV_DIB_SetDIBits(
2984   BITMAPOBJ *bmp, DC *dc, UINT startscan,
2985   UINT lines, LPCVOID bits, const BITMAPINFO *info,
2986   UINT coloruse, HBITMAP hbitmap)
2987 {
2988   X11DRV_DIB_IMAGEBITS_DESCR descr;
2989   int height, tmpheight;
2990   INT result;
2991
2992   descr.dc = dc;
2993
2994   if (DIB_GetBitmapInfo( &info->bmiHeader, &descr.infoWidth, &height,
2995                          &descr.infoBpp, &descr.compression ) == -1)
2996       return 0;
2997
2998   tmpheight = height;
2999   if (height < 0) height = -height;
3000   if (!lines || (startscan >= height))
3001       return 0;
3002
3003   if (startscan + lines > height) lines = height - startscan;
3004
3005   switch (descr.infoBpp)
3006   {
3007        case 1:
3008        case 4:
3009        case 8:
3010                descr.colorMap = (RGBQUAD *)X11DRV_DIB_BuildColorMap(
3011                         coloruse == DIB_PAL_COLORS ? descr.dc : NULL, coloruse,
3012                                                           bmp->bitmap.bmBitsPixel,
3013                                                           info, &descr.nColorMap );
3014                if (!descr.colorMap) return 0;
3015                descr.rMask = descr.gMask = descr.bMask = 0;
3016                break;
3017        case 15:
3018        case 16:
3019                descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0x7c00;
3020                descr.gMask = (descr.compression == BI_BITFIELDS) ?  *((DWORD *)info->bmiColors + 1) : 0x03e0;
3021                descr.bMask = (descr.compression == BI_BITFIELDS) ?  *((DWORD *)info->bmiColors + 2) : 0x001f;
3022                descr.colorMap = 0;
3023                break;
3024
3025        case 24:
3026                descr.rMask = descr.gMask = descr.bMask = 0;
3027                descr.colorMap = 0;
3028                break;
3029
3030        case 32:
3031                descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0xff0000;
3032                descr.gMask = (descr.compression == BI_BITFIELDS) ?  *((DWORD *)info->bmiColors + 1) : 0xff00;
3033                descr.bMask = (descr.compression == BI_BITFIELDS) ?  *((DWORD *)info->bmiColors + 2) : 0xff;
3034                descr.colorMap = 0;
3035                break;
3036
3037        default: break;
3038   }
3039
3040   /* HACK for now */
3041   if(!bmp->physBitmap)
3042     X11DRV_CreateBitmap(hbitmap);
3043
3044   descr.bits      = bits;
3045   descr.image     = NULL;
3046   descr.palentry  = NULL;
3047   descr.lines     = tmpheight >= 0 ? lines : -lines;
3048   descr.depth     = bmp->bitmap.bmBitsPixel;
3049   descr.drawable  = (Pixmap)bmp->physBitmap;
3050   descr.gc        = BITMAP_GC(bmp);
3051   descr.xSrc      = 0;
3052   descr.ySrc      = 0;
3053   descr.xDest     = 0;
3054   descr.yDest     = height - startscan - lines;
3055   descr.width     = bmp->bitmap.bmWidth;
3056   descr.height    = lines;
3057   descr.useShm    = FALSE;
3058   descr.dibpitch  = ((descr.infoWidth * descr.infoBpp + 31) &~31) / 8;
3059   result = X11DRV_DIB_SetImageBits( &descr );
3060
3061   if (descr.colorMap) HeapFree(GetProcessHeap(), 0, descr.colorMap);
3062
3063   return result;
3064 }
3065
3066 /***********************************************************************
3067  *           X11DRV_DIB_GetDIBits
3068  */
3069 INT X11DRV_DIB_GetDIBits(
3070   BITMAPOBJ *bmp, DC *dc, UINT startscan, 
3071   UINT lines, LPVOID bits, BITMAPINFO *info,
3072   UINT coloruse, HBITMAP hbitmap)
3073 {
3074   X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
3075   X11DRV_DIB_IMAGEBITS_DESCR descr;
3076   PALETTEOBJ * palette;
3077   int height;
3078   
3079   TRACE("%u scanlines of (%i,%i) -> (%i,%i) starting from %u\n",
3080         lines, bmp->bitmap.bmWidth, bmp->bitmap.bmHeight,
3081         (int)info->bmiHeader.biWidth, (int)info->bmiHeader.biHeight,
3082         startscan );
3083
3084   if (!(palette = (PALETTEOBJ*)GDI_GetObjPtr( dc->hPalette, PALETTE_MAGIC )))
3085       return 0;
3086
3087   if( lines > bmp->bitmap.bmHeight ) lines = bmp->bitmap.bmHeight;
3088
3089   height = info->bmiHeader.biHeight;
3090   if (height < 0) height = -height;
3091   if( lines > height ) lines = height;
3092   /* Top-down images have a negative biHeight, the scanlines of theses images
3093    * were inverted in X11DRV_DIB_GetImageBits_xx
3094    * To prevent this we simply change the sign of lines
3095    * (the number of scan lines to copy).
3096    * Negative lines are correctly handled by X11DRV_DIB_GetImageBits_xx.
3097    */
3098   if( info->bmiHeader.biHeight < 0 && lines > 0) lines = -lines;
3099
3100   if( startscan >= bmp->bitmap.bmHeight )
3101   {
3102       lines = 0;
3103       goto done;
3104   }
3105   
3106   if (DIB_GetBitmapInfo( &info->bmiHeader, &descr.infoWidth, &descr.lines,
3107                         &descr.infoBpp, &descr.compression ) == -1)
3108   {
3109       lines = 0;
3110       goto done;
3111   }
3112
3113   switch (descr.infoBpp)
3114   {
3115       case 1:
3116       case 4:
3117       case 8:
3118       case 24:
3119           descr.rMask = descr.gMask = descr.bMask = 0;
3120           break;
3121       case 15:
3122       case 16:
3123           descr.rMask = 0x7c00;
3124           descr.gMask = 0x03e0;
3125           descr.bMask = 0x001f;
3126           break;
3127   
3128       case 32:
3129           descr.rMask = 0xff0000;
3130           descr.gMask = 0xff00;
3131           descr.bMask = 0xff;
3132           break;
3133   }
3134
3135   /* Hack for now */
3136   if(!bmp->physBitmap)
3137     X11DRV_CreateBitmap(hbitmap);
3138
3139
3140   descr.dc        = dc;
3141   descr.palentry  = palette->logpalette.palPalEntry;
3142   descr.bits      = bits;
3143   descr.image     = NULL;
3144   descr.lines     = lines;
3145   descr.depth     = bmp->bitmap.bmBitsPixel;
3146   descr.drawable  = (Pixmap)bmp->physBitmap;
3147   descr.gc        = BITMAP_GC(bmp);
3148   descr.width     = bmp->bitmap.bmWidth;
3149   descr.height    = bmp->bitmap.bmHeight;
3150   descr.colorMap  = info->bmiColors;
3151   descr.xDest     = 0;
3152   descr.yDest     = 0;
3153   descr.xSrc      = 0;
3154   
3155   if (descr.lines > 0)
3156   {
3157      descr.ySrc = (descr.height-1) - (startscan + (lines-1));
3158   }
3159   else
3160   {
3161      descr.ySrc = startscan;
3162   }
3163 #ifdef HAVE_LIBXXSHM
3164   descr.useShm = dib ? (dib->shminfo.shmid != -1) : FALSE;
3165 #else
3166   descr.useShm = FALSE;
3167 #endif
3168   descr.dibpitch = dib ? (dib->dibSection.dsBm.bmWidthBytes)
3169                        : (((descr.infoWidth * descr.infoBpp + 31) &~31) / 8);
3170
3171   X11DRV_DIB_GetImageBits( &descr );
3172
3173   if(info->bmiHeader.biSizeImage == 0) /* Fill in biSizeImage */
3174       info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes(
3175                                          info->bmiHeader.biWidth,
3176                                          info->bmiHeader.biHeight,
3177                                          info->bmiHeader.biBitCount );
3178
3179   info->bmiHeader.biCompression = 0;
3180   if (descr.compression == BI_BITFIELDS)
3181   {
3182     *(DWORD *)info->bmiColors = descr.rMask;
3183     *((DWORD *)info->bmiColors+1) = descr.gMask;
3184     *((DWORD *)info->bmiColors+2) = descr.bMask;
3185   }
3186
3187 done:
3188   GDI_ReleaseObj( dc->hPalette );
3189  
3190   return lines;
3191 }
3192
3193 /***********************************************************************
3194  *           DIB_DoProtectDIBSection
3195  */
3196 static void X11DRV_DIB_DoProtectDIBSection( BITMAPOBJ *bmp, DWORD new_prot )
3197 {
3198     DIBSECTION *dib = bmp->dib;
3199     INT effHeight = dib->dsBm.bmHeight >= 0? dib->dsBm.bmHeight
3200                                              : -dib->dsBm.bmHeight;
3201     /* use the biSizeImage data as the memory size only if we're dealing with a
3202        compressed image where the value is set.  Otherwise, calculate based on
3203        width * height */
3204     INT totalSize = dib->dsBmih.biSizeImage && dib->dsBmih.biCompression != BI_RGB
3205                          ? dib->dsBmih.biSizeImage
3206                          : dib->dsBm.bmWidthBytes * effHeight;
3207     DWORD old_prot;
3208
3209     VirtualProtect(dib->dsBm.bmBits, totalSize, new_prot, &old_prot);
3210     TRACE("Changed protection from %ld to %ld\n", old_prot, new_prot);
3211 }
3212
3213 /***********************************************************************
3214  *           X11DRV_DIB_DoUpdateDIBSection
3215  */
3216 static void X11DRV_DIB_DoCopyDIBSection(BITMAPOBJ *bmp, BOOL toDIB,
3217                                         void *colorMap, int nColorMap,
3218                                         Drawable dest,
3219                                         DWORD xSrc, DWORD ySrc,
3220                                         DWORD xDest, DWORD yDest,
3221                                         DWORD width, DWORD height)
3222 {
3223   X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
3224   X11DRV_DIB_IMAGEBITS_DESCR descr;
3225   
3226   if (DIB_GetBitmapInfo( &dib->dibSection.dsBmih, &descr.infoWidth, &descr.lines,
3227                          &descr.infoBpp, &descr.compression ) == -1)
3228     return;
3229
3230   descr.dc        = NULL;
3231   descr.palentry  = NULL;
3232   descr.image     = dib->image;
3233   descr.colorMap  = colorMap;
3234   descr.nColorMap = nColorMap;
3235   descr.bits      = dib->dibSection.dsBm.bmBits;
3236   descr.depth     = bmp->bitmap.bmBitsPixel;
3237   
3238   switch (descr.infoBpp)
3239   {
3240     case 1:
3241     case 4:
3242     case 8:
3243     case 24:
3244       descr.rMask = descr.gMask = descr.bMask = 0;
3245       break;
3246     case 15:
3247     case 16:
3248       descr.rMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[0] : 0x7c00;
3249       descr.gMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[1] : 0x03e0;
3250       descr.bMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[2] : 0x001f;
3251       break;
3252
3253     case 32:
3254       descr.rMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[0] : 0xff;
3255       descr.gMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[1] : 0xff00;
3256       descr.bMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[2] : 0xff0000;
3257       break;
3258   }
3259
3260   /* Hack for now */
3261   descr.drawable  = dest;
3262   descr.gc        = BITMAP_GC(bmp);
3263   descr.xSrc      = xSrc;
3264   descr.ySrc      = ySrc;
3265   descr.xDest     = xDest;
3266   descr.yDest     = yDest;
3267   descr.width     = width;
3268   descr.height    = height;
3269 #ifdef HAVE_LIBXXSHM
3270   descr.useShm = (dib->shminfo.shmid != -1);
3271 #else
3272   descr.useShm = FALSE;
3273 #endif
3274   descr.dibpitch = dib->dibSection.dsBm.bmWidthBytes;
3275
3276   if (toDIB)
3277     {
3278       TRACE("Copying from Pixmap to DIB bits\n");
3279       X11DRV_DIB_GetImageBits( &descr );
3280     }
3281   else
3282     {
3283       TRACE("Copying from DIB bits to Pixmap\n"); 
3284       X11DRV_DIB_SetImageBits( &descr );
3285     }
3286 }
3287
3288 /***********************************************************************
3289  *           X11DRV_DIB_CopyDIBSection
3290  */
3291 void X11DRV_DIB_CopyDIBSection(DC *dcSrc, DC *dcDst,
3292                                DWORD xSrc, DWORD ySrc,
3293                                DWORD xDest, DWORD yDest,
3294                                DWORD width, DWORD height)
3295 {
3296   BITMAPOBJ *bmp;
3297   X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dcDst->physDev;
3298   int nColorMap = 0, *colorMap = NULL, aColorMap = FALSE;
3299
3300   TRACE("(%p,%p,%ld,%ld,%ld,%ld,%ld,%ld)\n", dcSrc, dcDst,
3301     xSrc, ySrc, xDest, yDest, width, height);
3302   /* this function is meant as an optimization for BitBlt,
3303    * not to be called otherwise */
3304   if (!(dcSrc->flags & DC_MEMORY)) {
3305     ERR("called for non-memory source DC!?\n");
3306     return;
3307   }
3308
3309   bmp = (BITMAPOBJ *)GDI_GetObjPtr( dcSrc->hBitmap, BITMAP_MAGIC );
3310   if (!(bmp && bmp->dib)) {
3311     ERR("called for non-DIBSection!?\n");
3312     GDI_ReleaseObj( dcSrc->hBitmap );
3313     return;
3314   }
3315   /* while BitBlt should already have made sure we only get
3316    * positive values, we should check for oversize values */
3317   if ((xSrc < bmp->bitmap.bmWidth) &&
3318       (ySrc < bmp->bitmap.bmHeight)) {
3319     if (xSrc + width > bmp->bitmap.bmWidth)
3320       width = bmp->bitmap.bmWidth - xSrc;
3321     if (ySrc + height > bmp->bitmap.bmHeight)
3322       height = bmp->bitmap.bmHeight - ySrc;
3323     /* if the source bitmap is 8bpp or less, we're supposed to use the
3324      * DC's palette for color conversion (not the DIB color table) */
3325     if (bmp->dib->dsBm.bmBitsPixel <= 8) {
3326       X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
3327       if ((!dcSrc->hPalette) ||
3328           (dcSrc->hPalette == GetStockObject(DEFAULT_PALETTE))) {
3329         /* HACK: no palette has been set in the source DC,
3330          * use the DIB colormap instead - this is necessary in some
3331          * cases since we need to do depth conversion in some places
3332          * where real Windows can just copy data straight over */
3333         colorMap = dib->colorMap;
3334         nColorMap = dib->nColorMap;
3335       } else {
3336         colorMap = X11DRV_DIB_BuildColorMap( dcSrc, (WORD)-1,
3337                                              bmp->dib->dsBm.bmBitsPixel,
3338                                              (BITMAPINFO*)&(bmp->dib->dsBmih),
3339                                              &nColorMap );
3340         if (colorMap) aColorMap = TRUE;
3341       }
3342     }
3343     /* perform the copy */
3344     X11DRV_DIB_DoCopyDIBSection(bmp, FALSE, colorMap, nColorMap,
3345                                 physDev->drawable, xSrc, ySrc, xDest, yDest,
3346                                 width, height);
3347     /* free color mapping */
3348     if (aColorMap)
3349       HeapFree(GetProcessHeap(), 0, colorMap);
3350   }
3351   GDI_ReleaseObj( dcSrc->hBitmap );
3352 }
3353
3354 /***********************************************************************
3355  *           X11DRV_DIB_DoUpdateDIBSection
3356  */
3357 static void X11DRV_DIB_DoUpdateDIBSection(BITMAPOBJ *bmp, BOOL toDIB)
3358 {
3359   X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
3360   X11DRV_DIB_DoCopyDIBSection(bmp, toDIB, dib->colorMap, dib->nColorMap,
3361                               (Drawable)bmp->physBitmap, 0, 0, 0, 0,
3362                               bmp->bitmap.bmWidth, bmp->bitmap.bmHeight);
3363 }
3364
3365 /***********************************************************************
3366  *           X11DRV_DIB_FaultHandler
3367  */
3368 static BOOL X11DRV_DIB_FaultHandler( LPVOID res, LPCVOID addr )
3369 {
3370   BITMAPOBJ *bmp;
3371   INT state;
3372   
3373   bmp = (BITMAPOBJ *)GDI_GetObjPtr( (HBITMAP)res, BITMAP_MAGIC );
3374   if (!bmp) return FALSE;
3375
3376   state = X11DRV_DIB_Lock(bmp, DIB_Status_None, FALSE);
3377   if (state != DIB_Status_InSync) {
3378     /* no way to tell whether app needs read or write yet,
3379      * try read first */
3380     X11DRV_DIB_Coerce(bmp, DIB_Status_InSync, FALSE);
3381   } else {
3382     /* hm, apparently the app must have write access */
3383     X11DRV_DIB_Coerce(bmp, DIB_Status_AppMod, FALSE);
3384   }
3385   X11DRV_DIB_Unlock(bmp, TRUE);
3386
3387   GDI_ReleaseObj( (HBITMAP)res );
3388   return TRUE;
3389 }
3390
3391 /***********************************************************************
3392  *           X11DRV_DIB_Coerce
3393  */
3394 INT X11DRV_DIB_Coerce(BITMAPOBJ *bmp, INT req, BOOL lossy)
3395 {
3396   X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
3397   INT ret = DIB_Status_None;
3398
3399   if (dib) {
3400     EnterCriticalSection(&(dib->lock));
3401     ret = dib->status;
3402     switch (req) {
3403     case DIB_Status_GdiMod:
3404       /* GDI access - request to draw on pixmap */
3405       switch (dib->status)
3406       {
3407         default:
3408         case DIB_Status_None:
3409           dib->p_status = DIB_Status_GdiMod;
3410           X11DRV_DIB_DoUpdateDIBSection( bmp, FALSE );
3411           break;
3412
3413         case DIB_Status_GdiMod:
3414           TRACE("GdiMod requested in status GdiMod\n" );
3415           break;
3416
3417         case DIB_Status_InSync:
3418           TRACE("GdiMod requested in status InSync\n" );
3419           X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS );
3420           dib->status = DIB_Status_GdiMod;
3421           dib->p_status = DIB_Status_InSync;
3422           break;
3423
3424         case DIB_Status_AuxMod:
3425           TRACE("GdiMod requested in status AuxMod\n" );
3426           if (lossy) dib->status = DIB_Status_GdiMod;
3427           else (*dib->copy_aux)(dib->aux_ctx, DIB_Status_GdiMod);
3428           dib->p_status = DIB_Status_AuxMod;
3429           if (dib->status != DIB_Status_AppMod) {
3430             X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS );
3431             break;
3432           }
3433           /* fall through if copy_aux() had to change to AppMod state */
3434
3435         case DIB_Status_AppMod:
3436           TRACE("GdiMod requested in status AppMod\n" );
3437           if (!lossy) {
3438             /* make it readonly to avoid app changing data while we copy */
3439             X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
3440             X11DRV_DIB_DoUpdateDIBSection( bmp, FALSE );
3441           }
3442           X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS );
3443           dib->p_status = DIB_Status_AppMod;
3444           dib->status = DIB_Status_GdiMod;
3445           break;
3446       }
3447       break;
3448
3449     case DIB_Status_InSync:
3450       /* App access - request access to read DIB surface */
3451       /* (typically called from signal handler) */
3452       switch (dib->status)
3453       {
3454         default:
3455         case DIB_Status_None:
3456           /* shouldn't happen from signal handler */
3457           break;
3458
3459         case DIB_Status_AuxMod:
3460           TRACE("InSync requested in status AuxMod\n" );
3461           if (lossy) dib->status = DIB_Status_InSync;
3462           else {
3463             X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
3464             (*dib->copy_aux)(dib->aux_ctx, DIB_Status_InSync);
3465           }
3466           if (dib->status != DIB_Status_GdiMod) {
3467             X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
3468             break;
3469           }
3470           /* fall through if copy_aux() had to change to GdiMod state */
3471
3472         case DIB_Status_GdiMod:
3473           TRACE("InSync requested in status GdiMod\n" );
3474           if (!lossy) {
3475             X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
3476             X11DRV_DIB_DoUpdateDIBSection( bmp, TRUE );
3477           }
3478           X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
3479           dib->status = DIB_Status_InSync;
3480           break;
3481
3482         case DIB_Status_InSync:
3483           TRACE("InSync requested in status InSync\n" );
3484           /* shouldn't happen from signal handler */
3485           break;
3486
3487         case DIB_Status_AppMod:
3488           TRACE("InSync requested in status AppMod\n" );
3489           /* no reason to do anything here, and this
3490            * shouldn't happen from signal handler */
3491           break;
3492       }
3493       break;
3494
3495     case DIB_Status_AppMod:
3496       /* App access - request access to write DIB surface */
3497       /* (typically called from signal handler) */
3498       switch (dib->status)
3499       {
3500         default:
3501         case DIB_Status_None:
3502           /* shouldn't happen from signal handler */
3503           break;
3504
3505         case DIB_Status_AuxMod:
3506           TRACE("AppMod requested in status AuxMod\n" );
3507           X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
3508           if (lossy) dib->status = DIB_Status_AppMod;
3509           else (*dib->copy_aux)(dib->aux_ctx, DIB_Status_AppMod);
3510           if (dib->status != DIB_Status_GdiMod)
3511             break;
3512           /* fall through if copy_aux() had to change to GdiMod state */
3513
3514         case DIB_Status_GdiMod:
3515           TRACE("AppMod requested in status GdiMod\n" );
3516           X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
3517           if (!lossy) X11DRV_DIB_DoUpdateDIBSection( bmp, TRUE );
3518           dib->status = DIB_Status_AppMod;
3519           break;
3520
3521         case DIB_Status_InSync:
3522           TRACE("AppMod requested in status InSync\n" );
3523           X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
3524           dib->status = DIB_Status_AppMod;
3525           break;
3526
3527         case DIB_Status_AppMod:
3528           TRACE("AppMod requested in status AppMod\n" );
3529           /* shouldn't happen from signal handler */
3530           break;
3531       }
3532       break;
3533
3534     case DIB_Status_AuxMod:
3535       if (dib->status == DIB_Status_None) {
3536         dib->p_status = req;
3537       } else {
3538         if (dib->status != DIB_Status_AuxMod)
3539           dib->p_status = dib->status;
3540         dib->status = DIB_Status_AuxMod;
3541       }
3542       break;
3543       /* it is up to the caller to do the copy/conversion, probably
3544        * using the return value to decide where to copy from */
3545     }
3546     LeaveCriticalSection(&(dib->lock));
3547   }
3548   return ret;
3549 }
3550
3551 /***********************************************************************
3552  *           X11DRV_DIB_Lock
3553  */
3554 INT X11DRV_DIB_Lock(BITMAPOBJ *bmp, INT req, BOOL lossy)
3555 {
3556   X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
3557   INT ret = DIB_Status_None;
3558
3559   if (dib) {
3560     TRACE("Locking %p from thread %08lx\n", bmp, GetCurrentThreadId());
3561     EnterCriticalSection(&(dib->lock));
3562     ret = dib->status;
3563     if (req != DIB_Status_None)
3564       X11DRV_DIB_Coerce(bmp, req, lossy);
3565   }
3566   return ret;
3567 }
3568
3569 /***********************************************************************
3570  *           X11DRV_DIB_Unlock
3571  */
3572 void X11DRV_DIB_Unlock(BITMAPOBJ *bmp, BOOL commit)
3573 {
3574   X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
3575
3576   if (dib) {
3577     switch (dib->status)
3578     {
3579       default:
3580       case DIB_Status_None:
3581         /* in case anyone is wondering, this is the "signal handler doesn't
3582          * work" case, where we always have to be ready for app access */
3583         if (commit) {
3584           switch (dib->p_status)
3585           {
3586             case DIB_Status_AuxMod:
3587               TRACE("Unlocking and syncing from AuxMod\n" );
3588               (*dib->copy_aux)(dib->aux_ctx, DIB_Status_AppMod);
3589               if (dib->status != DIB_Status_None) {
3590                 dib->p_status = dib->status;
3591                 dib->status = DIB_Status_None;
3592               }
3593               if (dib->p_status != DIB_Status_GdiMod)
3594                 break;
3595               /* fall through if copy_aux() had to change to GdiMod state */
3596
3597             case DIB_Status_GdiMod:
3598               TRACE("Unlocking and syncing from GdiMod\n" );
3599               X11DRV_DIB_DoUpdateDIBSection( bmp, TRUE );
3600               break;
3601
3602             default:
3603               TRACE("Unlocking without needing to sync\n" );
3604               break;
3605           }
3606         }
3607         else TRACE("Unlocking with no changes\n");
3608         dib->p_status = DIB_Status_None;
3609         break;
3610
3611       case DIB_Status_GdiMod:
3612         TRACE("Unlocking in status GdiMod\n" );
3613         /* DIB was protected in Coerce */
3614         if (!commit) {
3615           /* no commit, revert to InSync if applicable */
3616           if ((dib->p_status == DIB_Status_InSync) ||
3617               (dib->p_status == DIB_Status_AppMod)) {
3618             X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
3619             dib->status = DIB_Status_InSync;
3620           }
3621         }
3622         break;
3623
3624       case DIB_Status_InSync:
3625         TRACE("Unlocking in status InSync\n" );
3626         /* DIB was already protected in Coerce */
3627         break;
3628
3629       case DIB_Status_AppMod:
3630         TRACE("Unlocking in status AppMod\n" );
3631         /* DIB was already protected in Coerce */
3632         /* this case is ordinary only called from the signal handler,
3633          * so we don't bother to check for !commit */
3634         break;
3635
3636       case DIB_Status_AuxMod:
3637         TRACE("Unlocking in status AuxMod\n" );
3638         if (commit) {
3639           /* DIB may need protection now */
3640           if ((dib->p_status == DIB_Status_InSync) ||
3641               (dib->p_status == DIB_Status_AppMod))
3642             X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS );
3643         } else {
3644           /* no commit, revert to previous state */
3645           if (dib->p_status != DIB_Status_None)
3646             dib->status = dib->p_status;
3647           /* no protections changed */
3648         }
3649         dib->p_status = DIB_Status_None;
3650         break;
3651     }
3652     LeaveCriticalSection(&(dib->lock));
3653     TRACE("Unlocked %p\n", bmp);
3654   }
3655 }
3656
3657 /***********************************************************************
3658  *           X11DRV_CoerceDIBSection2
3659  */
3660 INT X11DRV_CoerceDIBSection2(HBITMAP hBmp, INT req, BOOL lossy)
3661 {
3662   BITMAPOBJ *bmp;
3663   INT ret;
3664
3665   bmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
3666   if (!bmp) return DIB_Status_None;
3667   ret = X11DRV_DIB_Coerce(bmp, req, lossy);
3668   GDI_ReleaseObj( hBmp );
3669   return ret;
3670 }
3671
3672 /***********************************************************************
3673  *           X11DRV_LockDIBSection2
3674  */
3675 INT X11DRV_LockDIBSection2(HBITMAP hBmp, INT req, BOOL lossy)
3676 {
3677   BITMAPOBJ *bmp;
3678   INT ret;
3679
3680   bmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
3681   if (!bmp) return DIB_Status_None;
3682   ret = X11DRV_DIB_Lock(bmp, req, lossy);
3683   GDI_ReleaseObj( hBmp );
3684   return ret;
3685 }
3686
3687 /***********************************************************************
3688  *           X11DRV_UnlockDIBSection2
3689  */
3690 void X11DRV_UnlockDIBSection2(HBITMAP hBmp, BOOL commit)
3691 {
3692   BITMAPOBJ *bmp;
3693
3694   bmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
3695   if (!bmp) return;
3696   X11DRV_DIB_Unlock(bmp, commit);
3697   GDI_ReleaseObj( hBmp );
3698 }
3699
3700 /***********************************************************************
3701  *           X11DRV_CoerceDIBSection
3702  */
3703 INT X11DRV_CoerceDIBSection(DC *dc, INT req, BOOL lossy)
3704 {
3705   if (!dc) return DIB_Status_None;
3706   return X11DRV_CoerceDIBSection2( dc->hBitmap, req, lossy );
3707 }
3708
3709 /***********************************************************************
3710  *           X11DRV_LockDIBSection
3711  */
3712 INT X11DRV_LockDIBSection(DC *dc, INT req, BOOL lossy)
3713 {
3714   if (!dc) return DIB_Status_None;
3715   if (!(dc->flags & DC_MEMORY)) return DIB_Status_None;
3716
3717   return X11DRV_LockDIBSection2( dc->hBitmap, req, lossy );
3718 }
3719
3720 /***********************************************************************
3721  *           X11DRV_UnlockDIBSection
3722  */
3723 void X11DRV_UnlockDIBSection(DC *dc, BOOL commit)
3724 {
3725   if (!dc) return;
3726   if (!(dc->flags & DC_MEMORY)) return;
3727
3728   X11DRV_UnlockDIBSection2( dc->hBitmap, commit );
3729 }
3730
3731 /***********************************************************************
3732  *           X11DRV_DIB_CreateDIBSection16
3733  */
3734 HBITMAP16 X11DRV_DIB_CreateDIBSection16(
3735   DC *dc, BITMAPINFO *bmi, UINT16 usage,
3736   SEGPTR *bits, HANDLE section,
3737   DWORD offset, DWORD ovr_pitch)
3738 {
3739   HBITMAP res = X11DRV_DIB_CreateDIBSection(dc, bmi, usage, NULL, 
3740                                             section, offset, ovr_pitch);
3741   if ( res )
3742     {
3743       BITMAPOBJ *bmp = (BITMAPOBJ *) GDI_GetObjPtr(res, BITMAP_MAGIC);
3744       if ( bmp && bmp->dib )
3745         {
3746           DIBSECTION *dib = bmp->dib;
3747           INT height = dib->dsBm.bmHeight >= 0 ?
3748             dib->dsBm.bmHeight : -dib->dsBm.bmHeight;
3749           /* same as above - only use biSizeImage as the correct size if it a
3750              compressed image and it's currently non-zero.  In other cases, use
3751              width * height as the value. */
3752           INT size = dib->dsBmih.biSizeImage && dib->dsBmih.biCompression != BI_RGB
3753             ? dib->dsBmih.biSizeImage
3754             : dib->dsBm.bmWidthBytes * height;
3755           if ( dib->dsBm.bmBits )
3756             {
3757               ((X11DRV_DIBSECTION *) bmp->dib)->selector = 
3758                   SELECTOR_AllocBlock( dib->dsBm.bmBits, size, WINE_LDT_FLAGS_DATA );
3759             }
3760           TRACE("ptr = %p, size =%d, selector = %04x, segptr = %ld\n",
3761                          dib->dsBm.bmBits, size, ((X11DRV_DIBSECTION *) bmp->dib)->selector,
3762                          MAKESEGPTR(((X11DRV_DIBSECTION *) bmp->dib)->selector, 0));
3763       if ( bits ) 
3764         *bits = MAKESEGPTR( ((X11DRV_DIBSECTION *) bmp->dib)->selector, 0 );
3765     }
3766       if (bmp) GDI_ReleaseObj( res );
3767     }
3768
3769     return res;
3770 }
3771
3772 /***********************************************************************
3773  *           X11DRV_XShmErrorHandler
3774  *
3775  */
3776 static int XShmErrorHandler(Display *dpy, XErrorEvent *event) 
3777 {
3778     XShmErrorFlag = 1;
3779     return 0;
3780 }
3781
3782 /***********************************************************************
3783  *           X11DRV_XShmCreateImage
3784  *
3785  */
3786
3787 #ifdef HAVE_LIBXXSHM
3788 static XImage *X11DRV_XShmCreateImage( int width, int height, int bpp,
3789                                        XShmSegmentInfo* shminfo)
3790 {
3791     int (*WineXHandler)(Display *, XErrorEvent *);
3792     XImage *image;
3793
3794     wine_tsx11_lock();
3795     image = XShmCreateImage(gdi_display, visual, bpp, ZPixmap, NULL, shminfo, width, height);
3796     if (image)
3797     {
3798         shminfo->shmid = shmget(IPC_PRIVATE, image->bytes_per_line * height,
3799                                   IPC_CREAT|0700);
3800         if( shminfo->shmid != -1 )
3801         {
3802             shminfo->shmaddr = image->data = shmat(shminfo->shmid, 0, 0);
3803             if( shminfo->shmaddr != (char*)-1 )
3804             {
3805                 shminfo->readOnly = FALSE;
3806                 if( XShmAttach( gdi_display, shminfo ) != 0)
3807                 {
3808                     /* Reset the error flag */
3809                     XShmErrorFlag = 0;
3810                     WineXHandler = XSetErrorHandler(XShmErrorHandler);
3811                     XSync( gdi_display, 0 );
3812
3813                     if (!XShmErrorFlag)
3814                     {
3815                         shmctl(shminfo->shmid, IPC_RMID, 0);
3816
3817                         XSetErrorHandler(WineXHandler);
3818                         wine_tsx11_unlock();
3819                         return image; /* Success! */
3820                     }
3821                     /* An error occured */
3822                     XShmErrorFlag = 0;
3823                     XSetErrorHandler(WineXHandler);
3824                 }
3825                 shmdt(shminfo->shmaddr);
3826             }
3827             shmctl(shminfo->shmid, IPC_RMID, 0);
3828         }
3829         XFlush(gdi_display);
3830         XDestroyImage(image);
3831         image = NULL;
3832     }
3833     wine_tsx11_unlock();
3834     return image;
3835 }
3836 #endif /* HAVE_LIBXXSHM */
3837
3838
3839 /***********************************************************************
3840  *           X11DRV_DIB_CreateDIBSection
3841  */
3842 HBITMAP X11DRV_DIB_CreateDIBSection(
3843   DC *dc, BITMAPINFO *bmi, UINT usage,
3844   LPVOID *bits, HANDLE section,
3845   DWORD offset, DWORD ovr_pitch)
3846 {
3847   HBITMAP res = 0;
3848   BITMAPOBJ *bmp = NULL;
3849   X11DRV_DIBSECTION *dib = NULL;
3850   int *colorMap = NULL;
3851   int nColorMap;
3852   
3853   /* Fill BITMAP32 structure with DIB data */
3854   BITMAPINFOHEADER *bi = &bmi->bmiHeader;
3855   INT effHeight, totalSize;
3856   BITMAP bm;
3857   LPVOID mapBits = NULL;
3858   
3859   TRACE("format (%ld,%ld), planes %d, bpp %d, size %ld, colors %ld (%s)\n",
3860         bi->biWidth, bi->biHeight, bi->biPlanes, bi->biBitCount,
3861         bi->biSizeImage, bi->biClrUsed, usage == DIB_PAL_COLORS? "PAL" : "RGB");
3862   
3863   effHeight = bi->biHeight >= 0 ? bi->biHeight : -bi->biHeight;
3864   bm.bmType = 0;
3865   bm.bmWidth = bi->biWidth;
3866   bm.bmHeight = effHeight;
3867   bm.bmWidthBytes = ovr_pitch ? ovr_pitch
3868                               : DIB_GetDIBWidthBytes(bm.bmWidth, bi->biBitCount);
3869   bm.bmPlanes = bi->biPlanes;
3870   bm.bmBitsPixel = bi->biBitCount;
3871   bm.bmBits = NULL;
3872   
3873   /* Get storage location for DIB bits.  Only use biSizeImage if it's valid and
3874      we're dealing with a compressed bitmap.  Otherwise, use width * height. */
3875   totalSize = bi->biSizeImage && bi->biCompression != BI_RGB
3876     ? bi->biSizeImage : bm.bmWidthBytes * effHeight;
3877   
3878   if (section)
3879   {
3880       SYSTEM_INFO SystemInfo;
3881       DWORD mapOffset;
3882       INT mapSize;
3883
3884       GetSystemInfo( &SystemInfo );
3885       mapOffset = offset - (offset % SystemInfo.dwAllocationGranularity);
3886       mapSize = totalSize + (offset - mapOffset);
3887       mapBits = MapViewOfFile( section,
3888                                FILE_MAP_ALL_ACCESS, 
3889                                0L,
3890                                mapOffset,
3891                                mapSize );
3892       bm.bmBits = (char *)mapBits + (offset - mapOffset);
3893   }
3894   else if (ovr_pitch && offset)
3895     bm.bmBits = (LPVOID) offset;
3896   else {
3897     offset = 0;
3898     bm.bmBits = VirtualAlloc(NULL, totalSize, 
3899                              MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
3900   }
3901   
3902   /* Create Color Map */
3903   if (bm.bmBits && bm.bmBitsPixel <= 8)
3904       colorMap = X11DRV_DIB_BuildColorMap( usage == DIB_PAL_COLORS? dc : NULL, 
3905                                 usage, bm.bmBitsPixel, bmi, &nColorMap );
3906
3907   /* Allocate Memory for DIB and fill structure */
3908   if (bm.bmBits)
3909     dib = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(X11DRV_DIBSECTION));
3910   if (dib)
3911     {
3912       dib->dibSection.dsBm = bm;
3913       dib->dibSection.dsBmih = *bi;
3914       dib->dibSection.dsBmih.biSizeImage = totalSize;
3915
3916       /* Set dsBitfields values */
3917        if ( usage == DIB_PAL_COLORS || bi->biBitCount <= 8)
3918        {
3919            dib->dibSection.dsBitfields[0] = dib->dibSection.dsBitfields[1] = dib->dibSection.dsBitfields[2] = 0;
3920        }
3921        else switch( bi->biBitCount )
3922        {
3923            case 16:
3924                dib->dibSection.dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)bmi->bmiColors : 0x7c00;
3925                dib->dibSection.dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 1) : 0x03e0;
3926                dib->dibSection.dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 2) : 0x001f;
3927                break;
3928
3929            case 24:
3930                dib->dibSection.dsBitfields[0] = 0xff;
3931                dib->dibSection.dsBitfields[1] = 0xff00;
3932                dib->dibSection.dsBitfields[2] = 0xff0000;
3933                break;
3934
3935            case 32:
3936                dib->dibSection.dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)bmi->bmiColors : 0xff;
3937                dib->dibSection.dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 1) : 0xff00;
3938                dib->dibSection.dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 2) : 0xff0000;
3939                break;
3940        }
3941       dib->dibSection.dshSection = section;
3942       dib->dibSection.dsOffset = offset;
3943       
3944       dib->status    = DIB_Status_None;
3945       dib->selector  = 0;
3946       
3947       dib->nColorMap = nColorMap;
3948       dib->colorMap  = colorMap;
3949     }
3950   
3951   /* Create Device Dependent Bitmap and add DIB pointer */
3952   if (dib) 
3953     {
3954       res = CreateDIBitmap(dc->hSelf, bi, 0, NULL, bmi, usage);
3955       if (res)
3956         {
3957           bmp = (BITMAPOBJ *) GDI_GetObjPtr(res, BITMAP_MAGIC);
3958           if (bmp)
3959             {
3960               bmp->dib = (DIBSECTION *) dib;
3961               /* HACK for now */
3962               if(!bmp->physBitmap)
3963                 X11DRV_CreateBitmap(res); 
3964             }
3965         }
3966     }
3967   
3968   /* Create XImage */
3969   if (dib && bmp)
3970   {
3971 #ifdef HAVE_LIBXXSHM
3972       if (TSXShmQueryExtension(gdi_display) &&
3973           (dib->image = X11DRV_XShmCreateImage( bm.bmWidth, effHeight,
3974                                                 bmp->bitmap.bmBitsPixel, &dib->shminfo )) )
3975       {
3976         ; /* Created Image */
3977       } else {
3978           dib->image = X11DRV_DIB_CreateXImage( bm.bmWidth, effHeight, bmp->bitmap.bmBitsPixel );
3979           dib->shminfo.shmid = -1;
3980       }
3981 #else
3982       dib->image = X11DRV_DIB_CreateXImage( bm.bmWidth, effHeight, bmp->bitmap.bmBitsPixel );
3983 #endif
3984   }
3985   
3986   /* Clean up in case of errors */
3987   if (!res || !bmp || !dib || !bm.bmBits || (bm.bmBitsPixel <= 8 && !colorMap))
3988     {
3989       TRACE("got an error res=%08x, bmp=%p, dib=%p, bm.bmBits=%p\n",
3990             res, bmp, dib, bm.bmBits);
3991       if (bm.bmBits)
3992         {
3993           if (section)
3994             UnmapViewOfFile(mapBits), bm.bmBits = NULL;
3995           else if (!offset)
3996             VirtualFree(bm.bmBits, 0L, MEM_RELEASE), bm.bmBits = NULL;
3997         }
3998       
3999       if (dib && dib->image) { XDestroyImage(dib->image); dib->image = NULL; }
4000       if (colorMap) { HeapFree(GetProcessHeap(), 0, colorMap); colorMap = NULL; }
4001       if (dib) { HeapFree(GetProcessHeap(), 0, dib); dib = NULL; }
4002       if (bmp) { GDI_ReleaseObj(res); bmp = NULL; }
4003       if (res) { DeleteObject(res); res = 0; }
4004     }
4005   else if (bm.bmBits)
4006     {
4007       /* Install fault handler, if possible */
4008       InitializeCriticalSection(&(dib->lock));
4009       if (VIRTUAL_SetFaultHandler(bm.bmBits, X11DRV_DIB_FaultHandler, (LPVOID)res))
4010         {
4011           if (section || offset)
4012             {
4013               X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
4014               if (dib) dib->status = DIB_Status_AppMod;
4015             }
4016           else
4017             {
4018               X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
4019               if (dib) dib->status = DIB_Status_InSync;
4020             }
4021         }
4022     }
4023
4024   /* Return BITMAP handle and storage location */
4025   if (bmp) GDI_ReleaseObj(res);
4026   if (bm.bmBits && bits) *bits = bm.bmBits;
4027   return res;
4028 }
4029
4030 /***********************************************************************
4031  *           X11DRV_DIB_DeleteDIBSection
4032  */
4033 void X11DRV_DIB_DeleteDIBSection(BITMAPOBJ *bmp)
4034 {
4035   X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
4036
4037   if (dib->image) 
4038   {
4039 #ifdef HAVE_LIBXXSHM
4040       if (dib->shminfo.shmid != -1)
4041       {
4042           TSXShmDetach (gdi_display, &(dib->shminfo));
4043           XDestroyImage (dib->image);
4044           shmdt (dib->shminfo.shmaddr);
4045           dib->shminfo.shmid = -1;
4046       }
4047       else
4048 #endif
4049           XDestroyImage( dib->image );
4050   }
4051   
4052   if (dib->colorMap)
4053     HeapFree(GetProcessHeap(), 0, dib->colorMap);
4054
4055   if (dib->selector) SELECTOR_FreeBlock( dib->selector );
4056   DeleteCriticalSection(&(dib->lock));
4057 }
4058
4059 /***********************************************************************
4060  *           X11DRV_DIB_SetDIBColorTable
4061  */
4062 UINT X11DRV_DIB_SetDIBColorTable(BITMAPOBJ *bmp, DC *dc, UINT start, UINT count, const RGBQUAD *colors)
4063 {
4064   X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
4065
4066   if (dib && dib->colorMap) {
4067     X11DRV_DIB_GenColorMap( dc, dib->colorMap, DIB_RGB_COLORS, dib->dibSection.dsBm.bmBitsPixel,
4068                             TRUE, colors, start, count + start );
4069     return count;
4070   }
4071   return 0;
4072 }
4073
4074 /***********************************************************************
4075  *           X11DRV_DIB_GetDIBColorTable
4076  */
4077 UINT X11DRV_DIB_GetDIBColorTable(BITMAPOBJ *bmp, DC *dc, UINT start, UINT count, RGBQUAD *colors)
4078 {
4079   X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
4080
4081   if (dib && dib->colorMap) {
4082     int i, end = count + start;
4083     if (end > dib->nColorMap) end = dib->nColorMap;
4084     for (i = start; i < end; i++,colors++) {
4085       COLORREF col = X11DRV_PALETTE_ToLogical( dib->colorMap[i] );
4086       colors->rgbBlue  = GetBValue(col);
4087       colors->rgbGreen = GetGValue(col);
4088       colors->rgbRed   = GetRValue(col);
4089       colors->rgbReserved = 0;
4090     }
4091     return end-start;
4092   }
4093   return 0;
4094 }
4095
4096
4097 /**************************************************************************
4098  *              X11DRV_DIB_CreateDIBFromPixmap
4099  *
4100  *  Allocates a packed DIB and copies the Pixmap data into it.
4101  *  If bDeletePixmap is TRUE, the Pixmap passed in is deleted after the conversion.
4102  */
4103 HGLOBAL X11DRV_DIB_CreateDIBFromPixmap(Pixmap pixmap, HDC hdc, BOOL bDeletePixmap)
4104 {
4105     HBITMAP hBmp = 0;
4106     BITMAPOBJ *pBmp = NULL;
4107     HGLOBAL hPackedDIB = 0;
4108
4109     /* Allocates an HBITMAP which references the Pixmap passed to us */
4110     hBmp = X11DRV_BITMAP_CreateBitmapHeaderFromPixmap(pixmap);
4111     if (!hBmp)
4112     {
4113         TRACE("\tCould not create bitmap header for Pixmap\n");
4114         goto END;
4115     }
4116
4117     /*
4118      * Create a packed DIB from the Pixmap wrapper bitmap created above.
4119      * A packed DIB contains a BITMAPINFO structure followed immediately by
4120      * an optional color palette and the pixel data.
4121      */
4122     hPackedDIB = DIB_CreateDIBFromBitmap(hdc, hBmp);
4123     
4124     /* Get a pointer to the BITMAPOBJ structure */
4125     pBmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
4126
4127     /* We can now get rid of the HBITMAP wrapper we created earlier.
4128      * Note: Simply calling DeleteObject will free the embedded Pixmap as well.
4129      */
4130     if (!bDeletePixmap)
4131     {
4132         /* Clear the physBitmap to prevent the Pixmap from being deleted by DeleteObject */
4133         pBmp->physBitmap = NULL;
4134         pBmp->funcs = NULL;
4135     }
4136     GDI_ReleaseObj( hBmp );
4137     DeleteObject(hBmp);  
4138     
4139 END:
4140     TRACE("\tReturning packed DIB %x\n", hPackedDIB);
4141     return hPackedDIB;
4142 }
4143
4144
4145 /**************************************************************************
4146  *                 X11DRV_DIB_CreatePixmapFromDIB
4147  *
4148  *    Creates a Pixmap from a packed DIB
4149  */
4150 Pixmap X11DRV_DIB_CreatePixmapFromDIB( HGLOBAL hPackedDIB, HDC hdc )
4151 {
4152     Pixmap pixmap = None;
4153     HBITMAP hBmp = 0;
4154     BITMAPOBJ *pBmp = NULL;
4155     LPBYTE pPackedDIB = NULL;
4156     LPBITMAPINFO pbmi = NULL;
4157     LPBITMAPINFOHEADER pbmiHeader = NULL;
4158     LPBYTE pbits = NULL;
4159     
4160     /* Get a pointer to the packed DIB's data  */
4161     pPackedDIB = (LPBYTE)GlobalLock(hPackedDIB);
4162     pbmiHeader = (LPBITMAPINFOHEADER)pPackedDIB;
4163     pbmi = (LPBITMAPINFO)pPackedDIB;
4164     pbits = (LPBYTE)(pPackedDIB
4165                      + DIB_BitmapInfoSize( (LPBITMAPINFO)pbmiHeader, DIB_RGB_COLORS ));
4166     
4167     /* Create a DDB from the DIB */
4168      
4169     hBmp = CreateDIBitmap(hdc,
4170                           pbmiHeader,
4171                           CBM_INIT,
4172                           (LPVOID)pbits,
4173                           pbmi,
4174                           DIB_RGB_COLORS);
4175
4176     GlobalUnlock(hPackedDIB);
4177
4178     TRACE("CreateDIBitmap returned %x\n", hBmp);
4179
4180     /* Retrieve the internal Pixmap from the DDB */
4181      
4182     pBmp = (BITMAPOBJ *) GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
4183
4184     pixmap = (Pixmap)pBmp->physBitmap;
4185     /* clear the physBitmap so that we can steal its pixmap */
4186     pBmp->physBitmap = NULL;
4187     pBmp->funcs = NULL;
4188
4189     /* Delete the DDB we created earlier now that we have stolen its pixmap */
4190     GDI_ReleaseObj( hBmp );
4191     DeleteObject(hBmp);
4192     
4193     TRACE("\tReturning Pixmap %ld\n", pixmap);
4194     return pixmap;
4195 }