Added DC object type to the list of valid objects that can be deleted
[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 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 static 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     WORD 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     HBITMAP32 hBitmap, hOldBitmap;
1182     HDC32 hdcMem;
1183
1184     hBitmap = CreateDIBitmap32( hdc, &info->bmiHeader, CBM_INIT,
1185                                 bits, info, wUsage );
1186     hdcMem = CreateCompatibleDC32( hdc );
1187     hOldBitmap = SelectObject32( hdcMem, hBitmap );
1188     StretchBlt32( hdc, xDst, yDst, widthDst, heightDst,
1189                   hdcMem, xSrc, ySrc, widthSrc, heightSrc, dwRop );
1190     SelectObject32( hdcMem, hOldBitmap );
1191     DeleteDC32( hdcMem );
1192     DeleteObject32( hBitmap );
1193     return heightSrc;
1194 }
1195
1196
1197 /***********************************************************************
1198  *           SetDIBits16    (GDI.440)
1199  */
1200 INT16 WINAPI SetDIBits16( HDC16 hdc, HBITMAP16 hbitmap, UINT16 startscan,
1201                           UINT16 lines, LPCVOID bits, const BITMAPINFO *info,
1202                           UINT16 coloruse )
1203 {
1204     return SetDIBits32( hdc, hbitmap, startscan, lines, bits, info, coloruse );
1205 }
1206
1207
1208 /******************************************************************************
1209  * SetDIBits32 [GDI32.312]  Sets pixels in a bitmap using colors from DIB
1210  *
1211  * PARAMS
1212  *    hdc       [I] Handle to device context
1213  *    hbitmap   [I] Handle to bitmap
1214  *    startscan [I] Starting scan line
1215  *    lines     [I] Number of scan lines
1216  *    bits      [I] Array of bitmap bits
1217  *    info      [I] Address of structure with data
1218  *    coloruse  [I] Type of color indexes to use
1219  *
1220  * RETURNS
1221  *    Success: Number of scan lines copied
1222  *    Failure: 0
1223  */
1224 INT32 WINAPI SetDIBits32( HDC32 hdc, HBITMAP32 hbitmap, UINT32 startscan,
1225                           UINT32 lines, LPCVOID bits, const BITMAPINFO *info,
1226                           UINT32 coloruse )
1227 {
1228     DIB_SETIMAGEBITS_DESCR descr;
1229     BITMAPOBJ * bmp;
1230     int height, tmpheight;
1231     INT32 result;
1232
1233       /* Check parameters */
1234
1235     descr.dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
1236     if (!descr.dc) 
1237     {
1238         descr.dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
1239         if (!descr.dc) return 0;
1240     }
1241     if (!(bmp = (BITMAPOBJ *)GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
1242     {
1243         GDI_HEAP_UNLOCK( hdc );
1244         return 0;
1245     }
1246     if (DIB_GetBitmapInfo( &info->bmiHeader, &descr.infoWidth, &height,
1247                            &descr.infoBpp, &descr.compression ) == -1)
1248     {
1249         GDI_HEAP_UNLOCK( hbitmap );
1250         GDI_HEAP_UNLOCK( hdc );
1251         return 0;
1252     }
1253     tmpheight = height;
1254     if (height < 0) height = -height;
1255     if (!lines || (startscan >= height))
1256     {
1257         GDI_HEAP_UNLOCK( hbitmap );
1258         GDI_HEAP_UNLOCK( hdc );
1259         return 0;
1260     }
1261     if (startscan + lines > height) lines = height - startscan;
1262
1263     if (descr.infoBpp <= 8)
1264     {
1265         descr.colorMap = DIB_BuildColorMap( descr.dc, coloruse, bmp->bitmap.bmBitsPixel,
1266                                             info, &descr.nColorMap );
1267         if (!descr.colorMap)
1268         {
1269             GDI_HEAP_UNLOCK( hbitmap );
1270             GDI_HEAP_UNLOCK( hdc );
1271             return 0;
1272         } 
1273     }
1274
1275     descr.bits      = bits;
1276     descr.image     = NULL;
1277     descr.lines     = tmpheight >= 0 ? lines : -lines;
1278     descr.depth     = bmp->bitmap.bmBitsPixel;
1279     descr.drawable  = bmp->pixmap;
1280     descr.gc        = BITMAP_GC(bmp);
1281     descr.xSrc      = 0;
1282     descr.ySrc      = 0;
1283     descr.xDest     = 0;
1284     descr.yDest     = height - startscan - lines;
1285     descr.width     = bmp->bitmap.bmWidth;
1286     descr.height    = lines;
1287
1288     EnterCriticalSection( &X11DRV_CritSection );
1289     result = CALL_LARGE_STACK( DIB_SetImageBits, &descr );
1290     LeaveCriticalSection( &X11DRV_CritSection );
1291
1292     HeapFree(GetProcessHeap(), 0, descr.colorMap);
1293
1294     GDI_HEAP_UNLOCK( hdc );
1295     GDI_HEAP_UNLOCK( hbitmap );
1296     return result;
1297 }
1298
1299
1300 /***********************************************************************
1301  *           SetDIBitsToDevice16    (GDI.443)
1302  */
1303 INT16 WINAPI SetDIBitsToDevice16(HDC16 hdc, INT16 xDest, INT16 yDest, INT16 cx,
1304                            INT16 cy, INT16 xSrc, INT16 ySrc, UINT16 startscan,
1305                            UINT16 lines, LPCVOID bits, const BITMAPINFO *info,
1306                            UINT16 coloruse )
1307 {
1308     return SetDIBitsToDevice32( hdc, xDest, yDest, cx, cy, xSrc, ySrc,
1309                                 startscan, lines, bits, info, coloruse );
1310 }
1311
1312
1313 /***********************************************************************
1314  *           SetDIBitsToDevice32   (GDI32.313)
1315  */
1316 INT32 WINAPI SetDIBitsToDevice32(HDC32 hdc, INT32 xDest, INT32 yDest, DWORD cx,
1317                            DWORD cy, INT32 xSrc, INT32 ySrc, UINT32 startscan,
1318                            UINT32 lines, LPCVOID bits, const BITMAPINFO *info,
1319                            UINT32 coloruse )
1320 {
1321     DIB_SETIMAGEBITS_DESCR descr;
1322     DC * dc;
1323     DWORD width, oldcy = cy;
1324     INT32 result;
1325     int height, tmpheight;
1326
1327       /* Check parameters */
1328
1329     dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
1330     if (!dc) 
1331     {
1332         dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
1333         if (!dc) return 0;
1334     }
1335     if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, 
1336                            &descr.infoBpp, &descr.compression ) == -1)
1337         return 0;
1338     tmpheight = height;
1339     if (height < 0) height = -height;
1340     if (!lines || (startscan >= height)) return 0;
1341     if (startscan + lines > height) lines = height - startscan;
1342     if (ySrc < startscan) ySrc = startscan;
1343     else if (ySrc >= startscan + lines) return 0;
1344     if (xSrc >= width) return 0;
1345     if (ySrc + cy >= startscan + lines) cy = startscan + lines - ySrc;
1346     if (xSrc + cx >= width) cx = width - xSrc;
1347     if (!cx || !cy) return 0;
1348
1349     DC_SetupGCForText( dc );  /* To have the correct colors */
1350     TSXSetFunction( display, dc->u.x.gc, DC_XROPfunction[dc->w.ROPmode-1] );
1351
1352     if (descr.infoBpp <= 8)
1353     {
1354         descr.colorMap = DIB_BuildColorMap( dc, coloruse, dc->w.bitsPerPixel,
1355                                             info, &descr.nColorMap );
1356         if (!descr.colorMap)
1357             return 0;
1358     }
1359
1360     descr.dc        = dc;
1361     descr.bits      = bits;
1362     descr.image     = NULL;
1363     descr.lines     = tmpheight >= 0 ? lines : -lines;
1364     descr.infoWidth = width;
1365     descr.depth     = dc->w.bitsPerPixel;
1366     descr.drawable  = dc->u.x.drawable;
1367     descr.gc        = dc->u.x.gc;
1368     descr.xSrc      = xSrc;
1369     descr.ySrc      = tmpheight >= 0 ? lines-(ySrc-startscan)-cy+(oldcy-cy) : ySrc - startscan;
1370     descr.xDest     = dc->w.DCOrgX + XLPTODP( dc, xDest );
1371     descr.yDest     = dc->w.DCOrgY + YLPTODP( dc, yDest ) + (tmpheight >= 0 ? oldcy-cy : 0);
1372     descr.width     = cx;
1373     descr.height    = cy;
1374
1375     EnterCriticalSection( &X11DRV_CritSection );
1376     result = CALL_LARGE_STACK( DIB_SetImageBits, &descr );
1377     LeaveCriticalSection( &X11DRV_CritSection );
1378
1379     HeapFree(GetProcessHeap(), 0, descr.colorMap);
1380     return result;
1381 }
1382
1383 /***********************************************************************
1384  *           SetDIBColorTable16    (GDI.602)
1385  */
1386 UINT16 WINAPI SetDIBColorTable16( HDC16 hdc, UINT16 startpos, UINT16 entries,
1387                                   RGBQUAD *colors )
1388 {
1389     return SetDIBColorTable32( hdc, startpos, entries, colors );
1390 }
1391
1392 /***********************************************************************
1393  *           SetDIBColorTable32    (GDI32.311)
1394  */
1395 UINT32 WINAPI SetDIBColorTable32( HDC32 hdc, UINT32 startpos, UINT32 entries,
1396                                   RGBQUAD *colors )
1397 {
1398     DC * dc;
1399     PALETTEENTRY * palEntry;
1400     PALETTEOBJ * palette;
1401     RGBQUAD *end;
1402
1403     dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
1404     if (!dc) 
1405     {
1406         dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
1407         if (!dc) return 0;
1408     }
1409
1410     if (!(palette = (PALETTEOBJ*)GDI_GetObjPtr( dc->w.hPalette, PALETTE_MAGIC )))
1411     {
1412         return 0;
1413     }
1414
1415     /* Transfer color info */
1416     
1417     if (dc->w.bitsPerPixel <= 8) {
1418         palEntry = palette->logpalette.palPalEntry + startpos;
1419         if (startpos + entries > (1 << dc->w.bitsPerPixel)) {
1420             entries = (1 << dc->w.bitsPerPixel) - startpos;
1421         }
1422         for (end = colors + entries; colors < end; palEntry++, colors++)
1423         {
1424             palEntry->peRed   = colors->rgbRed;
1425             palEntry->peGreen = colors->rgbGreen;
1426             palEntry->peBlue  = colors->rgbBlue;
1427         }
1428     } else {
1429         entries = 0;
1430     }
1431     GDI_HEAP_UNLOCK( dc->w.hPalette );
1432     return entries;
1433 }
1434
1435 /***********************************************************************
1436  *           GetDIBColorTable16    (GDI.603)
1437  */
1438 UINT16 WINAPI GetDIBColorTable16( HDC16 hdc, UINT16 startpos, UINT16 entries,
1439                                   RGBQUAD *colors )
1440 {
1441     return GetDIBColorTable32( hdc, startpos, entries, colors );
1442 }
1443
1444 /***********************************************************************
1445  *           GetDIBColorTable32    (GDI32.169)
1446  */
1447 UINT32 WINAPI GetDIBColorTable32( HDC32 hdc, UINT32 startpos, UINT32 entries,
1448                                   RGBQUAD *colors )
1449 {
1450     DC * dc;
1451     PALETTEENTRY * palEntry;
1452     PALETTEOBJ * palette;
1453     RGBQUAD *end;
1454
1455     dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
1456     if (!dc) 
1457     {
1458         dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
1459         if (!dc) return 0;
1460     }
1461
1462     if (!(palette = (PALETTEOBJ*)GDI_GetObjPtr( dc->w.hPalette, PALETTE_MAGIC )))
1463     {
1464         return 0;
1465     }
1466
1467     /* Transfer color info */
1468     
1469     if (dc->w.bitsPerPixel <= 8) {
1470         palEntry = palette->logpalette.palPalEntry + startpos;
1471         if (startpos + entries > (1 << dc->w.bitsPerPixel)) {
1472             entries = (1 << dc->w.bitsPerPixel) - startpos;
1473         }
1474         for (end = colors + entries; colors < end; palEntry++, colors++)
1475         {
1476             colors->rgbRed      = palEntry->peRed;
1477             colors->rgbGreen    = palEntry->peGreen;
1478             colors->rgbBlue     = palEntry->peBlue;
1479             colors->rgbReserved = 0;
1480         }
1481     } else {
1482         entries = 0;
1483     }
1484     GDI_HEAP_UNLOCK( dc->w.hPalette );
1485     return entries;
1486 }
1487
1488 /***********************************************************************
1489  *           GetDIBits16    (GDI.441)
1490  */
1491 INT16 WINAPI GetDIBits16( HDC16 hdc, HBITMAP16 hbitmap, UINT16 startscan,
1492                           UINT16 lines, LPSTR bits, BITMAPINFO * info,
1493                           UINT16 coloruse )
1494 {
1495     return GetDIBits32( hdc, hbitmap, startscan, lines, bits, info, coloruse );
1496 }
1497
1498
1499 /******************************************************************************
1500  * GetDIBits32 [GDI32.170]  Retrieves bits of bitmap and copies to buffer
1501  *
1502  * RETURNS
1503  *    Success: Number of scan lines copied from bitmap
1504  *    Failure: 0
1505  *
1506  * http://www.microsoft.com/msdn/sdk/platforms/doc/sdk/win32/func/src/f30_14.htm
1507  */
1508 INT32 WINAPI GetDIBits32(
1509     HDC32 hdc,         /* [in]  Handle to device context */
1510     HBITMAP32 hbitmap, /* [in]  Handle to bitmap */
1511     UINT32 startscan,  /* [in]  First scan line to set in dest bitmap */
1512     UINT32 lines,      /* [in]  Number of scan lines to copy */
1513     LPSTR bits,        /* [out] Address of array for bitmap bits */
1514     BITMAPINFO * info, /* [out] Address of structure with bitmap data */
1515     UINT32 coloruse)   /* [in]  RGB or palette index */
1516 {
1517     DC * dc;
1518     BITMAPOBJ * bmp;
1519     PALETTEENTRY * palEntry;
1520     PALETTEOBJ * palette;
1521     XImage * bmpImage;
1522     int i, x, y;
1523
1524     if (!lines) return 0;
1525     dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
1526     if (!dc) 
1527     {
1528         dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
1529         if (!dc) return 0;
1530     }
1531     if (!(bmp = (BITMAPOBJ *)GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
1532         return 0;
1533     if (!(palette = (PALETTEOBJ*)GDI_GetObjPtr( dc->w.hPalette, PALETTE_MAGIC )))
1534     {
1535         GDI_HEAP_UNLOCK( hbitmap );
1536         return 0;
1537     }
1538
1539       /* Transfer color info */
1540     
1541     if (info->bmiHeader.biBitCount<=8) {
1542         palEntry = palette->logpalette.palPalEntry;
1543         for (i = 0; i < info->bmiHeader.biClrUsed; i++, palEntry++)
1544         {
1545             if (coloruse == DIB_RGB_COLORS)
1546             {
1547                 info->bmiColors[i].rgbRed      = palEntry->peRed;
1548                 info->bmiColors[i].rgbGreen    = palEntry->peGreen;
1549                 info->bmiColors[i].rgbBlue     = palEntry->peBlue;
1550                 info->bmiColors[i].rgbReserved = 0;
1551             }
1552             else ((WORD *)info->bmiColors)[i] = (WORD)i;
1553         }
1554     }
1555
1556     if (bits)
1557     {   
1558         BYTE*   bbits = bits;
1559         int     pad, yend, xend = bmp->bitmap.bmWidth;
1560
1561         TRACE(bitmap, "%u scanlines of (%i,%i) -> (%i,%i) starting from %u\n",
1562                             lines, bmp->bitmap.bmWidth, bmp->bitmap.bmHeight,
1563                             (int)info->bmiHeader.biWidth, (int)info->bmiHeader.biHeight, startscan );
1564
1565         /* adjust number of scanlines to copy */
1566
1567         if( lines > info->bmiHeader.biHeight ) lines = info->bmiHeader.biHeight;
1568         yend = startscan + lines;
1569         if( startscan >= bmp->bitmap.bmHeight ) 
1570         {
1571             GDI_HEAP_UNLOCK( hbitmap );
1572             GDI_HEAP_UNLOCK( dc->w.hPalette );
1573             return FALSE;
1574         }
1575         if( yend > bmp->bitmap.bmHeight ) yend = bmp->bitmap.bmHeight;
1576
1577         /* adjust scanline width */
1578
1579         pad = info->bmiHeader.biWidth - bmp->bitmap.bmWidth;
1580         if( pad < 0 ) 
1581         {
1582             /* bitmap is wider than DIB, copy only a part */
1583
1584             pad = 0;
1585             xend = info->bmiHeader.biWidth;
1586         }
1587
1588         EnterCriticalSection( &X11DRV_CritSection );
1589         bmpImage = (XImage *)CALL_LARGE_STACK( BITMAP_GetXImage, bmp );
1590
1591         switch( info->bmiHeader.biBitCount )
1592         {
1593            case 8:
1594                 /* pad up to 32 bit */
1595                 pad += (4 - (info->bmiHeader.biWidth & 3)) & 3;
1596                 for( y = yend - 1; (int)y >= (int)startscan; y-- )
1597                 {
1598                    for( x = 0; x < xend; x++ )
1599                         *bbits++ = XGetPixel( bmpImage, x, y );
1600                    bbits += pad;
1601                 }
1602                 break;
1603            case 1:
1604                 pad += ((32 - (info->bmiHeader.biWidth & 31)) / 8) & 3;
1605                 for( y = yend - 1; (int)y >= (int)startscan; y-- )
1606                 {
1607                    for( x = 0; x < xend; x++ ) {
1608                         if (!(x&7)) *bbits = 0;
1609                         *bbits |= XGetPixel( bmpImage, x, y)<<(7-(x&7));
1610                         if ((x&7)==7) bbits++;
1611                    }
1612                    bbits += pad;
1613                 }
1614                 break;
1615            case 4:
1616                 pad += ((8 - (info->bmiHeader.biWidth & 7)) / 2) & 3;
1617                 for( y = yend - 1; (int)y >= (int)startscan; y-- )
1618                 {
1619                    for( x = 0; x < xend; x++ ) {
1620                         if (!(x&1)) *bbits = 0;
1621                         *bbits |= XGetPixel( bmpImage, x, y)<<(4*(1-(x&1)));
1622                         if ((x&1)==1) bbits++;
1623                    }
1624                    bbits += pad;
1625                 }
1626                 break;
1627            case 15:
1628            case 16:
1629                 pad += (4 - ((info->bmiHeader.biWidth*2) & 3)) & 3;
1630                 for( y = yend - 1; (int)y >= (int)startscan; y-- )
1631                 {
1632                    for( x = 0; x < xend; x++ ) {
1633                         unsigned long pixel=XGetPixel( bmpImage, x, y);
1634                         *bbits++ = pixel & 0xff;
1635                         *bbits++ = (pixel >> 8) & 0xff;
1636                    }
1637                    bbits += pad;
1638                 }
1639                 break;
1640            case 24:
1641                 pad += (4 - ((info->bmiHeader.biWidth*3) & 3)) & 3;
1642                 for( y = yend - 1; (int)y >= (int)startscan; y-- )
1643                 {
1644                    for( x = 0; x < xend; x++ ) {
1645                         unsigned long pixel=XGetPixel( bmpImage, x, y);
1646                         *bbits++ = (pixel >>16) & 0xff;
1647                         *bbits++ = (pixel >> 8) & 0xff;
1648                         *bbits++ =  pixel       & 0xff;
1649                    }
1650                    bbits += pad;
1651                 }
1652                 break;
1653            case 32:
1654                 for( y = yend - 1; (int)y >= (int)startscan; y-- )
1655                 {
1656                    for( x = 0; x < xend; x++ ) {
1657                         unsigned long pixel=XGetPixel( bmpImage, x, y);
1658                         *bbits++ = (pixel >>16) & 0xff;
1659                         *bbits++ = (pixel >> 8) & 0xff;
1660                         *bbits++ =  pixel       & 0xff;
1661                    }
1662                 }
1663                 break;
1664            default:
1665                 WARN(bitmap,"Unsupported depth %d\n",
1666                    info->bmiHeader.biBitCount);
1667                 break;
1668         }
1669
1670         XDestroyImage( bmpImage );
1671         LeaveCriticalSection( &X11DRV_CritSection );
1672
1673         info->bmiHeader.biCompression = 0;
1674     }
1675     else if( info->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER) ) 
1676     {
1677         /* fill in struct members */
1678         
1679         info->bmiHeader.biWidth = bmp->bitmap.bmWidth;
1680         info->bmiHeader.biHeight = bmp->bitmap.bmHeight;
1681         info->bmiHeader.biPlanes = 1;
1682         info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel;
1683         info->bmiHeader.biSizeImage = bmp->bitmap.bmHeight *
1684                              DIB_GetDIBWidthBytes( bmp->bitmap.bmWidth,
1685                                                    bmp->bitmap.bmBitsPixel );
1686         info->bmiHeader.biCompression = 0;
1687     }
1688
1689     GDI_HEAP_UNLOCK( hbitmap );
1690     GDI_HEAP_UNLOCK( dc->w.hPalette );
1691     return lines;
1692 }
1693
1694
1695 /***********************************************************************
1696  *           CreateDIBitmap16    (GDI.442)
1697  */
1698 HBITMAP16 WINAPI CreateDIBitmap16( HDC16 hdc, const BITMAPINFOHEADER * header,
1699                             DWORD init, LPCVOID bits, const BITMAPINFO * data,
1700                             UINT16 coloruse )
1701 {
1702     return CreateDIBitmap32( hdc, header, init, bits, data, coloruse );
1703 }
1704
1705
1706 /***********************************************************************
1707  *           CreateDIBitmap32    (GDI32.37)
1708  */
1709 HBITMAP32 WINAPI CreateDIBitmap32( HDC32 hdc, const BITMAPINFOHEADER *header,
1710                             DWORD init, LPCVOID bits, const BITMAPINFO *data,
1711                             UINT32 coloruse )
1712 {
1713     HBITMAP32 handle;
1714     BOOL32 fColor;
1715     DWORD width;
1716     int height;
1717     WORD bpp;
1718     WORD compr;
1719
1720     if (DIB_GetBitmapInfo( header, &width, &height, &bpp, &compr ) == -1) return 0;
1721     if (height < 0) height = -height;
1722
1723     /* Check if we should create a monochrome or color bitmap. */
1724     /* We create a monochrome bitmap only if it has exactly 2  */
1725     /* colors, which are either black or white, nothing else.  */
1726     /* In all other cases, we create a color bitmap.           */
1727
1728     if (bpp != 1) fColor = TRUE;
1729     else if ((coloruse != DIB_RGB_COLORS) ||
1730              (init != CBM_INIT) || !data) fColor = FALSE;
1731     else
1732     {
1733         if (data->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
1734         {
1735             RGBQUAD *rgb = data->bmiColors;
1736             DWORD col = RGB( rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue );
1737             if ((col == RGB(0,0,0)) || (col == RGB(0xff,0xff,0xff)))
1738             {
1739                 rgb++;
1740                 col = RGB( rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue );
1741                 fColor = ((col != RGB(0,0,0)) && (col != RGB(0xff,0xff,0xff)));
1742             }
1743             else fColor = TRUE;
1744         }
1745         else if (data->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
1746         {
1747             RGBTRIPLE *rgb = ((BITMAPCOREINFO *)data)->bmciColors;
1748             DWORD col = RGB( rgb->rgbtRed, rgb->rgbtGreen, rgb->rgbtBlue );
1749             if ((col == RGB(0,0,0)) || (col == RGB(0xff,0xff,0xff)))
1750             {
1751                 rgb++;
1752                 col = RGB( rgb->rgbtRed, rgb->rgbtGreen, rgb->rgbtBlue );
1753                 fColor = ((col != RGB(0,0,0)) && (col != RGB(0xff,0xff,0xff)));
1754             }
1755             else fColor = TRUE;
1756         }
1757         else
1758         {
1759             WARN(bitmap, "(%ld): wrong size for data\n",
1760                      data->bmiHeader.biSize );
1761             return 0;
1762         }
1763     }
1764
1765     /* Now create the bitmap */
1766
1767     handle = fColor ? CreateBitmap32( width, height, 1, screenDepth, NULL ) :
1768                       CreateBitmap32( width, height, 1, 1, NULL );
1769     if (!handle) return 0;
1770
1771     if (init == CBM_INIT)
1772         SetDIBits32( hdc, handle, 0, height, bits, data, coloruse );
1773     return handle;
1774 }
1775
1776
1777 /***********************************************************************
1778  *           DIB_DoProtectDIBSection
1779  */
1780 static void DIB_DoProtectDIBSection( BITMAPOBJ *bmp, DWORD new_prot )
1781 {
1782     DIBSECTION *dib = &bmp->dib->dibSection;
1783     INT32 effHeight = dib->dsBm.bmHeight >= 0? dib->dsBm.bmHeight
1784                                              : -dib->dsBm.bmHeight;
1785     INT32 totalSize = dib->dsBmih.biSizeImage? dib->dsBmih.biSizeImage
1786                          : dib->dsBm.bmWidthBytes * effHeight;
1787     DWORD old_prot;
1788
1789     VirtualProtect(dib->dsBm.bmBits, totalSize, new_prot, &old_prot);
1790     TRACE(bitmap, "Changed protection from %ld to %ld\n", 
1791                   old_prot, new_prot);
1792 }
1793
1794 /***********************************************************************
1795  *           DIB_DoUpdateDIBSection
1796  */
1797 static void DIB_DoUpdateDIBSection( BITMAPOBJ *bmp, BOOL32 toDIB )
1798 {
1799     DIBSECTIONOBJ *dib = bmp->dib;
1800     DIB_SETIMAGEBITS_DESCR descr;
1801
1802     if (DIB_GetBitmapInfo( &dib->dibSection.dsBmih, &descr.infoWidth, &descr.lines,
1803                            &descr.infoBpp, &descr.compression ) == -1)
1804         return;
1805
1806     descr.dc        = NULL;
1807     descr.image     = dib->image;
1808     descr.colorMap  = dib->colorMap;
1809     descr.nColorMap = dib->nColorMap;
1810     descr.bits      = dib->dibSection.dsBm.bmBits;
1811     descr.depth     = bmp->bitmap.bmBitsPixel;
1812     descr.drawable  = bmp->pixmap;
1813     descr.gc        = BITMAP_GC(bmp);
1814     descr.xSrc      = 0;
1815     descr.ySrc      = 0;
1816     descr.xDest     = 0;
1817     descr.yDest     = 0;
1818     descr.width     = bmp->bitmap.bmWidth;
1819     descr.height    = bmp->bitmap.bmHeight;
1820
1821     if (toDIB)
1822     {
1823         TRACE(bitmap, "Copying from Pixmap to DIB bits\n");
1824         EnterCriticalSection( &X11DRV_CritSection );
1825         CALL_LARGE_STACK( DIB_GetImageBits, &descr );
1826         LeaveCriticalSection( &X11DRV_CritSection );
1827     }
1828     else
1829     {
1830         TRACE(bitmap, "Copying from DIB bits to Pixmap\n"); 
1831         EnterCriticalSection( &X11DRV_CritSection );
1832         CALL_LARGE_STACK( DIB_SetImageBits, &descr );
1833         LeaveCriticalSection( &X11DRV_CritSection );
1834     }
1835 }
1836
1837 /***********************************************************************
1838  *           DIB_FaultHandler
1839  */
1840 static BOOL32 DIB_FaultHandler( LPVOID res, LPVOID addr )
1841 {
1842     BOOL32 handled = FALSE;
1843     BITMAPOBJ *bmp;
1844
1845     bmp = (BITMAPOBJ *)GDI_GetObjPtr( (HBITMAP32)res, BITMAP_MAGIC );
1846     if (!bmp) return FALSE;
1847
1848     if (bmp->dib)
1849         switch (bmp->dib->status)
1850         {
1851         case DIB_GdiMod:
1852             TRACE( bitmap, "called in status DIB_GdiMod\n" );
1853             DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
1854             DIB_DoUpdateDIBSection( bmp, TRUE );
1855             DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
1856             bmp->dib->status = DIB_InSync;
1857             handled = TRUE;
1858             break;
1859
1860         case DIB_InSync:
1861             TRACE( bitmap, "called in status DIB_InSync\n" );
1862             DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
1863             bmp->dib->status = DIB_AppMod;
1864             handled = TRUE;
1865             break;
1866
1867         case DIB_AppMod:
1868             FIXME( bitmap, "called in status DIB_AppMod: "
1869                            "this can't happen!\n" );
1870             break;
1871
1872         case DIB_NoHandler:
1873             FIXME( bitmap, "called in status DIB_NoHandler: "
1874                            "this can't happen!\n" );
1875             break;
1876         }
1877
1878     GDI_HEAP_UNLOCK( (HBITMAP32)res );
1879     return handled;
1880 }
1881
1882 /***********************************************************************
1883  *           DIB_UpdateDIBSection
1884  */
1885 void DIB_UpdateDIBSection( DC *dc, BOOL32 toDIB )
1886 {
1887     BITMAPOBJ *bmp;
1888
1889     /* Ensure this is a Compatible DC that has a DIB section selected */
1890
1891     if (!dc) return;
1892     if (!(dc->w.flags & DC_MEMORY)) return;
1893
1894     bmp = (BITMAPOBJ *)GDI_GetObjPtr( dc->w.hBitmap, BITMAP_MAGIC );
1895     if (!bmp) return;
1896
1897     if (!bmp->dib)
1898     {
1899         GDI_HEAP_UNLOCK(dc->w.hBitmap);
1900         return;
1901     }
1902
1903
1904     if (!toDIB)
1905     {
1906         /* Prepare for access to the DIB by GDI functions */
1907
1908         switch (bmp->dib->status)
1909         {
1910         default:
1911         case DIB_NoHandler:
1912             DIB_DoUpdateDIBSection( bmp, FALSE );
1913             break;
1914
1915         case DIB_GdiMod:
1916             TRACE( bitmap, "fromDIB called in status DIB_GdiMod\n" );
1917             /* nothing to do */
1918             break;
1919
1920         case DIB_InSync:
1921             TRACE( bitmap, "fromDIB called in status DIB_InSync\n" );
1922             /* nothing to do */
1923             break;
1924
1925         case DIB_AppMod:
1926             TRACE( bitmap, "fromDIB called in status DIB_AppMod\n" );
1927             DIB_DoUpdateDIBSection( bmp, FALSE );
1928             DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
1929             bmp->dib->status = DIB_InSync;
1930             break;
1931         }
1932     }
1933     else
1934     {
1935         /* Acknowledge write access to the DIB by GDI functions */
1936
1937         switch (bmp->dib->status)
1938         {
1939         default:
1940         case DIB_NoHandler:
1941             DIB_DoUpdateDIBSection( bmp, TRUE );
1942             break;
1943
1944         case DIB_GdiMod:
1945             TRACE( bitmap, "  toDIB called in status DIB_GdiMod\n" );
1946             /* nothing to do */
1947             break;
1948
1949         case DIB_InSync:
1950             TRACE( bitmap, "  toDIB called in status DIB_InSync\n" );
1951             DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS );
1952             bmp->dib->status = DIB_GdiMod;
1953             break;
1954
1955         case DIB_AppMod:
1956             FIXME( bitmap, "  toDIB called in status DIB_AppMod: "
1957                            "this can't happen!\n" );
1958             break;
1959         }
1960     }
1961
1962   
1963     GDI_HEAP_UNLOCK(dc->w.hBitmap);
1964 }
1965
1966 /***********************************************************************
1967  *           CreateDIBSection16    (GDI.489)
1968  */
1969 HBITMAP16 WINAPI CreateDIBSection16 (HDC16 hdc, BITMAPINFO *bmi, UINT16 usage,
1970                                      LPVOID **bits, HANDLE32 section,
1971                                      DWORD offset)
1972 {
1973     return CreateDIBSection32(hdc, bmi, usage, bits, section, offset);
1974 }
1975
1976 /***********************************************************************
1977  *           CreateDIBSection32    (GDI32.36)
1978  */
1979 HBITMAP32 WINAPI CreateDIBSection32 (HDC32 hdc, BITMAPINFO *bmi, UINT32 usage,
1980                                      LPVOID **bits,HANDLE32 section,
1981                                      DWORD offset)
1982 {
1983     HBITMAP32 res = 0;
1984     BITMAPOBJ *bmp = NULL;
1985     DIBSECTIONOBJ *dib = NULL;
1986     int *colorMap = NULL;
1987     int nColorMap;
1988
1989     /* Fill BITMAP32 structure with DIB data */
1990     BITMAPINFOHEADER *bi = &bmi->bmiHeader;
1991     INT32 effHeight, totalSize;
1992     BITMAP32 bm;
1993
1994     TRACE(bitmap, "format (%ld,%ld), planes %d, bpp %d, size %ld, colors %ld (%s)\n",
1995           bi->biWidth, bi->biHeight, bi->biPlanes, bi->biBitCount,
1996           bi->biSizeImage, bi->biClrUsed, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1997
1998     bm.bmType = 0;
1999     bm.bmWidth = bi->biWidth;
2000     bm.bmHeight = bi->biHeight;
2001     bm.bmWidthBytes = DIB_GetDIBWidthBytes(bm.bmWidth, bi->biBitCount);
2002     bm.bmPlanes = bi->biPlanes;
2003     bm.bmBitsPixel = bi->biBitCount;
2004     bm.bmBits = NULL;
2005
2006     /* Get storage location for DIB bits */
2007     effHeight = bm.bmHeight >= 0 ? bm.bmHeight : -bm.bmHeight;
2008     totalSize = bi->biSizeImage? bi->biSizeImage : bm.bmWidthBytes * effHeight;
2009
2010     if (section)
2011         bm.bmBits = MapViewOfFile(section, FILE_MAP_ALL_ACCESS, 
2012                                   0L, offset, totalSize);
2013     else
2014         bm.bmBits = VirtualAlloc(NULL, totalSize, 
2015                                  MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
2016
2017     /* Create Color Map */
2018     if (bm.bmBits && bm.bmBitsPixel <= 8)
2019     {
2020         DC *dc = hdc? (DC *)GDI_GetObjPtr(hdc, DC_MAGIC) : NULL;
2021         if (hdc && !dc) dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
2022
2023         if (!hdc || dc)
2024             colorMap = DIB_BuildColorMap( dc, usage, bm.bmBitsPixel,
2025                                           bmi, &nColorMap );
2026         GDI_HEAP_UNLOCK(hdc);
2027     }
2028
2029     /* Allocate Memory for DIB and fill structure */
2030     if (bm.bmBits)
2031         dib = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DIBSECTIONOBJ));
2032     if (dib)
2033     {
2034         dib->dibSection.dsBm = bm;
2035         dib->dibSection.dsBmih = *bi;
2036         /* FIXME: dib->dibSection.dsBitfields ??? */
2037         dib->dibSection.dshSection = section;
2038         dib->dibSection.dsOffset = offset;
2039
2040         dib->status    = DIB_NoHandler;
2041         
2042         dib->nColorMap = nColorMap;
2043         dib->colorMap  = colorMap;
2044     }
2045
2046     /* Create Device Dependent Bitmap and add DIB pointer */
2047     if (dib) 
2048     {
2049        res = CreateDIBitmap32(hdc, bi, 0, NULL, bmi, usage);
2050        bmp = (BITMAPOBJ *) GDI_GetObjPtr(res, BITMAP_MAGIC);
2051        if (bmp) bmp->dib = dib;
2052     }
2053
2054     /* Create XImage */
2055     if (dib && bmp)
2056         XCREATEIMAGE( dib->image, bm.bmWidth, effHeight, bmp->bitmap.bmBitsPixel );
2057
2058     /* Clean up in case of errors */
2059     if (!res || !bmp || !dib || !bm.bmBits || (bm.bmBitsPixel <= 8 && !colorMap))
2060     {
2061         if (bm.bmBits)
2062             if (section)
2063                 UnmapViewOfFile(bm.bmBits), bm.bmBits = NULL;
2064             else
2065                 VirtualFree(bm.bmBits, MEM_RELEASE, 0L), bm.bmBits = NULL;
2066
2067         if (dib->image) XDestroyImage(dib->image), dib->image = NULL;
2068         if (colorMap) HeapFree(GetProcessHeap(), 0, colorMap), colorMap = NULL;
2069         if (dib) HeapFree(GetProcessHeap(), 0, dib), dib = NULL;
2070         if (res) DeleteObject32(res), res = 0;
2071     }
2072
2073     /* Install fault handler, if possible */
2074     if (bm.bmBits)
2075         if (VIRTUAL_SetFaultHandler(bm.bmBits, DIB_FaultHandler, (LPVOID)res))
2076         {
2077             DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
2078             dib->status = DIB_InSync;
2079         }
2080
2081     /* Return BITMAP handle and storage location */
2082     if (res) GDI_HEAP_UNLOCK(res);
2083     if (bm.bmBits && bits) *bits = bm.bmBits;
2084     return res;
2085 }
2086
2087 /***********************************************************************
2088  *           DIB_DeleteDIBSection
2089  */
2090 void DIB_DeleteDIBSection( BITMAPOBJ *bmp )
2091 {
2092     if (bmp && bmp->dib)
2093     {
2094         DIBSECTIONOBJ *dib = bmp->dib;
2095
2096         if (dib->dibSection.dsBm.bmBits)
2097             if (dib->dibSection.dshSection)
2098                 UnmapViewOfFile(dib->dibSection.dsBm.bmBits);
2099             else
2100                 VirtualFree(dib->dibSection.dsBm.bmBits, MEM_RELEASE, 0L);
2101
2102         if (dib->image) 
2103             XDestroyImage( dib->image );
2104
2105         if (dib->colorMap)
2106             HeapFree(GetProcessHeap(), 0, dib->colorMap);
2107
2108         HeapFree(GetProcessHeap(), 0, dib);
2109         bmp->dib = NULL;
2110     }
2111 }
2112