Adapted to separation between KERNEL and USER.
[wine] / objects / dib.c
1 /*
2  * GDI device-independent bitmaps
3  *
4  * Copyright 1993,1994  Alexandre Julliard
5  */
6
7 #include <stdlib.h>
8 #include "ts_xlib.h"
9 #include "ts_xutil.h"
10 #include "dc.h"
11 #include "bitmap.h"
12 #include "callback.h"
13 #include "palette.h"
14 #include "color.h"
15 #include "global.h"
16 #include "debug.h"
17
18 static int bitmapDepthTable[] = { 8, 1, 32, 16, 24, 15, 4, 0 };
19 static int ximageDepthTable[] = { 0, 0, 0,  0,  0,  0,  0 };
20
21
22 /* This structure holds the arguments for DIB_SetImageBits() */
23 typedef struct
24 {
25     DC               *dc;
26     LPCVOID           bits;
27     XImage           *image;
28     int               lines;
29     DWORD             infoWidth;
30     WORD              depth;
31     WORD              infoBpp;
32     WORD              compression;
33     int              *colorMap;
34     int               nColorMap;
35     Drawable          drawable;
36     GC                gc;
37     int               xSrc;
38     int               ySrc;
39     int               xDest;
40     int               yDest;
41     int               width;
42     int               height;
43 } DIB_SETIMAGEBITS_DESCR;
44
45
46 /***********************************************************************
47  *           DIB_Init
48  */
49 BOOL32 DIB_Init(void)
50 {
51     int         i;
52     XImage*     testimage;
53
54     for( i = 0; bitmapDepthTable[i]; i++ )
55     {
56          testimage = TSXCreateImage(display, DefaultVisualOfScreen(screen),
57                          bitmapDepthTable[i], ZPixmap, 0, NULL, 1, 1, 32, 20 );
58          if( testimage ) ximageDepthTable[i] = testimage->bits_per_pixel;
59          else return FALSE;
60          TSXDestroyImage(testimage);
61     }
62     return TRUE;
63 }
64
65 /***********************************************************************
66  *           DIB_GetXImageWidthBytes
67  *
68  * Return the width of an X image in bytes
69  */
70 int X11DRV_DIB_GetXImageWidthBytes( int width, int depth )
71 {
72     int         i;
73
74     if (!ximageDepthTable[0]) {
75             DIB_Init();
76     }
77     for( i = 0; bitmapDepthTable[i] ; i++ )
78          if( bitmapDepthTable[i] == depth )
79              return (4 * ((width * ximageDepthTable[i] + 31)/32));
80     
81     WARN(bitmap, "(%d): Unsupported depth\n", depth );
82     return (4 * width);
83 }
84
85 /***********************************************************************
86  *           DIB_GetDIBWidthBytes
87  *
88  * Return the width of a DIB bitmap in bytes. DIB bitmap data is 32-bit aligned.
89  * http://www.microsoft.com/msdn/sdk/platforms/doc/sdk/win32/struc/src/str01.htm
90  */
91 int DIB_GetDIBWidthBytes( int width, int depth )
92 {
93     int words;
94
95     switch(depth)
96     {
97         case 1:  words = (width + 31) / 32; break;
98         case 4:  words = (width + 7) / 8; break;
99         case 8:  words = (width + 3) / 4; break;
100         case 15:
101         case 16: words = (width + 1) / 2; break;
102         case 24: words = (width * 3 + 3)/4; break;
103
104         default:
105             WARN(bitmap, "(%d): Unsupported depth\n", depth );
106         /* fall through */
107         case 32:
108                 words = width;
109     }
110     return 4 * words;
111 }
112
113
114 /***********************************************************************
115  *           DIB_BitmapInfoSize
116  *
117  * Return the size of the bitmap info structure including color table.
118  */
119 int DIB_BitmapInfoSize( BITMAPINFO * info, WORD coloruse )
120 {
121     int colors;
122
123     if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
124     {
125         BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)info;
126         colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
127         return sizeof(BITMAPCOREHEADER) + colors *
128              ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
129     }
130     else  /* assume BITMAPINFOHEADER */
131     {
132         colors = info->bmiHeader.biClrUsed;
133         if (!colors && (info->bmiHeader.biBitCount <= 8))
134             colors = 1 << info->bmiHeader.biBitCount;
135         return sizeof(BITMAPINFOHEADER) + colors *
136                ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
137     }
138 }
139
140
141 /***********************************************************************
142  *           DIB_GetBitmapInfo
143  *
144  * Get the info from a bitmap header.
145  * Return 1 for INFOHEADER, 0 for COREHEADER, -1 for error.
146  */
147 int DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, DWORD *width,
148                               int *height, WORD *bpp, WORD *compr )
149 {
150     if (header->biSize == sizeof(BITMAPINFOHEADER))
151     {
152         *width  = header->biWidth;
153         *height = header->biHeight;
154         *bpp    = header->biBitCount;
155         *compr  = header->biCompression;
156         return 1;
157     }
158     if (header->biSize == sizeof(BITMAPCOREHEADER))
159     {
160         BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)header;
161         *width  = core->bcWidth;
162         *height = core->bcHeight;
163         *bpp    = core->bcBitCount;
164         *compr  = 0;
165         return 0;
166     }
167     WARN(bitmap, "(%ld): wrong size for header\n", header->biSize );
168     return -1;
169 }
170
171
172 /***********************************************************************
173  *           DIB_BuildColorMap
174  *
175  * Build the color map from the bitmap palette. Should not be called
176  * for a >8-bit deep bitmap.
177  */
178 static int *DIB_BuildColorMap( DC *dc, WORD coloruse, WORD depth, 
179                                const BITMAPINFO *info, int *nColors )
180 {
181     int i, colors;
182     BOOL32 isInfo;
183     WORD *colorPtr;
184     int *colorMapping;
185
186     if ((isInfo = (info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))))
187     {
188         colors = info->bmiHeader.biClrUsed;
189         if (!colors) colors = 1 << info->bmiHeader.biBitCount;
190         colorPtr = (WORD *)info->bmiColors;
191     }
192     else  /* assume BITMAPCOREINFO */
193     {
194         colors = 1 << ((BITMAPCOREHEADER *)&info->bmiHeader)->bcBitCount;
195         colorPtr = (WORD *)((BITMAPCOREINFO *)info)->bmciColors;
196     }
197
198     if (colors > 256)
199     {
200         ERR(bitmap, "DIB_BuildColorMap called with >256 colors!\n");
201         return NULL;
202     }
203
204     if (!(colorMapping = (int *)HeapAlloc(GetProcessHeap(), 0,
205                                           colors * sizeof(int) ))) 
206         return NULL;
207
208     if (coloruse == DIB_RGB_COLORS)
209     {
210         if (isInfo)
211         {
212             RGBQUAD * rgb = (RGBQUAD *)colorPtr;
213
214             if (depth == 1)  /* Monochrome */
215                 for (i = 0; i < colors; i++, rgb++)
216                     colorMapping[i] = (rgb->rgbRed + rgb->rgbGreen +
217                                        rgb->rgbBlue > 255*3/2);
218             else
219                 for (i = 0; i < colors; i++, rgb++)
220                     colorMapping[i] = COLOR_ToPhysical( dc, RGB(rgb->rgbRed,
221                                                                 rgb->rgbGreen,
222                                                                 rgb->rgbBlue));
223         }
224         else
225         {
226             RGBTRIPLE * rgb = (RGBTRIPLE *)colorPtr;
227
228             if (depth == 1)  /* Monochrome */
229                 for (i = 0; i < colors; i++, rgb++)
230                     colorMapping[i] = (rgb->rgbtRed + rgb->rgbtGreen +
231                                        rgb->rgbtBlue > 255*3/2);
232             else
233                 for (i = 0; i < colors; i++, rgb++)
234                     colorMapping[i] = COLOR_ToPhysical( dc, RGB(rgb->rgbtRed,
235                                                                rgb->rgbtGreen,
236                                                                rgb->rgbtBlue));
237         }
238     }
239     else  /* DIB_PAL_COLORS */
240     {
241         for (i = 0; i < colors; i++, colorPtr++)
242             colorMapping[i] = COLOR_ToPhysical( dc, PALETTEINDEX(*colorPtr) );
243     }
244
245     *nColors = colors;
246     return colorMapping;
247 }
248
249
250 /***********************************************************************
251  *           DIB_MapColor
252  */
253 static int DIB_MapColor( int *physMap, int nPhysMap, int phys )
254 {
255     int color;
256
257     for (color = 0; color < nPhysMap; color++)
258         if (physMap[color] == phys)
259             return color;
260
261     WARN(bitmap, "Strange color %08x\n", phys);
262     return 0;
263 }
264
265
266 /***********************************************************************
267  *           DIB_SetImageBits_1_Line
268  *
269  * Handles a single line of 1 bit data.
270  */
271 static void DIB_SetImageBits_1_Line(DWORD dstwidth, int left, int *colors,
272                                     XImage *bmpImage, int h, const BYTE *bits)
273 {
274     BYTE pix;
275     DWORD i, x;
276
277     dstwidth += left; bits += left >> 3;
278
279     /* FIXME: should avoid putting x<left pixels (minor speed issue) */
280     for (i = dstwidth/8, x = left&~7; (i > 0); i--)
281     {
282         pix = *bits++;
283         XPutPixel( bmpImage, x++, h, colors[pix >> 7] );
284         XPutPixel( bmpImage, x++, h, colors[(pix >> 6) & 1] );
285         XPutPixel( bmpImage, x++, h, colors[(pix >> 5) & 1] );
286         XPutPixel( bmpImage, x++, h, colors[(pix >> 4) & 1] );
287         XPutPixel( bmpImage, x++, h, colors[(pix >> 3) & 1] );
288         XPutPixel( bmpImage, x++, h, colors[(pix >> 2) & 1] );
289         XPutPixel( bmpImage, x++, h, colors[(pix >> 1) & 1] );
290         XPutPixel( bmpImage, x++, h, colors[pix & 1] );
291     }
292     pix = *bits;
293     switch(dstwidth & 7)
294     {
295     case 7: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
296     case 6: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
297     case 5: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
298     case 4: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
299     case 3: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
300     case 2: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
301     case 1: XPutPixel( bmpImage, x++, h, colors[pix >> 7] );
302     }
303 }
304
305 /***********************************************************************
306  *           DIB_SetImageBits_1
307  *
308  * SetDIBits for a 1-bit deep DIB.
309  */
310 static void DIB_SetImageBits_1( int lines, const BYTE *srcbits,
311                                 DWORD srcwidth, DWORD dstwidth, int left,
312                                 int *colors, XImage *bmpImage )
313 {
314     int h;
315
316     /* 32 bit aligned */
317     DWORD linebytes = ((srcwidth + 31) & ~31) / 8;
318
319     if (lines > 0) {
320         for (h = lines-1; h >=0; h--) {
321             DIB_SetImageBits_1_Line(dstwidth, left, colors, bmpImage, h, srcbits);
322             srcbits += linebytes;
323         }
324     } else {
325         lines = -lines;
326         for (h = 0; h < lines; h++) {
327             DIB_SetImageBits_1_Line(dstwidth, left, colors, bmpImage, h, srcbits);
328             srcbits += linebytes;
329         }
330     }
331 }
332
333
334 /***********************************************************************
335  *           DIB_SetImageBits_4
336  *
337  * SetDIBits for a 4-bit deep DIB.
338  */
339 static void DIB_SetImageBits_4( int lines, const BYTE *srcbits,
340                                 DWORD srcwidth, DWORD dstwidth, int left,
341                                 int *colors, XImage *bmpImage )
342 {
343     DWORD i, x;
344     int h;
345     const BYTE *bits = srcbits + (left >> 1);
346   
347     /* 32 bit aligned */
348     DWORD linebytes = ((srcwidth+7)&~7)/2;
349
350     dstwidth += left;
351
352     /* FIXME: should avoid putting x<left pixels (minor speed issue) */
353     if (lines > 0) {
354         for (h = lines-1; h >= 0; h--) {
355             for (i = dstwidth/2, x = left&~1; i > 0; i--) {
356                 BYTE pix = *bits++;
357                 XPutPixel( bmpImage, x++, h, colors[pix >> 4] );
358                 XPutPixel( bmpImage, x++, h, colors[pix & 0x0f] );
359             }
360             if (dstwidth & 1) XPutPixel( bmpImage, x, h, colors[*bits >> 4] );
361             srcbits += linebytes;
362             bits         = srcbits + (left >> 1);
363         }
364     } else {
365         lines = -lines;
366         for (h = 0; h < lines; h++) {
367             for (i = dstwidth/2, x = left&~1; i > 0; i--) {
368                 BYTE pix = *bits++;
369                 XPutPixel( bmpImage, x++, h, colors[pix >> 4] );
370                 XPutPixel( bmpImage, x++, h, colors[pix & 0x0f] );
371             }
372             if (dstwidth & 1) XPutPixel( bmpImage, x, h, colors[*bits >> 4] );
373             srcbits += linebytes;
374             bits         = srcbits + (left >> 1);
375         }
376     }
377 }
378
379 /***********************************************************************
380  *           DIB_GetImageBits_4
381  *
382  * GetDIBits for a 4-bit deep DIB.
383  */
384 static void DIB_GetImageBits_4( int lines, BYTE *srcbits,
385                                 DWORD srcwidth, DWORD dstwidth, int left,
386                                 int *colors, int nColors, XImage *bmpImage )
387 {
388     DWORD i, x;
389     int h;
390     BYTE *bits = srcbits + (left >> 1);
391
392     /* 32 bit aligned */
393     DWORD linebytes = ((srcwidth+7)&~7)/2;
394
395     dstwidth += left;
396
397     /* FIXME: should avoid putting x<left pixels (minor speed issue) */
398     if (lines > 0) {
399        for (h = lines-1; h >= 0; h--) {
400            for (i = dstwidth/2, x = left&~1; i > 0; i--) {
401                *bits++ = (DIB_MapColor( colors, nColors, XGetPixel( bmpImage, x++, h )) << 4)
402                        | (DIB_MapColor( colors, nColors, XGetPixel( bmpImage, x++, h )) & 0x0f);
403            }
404            if (dstwidth & 1)
405                *bits = (DIB_MapColor( colors, nColors, XGetPixel( bmpImage, x++, h )) << 4);
406            srcbits += linebytes;
407            bits     = srcbits + (left >> 1);
408        }
409     } else {
410        lines = -lines;
411        for (h = 0; h < lines; h++) {
412            for (i = dstwidth/2, x = left&~1; i > 0; i--) {
413                *bits++ = (DIB_MapColor( colors, nColors, XGetPixel( bmpImage, x++, h )) << 4)
414                        | (DIB_MapColor( colors, nColors, XGetPixel( bmpImage, x++, h )) & 0x0f);
415            }
416            if (dstwidth & 1)
417                *bits = (DIB_MapColor( colors, nColors, XGetPixel( bmpImage, x++, h )) << 4);
418            srcbits += linebytes;
419            bits     = srcbits + (left >> 1);
420        }
421     }
422 }
423
424 #define check_xy(x,y) \
425         if (x > width) { \
426                 x = 0; \
427                 if (lines) \
428                         lines--; \
429         }
430
431 /***********************************************************************
432  *           DIB_SetImageBits_RLE4
433  *
434  * SetDIBits for a 4-bit deep compressed DIB.
435  */
436 static void DIB_SetImageBits_RLE4( int lines, const BYTE *bits, DWORD width,
437                                 DWORD dstwidth, int left, int *colors, XImage *bmpImage )
438 {
439         int x = 0, c, length;
440         const BYTE *begin = bits;
441
442         dstwidth += left; /* FIXME: avoid putting x<left pixels */
443
444         lines--;
445         while ((int)lines >= 0)
446         {
447                 length = *bits++;
448                 if (length) {   /* encoded */
449                         c = *bits++;
450                         while (length--) {
451                                 XPutPixel(bmpImage, x++, lines, colors[c >> 4]);
452                                 check_xy(x, y);
453                                 if (length) {
454                                         length--;
455                                         XPutPixel(bmpImage, x++, lines, colors[c & 0xf]);
456                                         check_xy(x, y);
457                                 }
458                         }
459                 } else {
460                         length = *bits++;
461                         switch (length) {
462                                 case 0: /* eol */
463                                         x = 0;
464                                         lines--;
465                                         continue;
466
467                                 case 1: /* eopicture */
468                                         return;
469
470                                 case 2: /* delta */
471                                         x += *bits++;
472                                         lines -= *bits++;
473                                         continue;
474
475                                 default: /* absolute */
476                                         while (length--) {
477                                                 c = *bits++;
478                                                 XPutPixel(bmpImage, x++, lines, colors[c >> 4]);
479                                                 check_xy(x, y);
480                                                 if (length) {
481                                                         length--;
482                                                         XPutPixel(bmpImage, x++, lines, colors[c & 0xf]);
483                                                         check_xy(x, y);
484                                                 }
485                                         }
486                                         if ((bits - begin) & 1)
487                                                 bits++;
488                         }
489                 }
490         }
491 }
492
493 /***********************************************************************
494  *           DIB_SetImageBits_8
495  *
496  * SetDIBits for an 8-bit deep DIB.
497  */
498 static void DIB_SetImageBits_8( int lines, const BYTE *srcbits,
499                                 DWORD srcwidth, DWORD dstwidth, int left,
500                                 int *colors, XImage *bmpImage )
501 {
502     DWORD x;
503     int h;
504     const BYTE *bits = srcbits + left;
505
506     /* align to 32 bit */
507     DWORD linebytes = (srcwidth + 3) & ~3;
508
509     dstwidth+=left;
510
511     if (lines > 0) {
512         for (h = lines - 1; h >= 0; h--) {
513             for (x = left; x < dstwidth; x++, bits++) {
514                 XPutPixel( bmpImage, x, h, colors[*bits] );
515             }
516             bits = (srcbits += linebytes) + left;
517         }
518     } else {
519         lines = -lines;
520         for (h = 0; h < lines; h++) {
521             for (x = left; x < dstwidth; x++, bits++) {
522                 XPutPixel( bmpImage, x, h, colors[*bits] );
523             }
524             bits = (srcbits += linebytes) + left;
525         }
526     }
527 }
528
529 /***********************************************************************
530  *           DIB_GetImageBits_8
531  *
532  * GetDIBits for an 8-bit deep DIB.
533  */
534 static void DIB_GetImageBits_8( int lines, BYTE *srcbits,
535                                 DWORD srcwidth, DWORD dstwidth, int left,
536                                 int *colors, int nColors, XImage *bmpImage )
537 {
538     DWORD x;
539     int h;
540     BYTE *bits = srcbits + left;
541
542     /* align to 32 bit */
543     DWORD linebytes = (srcwidth + 3) & ~3;
544
545     dstwidth+=left;
546
547     if (lines > 0) {
548        for (h = lines - 1; h >= 0; h--) {
549            for (x = left; x < dstwidth; x++, bits++) {
550                if ( XGetPixel( bmpImage, x, h ) != colors[*bits] )
551                    *bits = DIB_MapColor( colors, nColors,
552                                           XGetPixel( bmpImage, x, h ) );
553            }
554            bits = (srcbits += linebytes) + left;
555        }
556     } else {
557        lines = -lines;
558        for (h = 0; h < lines; h++) {
559            for (x = left; x < dstwidth; x++, bits++) {
560                if ( XGetPixel( bmpImage, x, h ) != colors[*bits] )
561                    *bits = DIB_MapColor( colors, nColors,
562                                          XGetPixel( bmpImage, x, h ) );
563            }
564            bits = (srcbits += linebytes) + left;
565        }
566     }
567 }
568
569 /***********************************************************************
570  *            DIB_SetImageBits_RLE8
571  *
572  * SetDIBits for an 8-bit deep compressed DIB.
573  *
574  * This function rewritten 941113 by James Youngman.  WINE blew out when I
575  * first ran it because my desktop wallpaper is a (large) RLE8 bitmap.  
576  *
577  * This was because the algorithm assumed that all RLE8 bitmaps end with the  
578  * 'End of bitmap' escape code.  This code is very much laxer in what it
579  * allows to end the expansion.  Possibly too lax.  See the note by 
580  * case RleDelta.  BTW, MS's documentation implies that a correct RLE8
581  * bitmap should end with RleEnd, but on the other hand, software exists 
582  * that produces ones that don't and Windows 3.1 doesn't complain a bit
583  * about it.
584  *
585  * (No) apologies for my English spelling.  [Emacs users: c-indent-level=4].
586  *                      James A. Youngman <mbcstjy@afs.man.ac.uk>
587  *                                              [JAY]
588  */
589
590 enum Rle8_EscapeCodes           
591 {
592   /* 
593    * Apologies for polluting your file's namespace...
594    */
595   RleEol        = 0,            /* End of line */
596   RleEnd        = 1,            /* End of bitmap */
597   RleDelta      = 2             /* Delta */
598 };
599   
600 static void DIB_SetImageBits_RLE8( int lines, const BYTE *bits, DWORD width,
601                                 DWORD dstwidth, int left, int *colors, XImage *bmpImage )
602 {
603     int x;                      /* X-positon on each line.  Increases. */
604     int line;                   /* Line #.  Starts at lines-1, decreases */
605     const BYTE *pIn = bits;     /* Pointer to current position in bits */
606     BYTE length;                /* The length pf a run */
607     BYTE color_index;           /* index into colors[] as read from bits */
608     BYTE escape_code;           /* See enum Rle8_EscapeCodes.*/
609     int color;                  /* value of colour[color_index] */
610     
611     if (lines == 0)             /* Let's hope this doesn't happen. */
612       return;
613     
614     dstwidth += left; /* FIXME: avoid putting x<left pixels */
615
616     /*
617      * Note that the bitmap data is stored by Windows starting at the
618      * bottom line of the bitmap and going upwards.  Within each line,
619      * the data is stored left-to-right.  That's the reason why line
620      * goes from lines-1 to 0.                  [JAY]
621      */
622     
623     x = 0;
624     line = lines-1;
625     do
626       {
627           length = *pIn++;
628           
629           /* 
630            * If the length byte is not zero (which is the escape value),
631            * We have a run of length pixels all the same colour.  The colour 
632            * index is stored next. 
633            *
634            * If the length byte is zero, we need to read the next byte to
635            * know what to do.                   [JAY]
636            */
637           if (length != 0) 
638             {                                   
639                 /* 
640                  * [Run-Length] Encoded mode 
641                  */
642                 color_index = (*pIn++); /* Get the colour index. */
643                 color = colors[color_index];
644
645                 while(length--)
646                   XPutPixel(bmpImage, x++, line, color);
647             }
648           else 
649             {    
650                 /* 
651                  * Escape codes (may be an absolute sequence though)
652                  */
653                 escape_code = (*pIn++);
654                 switch(escape_code)
655                   {
656                     case RleEol: /* =0, end of line */
657                       {
658                           x = 0;  
659                           line--;  
660                           break;
661                       }
662                       
663                     case RleEnd: /* =1, end of bitmap */
664                       {
665                           /*
666                            * Not all RLE8 bitmaps end with this 
667                            * code.  For example, Paint Shop Pro 
668                            * produces some that don't.  That's (I think)
669                            * what caused the previous implementation to 
670                            * fail.                      [JAY]
671                            */
672                           line=-1; /* Cause exit from do loop. */
673                           break;
674                       }
675                       
676                     case RleDelta: /* =2, a delta */
677                       {
678                           /* 
679                            * Note that deltaing to line 0 
680                            * will cause an exit from the loop, 
681                            * which may not be what is intended. 
682                            * The fact that there is a delta in the bits
683                            * almost certainly implies that there is data
684                            * to follow.  You may feel that we should 
685                            * jump to the top of the loop to avoid exiting
686                            * in this case.  
687                            *
688                            * TODO: Decide what to do here in that case. [JAY]
689                            */
690                           x     += (*pIn++); 
691                           line  -= (*pIn++);
692                           if (line == 0)
693                             {
694                               TRACE(bitmap, "Delta to last line of bitmap "
695                                            "(wrongly?) causes loop exit\n");
696                             }
697                           break;
698                       }
699                       
700                     default:    /* >2, switch to absolute mode */
701                       {
702                           /* 
703                            * Absolute Mode 
704                            */
705                           length = escape_code;
706                           while(length--)
707                             {
708                                 color_index = (*pIn++);
709                                 XPutPixel(bmpImage, x++, line, 
710                                           colors[color_index]);
711                             }
712                           
713                           /*
714                            * If you think for a moment you'll realise that the
715                            * only time we could ever possibly read an odd
716                            * number of bytes is when there is a 0x00 (escape),
717                            * a value >0x02 (absolute mode) and then an odd-
718                            * length run.  Therefore this is the only place we
719                            * need to worry about it.  Everywhere else the
720                            * bytes are always read in pairs.  [JAY]
721                            */
722                           if (escape_code & 1) 
723                             pIn++; /* Throw away the pad byte. */
724                           break;
725                       }
726                   } /* switch (escape_code) : Escape sequence */
727             }  /* process either an encoded sequence or an escape sequence */
728           
729           /* We expect to come here more than once per line. */
730       } while (line >= 0);  /* Do this until the bitmap is filled */
731     
732     /*
733      * Everybody comes here at the end.
734      * Check how we exited the loop and print a message if it's a bit odd.
735      *                                          [JAY]
736      */
737     if ( (*(pIn-2) != 0/*escape*/) || (*(pIn-1)!= RleEnd) )
738       {
739         TRACE(bitmap, "End-of-bitmap "
740                        "without (strictly) proper escape code.  Last two "
741                        "bytes were: %02X %02X.\n",
742                        (int)*(pIn-2),
743                        (int)*(pIn-1));           
744       }
745 }  
746
747
748 /***********************************************************************
749  *           DIB_SetImageBits_16
750  *
751  * SetDIBits for a 16-bit deep DIB.
752  */
753 static void DIB_SetImageBits_16( int lines, const BYTE *srcbits,
754                                  DWORD srcwidth, DWORD dstwidth, int left,
755                                  DC *dc, XImage *bmpImage )
756 {
757     DWORD x;
758     LPWORD ptr;
759     WORD val;
760     int h;
761     BYTE r, g, b;
762   
763     /* align to 32 bit */
764     DWORD linebytes = (srcwidth * 2 + 3) & ~3;
765
766     dstwidth += left;
767
768     ptr = (LPWORD) srcbits + left;
769     if (lines > 0) {
770         for (h = lines - 1; h >= 0; h--) {
771             for (x = left; x < dstwidth; x++, ptr++) {
772                 val = *ptr;
773                 r = (BYTE) ((val & 0x7c00) >> 7);
774                 g = (BYTE) ((val & 0x03e0) >> 2);
775                 b = (BYTE) ((val & 0x001f) << 3);
776                 XPutPixel( bmpImage, x, h,
777                            COLOR_ToPhysical(dc, RGB(r,g,b)) );
778             }
779             ptr = (LPWORD) (srcbits += linebytes) + left;
780         }
781     } else {
782         lines = -lines;
783         for (h = 0; h < lines; h++) {
784             for (x = left; x < dstwidth; x++, ptr++) {
785                 val = *ptr;
786                 r = (BYTE) ((val & 0x7c00) >> 7);
787                 g = (BYTE) ((val & 0x03e0) >> 2);
788                 b = (BYTE) ((val & 0x001f) << 3);
789                 XPutPixel( bmpImage, x, h,
790                            COLOR_ToPhysical(dc, RGB(r,g,b)) );
791             }
792             ptr = (LPWORD) (srcbits += linebytes) + left;
793         }
794     }
795 }
796
797
798 /***********************************************************************
799  *           DIB_GetImageBits_16
800  *
801  * GetDIBits for an 16-bit deep DIB.
802  */
803 static void DIB_GetImageBits_16( int lines, BYTE *srcbits,
804                                  DWORD srcwidth, DWORD dstwidth, int left,
805                                  XImage *bmpImage )
806 {
807     DWORD x;
808     LPWORD ptr;
809     int h;
810     BYTE r, g, b;
811
812     /* align to 32 bit */
813     DWORD linebytes = (srcwidth * 2 + 3) & ~3;
814
815     dstwidth += left;
816
817     ptr = (LPWORD) srcbits + left;
818     if (lines > 0) {
819        for (h = lines - 1; h >= 0; h--)
820         {
821            for (x = left; x < dstwidth; x++, ptr++)
822             {
823                 COLORREF pixel = COLOR_ToLogical( XGetPixel( bmpImage, x, h ) );
824                r = (BYTE) GetRValue(pixel);
825                g = (BYTE) GetGValue(pixel);
826                b = (BYTE) GetBValue(pixel);
827                 *ptr = ( ((r << 7) & 0x7c00) | ((g << 2) & 0x03e0) | ((b >> 3) & 0x001f) );
828            }
829            ptr = (LPWORD) (srcbits += linebytes) + left;
830        }
831     } else {
832        lines = -lines;
833        for (h = 0; h < lines; h++)
834         {
835            for (x = left; x < dstwidth; x++, ptr++)
836             {
837                 COLORREF pixel = COLOR_ToLogical( XGetPixel( bmpImage, x, h ) );
838                r = (BYTE) GetRValue(pixel);
839                g = (BYTE) GetGValue(pixel);
840                b = (BYTE) GetBValue(pixel);
841                 *ptr = ( ((r << 7) & 0x7c00) | ((g << 2) & 0x03e0) | ((b >> 3) & 0x001f) );
842            }
843
844            ptr = (LPWORD) (srcbits += linebytes) + left;
845        }
846     }
847 }
848
849
850 /***********************************************************************
851  *           DIB_SetImageBits_24
852  *
853  * SetDIBits for a 24-bit deep DIB.
854  */
855 static void DIB_SetImageBits_24( int lines, const BYTE *srcbits,
856                                  DWORD srcwidth, DWORD dstwidth, int left,
857                                  DC *dc, XImage *bmpImage )
858 {
859     DWORD x;
860     const BYTE *bits = srcbits + left * 3;
861     int h;
862   
863     /* align to 32 bit */
864     DWORD linebytes = (srcwidth * 3 + 3) & ~3;
865
866     dstwidth += left;
867
868     /* "bits" order is reversed for some reason */
869
870     if (lines > 0) {
871         for (h = lines - 1; h >= 0; h--) {
872             for (x = left; x < dstwidth; x++, bits += 3) {
873                 XPutPixel( bmpImage, x, h, 
874                            COLOR_ToPhysical(dc, RGB(bits[2],bits[1],bits[0])));
875             }
876             bits = (srcbits += linebytes) + left * 3;
877         }
878     } else {
879         lines = -lines;
880         for (h = 0; h < lines; h++) {
881             for (x = left; x < dstwidth; x++, bits += 3) {
882                 XPutPixel( bmpImage, x, h,
883                            COLOR_ToPhysical(dc, RGB(bits[2],bits[1],bits[0])));
884             }
885             bits = (srcbits += linebytes) + left * 3;
886         }
887     }
888 }
889
890
891 /***********************************************************************
892  *           DIB_GetImageBits_24
893  *
894  * GetDIBits for an 24-bit deep DIB.
895  */
896 static void DIB_GetImageBits_24( int lines, BYTE *srcbits,
897                                  DWORD srcwidth, DWORD dstwidth, int left,
898                                  XImage *bmpImage )
899 {
900     DWORD x;
901     int h;
902     BYTE *bits = srcbits + (left * 3);
903
904     /* align to 32 bit */
905     DWORD linebytes = (srcwidth * 3 + 3) & ~3;
906
907     dstwidth += left;
908
909     if (lines > 0) {
910        for (h = lines - 1; h >= 0; h--)
911         {
912            for (x = left; x < dstwidth; x++, bits += 3)
913             {
914                 COLORREF pixel = COLOR_ToLogical( XGetPixel( bmpImage, x, h ) );
915                 bits[0] = GetRValue(pixel);
916                 bits[1] = GetGValue(pixel);
917                 bits[2] = GetBValue(pixel);
918            }
919            bits = (srcbits += linebytes) + (left * 3);
920        }
921     } else {
922        lines = -lines;
923        for (h = 0; h < lines; h++)
924         {
925            for (x = left; x < dstwidth; x++, bits += 3)
926             {
927                 COLORREF pixel = COLOR_ToLogical( XGetPixel( bmpImage, x, h ) );
928                 bits[0] = GetRValue(pixel);
929                 bits[1] = GetGValue(pixel);
930                 bits[2] = GetBValue(pixel);
931            }
932
933            bits = (srcbits += linebytes) + (left * 3);
934        }
935     }
936 }
937
938
939 /***********************************************************************
940  *           DIB_SetImageBits_32
941  *
942  * SetDIBits for a 32-bit deep DIB.
943  */
944 static void DIB_SetImageBits_32( int lines, const BYTE *srcbits,
945                                  DWORD srcwidth, DWORD dstwidth, int left,
946                                  DC *dc, XImage *bmpImage )
947 {
948     DWORD x;
949     const BYTE *bits = srcbits + left * 4;
950     int h;
951   
952     DWORD linebytes = (srcwidth * 4);
953
954     dstwidth += left;
955
956     if (lines > 0) {
957         for (h = lines - 1; h >= 0; h--) {
958             for (x = left; x < dstwidth; x++, bits += 4) {
959                 XPutPixel( bmpImage, x, h, 
960                            COLOR_ToPhysical(dc, RGB(bits[2],bits[1],bits[0])));
961             }
962             bits = (srcbits += linebytes) + left * 4;
963         }
964     } else {
965         lines = -lines;
966         for (h = 0; h < lines; h++) {
967             for (x = left; x < dstwidth; x++, bits += 4) {
968                 XPutPixel( bmpImage, x, h,
969                            COLOR_ToPhysical(dc, RGB(bits[2],bits[1],bits[0])));
970             }
971             bits = (srcbits += linebytes) + left * 4;
972         }
973     }
974 }
975
976
977 /***********************************************************************
978  *           DIB_GetImageBits_32
979  *
980  * GetDIBits for an 32-bit deep DIB.
981  */
982 static void DIB_GetImageBits_32( int lines, BYTE *srcbits,
983                                  DWORD srcwidth, DWORD dstwidth, int left,
984                                  XImage *bmpImage )
985 {
986     DWORD x;
987     int h;
988     BYTE *bits = srcbits + (left * 4);
989
990     /* align to 32 bit */
991     DWORD linebytes = (srcwidth * 4);
992
993     dstwidth += left;
994
995     if (lines > 0) {
996        for (h = lines - 1; h >= 0; h--)
997         {
998            for (x = left; x < dstwidth; x++, bits += 4)
999             {
1000                 COLORREF pixel = COLOR_ToLogical( XGetPixel( bmpImage, x, h ) );
1001                 bits[0] = GetRValue(pixel);
1002                 bits[1] = GetGValue(pixel);
1003                 bits[2] = GetBValue(pixel);
1004            }
1005            bits = (srcbits += linebytes) + (left * 4);
1006        }
1007     } else {
1008        lines = -lines;
1009        for (h = 0; h < lines; h++)
1010         {
1011            for (x = left; x < dstwidth; x++, bits += 4)
1012             {
1013                 COLORREF pixel = COLOR_ToLogical( XGetPixel( bmpImage, x, h ) );
1014                 bits[0] = GetRValue(pixel);
1015                 bits[1] = GetGValue(pixel);
1016                 bits[2] = GetBValue(pixel);
1017            }
1018
1019            bits = (srcbits += linebytes) + (left * 4);
1020        }
1021     }
1022 }
1023
1024
1025 /***********************************************************************
1026  *           DIB_SetImageBits
1027  *
1028  * Transfer the bits to an X image.
1029  * Helper function for SetDIBits() and SetDIBitsToDevice().
1030  * The Xlib critical section must be entered before calling this function.
1031  */
1032 static int DIB_SetImageBits( const DIB_SETIMAGEBITS_DESCR *descr )
1033 {
1034     int lines = descr->lines >= 0 ? descr->lines : -descr->lines;
1035     XImage *bmpImage;
1036
1037     if ( descr->dc && descr->dc->w.flags & DC_DIRTY ) 
1038         CLIPPING_UpdateGCRegion( descr->dc );
1039
1040     if (descr->image)
1041         bmpImage = descr->image;
1042     else
1043         XCREATEIMAGE( bmpImage, descr->infoWidth, lines, descr->depth );
1044
1045       /* Transfer the pixels */
1046     switch(descr->infoBpp)
1047     {
1048     case 1:
1049         DIB_SetImageBits_1( descr->lines, descr->bits, descr->infoWidth,
1050                             descr->width, descr->xSrc, descr->colorMap, bmpImage );
1051         break;
1052     case 4:
1053         if (descr->compression) DIB_SetImageBits_RLE4( descr->lines, descr->bits,
1054                                                 descr->infoWidth, descr->width, descr->xSrc,
1055                                                 descr->colorMap, bmpImage );
1056         else DIB_SetImageBits_4( descr->lines, descr->bits, descr->infoWidth,
1057                                  descr->width, descr->xSrc, descr->colorMap, bmpImage );
1058         break;
1059     case 8:
1060         if (descr->compression) DIB_SetImageBits_RLE8( descr->lines, descr->bits,
1061                                                 descr->infoWidth, descr->width, descr->xSrc,
1062                                                 descr->colorMap, bmpImage );
1063         else DIB_SetImageBits_8( descr->lines, descr->bits, descr->infoWidth,
1064                                  descr->width, descr->xSrc, descr->colorMap, bmpImage );
1065         break;
1066     case 15:
1067     case 16:
1068         DIB_SetImageBits_16( descr->lines, descr->bits, descr->infoWidth,
1069                              descr->width, descr->xSrc, descr->dc, bmpImage);
1070         break;
1071     case 24:
1072         DIB_SetImageBits_24( descr->lines, descr->bits, descr->infoWidth,
1073                              descr->width, descr->xSrc, descr->dc, bmpImage );
1074         break;
1075     case 32:
1076         DIB_SetImageBits_32( descr->lines, descr->bits, descr->infoWidth,
1077                              descr->width, descr->xSrc, descr->dc, bmpImage);
1078         break;
1079     default:
1080         WARN(bitmap, "(%d): Invalid depth\n", descr->infoBpp );
1081         break;
1082     }
1083
1084     XPutImage( display, descr->drawable, descr->gc, bmpImage,
1085                descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
1086                descr->width, descr->height );
1087
1088     if (!descr->image) XDestroyImage( bmpImage );
1089     return lines;
1090 }
1091
1092 /***********************************************************************
1093  *           DIB_GetImageBits
1094  *
1095  * Transfer the bits from an X image.
1096  * The Xlib critical section must be entered before calling this function.
1097  */
1098 static int DIB_GetImageBits( const DIB_SETIMAGEBITS_DESCR *descr )
1099 {
1100     int lines = descr->lines >= 0 ? descr->lines : -descr->lines;
1101     XImage *bmpImage;
1102
1103     if (descr->image)
1104         bmpImage = descr->image;
1105     else
1106         XCREATEIMAGE( bmpImage, descr->infoWidth, lines, descr->depth );
1107
1108     XGetSubImage( display, descr->drawable, descr->xDest, descr->yDest,
1109                   descr->width, descr->height, AllPlanes, ZPixmap,
1110                   bmpImage, descr->xSrc, descr->ySrc );
1111
1112       /* Transfer the pixels */
1113     switch(descr->infoBpp)
1114     {
1115     case 1:
1116         FIXME(bitmap, "Depth 1 not yet supported!\n");
1117        break;
1118
1119     case 4:
1120        if (descr->compression) FIXME(bitmap, "Compression not yet supported!\n");
1121        else DIB_GetImageBits_4( descr->lines, (LPVOID)descr->bits, descr->infoWidth,
1122                                 descr->width, descr->xSrc,
1123                                 descr->colorMap, descr->nColorMap, bmpImage );
1124        break;
1125
1126     case 8:
1127        if (descr->compression) FIXME(bitmap, "Compression not yet supported!\n");
1128        else DIB_GetImageBits_8( descr->lines, (LPVOID)descr->bits, descr->infoWidth,
1129                                 descr->width, descr->xSrc,
1130                                 descr->colorMap, descr->nColorMap, bmpImage );
1131        break;
1132
1133     case 15:
1134     case 16:
1135        DIB_GetImageBits_16( descr->lines, (LPVOID)descr->bits, descr->infoWidth,
1136                             descr->width, descr->xSrc, bmpImage );
1137        break;
1138
1139     case 24:
1140        DIB_GetImageBits_24( descr->lines, (LPVOID)descr->bits, descr->infoWidth,
1141                             descr->width, descr->xSrc, bmpImage );
1142        break;
1143
1144     case 32:
1145        DIB_GetImageBits_32( descr->lines, (LPVOID)descr->bits, descr->infoWidth,
1146                             descr->width, descr->xSrc, bmpImage );
1147        break;
1148
1149     default:
1150         WARN(bitmap, "(%d): Invalid depth\n", descr->infoBpp );
1151         break;
1152     }
1153
1154     if (!descr->image) XDestroyImage( bmpImage );
1155     return lines;
1156 }
1157
1158
1159 /***********************************************************************
1160  *           StretchDIBits16   (GDI.439)
1161  */
1162 INT16 WINAPI StretchDIBits16(HDC16 hdc, INT16 xDst, INT16 yDst, INT16 widthDst,
1163                        INT16 heightDst, INT16 xSrc, INT16 ySrc, INT16 widthSrc,
1164                        INT16 heightSrc, const VOID *bits,
1165                        const BITMAPINFO *info, UINT16 wUsage, DWORD dwRop )
1166 {
1167     return (INT16)StretchDIBits32( hdc, xDst, yDst, widthDst, heightDst,
1168                                    xSrc, ySrc, widthSrc, heightSrc, bits,
1169                                    info, wUsage, dwRop );
1170 }
1171
1172
1173 /***********************************************************************
1174  *           StretchDIBits32   (GDI32.351)
1175  */
1176 INT32 WINAPI StretchDIBits32(HDC32 hdc, INT32 xDst, INT32 yDst, INT32 widthDst,
1177                        INT32 heightDst, INT32 xSrc, INT32 ySrc, INT32 widthSrc,
1178                        INT32 heightSrc, const void *bits,
1179                        const BITMAPINFO *info, UINT32 wUsage, DWORD dwRop )
1180 {
1181     DC *dc = DC_GetDCPtr( hdc );
1182     if(!dc) return FALSE;
1183
1184     if(dc->funcs->pStretchDIBits)
1185            return dc->funcs->pStretchDIBits(dc, xDst, yDst, widthDst, 
1186                                             heightDst, xSrc, ySrc, widthSrc,
1187                                             heightSrc, bits, info, wUsage,
1188                                             dwRop);
1189     else { /* use StretchBlt32 */
1190         HBITMAP32 hBitmap, hOldBitmap;
1191         HDC32 hdcMem;
1192     
1193         hBitmap = CreateDIBitmap32( hdc, &info->bmiHeader, CBM_INIT,
1194                                     bits, info, wUsage );
1195         hdcMem = CreateCompatibleDC32( hdc );
1196         hOldBitmap = SelectObject32( hdcMem, hBitmap );
1197         StretchBlt32( hdc, xDst, yDst, widthDst, heightDst,
1198                       hdcMem, xSrc, ySrc, widthSrc, heightSrc, dwRop );
1199         SelectObject32( hdcMem, hOldBitmap );
1200         DeleteDC32( hdcMem );
1201         DeleteObject32( hBitmap );
1202         return heightSrc;
1203     }
1204 }
1205
1206
1207 /***********************************************************************
1208  *           SetDIBits16    (GDI.440)
1209  */
1210 INT16 WINAPI SetDIBits16( HDC16 hdc, HBITMAP16 hbitmap, UINT16 startscan,
1211                           UINT16 lines, LPCVOID bits, const BITMAPINFO *info,
1212                           UINT16 coloruse )
1213 {
1214     return SetDIBits32( hdc, hbitmap, startscan, lines, bits, info, coloruse );
1215 }
1216
1217
1218 /******************************************************************************
1219  * SetDIBits32 [GDI32.312]  Sets pixels in a bitmap using colors from DIB
1220  *
1221  * PARAMS
1222  *    hdc       [I] Handle to device context
1223  *    hbitmap   [I] Handle to bitmap
1224  *    startscan [I] Starting scan line
1225  *    lines     [I] Number of scan lines
1226  *    bits      [I] Array of bitmap bits
1227  *    info      [I] Address of structure with data
1228  *    coloruse  [I] Type of color indexes to use
1229  *
1230  * RETURNS
1231  *    Success: Number of scan lines copied
1232  *    Failure: 0
1233  */
1234 INT32 WINAPI SetDIBits32( HDC32 hdc, HBITMAP32 hbitmap, UINT32 startscan,
1235                           UINT32 lines, LPCVOID bits, const BITMAPINFO *info,
1236                           UINT32 coloruse )
1237 {
1238     DIB_SETIMAGEBITS_DESCR descr;
1239     BITMAPOBJ * bmp;
1240     int height, tmpheight;
1241     INT32 result;
1242
1243       /* Check parameters */
1244
1245     descr.dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
1246     if (!descr.dc) 
1247     {
1248         descr.dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
1249         if (!descr.dc) return 0;
1250     }
1251     if (!(bmp = (BITMAPOBJ *)GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
1252     {
1253         GDI_HEAP_UNLOCK( hdc );
1254         return 0;
1255     }
1256     if (DIB_GetBitmapInfo( &info->bmiHeader, &descr.infoWidth, &height,
1257                            &descr.infoBpp, &descr.compression ) == -1)
1258     {
1259         GDI_HEAP_UNLOCK( hbitmap );
1260         GDI_HEAP_UNLOCK( hdc );
1261         return 0;
1262     }
1263     tmpheight = height;
1264     if (height < 0) height = -height;
1265     if (!lines || (startscan >= height))
1266     {
1267         GDI_HEAP_UNLOCK( hbitmap );
1268         GDI_HEAP_UNLOCK( hdc );
1269         return 0;
1270     }
1271     if (startscan + lines > height) lines = height - startscan;
1272
1273     if (descr.infoBpp <= 8)
1274     {
1275         descr.colorMap = DIB_BuildColorMap( descr.dc, coloruse, bmp->bitmap.bmBitsPixel,
1276                                             info, &descr.nColorMap );
1277         if (!descr.colorMap)
1278         {
1279             GDI_HEAP_UNLOCK( hbitmap );
1280             GDI_HEAP_UNLOCK( hdc );
1281             return 0;
1282         } 
1283     } else
1284         descr.colorMap = 0;
1285
1286     /* HACK for now */
1287     if(!bmp->DDBitmap)
1288         X11DRV_CreateBitmap(hbitmap);
1289 {
1290     X11DRV_PHYSBITMAP *pbitmap = bmp->DDBitmap->physBitmap;
1291
1292
1293     descr.bits      = bits;
1294     descr.image     = NULL;
1295     descr.lines     = tmpheight >= 0 ? lines : -lines;
1296     descr.depth     = bmp->bitmap.bmBitsPixel;
1297     descr.drawable  = pbitmap->pixmap;
1298     descr.gc        = BITMAP_GC(bmp);
1299     descr.xSrc      = 0;
1300     descr.ySrc      = 0;
1301     descr.xDest     = 0;
1302     descr.yDest     = height - startscan - lines;
1303     descr.width     = bmp->bitmap.bmWidth;
1304     descr.height    = lines;
1305 }
1306     EnterCriticalSection( &X11DRV_CritSection );
1307     result = CALL_LARGE_STACK( DIB_SetImageBits, &descr );
1308     LeaveCriticalSection( &X11DRV_CritSection );
1309
1310     if (descr.colorMap) HeapFree(GetProcessHeap(), 0, descr.colorMap);
1311
1312     GDI_HEAP_UNLOCK( hdc );
1313     GDI_HEAP_UNLOCK( hbitmap );
1314     return result;
1315 }
1316
1317
1318 /***********************************************************************
1319  *           SetDIBitsToDevice16    (GDI.443)
1320  */
1321 INT16 WINAPI SetDIBitsToDevice16(HDC16 hdc, INT16 xDest, INT16 yDest, INT16 cx,
1322                            INT16 cy, INT16 xSrc, INT16 ySrc, UINT16 startscan,
1323                            UINT16 lines, LPCVOID bits, const BITMAPINFO *info,
1324                            UINT16 coloruse )
1325 {
1326     return SetDIBitsToDevice32( hdc, xDest, yDest, cx, cy, xSrc, ySrc,
1327                                 startscan, lines, bits, info, coloruse );
1328 }
1329
1330
1331 /***********************************************************************
1332  *           SetDIBitsToDevice32   (GDI32.313)
1333  */
1334 INT32 WINAPI SetDIBitsToDevice32(HDC32 hdc, INT32 xDest, INT32 yDest, DWORD cx,
1335                            DWORD cy, INT32 xSrc, INT32 ySrc, UINT32 startscan,
1336                            UINT32 lines, LPCVOID bits, const BITMAPINFO *info,
1337                            UINT32 coloruse )
1338 {
1339     DIB_SETIMAGEBITS_DESCR descr;
1340     DC * dc;
1341     DWORD width, oldcy = cy;
1342     INT32 result;
1343     int height, tmpheight;
1344
1345       /* Check parameters */
1346
1347     dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
1348     if (!dc) 
1349     {
1350         dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
1351         if (!dc) return 0;
1352     }
1353     if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, 
1354                            &descr.infoBpp, &descr.compression ) == -1)
1355         return 0;
1356     tmpheight = height;
1357     if (height < 0) height = -height;
1358     if (!lines || (startscan >= height)) return 0;
1359     if (startscan + lines > height) lines = height - startscan;
1360     if (ySrc < startscan) ySrc = startscan;
1361     else if (ySrc >= startscan + lines) return 0;
1362     if (xSrc >= width) return 0;
1363     if (ySrc + cy >= startscan + lines) cy = startscan + lines - ySrc;
1364     if (xSrc + cx >= width) cx = width - xSrc;
1365     if (!cx || !cy) return 0;
1366
1367     DC_SetupGCForText( dc );  /* To have the correct colors */
1368     TSXSetFunction( display, dc->u.x.gc, DC_XROPfunction[dc->w.ROPmode-1] );
1369
1370     if (descr.infoBpp <= 8)
1371     {
1372         descr.colorMap = DIB_BuildColorMap( dc, coloruse, dc->w.bitsPerPixel,
1373                                             info, &descr.nColorMap );
1374         if (!descr.colorMap)
1375             return 0;
1376     }
1377
1378     descr.dc        = dc;
1379     descr.bits      = bits;
1380     descr.image     = NULL;
1381     descr.lines     = tmpheight >= 0 ? lines : -lines;
1382     descr.infoWidth = width;
1383     descr.depth     = dc->w.bitsPerPixel;
1384     descr.drawable  = dc->u.x.drawable;
1385     descr.gc        = dc->u.x.gc;
1386     descr.xSrc      = xSrc;
1387     descr.ySrc      = tmpheight >= 0 ? lines-(ySrc-startscan)-cy+(oldcy-cy) : ySrc - startscan;
1388     descr.xDest     = dc->w.DCOrgX + XLPTODP( dc, xDest );
1389     descr.yDest     = dc->w.DCOrgY + YLPTODP( dc, yDest ) + (tmpheight >= 0 ? oldcy-cy : 0);
1390     descr.width     = cx;
1391     descr.height    = cy;
1392
1393     EnterCriticalSection( &X11DRV_CritSection );
1394     result = CALL_LARGE_STACK( DIB_SetImageBits, &descr );
1395     LeaveCriticalSection( &X11DRV_CritSection );
1396
1397     HeapFree(GetProcessHeap(), 0, descr.colorMap);
1398     return result;
1399 }
1400
1401 /***********************************************************************
1402  *           SetDIBColorTable16    (GDI.602)
1403  */
1404 UINT16 WINAPI SetDIBColorTable16( HDC16 hdc, UINT16 startpos, UINT16 entries,
1405                                   RGBQUAD *colors )
1406 {
1407     return SetDIBColorTable32( hdc, startpos, entries, colors );
1408 }
1409
1410 /***********************************************************************
1411  *           SetDIBColorTable32    (GDI32.311)
1412  */
1413 UINT32 WINAPI SetDIBColorTable32( HDC32 hdc, UINT32 startpos, UINT32 entries,
1414                                   RGBQUAD *colors )
1415 {
1416     DC * dc;
1417     PALETTEENTRY * palEntry;
1418     PALETTEOBJ * palette;
1419     RGBQUAD *end;
1420
1421     dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
1422     if (!dc) 
1423     {
1424         dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
1425         if (!dc) return 0;
1426     }
1427
1428     if (!(palette = (PALETTEOBJ*)GDI_GetObjPtr( dc->w.hPalette, PALETTE_MAGIC )))
1429     {
1430         return 0;
1431     }
1432
1433     /* Transfer color info */
1434     
1435     if (dc->w.bitsPerPixel <= 8) {
1436         palEntry = palette->logpalette.palPalEntry + startpos;
1437         if (startpos + entries > (1 << dc->w.bitsPerPixel)) {
1438             entries = (1 << dc->w.bitsPerPixel) - startpos;
1439         }
1440         for (end = colors + entries; colors < end; palEntry++, colors++)
1441         {
1442             palEntry->peRed   = colors->rgbRed;
1443             palEntry->peGreen = colors->rgbGreen;
1444             palEntry->peBlue  = colors->rgbBlue;
1445         }
1446     } else {
1447         entries = 0;
1448     }
1449     GDI_HEAP_UNLOCK( dc->w.hPalette );
1450     return entries;
1451 }
1452
1453 /***********************************************************************
1454  *           GetDIBColorTable16    (GDI.603)
1455  */
1456 UINT16 WINAPI GetDIBColorTable16( HDC16 hdc, UINT16 startpos, UINT16 entries,
1457                                   RGBQUAD *colors )
1458 {
1459     return GetDIBColorTable32( hdc, startpos, entries, colors );
1460 }
1461
1462 /***********************************************************************
1463  *           GetDIBColorTable32    (GDI32.169)
1464  */
1465 UINT32 WINAPI GetDIBColorTable32( HDC32 hdc, UINT32 startpos, UINT32 entries,
1466                                   RGBQUAD *colors )
1467 {
1468     DC * dc;
1469     PALETTEENTRY * palEntry;
1470     PALETTEOBJ * palette;
1471     RGBQUAD *end;
1472
1473     dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
1474     if (!dc) 
1475     {
1476         dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
1477         if (!dc) return 0;
1478     }
1479
1480     if (!(palette = (PALETTEOBJ*)GDI_GetObjPtr( dc->w.hPalette, PALETTE_MAGIC )))
1481     {
1482         return 0;
1483     }
1484
1485     /* Transfer color info */
1486     
1487     if (dc->w.bitsPerPixel <= 8) {
1488         palEntry = palette->logpalette.palPalEntry + startpos;
1489         if (startpos + entries > (1 << dc->w.bitsPerPixel)) {
1490             entries = (1 << dc->w.bitsPerPixel) - startpos;
1491         }
1492         for (end = colors + entries; colors < end; palEntry++, colors++)
1493         {
1494             colors->rgbRed      = palEntry->peRed;
1495             colors->rgbGreen    = palEntry->peGreen;
1496             colors->rgbBlue     = palEntry->peBlue;
1497             colors->rgbReserved = 0;
1498         }
1499     } else {
1500         entries = 0;
1501     }
1502     GDI_HEAP_UNLOCK( dc->w.hPalette );
1503     return entries;
1504 }
1505
1506 /***********************************************************************
1507  *           GetDIBits16    (GDI.441)
1508  */
1509 INT16 WINAPI GetDIBits16( HDC16 hdc, HBITMAP16 hbitmap, UINT16 startscan,
1510                           UINT16 lines, LPSTR bits, BITMAPINFO * info,
1511                           UINT16 coloruse )
1512 {
1513     return GetDIBits32( hdc, hbitmap, startscan, lines, bits, info, coloruse );
1514 }
1515
1516
1517 /******************************************************************************
1518  * GetDIBits32 [GDI32.170]  Retrieves bits of bitmap and copies to buffer
1519  *
1520  * RETURNS
1521  *    Success: Number of scan lines copied from bitmap
1522  *    Failure: 0
1523  *
1524  * http://www.microsoft.com/msdn/sdk/platforms/doc/sdk/win32/func/src/f30_14.htm
1525  */
1526 INT32 WINAPI GetDIBits32(
1527     HDC32 hdc,         /* [in]  Handle to device context */
1528     HBITMAP32 hbitmap, /* [in]  Handle to bitmap */
1529     UINT32 startscan,  /* [in]  First scan line to set in dest bitmap */
1530     UINT32 lines,      /* [in]  Number of scan lines to copy */
1531     LPSTR bits,        /* [out] Address of array for bitmap bits */
1532     BITMAPINFO * info, /* [out] Address of structure with bitmap data */
1533     UINT32 coloruse)   /* [in]  RGB or palette index */
1534 {
1535     DC * dc;
1536     BITMAPOBJ * bmp;
1537     PALETTEENTRY * palEntry;
1538     PALETTEOBJ * palette;
1539     XImage * bmpImage;
1540     int i, x, y;
1541
1542     if (!lines) return 0;
1543     dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
1544     if (!dc) 
1545     {
1546         dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
1547         if (!dc) return 0;
1548     }
1549     if (!(bmp = (BITMAPOBJ *)GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
1550         return 0;
1551     if (!(palette = (PALETTEOBJ*)GDI_GetObjPtr( dc->w.hPalette, PALETTE_MAGIC )))
1552     {
1553         GDI_HEAP_UNLOCK( hbitmap );
1554         return 0;
1555     }
1556
1557       /* Transfer color info */
1558     
1559     if (info->bmiHeader.biBitCount<=8) {
1560         int colors = info->bmiHeader.biClrUsed;
1561         if (!colors && (info->bmiHeader.biBitCount <= 8))
1562             colors = 1 << info->bmiHeader.biBitCount;
1563         palEntry = palette->logpalette.palPalEntry;
1564         for (i = 0; i < colors; i++, palEntry++)
1565         {
1566             if (coloruse == DIB_RGB_COLORS)
1567             {
1568                 info->bmiColors[i].rgbRed      = palEntry->peRed;
1569                 info->bmiColors[i].rgbGreen    = palEntry->peGreen;
1570                 info->bmiColors[i].rgbBlue     = palEntry->peBlue;
1571                 info->bmiColors[i].rgbReserved = 0;
1572             }
1573             else ((WORD *)info->bmiColors)[i] = (WORD)i;
1574         }
1575     }
1576
1577     if (bits)
1578     {   
1579         BYTE*   bbits = bits;
1580         int     pad, yend, xend = bmp->bitmap.bmWidth;
1581
1582         TRACE(bitmap, "%u scanlines of (%i,%i) -> (%i,%i) starting from %u\n",
1583                             lines, bmp->bitmap.bmWidth, bmp->bitmap.bmHeight,
1584                             (int)info->bmiHeader.biWidth, (int)info->bmiHeader.biHeight, startscan );
1585
1586         /* adjust number of scanlines to copy */
1587
1588         if( lines > info->bmiHeader.biHeight ) lines = info->bmiHeader.biHeight;
1589         yend = startscan + lines;
1590         if( startscan >= bmp->bitmap.bmHeight ) 
1591         {
1592             GDI_HEAP_UNLOCK( hbitmap );
1593             GDI_HEAP_UNLOCK( dc->w.hPalette );
1594             return FALSE;
1595         }
1596         if( yend > bmp->bitmap.bmHeight ) yend = bmp->bitmap.bmHeight;
1597
1598         /* adjust scanline width */
1599
1600         pad = info->bmiHeader.biWidth - bmp->bitmap.bmWidth;
1601         if( pad < 0 ) 
1602         {
1603             /* bitmap is wider than DIB, copy only a part */
1604
1605             pad = 0;
1606             xend = info->bmiHeader.biWidth;
1607         }
1608
1609         /* HACK for now */
1610         if(!bmp->DDBitmap)
1611             X11DRV_CreateBitmap(hbitmap);
1612
1613         EnterCriticalSection( &X11DRV_CritSection );
1614         bmpImage = (XImage *)CALL_LARGE_STACK( X11DRV_BITMAP_GetXImage, bmp );
1615
1616         switch( info->bmiHeader.biBitCount )
1617         {
1618            case 8:
1619                 /* pad up to 32 bit */
1620                 pad += (4 - (info->bmiHeader.biWidth & 3)) & 3;
1621                 for( y = yend - 1; (int)y >= (int)startscan; y-- )
1622                 {
1623                    for( x = 0; x < xend; x++ )
1624                         *bbits++ = XGetPixel( bmpImage, x, y );
1625                    bbits += pad;
1626                 }
1627                 break;
1628            case 1:
1629                 pad += ((32 - (info->bmiHeader.biWidth & 31)) / 8) & 3;
1630                 for( y = yend - 1; (int)y >= (int)startscan; y-- )
1631                 {
1632                    for( x = 0; x < xend; x++ ) {
1633                         if (!(x&7)) *bbits = 0;
1634                         *bbits |= XGetPixel( bmpImage, x, y)<<(7-(x&7));
1635                         if ((x&7)==7) bbits++;
1636                    }
1637                    bbits += pad;
1638                 }
1639                 break;
1640            case 4:
1641                 pad += ((8 - (info->bmiHeader.biWidth & 7)) / 2) & 3;
1642                 for( y = yend - 1; (int)y >= (int)startscan; y-- )
1643                 {
1644                    for( x = 0; x < xend; x++ ) {
1645                         if (!(x&1)) *bbits = 0;
1646                         *bbits |= XGetPixel( bmpImage, x, y)<<(4*(1-(x&1)));
1647                         if ((x&1)==1) bbits++;
1648                    }
1649                    bbits += pad;
1650                 }
1651                 break;
1652            case 15:
1653            case 16:
1654                 pad += (4 - ((info->bmiHeader.biWidth*2) & 3)) & 3;
1655                 for( y = yend - 1; (int)y >= (int)startscan; y-- )
1656                 {
1657                    for( x = 0; x < xend; x++ ) {
1658                         unsigned long pixel=XGetPixel( bmpImage, x, y);
1659                         *bbits++ = pixel & 0xff;
1660                         *bbits++ = (pixel >> 8) & 0xff;
1661                    }
1662                    bbits += pad;
1663                 }
1664                 break;
1665            case 24:
1666                 pad += (4 - ((info->bmiHeader.biWidth*3) & 3)) & 3;
1667                 for( y = yend - 1; (int)y >= (int)startscan; y-- )
1668                 {
1669                    for( x = 0; x < xend; x++ ) {
1670                         unsigned long pixel=XGetPixel( bmpImage, x, y);
1671                         *bbits++ = (pixel >>16) & 0xff;
1672                         *bbits++ = (pixel >> 8) & 0xff;
1673                         *bbits++ =  pixel       & 0xff;
1674                    }
1675                    bbits += pad;
1676                 }
1677                 break;
1678            case 32:
1679                 for( y = yend - 1; (int)y >= (int)startscan; y-- )
1680                 {
1681                    for( x = 0; x < xend; x++ ) {
1682                         unsigned long pixel=XGetPixel( bmpImage, x, y);
1683                         *bbits++ = (pixel >>16) & 0xff;
1684                         *bbits++ = (pixel >> 8) & 0xff;
1685                         *bbits++ =  pixel       & 0xff;
1686                    }
1687                 }
1688                 break;
1689            default:
1690                 WARN(bitmap,"Unsupported depth %d\n",
1691                    info->bmiHeader.biBitCount);
1692                 break;
1693         }
1694
1695         XDestroyImage( bmpImage );
1696         LeaveCriticalSection( &X11DRV_CritSection );
1697
1698         info->bmiHeader.biCompression = 0;
1699     }
1700     else if( info->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER) ) 
1701     {
1702         /* fill in struct members */
1703         
1704         info->bmiHeader.biWidth = bmp->bitmap.bmWidth;
1705         info->bmiHeader.biHeight = bmp->bitmap.bmHeight;
1706         info->bmiHeader.biPlanes = 1;
1707         info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel;
1708         info->bmiHeader.biSizeImage = bmp->bitmap.bmHeight *
1709                              DIB_GetDIBWidthBytes( bmp->bitmap.bmWidth,
1710                                                    bmp->bitmap.bmBitsPixel );
1711         info->bmiHeader.biCompression = 0;
1712     }
1713
1714     GDI_HEAP_UNLOCK( hbitmap );
1715     GDI_HEAP_UNLOCK( dc->w.hPalette );
1716     return lines;
1717 }
1718
1719
1720 /***********************************************************************
1721  *           CreateDIBitmap16    (GDI.442)
1722  */
1723 HBITMAP16 WINAPI CreateDIBitmap16( HDC16 hdc, const BITMAPINFOHEADER * header,
1724                             DWORD init, LPCVOID bits, const BITMAPINFO * data,
1725                             UINT16 coloruse )
1726 {
1727     return CreateDIBitmap32( hdc, header, init, bits, data, coloruse );
1728 }
1729
1730
1731 /***********************************************************************
1732  *           CreateDIBitmap32    (GDI32.37)
1733  */
1734 HBITMAP32 WINAPI CreateDIBitmap32( HDC32 hdc, const BITMAPINFOHEADER *header,
1735                             DWORD init, LPCVOID bits, const BITMAPINFO *data,
1736                             UINT32 coloruse )
1737 {
1738     HBITMAP32 handle;
1739     BOOL32 fColor;
1740     DWORD width;
1741     int height;
1742     WORD bpp;
1743     WORD compr;
1744
1745     if (DIB_GetBitmapInfo( header, &width, &height, &bpp, &compr ) == -1) return 0;
1746     if (height < 0) height = -height;
1747
1748     /* Check if we should create a monochrome or color bitmap. */
1749     /* We create a monochrome bitmap only if it has exactly 2  */
1750     /* colors, which are either black or white, nothing else.  */
1751     /* In all other cases, we create a color bitmap.           */
1752
1753     if (bpp != 1) fColor = TRUE;
1754     else if ((coloruse != DIB_RGB_COLORS) ||
1755              (init != CBM_INIT) || !data) fColor = FALSE;
1756     else
1757     {
1758         if (data->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
1759         {
1760             RGBQUAD *rgb = data->bmiColors;
1761             DWORD col = RGB( rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue );
1762             if ((col == RGB(0,0,0)) || (col == RGB(0xff,0xff,0xff)))
1763             {
1764                 rgb++;
1765                 col = RGB( rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue );
1766                 fColor = ((col != RGB(0,0,0)) && (col != RGB(0xff,0xff,0xff)));
1767             }
1768             else fColor = TRUE;
1769         }
1770         else if (data->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
1771         {
1772             RGBTRIPLE *rgb = ((BITMAPCOREINFO *)data)->bmciColors;
1773             DWORD col = RGB( rgb->rgbtRed, rgb->rgbtGreen, rgb->rgbtBlue );
1774             if ((col == RGB(0,0,0)) || (col == RGB(0xff,0xff,0xff)))
1775             {
1776                 rgb++;
1777                 col = RGB( rgb->rgbtRed, rgb->rgbtGreen, rgb->rgbtBlue );
1778                 fColor = ((col != RGB(0,0,0)) && (col != RGB(0xff,0xff,0xff)));
1779             }
1780             else fColor = TRUE;
1781         }
1782         else
1783         {
1784             WARN(bitmap, "(%ld): wrong size for data\n",
1785                      data->bmiHeader.biSize );
1786             return 0;
1787         }
1788     }
1789
1790     /* Now create the bitmap */
1791
1792     handle = fColor ? CreateBitmap32( width, height, 1, screenDepth, NULL ) :
1793                       CreateBitmap32( width, height, 1, 1, NULL );
1794     if (!handle) return 0;
1795
1796     if (init == CBM_INIT)
1797         SetDIBits32( hdc, handle, 0, height, bits, data, coloruse );
1798     return handle;
1799 }
1800
1801
1802 /***********************************************************************
1803  *           DIB_DoProtectDIBSection
1804  */
1805 static void DIB_DoProtectDIBSection( BITMAPOBJ *bmp, DWORD new_prot )
1806 {
1807     DIBSECTION *dib = &bmp->dib->dibSection;
1808     INT32 effHeight = dib->dsBm.bmHeight >= 0? dib->dsBm.bmHeight
1809                                              : -dib->dsBm.bmHeight;
1810     INT32 totalSize = dib->dsBmih.biSizeImage? dib->dsBmih.biSizeImage
1811                          : dib->dsBm.bmWidthBytes * effHeight;
1812     DWORD old_prot;
1813
1814     VirtualProtect(dib->dsBm.bmBits, totalSize, new_prot, &old_prot);
1815     TRACE(bitmap, "Changed protection from %ld to %ld\n", 
1816                   old_prot, new_prot);
1817 }
1818
1819 /***********************************************************************
1820  *           DIB_DoUpdateDIBSection
1821  */
1822 static void DIB_DoUpdateDIBSection( BITMAPOBJ *bmp, BOOL32 toDIB )
1823 {
1824     DIBSECTIONOBJ *dib = bmp->dib;
1825     DIB_SETIMAGEBITS_DESCR descr;
1826
1827     if (DIB_GetBitmapInfo( &dib->dibSection.dsBmih, &descr.infoWidth, &descr.lines,
1828                            &descr.infoBpp, &descr.compression ) == -1)
1829         return;
1830
1831     descr.dc        = NULL;
1832     descr.image     = dib->image;
1833     descr.colorMap  = dib->colorMap;
1834     descr.nColorMap = dib->nColorMap;
1835     descr.bits      = dib->dibSection.dsBm.bmBits;
1836     descr.depth     = bmp->bitmap.bmBitsPixel;
1837     
1838     /* Hack for now */
1839     descr.drawable  = ((X11DRV_PHYSBITMAP *)bmp->DDBitmap->physBitmap)->pixmap;
1840     descr.gc        = BITMAP_GC(bmp);
1841     descr.xSrc      = 0;
1842     descr.ySrc      = 0;
1843     descr.xDest     = 0;
1844     descr.yDest     = 0;
1845     descr.width     = bmp->bitmap.bmWidth;
1846     descr.height    = bmp->bitmap.bmHeight;
1847
1848     if (toDIB)
1849     {
1850         TRACE(bitmap, "Copying from Pixmap to DIB bits\n");
1851         EnterCriticalSection( &X11DRV_CritSection );
1852         CALL_LARGE_STACK( DIB_GetImageBits, &descr );
1853         LeaveCriticalSection( &X11DRV_CritSection );
1854     }
1855     else
1856     {
1857         TRACE(bitmap, "Copying from DIB bits to Pixmap\n"); 
1858         EnterCriticalSection( &X11DRV_CritSection );
1859         CALL_LARGE_STACK( DIB_SetImageBits, &descr );
1860         LeaveCriticalSection( &X11DRV_CritSection );
1861     }
1862 }
1863
1864 /***********************************************************************
1865  *           DIB_FaultHandler
1866  */
1867 static BOOL32 DIB_FaultHandler( LPVOID res, LPVOID addr )
1868 {
1869     BOOL32 handled = FALSE;
1870     BITMAPOBJ *bmp;
1871
1872     bmp = (BITMAPOBJ *)GDI_GetObjPtr( (HBITMAP32)res, BITMAP_MAGIC );
1873     if (!bmp) return FALSE;
1874
1875     if (bmp->dib)
1876         switch (bmp->dib->status)
1877         {
1878         case DIB_GdiMod:
1879             TRACE( bitmap, "called in status DIB_GdiMod\n" );
1880             DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
1881             DIB_DoUpdateDIBSection( bmp, TRUE );
1882             DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
1883             bmp->dib->status = DIB_InSync;
1884             handled = TRUE;
1885             break;
1886
1887         case DIB_InSync:
1888             TRACE( bitmap, "called in status DIB_InSync\n" );
1889             DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
1890             bmp->dib->status = DIB_AppMod;
1891             handled = TRUE;
1892             break;
1893
1894         case DIB_AppMod:
1895             FIXME( bitmap, "called in status DIB_AppMod: "
1896                            "this can't happen!\n" );
1897             break;
1898
1899         case DIB_NoHandler:
1900             FIXME( bitmap, "called in status DIB_NoHandler: "
1901                            "this can't happen!\n" );
1902             break;
1903         }
1904
1905     GDI_HEAP_UNLOCK( (HBITMAP32)res );
1906     return handled;
1907 }
1908
1909 /***********************************************************************
1910  *           DIB_UpdateDIBSection
1911  */
1912 void DIB_UpdateDIBSection( DC *dc, BOOL32 toDIB )
1913 {
1914     BITMAPOBJ *bmp;
1915
1916     /* Ensure this is a Compatible DC that has a DIB section selected */
1917
1918     if (!dc) return;
1919     if (!(dc->w.flags & DC_MEMORY)) return;
1920
1921     bmp = (BITMAPOBJ *)GDI_GetObjPtr( dc->w.hBitmap, BITMAP_MAGIC );
1922     if (!bmp) return;
1923
1924     if (!bmp->dib)
1925     {
1926         GDI_HEAP_UNLOCK(dc->w.hBitmap);
1927         return;
1928     }
1929
1930
1931     if (!toDIB)
1932     {
1933         /* Prepare for access to the DIB by GDI functions */
1934
1935         switch (bmp->dib->status)
1936         {
1937         default:
1938         case DIB_NoHandler:
1939             DIB_DoUpdateDIBSection( bmp, FALSE );
1940             break;
1941
1942         case DIB_GdiMod:
1943             TRACE( bitmap, "fromDIB called in status DIB_GdiMod\n" );
1944             /* nothing to do */
1945             break;
1946
1947         case DIB_InSync:
1948             TRACE( bitmap, "fromDIB called in status DIB_InSync\n" );
1949             /* nothing to do */
1950             break;
1951
1952         case DIB_AppMod:
1953             TRACE( bitmap, "fromDIB called in status DIB_AppMod\n" );
1954             DIB_DoUpdateDIBSection( bmp, FALSE );
1955             DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
1956             bmp->dib->status = DIB_InSync;
1957             break;
1958         }
1959     }
1960     else
1961     {
1962         /* Acknowledge write access to the DIB by GDI functions */
1963
1964         switch (bmp->dib->status)
1965         {
1966         default:
1967         case DIB_NoHandler:
1968             DIB_DoUpdateDIBSection( bmp, TRUE );
1969             break;
1970
1971         case DIB_GdiMod:
1972             TRACE( bitmap, "  toDIB called in status DIB_GdiMod\n" );
1973             /* nothing to do */
1974             break;
1975
1976         case DIB_InSync:
1977             TRACE( bitmap, "  toDIB called in status DIB_InSync\n" );
1978             DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS );
1979             bmp->dib->status = DIB_GdiMod;
1980             break;
1981
1982         case DIB_AppMod:
1983             FIXME( bitmap, "  toDIB called in status DIB_AppMod: "
1984                            "this can't happen!\n" );
1985             break;
1986         }
1987     }
1988
1989   
1990     GDI_HEAP_UNLOCK(dc->w.hBitmap);
1991 }
1992
1993 /***********************************************************************
1994  *           CreateDIBSection16    (GDI.489)
1995  */
1996 HBITMAP16 WINAPI CreateDIBSection16 (HDC16 hdc, BITMAPINFO *bmi, UINT16 usage,
1997                                      LPVOID **bits, HANDLE32 section,
1998                                      DWORD offset)
1999 {
2000     return CreateDIBSection32(hdc, bmi, usage, bits, section, offset);
2001 }
2002
2003 /***********************************************************************
2004  *           CreateDIBSection32    (GDI32.36)
2005  */
2006 HBITMAP32 WINAPI CreateDIBSection32 (HDC32 hdc, BITMAPINFO *bmi, UINT32 usage,
2007                                      LPVOID **bits,HANDLE32 section,
2008                                      DWORD offset)
2009 {
2010     HBITMAP32 res = 0;
2011     BITMAPOBJ *bmp = NULL;
2012     DIBSECTIONOBJ *dib = NULL;
2013     int *colorMap = NULL;
2014     int nColorMap;
2015
2016     /* Fill BITMAP32 structure with DIB data */
2017     BITMAPINFOHEADER *bi = &bmi->bmiHeader;
2018     INT32 effHeight, totalSize;
2019     BITMAP32 bm;
2020
2021     TRACE(bitmap, "format (%ld,%ld), planes %d, bpp %d, size %ld, colors %ld (%s)\n",
2022           bi->biWidth, bi->biHeight, bi->biPlanes, bi->biBitCount,
2023           bi->biSizeImage, bi->biClrUsed, usage == DIB_PAL_COLORS? "PAL" : "RGB");
2024
2025     bm.bmType = 0;
2026     bm.bmWidth = bi->biWidth;
2027     bm.bmHeight = bi->biHeight;
2028     bm.bmWidthBytes = DIB_GetDIBWidthBytes(bm.bmWidth, bi->biBitCount);
2029     bm.bmPlanes = bi->biPlanes;
2030     bm.bmBitsPixel = bi->biBitCount;
2031     bm.bmBits = NULL;
2032
2033     /* Get storage location for DIB bits */
2034     effHeight = bm.bmHeight >= 0 ? bm.bmHeight : -bm.bmHeight;
2035     totalSize = bi->biSizeImage? bi->biSizeImage : bm.bmWidthBytes * effHeight;
2036
2037     if (section)
2038         bm.bmBits = MapViewOfFile(section, FILE_MAP_ALL_ACCESS, 
2039                                   0L, offset, totalSize);
2040     else
2041         bm.bmBits = VirtualAlloc(NULL, totalSize, 
2042                                  MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
2043
2044     /* Create Color Map */
2045     if (bm.bmBits && bm.bmBitsPixel <= 8)
2046     {
2047         DC *dc = hdc? (DC *)GDI_GetObjPtr(hdc, DC_MAGIC) : NULL;
2048         if (hdc && !dc) dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
2049
2050         if (!hdc || dc)
2051             colorMap = DIB_BuildColorMap( dc, usage, bm.bmBitsPixel,
2052                                           bmi, &nColorMap );
2053         GDI_HEAP_UNLOCK(hdc);
2054     }
2055
2056     /* Allocate Memory for DIB and fill structure */
2057     if (bm.bmBits)
2058         dib = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DIBSECTIONOBJ));
2059     if (dib)
2060     {
2061         dib->dibSection.dsBm = bm;
2062         dib->dibSection.dsBmih = *bi;
2063         /* FIXME: dib->dibSection.dsBitfields ??? */
2064         dib->dibSection.dshSection = section;
2065         dib->dibSection.dsOffset = offset;
2066
2067         dib->status    = DIB_NoHandler;
2068         
2069         dib->nColorMap = nColorMap;
2070         dib->colorMap  = colorMap;
2071     }
2072
2073     /* Create Device Dependent Bitmap and add DIB pointer */
2074     if (dib) 
2075     {
2076        res = CreateDIBitmap32(hdc, bi, 0, NULL, bmi, usage);
2077        bmp = (BITMAPOBJ *) GDI_GetObjPtr(res, BITMAP_MAGIC);
2078        if (bmp) bmp->dib = dib;
2079
2080        /* HACK for now */
2081        if(!bmp->DDBitmap)
2082           X11DRV_CreateBitmap(res); 
2083     }
2084
2085     /* Create XImage */
2086     if (dib && bmp)
2087         XCREATEIMAGE( dib->image, bm.bmWidth, effHeight, bmp->bitmap.bmBitsPixel );
2088
2089     /* Clean up in case of errors */
2090     if (!res || !bmp || !dib || !bm.bmBits || (bm.bmBitsPixel <= 8 && !colorMap))
2091     {
2092         if (bm.bmBits)
2093             if (section)
2094                 UnmapViewOfFile(bm.bmBits), bm.bmBits = NULL;
2095             else
2096                 VirtualFree(bm.bmBits, MEM_RELEASE, 0L), bm.bmBits = NULL;
2097
2098         if (dib->image) XDestroyImage(dib->image), dib->image = NULL;
2099         if (colorMap) HeapFree(GetProcessHeap(), 0, colorMap), colorMap = NULL;
2100         if (dib) HeapFree(GetProcessHeap(), 0, dib), dib = NULL;
2101         if (res) DeleteObject32(res), res = 0;
2102     }
2103
2104     /* Install fault handler, if possible */
2105     if (bm.bmBits)
2106         if (VIRTUAL_SetFaultHandler(bm.bmBits, DIB_FaultHandler, (LPVOID)res))
2107         {
2108             DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
2109             dib->status = DIB_InSync;
2110         }
2111
2112     /* Return BITMAP handle and storage location */
2113     if (res) GDI_HEAP_UNLOCK(res);
2114     if (bm.bmBits && bits) *bits = bm.bmBits;
2115     return res;
2116 }
2117
2118 /***********************************************************************
2119  *           DIB_DeleteDIBSection
2120  */
2121 void DIB_DeleteDIBSection( BITMAPOBJ *bmp )
2122 {
2123     if (bmp && bmp->dib)
2124     {
2125         DIBSECTIONOBJ *dib = bmp->dib;
2126
2127         if (dib->dibSection.dsBm.bmBits)
2128             if (dib->dibSection.dshSection)
2129                 UnmapViewOfFile(dib->dibSection.dsBm.bmBits);
2130             else
2131                 VirtualFree(dib->dibSection.dsBm.bmBits, MEM_RELEASE, 0L);
2132
2133         if (dib->image) 
2134             XDestroyImage( dib->image );
2135
2136         if (dib->colorMap)
2137             HeapFree(GetProcessHeap(), 0, dib->colorMap);
2138
2139         HeapFree(GetProcessHeap(), 0, dib);
2140         bmp->dib = NULL;
2141     }
2142 }
2143
2144 /***********************************************************************
2145  *           DIB_FixColorsToLoadflags
2146  *
2147  * Change color table entries when LR_LOADTRANSPARENT or LR_LOADMAP3DCOLORS
2148  * are in loadflags
2149  */
2150 void DIB_FixColorsToLoadflags(BITMAPINFO * bmi, UINT32 loadflags, BYTE pix)
2151 {
2152   int colors;
2153   COLORREF c_W, c_S, c_F, c_L, c_C;
2154   int incr,i;
2155   RGBQUAD *ptr;
2156
2157   if (bmi->bmiHeader.biBitCount > 8) return;
2158   if (bmi->bmiHeader.biSize == sizeof(BITMAPINFOHEADER)) incr = 4;
2159   else if (bmi->bmiHeader.biSize == sizeof(BITMAPCOREHEADER)) incr = 3;
2160   else {
2161     WARN(bitmap, "Wrong bitmap header size!\n");
2162     return;
2163   }
2164   colors = bmi->bmiHeader.biClrUsed;
2165   if (!colors && (bmi->bmiHeader.biBitCount <= 8))
2166     colors = 1 << bmi->bmiHeader.biBitCount;
2167   c_W = GetSysColor32(COLOR_WINDOW);
2168   c_S = GetSysColor32(COLOR_3DSHADOW);
2169   c_F = GetSysColor32(COLOR_3DFACE);
2170   c_L = GetSysColor32(COLOR_3DLIGHT);
2171   if (loadflags & LR_LOADTRANSPARENT) {
2172     switch (bmi->bmiHeader.biBitCount) {
2173       case 1: pix = pix >> 7; break;
2174       case 4: pix = pix >> 4; break;
2175       case 8: break;
2176       default: 
2177         WARN(bitmap, "(%d): Unsupported depth\n", bmi->bmiHeader.biBitCount); 
2178         return;
2179     }
2180     if (pix >= colors) {
2181       WARN(bitmap, "pixel has color index greater than biClrUsed!\n");
2182       return;
2183     }
2184     if (loadflags & LR_LOADMAP3DCOLORS) c_W = c_F;
2185     ptr = (RGBQUAD*)((char*)bmi->bmiColors+pix*incr);
2186     ptr->rgbBlue = GetBValue(c_W);
2187     ptr->rgbGreen = GetGValue(c_W);
2188     ptr->rgbRed = GetRValue(c_W);
2189   }
2190   if (loadflags & LR_LOADMAP3DCOLORS)
2191     for (i=0; i<colors; i++) {
2192       ptr = (RGBQUAD*)((char*)bmi->bmiColors+i*incr);
2193       c_C = RGB(ptr->rgbRed, ptr->rgbGreen, ptr->rgbBlue);
2194       if (c_C == RGB(128, 128, 128)) { 
2195         ptr->rgbRed = GetRValue(c_S);
2196         ptr->rgbGreen = GetGValue(c_S);
2197         ptr->rgbBlue = GetBValue(c_S);
2198       } else if (c_C == RGB(192, 192, 192)) { 
2199         ptr->rgbRed = GetRValue(c_F);
2200         ptr->rgbGreen = GetGValue(c_F);
2201         ptr->rgbBlue = GetBValue(c_F);
2202       } else if (c_C == RGB(223, 223, 223)) { 
2203         ptr->rgbRed = GetRValue(c_L);
2204         ptr->rgbGreen = GetGValue(c_L);
2205         ptr->rgbBlue = GetBValue(c_L);
2206       } 
2207     }
2208 }