Release 980628
[wine] / misc / imagelist.c
1 /*
2  *  ImageList implementation
3  *
4  *  Copyright 1998 Eric Kohl
5  *
6  *  TODO:
7  *    - Fix xBitmap and yBitmap in ImageList_DrawIndirect.
8  *    - Fix ILD_TRANSPARENT error in ImageList_DrawIndirect.
9  *    - Fix ImageList_GetIcon (might be a result of the
10  *      ILD_TRANSPARENT error in ImageList_DrawIndirect).
11  *    - Fix drag functions.
12  *    - Fix ImageList_Read and ImageList_Write.
13  *    - Add ImageList_SetFilter (undocumented).
14  *      BTW does anybody know anything about this function???
15  *        - It removes 12 Bytes from the stack (3 Parameters).
16  *        - First parameter SHOULD be a HIMAGELIST.
17  *        - Second parameter COULD be an index?????
18  *        - Third parameter.... ?????????????????????
19  *
20  *  Comments:
21  *    - ImageList_Draw, ImageList_DrawEx and ImageList_GetIcon use
22  *      ImageList_DrawIndirect. Since ImageList_DrawIndirect is still
23  *      partially imlemented, the functions mentioned above will be 
24  *      limited in functionality too.
25  */
26
27 /* This must be defined because the HIMAGELIST type is just a pointer
28  * to the _IMAGELIST data structure. But M$ does not want us to know
29  * anything about its contents. Applications just see a pointer to
30  * an empty structure. It's just to keep compatibility.
31  */
32 #define __WINE_IMAGELIST_C
33  
34 /* This must be defined until "GetIconInfo" is implemented completely.
35  * To do that the cursor and icon code in objects/cursoricon.c must
36  * be rewritten.
37  */
38 #define __GET_ICON_INFO_HACK__ 
39  
40 #include "windows.h"
41 #include "compobj.h"
42 #include "storage.h"
43 #include "imagelist.h"
44 #include "commctrl.h"
45 #include "debug.h"
46
47 #ifdef __GET_ICON_INFO_HACK__
48 #include "bitmap.h"
49 #endif
50
51
52 #define _MAX(a,b) (((a)>(b))?(a):(b))
53 #define _MIN(a,b) (((a)>(b))?(b):(a))
54
55 #define MAX_OVERLAYIMAGE 15
56
57
58 /* internal image list data used for Drag & Drop operations */
59
60 static HIMAGELIST himlInternalDrag = NULL;
61 static INT32      nInternalDragHotspotX = 0;
62 static INT32      nInternalDragHotspotY = 0;
63
64 static HWND32     hwndInternalDrag = 0;
65 static INT32      xInternalPos = 0;
66 static INT32      yInternalPos = 0;
67
68 static HDC32      hdcBackBuffer = 0;
69 static HBITMAP32  hbmBackBuffer = 0;
70
71
72 /*************************************************************************
73  * IMAGELIST_InternalExpandBitmaps [Internal] 
74  *
75  * Expands the bitmaps of an image list by the given number of images.
76  *
77  * PARAMS
78  *     himl        [I] image list handle
79  *     nImageCount [I] Number of images to add.
80  *
81  * RETURNS
82  *     nothing
83  *
84  * NOTES
85  *     This function can NOT be used to reduce the number of images.
86  */
87
88 static VOID
89 IMAGELIST_InternalExpandBitmaps (HIMAGELIST himl, INT32 nImageCount)
90 {
91     HDC32     hdcImageList, hdcBitmap;
92     HBITMAP32 hbmNewBitmap;
93     INT32     nNewWidth, nNewCount;
94
95     TRACE(imagelist, "Create expanded bitmaps!\n");
96
97     nNewCount = himl->cCurImage + nImageCount + himl->cGrow;
98     nNewWidth = nNewCount * himl->cx;
99
100     hdcImageList = CreateCompatibleDC32 (0);
101     hdcBitmap = CreateCompatibleDC32 (0);
102
103     hbmNewBitmap =
104         CreateBitmap32 (nNewWidth, himl->cy, 1, himl->uBitsPixel, NULL);
105     if (hbmNewBitmap == 0)
106         ERR (imagelist, "creating new image bitmap!\n");
107
108     SelectObject32 (hdcImageList, himl->hbmImage);
109     SelectObject32 (hdcBitmap, hbmNewBitmap);
110     BitBlt32 (hdcBitmap, 0, 0, himl->cCurImage * himl->cx, himl->cy,
111               hdcImageList, 0, 0, SRCCOPY);
112
113     DeleteObject32 (himl->hbmImage);
114     himl->hbmImage = hbmNewBitmap;
115
116     if (himl->hbmMask) {
117         hbmNewBitmap = 
118             CreateBitmap32 (nNewWidth, himl->cy, 1, himl->uBitsPixel, NULL);
119
120         if (hbmNewBitmap == 0)
121             ERR (imagelist, "creating new mask bitmap!");
122
123         SelectObject32 (hdcImageList, himl->hbmMask);
124         SelectObject32 (hdcBitmap, hbmNewBitmap);
125         BitBlt32 (hdcBitmap, 0, 0, himl->cCurImage * himl->cx, himl->cy,
126                   hdcImageList, 0, 0, SRCCOPY);
127         DeleteObject32 (himl->hbmMask);
128         himl->hbmMask = hbmNewBitmap;
129     }
130
131     himl->cMaxImage = nNewCount;
132
133     DeleteDC32 (hdcImageList);
134     DeleteDC32 (hdcBitmap);
135 }
136
137
138 /*************************************************************************
139  * ImageList_Add [COMCTL32.39]
140  *
141  * Add an image or images to an image list.
142  *
143  * PARAMS
144  *     himl     [I] image list handle
145  *     hbmImage [I] image bitmap handle
146  *     hbmMask  [I] mask bitmap handle
147  *
148  * RETURNS
149  *     Success: Index of the first new image.
150  *     Failure: -1
151  */
152
153 INT32 WINAPI
154 ImageList_Add (HIMAGELIST himl, HBITMAP32 hbmImage, HBITMAP32 hbmMask)
155 {
156     HDC32    hdcSrc, hdcDst;
157     INT32    nFirstIndex, nImageCount;
158     INT32    nStartX, nRunX, nRunY;
159     BITMAP32 bmp;
160
161     if (himl == NULL) return (-1);
162     if (hbmImage == 0) return (-1);
163
164     GetObject32A (hbmImage, sizeof(BITMAP32), (LPVOID)&bmp);
165     nImageCount = bmp.bmWidth / himl->cx;
166
167     if (himl->cCurImage + nImageCount >= himl->cMaxImage)
168         IMAGELIST_InternalExpandBitmaps (himl, nImageCount);
169
170     hdcSrc = CreateCompatibleDC32 (0);
171     hdcDst = CreateCompatibleDC32 (0);
172
173     SelectObject32 (hdcDst, himl->hbmImage);
174     SelectObject32 (hdcSrc, hbmImage);
175
176     BitBlt32 (hdcDst, himl->cCurImage * himl->cx, 0,
177               bmp.bmWidth, himl->cy, hdcSrc, 0, 0, SRCCOPY);
178           
179     if (himl->hbmMask) {
180         if (hbmMask) {
181             SelectObject32 (hdcDst, himl->hbmMask);
182             SelectObject32 (hdcSrc, hbmMask);
183             BitBlt32 (hdcDst, himl->cCurImage * himl->cx, 0,
184                       bmp.bmWidth, himl->cy, hdcSrc, 0, 0, SRCCOPY);
185
186             /* fix transparent areas of the image bitmap*/
187             SelectObject32 (hdcSrc, himl->hbmMask);
188             SelectObject32 (hdcDst, himl->hbmImage);
189             nStartX = himl->cCurImage * himl->cx;
190
191             for (nRunY = 0; nRunY < himl->cy; nRunY++) {
192                 for (nRunX = 0; nRunX < bmp.bmWidth; nRunX++) {
193                     if (GetPixel32 (hdcSrc, nStartX + nRunX, nRunY) !=
194                         RGB(0, 0, 0))
195                         SetPixel32 (hdcDst, nStartX + nRunX, nRunY, 
196                                     RGB(0, 0, 0));
197                 }
198             }
199         }
200         else {
201             /* create mask from the imagelist's background color */
202             SelectObject32 (hdcDst, himl->hbmMask);
203             SelectObject32 (hdcSrc, himl->hbmImage);
204             nStartX = himl->cCurImage * himl->cx;
205             for (nRunY = 0; nRunY < himl->cy; nRunY++) {
206                 for (nRunX = 0; nRunX < bmp.bmWidth; nRunX++) {
207                     if (GetPixel32 (hdcSrc, nStartX + nRunX, nRunY) ==
208                         himl->clrBk)
209                     {
210                         SetPixel32 (hdcSrc, nStartX + nRunX, nRunY, 
211                                     RGB(0, 0, 0));
212                         SetPixel32 (hdcDst, nStartX + nRunX, nRunY, 
213                                     RGB(255, 255, 255));
214                     }
215                     else
216                         SetPixel32 (hdcDst, nStartX + nRunX, nRunY, 
217                                     RGB(0, 0, 0));        
218                 }
219             }
220         }
221     }
222
223     DeleteDC32 (hdcSrc);
224     DeleteDC32 (hdcDst);
225
226     nFirstIndex = himl->cCurImage;
227     himl->cCurImage += nImageCount;
228
229     return (nFirstIndex);
230 }
231
232
233 /*************************************************************************
234  * ImageList_AddIcon [COMCTL32.40]
235  *
236  * Adds an icon to an image list.
237  *
238  * PARAMS
239  *     himl  [I] image list handle
240  *     hIcon [I] icon handle
241  *
242  * RETURNS
243  *     Success: index of the new image
244  *     Failure: -1
245  */
246
247 INT32 WINAPI
248 ImageList_AddIcon (HIMAGELIST himl, HICON32 hIcon)
249 {
250     return (ImageList_ReplaceIcon (himl, -1, hIcon));
251 }
252
253
254 /*************************************************************************
255  * ImageList_AddMasked [COMCTL32.41] 
256  *
257  * Adds an image or images to an image list and creates a mask from the
258  * specified bitmap using the mask color.
259  *
260  * PARAMS
261  *     himl     [I] image list handle.
262  *     hbmImage [I] image bitmap handle.
263  *     clrMask  [I] mask color.
264  *
265  * RETURNS
266  *     Success: Index of the first new image.
267  *     Failure: -1
268  */
269
270 INT32 WINAPI
271 ImageList_AddMasked (HIMAGELIST himl, HBITMAP32 hbmImage, COLORREF clrMask)
272 {
273     HDC32    hdcImageList, hdcImage, hdcMask;
274     INT32    nIndex, nImageCount;
275     BITMAP32 bmp;
276     INT32    nStartX, nRunX, nRunY;
277     COLORREF bkColor;
278
279     if (himl == NULL)
280         return (-1);
281
282     bkColor = (clrMask == CLR_NONE) ? himl->clrBk : clrMask;
283
284     GetObject32A (hbmImage, sizeof(BITMAP32), &bmp);
285     nImageCount = bmp.bmWidth / himl->cx;
286
287     if (himl->cCurImage + nImageCount >= himl->cMaxImage)
288         IMAGELIST_InternalExpandBitmaps (himl, nImageCount);
289
290     nIndex = himl->cCurImage;
291     himl->cCurImage += nImageCount;
292
293     hdcImageList = CreateCompatibleDC32 (0);
294     hdcImage = CreateCompatibleDC32 (0);
295
296     SelectObject32 (hdcImageList, himl->hbmImage);
297     SelectObject32 (hdcImage, hbmImage);
298     BitBlt32 (hdcImageList, nIndex * himl->cx, 0, bmp.bmWidth, himl->cy,
299               hdcImage, 0, 0, SRCCOPY);
300
301     if (himl->hbmMask) {
302         /* create Mask */
303         hdcMask = CreateCompatibleDC32 (0);
304         SelectObject32 (hdcMask, himl->hbmMask);
305         nStartX = nIndex * himl->cx;
306         for (nRunY = 0; nRunY < himl->cy; nRunY++) {
307             for (nRunX = 0; nRunX < bmp.bmWidth; nRunX++) {
308                 if (GetPixel32 (hdcImageList, nStartX + nRunX, nRunY) ==
309                     bkColor) {
310                     SetPixel32 (hdcImageList, nStartX + nRunX, nRunY,
311                                 RGB(0, 0, 0));
312                     SetPixel32 (hdcMask, nStartX + nRunX, nRunY,
313                                 RGB(255, 255, 255));
314                 }
315                 else
316                     SetPixel32 (hdcMask, nStartX + nRunX, nRunY, RGB(0, 0, 0));
317             }
318         }
319         DeleteDC32 (hdcMask);
320     }
321
322     DeleteDC32 (hdcImageList);
323     DeleteDC32 (hdcImage);
324   
325     return (nIndex);
326 }
327
328
329 /*************************************************************************
330  * ImageList_BeginDrag [COMCTL32.42] 
331  *
332  * Creates a temporary image list that contains one image. It will be used
333  * as a drag image.
334  *
335  * PARAMS
336  *     himlTrack [I] Handle of the source image list
337  *     iTrack    [I] Index of the drag image in the source image list
338  *     dxHotspot [I] X position of the hot spot of the drag image
339  *     dyHotspot [I] Y position of the hot spot of the drag image
340  *
341  * RETURNS
342  *     Success: TRUE
343  *     Failure: FALSE
344  */
345
346 BOOL32 WINAPI
347 ImageList_BeginDrag (HIMAGELIST himlTrack, INT32 iTrack,
348                      INT32 dxHotspot, INT32 dyHotspot)
349 {
350     HDC32 hdcSrc, hdcDst;
351
352     FIXME(imagelist, "partially implemented!\n");
353
354     if (himlTrack == NULL)
355         return (FALSE);
356
357     if (himlInternalDrag)
358         ImageList_EndDrag ();
359
360     himlInternalDrag =
361         ImageList_Create (himlTrack->cx, himlTrack->cy,
362                           himlTrack->flags, 1, 1);
363     if (himlInternalDrag == NULL) {
364         ERR(imagelist, "Error creating drag image list!\n");
365         return (FALSE);
366     }
367
368     nInternalDragHotspotX = dxHotspot;
369     nInternalDragHotspotY = dyHotspot;
370
371     hdcSrc = CreateCompatibleDC32 (0);
372     hdcDst = CreateCompatibleDC32 (0);
373
374     /* copy image */
375     SelectObject32 (hdcSrc, himlTrack->hbmImage);
376     SelectObject32 (hdcDst, himlInternalDrag->hbmImage);
377     StretchBlt32 (hdcDst, 0, 0, himlInternalDrag->cx, himlInternalDrag->cy, hdcSrc,
378                   iTrack * himlTrack->cx, 0, himlTrack->cx, himlTrack->cy, SRCCOPY);
379
380     /* copy mask */
381     SelectObject32 (hdcSrc, himlTrack->hbmMask);
382     SelectObject32 (hdcDst, himlInternalDrag->hbmMask);
383     StretchBlt32 (hdcDst, 0, 0, himlInternalDrag->cx, himlInternalDrag->cy, hdcSrc,
384                   iTrack * himlTrack->cx, 0, himlTrack->cx, himlTrack->cy, SRCCOPY);
385
386     DeleteDC32 (hdcSrc);
387     DeleteDC32 (hdcDst);
388
389     himlInternalDrag->cCurImage = 1;
390
391     return (TRUE);
392 }
393
394
395 /*************************************************************************
396  * ImageList_Copy [COMCTL32.43] 
397  *
398  *  Copies an image of the source image list to an image of the 
399  *  destination image list. Images can be copied or swapped.
400  *
401  * PARAMS
402  *     himlDst [I] destination image list handle.
403  *     iDst    [I] destination image index.
404  *     himlSrc [I] source image list handle
405  *     iSrc    [I] source image index
406  *     uFlags  [I] flags for the copy operation
407  *
408  * RETURNS
409  *     Success: TRUE
410  *     Failure: FALSE
411  *
412  * NOTES
413  *     Copying from one image list to another is possible. The original
414  *     implementation just copies or swapps within one image list.
415  *     Could this feature become a bug??? ;-)
416  */
417
418 BOOL32 WINAPI
419 ImageList_Copy (HIMAGELIST himlDst, INT32 iDst, HIMAGELIST himlSrc,
420                 INT32 iSrc, INT32 uFlags)
421 {
422     HDC32 hdcSrc, hdcDst;    
423
424     TRACE(imagelist, "iDst=%d  iSrc=%d\n", iDst, iSrc);
425
426     if ((himlSrc == NULL) || (himlDst == NULL)) return (FALSE);
427     if ((iDst < 0) || (iDst >= himlDst->cCurImage)) return (FALSE);
428     if ((iSrc < 0) || (iSrc >= himlSrc->cCurImage)) return (FALSE);
429
430     hdcSrc = CreateCompatibleDC32 (0);
431     if (himlDst == himlSrc)
432         hdcDst = hdcSrc;
433     else
434         hdcDst = CreateCompatibleDC32 (0);
435
436     if (uFlags & ILCF_SWAP) {
437         /* swap */
438         HBITMAP32 hbmTempImage, hbmTempMask;
439
440         /* create temporary bitmaps */
441         hbmTempImage = CreateBitmap32 (himlSrc->cx, himlSrc->cy, 1,
442                                        himlSrc->uBitsPixel, NULL);
443         hbmTempMask = CreateBitmap32 (himlSrc->cx, himlSrc->cy, 1,
444                                       himlSrc->uBitsPixel, NULL);
445
446         /* copy (and stretch) destination to temporary bitmaps.(save) */
447         /* image */
448         SelectObject32 (hdcSrc, himlDst->hbmImage);
449         SelectObject32 (hdcDst, hbmTempImage);
450         StretchBlt32 (hdcDst, 0, 0, himlSrc->cx, himlSrc->cy,
451                       hdcSrc, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
452                       SRCCOPY);
453         /* mask */
454         SelectObject32 (hdcSrc, himlDst->hbmMask);
455         SelectObject32 (hdcDst, hbmTempMask);
456         StretchBlt32 (hdcDst, 0, 0, himlSrc->cx, himlSrc->cy,
457                       hdcSrc, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
458                       SRCCOPY);
459
460         /* copy (and stretch) source to destination */
461         /* image */
462         SelectObject32 (hdcSrc, himlSrc->hbmImage);
463         SelectObject32 (hdcDst, himlDst->hbmImage);
464         StretchBlt32 (hdcDst, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
465                       hdcSrc, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
466                       SRCCOPY);
467         /* mask */
468         SelectObject32 (hdcSrc, himlSrc->hbmMask);
469         SelectObject32 (hdcDst, himlDst->hbmMask);
470         StretchBlt32 (hdcDst, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
471                       hdcSrc, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
472                       SRCCOPY);
473
474         /* copy (without stretching) temporary bitmaps to source (restore) */
475         /* image */
476         SelectObject32 (hdcSrc, hbmTempImage);
477         SelectObject32 (hdcDst, himlSrc->hbmImage);
478         BitBlt32 (hdcDst, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
479                   hdcSrc, 0, 0, SRCCOPY);
480         /* mask */
481         SelectObject32 (hdcSrc, hbmTempMask);
482         SelectObject32 (hdcDst, himlSrc->hbmMask);
483         BitBlt32 (hdcDst, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
484                   hdcSrc, 0, 0, SRCCOPY);
485
486         /* delete temporary bitmaps */
487         DeleteObject32 (hbmTempMask);
488         DeleteObject32 (hbmTempImage);
489     }
490     else {
491         /* copy image */
492         SelectObject32 (hdcSrc, himlSrc->hbmImage);
493         if (himlSrc == himlDst)
494             hdcDst = hdcSrc;
495         else
496             SelectObject32 (hdcDst, himlDst->hbmImage);
497         StretchBlt32 (hdcDst, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
498                       hdcSrc, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
499                       SRCCOPY);
500
501         /* copy mask */
502         SelectObject32 (hdcSrc, himlSrc->hbmMask);
503         if (himlSrc == himlDst)
504             hdcDst = hdcSrc;
505         else
506             SelectObject32 (hdcDst, himlDst->hbmMask);
507         StretchBlt32 (hdcDst, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
508                       hdcSrc, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
509                       SRCCOPY);
510     }
511
512     DeleteDC32 (hdcSrc);
513     if (himlSrc != himlDst)
514         DeleteDC32 (hdcDst);
515
516     return (TRUE);
517 }
518
519
520 /*************************************************************************
521  * ImageList_Create [COMCTL32.44] 
522  *
523  * Creates a new image list.
524  *
525  * PARAMS
526  *     cx       [I] image height
527  *     cy       [I] image width
528  *     flags    [I] creation flags
529  *     cInitial [I] initial number of images in the image list
530  *     cGrow    [I] number of images by which image list grows
531  *
532  * RETURNS
533  *     Success: Handle of the created image list
534  *     Failure: 0
535  */
536
537 HIMAGELIST WINAPI
538 ImageList_Create (INT32 cx, INT32 cy, UINT32 flags,
539                   INT32 cInitial, INT32 cGrow)
540 {
541     HIMAGELIST himl;
542     HDC32      hdc;
543     INT32      nCount;
544     HBITMAP32  hbmTemp;
545     WORD       aBitBlend25[16] = 
546         {0x7777, 0xDDDD, 0x7777, 0xDDDD, 0x7777, 0xDDDD, 0x7777, 0xDDDD,
547          0x7777, 0xDDDD, 0x7777, 0xDDDD, 0x7777, 0xDDDD, 0x7777, 0xDDDD};
548     WORD       aBitBlend50[16] =
549         {0x5555, 0xAAAA, 0x5555, 0xAAAA, 0x5555, 0xAAAA, 0x5555, 0xAAAA,
550          0x5555, 0xAAAA, 0x5555, 0xAAAA, 0x5555, 0xAAAA, 0x5555, 0xAAAA};
551
552     himl = (HIMAGELIST)LocalAlloc32 (LMEM_FIXED | LMEM_ZEROINIT,
553                                      sizeof(struct _IMAGELIST));
554     if (!himl)
555         return (NULL);
556     himl->cx = cx;
557     himl->cy = cy;
558     himl->flags = flags;
559     himl->cMaxImage = cInitial + cGrow;
560     himl->cInitial = cInitial;
561     himl->cGrow = cGrow;
562     himl->cCurImage = 0;
563     himl->clrBk = CLR_NONE;
564
565     /* initialize overlay mask indices */
566     for (nCount = 0; nCount <= MAX_OVERLAYIMAGE; nCount++)
567         himl->nOvlIdx[nCount] = -1;
568
569     hdc = CreateCompatibleDC32 (0);
570     himl->uBitsPixel = (UINT32)GetDeviceCaps32 (hdc, BITSPIXEL);
571     DeleteDC32 (hdc);
572
573     TRACE(imagelist, "Image: %d Bits per Pixel\n", himl->uBitsPixel);
574
575     himl->hbmImage =
576         CreateBitmap32 (himl->cx * himl->cMaxImage, himl->cy,
577                         1, himl->uBitsPixel, NULL);
578     if (himl->hbmImage == 0) {
579         ERR(imagelist, "Error creating image bitmap!\n");
580         return (0);
581     }
582
583     if (himl->flags & ILC_MASK) {
584         himl->hbmMask = CreateBitmap32 (himl->cx * himl->cMaxImage, himl->cy,
585                                         1, himl->uBitsPixel, NULL);
586         if (himl->hbmMask == 0) {
587             ERR(imagelist, "Error creating mask bitmap!\n");
588             if (himl->hbmImage)
589                 DeleteObject32 (himl->hbmImage);
590             return (0);
591         }
592     }
593     else
594         himl->hbmMask = 0;
595
596     /* create blending brushes */
597     hbmTemp = CreateBitmap32 (16, 16, 1, 1, &aBitBlend25);
598     himl->hbrBlend25 = CreatePatternBrush32 (hbmTemp);
599     DeleteObject32 (hbmTemp);
600
601     hbmTemp = CreateBitmap32 (16, 16, 1, 1, &aBitBlend50);
602     himl->hbrBlend50 = CreatePatternBrush32 (hbmTemp);
603     DeleteObject32 (hbmTemp);
604
605     return (himl);    
606 }
607
608
609 /*************************************************************************
610  * ImageList_Destroy [COMCTL32.45] 
611  *
612  * Destroys an image list.
613  *
614  * PARAMS
615  *     himl [I] image list handle
616  *
617  * RETURNS
618  *     Success: TRUE
619  *     Failure: FALSE
620  */
621
622 BOOL32 WINAPI
623 ImageList_Destroy (HIMAGELIST himl)
624
625     if (himl == NULL) return (FALSE);
626
627     if (himl->hbmImage)
628         DeleteObject32 (himl->hbmImage);
629     if (himl->hbmMask)
630         DeleteObject32 (himl->hbmMask);
631         
632     LocalFree32 ((HLOCAL32)himl);
633     return (TRUE);
634 }
635
636
637 /*************************************************************************
638  * ImageList_DragEnter [COMCTL32.46] 
639  *
640  * Locks window update and displays the drag image at the given position.
641  *
642  * PARAMS
643  *     hwndLock [I] handle of the window that owns the drag image.
644  *     x        [I] X position of the drag image.
645  *     y        [I] Y position of the drag image.
646  *
647  * RETURNS
648  *     Success: TRUE
649  *     Failure: FALSE
650  *
651  * NOTES
652  *     The position of the drag image is relative to the window, not
653  *     the client area.
654  */
655
656 BOOL32 WINAPI
657 ImageList_DragEnter (HWND32 hwndLock, INT32 x, INT32 y)
658 {
659     if (himlInternalDrag == NULL) return (FALSE);
660
661     if (hwndLock)
662         hwndInternalDrag = hwndLock;
663     else
664         hwndInternalDrag = GetDesktopWindow32 ();
665
666     xInternalPos = x;
667     yInternalPos = y;
668
669     hdcBackBuffer = CreateCompatibleDC32 (0);
670     hbmBackBuffer = CreateCompatibleBitmap32 (hdcBackBuffer,
671                 himlInternalDrag->cx, himlInternalDrag->cy);
672
673     ImageList_DragShowNolock (TRUE);
674
675     return (FALSE);
676 }
677
678
679 /*************************************************************************
680  * ImageList_DragLeave [COMCTL32.47] 
681  *
682  * Unlocks window update and hides the drag image.
683  *
684  * PARAMS
685  *     hwndLock [I] handle of the window that owns the drag image.
686  *
687  * RETURNS
688  *     Success: TRUE
689  *     Failure: FALSE
690  */
691
692 BOOL32 WINAPI
693 ImageList_DragLeave (HWND32 hwndLock)
694 {
695     if (hwndLock)
696         hwndInternalDrag = hwndLock;
697     else
698         hwndInternalDrag = GetDesktopWindow32 ();
699
700     ImageList_DragShowNolock (FALSE);
701
702     DeleteDC32 (hdcBackBuffer);
703     DeleteObject32 (hbmBackBuffer);
704
705     return (TRUE);
706 }
707
708
709 /*************************************************************************
710  * ImageList_DragMove [COMCTL32.48] 
711  *
712  * Moves the drag image.
713  *
714  * PARAMS
715  *     x [I] X position of the drag image.
716  *     y [I] Y position of the drag image.
717  *
718  * RETURNS
719  *     Success: TRUE
720  *     Failure: FALSE
721  *
722  * NOTES
723  *     The position of the drag image is relative to the window, not
724  *     the client area.
725  */
726
727 BOOL32 WINAPI
728 ImageList_DragMove (INT32 x, INT32 y)
729 {
730     ImageList_DragShowNolock (FALSE);
731
732     xInternalPos = x;
733     yInternalPos = y;
734
735     ImageList_DragShowNolock (TRUE);
736
737     return (FALSE);
738 }
739
740
741 /*************************************************************************
742  * ImageList_DragShowNolock [COMCTL32.49] 
743  *
744  * Shows or hides the drag image.
745  *
746  * PARAMS
747  *     bShow [I] TRUE shows the drag image, FALSE hides it.
748  *
749  * RETURNS
750  *     Success: TRUE
751  *     Failure: FALSE
752  *
753  * FIXME
754  *     semi-stub.
755  */
756
757 BOOL32 WINAPI
758 ImageList_DragShowNolock (BOOL32 bShow)
759 {
760     HDC32 hdcDrag;
761
762     FIXME (imagelist, "semi-stub!\n");
763     TRACE (imagelist, "bShow=0x%X!\n", bShow);
764
765     hdcDrag = GetDCEx32 (hwndInternalDrag, 0,
766                          DCX_WINDOW | DCX_CACHE | DCX_LOCKWINDOWUPDATE);
767
768     if (bShow) {
769         /* show drag image */
770
771         /* save background */
772
773         /* draw drag image */
774
775     }
776     else {
777         /* hide drag image */
778
779         /* restore background */
780
781     }
782
783     ReleaseDC32 (hwndInternalDrag, hdcDrag);
784
785     return (FALSE);
786 }
787
788
789 /*************************************************************************
790  * ImageList_Draw [COMCTL32.50] Draws an image.
791  *
792  * PARAMS
793  *     himl   [I] image list handle
794  *     i      [I] image index
795  *     hdc    [I] display context handle
796  *     x      [I] x position
797  *     y      [I] y position
798  *     fStyle [I] drawing flags
799  *
800  * RETURNS
801  *     Success: TRUE
802  *     Failure: FALSE
803  *
804  * NOTES
805  *     Calls ImageList_DrawIndirect.
806  *
807  * SEE
808  *     ImageList_DrawIndirect.
809  */
810
811 BOOL32 WINAPI
812 ImageList_Draw (HIMAGELIST himl, INT32 i, HDC32 hdc,
813                 INT32 x, INT32 y, UINT32 fStyle)
814 {
815     IMAGELISTDRAWPARAMS imldp;
816
817     imldp.cbSize  = sizeof(IMAGELISTDRAWPARAMS);
818     imldp.himl    = himl;
819     imldp.i       = i;
820     imldp.hdcDst  = hdc,
821     imldp.x       = x;
822     imldp.y       = y;
823     imldp.cx      = 0;
824     imldp.cy      = 0;
825     imldp.xBitmap = 0;
826     imldp.yBitmap = 0;
827     imldp.rgbBk   = CLR_DEFAULT;
828     imldp.rgbFg   = CLR_DEFAULT;
829     imldp.fStyle  = fStyle;
830     imldp.dwRop   = 0;
831
832     return (ImageList_DrawIndirect (&imldp));
833 }
834
835
836 /*************************************************************************
837  * ImageList_DrawEx [COMCTL32.51]
838  *
839  * Draws an image and allows to use extended drawing features.
840  *
841  * PARAMS
842  *     himl   [I] image list handle
843  *     i      [I] image index
844  *     hdc    [I] device context handle
845  *     x      [I] X position
846  *     y      [I] Y position
847  *     xOffs  [I] X offset
848  *     yOffs  [I] Y offset
849  *     rgbBk  [I] background color
850  *     rgbFg  [I] foreground color
851  *     fStyle [I] drawing flags
852  *
853  * RETURNS
854  *     Success: TRUE
855  *     Failure: FALSE
856  *
857  * NOTES
858  *     Calls ImageList_DrawIndirect.
859  *
860  * SEE
861  *     ImageList_DrawIndirect.
862  */
863
864 BOOL32 WINAPI
865 ImageList_DrawEx (HIMAGELIST himl, INT32 i, HDC32 hdc, INT32 x, INT32 y,
866                   INT32 dx, INT32 dy, COLORREF rgbBk, COLORREF rgbFg,
867                   UINT32 fStyle)
868 {
869     IMAGELISTDRAWPARAMS imldp;
870
871     imldp.cbSize  = sizeof(IMAGELISTDRAWPARAMS);
872     imldp.himl    = himl;
873     imldp.i       = i;
874     imldp.hdcDst  = hdc,
875     imldp.x       = x;
876     imldp.y       = y;
877     imldp.cx      = dx;
878     imldp.cy      = dy;
879     imldp.xBitmap = 0;
880     imldp.yBitmap = 0;
881     imldp.rgbBk   = rgbBk;
882     imldp.rgbFg   = rgbFg;
883     imldp.fStyle  = fStyle;
884     imldp.dwRop   = 0;
885
886     return (ImageList_DrawIndirect (&imldp));
887 }
888
889
890 /*************************************************************************
891  * ImageList_DrawIndirect [COMCTL32.52] 
892  *
893  * Draws an image using ...
894  *
895  * PARAMS
896  *     pimldp [I] pointer to IMAGELISTDRAWPARAMS structure.
897  *
898  * RETURNS
899  *     Success: TRUE
900  *     Failure: FALSE
901  */
902
903 BOOL32 WINAPI
904 ImageList_DrawIndirect (IMAGELISTDRAWPARAMS *pimldp)
905 {
906     HIMAGELIST himlLocal;
907     HDC32      hdcImageList, hdcTempImage;
908     HBITMAP32  hbmTempImage;
909     HBRUSH32   hBrush, hOldBrush;
910     INT32      cx, cy;
911     INT32      nOvlIdx;
912     COLORREF   clrBlend;
913     BOOL32     bImage;       /* draw image ? */
914     BOOL32     bImageTrans;  /* draw image transparent ? */
915     BOOL32     bMask;        /* draw mask ? */
916     BOOL32     bMaskTrans;   /* draw mask transparent ? */
917     BOOL32     bBlend25;
918     BOOL32     bBlend50;
919
920     if (pimldp == NULL) return (FALSE);
921     if (pimldp->cbSize < sizeof(IMAGELISTDRAWPARAMS)) return (FALSE);
922     if (pimldp->himl == NULL) return (FALSE);
923     if ((pimldp->i < 0) || (pimldp->i >= pimldp->himl->cCurImage))
924         return (FALSE);
925
926     himlLocal = pimldp->himl;
927
928     cx = (pimldp->cx == 0) ? himlLocal->cx : pimldp->cx;
929     cy = (pimldp->cy == 0) ? himlLocal->cy : pimldp->cy;
930
931     /* ILD_NORMAL state */
932     bImage      = TRUE;
933     bImageTrans = FALSE;
934     bMask       = FALSE;
935     bMaskTrans  = FALSE;
936     bBlend25    = FALSE;
937     bBlend50    = FALSE;
938     if ((himlLocal->clrBk == CLR_NONE) && (himlLocal->hbmMask))
939     {
940         bImageTrans = TRUE;
941         bMask = TRUE;
942         bMaskTrans = TRUE;
943     }
944     
945     /* ILD_IMAGE state (changes) */
946     if (pimldp->fStyle & ILD_IMAGE)
947     {
948         bMask = FALSE;
949         bImage = TRUE;
950         bImageTrans = FALSE;
951     }
952     
953     /* ILD_MASK state (changes) */
954     if ((pimldp->fStyle & ILD_MASK) && (himlLocal->hbmMask))
955     {
956         bMask  = TRUE;
957         bMaskTrans = FALSE;
958         bImage = FALSE;
959     }
960     if ((pimldp->fStyle & ILD_TRANSPARENT) && (himlLocal->hbmMask))
961     {
962         bMaskTrans = TRUE;
963         bImageTrans = TRUE;
964     }
965     if ((himlLocal->clrBk == CLR_NONE) && (himlLocal->hbmMask))
966         bMaskTrans = TRUE;
967
968     if (pimldp->fStyle & ILD_BLEND50)
969         bBlend50 = TRUE;
970     else if (pimldp->fStyle & ILD_BLEND25)
971         bBlend25 = TRUE;
972
973     hdcImageList = CreateCompatibleDC32 (0);
974
975     if (bMask)
976     {
977         /* draw the mask */
978         SelectObject32 (hdcImageList, himlLocal->hbmMask);
979         BitBlt32 (pimldp->hdcDst, pimldp->x, pimldp->y, cx, cy,
980                   hdcImageList, himlLocal->cx * pimldp->i, 0,
981                   bMaskTrans ? SRCAND : SRCCOPY);
982     }
983
984     if (bImage)
985     {
986         /* draw the image */
987         SelectObject32 (hdcImageList, himlLocal->hbmImage);
988
989         if (!bImageTrans)
990         {
991             hBrush = CreateSolidBrush32 (himlLocal->clrBk);
992             hOldBrush = SelectObject32 (pimldp->hdcDst, hBrush);
993             PatBlt32 (pimldp->hdcDst, pimldp->x, pimldp->y,
994                       cx, cy, PATCOPY);
995             DeleteObject32 (SelectObject32 (pimldp->hdcDst, hOldBrush));
996         }
997
998         BitBlt32 (pimldp->hdcDst, pimldp->x, pimldp->y, cx, cy,
999                   hdcImageList, himlLocal->cx * pimldp->i, 0,
1000                   SRCPAINT);
1001
1002         if (bBlend25 || bBlend50)
1003         {
1004             if (pimldp->rgbFg == CLR_DEFAULT)
1005                 clrBlend = GetSysColor32 (COLOR_HIGHLIGHT);
1006             else
1007                 clrBlend = pimldp->rgbFg;
1008
1009             hdcTempImage = CreateCompatibleDC32 (0);
1010             hbmTempImage = CreateBitmap32 (himlLocal->cx, himlLocal->cy,
1011                                            1, himlLocal->uBitsPixel, NULL);
1012             SelectObject32 (hdcTempImage, hbmTempImage);
1013
1014
1015             /* mask */
1016             SelectObject32 (hdcTempImage,
1017                             bBlend50 ? himlLocal->hbrBlend50 : himlLocal->hbrBlend25);
1018             PatBlt32 (hdcTempImage, 0, 0, himlLocal->cx, himlLocal->cy, PATCOPY);
1019
1020             SelectObject32 (hdcImageList, himlLocal->hbmMask);
1021             BitBlt32 (hdcTempImage, 0, 0, himlLocal->cx,
1022                       himlLocal->cy, hdcImageList, 
1023                       pimldp->i * himlLocal->cx, 0, SRCPAINT);
1024
1025             BitBlt32 (pimldp->hdcDst, pimldp->x, pimldp->y, cx, cy,
1026                       hdcTempImage, 0, 0, SRCAND);
1027
1028             /* fill */
1029             hBrush = CreateSolidBrush32 (clrBlend);
1030             SelectObject32 (hdcTempImage, hBrush);
1031             PatBlt32 (hdcTempImage, 0, 0, himlLocal->cx, himlLocal->cy, PATCOPY);
1032             DeleteObject32 (hBrush);
1033
1034             SelectObject32 (hdcTempImage,
1035                             bBlend50 ? himlLocal->hbrBlend50 : himlLocal->hbrBlend25);
1036             PatBlt32 (hdcTempImage, 0, 0, himlLocal->cx, himlLocal->cy, 0x0A0329);
1037
1038             SelectObject32 (hdcImageList, himlLocal->hbmMask);
1039             BitBlt32 (hdcTempImage, 0, 0, himlLocal->cx,
1040                       himlLocal->cy, hdcImageList, 
1041                       pimldp->i * himlLocal->cx, 0, SRCPAINT);
1042
1043             BitBlt32 (pimldp->hdcDst, pimldp->x, pimldp->y, cx, cy,
1044                       hdcTempImage, 0, 0, SRCPAINT);
1045
1046             DeleteObject32 (hbmTempImage);
1047             DeleteDC32 (hdcTempImage);
1048         }
1049     }   
1050
1051     /* Draw overlay image */
1052     if (pimldp->fStyle & 0x0700) {
1053         nOvlIdx = (pimldp->fStyle & 0x0700) >> 8;
1054         if ((nOvlIdx >= 1) && (nOvlIdx <= MAX_OVERLAYIMAGE)) {
1055             nOvlIdx = pimldp->himl->nOvlIdx[nOvlIdx - 1];
1056             if ((nOvlIdx >= 0) && (nOvlIdx <= pimldp->himl->cCurImage)) {
1057                 if (pimldp->himl->hbmMask) {  
1058                     SelectObject32 (hdcImageList, pimldp->himl->hbmMask);
1059                     BitBlt32 (pimldp->hdcDst, pimldp->x, pimldp->y, cx, cy,
1060                               hdcImageList, pimldp->himl->cx * nOvlIdx, 0,
1061                               SRCAND);
1062                 }  
1063                 SelectObject32 (hdcImageList, pimldp->himl->hbmImage);
1064                 BitBlt32 (pimldp->hdcDst, pimldp->x, pimldp->y,
1065                           cx, cy, hdcImageList,
1066                           pimldp->himl->cx * nOvlIdx, 0, SRCPAINT);
1067             }
1068         }
1069     }
1070
1071     DeleteDC32 (hdcImageList);
1072   
1073     return (TRUE);
1074 }
1075
1076
1077 /*************************************************************************
1078  * ImageList_Duplicate [COMCTL32.53] Duplicates an image list.
1079  *
1080  * PARAMS
1081  *     himlSrc [I] source image list handle
1082  *
1083  * RETURNS
1084  *     Success: Handle of duplicated image list.
1085  *     Failure: NULL
1086  */
1087
1088 HIMAGELIST WINAPI
1089 ImageList_Duplicate (HIMAGELIST himlSrc)
1090 {
1091     HIMAGELIST himlDst;
1092     HDC32 hdcSrc, hdcDst;
1093
1094     if (himlSrc == NULL) {
1095         ERR (imagelist, "Invalid image list handle!\n");
1096         return (NULL);
1097     }
1098
1099     himlDst = ImageList_Create (himlSrc->cx, himlSrc->cy, himlSrc->flags,
1100                                 himlSrc->cInitial, himlSrc->cGrow);
1101
1102     if (himlDst)
1103     {
1104         hdcSrc = CreateCompatibleDC32 (0);
1105         hdcDst = CreateCompatibleDC32 (0);
1106         SelectObject32 (hdcSrc, himlSrc->hbmImage);
1107         SelectObject32 (hdcDst, himlDst->hbmImage);
1108         BitBlt32 (hdcDst, 0, 0, himlSrc->cCurImage * himlSrc->cx, himlSrc->cy,
1109                   hdcSrc, 0, 0, SRCCOPY);
1110
1111         if (himlDst->hbmMask)
1112         {
1113             SelectObject32 (hdcSrc, himlSrc->hbmMask);
1114             SelectObject32 (hdcDst, himlDst->hbmMask);
1115             BitBlt32 (hdcDst, 0, 0, himlSrc->cCurImage * himlSrc->cx,
1116                       himlSrc->cy, hdcSrc, 0, 0, SRCCOPY);
1117         }
1118
1119         DeleteDC32 (hdcDst);
1120         DeleteDC32 (hdcSrc);
1121     }
1122
1123     return (himlDst);
1124 }
1125
1126
1127 /*************************************************************************
1128  * ImageList_EndDrag [COMCTL32.54] Finishes a drag operation.
1129  *
1130  * Finishes a drag operation.
1131  *
1132  * PARAMS
1133  *     no Parameters
1134  *
1135  * RETURNS
1136  *     Success: TRUE
1137  *     Failure: FALSE
1138  *
1139  * BUGS
1140  *     semi-stub.
1141  */
1142
1143 BOOL32 WINAPI
1144 ImageList_EndDrag (VOID)
1145 {
1146     FIXME (imagelist, "semi-stub!\n");
1147
1148     if (himlInternalDrag)
1149     {
1150
1151         ImageList_Destroy (himlInternalDrag);
1152         himlInternalDrag = NULL;
1153
1154         nInternalDragHotspotX = 0;
1155         nInternalDragHotspotY = 0;
1156
1157     }
1158
1159     return (TRUE);
1160 }
1161
1162
1163 /*************************************************************************
1164  * ImageList_GetBkColor [COMCTL32.55]
1165  *
1166  * Returns the background color of an image list.
1167  *
1168  * PARAMS
1169  *     himl [I] Image list handle.
1170  *
1171  * RETURNS
1172  *     Success: background color
1173  *     Failure: CLR_NONE
1174  */
1175
1176 COLORREF WINAPI
1177 ImageList_GetBkColor (HIMAGELIST himl)
1178 {
1179     if (himl == NULL)
1180         return CLR_NONE;
1181
1182     return (himl->clrBk);
1183 }
1184
1185
1186 /*************************************************************************
1187  * ImageList_GetDragImage [COMCTL32.56]
1188  *
1189  * Returns the handle to the internal drag image list.
1190  *
1191  * PARAMS
1192  *     ppt        [O] Pointer to the drag position. Can be NULL.
1193  *     pptHotspot [O] Pointer to the position of the hot spot. Can be NULL.
1194  *
1195  * RETURNS
1196  *     Success: Handle of the drag image list.
1197  *     Failure: NULL.
1198  *
1199  * BUGS
1200  *     semi-stub.
1201  */
1202
1203 HIMAGELIST WINAPI
1204 ImageList_GetDragImage (POINT32 *ppt, POINT32 *pptHotspot)
1205 {
1206     FIXME (imagelist, "semi-stub!\n");
1207
1208     if (himlInternalDrag)
1209         return (himlInternalDrag);
1210
1211     return (NULL);
1212 }
1213
1214
1215 /*************************************************************************
1216  * ImageList_GetIcon [COMCTL32.57] 
1217  *
1218  * Creates an icon from a masked image of an image list.
1219  *
1220  * PARAMS
1221  *     himl  [I] image list handle
1222  *     i     [I] image index
1223  *     flags [I] drawing style flags
1224  *
1225  * RETURNS
1226  *     Success: icon handle
1227  *     Failure: NULL
1228  */
1229
1230 HICON32 WINAPI
1231 ImageList_GetIcon (HIMAGELIST himl, INT32 i, UINT32 fStyle)
1232 {
1233     ICONINFO ii;
1234     HICON32  hIcon;
1235     HDC32    hdc;
1236     INT32    nWidth, nHeight;
1237
1238     if (himl == NULL) return 0;
1239     if ((i < 0) || (i >= himl->cCurImage)) return 0;
1240
1241     nWidth = GetSystemMetrics32 (SM_CXICON);
1242     nHeight = GetSystemMetrics32 (SM_CYICON);
1243
1244     ii.fIcon = TRUE;
1245     ii.xHotspot = 0;
1246     ii.yHotspot = 0;
1247     ii.hbmMask  = CreateBitmap32 (nWidth, nHeight, 1, 1, NULL);
1248     ii.hbmColor = CreateBitmap32 (nWidth, nHeight, 1, 1, NULL);
1249
1250     hdc = CreateCompatibleDC32(0);
1251
1252     /* draw image*/
1253     SelectObject32 (hdc, ii.hbmColor);
1254     PatBlt32 (hdc, 0, 0, nWidth, nHeight, BLACKNESS);
1255     ImageList_Draw (himl, i, hdc, 0, 0, fStyle | ILD_TRANSPARENT);
1256
1257     /* draw mask*/
1258     SelectObject32 (hdc, ii.hbmMask);
1259     PatBlt32 (hdc, 0, 0, nWidth, nHeight, WHITENESS);
1260     ImageList_Draw (himl, i, hdc, 0, 0, fStyle | ILD_MASK);
1261
1262     hIcon = CreateIconIndirect (&ii);    
1263
1264     DeleteDC32 (hdc);
1265     DeleteObject32 (ii.hbmMask);
1266     DeleteObject32 (ii.hbmColor);
1267
1268     return (hIcon);
1269 }
1270
1271
1272 /*************************************************************************
1273  * ImageList_GetIconSize [COMCTL32.58]
1274  *
1275  * Retrieves the size of an image in an image list.
1276  *
1277  * PARAMS
1278  *     himl [I] image list handle
1279  *     cx   [O] pointer to the image width.
1280  *     cy   [O] pointer to the image height.
1281  *
1282  * RETURNS
1283  *     Success: TRUE
1284  *     Failure: FALSE
1285  *
1286  * NOTES
1287  *     All images in an image list have the same size.
1288  */
1289
1290 BOOL32 WINAPI
1291 ImageList_GetIconSize (HIMAGELIST himl, INT32 *cx, INT32 *cy)
1292 {
1293
1294     if (himl == NULL) return (FALSE);
1295
1296     if (cx)
1297         *cx = himl->cx;
1298     
1299     if (cy)
1300         *cy = himl->cy;
1301     return (TRUE);
1302 }
1303
1304
1305 /*************************************************************************
1306  * ImageList_GetImageCount [COMCTL32.59]
1307  *
1308  * Returns the number of images in an image list.
1309  *
1310  * PARAMS
1311  *     himl [I] image list handle.
1312  *
1313  * RETURNS
1314  *     Success: Number of images.
1315  *     Failure: 0
1316  */
1317
1318 INT32 WINAPI
1319 ImageList_GetImageCount (HIMAGELIST himl)
1320 {
1321     if (himl == NULL)
1322         return 0;
1323
1324     return (himl->cCurImage);
1325 }
1326
1327
1328 /*************************************************************************
1329  * ImageList_GetImageInfo [COMCTL32.60]
1330  *
1331  * Returns information about an image in an image list.
1332  *
1333  * PARAMS
1334  *     himl       [I] image list handle.
1335  *     i          [I] image index
1336  *     pImageInfo [O] pointer to the image information.
1337  *
1338  * RETURNS
1339  *     Success: TRUE
1340  *     Failure: FALSE
1341  */
1342
1343 BOOL32 WINAPI
1344 ImageList_GetImageInfo (HIMAGELIST himl, INT32 i, IMAGEINFO *pImageInfo)
1345 {
1346     if ((himl == NULL) || (pImageInfo == NULL)) return (FALSE);
1347     if ((i < 0) || (i >= himl->cCurImage)) return (FALSE);
1348
1349     pImageInfo->hbmImage = himl->hbmImage;
1350     pImageInfo->hbmMask  = himl->hbmMask;
1351     
1352     pImageInfo->rcImage.top    = 0;
1353     pImageInfo->rcImage.bottom = himl->cy;
1354     pImageInfo->rcImage.left   = i * himl->cx;
1355     pImageInfo->rcImage.right  = (i+1) * himl->cx;
1356     
1357     return (TRUE);
1358 }
1359
1360
1361 /*************************************************************************
1362  * ImageList_GetImageRect [COMCTL32.61] 
1363  *
1364  * Retrieves the rectangle of the specified image in an image list.
1365  *
1366  * PARAMS
1367  *     himl   [I] image list handle
1368  *     i      [I] image index
1369  *     lpRect [O] pointer to the image rectangle
1370  *
1371  * RETURNS
1372  *    Success: TRUE
1373  *    Failure: FALSE
1374  *
1375  * NOTES
1376  *    This is an UNDOCUMENTED function!!!
1377  */
1378
1379 BOOL32 WINAPI
1380 ImageList_GetImageRect (HIMAGELIST himl, INT32 i, LPRECT32 lpRect)
1381 {
1382     if ((himl == NULL) || (lpRect == NULL)) return (FALSE);
1383     if ((i < 0) || (i >= himl->cCurImage)) return (FALSE);
1384
1385     lpRect->left = i * himl->cx;
1386     lpRect->top = 0;
1387     lpRect->right = lpRect->left + himl->cx;
1388     lpRect->bottom = himl->cy;
1389
1390     return (TRUE);
1391 }
1392
1393
1394 /*************************************************************************
1395  * ImageList_LoadImage32A [COMCTL32.62][COMCTL32.63]
1396  *
1397  * Creates an image list from a bitmap, icon or cursor.
1398  *
1399  * PARAMS
1400  *     hi      [I] instance handle
1401  *     lpbmp   [I] name or id of the image
1402  *     cx      [I] width of each image
1403  *     cGrow   [I] number of images to expand
1404  *     clrMask [I] mask color
1405  *     uType   [I] type of image to load
1406  *     uFlags  [I] loading flags
1407  *
1408  * RETURNS
1409  *     Success: handle of the loaded image
1410  *     Failure: NULL
1411  *
1412  * SEE
1413  *     LoadImage ()
1414  */
1415
1416 HIMAGELIST WINAPI
1417 ImageList_LoadImage32A (HINSTANCE32 hi, LPCSTR lpbmp, INT32 cx, INT32 cGrow,
1418                         COLORREF clrMask, UINT32 uType, UINT32 uFlags)
1419 {
1420     HIMAGELIST himl = NULL;
1421     HANDLE32   handle;
1422     INT32      nImageCount;
1423
1424     handle = LoadImage32A (hi, lpbmp, uType, 0, 0, uFlags);
1425     if (!handle) return (NULL);
1426
1427     if (uType == IMAGE_BITMAP) {
1428         BITMAP32 bmp;
1429         GetObject32A (handle, sizeof(BITMAP32), &bmp);
1430         nImageCount = bmp.bmWidth / cx;
1431
1432         himl = ImageList_Create (cx, bmp.bmHeight, ILC_MASK | ILC_COLOR,
1433                                  nImageCount, cGrow);
1434         ImageList_AddMasked (himl, (HBITMAP32)handle, clrMask);
1435     }
1436     else if ((uType == IMAGE_ICON) || (uType == IMAGE_CURSOR)) {
1437 #ifdef __GET_ICON_INFO_HACK__
1438         HBITMAP32 hbmImage;
1439         HBITMAP32 hbmMask;
1440         CURSORICONINFO *ptr;
1441
1442         if (!(ptr = (CURSORICONINFO *)GlobalLock16(handle))) return (NULL);
1443         hbmMask  = CreateBitmap32 (ptr->nWidth, ptr->nHeight, 1, 1, 
1444                                    (char *)(ptr + 1));
1445         hbmImage = CreateBitmap32 (ptr->nWidth, ptr->nHeight, ptr->bPlanes,
1446                                    ptr->bBitsPerPixel,
1447                                    (char *)(ptr + 1) + ptr->nHeight * 
1448                                    BITMAP_WIDTH_BYTES(ptr->nWidth, 1));
1449         himl = ImageList_Create (ptr->nWidth, ptr->nHeight,
1450                                  ILC_MASK | ILC_COLOR, 1, cGrow);
1451         ImageList_Add (himl, hbmImage, hbmMask);
1452         DeleteObject32 (hbmImage);
1453         DeleteObject32 (hbmMask);
1454         GlobalUnlock16 (handle);
1455 #else
1456         ICONINFO32 ii;
1457         BITMAP32 bmp;
1458
1459         GetIconInfo (hIcon, &ii);
1460         GetObject32A (ii->hbmMask, sizeof(BITMAP32), (LPVOID)&bmp);
1461         himl = ImageList_Create (bmp.bmWidth, bmp.bmHeight, 
1462                                  ILC_MASK | ILC_COLOR, 1, cGrow);
1463         ImageList_Add (himl, ii->hbmColor, ii->hbmMask);
1464 #endif
1465     }
1466
1467     DeleteObject32 (handle);
1468     
1469     return (himl);
1470 }
1471
1472
1473 /*************************************************************************
1474  * ImageList_LoadImage32W [COMCTL32.64]
1475  *
1476  * Creates an image list from a bitmap, icon or cursor.
1477  *
1478  * PARAMS
1479  *     hi      [I] instance handle
1480  *     lpbmp   [I] name or id of the image
1481  *     cx      [I] width of each image
1482  *     cGrow   [I] number of images to expand
1483  *     clrMask [I] mask color
1484  *     uType   [I] type of image to load
1485  *     uFlags  [I] loading flags
1486  *
1487  * RETURNS
1488  *     Success: handle of the loaded image
1489  *     Failure: NULL
1490  *
1491  * SEE
1492  *     LoadImage ()
1493  */
1494
1495 HIMAGELIST WINAPI
1496 ImageList_LoadImage32W (HINSTANCE32 hi, LPCWSTR lpbmp, INT32 cx, INT32 cGrow,
1497                         COLORREF clrMask, UINT32 uType, UINT32 uFlags)
1498 {
1499     HIMAGELIST himl = NULL;
1500     HANDLE32   handle;
1501     INT32      nImageCount;
1502
1503     handle = LoadImage32W (hi, lpbmp, uType, 0, 0, uFlags);
1504     if (!handle) {
1505         ERR (imagelist, "Error loading image!\n");
1506         return (NULL);
1507     }
1508
1509     if (uType == IMAGE_BITMAP) {
1510         BITMAP32 bmp;
1511         GetObject32A (handle, sizeof(BITMAP32), &bmp);
1512         nImageCount = bmp.bmWidth / cx;
1513
1514         himl = ImageList_Create (cx, bmp.bmHeight, ILC_MASK | ILC_COLOR,
1515                                  nImageCount, cGrow);
1516         ImageList_AddMasked (himl, (HBITMAP32)handle, clrMask);
1517     }
1518     else if ((uType == IMAGE_ICON) || (uType == IMAGE_CURSOR)) {
1519 #ifdef __GET_ICON_INFO_HACK__
1520         HBITMAP32 hbmImage;
1521         HBITMAP32 hbmMask;
1522         CURSORICONINFO *ptr;
1523
1524         if (!(ptr = (CURSORICONINFO *)GlobalLock16(handle))) return (NULL);
1525         hbmMask  = CreateBitmap32 (ptr->nWidth, ptr->nHeight, 1, 1, 
1526                                    (char *)(ptr + 1));
1527         hbmImage = CreateBitmap32 (ptr->nWidth, ptr->nHeight, ptr->bPlanes,
1528                                    ptr->bBitsPerPixel,
1529                                    (char *)(ptr + 1) + ptr->nHeight * 
1530                                    BITMAP_WIDTH_BYTES(ptr->nWidth, 1));
1531         himl = ImageList_Create (ptr->nWidth, ptr->nHeight,
1532                                  ILC_MASK | ILC_COLOR, 1, cGrow);
1533         ImageList_Add (himl, hbmImage, hbmMask);
1534         DeleteObject32 (hbmImage);
1535         DeleteObject32 (hbmMask);
1536         GlobalUnlock16 (handle);
1537 #else
1538         ICONINFO32 ii;
1539         BITMAP32 bmp;
1540
1541         GetIconInfo (hIcon, &ii);
1542         GetObject32A (ii->hbmMask, sizeof(BITMAP32), (LPVOID)&bmp);
1543         himl = ImageList_Create (bmp.bmWidth, bmp.bmHeight, 
1544                                  ILC_MASK | ILC_COLOR, 1, cGrow);
1545         ImageList_Add (himl, ii->hbmColor, ii->hbmMask);
1546 #endif
1547     }
1548
1549     DeleteObject32 (handle);
1550     
1551     return (himl);
1552 }
1553
1554
1555 /*************************************************************************
1556  * ImageList_Merge [COMCTL32.65] 
1557  *
1558  * Creates a new image list that contains a merged image from the specified
1559  * images of both source image lists.
1560  *
1561  * PARAMS
1562  *     himl1 [I] first image list handle
1563  *     i1    [I] first image index
1564  *     himl2 [I] second image list handle
1565  *     i2    [I] second image index
1566  *     dx    [I] X offset of the second image relative to the first.
1567  *     dy    [I] Y offset of the second image relative to the first.
1568  *
1569  * RETURNS
1570  *     Success: handle of the merged image list.
1571  *     Failure: NULL
1572  */
1573
1574 HIMAGELIST WINAPI
1575 ImageList_Merge (HIMAGELIST himl1, INT32 i1, HIMAGELIST himl2, INT32 i2,
1576                  INT32 dx, INT32 dy)
1577 {
1578     HIMAGELIST himlDst = NULL;
1579     HDC32      hdcSrcImage, hdcDstImage;
1580     INT32      cxDst, cyDst;
1581     INT32      xOff1, yOff1, xOff2, yOff2;
1582     INT32      nX1, nX2;
1583
1584     if ((himl1 == NULL) || (himl2 == NULL)) return (NULL);
1585
1586     /* check indices */
1587     if ((i1 < 0) || (i1 >= himl1->cCurImage)) {
1588         ERR (imagelist, "Index 1 out of range! %d\n", i1);
1589         return (NULL);
1590     }
1591
1592     if ((i2 < 0) || (i2 >= himl2->cCurImage)) {
1593         ERR (imagelist, "Index 2 out of range! %d\n", i2);
1594         return (NULL);
1595     }
1596
1597     if (dx > 0) {
1598         cxDst = _MAX (himl1->cx, dx + himl2->cx);
1599         xOff1 = 0;
1600         xOff2 = dx;
1601     }
1602     else if (dx < 0) {
1603         cxDst = _MAX (himl2->cx, himl1->cx - dx);
1604         xOff1 = -dx;
1605         xOff2 = 0;
1606     }
1607     else {
1608         cxDst = _MAX (himl1->cx, himl2->cx);
1609         xOff1 = 0;
1610         xOff2 = 0;
1611     }
1612
1613     if (dy > 0) {
1614         cyDst = _MAX (himl1->cy, dy + himl2->cy);
1615         yOff1 = 0;
1616         yOff2 = dy;
1617     }
1618     else if (dy < 0) {
1619         cyDst = _MAX (himl2->cy, himl1->cy - dy);
1620         yOff1 = -dy;
1621         yOff2 = 0;
1622     }
1623     else {
1624         cyDst = _MAX (himl1->cy, himl2->cy);
1625         yOff1 = 0;
1626         yOff2 = 0;
1627     }
1628
1629     himlDst = ImageList_Create (cxDst, cyDst, ILC_MASK | ILC_COLOR, 1, 1);
1630
1631     if (himlDst) {
1632         hdcSrcImage = CreateCompatibleDC32 (0);
1633         hdcDstImage = CreateCompatibleDC32 (0);
1634         nX1 = i1 * himl1->cx;
1635         nX2 = i2 * himl2->cx;
1636         
1637         /* copy image */
1638         SelectObject32 (hdcSrcImage, himl1->hbmImage);
1639         SelectObject32 (hdcDstImage, himlDst->hbmImage);
1640         BitBlt32 (hdcDstImage, 0, 0, cxDst, cyDst, 
1641                   hdcSrcImage, 0, 0, BLACKNESS);
1642         BitBlt32 (hdcDstImage, xOff1, yOff1, himl1->cx, himl1->cy, 
1643                   hdcSrcImage, nX1, 0, SRCCOPY);
1644
1645         SelectObject32 (hdcSrcImage, himl2->hbmMask);
1646         BitBlt32 (hdcDstImage, xOff2, yOff2, himl2->cx, himl2->cy, 
1647                   hdcSrcImage, nX2, 0, SRCAND);
1648
1649         SelectObject32 (hdcSrcImage, himl2->hbmImage);
1650         BitBlt32 (hdcDstImage, xOff2, yOff2, himl2->cx, himl2->cy, 
1651                   hdcSrcImage, nX2, 0, SRCPAINT);
1652
1653         /* copy mask */
1654         SelectObject32 (hdcSrcImage, himl1->hbmMask);
1655         SelectObject32 (hdcDstImage, himlDst->hbmMask);
1656         BitBlt32 (hdcDstImage, 0, 0, cxDst, cyDst, 
1657                   hdcSrcImage, 0, 0, WHITENESS);
1658         BitBlt32 (hdcDstImage, xOff1, yOff1, himl1->cx, himl1->cy, 
1659                   hdcSrcImage, nX1, 0, SRCCOPY);
1660
1661         SelectObject32 (hdcSrcImage, himl2->hbmMask);
1662         BitBlt32 (hdcDstImage, xOff2, yOff2, himl2->cx, himl2->cy, 
1663                   hdcSrcImage, nX2, 0, SRCAND);
1664
1665         DeleteDC32 (hdcSrcImage);
1666         DeleteDC32 (hdcDstImage);
1667     }
1668    
1669     return (himlDst);
1670 }
1671
1672
1673 /*************************************************************************
1674  * ImageList_Read [COMCTL32.66]
1675  *
1676  * Reads an image list from a stream.
1677  *
1678  * PARAMS
1679  *     pstm [I] pointer to a stream
1680  *
1681  * RETURNS
1682  *     Success: image list handle
1683  *     Failure: NULL
1684  *
1685  * NOTES
1686  *     This function can not be implemented yet, because
1687  *     IStream32::Read is not implemented.
1688  *
1689  * BUGS
1690  *     empty stub.
1691  */
1692
1693 HIMAGELIST WINAPI ImageList_Read (LPSTREAM32 pstm)
1694 {
1695     FIXME (imagelist, "empty stub!\n");
1696
1697
1698     return (NULL);
1699 }
1700
1701
1702 /*************************************************************************
1703  * ImageList_Remove [COMCTL32.67] Removes an image from an image list
1704  *
1705  * PARAMS
1706  *     himl [I] image list handle
1707  *     i    [I] image index
1708  *
1709  * RETURNS
1710  *     Success: TRUE
1711  *     Failure: FALSE
1712  */
1713
1714 BOOL32 WINAPI
1715 ImageList_Remove (HIMAGELIST himl, INT32 i)
1716 {
1717     HBITMAP32 hbmNewImage, hbmNewMask;
1718     HDC32     hdcSrc, hdcDst;
1719     INT32     cxNew, nCount;
1720
1721     if ((i < -1) || (i >= himl->cCurImage)) {
1722         ERR (imagelist, "index out of range! %d\n", i);
1723         return (FALSE);
1724     }
1725
1726     if (himl->cCurImage == 0) {
1727         ERR (imagelist, "image list is already empty!\n");
1728         return (FALSE);
1729     }
1730
1731     if (i == -1) {
1732         /* remove all */
1733         TRACE (imagelist, "remove all!\n");
1734
1735         himl->cMaxImage = himl->cInitial + himl->cGrow;
1736         himl->cCurImage = 0;
1737         for (nCount = 0; nCount <= MAX_OVERLAYIMAGE; nCount++)
1738              himl->nOvlIdx[nCount] = -1;
1739
1740         DeleteObject32 (himl->hbmImage);
1741         himl->hbmImage =
1742             CreateBitmap32 (himl->cMaxImage * himl->cx, himl->cy,
1743                             1, himl->uBitsPixel, NULL);
1744
1745         if (himl->hbmMask) {
1746             DeleteObject32 (himl->hbmMask);
1747             himl->hbmMask =
1748                 CreateBitmap32 (himl->cMaxImage * himl->cx, himl->cy,
1749                                 1, himl->uBitsPixel, NULL);
1750         }
1751     }
1752     else {
1753         /* delete one image */
1754         TRACE (imagelist, "Remove single image! %d\n", i);
1755
1756         /* create new bitmap(s) */
1757         cxNew = (himl->cCurImage + himl->cGrow - 1) * himl->cx;
1758
1759         TRACE(imagelist, " - Number of images: %d / %d (Old/New)\n",
1760                  himl->cCurImage, himl->cCurImage - 1);
1761         TRACE(imagelist, " - Max. number of images: %d / %d (Old/New)\n",
1762                  himl->cMaxImage, himl->cCurImage + himl->cGrow - 1);
1763         
1764         hbmNewImage =
1765             CreateBitmap32 (cxNew, himl->cy, 1, himl->uBitsPixel, NULL);
1766
1767         if (himl->hbmMask)
1768             hbmNewMask = CreateBitmap32 (cxNew, himl->cy, 1, himl->uBitsPixel, NULL);
1769         else
1770             hbmNewMask = 0;  /* Just to keep compiler happy! */
1771
1772         hdcSrc = CreateCompatibleDC32 (0);
1773         hdcDst = CreateCompatibleDC32 (0);
1774
1775         /* copy all images and masks prior to the "removed" image */
1776         if (i > 0) {
1777             TRACE (imagelist, "Pre image copy: Copy %d images\n", i);
1778        
1779             SelectObject32 (hdcSrc, himl->hbmImage);
1780             SelectObject32 (hdcDst, hbmNewImage);
1781             BitBlt32 (hdcDst, 0, 0, i * himl->cx, himl->cy,
1782                       hdcSrc, 0, 0, SRCCOPY);
1783
1784             if (himl->hbmMask) {
1785                 SelectObject32 (hdcSrc, himl->hbmMask);
1786                 SelectObject32 (hdcDst, hbmNewMask);
1787                 BitBlt32 (hdcDst, 0, 0, i * himl->cx, himl->cy,
1788                           hdcSrc, 0, 0, SRCCOPY);
1789             }
1790         }
1791
1792         /* copy all images and masks behind the removed image */
1793         if (i < himl->cCurImage - 1) {
1794             TRACE (imagelist, "Post image copy!\n");
1795             SelectObject32 (hdcSrc, himl->hbmImage);
1796             SelectObject32 (hdcDst, hbmNewImage);
1797             BitBlt32 (hdcDst, i * himl->cx, 0, (himl->cCurImage - i - 1) * himl->cx,
1798                       himl->cy, hdcSrc, (i + 1) * himl->cx, 0, SRCCOPY);
1799
1800             if (himl->hbmMask) {
1801                 SelectObject32 (hdcSrc, himl->hbmMask);
1802                 SelectObject32 (hdcDst, hbmNewMask);
1803                 BitBlt32 (hdcDst, i * himl->cx, 0,
1804                           (himl->cCurImage - i - 1) * himl->cx,
1805                           himl->cy, hdcSrc, (i + 1) * himl->cx, 0, SRCCOPY);
1806             }
1807         }
1808
1809         DeleteDC32 (hdcSrc);
1810         DeleteDC32 (hdcDst);
1811
1812         /* delete old images and insert new ones */
1813         DeleteObject32 (himl->hbmImage);
1814         himl->hbmImage = hbmNewImage;
1815         if (himl->hbmMask) {
1816             DeleteObject32 (himl->hbmMask);
1817             himl->hbmMask = hbmNewMask;
1818         }
1819
1820         himl->cCurImage--;
1821         himl->cMaxImage = himl->cCurImage + himl->cGrow;
1822     }
1823
1824     return (TRUE);
1825 }
1826
1827
1828 /*************************************************************************
1829  * ImageList_Replace [COMCTL32.68] 
1830  *
1831  * Replaces an image in an image list with a new image.
1832  *
1833  * PARAMS
1834  *     himl     [I] image list handle
1835  *     i        [I] image index
1836  *     hbmImage [I] image bitmap handle
1837  *     hbmMask  [I] mask bitmap handle. Can be NULL.
1838  *
1839  * RETURNS
1840  *     Success: TRUE
1841  *     Failure: FALSE
1842  */
1843
1844 BOOL32 WINAPI
1845 ImageList_Replace (HIMAGELIST himl, INT32 i, HBITMAP32 hbmImage,
1846                    HBITMAP32 hbmMask)
1847 {
1848     HDC32 hdcImageList, hdcImage;
1849     BITMAP32 bmp;
1850
1851     if (himl == NULL) {
1852         ERR (imagelist, "Invalid image list handle!\n");
1853         return (FALSE);
1854     }
1855     
1856     if ((i >= himl->cCurImage) || (i < 0)) {
1857         ERR (imagelist, "Invalid image index!\n");
1858         return (FALSE);
1859     }
1860
1861     hdcImageList = CreateCompatibleDC32 (0);
1862     hdcImage = CreateCompatibleDC32 (0);
1863     GetObject32A (hbmImage, sizeof(BITMAP32), (LPVOID)&bmp);
1864
1865     /* Replace Image */
1866     SelectObject32 (hdcImageList, himl->hbmImage);
1867     SelectObject32 (hdcImage, hbmImage);
1868
1869     StretchBlt32 (hdcImageList, i * himl->cx, 0, himl->cx, himl->cy,
1870                   hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
1871
1872     if (himl->hbmMask)
1873     {
1874         /* Replace Mask */
1875         SelectObject32 (hdcImageList, himl->hbmMask);
1876         SelectObject32 (hdcImage, hbmMask);
1877
1878         StretchBlt32 (hdcImageList, i * himl->cx, 0, himl->cx, himl->cy,
1879                       hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
1880     }
1881
1882     DeleteDC32 (hdcImage);
1883     DeleteDC32 (hdcImageList);
1884
1885     return (TRUE);
1886 }
1887
1888
1889 /*************************************************************************
1890  * ImageList_ReplaceIcon [COMCTL32.69]
1891  *
1892  * Replaces an image in an image list using an icon.
1893  *
1894  * PARAMS
1895  *     himl  [I] image list handle
1896  *     i     [I] image index
1897  *     hIcon [I] icon handle
1898  *
1899  * RETURNS
1900  *     Success: index of the replaced image
1901  *     Failure: -1
1902  */
1903
1904 INT32 WINAPI
1905 ImageList_ReplaceIcon (HIMAGELIST himl, INT32 i, HICON32 hIcon)
1906 {
1907     HDC32     hdcImageList, hdcImage;
1908     INT32     nIndex;
1909 #ifdef __GET_ICON_INFO_HACK__
1910     HBITMAP32 hbmImage;
1911     HBITMAP32 hbmMask;
1912     CURSORICONINFO *ptr;
1913 #else    
1914     ICONINFO32 ii;
1915     BITMAP32 bmp;
1916 #endif
1917
1918     if (himl == NULL) return (-1);
1919     if ((i >= himl->cCurImage) || (i < -1)) return (-1);
1920
1921 #ifdef __GET_ICON_INFO_HACK__
1922     if (!(ptr = (CURSORICONINFO *)GlobalLock16(hIcon))) return (-1);
1923     hbmMask  = CreateBitmap32 (ptr->nWidth, ptr->nHeight, 1, 1, 
1924                                (char *)(ptr + 1));
1925     hbmImage = CreateBitmap32 (ptr->nWidth, ptr->nHeight, ptr->bPlanes,
1926                                ptr->bBitsPerPixel,
1927                                (char *)(ptr + 1) + ptr->nHeight * 
1928                                BITMAP_WIDTH_BYTES(ptr->nWidth, 1));
1929 #else
1930     GetIconInfo (hIcon, &ii);
1931     GetObject32A (ii->hbmMask, sizeof(BITMAP32), (LPVOID)&bmp);
1932 #endif
1933
1934     if (i == -1) {
1935         if (himl->cCurImage + 1 >= himl->cMaxImage)
1936             IMAGELIST_InternalExpandBitmaps (himl, 1);
1937
1938         nIndex = himl->cCurImage;
1939         himl->cCurImage++;
1940     }
1941     else
1942         nIndex = i;
1943
1944     hdcImageList = CreateCompatibleDC32 (0);
1945     hdcImage = CreateCompatibleDC32 (0);
1946
1947 #ifdef __GET_ICON_INFO_HACK__
1948     SelectObject32 (hdcImageList, himl->hbmImage);
1949     SelectObject32 (hdcImage, hbmImage);
1950     StretchBlt32 (hdcImageList, nIndex * himl->cx, 0, himl->cx, himl->cy,
1951                   hdcImage, 0, 0, ptr->nWidth, ptr->nHeight, SRCCOPY);
1952 #else
1953     SelectObject32 (hdcImage, ii->hbmColor);
1954     StretchBlt32 (hdcImageList, nIndex * himl->cx, 0, himl->cx, himl->cy,
1955                   hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
1956 #endif
1957
1958     if (himl->hbmMask) {
1959 #ifdef __GET_ICON_INFO_HACK__
1960         SelectObject32 (hdcImageList, himl->hbmMask);
1961         SelectObject32 (hdcImage, hbmMask);
1962         StretchBlt32 (hdcImageList, nIndex * himl->cx, 0, himl->cx, himl->cy,
1963                       hdcImage, 0, 0, ptr->nWidth, ptr->nHeight, SRCCOPY);
1964 #else
1965         SelectObject32 (hdcImage, ii->hbmMask);
1966         StretchBlt32 (hdcImageList, nIndex * himl->cx, 0, himl->cx, himl->cy,
1967                       hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
1968 #endif
1969     }
1970
1971     DeleteDC32 (hdcImageList);
1972     DeleteDC32 (hdcImage);
1973 #ifdef __GET_ICON_INFO_HACK        
1974     DeleteObject32 (hbmImage);
1975     DeleteObject32 (hbmMask);
1976     GlobalUnlock16 (hIcon);
1977 #endif
1978     return (nIndex);
1979 }
1980
1981
1982 /*************************************************************************
1983  * ImageList_SetBkColor [COMCTL32.70] 
1984  *
1985  * Sets the background color of an image list.
1986  *
1987  * PARAMS
1988  *     himl  [I] image list handle
1989  *     clrBk [I] background color
1990  *
1991  * RETURNS
1992  *     Success: previous background color
1993  *     Failure: CLR_NONE
1994  */
1995
1996 COLORREF WINAPI
1997 ImageList_SetBkColor (HIMAGELIST himl, COLORREF clrBk)
1998 {
1999     COLORREF clrOldBk;
2000
2001     if (himl == NULL)
2002         return (CLR_NONE);
2003
2004     clrOldBk = himl->clrBk;
2005     himl->clrBk = clrBk;
2006     return (clrOldBk);
2007 }
2008
2009
2010 /*************************************************************************
2011  * ImageList_SetDragCursorImage [COMCTL32.75]
2012  *
2013  * Combines the specified image with the current drag image
2014  *
2015  * PARAMS
2016  *     himlDrag  [I] drag image list handle
2017  *     iDrag     [I] drag image index
2018  *     dxHotspot [I] X position of the hot spot
2019  *     dyHotspot [I] Y position of the hot spot
2020  *
2021  * RETURNS
2022  *     Success: TRUE
2023  *     Failure: FALSE
2024  *
2025  * BUGS
2026  *     semi-stub.
2027  */
2028
2029 BOOL32 WINAPI
2030 ImageList_SetDragCursorImage (HIMAGELIST himlDrag, INT32 iDrag,
2031                               INT32 dxHotspot, INT32 dyHotspot)
2032 {
2033     HIMAGELIST himlTemp;
2034
2035     FIXME (imagelist, "semi-stub!\n");
2036
2037     if (himlInternalDrag == NULL) return (FALSE);
2038
2039     TRACE (imagelist, " dxH=%d dyH=%d nX=%d nY=%d\n",
2040            dxHotspot, dyHotspot, nInternalDragHotspotX, nInternalDragHotspotY);
2041
2042     himlTemp = ImageList_Merge (himlInternalDrag, 0, himlDrag, iDrag,
2043                                 dxHotspot, dyHotspot);
2044
2045     ImageList_Destroy (himlInternalDrag);
2046     himlInternalDrag = himlTemp;
2047
2048     nInternalDragHotspotX = dxHotspot;
2049     nInternalDragHotspotY = dyHotspot;
2050
2051     return (FALSE);
2052 }
2053
2054
2055 /*************************************************************************
2056  * ImageList_SetFilter [COMCTL32.76] 
2057  *
2058  * Sets a filter (or does something completely different)!!???
2059  *
2060  * PARAMS
2061  *     himl     [I] ???
2062  *     i        [I] ???
2063  *     dwFilter [I] ???
2064  *
2065  * RETURNS
2066  *     Success: TRUE ???
2067  *     Failure: FALSE ???
2068  *
2069  * BUGS
2070  *     This is an UNDOCUMENTED function!!!!
2071  *     empty stub.
2072  */
2073
2074 #if 0
2075 BOOL32 WINAPI
2076 ImageList_SetFilter (HIMAGELIST himl, INT32 i, DWORD dwFilter)
2077 {
2078     FIXME (imagelist, "empty stub!\n");
2079
2080
2081 }
2082 #endif /* 0 */
2083
2084
2085 /*************************************************************************
2086  * ImageList_SetIconSize [COMCTL32.77]
2087  *
2088  * Sets the image size of the bitmap and deletes all images.
2089  *
2090  * PARAMS
2091  *     himl [I] image list handle
2092  *     cx   [I] image width
2093  *     cy   [I] image height
2094  *
2095  * RETURNS
2096  *     Success: TRUE
2097  *     Failure: FALSE
2098  */
2099
2100 BOOL32 WINAPI
2101 ImageList_SetIconSize (HIMAGELIST himl, INT32 cx, INT32 cy)
2102 {
2103     INT32 nCount;
2104
2105     if (himl == NULL) return (FALSE);
2106
2107     /* remove all images*/
2108     himl->cMaxImage  = himl->cInitial + himl->cGrow;
2109     himl->cCurImage  = 0;
2110     himl->cx         = cx;
2111     himl->cy         = cy;
2112
2113     /* initialize overlay mask indices */
2114     for (nCount = 0; nCount < MAX_OVERLAYIMAGE; nCount++)
2115         himl->nOvlIdx[nCount] = -1;
2116
2117     DeleteObject32 (himl->hbmImage);
2118     himl->hbmImage =
2119         CreateBitmap32 (himl->cMaxImage * himl->cx, himl->cy,
2120                         1, himl->uBitsPixel, NULL);
2121
2122     if (himl->hbmMask) {
2123         DeleteObject32 (himl->hbmMask);
2124         himl->hbmMask =
2125             CreateBitmap32 (himl->cMaxImage * himl->cx, himl->cy,
2126                             1, himl->uBitsPixel, NULL);
2127     }
2128
2129     return (TRUE);
2130 }
2131
2132
2133 /*************************************************************************
2134  * ImageList_SetImageCount [COMCTL32.78]
2135  *
2136  * Resizes an image list to the specified number of images.
2137  *
2138  * PARAMS
2139  *     himl        [I] image list handle
2140  *     iImageCount [I] number of images in the image list
2141  *
2142  * RETURNS
2143  *     Success: TRUE
2144  *     Failure: FALSE
2145  */
2146
2147 BOOL32 WINAPI
2148 ImageList_SetImageCount (HIMAGELIST himl, INT32 iImageCount)
2149 {
2150     HDC32     hdcImageList, hdcBitmap;
2151     HBITMAP32 hbmNewBitmap;
2152     INT32     nNewCount, nCopyCount;
2153
2154     if (himl == NULL) return (FALSE);
2155     if (himl->cCurImage <= iImageCount) return (FALSE);
2156     if (himl->cMaxImage > iImageCount) return (TRUE);
2157
2158     nNewCount = iImageCount + himl->cGrow;
2159     nCopyCount = _MIN(himl->cCurImage, iImageCount);
2160
2161     hdcImageList = CreateCompatibleDC32 (0);
2162     hdcBitmap = CreateCompatibleDC32 (0);
2163
2164     hbmNewBitmap = CreateBitmap32 (nNewCount * himl->cx, himl->cy,
2165                                    1, himl->uBitsPixel, NULL);
2166     if (hbmNewBitmap == 0)
2167     {
2168         SelectObject32 (hdcImageList, himl->hbmImage);
2169         SelectObject32 (hdcBitmap, hbmNewBitmap);
2170         BitBlt32 (hdcBitmap, 0, 0, nCopyCount * himl->cx, himl->cy,
2171                   hdcImageList, 0, 0, SRCCOPY);
2172         DeleteObject32 (himl->hbmImage);
2173         himl->hbmImage = hbmNewBitmap;
2174     }
2175     else
2176     {
2177         WARN (imagelist, "Could not create new image bitmap !\n");
2178     }
2179
2180     if (himl->hbmMask)
2181     {
2182         hbmNewBitmap = CreateBitmap32 (nNewCount * himl->cx, himl->cy,
2183                                        1, himl->uBitsPixel, NULL);
2184         if (hbmNewBitmap != 0)
2185         {
2186             SelectObject32 (hdcImageList, himl->hbmMask);
2187             SelectObject32 (hdcBitmap, hbmNewBitmap);
2188             BitBlt32 (hdcBitmap, 0, 0, nCopyCount * himl->cx, himl->cy,
2189                       hdcImageList, 0, 0, SRCCOPY);
2190             DeleteObject32 (himl->hbmMask);
2191             himl->hbmMask = hbmNewBitmap;
2192         }
2193         else
2194         {
2195             WARN (imagelist, "Could not create new mask bitmap!\n");
2196         }
2197     }
2198
2199     DeleteDC32 (hdcImageList);
2200     DeleteDC32 (hdcBitmap);
2201
2202     /* Update max image count and current image count */
2203     himl->cMaxImage = nNewCount;
2204     if (himl->cCurImage > nCopyCount)
2205         himl->cCurImage = nCopyCount;
2206
2207     return (TRUE);
2208 }
2209
2210
2211 /*************************************************************************
2212  * ImageList_SetOverlayImage [COMCTL32.79]
2213  *
2214  * Assigns an overlay mask index to an existing image in an image list.
2215  *
2216  * PARAMS
2217  *     himl     [I] image list handle
2218  *     iImage   [I] image index
2219  *     iOverlay [I] overlay mask index
2220  *
2221  * RETURNS
2222  *     Success: TRUE
2223  *     Failure: FALSE
2224  */
2225
2226 BOOL32 WINAPI
2227 ImageList_SetOverlayImage (HIMAGELIST himl, INT32 iImage, INT32 iOverlay)
2228 {
2229     if ((iOverlay < 1) || (iOverlay > MAX_OVERLAYIMAGE)) return (FALSE);
2230     if ((iImage < 0) || (iImage > himl->cCurImage)) return (FALSE);
2231     
2232     himl->nOvlIdx[iOverlay - 1] = iImage;
2233     return TRUE;
2234 }
2235
2236
2237 /*************************************************************************
2238  * ImageList_Write [COMCTL32.80]
2239  *
2240  * Writes an image list to a stream.
2241  *
2242  * PARAMS
2243  *     himl [I] Image list handle.
2244  *     pstm [O] Pointer to a stream.
2245  *
2246  * RETURNS
2247  *     Success: TRUE
2248  *     Failure: FALSE
2249  *
2250  * NOTES
2251  *     This function can not be implemented yet, because
2252  *     IStream32::Write is not implemented.
2253  *
2254  * BUGS
2255  *     empty stub.
2256  */
2257
2258 BOOL32 WINAPI
2259 ImageList_Write (HIMAGELIST himl, LPSTREAM32 pstm)
2260 {
2261     FIXME (imagelist, "empty stub!\n");
2262
2263     if (himl == NULL) return (FALSE);
2264
2265     return FALSE;
2266 }
2267