Release 980503
[wine] / misc / imagelist.c
1 /*
2  *  ImageList implementation
3  *
4  *  Copyright 1998 Eric Kohl
5  *
6  *  TODO:
7  *    - Improve the documentation.
8  *    - Improve error checking in some functions.
9  *    - Fix ILD_TRANSPARENT error in ImageList_DrawIndirect.
10  *    - Fix offsets in ImageList_DrawIndirect.
11  *    - Fix ImageList_GetIcon (might be a result of the
12  *      ILD_TRANSPARENT error in ImageList_DrawIndirect).
13  *    - Fix drag functions.
14  *    - Fix all other stubs.
15  *    - Add ImageList_SetFilter (undocumented).
16  *      BTW does anybody know anything about this function???
17  *        - It removes 12 Bytes from the stack (3 Parameters).
18  *        - First parameter SHOULD be a HIMAGELIST.
19  *        - Second parameter COULD be an index?????
20  *        - Third parameter.... ?????????????????????
21  *
22  *  Testing:
23  *    - Test ImageList_GetImageRect (undocumented).
24  *    - Test all the other functions.
25  *
26  *  Comments:
27  *    - ImageList_Draw, ImageList_DrawEx and ImageList_GetIcon use
28  *      ImageList_DrawIndirect. Since ImageList_DrawIndirect is still
29  *      partially imlemented, the functions mentioned above will be 
30  *      limited in functionality too.
31  */
32
33 /* This must be defined because the HIMAGELIST type is just a pointer
34  * to the _IMAGELIST data structure. But M$ does not want us to know
35  * anything about its contents. Applications just see a pointer to
36  * an empty structure. It's just to keep compatibility.
37  */
38 #define __WINE_IMAGELIST_C
39  
40 /* This must be defined until "GetIconInfo" is implemented completely.
41  * To do that the Cursor and Icon code in objects/cursoricon.c must
42  * be rewritten.
43  */
44 #define __GET_ICON_INFO_HACK__ 
45  
46 #include "windows.h"
47 #include "imagelist.h"
48 #include "commctrl.h"
49 #include "debug.h"
50
51 #ifdef __GET_ICON_INFO_HACK__
52 #include "bitmap.h"
53 #endif
54
55
56 #define _MAX(a,b) (((a)>(b))?(a):(b))
57 #define _MIN(a,b) (((a)>(b))?(b):(a))
58
59 #define MAX_OVERLAYIMAGE 15
60
61
62 /*
63  * internal ImageList data used for dragging
64  */
65 static HIMAGELIST himlInternalDrag = NULL;
66 static INT32      nInternalDragHotspotX = 0;
67 static INT32      nInternalDragHotspotY = 0;
68 static HCURSOR32  hcurInternal = 0;
69
70
71 /*************************************************************************
72  *                       IMAGELIST_InternalGrowBitmaps   [Internal]
73  *
74  *  Grows the bitmaps of the given image list by the given number of 
75  *  images. Can NOT be used to reduce the number of images.
76  */
77
78 static void IMAGELIST_InternalGrowBitmaps (
79         HIMAGELIST himl,    /* image list handle */
80         INT32 nImageCount)  /* number of images to grow by */
81 {
82     HDC32     hdcImageList, hdcBitmap;
83     HBITMAP32 hbmNewBitmap;
84     INT32     nNewWidth, nNewCount;
85
86     TRACE(imagelist, "Create grown bitmaps!\n");
87
88     nNewCount = himl->cCurImage + nImageCount + himl->cGrow;
89     nNewWidth = nNewCount * himl->cx;
90
91     hdcImageList = CreateCompatibleDC32 (0);
92     hdcBitmap = CreateCompatibleDC32 (0);
93
94     hbmNewBitmap =
95         CreateBitmap32 (nNewWidth, himl->cy, 1, himl->uBitsPixel, NULL);
96     if (hbmNewBitmap == 0)
97         ERR (imagelist, "Error creating new image bitmap!\n");
98
99     SelectObject32 (hdcImageList, himl->hbmImage);
100     SelectObject32 (hdcBitmap, hbmNewBitmap);
101     BitBlt32 (hdcBitmap, 0, 0, himl->cCurImage * himl->cx, himl->cy,
102               hdcImageList, 0, 0, SRCCOPY);
103
104     DeleteObject32 (himl->hbmImage);
105     himl->hbmImage = hbmNewBitmap;
106
107     if (himl->hbmMask) {
108         hbmNewBitmap = 
109             CreateBitmap32 (nNewWidth, himl->cy, 1, 1, NULL);
110
111         if (hbmNewBitmap == 0)
112             ERR (imagelist, "Error creating new mask bitmap!");
113
114         SelectObject32 (hdcImageList, himl->hbmMask);
115         SelectObject32 (hdcBitmap, hbmNewBitmap);
116         BitBlt32 (hdcBitmap, 0, 0, himl->cCurImage * himl->cx, himl->cy,
117                   hdcImageList, 0, 0, SRCCOPY);
118         DeleteObject32 (himl->hbmMask);
119         himl->hbmMask = hbmNewBitmap;
120     }
121
122     himl->cMaxImage = nNewCount;
123
124     DeleteDC32 (hdcImageList);
125     DeleteDC32 (hdcBitmap);
126 }
127
128
129 /*************************************************************************
130  *                       ImageList_Add   [COMCTL32.39]
131  *
132  *  Add an image (and a mask) to an image list.
133  *
134  *  RETURNS
135  *    Index of the first image that was added.
136  *    -1 if an error occurred.
137  */
138
139 INT32 WINAPI ImageList_Add (
140         HIMAGELIST himl,     /* imagelist handle */
141         HBITMAP32 hbmImage,  /* image bitmap */
142         HBITMAP32 hbmMask)   /* mask bitmap */
143 {
144     HDC32    hdcImageList, hdcImage, hdcMask;
145     INT32    nFirstIndex, nImageCount;
146     INT32    nStartX, nRunX, nRunY;
147     BITMAP32 bmp;
148
149     if (himl == NULL) return (-1);
150
151     hdcMask = 0; /* to keep compiler happy ;-) */
152
153     GetObject32A (hbmImage, sizeof(BITMAP32), (LPVOID)&bmp);
154     nImageCount = bmp.bmWidth / himl->cx;
155
156     if (himl->cCurImage + nImageCount >= himl->cMaxImage)
157         IMAGELIST_InternalGrowBitmaps (himl, nImageCount);
158
159     hdcImageList = CreateCompatibleDC32 (0);
160     hdcImage = CreateCompatibleDC32 (0);
161
162     SelectObject32 (hdcImageList, himl->hbmImage);
163     SelectObject32 (hdcImage, hbmImage);
164
165     BitBlt32 (hdcImageList, himl->cCurImage * himl->cx, 0,
166               bmp.bmWidth, himl->cy, hdcImage, 0, 0, SRCCOPY);
167           
168     if (himl->hbmMask)
169     {
170         if (hbmMask)
171         {
172             SelectObject32 (hdcImageList, himl->hbmMask);
173             SelectObject32 (hdcImage, hbmMask);
174             BitBlt32 (hdcImageList, himl->cCurImage * himl->cx, 0,
175                       bmp.bmWidth, himl->cy, hdcImage, 0, 0, SRCCOPY);
176
177             /* fix transparent areas of the image bitmap*/
178             SelectObject32 (hdcMask, himl->hbmMask);
179             SelectObject32 (hdcImage, himl->hbmImage);
180             nStartX = himl->cCurImage * himl->cx;
181             for (nRunY = 0; nRunY < himl->cy; nRunY++)
182             {
183                 for (nRunX = 0; nRunX < bmp.bmWidth; nRunX++)
184                 {
185                     if (GetPixel32 (hdcMask, nStartX + nRunX, nRunY) ==
186                         RGB(255, 255, 255))
187                         SetPixel32 (hdcImage, nStartX + nRunX, nRunY, 
188                                     RGB(0, 0, 0));
189                 }
190             }
191         }
192         else
193         {
194             /* create mask from the imagelist's background color */
195             hdcMask = CreateCompatibleDC32 (0);
196             SelectObject32 (hdcMask, himl->hbmMask);
197             nStartX = himl->cCurImage * himl->cx;
198             for (nRunY = 0; nRunY < himl->cy; nRunY++)
199             {
200                 for (nRunX = 0; nRunX < bmp.bmWidth; nRunX++)
201                 {
202                     if (GetPixel32 (hdcImageList, nStartX + nRunX, nRunY) ==
203                         himl->clrBk)
204                     {
205                         SetPixel32 (hdcImageList, nStartX + nRunX, nRunY, 
206                                     RGB(0, 0, 0));
207                         SetPixel32 (hdcMask, nStartX + nRunX, nRunY, 
208                                     RGB(255, 255, 255));
209                     }
210                     else
211                         SetPixel32 (hdcMask, nStartX + nRunX, nRunY, 
212                                     RGB(0, 0, 0));        
213                 }
214             }
215             DeleteDC32 (hdcMask);
216         }
217     }
218
219     DeleteDC32 (hdcImageList);
220     DeleteDC32 (hdcImage);
221
222     nFirstIndex = himl->cCurImage;
223     himl->cCurImage += nImageCount;
224
225     return (nFirstIndex);
226 }
227
228
229 /*************************************************************************
230  *                       ImageList_AddMasked   [COMCTL32.41]
231  *
232  *  Adds an image to an imagelist and creates a mask from the given
233  *  mask color.
234  *
235  *  RETURNS
236  *    Index of the first image that was added.
237  *    -1 if an error occurred.
238  */
239
240 INT32 WINAPI ImageList_AddMasked (
241         HIMAGELIST himl,    /* image list handle */
242         HBITMAP32 hbmImage, /* bitmap handle */
243         COLORREF clrMask)   /* backround color of the image */
244 {
245     HDC32    hdcImageList, hdcImage, hdcMask;
246     INT32    nIndex, nImageCount;
247     BITMAP32 bmp;
248     INT32    nStartX, nRunX, nRunY;
249
250     if (himl == NULL) return (-1);
251
252     GetObject32A (hbmImage, sizeof(BITMAP32), &bmp);
253     nImageCount = bmp.bmWidth / himl->cx;
254
255     if (himl->cCurImage + nImageCount >= himl->cMaxImage)
256         IMAGELIST_InternalGrowBitmaps (himl, nImageCount);
257
258     nIndex = himl->cCurImage;
259     himl->cCurImage += nImageCount;
260
261     hdcImageList = CreateCompatibleDC32 (0);
262     hdcImage = CreateCompatibleDC32 (0);
263
264     SelectObject32 (hdcImageList, himl->hbmImage);
265     SelectObject32 (hdcImage, hbmImage);
266     BitBlt32 (hdcImageList, nIndex * himl->cx, 0, bmp.bmWidth, himl->cy,
267               hdcImage, 0, 0, SRCCOPY);
268
269     if (himl->hbmMask)
270     {
271         /* create Mask */
272         hdcMask = CreateCompatibleDC32 (0);
273         SelectObject32 (hdcMask, himl->hbmMask);
274         nStartX = nIndex * himl->cx;
275         for (nRunY = 0; nRunY < himl->cy; nRunY++)
276         {
277             for (nRunX = 0; nRunX < bmp.bmWidth; nRunX++)
278             {
279                 if (GetPixel32 (hdcImageList, nStartX + nRunX, nRunY) ==
280                     clrMask)
281                 {
282                     SetPixel32 (hdcImageList, nStartX + nRunX, nRunY,
283                                 RGB(0, 0, 0));
284                     SetPixel32 (hdcMask, nStartX + nRunX, nRunY,
285                                 RGB(255, 255, 255));
286                 }
287                 else
288                     SetPixel32 (hdcMask, nStartX + nRunX, nRunY, RGB(0, 0, 0));
289             }
290         }
291         DeleteDC32 (hdcMask);
292     }
293
294     DeleteDC32 (hdcImageList);
295     DeleteDC32 (hdcImage);
296   
297     return (nIndex);
298 }
299
300
301 /*************************************************************************
302  *                       ImageList_BeginDrag   [COMCTL32.42]
303  *
304  *  Creates a temporary imagelist with an image in it, which will be used
305  *  as a drag image.
306  *
307  *  RETURNS
308  *    ...
309  */
310
311 BOOL32 WINAPI ImageList_BeginDrag (
312         HIMAGELIST himlTrack, /* Handle of the source imagelist */
313         INT32 iTrack,         /* Index of the image in the source imagelist */
314         INT32 dxHotspot,      /* Position of the hot spot of the */
315         INT32 dyHotspot)      /* drag image */
316 {
317     HDC32 hdcSrc, hdcDst;
318
319     FIXME(imagelist, "ImageList_BeginDrag: partially implemented!\n");
320
321     if (himlTrack == NULL) return (FALSE);
322     if (himlInternalDrag)
323         ImageList_EndDrag ();
324
325     himlInternalDrag = ImageList_Create (himlTrack->cx, himlTrack->cy,
326                                          himlTrack->flags, 1, 1);
327     if (himlInternalDrag == NULL)
328     {
329         ERR(imagelist, "Error creating drag image list!\n");
330         return (FALSE);
331     }
332
333     nInternalDragHotspotX = dxHotspot;
334     nInternalDragHotspotY = dyHotspot;
335
336     hdcSrc = CreateCompatibleDC32 (0);
337     hdcDst = CreateCompatibleDC32 (0);
338
339     /* copy image */
340     SelectObject32 (hdcSrc, himlTrack->hbmImage);
341     SelectObject32 (hdcDst, himlInternalDrag->hbmImage);
342     StretchBlt32 (hdcDst, 0, 0, himlInternalDrag->cx, himlInternalDrag->cy, hdcSrc,
343                   iTrack * himlTrack->cx, 0, himlTrack->cx, himlTrack->cy, SRCCOPY);
344
345     /* copy mask */
346     SelectObject32 (hdcSrc, himlTrack->hbmMask);
347     SelectObject32 (hdcDst, himlInternalDrag->hbmMask);
348     StretchBlt32 (hdcDst, 0, 0, himlInternalDrag->cx, himlInternalDrag->cy, hdcSrc,
349                   iTrack * himlTrack->cx, 0, himlTrack->cx, himlTrack->cy, SRCCOPY);
350
351     DeleteDC32 (hdcSrc);
352     DeleteDC32 (hdcDst);
353
354     himlInternalDrag->cCurImage = 1;
355
356     return (TRUE);
357 }
358
359
360 /*************************************************************************
361  *                       ImageList_Copy   [COMCTL32.43]
362  *
363  *  Copies an image of the source imagelist to an image of the 
364  *  destination imagelist. Images can be copied or swapped.
365  *  Copying from one imagelist to another is allowed, in contrary to
366  *  M$'s original implementation. They just allow copying or swapping
367  *  within one imagelist (himlDst and himlSrc must be the same).
368  *
369  *  RETURNS
370  *    ...
371  */
372
373 BOOL32 WINAPI ImageList_Copy (
374         HIMAGELIST himlDst,  /* Handle of the destination imagelist */
375         INT32 iDst,          /* Index of the destination image */
376         HIMAGELIST himlSrc,  /* Handel od the source imagelist */
377         INT32 iSrc,          /* Index of the source image */
378         INT32 uFlags)        /* Flags used for the copy operation */
379 {
380     HDC32 hdcSrc, hdcDst;    
381
382     TRACE(imagelist, "iDst=%d  iSrc=%d\n", iDst, iSrc);
383
384     if ((himlSrc == NULL) || (himlDst == NULL)) return (FALSE);
385     if ((iDst < 0) || (iDst >= himlDst->cCurImage)) return (FALSE);
386     if ((iSrc < 0) || (iSrc >= himlSrc->cCurImage)) return (FALSE);
387
388     hdcSrc = CreateCompatibleDC32 (0);
389     if (himlDst == himlSrc)
390         hdcDst = hdcSrc;
391     else
392         hdcDst = CreateCompatibleDC32 (0);
393
394     if (uFlags & ILCF_SWAP)
395     {
396         /* swap */
397         HBITMAP32 hbmTempImage, hbmTempMask;
398
399         /* create temporary bitmaps */
400         hbmTempImage = CreateBitmap32 (himlSrc->cx, himlSrc->cy, 1,
401                                        himlSrc->uBitsPixel, NULL);
402         hbmTempMask = CreateBitmap32 (himlSrc->cx, himlSrc->cy, 1, 1, NULL);
403
404         /* copy (and stretch) destination to temporary bitmaps.(save) */
405         /* image */
406         SelectObject32 (hdcSrc, himlDst->hbmImage);
407         SelectObject32 (hdcDst, hbmTempImage);
408         StretchBlt32 (hdcDst, 0, 0, himlSrc->cx, himlSrc->cy,
409                       hdcSrc, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
410                       SRCCOPY);
411         /* mask */
412         SelectObject32 (hdcSrc, himlDst->hbmMask);
413         SelectObject32 (hdcDst, hbmTempMask);
414         StretchBlt32 (hdcDst, 0, 0, himlSrc->cx, himlSrc->cy,
415                       hdcSrc, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
416                       SRCCOPY);
417
418         /* copy (and stretch) source to destination */
419         /* image */
420         SelectObject32 (hdcSrc, himlSrc->hbmImage);
421         SelectObject32 (hdcDst, himlDst->hbmImage);
422         StretchBlt32 (hdcDst, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
423                       hdcSrc, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
424                       SRCCOPY);
425         /* mask */
426         SelectObject32 (hdcSrc, himlSrc->hbmMask);
427         SelectObject32 (hdcDst, himlDst->hbmMask);
428         StretchBlt32 (hdcDst, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
429                       hdcSrc, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
430                       SRCCOPY);
431
432         /* copy (without stretching) temporary bitmaps to source (restore) */
433         /* image */
434         SelectObject32 (hdcSrc, hbmTempImage);
435         SelectObject32 (hdcDst, himlSrc->hbmImage);
436         BitBlt32 (hdcDst, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
437                   hdcSrc, 0, 0, SRCCOPY);
438         /* mask */
439         SelectObject32 (hdcSrc, hbmTempMask);
440         SelectObject32 (hdcDst, himlSrc->hbmMask);
441         BitBlt32 (hdcDst, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
442                   hdcSrc, 0, 0, SRCCOPY);
443
444         /* delete temporary bitmaps */
445         DeleteObject32 (hbmTempMask);
446         DeleteObject32 (hbmTempImage);
447     }
448     else
449     {
450         /* copy image */
451         SelectObject32 (hdcSrc, himlSrc->hbmImage);
452         if (himlSrc == himlDst)
453             hdcDst = hdcSrc;
454         else
455             SelectObject32 (hdcDst, himlDst->hbmImage);
456         StretchBlt32 (hdcDst, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
457                       hdcSrc, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
458                       SRCCOPY);
459
460         /* copy mask */
461         SelectObject32 (hdcSrc, himlSrc->hbmMask);
462         if (himlSrc == himlDst)
463             hdcDst = hdcSrc;
464         else
465             SelectObject32 (hdcDst, himlDst->hbmMask);
466         StretchBlt32 (hdcDst, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
467                       hdcSrc, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
468                       SRCCOPY);
469     }
470
471     DeleteDC32 (hdcSrc);
472     if (himlSrc != himlDst)
473         DeleteDC32 (hdcDst);
474
475     return (TRUE);
476 }
477
478
479 /*************************************************************************
480  *                       ImageList_Create   [COMCTL32.44]
481  *
482  *  Creates an imagelist of the given image size and number of images.
483  *
484  *  RETURNS
485  *    Handle of the created image list.
486  *    0 if an error occurred.
487  */
488
489 HIMAGELIST WINAPI ImageList_Create (
490         INT32 cx,        /* Width of an image */
491         INT32 cy,        /* Height of an image */
492         UINT32 flags,    /* Flags for imagelist creation */
493         INT32 cInitial,  /* Initial number of images in the imaglist */
494         INT32 cGrow)     /* Number of images that is added to the */
495                          /* imagelist when it grows */
496 {
497     HIMAGELIST himl;
498     HDC32      hdc;
499     INT32      nCount;
500     HBITMAP32  hbmTemp;
501     WORD       aBitBlend25[16] = 
502         {0x7777, 0xDDDD, 0x7777, 0xDDDD, 0x7777, 0xDDDD, 0x7777, 0xDDDD,
503          0x7777, 0xDDDD, 0x7777, 0xDDDD, 0x7777, 0xDDDD, 0x7777, 0xDDDD};
504     WORD       aBitBlend50[16] =
505         {0x5555, 0xAAAA, 0x5555, 0xAAAA, 0x5555, 0xAAAA, 0x5555, 0xAAAA,
506          0x5555, 0xAAAA, 0x5555, 0xAAAA, 0x5555, 0xAAAA, 0x5555, 0xAAAA};
507
508     himl = (HIMAGELIST)LocalAlloc32 (LMEM_FIXED | LMEM_ZEROINIT,
509                                      sizeof(struct _IMAGELIST));
510     if (!himl)
511         return (NULL);
512     himl->cx = cx;
513     himl->cy = cy;
514     himl->flags = flags;
515     himl->cMaxImage = cInitial + cGrow;
516     himl->cInitial = cInitial;
517     himl->cGrow = cGrow;
518     himl->cCurImage = 0;
519     himl->clrBk = CLR_NONE;
520
521     /* initialize overlay mask indices */
522     for (nCount = 0; nCount <= MAX_OVERLAYIMAGE; nCount++)
523         himl->nOvlIdx[nCount] = -1;
524
525     hdc = CreateCompatibleDC32 (0);
526     himl->uBitsPixel = (UINT32)GetDeviceCaps32 (hdc, BITSPIXEL);
527     DeleteDC32 (hdc);
528
529     TRACE(imagelist, "Image: %d Bits per Pixel\n", himl->uBitsPixel);
530
531     himl->hbmImage =
532         CreateBitmap32 (himl->cx * himl->cMaxImage, himl->cy,
533                         1, himl->uBitsPixel, NULL);
534     if (himl->hbmImage == 0)
535     {
536         ERR(imagelist, "Error creating image bitmap!\n");
537         return (0);
538     }
539
540     if (himl->flags & ILC_MASK)
541     {
542         himl->hbmMask = 
543             CreateBitmap32 (himl->cx * himl->cMaxImage, himl->cy, 1, 1, NULL);
544         if (himl->hbmMask == 0)
545         {
546             ERR(imagelist, "Error creating mask bitmap!\n");
547             if (himl->hbmImage)
548                 DeleteObject32 (himl->hbmImage);
549             return (0);
550         }
551     }
552     else
553         himl->hbmMask = 0;
554
555     /* create blending brushes */
556     hbmTemp = CreateBitmap32 (16, 16, 1, 1, &aBitBlend25);
557     himl->hbrBlend25 = CreatePatternBrush32 (hbmTemp);
558     DeleteObject32 (hbmTemp);
559
560     hbmTemp = CreateBitmap32 (16, 16, 1, 1, &aBitBlend50);
561     himl->hbrBlend50 = CreatePatternBrush32 (hbmTemp);
562     DeleteObject32 (hbmTemp);
563
564     return (himl);    
565 }
566
567
568 /*************************************************************************
569  *                       ImageList_Destroy   [COMCTL32.45]
570  *
571  *  Destroy the given imagelist.
572  *
573  *  RETURNS
574  *    TRUE if the image list was destroyed.
575  *    FALSE if an error occurred.
576  */
577
578 BOOL32 WINAPI ImageList_Destroy (
579         HIMAGELIST himl)  /* Handle of the imagelist */
580
581     if (himl == NULL) return (FALSE);
582
583     if (himl->hbmImage)
584         DeleteObject32 (himl->hbmImage);
585     if (himl->hbmMask)
586         DeleteObject32 (himl->hbmMask);
587         
588     LocalFree32 ((HLOCAL32)himl);
589     return (TRUE);
590 }
591
592
593 /*************************************************************************
594  *                       ImageList_DragEnter   [COMCTL32.46]
595  *
596  *  FIXME
597  *    This is still an empty stub.
598  */
599
600 BOOL32 WINAPI ImageList_DragEnter (
601         HWND32 hwndLock, 
602         INT32 x, 
603         INT32 y)
604 {
605     FIXME (imagelist, "empty stub!\n");
606
607     hcurInternal = GetCursor32 ();
608
609
610     ShowCursor32 (TRUE);
611
612     return (FALSE);
613 }
614
615
616 /*************************************************************************
617  *                       ImageList_DragLeave   [COMCTL32.47]
618  */
619
620 BOOL32 WINAPI ImageList_DragLeave (
621         HWND32 hwndLock)
622 {
623     FIXME (imagelist, "empty stub!\n");
624
625
626     SetCursor32 (hcurInternal);
627     hcurInternal = 0;
628  
629     ShowCursor32 (FALSE);
630
631     return (FALSE);
632 }
633
634
635 /*************************************************************************
636  *                       ImageList_DragMove   [COMCTL32.48]
637  */
638
639 BOOL32 WINAPI ImageList_DragMove (
640         INT32 x,
641         INT32 y)
642 {
643     FIXME (imagelist, "empty stub!\n");
644
645 //    if (hcurInternal)
646 //        SetCursor32 (hcurInternal);
647 //    ImageList_Draw (himlInternalDrag, 0, x, y, 0);
648
649
650     return (FALSE);
651 }
652
653
654 /*************************************************************************
655  *                       ImageList_DragShowNolock   [COMCTL32.49]
656  */
657
658 BOOL32 WINAPI
659 ImageList_DragShowNolock (BOOL32 bShow)
660 {
661     FIXME (imagelist, "empty stub!\n");
662
663     return (FALSE);
664 }
665
666
667 /*************************************************************************
668  *                       ImageList_Draw   [COMCTL32.50]
669  */
670
671 BOOL32 WINAPI ImageList_Draw (
672         HIMAGELIST himl,
673         INT32 i,
674         HDC32 hdc, 
675         INT32 x,
676         INT32 y,
677         UINT32 fStyle)
678 {
679     IMAGELISTDRAWPARAMS imldp;
680
681     imldp.cbSize  = sizeof(IMAGELISTDRAWPARAMS);
682     imldp.himl    = himl;
683     imldp.i       = i;
684     imldp.hdcDst  = hdc,
685     imldp.x       = x;
686     imldp.y       = y;
687     imldp.cx      = 0;
688     imldp.cy      = 0;
689     imldp.xBitmap = 0;
690     imldp.yBitmap = 0;
691     imldp.rgbBk   = CLR_DEFAULT;
692     imldp.rgbFg   = CLR_DEFAULT;
693     imldp.fStyle  = fStyle;
694     imldp.dwRop   = 0;
695
696     return (ImageList_DrawIndirect (&imldp));
697 }
698
699
700 /*************************************************************************
701  *                       ImageList_DrawEx   [COMCTL32.51]
702  */
703
704 BOOL32 WINAPI ImageList_DrawEx (
705         HIMAGELIST himl,
706         INT32 i,
707         HDC32 hdc,
708         INT32 x,
709         INT32 y,
710         INT32 xOffs,
711         INT32 yOffs,
712         COLORREF rgbBk,
713         COLORREF rgbFg,
714         UINT32 fStyle)
715 {
716     IMAGELISTDRAWPARAMS imldp;
717
718     imldp.cbSize  = sizeof(IMAGELISTDRAWPARAMS);
719     imldp.himl    = himl;
720     imldp.i       = i;
721     imldp.hdcDst  = hdc,
722     imldp.x       = x;
723     imldp.y       = y;
724     imldp.cx      = xOffs;
725     imldp.cy      = yOffs;
726     imldp.xBitmap = 0;
727     imldp.yBitmap = 0;
728     imldp.rgbBk   = rgbBk;
729     imldp.rgbFg   = rgbFg;
730     imldp.fStyle  = fStyle;
731     imldp.dwRop   = 0;
732
733     return (ImageList_DrawIndirect (&imldp));
734 }
735
736
737 /*************************************************************************
738  *                       ImageList_DrawIndirect   [COMCTL32.52]
739  */
740
741 BOOL32 WINAPI ImageList_DrawIndirect (
742         IMAGELISTDRAWPARAMS *pimldp)
743 {
744     HIMAGELIST himlLocal;
745     HDC32      hdcImageList, hdcTempImage;
746     HBITMAP32  hbmTempImage;
747     HBRUSH32   hBrush, hOldBrush;
748     INT32      nOvlIdx;
749     COLORREF   clrBlend;
750     BOOL32     bImage;       /* draw image ? */
751     BOOL32     bImageTrans;  /* draw image transparent ? */
752     BOOL32     bMask;        /* draw mask ? */
753     BOOL32     bMaskTrans;   /* draw mask transparent ? */
754     BOOL32     bBlend25;
755     BOOL32     bBlend50;
756
757     if (pimldp == NULL) return (FALSE);
758     if (pimldp->cbSize < sizeof(IMAGELISTDRAWPARAMS)) return (FALSE);
759
760     himlLocal = pimldp->himl;
761     
762     /* ILD_NORMAL state */
763     bImage      = TRUE;
764     bImageTrans = FALSE;
765     bMask       = FALSE;
766     bMaskTrans  = FALSE;
767     bBlend25    = FALSE;
768     bBlend50    = FALSE;
769     if ((himlLocal->clrBk == CLR_NONE) && (himlLocal->hbmMask))
770     {
771         bImageTrans = TRUE;
772         bMask = TRUE;
773         bMaskTrans = TRUE;
774     }
775     
776     /* ILD_IMAGE state (changes) */
777     if (pimldp->fStyle & ILD_IMAGE)
778     {
779         bMask = FALSE;
780         bImage = TRUE;
781         bImageTrans = FALSE;
782     }
783     
784     /* ILD_MASK state (changes) */
785     if ((pimldp->fStyle & ILD_MASK) && (himlLocal->hbmMask))
786     {
787         bMask  = TRUE;
788         bMaskTrans = FALSE;
789         bImage = FALSE;
790     }
791     if ((pimldp->fStyle & ILD_TRANSPARENT) && (himlLocal->hbmMask))
792     {
793         bMaskTrans = TRUE;
794         bImageTrans = TRUE;
795     }
796     if ((himlLocal->clrBk == CLR_NONE) && (himlLocal->hbmMask))
797         bMaskTrans = TRUE;
798
799     if (pimldp->fStyle & ILD_BLEND50)
800         bBlend50 = TRUE;
801     else if (pimldp->fStyle & ILD_BLEND25)
802         bBlend25 = TRUE;
803
804     hdcImageList = CreateCompatibleDC32 (0);
805
806     if (bMask)
807     {
808         /* draw the mask */
809         SelectObject32 (hdcImageList, himlLocal->hbmMask);
810         
811         BitBlt32 (pimldp->hdcDst, pimldp->x, pimldp->y,
812                   himlLocal->cx, himlLocal->cy, hdcImageList,
813                   himlLocal->cx * pimldp->i, 0,
814                   bMaskTrans ? SRCAND : SRCCOPY);
815     }
816
817     if (bImage)
818     {
819         /* draw the image */
820         SelectObject32 (hdcImageList, himlLocal->hbmImage);
821
822         if (!bImageTrans)
823         {
824             hBrush = CreateSolidBrush32 (himlLocal->clrBk);
825             hOldBrush = SelectObject32 (pimldp->hdcDst, hBrush);
826             PatBlt32 (pimldp->hdcDst, pimldp->x, pimldp->y,
827                       himlLocal->cx, himlLocal->cy, PATCOPY);
828             DeleteObject32 (SelectObject32 (pimldp->hdcDst, hOldBrush));
829         }
830
831         BitBlt32 (pimldp->hdcDst, pimldp->x, pimldp->y, himlLocal->cx,
832                   himlLocal->cy, hdcImageList, himlLocal->cx * pimldp->i, 0,
833                   SRCPAINT);
834
835         if (bBlend25 || bBlend50)
836         {
837             if (pimldp->rgbFg == CLR_DEFAULT)
838                 clrBlend = GetSysColor32 (COLOR_HIGHLIGHT);
839             else
840                 clrBlend = pimldp->rgbFg;
841
842             hdcTempImage = CreateCompatibleDC32 (0);
843             hbmTempImage = CreateBitmap32 (himlLocal->cx, himlLocal->cy,
844                                            1, himlLocal->uBitsPixel, NULL);
845             SelectObject32 (hdcTempImage, hbmTempImage);
846
847
848             /* mask */
849             SelectObject32 (hdcTempImage,
850                             bBlend50 ? himlLocal->hbrBlend50 : himlLocal->hbrBlend25);
851             PatBlt32 (hdcTempImage, 0, 0, himlLocal->cx, himlLocal->cy, PATCOPY);
852
853             SelectObject32 (hdcImageList, himlLocal->hbmMask);
854             BitBlt32 (hdcTempImage, 0, 0, himlLocal->cx,
855                       himlLocal->cy, hdcImageList, 
856                       pimldp->i * himlLocal->cx, 0, SRCPAINT);
857
858             BitBlt32 (pimldp->hdcDst, pimldp->x, pimldp->y, himlLocal->cx,
859                       himlLocal->cy, hdcTempImage, 0, 0, SRCAND);
860
861             /* fill */
862             hBrush = CreateSolidBrush32 (clrBlend);
863             SelectObject32 (hdcTempImage, hBrush);
864             PatBlt32 (hdcTempImage, 0, 0, himlLocal->cx, himlLocal->cy, PATCOPY);
865             DeleteObject32 (hBrush);
866
867             SelectObject32 (hdcTempImage,
868                             bBlend50 ? himlLocal->hbrBlend50 : himlLocal->hbrBlend25);
869             PatBlt32 (hdcTempImage, 0, 0, himlLocal->cx, himlLocal->cy, 0x0A0329);
870
871             SelectObject32 (hdcImageList, himlLocal->hbmMask);
872             BitBlt32 (hdcTempImage, 0, 0, himlLocal->cx,
873                       himlLocal->cy, hdcImageList, 
874                       pimldp->i * himlLocal->cx, 0, SRCPAINT);
875
876             BitBlt32 (pimldp->hdcDst, pimldp->x, pimldp->y, himlLocal->cx,
877                       himlLocal->cy, hdcTempImage, 0, 0, SRCPAINT);
878
879             DeleteObject32 (hbmTempImage);
880             DeleteDC32 (hdcTempImage);
881         }
882     }   
883
884     /* Draw overlay image */
885     if (pimldp->fStyle & 0x0700)
886     {
887         nOvlIdx = (pimldp->fStyle & 0x0700) >> 8;
888         if ((nOvlIdx >= 1) && (nOvlIdx <= MAX_OVERLAYIMAGE))
889         {
890             nOvlIdx = pimldp->himl->nOvlIdx[nOvlIdx - 1];
891             if ((nOvlIdx >= 0) && (nOvlIdx <= pimldp->himl->cCurImage))
892             {
893                 if (pimldp->himl->hbmMask)
894                 {  
895                     SelectObject32 (hdcImageList, pimldp->himl->hbmMask);
896                     BitBlt32 (pimldp->hdcDst, pimldp->x, pimldp->y, 
897                               pimldp->himl->cx, pimldp->himl->cy, hdcImageList,
898                               pimldp->himl->cx * nOvlIdx, 0, SRCAND);  
899                 }  
900                 SelectObject32 (hdcImageList, pimldp->himl->hbmImage);
901                 BitBlt32 (pimldp->hdcDst, pimldp->x, pimldp->y, 
902                           pimldp->himl->cx, pimldp->himl->cy, hdcImageList,
903                           pimldp->himl->cx * nOvlIdx, 0, SRCPAINT);
904             }
905         }
906     }
907
908     DeleteDC32 (hdcImageList);
909   
910     return (TRUE);
911 }
912
913
914 /*************************************************************************
915  *                       ImageList_Duplicate   [COMCTL32.53]
916  *
917  *  Duplicates an image list.
918  *
919  *  RETURNS
920  *    Handle of duplicate image list, 0 if an error occurred.
921  */
922
923 HIMAGELIST WINAPI ImageList_Duplicate (
924         HIMAGELIST himlSrc)
925 {
926     HIMAGELIST himlDst;
927     HDC32 hdcSrc, hdcDst;
928
929     if (himlSrc == NULL) {
930         ERR (imagelist, "Invalid image list handle!\n");
931         return (NULL);
932     }
933
934     himlDst = ImageList_Create (himlSrc->cx, himlSrc->cy, himlSrc->flags,
935                                 himlSrc->cInitial, himlSrc->cGrow);
936
937     if (himlDst)
938     {
939         hdcSrc = CreateCompatibleDC32 (0);
940         hdcDst = CreateCompatibleDC32 (0);
941         SelectObject32 (hdcSrc, himlSrc->hbmImage);
942         SelectObject32 (hdcDst, himlDst->hbmImage);
943         BitBlt32 (hdcDst, 0, 0, himlSrc->cCurImage * himlSrc->cx, himlSrc->cy,
944                   hdcSrc, 0, 0, SRCCOPY);
945
946         if (himlDst->hbmMask)
947         {
948             SelectObject32 (hdcSrc, himlSrc->hbmMask);
949             SelectObject32 (hdcDst, himlDst->hbmMask);
950             BitBlt32 (hdcDst, 0, 0, himlSrc->cCurImage * himlSrc->cx,
951                       himlSrc->cy, hdcSrc, 0, 0, SRCCOPY);
952         }
953
954         DeleteDC32 (hdcDst);
955         DeleteDC32 (hdcSrc);
956     }
957
958     return (himlDst);
959 }
960
961
962 /*************************************************************************
963  *                       ImageList_EndDrag   [COMCTL32.54]
964  *
965  *  Finishes a drag operation.
966  *
967  *  FIXME
968  *    semi-stub.
969  */
970
971 BOOL32 WINAPI ImageList_EndDrag (VOID)
972 {
973     FIXME (imagelist, "partially implemented!\n");
974
975     if (himlInternalDrag)
976     {
977
978         ImageList_Destroy (himlInternalDrag);
979         himlInternalDrag = NULL;
980
981         nInternalDragHotspotX = 0;
982         nInternalDragHotspotY = 0;
983
984     }
985
986     return (TRUE);
987 }
988
989
990 /*************************************************************************
991  *                       ImageList_GetBkColor   [COMCTL32.55]
992  *
993  *  Returns the background color of an image list.
994  *
995  *  RETURNS
996  *    Background color.
997  */
998
999 COLORREF WINAPI ImageList_GetBkColor (
1000         HIMAGELIST himl)
1001 {
1002     return (himl->clrBk);
1003 }
1004
1005
1006 /*************************************************************************
1007  *                       ImageList_GetDragImage   [COMCTL32.56]
1008  *
1009  *  Returns the handle to the internal drag image list.
1010  *
1011  *  FIXME
1012  *    semi-stub.
1013  */
1014
1015 HIMAGELIST WINAPI ImageList_GetDragImage (
1016         POINT32 *ppt,
1017         POINT32 *pptHotspot)
1018 {
1019     FIXME (imagelist, "partially imlemented!\n");
1020
1021     if (himlInternalDrag)
1022         return (himlInternalDrag);
1023
1024     return (NULL);
1025 }
1026
1027
1028 /*************************************************************************
1029  *                       ImageList_GetIcon   [COMCTL32.57]
1030  */
1031
1032 HICON32 WINAPI ImageList_GetIcon (
1033         HIMAGELIST himl, 
1034         INT32 i, 
1035         UINT32 fStyle)
1036 {
1037     ICONINFO ii;
1038     HICON32  hIcon;
1039     HDC32    hdc;
1040     INT32    nWidth, nHeight;
1041
1042     nWidth = GetSystemMetrics32 (SM_CXICON);
1043     nHeight = GetSystemMetrics32 (SM_CYICON);
1044
1045     ii.fIcon = TRUE;
1046     ii.xHotspot = 0;
1047     ii.yHotspot = 0;
1048     ii.hbmMask  = CreateBitmap32 (nWidth, nHeight, 1, 1, NULL);
1049     ii.hbmColor = CreateBitmap32 (nWidth, nHeight, 1, 1, NULL);
1050
1051     hdc = CreateCompatibleDC32(0);
1052
1053     /* draw image*/
1054     SelectObject32 (hdc, ii.hbmColor);
1055     PatBlt32 (hdc, 0, 0, nWidth, nHeight, BLACKNESS);
1056     ImageList_Draw (himl, i, hdc, 0, 0, fStyle | ILD_TRANSPARENT);
1057
1058     /* draw mask*/
1059     SelectObject32 (hdc, ii.hbmMask);
1060     PatBlt32 (hdc, 0, 0, nWidth, nHeight, WHITENESS);
1061     ImageList_Draw (himl, i, hdc, 0, 0, fStyle | ILD_MASK);
1062
1063     hIcon = CreateIconIndirect (&ii);    
1064
1065     DeleteDC32 (hdc);
1066     DeleteObject32 (ii.hbmMask);
1067     DeleteObject32 (ii.hbmColor);
1068
1069     return (hIcon);
1070 }
1071
1072
1073 /*************************************************************************
1074  *                       ImageList_GetIconSize   [COMCTL32.58]
1075  */
1076
1077 BOOL32 WINAPI ImageList_GetIconSize (
1078         HIMAGELIST himl,
1079         INT32 *cx,
1080         INT32 *cy)
1081 {
1082
1083     if (himl == NULL) return (FALSE);
1084
1085     if (cx)
1086         *cx = himl->cx;
1087     
1088     if (cy)
1089         *cy = himl->cy;
1090     return (TRUE);
1091 }
1092
1093
1094 /*************************************************************************
1095  *                       ImageList_GetIconCount   [COMCTL32.59]
1096  */
1097
1098 INT32 WINAPI ImageList_GetImageCount (
1099         HIMAGELIST himl)
1100 {
1101     return (himl->cCurImage);
1102 }
1103
1104
1105 /*************************************************************************
1106  *                       ImageList_GetImageInfo   [COMCTL32.60]
1107  */
1108
1109 BOOL32 WINAPI ImageList_GetImageInfo (
1110         HIMAGELIST himl,
1111         INT32 i,
1112         IMAGEINFO *pImageInfo)
1113 {
1114     if ((himl == NULL) || (pImageInfo == NULL)) return (FALSE);
1115
1116     pImageInfo->hbmImage = himl->hbmImage;
1117     pImageInfo->hbmMask  = himl->hbmMask;
1118     
1119     pImageInfo->rcImage.top    = 0;
1120     pImageInfo->rcImage.bottom = himl->cy;
1121     pImageInfo->rcImage.left   = i * himl->cx;
1122     pImageInfo->rcImage.right  = (i+1) * himl->cx;
1123     
1124     return (TRUE);
1125 }
1126
1127
1128 /*************************************************************************
1129  *                       ImageList_GetImageRect   [COMCTL32.61]
1130  *
1131  *  COMMENTS
1132  *    I don't know if it really returns a BOOL32 or something else!!!??
1133  */
1134
1135 BOOL32 WINAPI ImageList_GetImageRect (
1136         HIMAGELIST himl,
1137         INT32 i,
1138         LPRECT32 lpRect)
1139 {
1140     if (himl == NULL) return (FALSE);
1141     if ((i < 0) || (i >= himl->cCurImage)) return (FALSE);
1142     if (lpRect == NULL) return (FALSE);
1143
1144     lpRect->left = i * himl->cx;
1145     lpRect->top = 0;
1146     lpRect->right = lpRect->left + himl->cx;
1147     lpRect->bottom = himl->cy;
1148
1149     return (TRUE);
1150 }
1151
1152
1153 /*************************************************************************
1154  *                       ImageList_LoadImage32A   [COMCTL32.63]
1155  */
1156
1157 HIMAGELIST WINAPI ImageList_LoadImage32A (
1158         HINSTANCE32 hi,
1159         LPCSTR lpbmp,
1160         INT32 cx,
1161         INT32 cGrow, 
1162         COLORREF clrMask,
1163         UINT32 uType,
1164         UINT32 uFlags)
1165 {
1166     HIMAGELIST himl = NULL;
1167     HANDLE32   handle;
1168     INT32      nImageCount;
1169
1170     handle = LoadImage32A (hi, lpbmp, uType, 0, 0, uFlags);
1171     if (!handle) return (NULL);
1172
1173     if (uType == IMAGE_BITMAP) {
1174         BITMAP32 bmp;
1175         GetObject32A (handle, sizeof(BITMAP32), &bmp);
1176         nImageCount = bmp.bmWidth / cx;
1177
1178         himl = ImageList_Create (cx, bmp.bmHeight, ILC_MASK | ILC_COLOR,
1179                                  nImageCount, cGrow);
1180         ImageList_AddMasked (himl, (HBITMAP32)handle, clrMask);
1181     }
1182     else if ((uType == IMAGE_ICON) || (uType == IMAGE_CURSOR)) {
1183 #ifdef __GET_ICON_INFO_HACK__
1184         HBITMAP32 hbmImage;
1185         HBITMAP32 hbmMask;
1186         CURSORICONINFO *ptr;
1187
1188         if (!(ptr = (CURSORICONINFO *)GlobalLock16(handle))) return (NULL);
1189         hbmMask  = CreateBitmap32 (ptr->nWidth, ptr->nHeight, 1, 1, 
1190                                    (char *)(ptr + 1));
1191         hbmImage = CreateBitmap32 (ptr->nWidth, ptr->nHeight, ptr->bPlanes,
1192                                    ptr->bBitsPerPixel,
1193                                    (char *)(ptr + 1) + ptr->nHeight * 
1194                                    BITMAP_WIDTH_BYTES(ptr->nWidth, 1));
1195         himl = ImageList_Create (ptr->nWidth, ptr->nHeight,
1196                                  ILC_MASK | ILC_COLOR, 1, cGrow);
1197         ImageList_Add (himl, hbmImage, hbmMask);
1198         DeleteObject32 (hbmImage);
1199         DeleteObject32 (hbmMask);
1200         GlobalUnlock16 (handle);
1201 #else
1202         ICONINFO32 ii;
1203         BITMAP32 bmp;
1204
1205         GetIconInfo (hIcon, &ii);
1206         GetObject32A (ii->hbmMask, sizeof(BITMAP32), (LPVOID)&bmp);
1207         himl = ImageList_Create (bmp.bmWidth, bmp.bmHeight, 
1208                                  ILC_MASK | ILC_COLOR, 1, cGrow);
1209         ImageList_Add (himl, ii->hbmColor, ii->hbmMask);
1210 #endif
1211     }
1212
1213     DeleteObject32 (handle);
1214     
1215     return (himl);
1216 }
1217
1218
1219 /*************************************************************************
1220  *                       ImageList_LoadImage32W   [COMCTL32.64]
1221  */
1222
1223 HIMAGELIST WINAPI ImageList_LoadImage32W (
1224         HINSTANCE32 hi,
1225         LPCWSTR lpbmp,
1226         INT32 cx,
1227         INT32 cGrow,
1228         COLORREF clrMask,
1229         UINT32 uType,
1230         UINT32 uFlags)
1231 {
1232     HIMAGELIST himl = NULL;
1233     HANDLE32   handle;
1234     INT32      nImageCount;
1235
1236     handle = LoadImage32W (hi, lpbmp, uType, 0, 0, uFlags);
1237     if (!handle) {
1238         ERR (imagelist, "Error loading image!\n");
1239         return (NULL);
1240     }
1241
1242     if (uType == IMAGE_BITMAP) {
1243         BITMAP32 bmp;
1244         GetObject32A (handle, sizeof(BITMAP32), &bmp);
1245         nImageCount = bmp.bmWidth / cx;
1246
1247         himl = ImageList_Create (cx, bmp.bmHeight, ILC_MASK | ILC_COLOR,
1248                                  nImageCount, cGrow);
1249         ImageList_AddMasked (himl, (HBITMAP32)handle, clrMask);
1250     }
1251     else if ((uType == IMAGE_ICON) || (uType == IMAGE_CURSOR)) {
1252 #ifdef __GET_ICON_INFO_HACK__
1253         HBITMAP32 hbmImage;
1254         HBITMAP32 hbmMask;
1255         CURSORICONINFO *ptr;
1256
1257         if (!(ptr = (CURSORICONINFO *)GlobalLock16(handle))) return (NULL);
1258         hbmMask  = CreateBitmap32 (ptr->nWidth, ptr->nHeight, 1, 1, 
1259                                    (char *)(ptr + 1));
1260         hbmImage = CreateBitmap32 (ptr->nWidth, ptr->nHeight, ptr->bPlanes,
1261                                    ptr->bBitsPerPixel,
1262                                    (char *)(ptr + 1) + ptr->nHeight * 
1263                                    BITMAP_WIDTH_BYTES(ptr->nWidth, 1));
1264         himl = ImageList_Create (ptr->nWidth, ptr->nHeight,
1265                                  ILC_MASK | ILC_COLOR, 1, cGrow);
1266         ImageList_Add (himl, hbmImage, hbmMask);
1267         DeleteObject32 (hbmImage);
1268         DeleteObject32 (hbmMask);
1269         GlobalUnlock16 (handle);
1270 #else
1271         ICONINFO32 ii;
1272         BITMAP32 bmp;
1273
1274         GetIconInfo (hIcon, &ii);
1275         GetObject32A (ii->hbmMask, sizeof(BITMAP32), (LPVOID)&bmp);
1276         himl = ImageList_Create (bmp.bmWidth, bmp.bmHeight, 
1277                                  ILC_MASK | ILC_COLOR, 1, cGrow);
1278         ImageList_Add (himl, ii->hbmColor, ii->hbmMask);
1279 #endif
1280     }
1281
1282     DeleteObject32 (handle);
1283     
1284     return (himl);
1285 }
1286
1287
1288 /*************************************************************************
1289  *                       ImageList_Merge   [COMCTL32.65]
1290  */
1291
1292 HIMAGELIST WINAPI ImageList_Merge (
1293         HIMAGELIST himl1,
1294         INT32 i1,
1295         HIMAGELIST himl2,
1296         INT32 i2,
1297         INT32 xOffs,
1298         INT32 yOffs)
1299 {
1300     HIMAGELIST himlDst = NULL;
1301     HDC32      hdcSrcImage, hdcDstImage;
1302     INT32      cxDst, cyDst;
1303     INT32      xOff1, yOff1, xOff2, yOff2;
1304     INT32      nX1, nX2;
1305
1306     if ((himl1 == NULL) || (himl2 == NULL)) return (NULL);
1307
1308     /* check indices */
1309     if ((i1 < 0) || (i1 >= himl1->cCurImage)) {
1310         ERR (imagelist, "Index 1 out of range! %d\n", i1);
1311         return (NULL);
1312     }
1313
1314     if ((i2 < 0) || (i2 >= himl2->cCurImage)) {
1315         ERR (imagelist, "Index 2 out of range! %d\n", i2);
1316         return (NULL);
1317     }
1318
1319     if (xOffs > 0) {
1320         cxDst = _MAX (himl1->cx, xOffs + himl2->cx);
1321         xOff1 = 0;
1322         xOff2 = xOffs;
1323     }
1324     else if (xOffs < 0) {
1325         cxDst = _MAX (himl2->cx, himl1->cx - xOffs);
1326         xOff1 = -xOffs;
1327         xOff2 = 0;
1328     }
1329     else {
1330         cxDst = 0;
1331         xOff1 = 0;
1332         xOff2 = 0;
1333     }
1334
1335     if (yOffs > 0) {
1336         cyDst = _MAX (himl1->cy, yOffs + himl2->cy);
1337         yOff1 = 0;
1338         yOff2 = yOffs;
1339     }
1340     else if (yOffs < 0) {
1341         cyDst = _MAX (himl2->cy, himl1->cy - yOffs);
1342         yOff1 = -yOffs;
1343         yOff2 = 0;
1344     }
1345     else {
1346         cyDst = 0;
1347         yOff1 = 0;
1348         yOff2 = 0;
1349     }
1350
1351     himlDst = ImageList_Create (cxDst, cyDst, ILC_MASK | ILC_COLOR, 1, 1);
1352
1353     if (himlDst) {
1354         hdcSrcImage = CreateCompatibleDC32 (0);
1355         hdcDstImage = CreateCompatibleDC32 (0);
1356         nX1 = i1 * himl1->cx;
1357         nX2 = i2 * himl2->cx;
1358         
1359         /* copy image */
1360         SelectObject32 (hdcSrcImage, himl1->hbmImage);
1361         SelectObject32 (hdcDstImage, himlDst->hbmImage);
1362         BitBlt32 (hdcDstImage, 0, 0, cxDst, cyDst, 
1363                   hdcSrcImage, 0, 0, BLACKNESS);
1364         BitBlt32 (hdcDstImage, xOff1, yOff1, himl1->cx, himl1->cy, 
1365                   hdcSrcImage, nX1, 0, SRCCOPY);
1366
1367         SelectObject32 (hdcSrcImage, himl2->hbmMask);
1368         BitBlt32 (hdcDstImage, xOff2, yOff2, himl2->cx, himl2->cy, 
1369                   hdcSrcImage, nX2, 0, SRCAND);
1370
1371         SelectObject32 (hdcSrcImage, himl2->hbmImage);
1372         BitBlt32 (hdcDstImage, xOff2, yOff2, himl2->cx, himl2->cy, 
1373                   hdcSrcImage, nX2, 0, SRCPAINT);
1374
1375         /* copy mask */
1376         SelectObject32 (hdcSrcImage, himl1->hbmMask);
1377         SelectObject32 (hdcDstImage, himlDst->hbmMask);
1378         BitBlt32 (hdcDstImage, 0, 0, cxDst, cyDst, 
1379                   hdcSrcImage, 0, 0, WHITENESS);
1380         BitBlt32 (hdcDstImage, xOff1, yOff1, himl1->cx, himl1->cy, 
1381                   hdcSrcImage, nX1, 0, SRCCOPY);
1382
1383         SelectObject32 (hdcSrcImage, himl2->hbmMask);
1384         BitBlt32 (hdcDstImage, xOff2, yOff2, himl2->cx, himl2->cy, 
1385                   hdcSrcImage, nX2, 0, SRCAND);
1386
1387         DeleteDC32 (hdcSrcImage);
1388         DeleteDC32 (hdcDstImage);
1389     }
1390    
1391     return (himlDst);
1392 }
1393
1394
1395 #if 0
1396 #if __IStream_INTERFACE_DEFINED__
1397 HIMAGELIST WINAPI ImageList_Read (
1398         LPSTREAM pstm)
1399 {
1400     FIXME (imagelist, "empty stub!\n");
1401
1402
1403     return (NULL);
1404 }
1405 #endif /* __IStream_INTERFACE_DEFINED__ */
1406 #endif /* 0 */
1407
1408
1409 BOOL32 WINAPI ImageList_Remove (
1410         HIMAGELIST himl,
1411         INT32 i)
1412 {
1413     HBITMAP32 hbmNewImage, hbmNewMask;
1414     HDC32     hdcSrc, hdcDst;
1415     INT32     cxNew, nCount;
1416
1417     if ((i < -1) || (i >= himl->cCurImage)) {
1418         ERR (imagelist, "Index out of range! %d\n", i);
1419         return (FALSE);
1420     }
1421
1422     if (himl->cCurImage == 0) {
1423         ERR (imagelist, "List is already empty!\n");
1424         return (FALSE);
1425     }
1426
1427     if (i == -1) {
1428         /* remove all */
1429         TRACE (imagelist, "Remove all!\n");
1430
1431         himl->cMaxImage = himl->cInitial + himl->cGrow;
1432         himl->cCurImage = 0;
1433         for (nCount = 0; nCount <= MAX_OVERLAYIMAGE; nCount++)
1434              himl->nOvlIdx[nCount] = -1;
1435
1436         DeleteObject32 (himl->hbmImage);
1437         himl->hbmImage =
1438             CreateBitmap32 (himl->cMaxImage * himl->cx, himl->cy,
1439                             1, himl->uBitsPixel, NULL);
1440
1441         if (himl->hbmMask) {
1442             DeleteObject32 (himl->hbmMask);
1443             himl->hbmMask =
1444                 CreateBitmap32 (himl->cMaxImage * himl->cx, himl->cy,
1445                                 1, 1, NULL);
1446         }
1447     }
1448     else {
1449         /* delete one image */
1450         TRACE (imagelist, "Remove single image! %d\n", i);
1451
1452         /* create new bitmap(s) */
1453         cxNew = (himl->cCurImage + himl->cGrow - 1) * himl->cx;
1454
1455         TRACE(imagelist, " - Number of images: %d / %d (Old/New)\n",
1456                  himl->cCurImage, himl->cCurImage - 1);
1457         TRACE(imagelist, " - Max. number of images: %d / %d (Old/New)\n",
1458                  himl->cMaxImage, himl->cCurImage + himl->cGrow - 1);
1459         
1460         hbmNewImage =
1461             CreateBitmap32 (cxNew, himl->cy, 1, himl->uBitsPixel, NULL);
1462
1463         if (himl->hbmMask)
1464             hbmNewMask = CreateBitmap32 (cxNew, himl->cy, 1, 1, NULL);
1465         else
1466             hbmNewMask = 0;  /* Just to keep compiler happy! */
1467
1468         hdcSrc = CreateCompatibleDC32 (0);
1469         hdcDst = CreateCompatibleDC32 (0);
1470
1471         /* copy all images and masks prior to the "removed" image */
1472         if (i > 0) {
1473             TRACE (imagelist, "Pre image copy: Copy %d images\n", i);
1474        
1475             SelectObject32 (hdcSrc, himl->hbmImage);
1476             SelectObject32 (hdcDst, hbmNewImage);
1477             BitBlt32 (hdcDst, 0, 0, i * himl->cx, himl->cy,
1478                       hdcSrc, 0, 0, SRCCOPY);
1479
1480             if (himl->hbmMask) {
1481                 SelectObject32 (hdcSrc, himl->hbmMask);
1482                 SelectObject32 (hdcDst, hbmNewMask);
1483                 BitBlt32 (hdcDst, 0, 0, i * himl->cx, himl->cy,
1484                           hdcSrc, 0, 0, SRCCOPY);
1485             }
1486         }
1487
1488         /* copy all images and masks behind the removed image */
1489         if (i < himl->cCurImage - 1) {
1490             TRACE (imagelist, "Post image copy!\n");
1491             SelectObject32 (hdcSrc, himl->hbmImage);
1492             SelectObject32 (hdcDst, hbmNewImage);
1493             BitBlt32 (hdcDst, i * himl->cx, 0, (himl->cCurImage - i - 1) * himl->cx,
1494                       himl->cy, hdcSrc, (i + 1) * himl->cx, 0, SRCCOPY);
1495
1496             if (himl->hbmMask) {
1497                 SelectObject32 (hdcSrc, himl->hbmMask);
1498                 SelectObject32 (hdcDst, hbmNewMask);
1499                 BitBlt32 (hdcDst, i * himl->cx, 0,
1500                           (himl->cCurImage - i - 1) * himl->cx,
1501                           himl->cy, hdcSrc, (i + 1) * himl->cx, 0, SRCCOPY);
1502             }
1503         }
1504
1505         DeleteDC32 (hdcSrc);
1506         DeleteDC32 (hdcDst);
1507
1508         /* delete old images and insert new ones */
1509         DeleteObject32 (himl->hbmImage);
1510         himl->hbmImage = hbmNewImage;
1511         if (himl->hbmMask) {
1512             DeleteObject32 (himl->hbmMask);
1513             himl->hbmMask = hbmNewMask;
1514         }
1515
1516         himl->cCurImage--;
1517         himl->cMaxImage = himl->cCurImage + himl->cGrow;
1518     }
1519
1520     return (TRUE);
1521 }
1522
1523
1524 BOOL32 WINAPI ImageList_Replace (
1525         HIMAGELIST himl,
1526         INT32 i,
1527         HBITMAP32 hbmImage, 
1528         HBITMAP32 hbmMask)
1529 {
1530     HDC32 hdcImageList, hdcImage;
1531     BITMAP32 bmp;
1532
1533     if (himl == NULL) {
1534         ERR (imagelist, "Invalid image list handle!\n");
1535         return (FALSE);
1536     }
1537     
1538     if ((i >= himl->cCurImage) || (i < 0)) {
1539         ERR (imagelist, "Invalid image index!\n");
1540         return (FALSE);
1541     }
1542
1543     hdcImageList = CreateCompatibleDC32 (0);
1544     hdcImage = CreateCompatibleDC32 (0);
1545     GetObject32A (hbmImage, sizeof(BITMAP32), (LPVOID)&bmp);
1546
1547     /* Replace Image */
1548     SelectObject32 (hdcImageList, himl->hbmImage);
1549     SelectObject32 (hdcImage, hbmImage);
1550
1551     StretchBlt32 (hdcImageList, i * himl->cx, 0, himl->cx, himl->cy,
1552                   hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
1553
1554     if (himl->hbmMask)
1555     {
1556         /* Replace Mask */
1557         SelectObject32 (hdcImageList, himl->hbmMask);
1558         SelectObject32 (hdcImage, hbmMask);
1559
1560         StretchBlt32 (hdcImageList, i * himl->cx, 0, himl->cx, himl->cy,
1561                       hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
1562     }
1563
1564     DeleteDC32 (hdcImage);
1565     DeleteDC32 (hdcImageList);
1566
1567     return (TRUE);
1568 }
1569
1570
1571 INT32 WINAPI ImageList_ReplaceIcon (
1572         HIMAGELIST himl,
1573         INT32 i,
1574         HICON32 hIcon)
1575 {
1576     HDC32     hdcImageList, hdcImage;
1577     INT32     nIndex;
1578 #ifdef __GET_ICON_INFO_HACK__
1579     HBITMAP32 hbmImage;
1580     HBITMAP32 hbmMask;
1581     CURSORICONINFO *ptr;
1582 #else    
1583     ICONINFO32 ii;
1584     BITMAP32 bmp;
1585 #endif
1586
1587     if (himl == NULL) return (-1);
1588     if ((i >= himl->cCurImage) || (i < -1)) return (-1);
1589
1590 #ifdef __GET_ICON_INFO_HACK__
1591     if (!(ptr = (CURSORICONINFO *)GlobalLock16(hIcon))) return (-1);
1592     hbmMask  = CreateBitmap32 (ptr->nWidth, ptr->nHeight, 1, 1, 
1593                                (char *)(ptr + 1));
1594     hbmImage = CreateBitmap32 (ptr->nWidth, ptr->nHeight, ptr->bPlanes,
1595                                ptr->bBitsPerPixel,
1596                                (char *)(ptr + 1) + ptr->nHeight * 
1597                                BITMAP_WIDTH_BYTES(ptr->nWidth, 1));
1598 #else
1599     GetIconInfo (hIcon, &ii);
1600     GetObject32A (ii->hbmMask, sizeof(BITMAP32), (LPVOID)&bmp);
1601 #endif
1602
1603     if (i == -1) {
1604         if (himl->cCurImage + 1 >= himl->cMaxImage)
1605             IMAGELIST_InternalGrowBitmaps (himl, 1);
1606
1607         nIndex = himl->cCurImage;
1608         himl->cCurImage++;
1609     }
1610     else
1611         nIndex = i;
1612
1613     hdcImageList = CreateCompatibleDC32 (0);
1614     hdcImage = CreateCompatibleDC32 (0);
1615
1616 #ifdef __GET_ICON_INFO_HACK__
1617     SelectObject32 (hdcImageList, himl->hbmImage);
1618     SelectObject32 (hdcImage, hbmImage);
1619     StretchBlt32 (hdcImageList, nIndex * himl->cx, 0, himl->cx, himl->cy,
1620                   hdcImage, 0, 0, ptr->nWidth, ptr->nHeight, SRCCOPY);
1621 #else
1622     SelectObject32 (hdcImage, ii->hbmColor);
1623     StretchBlt32 (hdcImageList, nIndex * himl->cx, 0, himl->cx, himl->cy,
1624                   hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
1625 #endif
1626
1627     if (himl->hbmMask) {
1628 #ifdef __GET_ICON_INFO_HACK__
1629         SelectObject32 (hdcImageList, himl->hbmMask);
1630         SelectObject32 (hdcImage, hbmMask);
1631         StretchBlt32 (hdcImageList, nIndex * himl->cx, 0, himl->cx, himl->cy,
1632                       hdcImage, 0, 0, ptr->nWidth, ptr->nHeight, SRCCOPY);
1633 #else
1634         SelectObject32 (hdcImage, ii->hbmMask);
1635         StretchBlt32 (hdcImageList, nIndex * himl->cx, 0, himl->cx, himl->cy,
1636                       hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
1637 #endif
1638     }
1639
1640     DeleteDC32 (hdcImageList);
1641     DeleteDC32 (hdcImage);
1642 #ifdef __GET_ICON_INFO_HACK        
1643     DeleteObject32 (hbmImage);
1644     DeleteObject32 (hbmMask);
1645     GlobalUnlock16 (hIcon);
1646 #endif
1647     return (nIndex);
1648 }
1649
1650
1651 COLORREF WINAPI ImageList_SetBkColor (
1652         HIMAGELIST himl,
1653         COLORREF clrBk)
1654 {
1655     COLORREF clrOldBk;
1656
1657     clrOldBk = himl->clrBk;
1658     himl->clrBk = clrBk;
1659     return (clrOldBk);
1660 }
1661
1662
1663 BOOL32 WINAPI ImageList_SetDragCursorImage (
1664         HIMAGELIST himlDrag,
1665         INT32 iDrag,
1666         INT32 dxHotspot,
1667         INT32 dyHotspot)
1668 {
1669     FIXME (imagelist, "empty stub!\n");
1670
1671     return (FALSE);
1672 }
1673
1674
1675 #if 0
1676 BOOL32 WINAPI ImageList_SetFilter (
1677         HIMAGELIST himl, 
1678         INT32 iIndex, 
1679         INT32 iFilter)
1680 {
1681     FIXME (imagelist, "empty stub!\n");
1682
1683
1684 }
1685 #endif /* 0 */
1686
1687
1688 BOOL32 WINAPI ImageList_SetIconSize (
1689         HIMAGELIST himl, 
1690         INT32 cx, 
1691         INT32 cy)
1692 {
1693     INT32 nCount;
1694
1695     /* remove all images*/
1696     himl->cMaxImage  = himl->cInitial + himl->cGrow;
1697     himl->cCurImage  = 0;
1698     himl->cx         = cx;
1699     himl->cy         = cy;
1700
1701     /* initialize overlay mask indices */
1702     for (nCount = 0; nCount < MAX_OVERLAYIMAGE; nCount++)
1703         himl->nOvlIdx[nCount] = -1;
1704
1705     DeleteObject32 (himl->hbmImage);
1706     himl->hbmImage =
1707         CreateBitmap32 (himl->cMaxImage * himl->cx, himl->cy,
1708                         1, himl->uBitsPixel, NULL);
1709
1710     if (himl->hbmMask) {
1711         DeleteObject32 (himl->hbmMask);
1712         himl->hbmMask =
1713             CreateBitmap32 (himl->cMaxImage * himl->cx, himl->cy,
1714                             1, 1, NULL);
1715     }
1716
1717     return (TRUE);
1718 }
1719
1720
1721 BOOL32 WINAPI ImageList_SetImageCount (
1722         HIMAGELIST himl, 
1723         INT32 iImageCount)
1724 {
1725     HDC32     hdcImageList, hdcBitmap;
1726     HBITMAP32 hbmNewBitmap;
1727     INT32     nNewCount, nCopyCount;
1728
1729     if (himl == NULL) return (FALSE);
1730     if (himl->cCurImage <= iImageCount) return (FALSE);
1731     if (himl->cMaxImage > iImageCount) return (TRUE);
1732
1733     nNewCount = iImageCount + himl->cGrow;
1734     nCopyCount = _MIN(himl->cCurImage, iImageCount);
1735
1736     hdcImageList = CreateCompatibleDC32 (0);
1737     hdcBitmap = CreateCompatibleDC32 (0);
1738
1739     hbmNewBitmap = CreateBitmap32 (nNewCount * himl->cx, himl->cy,
1740                                    1, himl->uBitsPixel, NULL);
1741     if (hbmNewBitmap == 0)
1742     {
1743         SelectObject32 (hdcImageList, himl->hbmImage);
1744         SelectObject32 (hdcBitmap, hbmNewBitmap);
1745         BitBlt32 (hdcBitmap, 0, 0, nCopyCount * himl->cx, himl->cy,
1746                   hdcImageList, 0, 0, SRCCOPY);
1747         DeleteObject32 (himl->hbmImage);
1748         himl->hbmImage = hbmNewBitmap;
1749     }
1750     else
1751     {
1752         WARN (imagelist, "Could not create new image bitmap !\n");
1753     }
1754
1755     if (himl->hbmMask)
1756     {
1757         hbmNewBitmap = CreateBitmap32 (nNewCount * himl->cx, himl->cy,
1758                                        1, 1, NULL);
1759         if (hbmNewBitmap != 0)
1760         {
1761             SelectObject32 (hdcImageList, himl->hbmMask);
1762             SelectObject32 (hdcBitmap, hbmNewBitmap);
1763             BitBlt32 (hdcBitmap, 0, 0, nCopyCount * himl->cx, himl->cy,
1764                       hdcImageList, 0, 0, SRCCOPY);
1765             DeleteObject32 (himl->hbmMask);
1766             himl->hbmMask = hbmNewBitmap;
1767         }
1768         else
1769         {
1770             WARN (imagelist, "Could not create new mask bitmap!\n");
1771         }
1772     }
1773
1774     DeleteDC32 (hdcImageList);
1775     DeleteDC32 (hdcBitmap);
1776
1777     /* Update max image count and current image count */
1778     himl->cMaxImage = nNewCount;
1779     if (himl->cCurImage > nCopyCount)
1780         himl->cCurImage = nCopyCount;
1781
1782     return (TRUE);
1783 }
1784
1785
1786 BOOL32 WINAPI ImageList_SetOverlayImage (
1787         HIMAGELIST himl, 
1788         INT32 iImage, 
1789         INT32 iOverlay)
1790 {
1791     if ((iOverlay < 1) || (iOverlay > MAX_OVERLAYIMAGE)) return (FALSE);
1792     if ((iImage < 0) || (iImage > himl->cCurImage)) return (FALSE);
1793     
1794     himl->nOvlIdx[iOverlay - 1] = iImage;
1795     return (TRUE);
1796 }
1797
1798
1799 #if 0
1800 #if __IStream_INTERFACE_DEFINED__
1801 BOOL32 WINAPI ImageList_Write (
1802         HIMAGELIST himl, 
1803         LPSTREAM pstm)
1804 {
1805     FIXME (imagelist, "empty stub!\n");
1806
1807
1808     return (FALSE);
1809 }
1810 #endif  /* __IStream_INTERFACE_DEFINED__ */
1811 #endif  /* 0 */