- stupid spelling fixes
[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_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 implemented, the functions mentioned above will be 
22  *      limited in functionality too.
23  */
24
25 #include "winerror.h"
26 #include "winbase.h"
27 #include "wine/obj_base.h"
28 #include "wine/obj_storage.h"
29 #include "commctrl.h"
30 #include "imagelist.h"
31 #include "debugtools.h"
32
33 DEFAULT_DEBUG_CHANNEL(imagelist);
34
35
36 #define _MAX(a,b) (((a)>(b))?(a):(b))
37 #define _MIN(a,b) (((a)>(b))?(b):(a))
38
39 #define MAX_OVERLAYIMAGE 15
40
41
42 /* internal image list data used for Drag & Drop operations */
43
44 static HIMAGELIST himlInternalDrag = NULL;
45 static INT      nInternalDragHotspotX = 0;
46 static INT      nInternalDragHotspotY = 0;
47
48 static HWND     hwndInternalDrag = 0;
49 static INT      xInternalPos = 0;
50 static INT      yInternalPos = 0;
51
52 static HDC      hdcBackBuffer = 0;
53 static HBITMAP  hbmBackBuffer = 0;
54
55
56 /*************************************************************************
57  * IMAGELIST_InternalExpandBitmaps [Internal] 
58  *
59  * Expands the bitmaps of an image list by the given number of images.
60  *
61  * PARAMS
62  *     himl        [I] handle to image list
63  *     nImageCount [I] number of images to add
64  *
65  * RETURNS
66  *     nothing
67  *
68  * NOTES
69  *     This function can NOT be used to reduce the number of images.
70  */
71 static VOID
72 IMAGELIST_InternalExpandBitmaps (HIMAGELIST himl, INT nImageCount, INT cx, INT cy)
73 {
74     HDC     hdcImageList, hdcBitmap;
75     HBITMAP hbmNewBitmap;
76     INT     nNewWidth, nNewCount;
77
78     if ((himl->cCurImage + nImageCount < himl->cMaxImage)
79         && (himl->cy >= cy))
80         return;
81
82     if (cy == 0) cy = himl->cy;
83     nNewCount = himl->cCurImage + nImageCount + himl->cGrow;
84     nNewWidth = nNewCount * himl->cx;
85
86     TRACE("Create expanded bitmaps : himl=%p x=%d y=%d count=%d\n", himl, nNewWidth, cy, nNewCount);
87     hdcImageList = CreateCompatibleDC (0);
88     hdcBitmap = CreateCompatibleDC (0);
89
90     hbmNewBitmap =
91         CreateBitmap (nNewWidth, cy, 1, himl->uBitsPixel, NULL);
92     if (hbmNewBitmap == 0)
93         ERR("creating new image bitmap (x=%d y=%d)!\n", nNewWidth, cy);
94
95     SelectObject (hdcImageList, himl->hbmImage);
96     SelectObject (hdcBitmap, hbmNewBitmap);
97     BitBlt (hdcBitmap, 0, 0, himl->cCurImage * himl->cx, cy,
98               hdcImageList, 0, 0, SRCCOPY);
99
100     DeleteObject (himl->hbmImage);
101     himl->hbmImage = hbmNewBitmap;
102
103     if (himl->hbmMask) {
104         hbmNewBitmap = 
105             CreateBitmap (nNewWidth, cy, 1, 1, NULL);
106
107         if (hbmNewBitmap == 0)
108             ERR("creating new mask bitmap!\n");
109
110         SelectObject (hdcImageList, himl->hbmMask);
111         SelectObject (hdcBitmap, hbmNewBitmap);
112         BitBlt (hdcBitmap, 0, 0, himl->cCurImage * himl->cx, cy,
113                   hdcImageList, 0, 0, SRCCOPY);
114         DeleteObject (himl->hbmMask);
115         himl->hbmMask = hbmNewBitmap;
116     }
117
118     himl->cMaxImage = nNewCount;
119
120     DeleteDC (hdcImageList);
121     DeleteDC (hdcBitmap);
122 }
123
124
125 /*************************************************************************
126  * IMAGELIST_InternalDraw [Internal] 
127  *
128  * Draws the image in the ImageList (without the mask)
129  *
130  * PARAMS
131  *     pimldp        [I] pointer to IMAGELISTDRAWPARAMS structure.
132  *     cx            [I] the width of the image to display
133  *     cy............[I] the height of the image to display
134  *
135  * RETURNS
136  *     nothing
137  *
138  * NOTES
139  *     This functions is used by ImageList_DrawIndirect, when it is 
140  *     required to draw only the Image (without the mask) to the screen.
141  *
142  *     Blending and Overlays styles are accomplised by another function
143  */
144 static VOID
145 IMAGELIST_InternalDraw(IMAGELISTDRAWPARAMS *pimldp, INT cx, INT cy)
146 {
147     HDC hImageDC;
148     HBITMAP hOldBitmap;
149
150     hImageDC = CreateCompatibleDC(0);
151     hOldBitmap = SelectObject(hImageDC, pimldp->himl->hbmImage);
152     BitBlt(pimldp->hdcDst, 
153         pimldp->x, pimldp->y, cx, cy,
154         hImageDC, 
155         pimldp->himl->cx * pimldp->i, 0, 
156         SRCCOPY);
157
158     SelectObject(hImageDC, hOldBitmap);
159     DeleteDC(hImageDC);
160 }
161
162
163 /*************************************************************************
164  * IMAGELIST_InternalDrawMask [Internal] 
165  *
166  * Draws the image in the ImageList witht the mask
167  *
168  * PARAMS
169  *     pimldp        [I] pointer to IMAGELISTDRAWPARAMS structure.
170  *     cx            [I] the width of the image to display
171  *     cy............[I] the height of the image to display
172  *
173  * RETURNS
174  *     nothing
175  *
176  * NOTES
177  *     This functions is used by ImageList_DrawIndirect, when it is 
178  *     required to draw the Image with the mask to the screen.
179  *
180  *     Blending and Overlays styles are accomplised by another function.
181  */
182 static VOID
183 IMAGELIST_InternalDrawMask(IMAGELISTDRAWPARAMS *pimldp, INT cx, INT cy)
184 {
185     HDC     hMaskDC, hImageDC;
186     BOOL bUseCustomBackground, bBlendFlag;
187     HBRUSH hBrush, hOldBrush;
188     HBITMAP hOldBitmapImage, hOldBitmapMask;
189     HIMAGELIST himlLocal = pimldp->himl;
190     COLORREF oldBkColor, oldFgColor;
191     UINT fStyle = pimldp->fStyle & (~ILD_OVERLAYMASK);
192
193     bUseCustomBackground = (himlLocal->clrBk != CLR_NONE);
194     bBlendFlag = (fStyle & ILD_BLEND50 ) || (fStyle & ILD_BLEND25);
195
196     hImageDC = CreateCompatibleDC(0);
197     hMaskDC = CreateCompatibleDC(0);
198
199     hOldBitmapImage = SelectObject(hImageDC, himlLocal->hbmImage);
200     hOldBitmapMask = SelectObject(hMaskDC, himlLocal->hbmMask);
201     /* Draw the Background for the appropriate Styles
202     */
203     if( bUseCustomBackground &&
204         (fStyle == ILD_NORMAL || fStyle & ILD_IMAGE || bBlendFlag))
205     {
206         hBrush = CreateSolidBrush (himlLocal->clrBk);
207         hOldBrush = SelectObject (pimldp->hdcDst, hBrush);
208         PatBlt (pimldp->hdcDst, 
209             pimldp->x, pimldp->y, cx, cy, 
210             PATCOPY);
211
212         DeleteObject (SelectObject (pimldp->hdcDst, hOldBrush));
213     }
214
215     /* Draw Image Transparently over the current background
216     */
217     if(fStyle == ILD_NORMAL
218         || (fStyle & ILD_TRANSPARENT)
219         || ((fStyle & ILD_IMAGE) && bUseCustomBackground)
220         || bBlendFlag)
221     {
222         /* to obtain a transparent look, background color should be set
223            to white and foreground color to black when blting the 
224            monochrome mask. */
225         oldBkColor = SetBkColor(pimldp->hdcDst, RGB(0xff, 0xff, 0xff)); 
226         oldFgColor = SetTextColor(pimldp->hdcDst, RGB(0, 0, 0));
227
228         BitBlt(pimldp->hdcDst, 
229             pimldp->x, pimldp->y, cx, cy,
230             hMaskDC, 
231             himlLocal->cx * pimldp->i, 0, 
232             SRCAND);
233
234         BitBlt(pimldp->hdcDst, 
235             pimldp->x, pimldp->y, cx, cy,
236             hImageDC, 
237             himlLocal->cx * pimldp->i, 0, 
238             SRCPAINT);
239
240         SetBkColor(pimldp->hdcDst, oldBkColor); 
241         SetTextColor(pimldp->hdcDst, oldFgColor);
242     }
243     /* Draw the image when no Background is specified
244     */
245     else if((fStyle & ILD_IMAGE) && !bUseCustomBackground)
246     {
247         BitBlt(pimldp->hdcDst, 
248             pimldp->x, pimldp->y, cx, cy,
249             hImageDC, 
250             himlLocal->cx * pimldp->i, 0, 
251             SRCCOPY);
252     }
253     /* Draw the mask with or without a background
254     */
255     else if(fStyle & ILD_MASK)
256     {
257         BitBlt(pimldp->hdcDst, 
258             pimldp->x, pimldp->y, cx, cy,
259             hMaskDC, 
260             himlLocal->cx * pimldp->i, 0,
261             bUseCustomBackground ? SRCCOPY : SRCAND);
262     }
263     SelectObject(hImageDC, hOldBitmapImage);
264     SelectObject(hMaskDC, hOldBitmapMask);
265     DeleteDC(hImageDC);
266     DeleteDC(hMaskDC);
267 }
268
269 /*************************************************************************
270  * IMAGELIST_InternalDrawBlend [Internal] 
271  *
272  * Draws the Blend over the current image 
273  *
274  * PARAMS
275  *     pimldp        [I] pointer to IMAGELISTDRAWPARAMS structure.
276  *     cx            [I] the width of the image to display
277  *     cy............[I] the height of the image to display
278  *
279  * RETURNS
280  *     nothing
281  *
282  * NOTES
283  *     This functions is used by ImageList_DrawIndirect, when it is 
284  *     required to add the blend to the current image.  
285  *     
286  */
287 static VOID
288 IMAGELIST_InternalDrawBlend(IMAGELISTDRAWPARAMS *pimldp, INT cx, INT cy)
289 {
290
291     HDC         hBlendMaskDC,hMaskDC;
292     HBRUSH      hBlendColorBrush, hBlendBrush, hOldBrush;
293     HBITMAP     hBlendMaskBitmap, hOldBitmap;
294     COLORREF    clrBlend, OldTextColor, OldBkColor;
295     HIMAGELIST  himlLocal = pimldp->himl;
296
297     clrBlend = GetSysColor (COLOR_HIGHLIGHT);
298     if (!(pimldp->rgbFg == CLR_DEFAULT))
299     {
300         clrBlend = pimldp->rgbFg;
301     }
302     /* Create the blend Mask
303     */
304     hBlendMaskDC = CreateCompatibleDC(0);
305     hBlendBrush = pimldp->fStyle & ILD_BLEND50 ?
306         himlLocal->hbrBlend50 : himlLocal->hbrBlend25;
307
308     hBlendMaskBitmap = CreateBitmap(cx, cy, 1, 1, NULL);
309     hOldBitmap = SelectObject(hBlendMaskDC, hBlendMaskBitmap);
310
311     hOldBrush = (HBRUSH) SelectObject(hBlendMaskDC, hBlendBrush);
312     PatBlt(hBlendMaskDC, 0, 0, cx, cy, PATCOPY);
313     SelectObject(hBlendMaskDC, hOldBrush);
314
315     /* Modify the blend mask if an Image Mask exist
316     */
317     if(pimldp->himl->hbmMask != 0)
318     {
319         HBITMAP hOldMaskBitmap;
320         hMaskDC = CreateCompatibleDC(0);
321         hOldMaskBitmap = (HBITMAP) SelectObject(hMaskDC, himlLocal->hbmMask);
322
323         BitBlt(hBlendMaskDC,
324             0,0, cx, cy, 
325             hMaskDC,
326             himlLocal->cx * pimldp->i,0,
327             0x220326); /* NOTSRCAND */
328
329         BitBlt(hBlendMaskDC,
330             0,0, cx, cy, 
331             hBlendMaskDC,
332             0,0, 
333             NOTSRCCOPY);
334
335         SelectObject(hMaskDC, hOldMaskBitmap);
336         DeleteDC(hMaskDC);
337
338     }
339     /* Apply blend to the current image given the BlendMask
340     */
341     OldTextColor = SetTextColor(pimldp->hdcDst, 0);
342     OldBkColor = SetBkColor(pimldp->hdcDst, RGB(255,255,255));
343     hBlendColorBrush = CreateSolidBrush(clrBlend);
344     hOldBrush = (HBRUSH) SelectObject (pimldp->hdcDst, hBlendColorBrush);
345
346     BitBlt (pimldp->hdcDst, 
347         pimldp->x, pimldp->y, cx, cy, 
348         hBlendMaskDC, 
349         0, 0, 
350         0xB8074A); /* PSDPxax */
351
352     SelectObject(pimldp->hdcDst, hOldBrush);
353     SetTextColor(pimldp->hdcDst, OldTextColor);
354     SetBkColor(pimldp->hdcDst, OldBkColor);
355     SelectObject(hBlendMaskDC, hOldBitmap);
356     DeleteDC(hBlendMaskDC);
357     DeleteObject(hBlendMaskBitmap);
358     DeleteObject(hBlendColorBrush);
359 }
360
361 /*************************************************************************
362  * IMAGELIST_InternalDrawOverlay [Internal] 
363  *
364  * Draws the overlay image 
365  *
366  * PARAMS
367  *     pimldp        [I] pointer to IMAGELISTDRAWPARAMS structure.
368  *     cx            [I] the width of the image to display
369  *     cy............[I] the height of the image to display
370  *
371  * RETURNS
372  *     nothing
373  *
374  * NOTES
375  *     This functions is used by ImageList_DrawIndirect, when it is 
376  *     required to draw the overlay
377  *
378  *     
379  */
380 static VOID 
381 IMAGELIST_InternalDrawOverlay(IMAGELISTDRAWPARAMS *pimldp, INT cx, INT cy)
382 {
383     INT     nOvlIdx;
384     HDC     hImageDC;
385     HBITMAP hOldBitmap;
386
387     nOvlIdx = (pimldp->fStyle & ILD_OVERLAYMASK) >> 8;
388     if ((nOvlIdx >= 1) && (nOvlIdx <= MAX_OVERLAYIMAGE))
389     {
390         nOvlIdx = pimldp->himl->nOvlIdx[nOvlIdx - 1];
391         if ((nOvlIdx >= 0) && (nOvlIdx <= pimldp->himl->cCurImage))
392         {
393             hImageDC = CreateCompatibleDC(0);
394             if (pimldp->himl->hbmMask)
395             {
396                 hOldBitmap = (HBITMAP) SelectObject (hImageDC, 
397                     pimldp->himl->hbmMask);
398
399                 BitBlt (pimldp->hdcDst, 
400                     pimldp->x, pimldp->y, cx, cy,
401                     hImageDC, pimldp->himl->cx * nOvlIdx, 0,
402                     SRCAND);
403
404                 SelectObject(hImageDC, hOldBitmap);
405             }
406             hOldBitmap = (HBITMAP) SelectObject (hImageDC, 
407                 pimldp->himl->hbmImage);
408
409             BitBlt (pimldp->hdcDst, 
410                 pimldp->x, pimldp->y, cx, cy, 
411                 hImageDC,
412                 pimldp->himl->cx * nOvlIdx, 0,
413                 SRCPAINT);
414
415             SelectObject(hImageDC, hOldBitmap);
416             DeleteDC(hImageDC);
417         }
418     }
419 }
420
421
422
423
424
425 /*************************************************************************
426  * ImageList_Add [COMCTL32.39]
427  *
428  * Add an image or images to an image list.
429  *
430  * PARAMS
431  *     himl     [I] handle to image list
432  *     hbmImage [I] handle to image bitmap
433  *     hbmMask  [I] handle to mask bitmap
434  *
435  * RETURNS
436  *     Success: Index of the first new image.
437  *     Failure: -1
438  */
439
440 INT WINAPI
441 ImageList_Add (HIMAGELIST himl, HBITMAP hbmImage, HBITMAP hbmMask)
442 {
443     HDC     hdcImage, hdcBitmap;
444     INT     nFirstIndex, nImageCount;
445     INT     nStartX;
446     BITMAP  bmp;
447     HBITMAP hOldBitmapImage, hOldBitmap;
448
449     TRACE("himl=%p hbmimage=%x hbmmask=%x\n", himl, hbmImage, hbmMask);
450     if (!himl || !hbmImage)
451         return -1;
452
453     GetObjectA (hbmImage, sizeof(BITMAP), (LPVOID)&bmp);
454     nImageCount = bmp.bmWidth / himl->cx;
455
456     IMAGELIST_InternalExpandBitmaps (himl, nImageCount, bmp.bmWidth, bmp.bmHeight);
457
458     nStartX = himl->cCurImage * himl->cx;
459
460     hdcImage  = CreateCompatibleDC(0);
461     hdcBitmap = CreateCompatibleDC(0);
462
463     hOldBitmapImage = SelectObject(hdcImage, himl->hbmImage);
464     hOldBitmap = SelectObject(hdcBitmap, hbmImage);
465
466     /* Copy result to the imagelist
467     */
468     BitBlt (hdcImage, nStartX, 0, bmp.bmWidth, bmp.bmHeight,
469         hdcBitmap, 0, 0, SRCCOPY);
470
471     if(himl->hbmMask)
472     {
473         HDC hdcMask, hdcTemp, hOldBitmapMask, hOldBitmapTemp;
474
475         hdcMask   = CreateCompatibleDC (0);
476         hdcTemp   = CreateCompatibleDC(0);
477         hOldBitmapMask = (HBITMAP) SelectObject(hdcMask, himl->hbmMask);
478         hOldBitmapTemp = (HBITMAP) SelectObject(hdcTemp, hbmMask);
479
480         BitBlt (hdcMask, 
481             nStartX, 0, bmp.bmWidth, bmp.bmHeight,
482             hdcTemp, 
483             0, 0, 
484             SRCCOPY);
485
486         SelectObject(hdcTemp, hOldBitmapTemp);
487         DeleteDC(hdcTemp);
488
489         /* Remove the background from the image
490         */
491         BitBlt (hdcImage, 
492             nStartX, 0, bmp.bmWidth, bmp.bmHeight,
493             hdcMask, 
494             nStartX, 0, 
495             0x220326); /* NOTSRCAND */
496
497         SelectObject(hdcMask, hOldBitmapMask);
498         DeleteDC(hdcMask);
499     }
500
501     SelectObject(hdcImage, hOldBitmapImage);
502     SelectObject(hdcBitmap, hOldBitmap);
503     DeleteDC(hdcImage);
504     DeleteDC(hdcBitmap);
505
506     nFirstIndex = himl->cCurImage;
507     himl->cCurImage += nImageCount;
508
509     return nFirstIndex;
510 }
511
512
513 /*************************************************************************
514  * ImageList_AddIcon [COMCTL32.40]
515  *
516  * Adds an icon to an image list.
517  *
518  * PARAMS
519  *     himl  [I] handle to image list
520  *     hIcon [I] handle to icon
521  *
522  * RETURNS
523  *     Success: index of the new image
524  *     Failure: -1
525  */
526
527 INT WINAPI
528 ImageList_AddIcon (HIMAGELIST himl, HICON hIcon)
529 {
530     return ImageList_ReplaceIcon (himl, -1, hIcon);
531 }
532
533
534 /*************************************************************************
535  * ImageList_AddMasked [COMCTL32.41] 
536  *
537  * Adds an image or images to an image list and creates a mask from the
538  * specified bitmap using the mask color.
539  *
540  * PARAMS
541  *     himl    [I] handle to image list.
542  *     hBitmap [I] handle to bitmap
543  *     clrMask [I] mask color.
544  *
545  * RETURNS
546  *     Success: Index of the first new image.
547  *     Failure: -1
548  */
549
550 INT WINAPI
551 ImageList_AddMasked (HIMAGELIST himl, HBITMAP hBitmap, COLORREF clrMask)
552 {
553     HDC    hdcImage, hdcMask, hdcBitmap;
554     INT    nIndex, nImageCount, nMaskXOffset=0;
555     BITMAP bmp;
556     HBITMAP hOldBitmap, hOldBitmapMask, hOldBitmapImage;
557     HBITMAP hMaskBitmap=0;
558     COLORREF bkColor;
559
560     TRACE("himl=%p hbitmap=%x clrmask=%lx\n", himl, hBitmap, clrMask);
561     if (himl == NULL)
562         return -1;
563
564     if (!GetObjectA (hBitmap, sizeof(BITMAP), &bmp))
565         return -1;
566
567     nImageCount = bmp.bmWidth / himl->cx;
568
569     IMAGELIST_InternalExpandBitmaps (himl, nImageCount, bmp.bmWidth, bmp.bmHeight);
570
571     nIndex = himl->cCurImage;
572     himl->cCurImage += nImageCount;
573
574     hdcMask   = CreateCompatibleDC (0);
575     hdcImage  = CreateCompatibleDC(0);
576     hdcBitmap = CreateCompatibleDC(0);
577
578
579     hOldBitmapImage = SelectObject(hdcImage, himl->hbmImage);
580     hOldBitmap = SelectObject(hdcBitmap, hBitmap);
581     if(himl->hbmMask)
582     {
583         hOldBitmapMask = SelectObject(hdcMask, himl->hbmMask);
584         nMaskXOffset = nIndex * himl->cx;
585     }
586     else
587     {
588         /*
589             Create a temp Mask so we can remove the background of
590             the Image (Windows does this even if there is no mask)
591         */
592         hMaskBitmap = CreateBitmap(bmp.bmWidth, bmp.bmHeight, 1, 1, NULL);
593         hOldBitmapMask = SelectObject(hdcMask, hMaskBitmap);
594         nMaskXOffset = 0;
595     }
596     /* create monochrome image to the mask bitmap */
597     bkColor = (clrMask != CLR_DEFAULT) ? clrMask :
598         GetPixel (hdcBitmap, 0, 0);
599     SetBkColor (hdcBitmap, bkColor);
600     BitBlt (hdcMask, 
601         nMaskXOffset, 0, bmp.bmWidth, bmp.bmHeight,
602         hdcBitmap, 0, 0, 
603         SRCCOPY);
604
605     SetBkColor(hdcBitmap, RGB(255,255,255));
606     /*Remove the background from the image
607     */
608     /*
609         WINDOWS BUG ALERT!!!!!!
610         The statement below should not be done in common practice
611         but this is how ImageList_AddMasked works in Windows.
612         It overwrites the original bitmap passed, this was discovered
613         by using the same bitmap to itterated the different styles
614         on windows where it failed (BUT ImageList_Add is OK)
615         This is here in case some apps really on this bug
616     */
617     BitBlt(hdcBitmap, 
618         0, 0, bmp.bmWidth, bmp.bmHeight,
619         hdcMask, 
620         nMaskXOffset, 0, 
621         0x220326); /* NOTSRCAND */
622     /* Copy result to the imagelist
623     */
624     BitBlt (hdcImage, 
625         nIndex * himl->cx, 0, bmp.bmWidth, bmp.bmHeight,
626         hdcBitmap, 
627         0, 0, 
628         SRCCOPY);
629     /* Clean up
630     */
631     SelectObject(hdcMask,hOldBitmapMask);
632     SelectObject(hdcImage, hOldBitmapImage);
633     SelectObject(hdcBitmap, hOldBitmap);
634     DeleteDC(hdcMask);
635     DeleteDC(hdcImage);
636     DeleteDC(hdcBitmap);
637     if(!himl->hbmMask)
638     {
639         DeleteObject(hMaskBitmap);
640     }
641
642     return nIndex;
643 }
644
645
646 /*************************************************************************
647  * ImageList_BeginDrag [COMCTL32.42] 
648  *
649  * Creates a temporary image list that contains one image. It will be used
650  * as a drag image.
651  *
652  * PARAMS
653  *     himlTrack [I] handle to the source image list
654  *     iTrack    [I] index of the drag image in the source image list
655  *     dxHotspot [I] X position of the hot spot of the drag image
656  *     dyHotspot [I] Y position of the hot spot of the drag image
657  *
658  * RETURNS
659  *     Success: TRUE
660  *     Failure: FALSE
661  */
662
663 BOOL WINAPI
664 ImageList_BeginDrag (HIMAGELIST himlTrack, INT iTrack,
665                      INT dxHotspot, INT dyHotspot)
666 {
667     HDC hdcSrc, hdcDst;
668
669     FIXME("partially implemented!\n");
670
671     if (himlTrack == NULL)
672         return FALSE;
673
674     if (himlInternalDrag)
675         ImageList_EndDrag ();
676
677     himlInternalDrag =
678         ImageList_Create (himlTrack->cx, himlTrack->cy,
679                           himlTrack->flags, 1, 1);
680     if (himlInternalDrag == NULL) {
681         ERR("Error creating drag image list!\n");
682         return FALSE;
683     }
684
685     nInternalDragHotspotX = dxHotspot;
686     nInternalDragHotspotY = dyHotspot;
687
688     hdcSrc = CreateCompatibleDC (0);
689     hdcDst = CreateCompatibleDC (0);
690
691     /* copy image */
692     SelectObject (hdcSrc, himlTrack->hbmImage);
693     SelectObject (hdcDst, himlInternalDrag->hbmImage);
694     StretchBlt (hdcDst, 0, 0, himlInternalDrag->cx, himlInternalDrag->cy, hdcSrc,
695                   iTrack * himlTrack->cx, 0, himlTrack->cx, himlTrack->cy, SRCCOPY);
696
697     /* copy mask */
698     SelectObject (hdcSrc, himlTrack->hbmMask);
699     SelectObject (hdcDst, himlInternalDrag->hbmMask);
700     StretchBlt (hdcDst, 0, 0, himlInternalDrag->cx, himlInternalDrag->cy, hdcSrc,
701                   iTrack * himlTrack->cx, 0, himlTrack->cx, himlTrack->cy, SRCCOPY);
702
703     DeleteDC (hdcSrc);
704     DeleteDC (hdcDst);
705
706     himlInternalDrag->cCurImage = 1;
707
708     return TRUE;
709 }
710
711
712 /*************************************************************************
713  * ImageList_Copy [COMCTL32.43] 
714  *
715  *  Copies an image of the source image list to an image of the 
716  *  destination image list. Images can be copied or swapped.
717  *
718  * PARAMS
719  *     himlDst [I] handle to the destination image list
720  *     iDst    [I] destination image index.
721  *     himlSrc [I] handle to the source image list
722  *     iSrc    [I] source image index
723  *     uFlags  [I] flags for the copy operation
724  *
725  * RETURNS
726  *     Success: TRUE
727  *     Failure: FALSE
728  *
729  * NOTES
730  *     Copying from one image list to another is possible. The original
731  *     implementation just copies or swapps within one image list.
732  *     Could this feature become a bug??? ;-)
733  */
734
735 BOOL WINAPI
736 ImageList_Copy (HIMAGELIST himlDst, INT iDst,   HIMAGELIST himlSrc,
737                 INT iSrc, INT uFlags)
738 {
739     HDC hdcSrc, hdcDst;    
740
741     TRACE("iDst=%d  iSrc=%d\n", iDst, iSrc);
742
743     if ((himlSrc == NULL) || (himlDst == NULL))
744         return FALSE;
745     if ((iDst < 0) || (iDst >= himlDst->cCurImage))
746         return FALSE;
747     if ((iSrc < 0) || (iSrc >= himlSrc->cCurImage))
748         return FALSE;
749
750     hdcSrc = CreateCompatibleDC (0);
751     if (himlDst == himlSrc)
752         hdcDst = hdcSrc;
753     else
754         hdcDst = CreateCompatibleDC (0);
755
756     if (uFlags & ILCF_SWAP) {
757         /* swap */
758         HBITMAP hbmTempImage, hbmTempMask;
759
760         /* create temporary bitmaps */
761         hbmTempImage = CreateBitmap (himlSrc->cx, himlSrc->cy, 1,
762                                        himlSrc->uBitsPixel, NULL);
763         hbmTempMask = CreateBitmap (himlSrc->cx, himlSrc->cy, 1,
764                                       1, NULL);
765
766         /* copy (and stretch) destination to temporary bitmaps.(save) */
767         /* image */
768         SelectObject (hdcSrc, himlDst->hbmImage);
769         SelectObject (hdcDst, hbmTempImage);
770         StretchBlt (hdcDst, 0, 0, himlSrc->cx, himlSrc->cy,
771                       hdcSrc, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
772                       SRCCOPY);
773         /* mask */
774         SelectObject (hdcSrc, himlDst->hbmMask);
775         SelectObject (hdcDst, hbmTempMask);
776         StretchBlt (hdcDst, 0, 0, himlSrc->cx, himlSrc->cy,
777                       hdcSrc, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
778                       SRCCOPY);
779
780         /* copy (and stretch) source to destination */
781         /* image */
782         SelectObject (hdcSrc, himlSrc->hbmImage);
783         SelectObject (hdcDst, himlDst->hbmImage);
784         StretchBlt (hdcDst, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
785                       hdcSrc, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
786                       SRCCOPY);
787         /* mask */
788         SelectObject (hdcSrc, himlSrc->hbmMask);
789         SelectObject (hdcDst, himlDst->hbmMask);
790         StretchBlt (hdcDst, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
791                       hdcSrc, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
792                       SRCCOPY);
793
794         /* copy (without stretching) temporary bitmaps to source (restore) */
795         /* image */
796         SelectObject (hdcSrc, hbmTempImage);
797         SelectObject (hdcDst, himlSrc->hbmImage);
798         BitBlt (hdcDst, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
799                   hdcSrc, 0, 0, SRCCOPY);
800         /* mask */
801         SelectObject (hdcSrc, hbmTempMask);
802         SelectObject (hdcDst, himlSrc->hbmMask);
803         BitBlt (hdcDst, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
804                   hdcSrc, 0, 0, SRCCOPY);
805
806         /* delete temporary bitmaps */
807         DeleteObject (hbmTempMask);
808         DeleteObject (hbmTempImage);
809     }
810     else {
811         /* copy image */
812         SelectObject (hdcSrc, himlSrc->hbmImage);
813         if (himlSrc == himlDst)
814             hdcDst = hdcSrc;
815         else
816             SelectObject (hdcDst, himlDst->hbmImage);
817         StretchBlt (hdcDst, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
818                       hdcSrc, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
819                       SRCCOPY);
820
821         /* copy mask */
822         SelectObject (hdcSrc, himlSrc->hbmMask);
823         if (himlSrc == himlDst)
824             hdcDst = hdcSrc;
825         else
826             SelectObject (hdcDst, himlDst->hbmMask);
827         StretchBlt (hdcDst, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
828                       hdcSrc, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
829                       SRCCOPY);
830     }
831
832     DeleteDC (hdcSrc);
833     if (himlSrc != himlDst)
834         DeleteDC (hdcDst);
835
836     return TRUE;
837 }
838
839
840 /*************************************************************************
841  * ImageList_Create [COMCTL32.44]  Creates a new image list.
842  *
843  * PARAMS
844  *     cx       [I] image height
845  *     cy       [I] image width
846  *     flags    [I] creation flags
847  *     cInitial [I] initial number of images in the image list
848  *     cGrow    [I] number of images by which image list grows
849  *
850  * RETURNS
851  *     Success: Handle to the created image list
852  *     Failure: NULL
853  */
854
855 HIMAGELIST WINAPI
856 ImageList_Create (INT cx, INT cy, UINT flags,
857                   INT cInitial, INT cGrow)
858 {
859     HIMAGELIST himl;
860     HDC      hdc;
861     INT      nCount;
862     HBITMAP  hbmTemp;
863     static WORD aBitBlend25[] = 
864         {0xAA, 0x00, 0x55, 0x00, 0xAA, 0x00, 0x55, 0x00};
865
866     static WORD aBitBlend50[] =
867         {0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA};
868
869     TRACE("(%d %d 0x%x %d %d)\n", cx, cy, flags, cInitial, cGrow);
870
871     himl = (HIMAGELIST)COMCTL32_Alloc (sizeof(struct _IMAGELIST));
872     if (!himl)
873         return NULL;
874
875     himl->cx        = cx;
876     himl->cy        = cy;
877     himl->flags     = flags;
878     himl->cMaxImage = cInitial + cGrow;
879     himl->cInitial  = cInitial;
880     himl->cGrow     = cGrow;
881     himl->cCurImage = 0;
882     himl->clrFg     = CLR_DEFAULT;
883     himl->clrBk     = CLR_NONE;
884
885     /* initialize overlay mask indices */
886     for (nCount = 0; nCount < MAX_OVERLAYIMAGE; nCount++)
887         himl->nOvlIdx[nCount] = -1;
888
889     hdc = CreateCompatibleDC (0);
890     himl->uBitsPixel = (UINT)GetDeviceCaps (hdc, BITSPIXEL);
891     DeleteDC (hdc);
892
893     TRACE("Image: %d Bits per Pixel\n", himl->uBitsPixel);
894
895     if (himl->cMaxImage > 0) {
896         himl->hbmImage =
897           CreateBitmap (himl->cx * himl->cMaxImage, himl->cy,
898                         1, himl->uBitsPixel, NULL);
899         if (himl->hbmImage == 0) {
900             ERR("Error creating image bitmap!\n");
901             return NULL;
902         }
903     }
904     else
905         himl->hbmImage = 0;
906     
907     if ( (himl->cMaxImage > 0) && (himl->flags & ILC_MASK)) {
908         himl->hbmMask = CreateBitmap (himl->cx * himl->cMaxImage, himl->cy,
909                                         1, 1, NULL);
910         if (himl->hbmMask == 0) {
911             ERR("Error creating mask bitmap!\n");
912             if (himl->hbmImage)
913                 DeleteObject (himl->hbmImage);
914             return NULL;
915         }
916     }
917     else
918         himl->hbmMask = 0;
919
920     /* create blending brushes */
921     hbmTemp = CreateBitmap (8, 8, 1, 1, &aBitBlend25);
922     himl->hbrBlend25 = CreatePatternBrush (hbmTemp);
923     DeleteObject (hbmTemp);
924
925     hbmTemp = CreateBitmap (8, 8, 1, 1, &aBitBlend50);
926     himl->hbrBlend50 = CreatePatternBrush (hbmTemp);
927     DeleteObject (hbmTemp);
928
929     TRACE("created imagelist %p\n", himl);
930     return himl;
931 }
932
933
934 /*************************************************************************
935  * ImageList_Destroy [COMCTL32.45] 
936  *
937  * Destroys an image list.
938  *
939  * PARAMS
940  *     himl [I] handle to image list
941  *
942  * RETURNS
943  *     Success: TRUE
944  *     Failure: FALSE
945  */
946
947 BOOL WINAPI
948 ImageList_Destroy (HIMAGELIST himl)
949
950     if (!himl)
951         return FALSE;
952
953     /* delete image bitmaps */
954     if (himl->hbmImage)
955         DeleteObject (himl->hbmImage);
956     if (himl->hbmMask)
957         DeleteObject (himl->hbmMask);
958
959     /* delete blending brushes */
960     if (himl->hbrBlend25)
961         DeleteObject (himl->hbrBlend25);
962     if (himl->hbrBlend50)
963         DeleteObject (himl->hbrBlend50);
964         
965     COMCTL32_Free (himl);
966
967     return TRUE;
968 }
969
970
971 /*************************************************************************
972  * ImageList_DragEnter [COMCTL32.46] 
973  *
974  * Locks window update and displays the drag image at the given position.
975  *
976  * PARAMS
977  *     hwndLock [I] handle of the window that owns the drag image.
978  *     x        [I] X position of the drag image.
979  *     y        [I] Y position of the drag image.
980  *
981  * RETURNS
982  *     Success: TRUE
983  *     Failure: FALSE
984  *
985  * NOTES
986  *     The position of the drag image is relative to the window, not
987  *     the client area.
988  */
989
990 BOOL WINAPI
991 ImageList_DragEnter (HWND hwndLock, INT x, INT y)
992 {
993     if (himlInternalDrag == NULL)
994         return FALSE;
995
996     if (hwndLock)
997         hwndInternalDrag = hwndLock;
998     else
999         hwndInternalDrag = GetDesktopWindow ();
1000
1001     xInternalPos = x;
1002     yInternalPos = y;
1003
1004     hdcBackBuffer = CreateCompatibleDC (0);
1005     hbmBackBuffer = CreateCompatibleBitmap (hdcBackBuffer,
1006                 himlInternalDrag->cx, himlInternalDrag->cy);
1007
1008     ImageList_DragShowNolock (TRUE);
1009
1010     return FALSE;
1011 }
1012
1013
1014 /*************************************************************************
1015  * ImageList_DragLeave [COMCTL32.47] 
1016  *
1017  * Unlocks window update and hides the drag image.
1018  *
1019  * PARAMS
1020  *     hwndLock [I] handle of the window that owns the drag image.
1021  *
1022  * RETURNS
1023  *     Success: TRUE
1024  *     Failure: FALSE
1025  */
1026
1027 BOOL WINAPI
1028 ImageList_DragLeave (HWND hwndLock)
1029 {
1030     if (hwndLock)
1031         hwndInternalDrag = hwndLock;
1032     else
1033         hwndInternalDrag = GetDesktopWindow ();
1034
1035     ImageList_DragShowNolock (FALSE);
1036
1037     DeleteDC (hdcBackBuffer);
1038     DeleteObject (hbmBackBuffer);
1039
1040     return TRUE;
1041 }
1042
1043
1044 /*************************************************************************
1045  * ImageList_DragMove [COMCTL32.48] 
1046  *
1047  * Moves the drag image.
1048  *
1049  * PARAMS
1050  *     x [I] X position of the drag image.
1051  *     y [I] Y position of the drag image.
1052  *
1053  * RETURNS
1054  *     Success: TRUE
1055  *     Failure: FALSE
1056  *
1057  * NOTES
1058  *     The position of the drag image is relative to the window, not
1059  *     the client area.
1060  */
1061
1062 BOOL WINAPI
1063 ImageList_DragMove (INT x, INT y)
1064 {
1065     ImageList_DragShowNolock (FALSE);
1066
1067     xInternalPos = x;
1068     yInternalPos = y;
1069
1070     ImageList_DragShowNolock (TRUE);
1071
1072     return FALSE;
1073 }
1074
1075
1076 /*************************************************************************
1077  * ImageList_DragShowNolock [COMCTL32.49] 
1078  *
1079  * Shows or hides the drag image.
1080  *
1081  * PARAMS
1082  *     bShow [I] TRUE shows the drag image, FALSE hides it.
1083  *
1084  * RETURNS
1085  *     Success: TRUE
1086  *     Failure: FALSE
1087  *
1088  * FIXME
1089  *     semi-stub.
1090  */
1091
1092 BOOL WINAPI
1093 ImageList_DragShowNolock (BOOL bShow)
1094 {
1095     HDC hdcDrag;
1096
1097     FIXME("semi-stub!\n");
1098     TRACE("bShow=0x%X!\n", bShow);
1099
1100     hdcDrag = GetDCEx (hwndInternalDrag, 0,
1101                          DCX_WINDOW | DCX_CACHE | DCX_LOCKWINDOWUPDATE);
1102
1103     if (bShow) {
1104         /* show drag image */
1105
1106         /* save background */
1107
1108         /* draw drag image */
1109
1110     }
1111     else {
1112         /* hide drag image */
1113
1114         /* restore background */
1115
1116     }
1117
1118     ReleaseDC (hwndInternalDrag, hdcDrag);
1119
1120     return FALSE;
1121 }
1122
1123
1124 /*************************************************************************
1125  * ImageList_Draw [COMCTL32.50] Draws an image.
1126  *
1127  * PARAMS
1128  *     himl   [I] handle to image list
1129  *     i      [I] image index
1130  *     hdc    [I] handle to device context
1131  *     x      [I] x position
1132  *     y      [I] y position
1133  *     fStyle [I] drawing flags
1134  *
1135  * RETURNS
1136  *     Success: TRUE
1137  *     Failure: FALSE
1138  *
1139  * NOTES
1140  *     Calls ImageList_DrawIndirect.
1141  *
1142  * SEE
1143  *     ImageList_DrawIndirect.
1144  */
1145
1146 BOOL WINAPI
1147 ImageList_Draw (HIMAGELIST himl, INT i, HDC hdc,
1148                 INT x, INT y, UINT fStyle)
1149 {
1150     IMAGELISTDRAWPARAMS imldp;
1151
1152     imldp.cbSize  = sizeof(IMAGELISTDRAWPARAMS);
1153     imldp.himl    = himl;
1154     imldp.i       = i;
1155     imldp.hdcDst  = hdc,
1156     imldp.x       = x;
1157     imldp.y       = y;
1158     imldp.cx      = 0;
1159     imldp.cy      = 0;
1160     imldp.xBitmap = 0;
1161     imldp.yBitmap = 0;
1162     imldp.rgbBk   = CLR_DEFAULT;
1163     imldp.rgbFg   = CLR_DEFAULT;
1164     imldp.fStyle  = fStyle;
1165     imldp.dwRop   = 0;
1166
1167     return ImageList_DrawIndirect (&imldp);
1168 }
1169
1170
1171 /*************************************************************************
1172  * ImageList_DrawEx [COMCTL32.51]
1173  *
1174  * Draws an image and allows to use extended drawing features.
1175  *
1176  * PARAMS
1177  *     himl   [I] handle to image list
1178  *     i      [I] image index
1179  *     hdc    [I] handle to device context
1180  *     x      [I] X position
1181  *     y      [I] Y position
1182  *     xOffs  [I] X offset
1183  *     yOffs  [I] Y offset
1184  *     rgbBk  [I] background color
1185  *     rgbFg  [I] foreground color
1186  *     fStyle [I] drawing flags
1187  *
1188  * RETURNS
1189  *     Success: TRUE
1190  *     Failure: FALSE
1191  *
1192  * NOTES
1193  *     Calls ImageList_DrawIndirect.
1194  *
1195  * SEE
1196  *     ImageList_DrawIndirect.
1197  */
1198
1199 BOOL WINAPI
1200 ImageList_DrawEx (HIMAGELIST himl, INT i, HDC hdc, INT x, INT y,
1201                   INT dx, INT dy, COLORREF rgbBk, COLORREF rgbFg,
1202                   UINT fStyle)
1203 {
1204     IMAGELISTDRAWPARAMS imldp;
1205
1206     imldp.cbSize  = sizeof(IMAGELISTDRAWPARAMS);
1207     imldp.himl    = himl;
1208     imldp.i       = i;
1209     imldp.hdcDst  = hdc,
1210     imldp.x       = x;
1211     imldp.y       = y;
1212     imldp.cx      = dx;
1213     imldp.cy      = dy;
1214     imldp.xBitmap = 0;
1215     imldp.yBitmap = 0;
1216     imldp.rgbBk   = rgbBk;
1217     imldp.rgbFg   = rgbFg;
1218     imldp.fStyle  = fStyle;
1219     imldp.dwRop   = 0;
1220
1221     return ImageList_DrawIndirect (&imldp);
1222 }
1223
1224
1225 /*************************************************************************
1226  * ImageList_DrawIndirect [COMCTL32.52] 
1227  *
1228  * Draws an image using ...
1229  *
1230  * PARAMS
1231  *     pimldp [I] pointer to IMAGELISTDRAWPARAMS structure.
1232  *
1233  * RETURNS
1234  *     Success: TRUE
1235  *     Failure: FALSE
1236  */
1237
1238 BOOL WINAPI
1239 ImageList_DrawIndirect (IMAGELISTDRAWPARAMS *pimldp)
1240 {
1241     INT      cx, cy;    
1242     /* 
1243         Do some Error Checking
1244     */
1245     if (pimldp == NULL)
1246         return FALSE;
1247     if (pimldp->cbSize < sizeof(IMAGELISTDRAWPARAMS))
1248         return FALSE;
1249     if (pimldp->himl == NULL)
1250         return FALSE;
1251     if ((pimldp->i < 0) || (pimldp->i > pimldp->himl->cCurImage)) {
1252         ERR("%d not within range (max %d)\n",pimldp->i,pimldp->himl->cCurImage);
1253         return FALSE;
1254     }
1255     /*
1256         Get the Height and Width to display
1257     */
1258     cx = (pimldp->cx == 0) ? pimldp->himl->cx : pimldp->cx;
1259     cy = (pimldp->cy == 0) ? pimldp->himl->cy : pimldp->cy;
1260     /*
1261         Draw the image
1262     */
1263     if(pimldp->himl->hbmMask != 0)
1264     {
1265         IMAGELIST_InternalDrawMask(pimldp, cx, cy);
1266     }
1267     else
1268     {
1269         IMAGELIST_InternalDraw(pimldp, cx, cy);
1270     }
1271     /* 
1272         Apply the blend if needed to the Image
1273     */
1274     if((pimldp->fStyle & ILD_BLEND50)
1275         || (pimldp->fStyle & ILD_BLEND25))
1276     {
1277         IMAGELIST_InternalDrawBlend(pimldp, cx, cy);
1278     }
1279     /*
1280         Apply the Overlay if needed
1281     */
1282     if (pimldp->fStyle & ILD_OVERLAYMASK)
1283     {
1284         IMAGELIST_InternalDrawOverlay(pimldp, cx, cy);
1285     }
1286
1287     return TRUE;
1288 }
1289
1290
1291 /*************************************************************************
1292  * ImageList_Duplicate [COMCTL32.53] Duplicates an image list.
1293  *
1294  * PARAMS
1295  *     himlSrc [I] source image list handle
1296  *
1297  * RETURNS
1298  *     Success: Handle of duplicated image list.
1299  *     Failure: NULL
1300  */
1301
1302 HIMAGELIST WINAPI
1303 ImageList_Duplicate (HIMAGELIST himlSrc)
1304 {
1305     HIMAGELIST himlDst;
1306     HDC hdcSrc, hdcDst;
1307
1308     if (himlSrc == NULL) {
1309         ERR("Invalid image list handle!\n");
1310         return NULL;
1311     }
1312
1313     himlDst = ImageList_Create (himlSrc->cx, himlSrc->cy, himlSrc->flags,
1314                                 himlSrc->cInitial, himlSrc->cGrow);
1315
1316     if (himlDst)
1317     {
1318         hdcSrc = CreateCompatibleDC (0);
1319         hdcDst = CreateCompatibleDC (0);
1320         SelectObject (hdcSrc, himlSrc->hbmImage);
1321         SelectObject (hdcDst, himlDst->hbmImage);
1322         BitBlt (hdcDst, 0, 0, himlSrc->cCurImage * himlSrc->cx, himlSrc->cy,
1323                   hdcSrc, 0, 0, SRCCOPY);
1324
1325         if (himlDst->hbmMask)
1326         {
1327             SelectObject (hdcSrc, himlSrc->hbmMask);
1328             SelectObject (hdcDst, himlDst->hbmMask);
1329             BitBlt (hdcDst, 0, 0, himlSrc->cCurImage * himlSrc->cx,
1330                       himlSrc->cy, hdcSrc, 0, 0, SRCCOPY);
1331         }
1332
1333         DeleteDC (hdcDst);
1334         DeleteDC (hdcSrc);
1335
1336         himlDst->cCurImage = himlSrc->cCurImage;
1337         himlDst->cMaxImage = himlSrc->cMaxImage;
1338     }
1339     return himlDst;
1340 }
1341
1342
1343 /*************************************************************************
1344  * ImageList_EndDrag [COMCTL32.54] Finishes a drag operation.
1345  *
1346  * Finishes a drag operation.
1347  *
1348  * PARAMS
1349  *     no Parameters
1350  *
1351  * RETURNS
1352  *     Success: TRUE
1353  *     Failure: FALSE
1354  *
1355  * BUGS
1356  *     semi-stub.
1357  */
1358
1359 BOOL WINAPI
1360 ImageList_EndDrag (void)
1361 {
1362     FIXME("semi-stub!\n");
1363
1364     if (himlInternalDrag)
1365     {
1366
1367         ImageList_Destroy (himlInternalDrag);
1368         himlInternalDrag = NULL;
1369
1370         nInternalDragHotspotX = 0;
1371         nInternalDragHotspotY = 0;
1372
1373     }
1374
1375     return TRUE;
1376 }
1377
1378
1379 /*************************************************************************
1380  * ImageList_GetBkColor [COMCTL32.55]
1381  *
1382  * Returns the background color of an image list.
1383  *
1384  * PARAMS
1385  *     himl [I] Image list handle.
1386  *
1387  * RETURNS
1388  *     Success: background color
1389  *     Failure: CLR_NONE
1390  */
1391
1392 COLORREF WINAPI
1393 ImageList_GetBkColor (HIMAGELIST himl)
1394 {
1395     if (himl == NULL)
1396         return CLR_NONE;
1397
1398     return himl->clrBk;
1399 }
1400
1401
1402 /*************************************************************************
1403  * ImageList_GetDragImage [COMCTL32.56]
1404  *
1405  * Returns the handle to the internal drag image list.
1406  *
1407  * PARAMS
1408  *     ppt        [O] Pointer to the drag position. Can be NULL.
1409  *     pptHotspot [O] Pointer to the position of the hot spot. Can be NULL.
1410  *
1411  * RETURNS
1412  *     Success: Handle of the drag image list.
1413  *     Failure: NULL.
1414  *
1415  * BUGS
1416  *     semi-stub.
1417  */
1418
1419 HIMAGELIST WINAPI
1420 ImageList_GetDragImage (POINT *ppt, POINT *pptHotspot)
1421 {
1422     FIXME("semi-stub!\n");
1423
1424     if (himlInternalDrag)
1425         return (himlInternalDrag);
1426
1427     return NULL;
1428 }
1429
1430
1431 /*************************************************************************
1432  * ImageList_GetIcon [COMCTL32.57] 
1433  *
1434  * Creates an icon from a masked image of an image list.
1435  *
1436  * PARAMS
1437  *     himl  [I] handle to image list
1438  *     i     [I] image index
1439  *     flags [I] drawing style flags
1440  *
1441  * RETURNS
1442  *     Success: icon handle
1443  *     Failure: NULL
1444  */
1445
1446 HICON WINAPI
1447 ImageList_GetIcon (HIMAGELIST himl, INT i, UINT fStyle)
1448 {
1449     ICONINFO ii;
1450     HICON  hIcon;
1451     HBITMAP hOldSrcBitmap,hOldDstBitmap;
1452     HDC    hdcSrc, hdcDst;
1453
1454     if ((himl == NULL) || (i < 0) || (i >= himl->cCurImage)) {
1455         FIXME("(%p,%d,%x), params out of range!\n",himl,i,fStyle);
1456         return 0;
1457    }
1458
1459     hdcSrc = CreateCompatibleDC(0);
1460     hdcDst = CreateCompatibleDC(0);
1461
1462     ii.fIcon = TRUE;
1463     ii.hbmMask  = CreateCompatibleBitmap (hdcDst, himl->cx, himl->cy);
1464
1465     /* draw mask*/
1466     hOldDstBitmap = (HBITMAP)SelectObject (hdcDst, ii.hbmMask);
1467     if (himl->hbmMask) {
1468         SelectObject (hdcSrc, himl->hbmMask);
1469         BitBlt (hdcDst, 0, 0, himl->cx, himl->cy,
1470                   hdcSrc, i * himl->cx, 0, SRCCOPY);
1471     }
1472     else
1473         PatBlt (hdcDst, 0, 0, himl->cx, himl->cy, BLACKNESS);
1474
1475     /* draw image*/
1476     hOldSrcBitmap = (HBITMAP)SelectObject (hdcSrc, himl->hbmImage);
1477     ii.hbmColor = CreateCompatibleBitmap (hdcSrc, himl->cx, himl->cy);
1478     SelectObject (hdcDst, ii.hbmColor);
1479     BitBlt (hdcDst, 0, 0, himl->cx, himl->cy,
1480               hdcSrc, i * himl->cx, 0, SRCCOPY);
1481
1482     /*
1483      * CreateIconIndirect requires us to deselect the bitmaps from
1484      * the DCs before calling 
1485      */
1486     SelectObject(hdcSrc, hOldSrcBitmap);
1487     SelectObject(hdcDst, hOldDstBitmap);
1488
1489     hIcon = CreateIconIndirect (&ii);    
1490
1491     DeleteDC (hdcSrc);
1492     DeleteDC (hdcDst);
1493     DeleteObject (ii.hbmMask);
1494     DeleteObject (ii.hbmColor);
1495
1496     return hIcon;
1497 }
1498
1499
1500 /*************************************************************************
1501  * ImageList_GetIconSize [COMCTL32.58]
1502  *
1503  * Retrieves the size of an image in an image list.
1504  *
1505  * PARAMS
1506  *     himl [I] handle to image list
1507  *     cx   [O] pointer to the image width.
1508  *     cy   [O] pointer to the image height.
1509  *
1510  * RETURNS
1511  *     Success: TRUE
1512  *     Failure: FALSE
1513  *
1514  * NOTES
1515  *     All images in an image list have the same size.
1516  */
1517
1518 BOOL WINAPI
1519 ImageList_GetIconSize (HIMAGELIST himl, INT *cx, INT *cy)
1520 {
1521     if (himl == NULL)
1522         return FALSE;
1523     if ((himl->cx <= 0) || (himl->cy <= 0))
1524         return FALSE;
1525
1526     if (cx)
1527         *cx = himl->cx;
1528     if (cy)
1529         *cy = himl->cy;
1530
1531     return TRUE;
1532 }
1533
1534
1535 /*************************************************************************
1536  * ImageList_GetImageCount [COMCTL32.59]
1537  *
1538  * Returns the number of images in an image list.
1539  *
1540  * PARAMS
1541  *     himl [I] handle to image list
1542  *
1543  * RETURNS
1544  *     Success: Number of images.
1545  *     Failure: 0
1546  */
1547
1548 INT WINAPI
1549 ImageList_GetImageCount (HIMAGELIST himl)
1550 {
1551     if (himl == NULL)
1552         return 0;
1553
1554     return himl->cCurImage;
1555 }
1556
1557
1558 /*************************************************************************
1559  * ImageList_GetImageInfo [COMCTL32.60]
1560  *
1561  * Returns information about an image in an image list.
1562  *
1563  * PARAMS
1564  *     himl       [I] handle to image list
1565  *     i          [I] image index
1566  *     pImageInfo [O] pointer to the image information
1567  *
1568  * RETURNS
1569  *     Success: TRUE
1570  *     Failure: FALSE
1571  */
1572
1573 BOOL WINAPI
1574 ImageList_GetImageInfo (HIMAGELIST himl, INT i, IMAGEINFO *pImageInfo)
1575 {
1576     if ((himl == NULL) || (pImageInfo == NULL))
1577         return FALSE;
1578     if ((i < 0) || (i >= himl->cCurImage))
1579         return FALSE;
1580
1581     pImageInfo->hbmImage = himl->hbmImage;
1582     pImageInfo->hbmMask  = himl->hbmMask;
1583     
1584     pImageInfo->rcImage.top    = 0;
1585     pImageInfo->rcImage.bottom = himl->cy;
1586     pImageInfo->rcImage.left   = i * himl->cx;
1587     pImageInfo->rcImage.right  = (i+1) * himl->cx;
1588     
1589     return TRUE;
1590 }
1591
1592
1593 /*************************************************************************
1594  * ImageList_GetImageRect [COMCTL32.61] 
1595  *
1596  * Retrieves the rectangle of the specified image in an image list.
1597  *
1598  * PARAMS
1599  *     himl   [I] handle to image list
1600  *     i      [I] image index
1601  *     lpRect [O] pointer to the image rectangle
1602  *
1603  * RETURNS
1604  *    Success: TRUE
1605  *    Failure: FALSE
1606  *
1607  * NOTES
1608  *    This is an UNDOCUMENTED function!!!
1609  */
1610
1611 BOOL WINAPI
1612 ImageList_GetImageRect (HIMAGELIST himl, INT i, LPRECT lpRect)
1613 {
1614     if ((himl == NULL) || (lpRect == NULL))
1615         return FALSE;
1616     if ((i < 0) || (i >= himl->cCurImage))
1617         return FALSE;
1618
1619     lpRect->left   = i * himl->cx;
1620     lpRect->top    = 0;
1621     lpRect->right  = lpRect->left + himl->cx;
1622     lpRect->bottom = himl->cy;
1623
1624     return TRUE;
1625 }
1626
1627
1628 /*************************************************************************
1629  * ImageList_LoadImageA [COMCTL32.63][COMCTL32.62]
1630  *
1631  * Creates an image list from a bitmap, icon or cursor.
1632  *
1633  * PARAMS
1634  *     hi      [I] instance handle
1635  *     lpbmp   [I] name or id of the image
1636  *     cx      [I] width of each image
1637  *     cGrow   [I] number of images to expand
1638  *     clrMask [I] mask color
1639  *     uType   [I] type of image to load
1640  *     uFlags  [I] loading flags
1641  *
1642  * RETURNS
1643  *     Success: handle to the loaded image list
1644  *     Failure: NULL
1645  *
1646  * SEE
1647  *     LoadImage ()
1648  */
1649
1650 HIMAGELIST WINAPI
1651 ImageList_LoadImageA (HINSTANCE hi, LPCSTR lpbmp, INT cx,       INT cGrow,
1652                         COLORREF clrMask, UINT uType,   UINT uFlags)
1653 {
1654     HIMAGELIST himl = NULL;
1655     HANDLE   handle;
1656     INT      nImageCount;
1657
1658     handle = LoadImageA (hi, lpbmp, uType, 0, 0, uFlags);
1659     if (!handle) {
1660         ERR("Error loading image!\n");
1661         return NULL;
1662     }
1663
1664     if (uType == IMAGE_BITMAP) {
1665         BITMAP bmp;
1666         GetObjectA (handle, sizeof(BITMAP), &bmp);
1667
1668         /* To match windows behavior, if cx is set to zero and
1669          the flag DI_DEFAULTSIZE is specified, cx becomes the
1670          system metric value for icons. If the flag is not specified
1671          the function sets the size to the height of the bitmap */
1672         if (cx == 0)
1673         {
1674             if (uFlags & DI_DEFAULTSIZE)
1675                 cx = GetSystemMetrics (SM_CXICON);
1676             else
1677                 cx = bmp.bmHeight;
1678         }
1679
1680         nImageCount = bmp.bmWidth / cx;
1681
1682         himl = ImageList_Create (cx, bmp.bmHeight, ILC_MASK | ILC_COLOR,
1683                                  nImageCount, cGrow);
1684         ImageList_AddMasked (himl, (HBITMAP)handle, clrMask);
1685     }
1686     else if ((uType == IMAGE_ICON) || (uType == IMAGE_CURSOR)) {
1687         ICONINFO ii;
1688         BITMAP bmp;
1689
1690         GetIconInfo (handle, &ii);
1691         GetObjectA (ii.hbmColor, sizeof(BITMAP), (LPVOID)&bmp);
1692         himl = ImageList_Create (bmp.bmWidth, bmp.bmHeight, 
1693                                  ILC_MASK | ILC_COLOR, 1, cGrow);
1694         ImageList_Add (himl, ii.hbmColor, ii.hbmMask);
1695         DeleteObject (ii.hbmColor);
1696         DeleteObject (ii.hbmMask);
1697     }
1698
1699     DeleteObject (handle);
1700     
1701     return himl;
1702 }
1703
1704
1705 /*************************************************************************
1706  * ImageList_LoadImageW [COMCTL32.64]
1707  *
1708  * Creates an image list from a bitmap, icon or cursor.
1709  *
1710  * PARAMS
1711  *     hi      [I] instance handle
1712  *     lpbmp   [I] name or id of the image
1713  *     cx      [I] width of each image
1714  *     cGrow   [I] number of images to expand
1715  *     clrMask [I] mask color
1716  *     uType   [I] type of image to load
1717  *     uFlags  [I] loading flags
1718  *
1719  * RETURNS
1720  *     Success: handle to the loaded image list
1721  *     Failure: NULL
1722  *
1723  * SEE
1724  *     LoadImage ()
1725  */
1726
1727 HIMAGELIST WINAPI
1728 ImageList_LoadImageW (HINSTANCE hi, LPCWSTR lpbmp, INT cx, INT cGrow,
1729                         COLORREF clrMask, UINT uType,   UINT uFlags)
1730 {
1731     HIMAGELIST himl = NULL;
1732     HANDLE   handle;
1733     INT      nImageCount;
1734
1735     handle = LoadImageW (hi, lpbmp, uType, 0, 0, uFlags);
1736     if (!handle) {
1737         ERR("Error loading image!\n");
1738         return NULL;
1739     }
1740
1741     if (uType == IMAGE_BITMAP) {
1742         BITMAP bmp;
1743         GetObjectA (handle, sizeof(BITMAP), &bmp);
1744         nImageCount = bmp.bmWidth / cx;
1745
1746         himl = ImageList_Create (cx, bmp.bmHeight, ILC_MASK | ILC_COLOR,
1747                                  nImageCount, cGrow);
1748         ImageList_AddMasked (himl, (HBITMAP)handle, clrMask);
1749     }
1750     else if ((uType == IMAGE_ICON) || (uType == IMAGE_CURSOR)) {
1751         ICONINFO ii;
1752         BITMAP bmp;
1753
1754         GetIconInfo (handle, &ii);
1755         GetObjectA (ii.hbmMask, sizeof(BITMAP), (LPVOID)&bmp);
1756         himl = ImageList_Create (bmp.bmWidth, bmp.bmHeight, 
1757                                  ILC_MASK | ILC_COLOR, 1, cGrow);
1758         ImageList_Add (himl, ii.hbmColor, ii.hbmMask);
1759         DeleteObject (ii.hbmColor);
1760         DeleteObject (ii.hbmMask);
1761     }
1762
1763     DeleteObject (handle);
1764     
1765     return himl;
1766 }
1767
1768
1769 /*************************************************************************
1770  * ImageList_Merge [COMCTL32.65] 
1771  *
1772  * Creates a new image list that contains a merged image from the specified
1773  * images of both source image lists.
1774  *
1775  * PARAMS
1776  *     himl1 [I] handle to first image list
1777  *     i1    [I] first image index
1778  *     himl2 [I] handle to second image list
1779  *     i2    [I] second image index
1780  *     dx    [I] X offset of the second image relative to the first.
1781  *     dy    [I] Y offset of the second image relative to the first.
1782  *
1783  * RETURNS
1784  *     Success: handle of the merged image list.
1785  *     Failure: NULL
1786  */
1787
1788 HIMAGELIST WINAPI
1789 ImageList_Merge (HIMAGELIST himl1, INT i1, HIMAGELIST himl2, INT i2,
1790                  INT dx, INT dy)
1791 {
1792     HIMAGELIST himlDst = NULL;
1793     HDC      hdcSrcImage, hdcDstImage;
1794     INT      cxDst, cyDst;
1795     INT      xOff1, yOff1, xOff2, yOff2;
1796     INT      nX1, nX2;
1797
1798     if ((himl1 == NULL) || (himl2 == NULL))
1799         return NULL;
1800
1801     /* check indices */
1802     if ((i1 < 0) || (i1 >= himl1->cCurImage)) {
1803         ERR("Index 1 out of range! %d\n", i1);
1804         return NULL;
1805     }
1806
1807     if ((i2 < 0) || (i2 >= himl2->cCurImage)) {
1808         ERR("Index 2 out of range! %d\n", i2);
1809         return NULL;
1810     }
1811
1812     if (dx > 0) {
1813         cxDst = _MAX (himl1->cx, dx + himl2->cx);
1814         xOff1 = 0;
1815         xOff2 = dx;
1816     }
1817     else if (dx < 0) {
1818         cxDst = _MAX (himl2->cx, himl1->cx - dx);
1819         xOff1 = -dx;
1820         xOff2 = 0;
1821     }
1822     else {
1823         cxDst = _MAX (himl1->cx, himl2->cx);
1824         xOff1 = 0;
1825         xOff2 = 0;
1826     }
1827
1828     if (dy > 0) {
1829         cyDst = _MAX (himl1->cy, dy + himl2->cy);
1830         yOff1 = 0;
1831         yOff2 = dy;
1832     }
1833     else if (dy < 0) {
1834         cyDst = _MAX (himl2->cy, himl1->cy - dy);
1835         yOff1 = -dy;
1836         yOff2 = 0;
1837     }
1838     else {
1839         cyDst = _MAX (himl1->cy, himl2->cy);
1840         yOff1 = 0;
1841         yOff2 = 0;
1842     }
1843
1844     himlDst = ImageList_Create (cxDst, cyDst, ILC_MASK | ILC_COLOR, 1, 1);
1845
1846     if (himlDst) {
1847         hdcSrcImage = CreateCompatibleDC (0);
1848         hdcDstImage = CreateCompatibleDC (0);
1849         nX1 = i1 * himl1->cx;
1850         nX2 = i2 * himl2->cx;
1851         
1852         /* copy image */
1853         SelectObject (hdcSrcImage, himl1->hbmImage);
1854         SelectObject (hdcDstImage, himlDst->hbmImage);
1855         BitBlt (hdcDstImage, 0, 0, cxDst, cyDst, 
1856                   hdcSrcImage, 0, 0, BLACKNESS);
1857         BitBlt (hdcDstImage, xOff1, yOff1, himl1->cx, himl1->cy, 
1858                   hdcSrcImage, nX1, 0, SRCCOPY);
1859
1860         SelectObject (hdcSrcImage, himl2->hbmMask);
1861         BitBlt (hdcDstImage, xOff2, yOff2, himl2->cx, himl2->cy, 
1862                   hdcSrcImage, nX2, 0, SRCAND);
1863
1864         SelectObject (hdcSrcImage, himl2->hbmImage);
1865         BitBlt (hdcDstImage, xOff2, yOff2, himl2->cx, himl2->cy, 
1866                   hdcSrcImage, nX2, 0, SRCPAINT);
1867
1868         /* copy mask */
1869         SelectObject (hdcSrcImage, himl1->hbmMask);
1870         SelectObject (hdcDstImage, himlDst->hbmMask);
1871         BitBlt (hdcDstImage, 0, 0, cxDst, cyDst, 
1872                   hdcSrcImage, 0, 0, WHITENESS);
1873         BitBlt (hdcDstImage, xOff1, yOff1, himl1->cx, himl1->cy, 
1874                   hdcSrcImage, nX1, 0, SRCCOPY);
1875
1876         SelectObject (hdcSrcImage, himl2->hbmMask);
1877         BitBlt (hdcDstImage, xOff2, yOff2, himl2->cx, himl2->cy, 
1878                   hdcSrcImage, nX2, 0, SRCAND);
1879
1880         DeleteDC (hdcSrcImage);
1881         DeleteDC (hdcDstImage);
1882     }
1883    
1884     return himlDst;
1885 }
1886
1887
1888 /* helper for _read_bitmap currently unused */
1889 #if 0
1890 static int may_use_dibsection(HDC hdc) {
1891     int bitspixel = GetDeviceCaps(hdc,BITSPIXEL)*GetDeviceCaps(hdc,PLANES);
1892     if (bitspixel>8)
1893         return TRUE;
1894     if (bitspixel<=4)
1895         return FALSE;
1896     return GetDeviceCaps(hdc,94) & 0x10;
1897 }
1898 #endif
1899
1900 /* helper for ImageList_Read, see comments below */
1901 static HBITMAP _read_bitmap(LPSTREAM pstm,int ilcFlag,int cx,int cy) {
1902     HDC                 xdc = 0;
1903     BITMAPFILEHEADER    bmfh;
1904     BITMAPINFOHEADER    bmih;
1905     int                 bitsperpixel,palspace,longsperline,width,height;
1906     LPBITMAPINFOHEADER  bmihc = NULL;
1907     int                 result = 0;
1908     HBITMAP             hbitmap = 0;
1909     LPBYTE              bits = NULL,nbits = NULL;
1910     int                 nbytesperline,bytesperline;
1911
1912     if (!SUCCEEDED(IStream_Read ( pstm, &bmfh, sizeof(bmfh), NULL))     ||
1913         (bmfh.bfType != (('M'<<8)|'B'))                                 ||
1914         !SUCCEEDED(IStream_Read ( pstm, &bmih, sizeof(bmih), NULL))     ||
1915         (bmih.biSize != sizeof(bmih))
1916     )
1917         return 0;
1918
1919     bitsperpixel = bmih.biPlanes * bmih.biBitCount;
1920     if (bitsperpixel<=8)
1921         palspace = (1<<bitsperpixel)*sizeof(RGBQUAD);
1922     else
1923         palspace = 0;
1924     width = bmih.biWidth;
1925     height = bmih.biHeight;
1926     bmihc = (LPBITMAPINFOHEADER)LocalAlloc(LMEM_ZEROINIT,sizeof(bmih)+palspace);
1927     memcpy(bmihc,&bmih,sizeof(bmih));
1928     longsperline        = ((width*bitsperpixel+31)&~0x1f)>>5;
1929     bmihc->biSizeImage  = (longsperline*height)<<2;
1930
1931     /* read the palette right after the end of the bitmapinfoheader */
1932     if (palspace)
1933         if (!SUCCEEDED(IStream_Read ( pstm, bmihc+1, palspace, NULL)))
1934             goto ret1;
1935
1936     xdc = GetDC(0);
1937 #if 0 /* Magic for NxM -> 1x(N*M) not implemented for DIB Sections */
1938     if ((bitsperpixel>1) &&
1939         ((ilcFlag!=ILC_COLORDDB) && (!ilcFlag || may_use_dibsection(xdc)))
1940      ) {
1941         hbitmap = CreateDIBSection(xdc,(BITMAPINFO*)bmihc,0,(LPVOID*)&bits,0,0);
1942         if (!hbitmap)
1943             goto ret1;
1944         if (!SUCCEEDED(IStream_Read( pstm, bits, bmihc->biSizeImage, NULL)))
1945             goto ret1;
1946         result = 1;
1947     } else
1948 #endif
1949     {
1950         int i,nwidth,nheight;
1951
1952         nwidth  = width*(height/cy);
1953         nheight = cy;
1954
1955         if (bitsperpixel==1)
1956             hbitmap = CreateBitmap(nwidth,nheight,1,1,NULL);
1957         else
1958             hbitmap = CreateCompatibleBitmap(xdc,nwidth,nheight);
1959
1960         /* Might be a bit excessive memory use here */
1961         bits = (LPBYTE)LocalAlloc(LMEM_ZEROINIT,bmihc->biSizeImage);
1962         nbits = (LPBYTE)LocalAlloc(LMEM_ZEROINIT,bmihc->biSizeImage);
1963         if (!SUCCEEDED(IStream_Read ( pstm, bits, bmihc->biSizeImage, NULL)))
1964                 goto ret1;
1965
1966         /* Copy the NxM bitmap into a 1x(N*M) bitmap we need, linewise */
1967         /* Do not forget that windows bitmaps are bottom->top */
1968         bytesperline    = longsperline*4;
1969         nbytesperline   = (height/cy)*bytesperline;
1970         for (i=0;i<height;i++) {
1971             memcpy(
1972                 nbits+((height-1-i)%cy)*nbytesperline+(i/cy)*bytesperline,
1973                 bits+bytesperline*(height-1-i),
1974                 bytesperline
1975             );
1976         }
1977         bmihc->biWidth  = nwidth;
1978         bmihc->biHeight = nheight;
1979         if (!SetDIBits(xdc,hbitmap,0,nheight,nbits,(BITMAPINFO*)bmihc,0))
1980                 goto ret1;
1981         LocalFree((HLOCAL)nbits);
1982         LocalFree((HLOCAL)bits);
1983         result = 1;
1984     }
1985 ret1:
1986     if (xdc)    ReleaseDC(0,xdc);
1987     if (bmihc)  LocalFree((HLOCAL)bmihc);
1988     if (!result) {
1989         if (hbitmap) {
1990             DeleteObject(hbitmap);
1991             hbitmap = 0;
1992         }
1993     }
1994     return hbitmap;
1995 }
1996
1997 /*************************************************************************
1998  * ImageList_Read [COMCTL32.66]
1999  *
2000  * Reads an image list from a stream.
2001  *
2002  * PARAMS
2003  *     pstm [I] pointer to a stream
2004  *
2005  * RETURNS
2006  *     Success: handle to image list
2007  *     Failure: NULL
2008  *
2009  * The format is like this:
2010  *      ILHEAD                  ilheadstruct;
2011  *
2012  * for the color image part:
2013  *      BITMAPFILEHEADER        bmfh; 
2014  *      BITMAPINFOHEADER        bmih;
2015  * only if it has a palette:
2016  *      RGBQUAD         rgbs[nr_of_paletted_colors]; 
2017  *
2018  *      BYTE                    colorbits[imagesize];
2019  *
2020  * the following only if the ILC_MASK bit is set in ILHEAD.ilFlags:
2021  *      BITMAPFILEHEADER        bmfh_mask;
2022  *      BITMAPINFOHEADER        bmih_mask;
2023  * only if it has a palette (it usually does not):
2024  *      RGBQUAD         rgbs[nr_of_paletted_colors]; 
2025  *
2026  *      BYTE                    maskbits[imagesize];
2027  *
2028  * CAVEAT: Those images are within a NxM bitmap, not the 1xN we expect.
2029  *         _read_bitmap needs to convert them.
2030  */
2031 HIMAGELIST WINAPI ImageList_Read (LPSTREAM pstm)
2032 {
2033     ILHEAD      ilHead;
2034     HIMAGELIST  himl;
2035     HBITMAP     hbmColor=0,hbmMask=0;
2036     int         i;
2037
2038     if (!SUCCEEDED(IStream_Read (pstm, &ilHead, sizeof(ILHEAD), NULL)))
2039         return NULL;
2040     if (ilHead.usMagic != (('L' << 8) | 'I'))
2041         return NULL;
2042     if (ilHead.usVersion != 0x101) /* probably version? */
2043         return NULL;
2044
2045 #if 0
2046     FIXME("     ilHead.cCurImage = %d\n",ilHead.cCurImage);
2047     FIXME("     ilHead.cMaxImage = %d\n",ilHead.cMaxImage);
2048     FIXME("     ilHead.cGrow = %d\n",ilHead.cGrow);
2049     FIXME("     ilHead.cx = %d\n",ilHead.cx);
2050     FIXME("     ilHead.cy = %d\n",ilHead.cy);
2051     FIXME("     ilHead.flags = %x\n",ilHead.flags);
2052     FIXME("     ilHead.ovls[0] = %d\n",ilHead.ovls[0]);
2053     FIXME("     ilHead.ovls[1] = %d\n",ilHead.ovls[1]);
2054     FIXME("     ilHead.ovls[2] = %d\n",ilHead.ovls[2]);
2055     FIXME("     ilHead.ovls[3] = %d\n",ilHead.ovls[3]);
2056 #endif
2057
2058     hbmColor = _read_bitmap(pstm,ilHead.flags & ~ILC_MASK,ilHead.cx,ilHead.cy);
2059     if (!hbmColor)
2060         return NULL;
2061     if (ilHead.flags & ILC_MASK) {
2062         hbmMask = _read_bitmap(pstm,0,ilHead.cx,ilHead.cy);
2063         if (!hbmMask) {
2064             DeleteObject(hbmColor);
2065             return NULL;
2066         }
2067     }
2068
2069     himl = ImageList_Create (
2070                     ilHead.cx,
2071                     ilHead.cy,
2072                     ilHead.flags,
2073                     1,          /* initial */
2074                     ilHead.cGrow
2075     );
2076     if (!himl) {
2077         DeleteObject(hbmColor);
2078         DeleteObject(hbmMask);
2079         return NULL;
2080     }
2081     himl->hbmImage = hbmColor;
2082     himl->hbmMask = hbmMask;
2083     himl->cCurImage = ilHead.cCurImage;
2084     himl->cMaxImage = ilHead.cMaxImage;
2085
2086     ImageList_SetBkColor(himl,ilHead.bkcolor);
2087     for (i=0;i<4;i++)
2088         ImageList_SetOverlayImage(himl,ilHead.ovls[i],i+1);
2089     return himl;
2090 }
2091
2092
2093 /*************************************************************************
2094  * ImageList_Remove [COMCTL32.67] Removes an image from an image list
2095  *
2096  * PARAMS
2097  *     himl [I] image list handle
2098  *     i    [I] image index
2099  *
2100  * RETURNS
2101  *     Success: TRUE
2102  *     Failure: FALSE
2103  */
2104
2105 BOOL WINAPI
2106 ImageList_Remove (HIMAGELIST himl, INT i)
2107 {
2108     HBITMAP hbmNewImage, hbmNewMask;
2109     HDC     hdcSrc, hdcDst;
2110     INT     cxNew, nCount;
2111
2112     if ((i < -1) || (i >= himl->cCurImage)) {
2113         ERR("index out of range! %d\n", i);
2114         return FALSE;
2115     }
2116
2117     if (himl->cCurImage == 0) {
2118         ERR("image list is already empty!\n");
2119         return FALSE;
2120     }
2121
2122     if (i == -1) {
2123         /* remove all */
2124         TRACE("remove all!\n");
2125
2126         himl->cMaxImage = himl->cInitial + himl->cGrow;
2127         himl->cCurImage = 0;
2128         for (nCount = 0; nCount < MAX_OVERLAYIMAGE; nCount++)
2129              himl->nOvlIdx[nCount] = -1;
2130
2131         DeleteObject (himl->hbmImage);
2132         himl->hbmImage =
2133             CreateBitmap (himl->cMaxImage * himl->cx, himl->cy,
2134                             1, himl->uBitsPixel, NULL);
2135
2136         if (himl->hbmMask) {
2137             DeleteObject (himl->hbmMask);
2138             himl->hbmMask =
2139                 CreateBitmap (himl->cMaxImage * himl->cx, himl->cy,
2140                                 1, 1, NULL);
2141         }
2142     }
2143     else {
2144         /* delete one image */
2145         TRACE("Remove single image! %d\n", i);
2146
2147         /* create new bitmap(s) */
2148         cxNew = (himl->cCurImage + himl->cGrow - 1) * himl->cx;
2149
2150         TRACE(" - Number of images: %d / %d (Old/New)\n",
2151                  himl->cCurImage, himl->cCurImage - 1);
2152         TRACE(" - Max. number of images: %d / %d (Old/New)\n",
2153                  himl->cMaxImage, himl->cCurImage + himl->cGrow - 1);
2154         
2155         hbmNewImage =
2156             CreateBitmap (cxNew, himl->cy, 1, himl->uBitsPixel, NULL);
2157
2158         if (himl->hbmMask)
2159             hbmNewMask = CreateBitmap (cxNew, himl->cy, 1, 1, NULL);
2160         else
2161             hbmNewMask = 0;  /* Just to keep compiler happy! */
2162
2163         hdcSrc = CreateCompatibleDC (0);
2164         hdcDst = CreateCompatibleDC (0);
2165
2166         /* copy all images and masks prior to the "removed" image */
2167         if (i > 0) {
2168             TRACE("Pre image copy: Copy %d images\n", i);
2169        
2170             SelectObject (hdcSrc, himl->hbmImage);
2171             SelectObject (hdcDst, hbmNewImage);
2172             BitBlt (hdcDst, 0, 0, i * himl->cx, himl->cy,
2173                       hdcSrc, 0, 0, SRCCOPY);
2174
2175             if (himl->hbmMask) {
2176                 SelectObject (hdcSrc, himl->hbmMask);
2177                 SelectObject (hdcDst, hbmNewMask);
2178                 BitBlt (hdcDst, 0, 0, i * himl->cx, himl->cy,
2179                           hdcSrc, 0, 0, SRCCOPY);
2180             }
2181         }
2182
2183         /* copy all images and masks behind the removed image */
2184         if (i < himl->cCurImage - 1) {
2185             TRACE("Post image copy!\n");
2186             SelectObject (hdcSrc, himl->hbmImage);
2187             SelectObject (hdcDst, hbmNewImage);
2188             BitBlt (hdcDst, i * himl->cx, 0, (himl->cCurImage - i - 1) * himl->cx,
2189                       himl->cy, hdcSrc, (i + 1) * himl->cx, 0, SRCCOPY);
2190
2191             if (himl->hbmMask) {
2192                 SelectObject (hdcSrc, himl->hbmMask);
2193                 SelectObject (hdcDst, hbmNewMask);
2194                 BitBlt (hdcDst, i * himl->cx, 0,
2195                           (himl->cCurImage - i - 1) * himl->cx,
2196                           himl->cy, hdcSrc, (i + 1) * himl->cx, 0, SRCCOPY);
2197             }
2198         }
2199
2200         DeleteDC (hdcSrc);
2201         DeleteDC (hdcDst);
2202
2203         /* delete old images and insert new ones */
2204         DeleteObject (himl->hbmImage);
2205         himl->hbmImage = hbmNewImage;
2206         if (himl->hbmMask) {
2207             DeleteObject (himl->hbmMask);
2208             himl->hbmMask = hbmNewMask;
2209         }
2210
2211         himl->cCurImage--;
2212         himl->cMaxImage = himl->cCurImage + himl->cGrow;
2213     }
2214
2215     return TRUE;
2216 }
2217
2218
2219 /*************************************************************************
2220  * ImageList_Replace [COMCTL32.68] 
2221  *
2222  * Replaces an image in an image list with a new image.
2223  *
2224  * PARAMS
2225  *     himl     [I] handle to image list
2226  *     i        [I] image index
2227  *     hbmImage [I] handle to image bitmap
2228  *     hbmMask  [I] handle to mask bitmap. Can be NULL.
2229  *
2230  * RETURNS
2231  *     Success: TRUE
2232  *     Failure: FALSE
2233  */
2234
2235 BOOL WINAPI
2236 ImageList_Replace (HIMAGELIST himl, INT i, HBITMAP hbmImage,
2237                    HBITMAP hbmMask)
2238 {
2239     HDC hdcImageList, hdcImage;
2240     BITMAP bmp;
2241
2242     if (himl == NULL) {
2243         ERR("Invalid image list handle!\n");
2244         return FALSE;
2245     }
2246     
2247     if ((i >= himl->cMaxImage) || (i < 0)) {
2248         ERR("Invalid image index!\n");
2249         return FALSE;
2250     }
2251
2252     hdcImageList = CreateCompatibleDC (0);
2253     hdcImage = CreateCompatibleDC (0);
2254     GetObjectA (hbmImage, sizeof(BITMAP), (LPVOID)&bmp);
2255
2256     /* Replace Image */
2257     SelectObject (hdcImageList, himl->hbmImage);
2258     SelectObject (hdcImage, hbmImage);
2259
2260     StretchBlt (hdcImageList, i * himl->cx, 0, himl->cx, himl->cy,
2261                   hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
2262
2263     if (himl->hbmMask)
2264     {
2265         /* Replace Mask */
2266         SelectObject (hdcImageList, himl->hbmMask);
2267         SelectObject (hdcImage, hbmMask);
2268
2269         StretchBlt (hdcImageList, i * himl->cx, 0, himl->cx, himl->cy,
2270                       hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
2271
2272
2273         /* Remove the background from the image
2274         */
2275         SelectObject (hdcImageList, himl->hbmImage);
2276         StretchBlt (hdcImageList, 
2277             i*himl->cx, 0, himl->cx, himl->cy,
2278             hdcImage, 
2279             0, 0, bmp.bmWidth, bmp.bmHeight, 
2280             0x220326); /* NOTSRCAND */
2281     }
2282
2283     DeleteDC (hdcImage);
2284     DeleteDC (hdcImageList);
2285
2286     return TRUE;
2287 }
2288
2289
2290 /*************************************************************************
2291  * ImageList_ReplaceIcon [COMCTL32.69]
2292  *
2293  * Replaces an image in an image list using an icon.
2294  *
2295  * PARAMS
2296  *     himl  [I] handle to image list
2297  *     i     [I] image index
2298  *     hIcon [I] handle to icon
2299  *
2300  * RETURNS
2301  *     Success: index of the replaced image
2302  *     Failure: -1
2303  */
2304
2305 INT WINAPI
2306 ImageList_ReplaceIcon (HIMAGELIST himl, INT i, HICON hIcon)
2307 {
2308     HDC     hdcImageList, hdcImage;
2309     INT     nIndex;
2310     HICON   hBestFitIcon;
2311     HBITMAP hbmOldSrc, hbmOldDst;
2312     ICONINFO  ii;
2313     BITMAP  bmp;
2314
2315     TRACE("(0x%lx 0x%x 0x%x)\n", (DWORD)himl, i, hIcon);
2316
2317     if (himl == NULL)
2318         return -1;
2319     if ((i >= himl->cMaxImage) || (i < -1))
2320         return -1;
2321
2322     hBestFitIcon = CopyImage(
2323         hIcon, IMAGE_ICON, 
2324         himl->cx, himl->cy, 
2325         LR_COPYFROMRESOURCE);
2326
2327     GetIconInfo (hBestFitIcon, &ii);
2328     if (ii.hbmMask == 0)
2329         ERR("no mask!\n");
2330     if (ii.hbmColor == 0)
2331         ERR("no color!\n");
2332     GetObjectA (ii.hbmMask, sizeof(BITMAP), (LPVOID)&bmp);
2333
2334     if (i == -1) {
2335         if (himl->cCurImage + 1 >= himl->cMaxImage)
2336             IMAGELIST_InternalExpandBitmaps (himl, 1, 0, 0);
2337
2338         nIndex = himl->cCurImage;
2339         himl->cCurImage++;
2340     }
2341     else
2342         nIndex = i;
2343
2344     hdcImageList = CreateCompatibleDC (0);
2345     TRACE("hdcImageList=0x%x!\n", hdcImageList);
2346     if (hdcImageList == 0)
2347         ERR("invalid hdcImageList!\n");
2348
2349     hdcImage = CreateCompatibleDC (0);
2350     TRACE("hdcImage=0x%x!\n", hdcImage);
2351     if (hdcImage == 0)
2352         ERR("invalid hdcImage!\n");
2353
2354     hbmOldDst = SelectObject (hdcImageList, himl->hbmImage);
2355     SetTextColor( hdcImageList, RGB(0,0,0));
2356     SetBkColor( hdcImageList, RGB(255,255,255));
2357     hbmOldSrc = SelectObject (hdcImage, ii.hbmColor);
2358     StretchBlt (hdcImageList, nIndex * himl->cx, 0, himl->cx, himl->cy,
2359                   hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
2360
2361     if (himl->hbmMask) {
2362         SelectObject (hdcImageList, himl->hbmMask);
2363         SelectObject (hdcImage, ii.hbmMask);
2364         StretchBlt (hdcImageList, nIndex * himl->cx, 0, himl->cx, himl->cy,
2365                       hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
2366     }
2367
2368     SelectObject (hdcImage, hbmOldSrc);
2369     SelectObject (hdcImageList, hbmOldDst);
2370
2371     if(hBestFitIcon)
2372         DestroyIcon(hBestFitIcon);
2373     if (hdcImageList)
2374         DeleteDC (hdcImageList);
2375     if (hdcImage)
2376         DeleteDC (hdcImage);
2377     if (ii.hbmColor)
2378         DeleteObject (ii.hbmColor);
2379     if (ii.hbmMask)
2380         DeleteObject (ii.hbmMask);
2381
2382     return nIndex;
2383 }
2384
2385
2386 /*************************************************************************
2387  * ImageList_SetBkColor [COMCTL32.70] 
2388  *
2389  * Sets the background color of an image list.
2390  *
2391  * PARAMS
2392  *     himl  [I] handle to image list
2393  *     clrBk [I] background color
2394  *
2395  * RETURNS
2396  *     Success: previous background color
2397  *     Failure: CLR_NONE
2398  */
2399
2400 COLORREF WINAPI
2401 ImageList_SetBkColor (HIMAGELIST himl, COLORREF clrBk)
2402 {
2403     COLORREF clrOldBk;
2404
2405     if (himl == NULL)
2406         return CLR_NONE;
2407
2408     clrOldBk = himl->clrBk;
2409     himl->clrBk = clrBk;
2410     return clrOldBk;
2411 }
2412
2413
2414 /*************************************************************************
2415  * ImageList_SetDragCursorImage [COMCTL32.75]
2416  *
2417  * Combines the specified image with the current drag image
2418  *
2419  * PARAMS
2420  *     himlDrag  [I] handle to drag image list
2421  *     iDrag     [I] drag image index
2422  *     dxHotspot [I] X position of the hot spot
2423  *     dyHotspot [I] Y position of the hot spot
2424  *
2425  * RETURNS
2426  *     Success: TRUE
2427  *     Failure: FALSE
2428  *
2429  * BUGS
2430  *     semi-stub.
2431  */
2432
2433 BOOL WINAPI
2434 ImageList_SetDragCursorImage (HIMAGELIST himlDrag, INT iDrag,
2435                               INT dxHotspot, INT dyHotspot)
2436 {
2437     HIMAGELIST himlTemp;
2438
2439     FIXME("semi-stub!\n");
2440
2441     if (himlInternalDrag == NULL)
2442         return FALSE;
2443
2444     TRACE(" dxH=%d dyH=%d nX=%d nY=%d\n",
2445            dxHotspot, dyHotspot, nInternalDragHotspotX, nInternalDragHotspotY);
2446
2447     himlTemp = ImageList_Merge (himlInternalDrag, 0, himlDrag, iDrag,
2448                                 dxHotspot, dyHotspot);
2449
2450     ImageList_Destroy (himlInternalDrag);
2451     himlInternalDrag = himlTemp;
2452
2453     nInternalDragHotspotX = dxHotspot;
2454     nInternalDragHotspotY = dyHotspot;
2455
2456     return FALSE;
2457 }
2458
2459
2460 /*************************************************************************
2461  * ImageList_SetFilter [COMCTL32.76] 
2462  *
2463  * Sets a filter (or does something completely different)!!???
2464  *
2465  * PARAMS
2466  *     himl     [I] handle to image list
2467  *     i        [I] ???
2468  *     dwFilter [I] ???
2469  *
2470  * RETURNS
2471  *     Success: TRUE ???
2472  *     Failure: FALSE ???
2473  *
2474  * BUGS
2475  *     This is an UNDOCUMENTED function!!!!
2476  *     empty stub.
2477  */
2478
2479 BOOL WINAPI
2480 ImageList_SetFilter (HIMAGELIST himl, INT i, DWORD dwFilter)
2481 {
2482     FIXME("(%p 0x%x 0x%lx):empty stub!\n",
2483            himl, i, dwFilter);
2484
2485     return FALSE;
2486 }
2487
2488
2489 /*************************************************************************
2490  * ImageList_SetIconSize [COMCTL32.77]
2491  *
2492  * Sets the image size of the bitmap and deletes all images.
2493  *
2494  * PARAMS
2495  *     himl [I] handle to image list
2496  *     cx   [I] image width
2497  *     cy   [I] image height
2498  *
2499  * RETURNS
2500  *     Success: TRUE
2501  *     Failure: FALSE
2502  */
2503
2504 BOOL WINAPI
2505 ImageList_SetIconSize (HIMAGELIST himl, INT cx, INT cy)
2506 {
2507     INT nCount;
2508
2509     if (!himl)
2510         return FALSE;
2511
2512     /* remove all images */
2513     himl->cMaxImage = himl->cInitial + himl->cGrow;
2514     himl->cCurImage = 0;
2515     himl->cx        = cx;
2516     himl->cy        = cy;
2517
2518     /* initialize overlay mask indices */
2519     for (nCount = 0; nCount < MAX_OVERLAYIMAGE; nCount++)
2520         himl->nOvlIdx[nCount] = -1;
2521
2522     DeleteObject (himl->hbmImage);
2523     himl->hbmImage =
2524         CreateBitmap (himl->cMaxImage * himl->cx, himl->cy,
2525                         1, himl->uBitsPixel, NULL);
2526
2527     if (himl->hbmMask) {
2528         DeleteObject (himl->hbmMask);
2529         himl->hbmMask =
2530             CreateBitmap (himl->cMaxImage * himl->cx, himl->cy,
2531                             1, 1, NULL);
2532     }
2533
2534     return TRUE;
2535 }
2536
2537
2538 /*************************************************************************
2539  * ImageList_SetImageCount [COMCTL32.78]
2540  *
2541  * Resizes an image list to the specified number of images.
2542  *
2543  * PARAMS
2544  *     himl        [I] handle to image list
2545  *     iImageCount [I] number of images in the image list
2546  *
2547  * RETURNS
2548  *     Success: TRUE
2549  *     Failure: FALSE
2550  */
2551
2552 BOOL WINAPI
2553 ImageList_SetImageCount (HIMAGELIST himl, INT iImageCount)
2554 {
2555     HDC     hdcImageList, hdcBitmap;
2556     HBITMAP hbmNewBitmap;
2557     INT     nNewCount, nCopyCount;
2558
2559     if (!himl)
2560         return FALSE;
2561     if (himl->cCurImage >= iImageCount)
2562         return FALSE;
2563     if (himl->cMaxImage > iImageCount)
2564         return TRUE;
2565
2566     nNewCount = iImageCount + himl->cGrow;
2567     nCopyCount = _MIN(himl->cCurImage, iImageCount);
2568
2569     hdcImageList = CreateCompatibleDC (0);
2570     hdcBitmap = CreateCompatibleDC (0);
2571
2572     hbmNewBitmap = CreateBitmap (nNewCount * himl->cx, himl->cy,
2573                                    1, himl->uBitsPixel, NULL);
2574     if (hbmNewBitmap != 0)
2575     {
2576         SelectObject (hdcImageList, himl->hbmImage);
2577         SelectObject (hdcBitmap, hbmNewBitmap);
2578
2579         /* copy images */
2580         BitBlt (hdcBitmap, 0, 0, nCopyCount * himl->cx, himl->cy,
2581                   hdcImageList, 0, 0, SRCCOPY);
2582 #if 0
2583         /* delete 'empty' image space */
2584         SetBkColor (hdcBitmap, RGB(255, 255, 255));
2585         SetTextColor (hdcBitmap, RGB(0, 0, 0));
2586         PatBlt (hdcBitmap,  nCopyCount * himl->cx, 0, 
2587                   (nNewCount - nCopyCount) * himl->cx, himl->cy, BLACKNESS);
2588 #endif
2589         DeleteObject (himl->hbmImage);
2590         himl->hbmImage = hbmNewBitmap;
2591     }
2592     else
2593         ERR("Could not create new image bitmap !\n");
2594
2595     if (himl->hbmMask)
2596     {
2597         hbmNewBitmap = CreateBitmap (nNewCount * himl->cx, himl->cy,
2598                                        1, 1, NULL);
2599         if (hbmNewBitmap != 0)
2600         {
2601             SelectObject (hdcImageList, himl->hbmMask);
2602             SelectObject (hdcBitmap, hbmNewBitmap);
2603
2604             /* copy images */
2605             BitBlt (hdcBitmap, 0, 0, nCopyCount * himl->cx, himl->cy,
2606                       hdcImageList, 0, 0, SRCCOPY);
2607 #if 0
2608             /* delete 'empty' image space */
2609             SetBkColor (hdcBitmap, RGB(255, 255, 255));
2610             SetTextColor (hdcBitmap, RGB(0, 0, 0));
2611             PatBlt (hdcBitmap,  nCopyCount * himl->cx, 0, 
2612                       (nNewCount - nCopyCount) * himl->cx, himl->cy, BLACKNESS);
2613 #endif
2614             DeleteObject (himl->hbmMask);
2615             himl->hbmMask = hbmNewBitmap;
2616         }
2617         else
2618             ERR("Could not create new mask bitmap!\n");
2619     }
2620
2621     DeleteDC (hdcImageList);
2622     DeleteDC (hdcBitmap);
2623
2624     /* Update max image count and current image count */
2625     himl->cMaxImage = nNewCount;
2626     if (himl->cCurImage > nCopyCount)
2627         himl->cCurImage = nCopyCount;
2628
2629     return TRUE;
2630 }
2631
2632
2633 /*************************************************************************
2634  * ImageList_SetOverlayImage [COMCTL32.79]
2635  *
2636  * Assigns an overlay mask index to an existing image in an image list.
2637  *
2638  * PARAMS
2639  *     himl     [I] handle to image list
2640  *     iImage   [I] image index
2641  *     iOverlay [I] overlay mask index
2642  *
2643  * RETURNS
2644  *     Success: TRUE
2645  *     Failure: FALSE
2646  */
2647
2648 BOOL WINAPI
2649 ImageList_SetOverlayImage (HIMAGELIST himl, INT iImage, INT iOverlay)
2650 {
2651     if (!himl)
2652         return FALSE;
2653     if ((iOverlay < 1) || (iOverlay > MAX_OVERLAYIMAGE))
2654         return FALSE;
2655     if ((iImage!=-1) && ((iImage < 0) || (iImage > himl->cCurImage)))
2656         return FALSE;
2657     himl->nOvlIdx[iOverlay - 1] = iImage;
2658     return TRUE;
2659 }
2660
2661
2662 /*************************************************************************
2663  * ImageList_Write [COMCTL32.80]
2664  *
2665  * Writes an image list to a stream.
2666  *
2667  * PARAMS
2668  *     himl [I] handle to image list
2669  *     pstm [O] Pointer to a stream.
2670  *
2671  * RETURNS
2672  *     Success: TRUE
2673  *     Failure: FALSE
2674  *
2675  * NOTES
2676  *     This function can not be implemented yet, because
2677  *     IStream32::Write is not implemented.
2678  *
2679  * BUGS
2680  *     empty stub.
2681  */
2682
2683 BOOL WINAPI
2684 ImageList_Write (HIMAGELIST himl, LPSTREAM pstm)
2685 {
2686     if (!himl)
2687         return FALSE;
2688
2689     FIXME("empty stub!\n");
2690
2691     return FALSE;
2692 }
2693