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