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