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