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