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