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