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