Release 980315
[wine] / objects / bitmap.c
1 /*
2  * GDI bitmap objects
3  *
4  * Copyright 1993 Alexandre Julliard
5  */
6
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include "ts_xlib.h"
11 #include "ts_xutil.h"
12 #include "gdi.h"
13 #include "callback.h"
14 #include "dc.h"
15 #include "bitmap.h"
16 #include "heap.h"
17 #include "debug.h"
18
19 #ifdef PRELIMINARY_WING16_SUPPORT
20 #include <sys/types.h>
21 #include <sys/ipc.h>
22 #include <sys/shm.h>
23 #endif
24
25   /* GCs used for B&W and color bitmap operations */
26 GC BITMAP_monoGC = 0, BITMAP_colorGC = 0;
27
28 /***********************************************************************
29  *           XPutImage_wrapper
30  *
31  * Wrapper to call XPutImage with CALL_LARGE_STACK.
32  */
33
34 struct XPutImage_descr
35 {
36     BITMAPOBJ *bmp;
37     XImage    *image;
38     INT32      width;
39     INT32      height;
40 };
41
42 static int XPutImage_wrapper( const struct XPutImage_descr *descr )
43 {
44     return XPutImage( display, descr->bmp->pixmap, BITMAP_GC(descr->bmp),
45                       descr->image, 0, 0, 0, 0, descr->width, descr->height );
46 }
47
48 /***********************************************************************
49  *           BITMAP_GetBitsPadding
50  *
51  * Return number of bytes to pad a scanline of 16-bit aligned Windows DDB data.
52  */
53 INT32 BITMAP_GetBitsPadding( int bmWidth, int bpp )
54 {
55     INT32 pad;
56
57     switch (bpp) 
58     {
59     case 1:
60         if (!(bmWidth & 15)) pad = 0;
61         else pad = ((16 - (bmWidth & 15)) + 7) / 8;
62         break;
63
64     case 8:
65         pad = (2 - (bmWidth & 1)) & 1;
66         break;
67
68     case 24:
69         pad = (bmWidth*3) & 1;
70         break;
71
72     case 32:
73     case 16:
74     case 15:
75         pad = 0; /* we have 16bit alignment already */
76         break;
77
78     case 4:
79         if (!(bmWidth & 3)) pad = 0;
80         else pad = ((4 - (bmWidth & 3)) + 1) / 2;
81         break;
82
83     default:
84         fprintf(stderr,"GetBitsPadding: unknown depth %d, please report.\n", bpp );
85         return -1;
86     }
87     return pad;
88 }
89
90 /***********************************************************************
91  *           BITMAP_GetBitsWidth
92  *
93  * Return number of bytes taken by a scanline of 16-bit aligned Windows DDB data.
94  */
95 INT32 BITMAP_GetBitsWidth( int bmWidth, int bpp )
96 {
97     switch(bpp)
98     {
99     case 1:
100         return 2 * ((bmWidth+15) >> 4);
101
102     case 24:
103         bmWidth *= 3; /* fall through */
104     case 8:
105         return bmWidth + (bmWidth & 1);
106
107     case 32:
108         return bmWidth * 4;
109
110     case 16:
111     case 15:
112         return bmWidth * 2;
113
114     case 4:
115         return 2 * ((bmWidth+3) >> 2);
116
117     default:
118         fprintf(stderr,"GetBitsPadding: unknown depth %d, please report.\n", bpp );
119     }
120     return -1;
121 }
122
123 /***********************************************************************
124  *           CreateBitmap16    (GDI.48)
125  */
126 HBITMAP16 WINAPI CreateBitmap16( INT16 width, INT16 height, UINT16 planes,
127                                  UINT16 bpp, LPCVOID bits )
128 {
129     return CreateBitmap32( width, height, planes, bpp, bits );
130 }
131
132
133 /***********************************************************************
134  *           CreateBitmap32    (GDI32.25)
135  */
136 HBITMAP32 WINAPI CreateBitmap32( INT32 width, INT32 height, UINT32 planes,
137                                  UINT32 bpp, LPCVOID bits )
138 {
139     BITMAPOBJ * bmpObjPtr;
140     HBITMAP32 hbitmap;
141
142     planes = (BYTE)planes;
143     bpp    = (BYTE)bpp;
144
145     TRACE(gdi, "%dx%d, %d colors\n", 
146                  width, height, 1 << (planes*bpp) );
147
148       /* Check parameters */
149     if (!height || !width || planes != 1) return 0;
150     if ((bpp != 1) && (bpp != screenDepth)) return 0;
151     if (height < 0) height = -height;
152     if (width < 0) width = -width;
153
154       /* Create the BITMAPOBJ */
155     hbitmap = GDI_AllocObject( sizeof(BITMAPOBJ), BITMAP_MAGIC );
156     if (!hbitmap) return 0;
157     bmpObjPtr = (BITMAPOBJ *) GDI_HEAP_LOCK( hbitmap );
158
159     bmpObjPtr->size.cx = 0;
160     bmpObjPtr->size.cy = 0;
161     bmpObjPtr->bitmap.bmType = 0;
162     bmpObjPtr->bitmap.bmWidth = (INT16)width;
163     bmpObjPtr->bitmap.bmHeight = (INT16)height;
164     bmpObjPtr->bitmap.bmPlanes = (BYTE)planes;
165     bmpObjPtr->bitmap.bmBitsPixel = (BYTE)bpp;
166     bmpObjPtr->bitmap.bmWidthBytes = (INT16)BITMAP_WIDTH_BYTES( width, bpp );
167     bmpObjPtr->bitmap.bmBits = NULL;
168
169       /* Create the pixmap */
170     bmpObjPtr->pixmap = TSXCreatePixmap(display, rootWindow, width, height, bpp);
171     if (!bmpObjPtr->pixmap)
172     {
173         GDI_HEAP_FREE( hbitmap );
174         hbitmap = 0;
175     }
176     else if (bits)  /* Set bitmap bits */
177         SetBitmapBits32( hbitmap, height * bmpObjPtr->bitmap.bmWidthBytes,
178                          bits );
179     GDI_HEAP_UNLOCK( hbitmap );
180     return hbitmap;
181 }
182
183
184 /***********************************************************************
185  *           CreateCompatibleBitmap16    (GDI.51)
186  */
187 HBITMAP16 WINAPI CreateCompatibleBitmap16(HDC16 hdc, INT16 width, INT16 height)
188 {
189     return CreateCompatibleBitmap32( hdc, width, height );
190 }
191
192
193 /***********************************************************************
194  *           CreateCompatibleBitmap32    (GDI32.30)
195  */
196 HBITMAP32 WINAPI CreateCompatibleBitmap32(HDC32 hdc, INT32 width, INT32 height)
197 {
198     HBITMAP32 hbmpRet = 0;
199     DC *dc;
200
201     TRACE(gdi, "(%04x,%d,%d) = \n", 
202                  hdc, width, height );
203     if (!(dc = DC_GetDCPtr( hdc ))) return 0;
204     hbmpRet = CreateBitmap32( width, height, 1, dc->w.bitsPerPixel, NULL );
205     TRACE(gdi,"\t\t%04x\n", hbmpRet);
206     return hbmpRet;
207 }
208
209
210 /***********************************************************************
211  *           CreateBitmapIndirect16    (GDI.49)
212  */
213 HBITMAP16 WINAPI CreateBitmapIndirect16( const BITMAP16 * bmp )
214 {
215     return CreateBitmap16( bmp->bmWidth, bmp->bmHeight, bmp->bmPlanes,
216                            bmp->bmBitsPixel, PTR_SEG_TO_LIN( bmp->bmBits ) );
217 }
218
219
220 /***********************************************************************
221  *           CreateBitmapIndirect32    (GDI32.26)
222  */
223 HBITMAP32 WINAPI CreateBitmapIndirect32( const BITMAP32 * bmp )
224 {
225     return CreateBitmap32( bmp->bmWidth, bmp->bmHeight, bmp->bmPlanes,
226                            bmp->bmBitsPixel, bmp->bmBits );
227 }
228
229
230 /***********************************************************************
231  *           BITMAP_GetXImage
232  *
233  * Get an X image for a bitmap. For use with CALL_LARGE_STACK.
234  */
235 XImage *BITMAP_GetXImage( const BITMAPOBJ *bmp )
236 {
237     return XGetImage( display, bmp->pixmap, 0, 0, bmp->bitmap.bmWidth,
238                       bmp->bitmap.bmHeight, AllPlanes, ZPixmap );
239 }
240
241
242 /***********************************************************************
243  *           GetBitmapBits16    (GDI.74)
244  */
245 LONG WINAPI GetBitmapBits16( HBITMAP16 hbitmap, LONG count, LPVOID buffer )
246 {
247     return GetBitmapBits32( hbitmap, count, buffer );
248 }
249
250
251 /***********************************************************************
252  *           GetBitmapBits32    (GDI32.143)
253  */
254 LONG WINAPI GetBitmapBits32( HBITMAP32 hbitmap, LONG count, LPVOID buffer )
255 {
256     BITMAPOBJ * bmp;
257     LONG height, old_height;
258     XImage * image;
259     LPBYTE tbuf;
260     int h,w,pad;
261     
262     /* KLUDGE! */
263     if (count < 0) {
264         fprintf(stderr, "Negative number of bytes (%ld) passed to GetBitmapBits???\n", count );
265         count = -count;
266     }
267     bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC );
268     if (!bmp) return 0;
269
270       /* Only get entire lines */
271     height = count / bmp->bitmap.bmWidthBytes;
272     if (height > bmp->bitmap.bmHeight) height = bmp->bitmap.bmHeight;
273
274     TRACE(bitmap, "%dx%d %d colors %p fetched height: %ld\n",
275             bmp->bitmap.bmWidth, bmp->bitmap.bmHeight,
276             1 << bmp->bitmap.bmBitsPixel, buffer, height );
277
278     pad = BITMAP_GetBitsPadding( bmp->bitmap.bmWidth, bmp->bitmap.bmBitsPixel );
279
280     if (!height || (pad == -1))
281     {
282       GDI_HEAP_UNLOCK( hbitmap );
283       return 0;
284     }
285
286     EnterCriticalSection( &X11DRV_CritSection );
287
288     /* Hack: change the bitmap height temporarily to avoid */
289     /*       getting unnecessary bitmap rows. */
290     old_height = bmp->bitmap.bmHeight;
291     bmp->bitmap.bmHeight = height;
292     image = (XImage *)CALL_LARGE_STACK( BITMAP_GetXImage, bmp );
293     bmp->bitmap.bmHeight = old_height;
294
295     /* copy XImage to 16 bit padded image buffer with real bitsperpixel */
296
297     tbuf = buffer;
298     switch (bmp->bitmap.bmBitsPixel)
299     {
300     case 1:
301         for (h=0;h<height;h++)
302         {
303             *tbuf = 0;
304             for (w=0;w<bmp->bitmap.bmWidth;w++)
305             {
306                 if ((w%8) == 0)
307                     *tbuf = 0;
308                 *tbuf |= XGetPixel(image,w,h)<<(7-(w&7));
309                 if ((w&7) == 7) ++tbuf;
310             }
311             tbuf += pad;
312         }
313         break;
314     case 4:
315         for (h=0;h<height;h++)
316         {
317             for (w=0;w<bmp->bitmap.bmWidth;w++)
318             {
319                 if (!(w & 1)) *tbuf = XGetPixel( image, w, h) << 4;
320                 else *tbuf++ |= XGetPixel( image, w, h) & 0x0f;
321             }
322             tbuf += pad;
323         }
324         break;
325     case 8:
326         for (h=0;h<height;h++)
327         {
328             for (w=0;w<bmp->bitmap.bmWidth;w++)
329                 *tbuf++ = XGetPixel(image,w,h);
330             tbuf += pad;
331         }
332         break;
333     case 15:
334     case 16:
335         for (h=0;h<height;h++)
336         {
337             for (w=0;w<bmp->bitmap.bmWidth;w++)
338             {
339                 long pixel = XGetPixel(image,w,h);
340
341                 *tbuf++ = pixel & 0xff;
342                 *tbuf++ = (pixel>>8) & 0xff;
343             }
344         }
345         break;
346     case 24:
347         for (h=0;h<height;h++)
348         {
349             for (w=0;w<bmp->bitmap.bmWidth;w++)
350             {
351                 long pixel = XGetPixel(image,w,h);
352
353                 *tbuf++ = pixel & 0xff;
354                 *tbuf++ = (pixel>> 8) & 0xff;
355                 *tbuf++ = (pixel>>16) & 0xff;
356             }
357             tbuf += pad;
358         }
359     }
360     XDestroyImage( image );
361     LeaveCriticalSection( &X11DRV_CritSection );
362
363     GDI_HEAP_UNLOCK( hbitmap );
364     return height * bmp->bitmap.bmWidthBytes;
365 }
366
367
368 /***********************************************************************
369  *           SetBitmapBits16    (GDI.106)
370  */
371 LONG WINAPI SetBitmapBits16( HBITMAP16 hbitmap, LONG count, LPCVOID buffer )
372 {
373     return SetBitmapBits32( hbitmap, count, buffer );
374 }
375
376
377 /***********************************************************************
378  *           SetBitmapBits32    (GDI32.303)
379  */
380 LONG WINAPI SetBitmapBits32( HBITMAP32 hbitmap, LONG count, LPCVOID buffer )
381 {
382     struct XPutImage_descr descr;
383     BITMAPOBJ * bmp;
384     LONG height;
385     XImage * image;
386     LPBYTE sbuf,tmpbuffer;
387     int w,h,pad,widthbytes;
388     
389     /* KLUDGE! */
390     if (count < 0) {
391         fprintf(stderr, "Negative number of bytes (%ld) passed to SetBitmapBits???\n", count );
392         count = -count;
393     }
394     bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC );
395     if (!bmp) return 0;
396
397     TRACE(bitmap, "%dx%d %d colors %p\n",
398             bmp->bitmap.bmWidth, bmp->bitmap.bmHeight,
399             1 << bmp->bitmap.bmBitsPixel, buffer );
400
401       /* Only set entire lines */
402     height = count / bmp->bitmap.bmWidthBytes;
403     if (height > bmp->bitmap.bmHeight) height = bmp->bitmap.bmHeight;
404
405     pad = BITMAP_GetBitsPadding( bmp->bitmap.bmWidth, bmp->bitmap.bmBitsPixel );
406
407     if (!height || (pad == -1)) 
408     {
409       GDI_HEAP_UNLOCK( hbitmap );
410       return 0;
411     }
412         
413     sbuf = (LPBYTE)buffer;
414
415     widthbytes  = DIB_GetXImageWidthBytes(bmp->bitmap.bmWidth,bmp->bitmap.bmBitsPixel);
416     tmpbuffer   = (LPBYTE)xmalloc(widthbytes*height);
417
418     EnterCriticalSection( &X11DRV_CritSection );
419     image = XCreateImage( display, DefaultVisualOfScreen(screen),
420                           bmp->bitmap.bmBitsPixel, ZPixmap, 0, tmpbuffer,
421                           bmp->bitmap.bmWidth,height,32,widthbytes );
422     
423     /* copy 16 bit padded image buffer with real bitsperpixel to XImage */
424     sbuf = (LPBYTE)buffer;
425     switch (bmp->bitmap.bmBitsPixel)
426     {
427     case 1:
428         for (h=0;h<height;h++)
429         {
430             for (w=0;w<bmp->bitmap.bmWidth;w++)
431             {
432                 XPutPixel(image,w,h,(sbuf[0]>>(7-(w&7))) & 1);
433                 if ((w&7) == 7)
434                     sbuf++;
435             }
436             sbuf += pad;
437         }
438         break;
439     case 4:
440         for (h=0;h<height;h++)
441         {
442             for (w=0;w<bmp->bitmap.bmWidth;w++)
443             {
444                 if (!(w & 1)) XPutPixel( image, w, h, *sbuf >> 4 );
445                 else XPutPixel( image, w, h, *sbuf++ & 0xf );
446             }
447             sbuf += pad;
448         }
449         break;
450     case 8:
451         for (h=0;h<height;h++)
452         {
453             for (w=0;w<bmp->bitmap.bmWidth;w++)
454                 XPutPixel(image,w,h,*sbuf++);
455             sbuf += pad;
456         }
457         break;
458     case 15:
459     case 16:
460         for (h=0;h<height;h++)
461         {
462             for (w=0;w<bmp->bitmap.bmWidth;w++)
463             {
464                 XPutPixel(image,w,h,sbuf[1]*256+sbuf[0]);
465                 sbuf+=2;
466             }
467         }
468         break;
469     case 24: 
470         for (h=0;h<height;h++)
471         {
472             for (w=0;w<bmp->bitmap.bmWidth;w++)
473             {
474                 XPutPixel(image,w,h,(sbuf[2]<<16)+(sbuf[1]<<8)+sbuf[0]);
475                 sbuf += 3;
476             }
477             sbuf += pad;
478         }
479         break;
480     }
481
482     descr.bmp    = bmp;
483     descr.image  = image;
484     descr.width  = bmp->bitmap.bmWidth;
485     descr.height = height;
486     CALL_LARGE_STACK( XPutImage_wrapper, &descr );
487     XDestroyImage( image ); /* frees tmpbuffer too */
488     LeaveCriticalSection( &X11DRV_CritSection );
489     
490     GDI_HEAP_UNLOCK( hbitmap );
491     return height * bmp->bitmap.bmWidthBytes;
492 }
493
494 HANDLE16 WINAPI LoadImage16( HINSTANCE16 hinst, LPCSTR name, UINT16 type,
495                              INT16 desiredx, INT16 desiredy, UINT16 loadflags)
496 {
497         if (HIWORD(name)) {
498                 fprintf(stddeb,"LoadImage16(0x%04x,%s,%d,%d,%d,0x%08x)\n",
499                         hinst,(char *)PTR_SEG_TO_LIN(name),type,desiredx,desiredy,loadflags
500                 );
501         } else {
502                 fprintf(stddeb,"LoadImage16(0x%04x,%p,%d,%d,%d,0x%08x)\n",
503                         hinst,name,type,desiredx,desiredy,loadflags
504                 );
505         }
506         switch (type) {
507         case IMAGE_BITMAP:
508                 return LoadBitmap16(hinst,(SEGPTR)name);
509         case IMAGE_ICON:
510                 return LoadIcon16(hinst,(SEGPTR)name);
511         case IMAGE_CURSOR:
512                 return LoadCursor16(hinst,(SEGPTR)name);
513         }
514         return 0;
515         
516 }
517 /**********************************************************************
518  *          LoadImage32A    (USER32.364)
519  * FIXME: implementation still lacks nearly all features, see LR_*
520  * defines in windows.h
521  */
522
523 HANDLE32 WINAPI LoadImage32A( HINSTANCE32 hinst, LPCSTR name, UINT32 type,
524                               INT32 desiredx, INT32 desiredy, UINT32 loadflags)
525 {
526         if (HIWORD(name)) {
527                 TRACE(resource,"(0x%04x,%s,%d,%d,%d,0x%08x)\n",
528                         hinst,name,type,desiredx,desiredy,loadflags
529                 );
530         } else {
531                 TRACE(resource,"(0x%04x,%p,%d,%d,%d,0x%08x)\n",
532                         hinst,name,type,desiredx,desiredy,loadflags
533                 );
534         }
535         switch (type) {
536         case IMAGE_BITMAP:
537                 return LoadBitmap32A(hinst,name);
538         case IMAGE_ICON:
539                 return LoadIcon32A(hinst,name);
540         case IMAGE_CURSOR:
541                 return LoadCursor32A(hinst,name);
542         }
543         return 0;
544 }
545
546 HANDLE32 WINAPI LoadImage32W( HINSTANCE32 hinst, LPCWSTR name, UINT32 type,
547                               INT32 desiredx, INT32 desiredy, UINT32 loadflags)
548 {
549         if (HIWORD(name)) {
550                 TRACE(resource,"(0x%04x,%p,%d,%d,%d,0x%08x)\n",
551                         hinst,name,type,desiredx,desiredy,loadflags
552                 );
553         } else {
554                 TRACE(resource,"(0x%04x,%p,%d,%d,%d,0x%08x)\n",
555                         hinst,name,type,desiredx,desiredy,loadflags
556                 );
557         }
558         switch (type) {
559         case IMAGE_BITMAP:
560                 return LoadBitmap32W(hinst,name);
561         case IMAGE_ICON:
562                 return LoadIcon32W(hinst,name);
563         case IMAGE_CURSOR:
564                 return LoadCursor32W(hinst,name);
565         }
566         return 0;
567 }
568
569 /**********************************************************************
570  *          CopyBitmap32 (not an API)
571  *
572  */
573 HBITMAP32 WINAPI CopyBitmap32 (HBITMAP32 hnd)
574 {
575     HBITMAP32 res = 0;
576     BITMAP32 bmp;
577
578     if (GetObject32A (hnd, sizeof (bmp), &bmp))
579     {
580         res = CreateBitmapIndirect32 (&bmp);
581         SetBitmapBits32 (res, bmp.bmWidthBytes * bmp.bmHeight, bmp.bmBits);
582     }
583     return res;
584 }
585
586 /**********************************************************************
587  *          CopyImage32    (USER32.60)
588  *
589  * FIXME: implementation still lacks nearly all features, see LR_*
590  * defines in windows.h
591  */
592 HANDLE32 WINAPI CopyImage32( HANDLE32 hnd, UINT32 type, INT32 desiredx,
593                              INT32 desiredy, UINT32 flags )
594 {
595     switch (type)
596     {
597         case IMAGE_BITMAP:
598                 return CopyBitmap32(hnd);
599         case IMAGE_ICON:
600                 return CopyIcon32(hnd);
601         case IMAGE_CURSOR:
602                 return CopyCursor32(hnd);
603     }
604     return 0;
605 }
606
607
608 /**********************************************************************
609  *          LoadBitmap16    (USER.175)
610  */
611 HBITMAP16 WINAPI LoadBitmap16( HINSTANCE16 instance, SEGPTR name )
612 {
613     HBITMAP32 hbitmap = 0;
614     HDC32 hdc;
615     HRSRC16 hRsrc;
616     HGLOBAL16 handle;
617     BITMAPINFO *info;
618
619     if (HIWORD(name))
620     {
621         char *str = (char *)PTR_SEG_TO_LIN( name );
622         TRACE(bitmap, "(%04x,'%s')\n", instance, str );
623         if (str[0] == '#') name = (SEGPTR)(DWORD)(WORD)atoi( str + 1 );
624     }
625     else
626         TRACE(bitmap, "(%04x,%04x)\n",
627                         instance, LOWORD(name) );
628
629     if (!instance)  /* OEM bitmap */
630     {
631         if (HIWORD((int)name)) return 0;
632         return OBM_LoadBitmap( LOWORD((int)name) );
633     }
634
635     if (!(hRsrc = FindResource16( instance, name, RT_BITMAP ))) return 0;
636     if (!(handle = LoadResource16( instance, hRsrc ))) return 0;
637
638     info = (BITMAPINFO *)LockResource16( handle );
639     if ((hdc = GetDC32(0)) != 0)
640     {
641         char *bits = (char *)info + DIB_BitmapInfoSize( info, DIB_RGB_COLORS );
642         hbitmap = CreateDIBitmap32( hdc, &info->bmiHeader, CBM_INIT,
643                                     bits, info, DIB_RGB_COLORS );
644         ReleaseDC32( 0, hdc );
645     }
646     FreeResource16( handle );
647     return hbitmap;
648 }
649
650 /**********************************************************************
651  *          LoadBitmap32W   (USER32.357)
652  */
653 HBITMAP32 WINAPI LoadBitmap32W( HINSTANCE32 instance, LPCWSTR name )
654 {
655     HBITMAP32 hbitmap = 0;
656     HDC32 hdc;
657     HRSRC32 hRsrc;
658     HGLOBAL32 handle;
659     BITMAPINFO *info;
660
661     if (!instance)  /* OEM bitmap */
662     {
663         if (HIWORD((int)name)) return 0;
664         return OBM_LoadBitmap( LOWORD((int)name) );
665     }
666
667     if (!(hRsrc = FindResource32W( instance, name,
668                 (LPWSTR)RT_BITMAP ))) return 0;
669     if (!(handle = LoadResource32( instance, hRsrc ))) return 0;
670
671     info = (BITMAPINFO *)LockResource32( handle );
672     if ((hdc = GetDC32(0)) != 0)
673     {
674         char *bits = (char *)info + DIB_BitmapInfoSize( info, DIB_RGB_COLORS );
675         hbitmap = CreateDIBitmap32( hdc, &info->bmiHeader, CBM_INIT,
676                                     bits, info, DIB_RGB_COLORS );
677         ReleaseDC32( 0, hdc );
678     }
679     return hbitmap;
680 }
681
682
683 /**********************************************************************
684  *          LoadBitmap32A   (USER32.356)
685  */
686 HBITMAP32 WINAPI LoadBitmap32A( HINSTANCE32 instance, LPCSTR name )
687 {
688     HBITMAP32 res;
689     if (!HIWORD(name)) res = LoadBitmap32W( instance, (LPWSTR)name );
690     else
691     {
692         LPWSTR uni = HEAP_strdupAtoW( GetProcessHeap(), 0, name );
693         res = LoadBitmap32W( instance, uni );
694         HeapFree( GetProcessHeap(), 0, uni );
695     }
696     return res;
697 }
698
699
700 /***********************************************************************
701  *           BITMAP_DeleteObject
702  */
703 BOOL32 BITMAP_DeleteObject( HBITMAP16 hbitmap, BITMAPOBJ * bmp )
704 {
705 #ifdef PRELIMINARY_WING16_SUPPORT
706     if( bmp->bitmap.bmBits )
707         TSXShmDetach( display, (XShmSegmentInfo*)bmp->bitmap.bmBits );
708 #endif
709
710     TSXFreePixmap( display, bmp->pixmap );
711 #ifdef PRELIMINARY_WING16_SUPPORT
712     if( bmp->bitmap.bmBits )
713     {
714     __ShmBitmapCtl* p = (__ShmBitmapCtl*)bmp->bitmap.bmBits;
715       WORD          sel = HIWORD(p->bits);
716       unsigned long l, limit = GetSelectorLimit(sel);
717
718       for( l = 0; l < limit; l += 0x10000, sel += __AHINCR )
719            FreeSelector(sel);
720       shmctl(p->si.shmid, IPC_RMID, NULL); 
721       shmdt(p->si.shmaddr);  /* already marked for destruction */
722     }
723 #endif
724     return GDI_FreeObject( hbitmap );
725 }
726
727         
728 /***********************************************************************
729  *           BITMAP_GetObject16
730  */
731 INT16 BITMAP_GetObject16( BITMAPOBJ * bmp, INT16 count, LPVOID buffer )
732 {
733     if (count > sizeof(bmp->bitmap)) count = sizeof(bmp->bitmap);
734     memcpy( buffer, &bmp->bitmap, count );
735     return count;
736 }
737     
738
739 /***********************************************************************
740  *           BITMAP_GetObject32
741  */
742 INT32 BITMAP_GetObject32( BITMAPOBJ * bmp, INT32 count, LPVOID buffer )
743 {
744     BITMAP32 bmp32;
745     bmp32.bmType       = bmp->bitmap.bmType;
746     bmp32.bmWidth      = bmp->bitmap.bmWidth;
747     bmp32.bmHeight     = bmp->bitmap.bmHeight;
748     bmp32.bmWidthBytes = bmp->bitmap.bmWidthBytes;
749     bmp32.bmPlanes     = bmp->bitmap.bmPlanes;
750     bmp32.bmBitsPixel  = bmp->bitmap.bmBitsPixel;
751     bmp32.bmBits       = NULL;
752     if (count > sizeof(bmp32)) count = sizeof(bmp32);
753     memcpy( buffer, &bmp32, count );
754     return count;
755 }
756     
757
758
759 /***********************************************************************
760  *           CreateDiscardableBitmap16    (GDI.156)
761  */
762 HBITMAP16 WINAPI CreateDiscardableBitmap16( HDC16 hdc, INT16 width,
763                                             INT16 height )
764 {
765     return CreateCompatibleBitmap16( hdc, width, height );
766 }
767
768
769 /***********************************************************************
770  *           CreateDiscardableBitmap32    (GDI32.38)
771  */
772 HBITMAP32 WINAPI CreateDiscardableBitmap32( HDC32 hdc, INT32 width,
773                                             INT32 height )
774 {
775     return CreateCompatibleBitmap32( hdc, width, height );
776 }
777
778
779 /***********************************************************************
780  *           GetBitmapDimensionEx16    (GDI.468)
781  */
782 BOOL16 WINAPI GetBitmapDimensionEx16( HBITMAP16 hbitmap, LPSIZE16 size )
783 {
784     BITMAPOBJ * bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC );
785     if (!bmp) return FALSE;
786     *size = bmp->size;
787     GDI_HEAP_UNLOCK( hbitmap );
788     return TRUE;
789 }
790
791
792 /***********************************************************************
793  *           GetBitmapDimensionEx32    (GDI32.144)
794  */
795 BOOL32 WINAPI GetBitmapDimensionEx32( HBITMAP32 hbitmap, LPSIZE32 size )
796 {
797     BITMAPOBJ * bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC );
798     if (!bmp) return FALSE;
799     size->cx = (INT32)bmp->size.cx;
800     size->cy = (INT32)bmp->size.cy;
801     GDI_HEAP_UNLOCK( hbitmap );
802     return TRUE;
803 }
804
805
806 /***********************************************************************
807  *           GetBitmapDimension    (GDI.162)
808  */
809 DWORD WINAPI GetBitmapDimension( HBITMAP16 hbitmap )
810 {
811     SIZE16 size;
812     if (!GetBitmapDimensionEx16( hbitmap, &size )) return 0;
813     return MAKELONG( size.cx, size.cy );
814 }
815
816
817 /***********************************************************************
818  *           SetBitmapDimensionEx16    (GDI.478)
819  */
820 BOOL16 WINAPI SetBitmapDimensionEx16( HBITMAP16 hbitmap, INT16 x, INT16 y,
821                                       LPSIZE16 prevSize )
822 {
823     BITMAPOBJ * bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC );
824     if (!bmp) return FALSE;
825     if (prevSize) *prevSize = bmp->size;
826     bmp->size.cx = x;
827     bmp->size.cy = y;
828     GDI_HEAP_UNLOCK( hbitmap );
829     return TRUE;
830 }
831
832
833 /***********************************************************************
834  *           SetBitmapDimensionEx32    (GDI32.304)
835  */
836 BOOL32 WINAPI SetBitmapDimensionEx32( HBITMAP32 hbitmap, INT32 x, INT32 y,
837                                       LPSIZE32 prevSize )
838 {
839     BITMAPOBJ * bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC );
840     if (!bmp) return FALSE;
841     if (prevSize) CONV_SIZE16TO32( &bmp->size, prevSize );
842     bmp->size.cx = (INT16)x;
843     bmp->size.cy = (INT16)y;
844     GDI_HEAP_UNLOCK( hbitmap );
845     return TRUE;
846 }
847
848
849 /***********************************************************************
850  *           SetBitmapDimension    (GDI.163)
851  */
852 DWORD WINAPI SetBitmapDimension( HBITMAP16 hbitmap, INT16 x, INT16 y )
853 {
854     SIZE16 size;
855     if (!SetBitmapDimensionEx16( hbitmap, x, y, &size )) return 0;
856     return MAKELONG( size.cx, size.cy );
857 }
858