Some minor improvements.
[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 "compobj.h"
35 #include "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] image list handle
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] image list handle
134  *     hbmImage [I] image bitmap handle
135  *     hbmMask  [I] mask bitmap handle
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] image list handle
206  *     hIcon [I] icon handle
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 of 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] destination image list handle.
362  *     iDst    [I] destination image index.
363  *     himlSrc [I] source image list handle
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] image list handle
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) return (FALSE);
631
632     if (hwndLock)
633         hwndInternalDrag = hwndLock;
634     else
635         hwndInternalDrag = GetDesktopWindow32 ();
636
637     xInternalPos = x;
638     yInternalPos = y;
639
640     hdcBackBuffer = CreateCompatibleDC32 (0);
641     hbmBackBuffer = CreateCompatibleBitmap32 (hdcBackBuffer,
642                 himlInternalDrag->cx, himlInternalDrag->cy);
643
644     ImageList_DragShowNolock (TRUE);
645
646     return FALSE;
647 }
648
649
650 /*************************************************************************
651  * ImageList_DragLeave [COMCTL32.47] 
652  *
653  * Unlocks window update and hides the drag image.
654  *
655  * PARAMS
656  *     hwndLock [I] handle of the window that owns the drag image.
657  *
658  * RETURNS
659  *     Success: TRUE
660  *     Failure: FALSE
661  */
662
663 BOOL32 WINAPI
664 ImageList_DragLeave (HWND32 hwndLock)
665 {
666     if (hwndLock)
667         hwndInternalDrag = hwndLock;
668     else
669         hwndInternalDrag = GetDesktopWindow32 ();
670
671     ImageList_DragShowNolock (FALSE);
672
673     DeleteDC32 (hdcBackBuffer);
674     DeleteObject32 (hbmBackBuffer);
675
676     return (TRUE);
677 }
678
679
680 /*************************************************************************
681  * ImageList_DragMove [COMCTL32.48] 
682  *
683  * Moves the drag image.
684  *
685  * PARAMS
686  *     x [I] X position of the drag image.
687  *     y [I] Y position of the drag image.
688  *
689  * RETURNS
690  *     Success: TRUE
691  *     Failure: FALSE
692  *
693  * NOTES
694  *     The position of the drag image is relative to the window, not
695  *     the client area.
696  */
697
698 BOOL32 WINAPI
699 ImageList_DragMove (INT32 x, INT32 y)
700 {
701     ImageList_DragShowNolock (FALSE);
702
703     xInternalPos = x;
704     yInternalPos = y;
705
706     ImageList_DragShowNolock (TRUE);
707
708     return (FALSE);
709 }
710
711
712 /*************************************************************************
713  * ImageList_DragShowNolock [COMCTL32.49] 
714  *
715  * Shows or hides the drag image.
716  *
717  * PARAMS
718  *     bShow [I] TRUE shows the drag image, FALSE hides it.
719  *
720  * RETURNS
721  *     Success: TRUE
722  *     Failure: FALSE
723  *
724  * FIXME
725  *     semi-stub.
726  */
727
728 BOOL32 WINAPI
729 ImageList_DragShowNolock (BOOL32 bShow)
730 {
731     HDC32 hdcDrag;
732
733     FIXME (imagelist, "semi-stub!\n");
734     TRACE (imagelist, "bShow=0x%X!\n", bShow);
735
736     hdcDrag = GetDCEx32 (hwndInternalDrag, 0,
737                          DCX_WINDOW | DCX_CACHE | DCX_LOCKWINDOWUPDATE);
738
739     if (bShow) {
740         /* show drag image */
741
742         /* save background */
743
744         /* draw drag image */
745
746     }
747     else {
748         /* hide drag image */
749
750         /* restore background */
751
752     }
753
754     ReleaseDC32 (hwndInternalDrag, hdcDrag);
755
756     return (FALSE);
757 }
758
759
760 /*************************************************************************
761  * ImageList_Draw [COMCTL32.50] Draws an image.
762  *
763  * PARAMS
764  *     himl   [I] image list handle
765  *     i      [I] image index
766  *     hdc    [I] display context handle
767  *     x      [I] x position
768  *     y      [I] y position
769  *     fStyle [I] drawing flags
770  *
771  * RETURNS
772  *     Success: TRUE
773  *     Failure: FALSE
774  *
775  * NOTES
776  *     Calls ImageList_DrawIndirect.
777  *
778  * SEE
779  *     ImageList_DrawIndirect.
780  */
781
782 BOOL32 WINAPI
783 ImageList_Draw (HIMAGELIST himl, INT32 i, HDC32 hdc,
784                 INT32 x, INT32 y, UINT32 fStyle)
785 {
786     IMAGELISTDRAWPARAMS imldp;
787
788     imldp.cbSize  = sizeof(IMAGELISTDRAWPARAMS);
789     imldp.himl    = himl;
790     imldp.i       = i;
791     imldp.hdcDst  = hdc,
792     imldp.x       = x;
793     imldp.y       = y;
794     imldp.cx      = 0;
795     imldp.cy      = 0;
796     imldp.xBitmap = 0;
797     imldp.yBitmap = 0;
798     imldp.rgbBk   = CLR_DEFAULT;
799     imldp.rgbFg   = CLR_DEFAULT;
800     imldp.fStyle  = fStyle;
801     imldp.dwRop   = 0;
802
803     return (ImageList_DrawIndirect (&imldp));
804 }
805
806
807 /*************************************************************************
808  * ImageList_DrawEx [COMCTL32.51]
809  *
810  * Draws an image and allows to use extended drawing features.
811  *
812  * PARAMS
813  *     himl   [I] image list handle
814  *     i      [I] image index
815  *     hdc    [I] device context handle
816  *     x      [I] X position
817  *     y      [I] Y position
818  *     xOffs  [I] X offset
819  *     yOffs  [I] Y offset
820  *     rgbBk  [I] background color
821  *     rgbFg  [I] foreground color
822  *     fStyle [I] drawing flags
823  *
824  * RETURNS
825  *     Success: TRUE
826  *     Failure: FALSE
827  *
828  * NOTES
829  *     Calls ImageList_DrawIndirect.
830  *
831  * SEE
832  *     ImageList_DrawIndirect.
833  */
834
835 BOOL32 WINAPI
836 ImageList_DrawEx (HIMAGELIST himl, INT32 i, HDC32 hdc, INT32 x, INT32 y,
837                   INT32 dx, INT32 dy, COLORREF rgbBk, COLORREF rgbFg,
838                   UINT32 fStyle)
839 {
840     IMAGELISTDRAWPARAMS imldp;
841
842     imldp.cbSize  = sizeof(IMAGELISTDRAWPARAMS);
843     imldp.himl    = himl;
844     imldp.i       = i;
845     imldp.hdcDst  = hdc,
846     imldp.x       = x;
847     imldp.y       = y;
848     imldp.cx      = dx;
849     imldp.cy      = dy;
850     imldp.xBitmap = 0;
851     imldp.yBitmap = 0;
852     imldp.rgbBk   = rgbBk;
853     imldp.rgbFg   = rgbFg;
854     imldp.fStyle  = fStyle;
855     imldp.dwRop   = 0;
856
857     return (ImageList_DrawIndirect (&imldp));
858 }
859
860
861 /*************************************************************************
862  * ImageList_DrawIndirect [COMCTL32.52] 
863  *
864  * Draws an image using ...
865  *
866  * PARAMS
867  *     pimldp [I] pointer to IMAGELISTDRAWPARAMS structure.
868  *
869  * RETURNS
870  *     Success: TRUE
871  *     Failure: FALSE
872  */
873
874 BOOL32 WINAPI
875 ImageList_DrawIndirect (IMAGELISTDRAWPARAMS *pimldp)
876 {
877     HIMAGELIST himlLocal;
878     HDC32      hdcImageList, hdcTempImage;
879     HBITMAP32  hbmTempImage;
880     HBRUSH32   hBrush, hOldBrush;
881     INT32      cx, cy;
882     INT32      nOvlIdx;
883     COLORREF   clrBlend;
884     BOOL32     bImage;       /* draw image ? */
885     BOOL32     bImageTrans;  /* draw image transparent ? */
886     BOOL32     bMask;        /* draw mask ? */
887     BOOL32     bMaskTrans;   /* draw mask transparent ? */
888     BOOL32     bBlend25;
889     BOOL32     bBlend50;
890
891     if (pimldp == NULL)
892         return FALSE;
893     if (pimldp->cbSize < sizeof(IMAGELISTDRAWPARAMS))
894         return (FALSE);
895     if (pimldp->himl == NULL)
896         return FALSE;
897     if ((pimldp->i < 0) || (pimldp->i >= pimldp->himl->cCurImage))
898         return FALSE;
899
900     himlLocal = pimldp->himl;
901
902     cx = (pimldp->cx == 0) ? himlLocal->cx : pimldp->cx;
903     cy = (pimldp->cy == 0) ? himlLocal->cy : pimldp->cy;
904
905     /* ILD_NORMAL state */
906     bImage      = TRUE;
907     bImageTrans = FALSE;
908     bMask       = FALSE;
909     bMaskTrans  = FALSE;
910     bBlend25    = FALSE;
911     bBlend50    = FALSE;
912     if ((himlLocal->clrBk == CLR_NONE) && (himlLocal->hbmMask))
913     {
914         bImageTrans = TRUE;
915         bMask = TRUE;
916         bMaskTrans = TRUE;
917     }
918     
919     /* ILD_IMAGE state (changes) */
920     if (pimldp->fStyle & ILD_IMAGE)
921     {
922         bMask = FALSE;
923         bImage = TRUE;
924         bImageTrans = FALSE;
925     }
926     
927     /* ILD_MASK state (changes) */
928     if ((pimldp->fStyle & ILD_MASK) && (himlLocal->hbmMask))
929     {
930         bMask  = TRUE;
931         bMaskTrans = FALSE;
932         bImage = FALSE;
933     }
934     if ((pimldp->fStyle & ILD_TRANSPARENT) && (himlLocal->hbmMask))
935     {
936         bMaskTrans = TRUE;
937         bImageTrans = TRUE;
938     }
939     if ((himlLocal->clrBk == CLR_NONE) && (himlLocal->hbmMask))
940         bMaskTrans = TRUE;
941
942     if (pimldp->fStyle & ILD_BLEND50)
943         bBlend50 = TRUE;
944     else if (pimldp->fStyle & ILD_BLEND25)
945         bBlend25 = TRUE;
946
947     hdcImageList = CreateCompatibleDC32 (0);
948
949     if (bMask)
950     {
951         /* draw the mask */
952         SelectObject32 (hdcImageList, himlLocal->hbmMask);
953         SetBkColor32 (hdcImageList, RGB(255, 255, 255));
954         SetTextColor32 (hdcImageList, RGB(0, 0, 0));
955         BitBlt32 (pimldp->hdcDst, pimldp->x, pimldp->y, cx, cy,
956                   hdcImageList, himlLocal->cx * pimldp->i, 0,
957                   bMaskTrans ? SRCAND : SRCCOPY);
958     }
959
960     if (bImage)
961     {
962         /* draw the image */
963         SelectObject32 (hdcImageList, himlLocal->hbmImage);
964
965         if (!bImageTrans)
966         {
967             hBrush = CreateSolidBrush32 (himlLocal->clrBk);
968             hOldBrush = SelectObject32 (pimldp->hdcDst, hBrush);
969             PatBlt32 (pimldp->hdcDst, pimldp->x, pimldp->y,
970                       cx, cy, PATCOPY);
971             DeleteObject32 (SelectObject32 (pimldp->hdcDst, hOldBrush));
972         }
973
974         BitBlt32 (pimldp->hdcDst, pimldp->x, pimldp->y, cx, cy,
975                   hdcImageList, himlLocal->cx * pimldp->i, 0, SRCPAINT);
976
977         if (bBlend25 || bBlend50)
978         {
979             if (pimldp->rgbFg == CLR_DEFAULT)
980                 clrBlend = GetSysColor32 (COLOR_HIGHLIGHT);
981             else
982                 clrBlend = pimldp->rgbFg;
983
984             hdcTempImage = CreateCompatibleDC32 (0);
985             hbmTempImage = CreateBitmap32 (himlLocal->cx, himlLocal->cy,
986                                            1, himlLocal->uBitsPixel, NULL);
987             SelectObject32 (hdcTempImage, hbmTempImage);
988
989
990             /* mask */
991             SelectObject32 (hdcTempImage,
992                             bBlend50 ? himlLocal->hbrBlend50 : himlLocal->hbrBlend25);
993             PatBlt32 (hdcTempImage, 0, 0, himlLocal->cx, himlLocal->cy, PATCOPY);
994
995             SelectObject32 (hdcImageList, himlLocal->hbmMask);
996             BitBlt32 (hdcTempImage, 0, 0, himlLocal->cx,
997                       himlLocal->cy, hdcImageList, 
998                       pimldp->i * himlLocal->cx, 0, SRCPAINT);
999
1000             BitBlt32 (pimldp->hdcDst, pimldp->x, pimldp->y, cx, cy,
1001                       hdcTempImage, 0, 0, SRCAND);
1002
1003             /* fill */
1004             hBrush = CreateSolidBrush32 (clrBlend);
1005             SelectObject32 (hdcTempImage, hBrush);
1006             PatBlt32 (hdcTempImage, 0, 0, himlLocal->cx, himlLocal->cy, PATCOPY);
1007             DeleteObject32 (hBrush);
1008
1009             SelectObject32 (hdcTempImage,
1010                             bBlend50 ? himlLocal->hbrBlend50 : himlLocal->hbrBlend25);
1011             PatBlt32 (hdcTempImage, 0, 0, himlLocal->cx, himlLocal->cy, 0x0A0329);
1012
1013             SelectObject32 (hdcImageList, himlLocal->hbmMask);
1014             BitBlt32 (hdcTempImage, 0, 0, himlLocal->cx,
1015                       himlLocal->cy, hdcImageList, 
1016                       pimldp->i * himlLocal->cx, 0, SRCPAINT);
1017
1018             BitBlt32 (pimldp->hdcDst, pimldp->x, pimldp->y, cx, cy,
1019                       hdcTempImage, 0, 0, SRCPAINT);
1020
1021             DeleteObject32 (hbmTempImage);
1022             DeleteDC32 (hdcTempImage);
1023         }
1024     }   
1025
1026     /* Draw overlay image */
1027     if (pimldp->fStyle & 0x0700) {
1028         nOvlIdx = (pimldp->fStyle & 0x0700) >> 8;
1029         if ((nOvlIdx >= 1) && (nOvlIdx <= MAX_OVERLAYIMAGE)) {
1030             nOvlIdx = pimldp->himl->nOvlIdx[nOvlIdx - 1];
1031             if ((nOvlIdx >= 0) && (nOvlIdx <= pimldp->himl->cCurImage)) {
1032                 if (pimldp->himl->hbmMask) {  
1033                     SelectObject32 (hdcImageList, pimldp->himl->hbmMask);
1034                     BitBlt32 (pimldp->hdcDst, pimldp->x, pimldp->y, cx, cy,
1035                               hdcImageList, pimldp->himl->cx * nOvlIdx, 0,
1036                               SRCAND);
1037                 }  
1038                 SelectObject32 (hdcImageList, pimldp->himl->hbmImage);
1039                 BitBlt32 (pimldp->hdcDst, pimldp->x, pimldp->y,
1040                           cx, cy, hdcImageList,
1041                           pimldp->himl->cx * nOvlIdx, 0, SRCPAINT);
1042             }
1043         }
1044     }
1045
1046     DeleteDC32 (hdcImageList);
1047   
1048     return (TRUE);
1049 }
1050
1051
1052 /*************************************************************************
1053  * ImageList_Duplicate [COMCTL32.53] Duplicates an image list.
1054  *
1055  * PARAMS
1056  *     himlSrc [I] source image list handle
1057  *
1058  * RETURNS
1059  *     Success: Handle of duplicated image list.
1060  *     Failure: NULL
1061  */
1062
1063 HIMAGELIST WINAPI
1064 ImageList_Duplicate (HIMAGELIST himlSrc)
1065 {
1066     HIMAGELIST himlDst;
1067     HDC32 hdcSrc, hdcDst;
1068
1069     if (himlSrc == NULL) {
1070         ERR (imagelist, "Invalid image list handle!\n");
1071         return (NULL);
1072     }
1073
1074     himlDst = ImageList_Create (himlSrc->cx, himlSrc->cy, himlSrc->flags,
1075                                 himlSrc->cInitial, himlSrc->cGrow);
1076
1077     if (himlDst)
1078     {
1079         hdcSrc = CreateCompatibleDC32 (0);
1080         hdcDst = CreateCompatibleDC32 (0);
1081         SelectObject32 (hdcSrc, himlSrc->hbmImage);
1082         SelectObject32 (hdcDst, himlDst->hbmImage);
1083         BitBlt32 (hdcDst, 0, 0, himlSrc->cCurImage * himlSrc->cx, himlSrc->cy,
1084                   hdcSrc, 0, 0, SRCCOPY);
1085
1086         if (himlDst->hbmMask)
1087         {
1088             SelectObject32 (hdcSrc, himlSrc->hbmMask);
1089             SelectObject32 (hdcDst, himlDst->hbmMask);
1090             BitBlt32 (hdcDst, 0, 0, himlSrc->cCurImage * himlSrc->cx,
1091                       himlSrc->cy, hdcSrc, 0, 0, SRCCOPY);
1092         }
1093
1094         DeleteDC32 (hdcDst);
1095         DeleteDC32 (hdcSrc);
1096     }
1097
1098     return (himlDst);
1099 }
1100
1101
1102 /*************************************************************************
1103  * ImageList_EndDrag [COMCTL32.54] Finishes a drag operation.
1104  *
1105  * Finishes a drag operation.
1106  *
1107  * PARAMS
1108  *     no Parameters
1109  *
1110  * RETURNS
1111  *     Success: TRUE
1112  *     Failure: FALSE
1113  *
1114  * BUGS
1115  *     semi-stub.
1116  */
1117
1118 BOOL32 WINAPI
1119 ImageList_EndDrag (VOID)
1120 {
1121     FIXME (imagelist, "semi-stub!\n");
1122
1123     if (himlInternalDrag)
1124     {
1125
1126         ImageList_Destroy (himlInternalDrag);
1127         himlInternalDrag = NULL;
1128
1129         nInternalDragHotspotX = 0;
1130         nInternalDragHotspotY = 0;
1131
1132     }
1133
1134     return (TRUE);
1135 }
1136
1137
1138 /*************************************************************************
1139  * ImageList_GetBkColor [COMCTL32.55]
1140  *
1141  * Returns the background color of an image list.
1142  *
1143  * PARAMS
1144  *     himl [I] Image list handle.
1145  *
1146  * RETURNS
1147  *     Success: background color
1148  *     Failure: CLR_NONE
1149  */
1150
1151 COLORREF WINAPI
1152 ImageList_GetBkColor (HIMAGELIST himl)
1153 {
1154     if (himl == NULL)
1155         return CLR_NONE;
1156
1157     return (himl->clrBk);
1158 }
1159
1160
1161 /*************************************************************************
1162  * ImageList_GetDragImage [COMCTL32.56]
1163  *
1164  * Returns the handle to the internal drag image list.
1165  *
1166  * PARAMS
1167  *     ppt        [O] Pointer to the drag position. Can be NULL.
1168  *     pptHotspot [O] Pointer to the position of the hot spot. Can be NULL.
1169  *
1170  * RETURNS
1171  *     Success: Handle of the drag image list.
1172  *     Failure: NULL.
1173  *
1174  * BUGS
1175  *     semi-stub.
1176  */
1177
1178 HIMAGELIST WINAPI
1179 ImageList_GetDragImage (POINT32 *ppt, POINT32 *pptHotspot)
1180 {
1181     FIXME (imagelist, "semi-stub!\n");
1182
1183     if (himlInternalDrag)
1184         return (himlInternalDrag);
1185
1186     return (NULL);
1187 }
1188
1189
1190 /*************************************************************************
1191  * ImageList_GetIcon [COMCTL32.57] 
1192  *
1193  * Creates an icon from a masked image of an image list.
1194  *
1195  * PARAMS
1196  *     himl  [I] image list handle
1197  *     i     [I] image index
1198  *     flags [I] drawing style flags
1199  *
1200  * RETURNS
1201  *     Success: icon handle
1202  *     Failure: NULL
1203  */
1204
1205 HICON32 WINAPI
1206 ImageList_GetIcon (HIMAGELIST himl, INT32 i, UINT32 fStyle)
1207 {
1208     ICONINFO ii;
1209     HICON32  hIcon;
1210     HDC32    hdcSrc, hdcDst;
1211     INT32    nWidth, nHeight;
1212
1213     if ((himl == NULL) ||(i < 0) || (i >= himl->cCurImage))
1214         return 0;
1215
1216     nWidth = GetSystemMetrics32 (SM_CXICON);
1217     nHeight = GetSystemMetrics32 (SM_CYICON);
1218
1219     hdcSrc = CreateCompatibleDC32(0);
1220     hdcDst = CreateCompatibleDC32(0);
1221
1222     ii.fIcon = TRUE;
1223     ii.xHotspot = nWidth / 2;
1224     ii.yHotspot = nHeight / 2;
1225     ii.hbmMask  = CreateCompatibleBitmap32 (hdcDst, nWidth, nHeight);
1226     ii.hbmColor = CreateCompatibleBitmap32 (hdcDst, nWidth, nHeight);
1227
1228
1229     /* draw mask*/
1230     SelectObject32 (hdcDst, ii.hbmMask);
1231     if (himl->hbmMask) {
1232         SelectObject32 (hdcSrc, himl->hbmMask);
1233         BitBlt32 (hdcDst, 0, 0, nWidth, nHeight,
1234                   hdcSrc, i * himl->cx, 0, SRCCOPY);
1235     }
1236     else
1237         PatBlt32 (hdcDst, 0, 0, nWidth, nHeight, BLACKNESS);
1238
1239     /* draw image*/
1240     SelectObject32 (hdcDst, ii.hbmColor);
1241     SelectObject32 (hdcSrc, himl->hbmImage);
1242     BitBlt32 (hdcDst, 0, 0, nWidth, nHeight,
1243               hdcSrc, i * himl->cx, 0, SRCCOPY);
1244
1245     hIcon = CreateIconIndirect (&ii);    
1246
1247     DeleteDC32 (hdcSrc);
1248     DeleteDC32 (hdcDst);
1249     DeleteObject32 (ii.hbmMask);
1250     DeleteObject32 (ii.hbmColor);
1251
1252     return hIcon;
1253 }
1254
1255
1256 /*************************************************************************
1257  * ImageList_GetIconSize [COMCTL32.58]
1258  *
1259  * Retrieves the size of an image in an image list.
1260  *
1261  * PARAMS
1262  *     himl [I] image list handle
1263  *     cx   [O] pointer to the image width.
1264  *     cy   [O] pointer to the image height.
1265  *
1266  * RETURNS
1267  *     Success: TRUE
1268  *     Failure: FALSE
1269  *
1270  * NOTES
1271  *     All images in an image list have the same size.
1272  */
1273
1274 BOOL32 WINAPI
1275 ImageList_GetIconSize (HIMAGELIST himl, INT32 *cx, INT32 *cy)
1276 {
1277     if (himl == NULL)
1278         return FALSE;
1279     if ((himl->cx <= 0) || (himl->cy <= 0))
1280         return FALSE;
1281
1282     if (cx)
1283         *cx = himl->cx;
1284     if (cy)
1285         *cy = himl->cy;
1286
1287     return TRUE;
1288 }
1289
1290
1291 /*************************************************************************
1292  * ImageList_GetImageCount [COMCTL32.59]
1293  *
1294  * Returns the number of images in an image list.
1295  *
1296  * PARAMS
1297  *     himl [I] image list handle.
1298  *
1299  * RETURNS
1300  *     Success: Number of images.
1301  *     Failure: 0
1302  */
1303
1304 INT32 WINAPI
1305 ImageList_GetImageCount (HIMAGELIST himl)
1306 {
1307     if (himl == NULL)
1308         return 0;
1309
1310     return himl->cCurImage;
1311 }
1312
1313
1314 /*************************************************************************
1315  * ImageList_GetImageInfo [COMCTL32.60]
1316  *
1317  * Returns information about an image in an image list.
1318  *
1319  * PARAMS
1320  *     himl       [I] image list handle.
1321  *     i          [I] image index
1322  *     pImageInfo [O] pointer to the image information.
1323  *
1324  * RETURNS
1325  *     Success: TRUE
1326  *     Failure: FALSE
1327  */
1328
1329 BOOL32 WINAPI
1330 ImageList_GetImageInfo (HIMAGELIST himl, INT32 i, IMAGEINFO *pImageInfo)
1331 {
1332     if ((himl == NULL) || (pImageInfo == NULL))
1333         return FALSE;
1334     if ((i < 0) || (i >= himl->cCurImage))
1335         return FALSE;
1336
1337     pImageInfo->hbmImage = himl->hbmImage;
1338     pImageInfo->hbmMask  = himl->hbmMask;
1339     
1340     pImageInfo->rcImage.top    = 0;
1341     pImageInfo->rcImage.bottom = himl->cy;
1342     pImageInfo->rcImage.left   = i * himl->cx;
1343     pImageInfo->rcImage.right  = (i+1) * himl->cx;
1344     
1345     return TRUE;
1346 }
1347
1348
1349 /*************************************************************************
1350  * ImageList_GetImageRect [COMCTL32.61] 
1351  *
1352  * Retrieves the rectangle of the specified image in an image list.
1353  *
1354  * PARAMS
1355  *     himl   [I] handle to the image list
1356  *     i      [I] image index
1357  *     lpRect [O] pointer to the image rectangle
1358  *
1359  * RETURNS
1360  *    Success: TRUE
1361  *    Failure: FALSE
1362  *
1363  * NOTES
1364  *    This is an UNDOCUMENTED function!!!
1365  */
1366
1367 BOOL32 WINAPI
1368 ImageList_GetImageRect (HIMAGELIST himl, INT32 i, LPRECT32 lpRect)
1369 {
1370     if ((himl == NULL) || (lpRect == NULL))
1371         return FALSE;
1372     if ((i < 0) || (i >= himl->cCurImage))
1373         return FALSE;
1374
1375     lpRect->left   = i * himl->cx;
1376     lpRect->top    = 0;
1377     lpRect->right  = lpRect->left + himl->cx;
1378     lpRect->bottom = himl->cy;
1379
1380     return TRUE;
1381 }
1382
1383
1384 /*************************************************************************
1385  * ImageList_LoadImage32A [COMCTL32.62][COMCTL32.63]
1386  *
1387  * Creates an image list from a bitmap, icon or cursor.
1388  *
1389  * PARAMS
1390  *     hi      [I] instance handle
1391  *     lpbmp   [I] name or id of the image
1392  *     cx      [I] width of each image
1393  *     cGrow   [I] number of images to expand
1394  *     clrMask [I] mask color
1395  *     uType   [I] type of image to load
1396  *     uFlags  [I] loading flags
1397  *
1398  * RETURNS
1399  *     Success: handle of the loaded image
1400  *     Failure: NULL
1401  *
1402  * SEE
1403  *     LoadImage ()
1404  */
1405
1406 HIMAGELIST WINAPI
1407 ImageList_LoadImage32A (HINSTANCE32 hi, LPCSTR lpbmp, INT32 cx, INT32 cGrow,
1408                         COLORREF clrMask, UINT32 uType, UINT32 uFlags)
1409 {
1410     HIMAGELIST himl = NULL;
1411     HANDLE32   handle;
1412     INT32      nImageCount;
1413
1414     handle = LoadImage32A (hi, lpbmp, uType, 0, 0, uFlags);
1415     if (!handle) return (NULL);
1416
1417     if (uType == IMAGE_BITMAP) {
1418         BITMAP32 bmp;
1419         GetObject32A (handle, sizeof(BITMAP32), &bmp);
1420         nImageCount = bmp.bmWidth / cx;
1421
1422         himl = ImageList_Create (cx, bmp.bmHeight, ILC_MASK | ILC_COLOR,
1423                                  nImageCount, cGrow);
1424         ImageList_AddMasked (himl, (HBITMAP32)handle, clrMask);
1425     }
1426     else if ((uType == IMAGE_ICON) || (uType == IMAGE_CURSOR)) {
1427         ICONINFO ii;
1428         BITMAP32 bmp;
1429
1430         GetIconInfo (handle, &ii);
1431         GetObject32A (ii.hbmColor, sizeof(BITMAP32), (LPVOID)&bmp);
1432         himl = ImageList_Create (bmp.bmWidth, bmp.bmHeight, 
1433                                  ILC_MASK | ILC_COLOR, 1, cGrow);
1434         ImageList_Add (himl, ii.hbmColor, ii.hbmMask);
1435         DeleteObject32 (ii.hbmColor);
1436         DeleteObject32 (ii.hbmMask);
1437     }
1438
1439     DeleteObject32 (handle);
1440     
1441     return (himl);
1442 }
1443
1444
1445 /*************************************************************************
1446  * ImageList_LoadImage32W [COMCTL32.64]
1447  *
1448  * Creates an image list from a bitmap, icon or cursor.
1449  *
1450  * PARAMS
1451  *     hi      [I] instance handle
1452  *     lpbmp   [I] name or id of the image
1453  *     cx      [I] width of each image
1454  *     cGrow   [I] number of images to expand
1455  *     clrMask [I] mask color
1456  *     uType   [I] type of image to load
1457  *     uFlags  [I] loading flags
1458  *
1459  * RETURNS
1460  *     Success: handle of the loaded image
1461  *     Failure: NULL
1462  *
1463  * SEE
1464  *     LoadImage ()
1465  */
1466
1467 HIMAGELIST WINAPI
1468 ImageList_LoadImage32W (HINSTANCE32 hi, LPCWSTR lpbmp, INT32 cx, INT32 cGrow,
1469                         COLORREF clrMask, UINT32 uType, UINT32 uFlags)
1470 {
1471     HIMAGELIST himl = NULL;
1472     HANDLE32   handle;
1473     INT32      nImageCount;
1474
1475     handle = LoadImage32W (hi, lpbmp, uType, 0, 0, uFlags);
1476     if (!handle) {
1477         ERR (imagelist, "Error loading image!\n");
1478         return (NULL);
1479     }
1480
1481     if (uType == IMAGE_BITMAP) {
1482         BITMAP32 bmp;
1483         GetObject32A (handle, sizeof(BITMAP32), &bmp);
1484         nImageCount = bmp.bmWidth / cx;
1485
1486         himl = ImageList_Create (cx, bmp.bmHeight, ILC_MASK | ILC_COLOR,
1487                                  nImageCount, cGrow);
1488         ImageList_AddMasked (himl, (HBITMAP32)handle, clrMask);
1489     }
1490     else if ((uType == IMAGE_ICON) || (uType == IMAGE_CURSOR)) {
1491         ICONINFO ii;
1492         BITMAP32 bmp;
1493
1494         GetIconInfo (handle, &ii);
1495         GetObject32A (ii.hbmMask, sizeof(BITMAP32), (LPVOID)&bmp);
1496         himl = ImageList_Create (bmp.bmWidth, bmp.bmHeight, 
1497                                  ILC_MASK | ILC_COLOR, 1, cGrow);
1498         ImageList_Add (himl, ii.hbmColor, ii.hbmMask);
1499         DeleteObject32 (ii.hbmColor);
1500         DeleteObject32 (ii.hbmMask);
1501     }
1502
1503     DeleteObject32 (handle);
1504     
1505     return (himl);
1506 }
1507
1508
1509 /*************************************************************************
1510  * ImageList_Merge [COMCTL32.65] 
1511  *
1512  * Creates a new image list that contains a merged image from the specified
1513  * images of both source image lists.
1514  *
1515  * PARAMS
1516  *     himl1 [I] first image list handle
1517  *     i1    [I] first image index
1518  *     himl2 [I] second image list handle
1519  *     i2    [I] second image index
1520  *     dx    [I] X offset of the second image relative to the first.
1521  *     dy    [I] Y offset of the second image relative to the first.
1522  *
1523  * RETURNS
1524  *     Success: handle of the merged image list.
1525  *     Failure: NULL
1526  */
1527
1528 HIMAGELIST WINAPI
1529 ImageList_Merge (HIMAGELIST himl1, INT32 i1, HIMAGELIST himl2, INT32 i2,
1530                  INT32 dx, INT32 dy)
1531 {
1532     HIMAGELIST himlDst = NULL;
1533     HDC32      hdcSrcImage, hdcDstImage;
1534     INT32      cxDst, cyDst;
1535     INT32      xOff1, yOff1, xOff2, yOff2;
1536     INT32      nX1, nX2;
1537
1538     if ((himl1 == NULL) || (himl2 == NULL))
1539         return NULL;
1540
1541     /* check indices */
1542     if ((i1 < 0) || (i1 >= himl1->cCurImage)) {
1543         ERR (imagelist, "Index 1 out of range! %d\n", i1);
1544         return NULL;
1545     }
1546
1547     if ((i2 < 0) || (i2 >= himl2->cCurImage)) {
1548         ERR (imagelist, "Index 2 out of range! %d\n", i2);
1549         return NULL;
1550     }
1551
1552     if (dx > 0) {
1553         cxDst = _MAX (himl1->cx, dx + himl2->cx);
1554         xOff1 = 0;
1555         xOff2 = dx;
1556     }
1557     else if (dx < 0) {
1558         cxDst = _MAX (himl2->cx, himl1->cx - dx);
1559         xOff1 = -dx;
1560         xOff2 = 0;
1561     }
1562     else {
1563         cxDst = _MAX (himl1->cx, himl2->cx);
1564         xOff1 = 0;
1565         xOff2 = 0;
1566     }
1567
1568     if (dy > 0) {
1569         cyDst = _MAX (himl1->cy, dy + himl2->cy);
1570         yOff1 = 0;
1571         yOff2 = dy;
1572     }
1573     else if (dy < 0) {
1574         cyDst = _MAX (himl2->cy, himl1->cy - dy);
1575         yOff1 = -dy;
1576         yOff2 = 0;
1577     }
1578     else {
1579         cyDst = _MAX (himl1->cy, himl2->cy);
1580         yOff1 = 0;
1581         yOff2 = 0;
1582     }
1583
1584     himlDst = ImageList_Create (cxDst, cyDst, ILC_MASK | ILC_COLOR, 1, 1);
1585
1586     if (himlDst) {
1587         hdcSrcImage = CreateCompatibleDC32 (0);
1588         hdcDstImage = CreateCompatibleDC32 (0);
1589         nX1 = i1 * himl1->cx;
1590         nX2 = i2 * himl2->cx;
1591         
1592         /* copy image */
1593         SelectObject32 (hdcSrcImage, himl1->hbmImage);
1594         SelectObject32 (hdcDstImage, himlDst->hbmImage);
1595         BitBlt32 (hdcDstImage, 0, 0, cxDst, cyDst, 
1596                   hdcSrcImage, 0, 0, BLACKNESS);
1597         BitBlt32 (hdcDstImage, xOff1, yOff1, himl1->cx, himl1->cy, 
1598                   hdcSrcImage, nX1, 0, SRCCOPY);
1599
1600         SelectObject32 (hdcSrcImage, himl2->hbmMask);
1601         BitBlt32 (hdcDstImage, xOff2, yOff2, himl2->cx, himl2->cy, 
1602                   hdcSrcImage, nX2, 0, SRCAND);
1603
1604         SelectObject32 (hdcSrcImage, himl2->hbmImage);
1605         BitBlt32 (hdcDstImage, xOff2, yOff2, himl2->cx, himl2->cy, 
1606                   hdcSrcImage, nX2, 0, SRCPAINT);
1607
1608         /* copy mask */
1609         SelectObject32 (hdcSrcImage, himl1->hbmMask);
1610         SelectObject32 (hdcDstImage, himlDst->hbmMask);
1611         BitBlt32 (hdcDstImage, 0, 0, cxDst, cyDst, 
1612                   hdcSrcImage, 0, 0, WHITENESS);
1613         BitBlt32 (hdcDstImage, xOff1, yOff1, himl1->cx, himl1->cy, 
1614                   hdcSrcImage, nX1, 0, SRCCOPY);
1615
1616         SelectObject32 (hdcSrcImage, himl2->hbmMask);
1617         BitBlt32 (hdcDstImage, xOff2, yOff2, himl2->cx, himl2->cy, 
1618                   hdcSrcImage, nX2, 0, SRCAND);
1619
1620         DeleteDC32 (hdcSrcImage);
1621         DeleteDC32 (hdcDstImage);
1622     }
1623    
1624     return himlDst;
1625 }
1626
1627
1628 /*************************************************************************
1629  * ImageList_Read [COMCTL32.66]
1630  *
1631  * Reads an image list from a stream.
1632  *
1633  * PARAMS
1634  *     pstm [I] pointer to a stream
1635  *
1636  * RETURNS
1637  *     Success: image list handle
1638  *     Failure: NULL
1639  *
1640  * NOTES
1641  *     This function can not be implemented yet, because
1642  *     IStream32::Read is not implemented yet.
1643  *
1644  * BUGS
1645  *     empty stub.
1646  */
1647
1648 HIMAGELIST WINAPI ImageList_Read (LPSTREAM32 pstm)
1649 {
1650     FIXME (imagelist, "empty stub!\n");
1651
1652
1653     return (NULL);
1654 }
1655
1656
1657 /*************************************************************************
1658  * ImageList_Remove [COMCTL32.67] Removes an image from an image list
1659  *
1660  * PARAMS
1661  *     himl [I] image list handle
1662  *     i    [I] image index
1663  *
1664  * RETURNS
1665  *     Success: TRUE
1666  *     Failure: FALSE
1667  */
1668
1669 BOOL32 WINAPI
1670 ImageList_Remove (HIMAGELIST himl, INT32 i)
1671 {
1672     HBITMAP32 hbmNewImage, hbmNewMask;
1673     HDC32     hdcSrc, hdcDst;
1674     INT32     cxNew, nCount;
1675
1676     if ((i < -1) || (i >= himl->cCurImage)) {
1677         ERR (imagelist, "index out of range! %d\n", i);
1678         return FALSE;
1679     }
1680
1681     if (himl->cCurImage == 0) {
1682         ERR (imagelist, "image list is already empty!\n");
1683         return FALSE;
1684     }
1685
1686     if (i == -1) {
1687         /* remove all */
1688         TRACE (imagelist, "remove all!\n");
1689
1690         himl->cMaxImage = himl->cInitial + himl->cGrow;
1691         himl->cCurImage = 0;
1692         for (nCount = 0; nCount < MAX_OVERLAYIMAGE; nCount++)
1693              himl->nOvlIdx[nCount] = -1;
1694
1695         DeleteObject32 (himl->hbmImage);
1696         himl->hbmImage =
1697             CreateBitmap32 (himl->cMaxImage * himl->cx, himl->cy,
1698                             1, himl->uBitsPixel, NULL);
1699
1700         if (himl->hbmMask) {
1701             DeleteObject32 (himl->hbmMask);
1702             himl->hbmMask =
1703                 CreateBitmap32 (himl->cMaxImage * himl->cx, himl->cy,
1704                                 1, 1, NULL);
1705         }
1706     }
1707     else {
1708         /* delete one image */
1709         TRACE (imagelist, "Remove single image! %d\n", i);
1710
1711         /* create new bitmap(s) */
1712         cxNew = (himl->cCurImage + himl->cGrow - 1) * himl->cx;
1713
1714         TRACE(imagelist, " - Number of images: %d / %d (Old/New)\n",
1715                  himl->cCurImage, himl->cCurImage - 1);
1716         TRACE(imagelist, " - Max. number of images: %d / %d (Old/New)\n",
1717                  himl->cMaxImage, himl->cCurImage + himl->cGrow - 1);
1718         
1719         hbmNewImage =
1720             CreateBitmap32 (cxNew, himl->cy, 1, himl->uBitsPixel, NULL);
1721
1722         if (himl->hbmMask)
1723             hbmNewMask = CreateBitmap32 (cxNew, himl->cy, 1, 1, NULL);
1724         else
1725             hbmNewMask = 0;  /* Just to keep compiler happy! */
1726
1727         hdcSrc = CreateCompatibleDC32 (0);
1728         hdcDst = CreateCompatibleDC32 (0);
1729
1730         /* copy all images and masks prior to the "removed" image */
1731         if (i > 0) {
1732             TRACE (imagelist, "Pre image copy: Copy %d images\n", i);
1733        
1734             SelectObject32 (hdcSrc, himl->hbmImage);
1735             SelectObject32 (hdcDst, hbmNewImage);
1736             BitBlt32 (hdcDst, 0, 0, i * himl->cx, himl->cy,
1737                       hdcSrc, 0, 0, SRCCOPY);
1738
1739             if (himl->hbmMask) {
1740                 SelectObject32 (hdcSrc, himl->hbmMask);
1741                 SelectObject32 (hdcDst, hbmNewMask);
1742                 BitBlt32 (hdcDst, 0, 0, i * himl->cx, himl->cy,
1743                           hdcSrc, 0, 0, SRCCOPY);
1744             }
1745         }
1746
1747         /* copy all images and masks behind the removed image */
1748         if (i < himl->cCurImage - 1) {
1749             TRACE (imagelist, "Post image copy!\n");
1750             SelectObject32 (hdcSrc, himl->hbmImage);
1751             SelectObject32 (hdcDst, hbmNewImage);
1752             BitBlt32 (hdcDst, i * himl->cx, 0, (himl->cCurImage - i - 1) * himl->cx,
1753                       himl->cy, hdcSrc, (i + 1) * himl->cx, 0, SRCCOPY);
1754
1755             if (himl->hbmMask) {
1756                 SelectObject32 (hdcSrc, himl->hbmMask);
1757                 SelectObject32 (hdcDst, hbmNewMask);
1758                 BitBlt32 (hdcDst, i * himl->cx, 0,
1759                           (himl->cCurImage - i - 1) * himl->cx,
1760                           himl->cy, hdcSrc, (i + 1) * himl->cx, 0, SRCCOPY);
1761             }
1762         }
1763
1764         DeleteDC32 (hdcSrc);
1765         DeleteDC32 (hdcDst);
1766
1767         /* delete old images and insert new ones */
1768         DeleteObject32 (himl->hbmImage);
1769         himl->hbmImage = hbmNewImage;
1770         if (himl->hbmMask) {
1771             DeleteObject32 (himl->hbmMask);
1772             himl->hbmMask = hbmNewMask;
1773         }
1774
1775         himl->cCurImage--;
1776         himl->cMaxImage = himl->cCurImage + himl->cGrow;
1777     }
1778
1779     return TRUE;
1780 }
1781
1782
1783 /*************************************************************************
1784  * ImageList_Replace [COMCTL32.68] 
1785  *
1786  * Replaces an image in an image list with a new image.
1787  *
1788  * PARAMS
1789  *     himl     [I] image list handle
1790  *     i        [I] image index
1791  *     hbmImage [I] image bitmap handle
1792  *     hbmMask  [I] mask bitmap handle. Can be NULL.
1793  *
1794  * RETURNS
1795  *     Success: TRUE
1796  *     Failure: FALSE
1797  */
1798
1799 BOOL32 WINAPI
1800 ImageList_Replace (HIMAGELIST himl, INT32 i, HBITMAP32 hbmImage,
1801                    HBITMAP32 hbmMask)
1802 {
1803     HDC32 hdcImageList, hdcImage;
1804     BITMAP32 bmp;
1805
1806     if (himl == NULL) {
1807         ERR (imagelist, "Invalid image list handle!\n");
1808         return FALSE;
1809     }
1810     
1811     if ((i >= himl->cCurImage) || (i < 0)) {
1812         ERR (imagelist, "Invalid image index!\n");
1813         return FALSE;
1814     }
1815
1816     hdcImageList = CreateCompatibleDC32 (0);
1817     hdcImage = CreateCompatibleDC32 (0);
1818     GetObject32A (hbmImage, sizeof(BITMAP32), (LPVOID)&bmp);
1819
1820     /* Replace Image */
1821     SelectObject32 (hdcImageList, himl->hbmImage);
1822     SelectObject32 (hdcImage, hbmImage);
1823
1824     StretchBlt32 (hdcImageList, i * himl->cx, 0, himl->cx, himl->cy,
1825                   hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
1826
1827     if (himl->hbmMask)
1828     {
1829         /* Replace Mask */
1830         SelectObject32 (hdcImageList, himl->hbmMask);
1831         SelectObject32 (hdcImage, hbmMask);
1832
1833         StretchBlt32 (hdcImageList, i * himl->cx, 0, himl->cx, himl->cy,
1834                       hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
1835     }
1836
1837     DeleteDC32 (hdcImage);
1838     DeleteDC32 (hdcImageList);
1839
1840     return TRUE;
1841 }
1842
1843
1844 /*************************************************************************
1845  * ImageList_ReplaceIcon [COMCTL32.69]
1846  *
1847  * Replaces an image in an image list using an icon.
1848  *
1849  * PARAMS
1850  *     himl  [I] image list handle
1851  *     i     [I] image index
1852  *     hIcon [I] icon handle
1853  *
1854  * RETURNS
1855  *     Success: index of the replaced image
1856  *     Failure: -1
1857  */
1858
1859 INT32 WINAPI
1860 ImageList_ReplaceIcon (HIMAGELIST himl, INT32 i, HICON32 hIcon)
1861 {
1862     HDC32     hdcImageList, hdcImage;
1863     INT32     nIndex;
1864     HBITMAP32 hbmOldSrc, hbmOldDst;
1865     ICONINFO  ii;
1866     BITMAP32  bmp;
1867
1868     TRACE (imagelist, "(0x%lx 0x%x 0x%x)\n", (DWORD)himl, i, hIcon);
1869
1870     if (himl == NULL)
1871         return -1;
1872     if ((i >= himl->cCurImage) || (i < -1))
1873         return -1;
1874
1875     GetIconInfo (hIcon, &ii);
1876     if (ii.hbmMask == 0)
1877         ERR (imagelist, "no mask!\n");
1878     if (ii.hbmColor == 0)
1879         ERR (imagelist, "no color!\n");
1880     GetObject32A (ii.hbmMask, sizeof(BITMAP32), (LPVOID)&bmp);
1881
1882     if (i == -1) {
1883         if (himl->cCurImage + 1 >= himl->cMaxImage)
1884             IMAGELIST_InternalExpandBitmaps (himl, 1);
1885
1886         nIndex = himl->cCurImage;
1887         himl->cCurImage++;
1888     }
1889     else
1890         nIndex = i;
1891
1892     hdcImageList = CreateCompatibleDC32 (0);
1893     TRACE (imagelist, "hdcImageList=0x%x!\n", hdcImageList);
1894     if (hdcImageList == 0)
1895         ERR (imagelist, "invalid hdcImageList!\n");
1896
1897     hdcImage = CreateCompatibleDC32 (0);
1898     TRACE (imagelist, "hdcImage=0x%x!\n", hdcImage);
1899     if (hdcImage == 0)
1900         ERR (imagelist, "invalid hdcImage!\n");
1901
1902     hbmOldDst = SelectObject32 (hdcImageList, himl->hbmImage);
1903     SetTextColor32( hdcImageList, RGB(0,0,0));
1904     SetBkColor32( hdcImageList, RGB(255,255,255));
1905     hbmOldSrc = SelectObject32 (hdcImage, ii.hbmColor);
1906     StretchBlt32 (hdcImageList, nIndex * himl->cx, 0, himl->cx, himl->cy,
1907                   hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
1908
1909     if (himl->hbmMask) {
1910         SelectObject32 (hdcImageList, himl->hbmMask);
1911         SelectObject32 (hdcImage, ii.hbmMask);
1912         StretchBlt32 (hdcImageList, nIndex * himl->cx, 0, himl->cx, himl->cy,
1913                       hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
1914     }
1915
1916     SelectObject32 (hdcImage, hbmOldSrc);
1917     SelectObject32 (hdcImageList, hbmOldDst);
1918
1919     if (hdcImageList)
1920         DeleteDC32 (hdcImageList);
1921     if (hdcImage)
1922         DeleteDC32 (hdcImage);
1923     if (ii.hbmColor)
1924         DeleteObject32 (ii.hbmColor);
1925     if (ii.hbmMask)
1926         DeleteObject32 (ii.hbmMask);
1927
1928     return nIndex;
1929 }
1930
1931
1932 /*************************************************************************
1933  * ImageList_SetBkColor [COMCTL32.70] 
1934  *
1935  * Sets the background color of an image list.
1936  *
1937  * PARAMS
1938  *     himl  [I] image list handle
1939  *     clrBk [I] background color
1940  *
1941  * RETURNS
1942  *     Success: previous background color
1943  *     Failure: CLR_NONE
1944  */
1945
1946 COLORREF WINAPI
1947 ImageList_SetBkColor (HIMAGELIST himl, COLORREF clrBk)
1948 {
1949     COLORREF clrOldBk;
1950
1951     if (himl == NULL)
1952         return CLR_NONE;
1953
1954     clrOldBk = himl->clrBk;
1955     himl->clrBk = clrBk;
1956     return clrOldBk;
1957 }
1958
1959
1960 /*************************************************************************
1961  * ImageList_SetDragCursorImage [COMCTL32.75]
1962  *
1963  * Combines the specified image with the current drag image
1964  *
1965  * PARAMS
1966  *     himlDrag  [I] drag image list handle
1967  *     iDrag     [I] drag image index
1968  *     dxHotspot [I] X position of the hot spot
1969  *     dyHotspot [I] Y position of the hot spot
1970  *
1971  * RETURNS
1972  *     Success: TRUE
1973  *     Failure: FALSE
1974  *
1975  * BUGS
1976  *     semi-stub.
1977  */
1978
1979 BOOL32 WINAPI
1980 ImageList_SetDragCursorImage (HIMAGELIST himlDrag, INT32 iDrag,
1981                               INT32 dxHotspot, INT32 dyHotspot)
1982 {
1983     HIMAGELIST himlTemp;
1984
1985     FIXME (imagelist, "semi-stub!\n");
1986
1987     if (himlInternalDrag == NULL)
1988         return FALSE;
1989
1990     TRACE (imagelist, " dxH=%d dyH=%d nX=%d nY=%d\n",
1991            dxHotspot, dyHotspot, nInternalDragHotspotX, nInternalDragHotspotY);
1992
1993     himlTemp = ImageList_Merge (himlInternalDrag, 0, himlDrag, iDrag,
1994                                 dxHotspot, dyHotspot);
1995
1996     ImageList_Destroy (himlInternalDrag);
1997     himlInternalDrag = himlTemp;
1998
1999     nInternalDragHotspotX = dxHotspot;
2000     nInternalDragHotspotY = dyHotspot;
2001
2002     return FALSE;
2003 }
2004
2005
2006 /*************************************************************************
2007  * ImageList_SetFilter [COMCTL32.76] 
2008  *
2009  * Sets a filter (or does something completely different)!!???
2010  *
2011  * PARAMS
2012  *     himl     [I] ???
2013  *     i        [I] ???
2014  *     dwFilter [I] ???
2015  *
2016  * RETURNS
2017  *     Success: TRUE ???
2018  *     Failure: FALSE ???
2019  *
2020  * BUGS
2021  *     This is an UNDOCUMENTED function!!!!
2022  *     empty stub.
2023  */
2024
2025 BOOL32 WINAPI
2026 ImageList_SetFilter (HIMAGELIST himl, INT32 i, DWORD dwFilter)
2027 {
2028     FIXME (imagelist, "(%p 0x%x 0x%lx):empty stub!\n",
2029            himl, i, dwFilter);
2030
2031     return FALSE;
2032 }
2033
2034
2035 /*************************************************************************
2036  * ImageList_SetIconSize [COMCTL32.77]
2037  *
2038  * Sets the image size of the bitmap and deletes all images.
2039  *
2040  * PARAMS
2041  *     himl [I] handle to image list
2042  *     cx   [I] image width
2043  *     cy   [I] image height
2044  *
2045  * RETURNS
2046  *     Success: TRUE
2047  *     Failure: FALSE
2048  */
2049
2050 BOOL32 WINAPI
2051 ImageList_SetIconSize (HIMAGELIST himl, INT32 cx, INT32 cy)
2052 {
2053     INT32 nCount;
2054
2055     if (!himl)
2056         return FALSE;
2057
2058     /* remove all images*/
2059     himl->cMaxImage = himl->cInitial + himl->cGrow;
2060     himl->cCurImage = 0;
2061     himl->cx        = cx;
2062     himl->cy        = cy;
2063
2064     /* initialize overlay mask indices */
2065     for (nCount = 0; nCount < MAX_OVERLAYIMAGE; nCount++)
2066         himl->nOvlIdx[nCount] = -1;
2067
2068     DeleteObject32 (himl->hbmImage);
2069     himl->hbmImage =
2070         CreateBitmap32 (himl->cMaxImage * himl->cx, himl->cy,
2071                         1, himl->uBitsPixel, NULL);
2072
2073     if (himl->hbmMask) {
2074         DeleteObject32 (himl->hbmMask);
2075         himl->hbmMask =
2076             CreateBitmap32 (himl->cMaxImage * himl->cx, himl->cy,
2077                             1, 1, NULL);
2078     }
2079
2080     return TRUE;
2081 }
2082
2083
2084 /*************************************************************************
2085  * ImageList_SetImageCount [COMCTL32.78]
2086  *
2087  * Resizes an image list to the specified number of images.
2088  *
2089  * PARAMS
2090  *     himl        [I] handle to image list
2091  *     iImageCount [I] number of images in the image list
2092  *
2093  * RETURNS
2094  *     Success: TRUE
2095  *     Failure: FALSE
2096  */
2097
2098 BOOL32 WINAPI
2099 ImageList_SetImageCount (HIMAGELIST himl, INT32 iImageCount)
2100 {
2101     HDC32     hdcImageList, hdcBitmap;
2102     HBITMAP32 hbmNewBitmap;
2103     INT32     nNewCount, nCopyCount;
2104
2105     if (!himl)
2106         return FALSE;
2107     if (himl->cCurImage <= iImageCount)
2108         return FALSE;
2109     if (himl->cMaxImage > iImageCount)
2110         return TRUE;
2111
2112     nNewCount = iImageCount + himl->cGrow;
2113     nCopyCount = _MIN(himl->cCurImage, iImageCount);
2114
2115     hdcImageList = CreateCompatibleDC32 (0);
2116     hdcBitmap = CreateCompatibleDC32 (0);
2117
2118     hbmNewBitmap = CreateBitmap32 (nNewCount * himl->cx, himl->cy,
2119                                    1, himl->uBitsPixel, NULL);
2120     if (hbmNewBitmap == 0)
2121     {
2122         SelectObject32 (hdcImageList, himl->hbmImage);
2123         SelectObject32 (hdcBitmap, hbmNewBitmap);
2124
2125         /* copy images */
2126         BitBlt32 (hdcBitmap, 0, 0, nCopyCount * himl->cx, himl->cy,
2127                   hdcImageList, 0, 0, SRCCOPY);
2128
2129         /* delete 'empty' image space */
2130         SetBkColor32 (hdcBitmap, RGB(255, 255, 255));
2131         SetTextColor32 (hdcBitmap, RGB(0, 0, 0));
2132         PatBlt32 (hdcBitmap,  nCopyCount * himl->cx, 0, 
2133                   (nNewCount - nCopyCount) * himl->cx, himl->cy, BLACKNESS);
2134
2135         DeleteObject32 (himl->hbmImage);
2136         himl->hbmImage = hbmNewBitmap;
2137     }
2138     else
2139         ERR (imagelist, "Could not create new image bitmap !\n");
2140
2141     if (himl->hbmMask)
2142     {
2143         hbmNewBitmap = CreateBitmap32 (nNewCount * himl->cx, himl->cy,
2144                                        1, 1, NULL);
2145         if (hbmNewBitmap != 0)
2146         {
2147             SelectObject32 (hdcImageList, himl->hbmMask);
2148             SelectObject32 (hdcBitmap, hbmNewBitmap);
2149
2150             /* copy images */
2151             BitBlt32 (hdcBitmap, 0, 0, nCopyCount * himl->cx, himl->cy,
2152                       hdcImageList, 0, 0, SRCCOPY);
2153
2154             /* delete 'empty' image space */
2155             SetBkColor32 (hdcBitmap, RGB(255, 255, 255));
2156             SetTextColor32 (hdcBitmap, RGB(0, 0, 0));
2157             PatBlt32 (hdcBitmap,  nCopyCount * himl->cx, 0, 
2158                       (nNewCount - nCopyCount) * himl->cx, himl->cy, BLACKNESS);
2159
2160             DeleteObject32 (himl->hbmMask);
2161             himl->hbmMask = hbmNewBitmap;
2162         }
2163         else
2164             ERR (imagelist, "Could not create new mask bitmap!\n");
2165     }
2166
2167     DeleteDC32 (hdcImageList);
2168     DeleteDC32 (hdcBitmap);
2169
2170     /* Update max image count and current image count */
2171     himl->cMaxImage = nNewCount;
2172     if (himl->cCurImage > nCopyCount)
2173         himl->cCurImage = nCopyCount;
2174
2175     return TRUE;
2176 }
2177
2178
2179 /*************************************************************************
2180  * ImageList_SetOverlayImage [COMCTL32.79]
2181  *
2182  * Assigns an overlay mask index to an existing image in an image list.
2183  *
2184  * PARAMS
2185  *     himl     [I] image list handle
2186  *     iImage   [I] image index
2187  *     iOverlay [I] overlay mask index
2188  *
2189  * RETURNS
2190  *     Success: TRUE
2191  *     Failure: FALSE
2192  */
2193
2194 BOOL32 WINAPI
2195 ImageList_SetOverlayImage (HIMAGELIST himl, INT32 iImage, INT32 iOverlay)
2196 {
2197     if (!himl)
2198         return FALSE;
2199     if ((iOverlay < 1) || (iOverlay > MAX_OVERLAYIMAGE))
2200         return FALSE;
2201     if ((iImage < 0) || (iImage > himl->cCurImage))
2202         return FALSE;
2203     
2204     himl->nOvlIdx[iOverlay - 1] = iImage;
2205     return TRUE;
2206 }
2207
2208
2209 /*************************************************************************
2210  * ImageList_Write [COMCTL32.80]
2211  *
2212  * Writes an image list to a stream.
2213  *
2214  * PARAMS
2215  *     himl [I] Image list handle.
2216  *     pstm [O] Pointer to a stream.
2217  *
2218  * RETURNS
2219  *     Success: TRUE
2220  *     Failure: FALSE
2221  *
2222  * NOTES
2223  *     This function can not be implemented yet, because
2224  *     IStream32::Write is not implemented.
2225  *
2226  * BUGS
2227  *     empty stub.
2228  */
2229
2230 BOOL32 WINAPI
2231 ImageList_Write (HIMAGELIST himl, LPSTREAM32 pstm)
2232 {
2233     if (!himl)
2234         return FALSE;
2235
2236     FIXME (imagelist, "empty stub!\n");
2237
2238     return FALSE;
2239 }
2240