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