French translation of the README file.
[wine.git] / windows / cursoricon.c
blobac62a1e9643dc4130debcb47b6cac94b2cfe77ac
1 /*
2 * Cursor and icon support
4 * Copyright 1995 Alexandre Julliard
5 * 1996 Martin Von Loewis
6 * 1997 Alex Korobka
7 * 1998 Turchanov Sergey
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 * Theory:
27 * http://www.microsoft.com/win32dev/ui/icons.htm
29 * Cursors and icons are stored in a global heap block, with the
30 * following layout:
32 * CURSORICONINFO info;
33 * BYTE[] ANDbits;
34 * BYTE[] XORbits;
36 * The bits structures are in the format of a device-dependent bitmap.
38 * This layout is very sub-optimal, as the bitmap bits are stored in
39 * the X client instead of in the server like other bitmaps; however,
40 * some programs (notably Paint Brush) expect to be able to manipulate
41 * the bits directly :-(
43 * FIXME: what are we going to do with animation and color (bpp > 1) cursors ?!
46 #include <string.h>
47 #include <stdlib.h>
49 #include "windef.h"
50 #include "wingdi.h"
51 #include "wine/winbase16.h"
52 #include "wine/winuser16.h"
53 #include "wine/exception.h"
54 #include "bitmap.h"
55 #include "cursoricon.h"
56 #include "module.h"
57 #include "wine/debug.h"
58 #include "user.h"
59 #include "input.h"
60 #include "message.h"
61 #include "winerror.h"
62 #include "msvcrt/excpt.h"
64 WINE_DECLARE_DEBUG_CHANNEL(cursor);
65 WINE_DECLARE_DEBUG_CHANNEL(icon);
66 WINE_DECLARE_DEBUG_CHANNEL(resource);
68 static HCURSOR hActiveCursor = 0; /* Active cursor */
69 static INT CURSOR_ShowCount = 0; /* Cursor display count */
70 static RECT CURSOR_ClipRect; /* Cursor clipping rect */
72 static HDC screen_dc;
74 /**********************************************************************
75 * ICONCACHE for cursors/icons loaded with LR_SHARED.
77 * FIXME: This should not be allocated on the system heap, but on a
78 * subsystem-global heap (i.e. one for all Win16 processes,
79 * and one for each Win32 process).
81 typedef struct tagICONCACHE
83 struct tagICONCACHE *next;
85 HMODULE hModule;
86 HRSRC hRsrc;
87 HRSRC hGroupRsrc;
88 HANDLE handle;
90 INT count;
92 } ICONCACHE;
94 static ICONCACHE *IconAnchor = NULL;
95 static CRITICAL_SECTION IconCrst = CRITICAL_SECTION_INIT("IconCrst");
96 static WORD ICON_HOTSPOT = 0x4242;
99 /***********************************************************************
100 * map_fileW
102 * Helper function to map a file to memory:
103 * name - file name
104 * [RETURN] ptr - pointer to mapped file
106 static void *map_fileW( LPCWSTR name )
108 HANDLE hFile, hMapping;
109 LPVOID ptr = NULL;
111 hFile = CreateFileW( name, GENERIC_READ, FILE_SHARE_READ, NULL,
112 OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, 0 );
113 if (hFile != INVALID_HANDLE_VALUE)
115 hMapping = CreateFileMappingA( hFile, NULL, PAGE_READONLY, 0, 0, NULL );
116 CloseHandle( hFile );
117 if (hMapping)
119 ptr = MapViewOfFile( hMapping, FILE_MAP_READ, 0, 0, 0 );
120 CloseHandle( hMapping );
123 return ptr;
127 /**********************************************************************
128 * CURSORICON_FindSharedIcon
130 static HANDLE CURSORICON_FindSharedIcon( HMODULE hModule, HRSRC hRsrc )
132 HANDLE handle = 0;
133 ICONCACHE *ptr;
135 EnterCriticalSection( &IconCrst );
137 for ( ptr = IconAnchor; ptr; ptr = ptr->next )
138 if ( ptr->hModule == hModule && ptr->hRsrc == hRsrc )
140 ptr->count++;
141 handle = ptr->handle;
142 break;
145 LeaveCriticalSection( &IconCrst );
147 return handle;
150 /*************************************************************************
151 * CURSORICON_FindCache
153 * Given a handle, find the corresponding cache element
155 * PARAMS
156 * Handle [I] handle to an Image
158 * RETURNS
159 * Success: The cache entry
160 * Failure: NULL
163 static ICONCACHE* CURSORICON_FindCache(HANDLE handle)
165 ICONCACHE *ptr;
166 ICONCACHE *pRet=NULL;
167 BOOL IsFound = FALSE;
168 int count;
170 EnterCriticalSection( &IconCrst );
172 for (count = 0, ptr = IconAnchor; ptr != NULL && !IsFound; ptr = ptr->next, count++ )
174 if ( handle == ptr->handle )
176 IsFound = TRUE;
177 pRet = ptr;
181 LeaveCriticalSection( &IconCrst );
183 return pRet;
186 /**********************************************************************
187 * CURSORICON_AddSharedIcon
189 static void CURSORICON_AddSharedIcon( HMODULE hModule, HRSRC hRsrc, HRSRC hGroupRsrc, HANDLE handle )
191 ICONCACHE *ptr = HeapAlloc( GetProcessHeap(), 0, sizeof(ICONCACHE) );
192 if ( !ptr ) return;
194 ptr->hModule = hModule;
195 ptr->hRsrc = hRsrc;
196 ptr->handle = handle;
197 ptr->hGroupRsrc = hGroupRsrc;
198 ptr->count = 1;
200 EnterCriticalSection( &IconCrst );
201 ptr->next = IconAnchor;
202 IconAnchor = ptr;
203 LeaveCriticalSection( &IconCrst );
206 /**********************************************************************
207 * CURSORICON_DelSharedIcon
209 static INT CURSORICON_DelSharedIcon( HANDLE handle )
211 INT count = -1;
212 ICONCACHE *ptr;
214 EnterCriticalSection( &IconCrst );
216 for ( ptr = IconAnchor; ptr; ptr = ptr->next )
217 if ( ptr->handle == handle )
219 if ( ptr->count > 0 ) ptr->count--;
220 count = ptr->count;
221 break;
224 LeaveCriticalSection( &IconCrst );
226 return count;
229 /**********************************************************************
230 * CURSORICON_FreeModuleIcons
232 void CURSORICON_FreeModuleIcons( HMODULE hModule )
234 ICONCACHE **ptr = &IconAnchor;
236 if ( HIWORD( hModule ) )
237 hModule = MapHModuleLS( hModule );
238 else
239 hModule = GetExePtr( hModule );
241 EnterCriticalSection( &IconCrst );
243 while ( *ptr )
245 if ( (*ptr)->hModule == hModule )
247 ICONCACHE *freePtr = *ptr;
248 *ptr = freePtr->next;
250 GlobalFree16( freePtr->handle );
251 HeapFree( GetProcessHeap(), 0, freePtr );
252 continue;
254 ptr = &(*ptr)->next;
257 LeaveCriticalSection( &IconCrst );
260 /**********************************************************************
261 * CURSORICON_FindBestIcon
263 * Find the icon closest to the requested size and number of colors.
265 static CURSORICONDIRENTRY *CURSORICON_FindBestIcon( CURSORICONDIR *dir, int width,
266 int height, int colors )
268 int i;
269 CURSORICONDIRENTRY *entry, *bestEntry = NULL;
270 UINT iTotalDiff, iXDiff=0, iYDiff=0, iColorDiff;
271 UINT iTempXDiff, iTempYDiff, iTempColorDiff;
273 if (dir->idCount < 1)
275 WARN_(icon)("Empty directory!\n" );
276 return NULL;
278 if (dir->idCount == 1) return &dir->idEntries[0]; /* No choice... */
280 /* Find Best Fit */
281 iTotalDiff = 0xFFFFFFFF;
282 iColorDiff = 0xFFFFFFFF;
283 for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
285 iTempXDiff = abs(width - entry->ResInfo.icon.bWidth);
286 iTempYDiff = abs(height - entry->ResInfo.icon.bHeight);
288 if(iTotalDiff > (iTempXDiff + iTempYDiff))
290 iXDiff = iTempXDiff;
291 iYDiff = iTempYDiff;
292 iTotalDiff = iXDiff + iYDiff;
296 /* Find Best Colors for Best Fit */
297 for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
299 if(abs(width - entry->ResInfo.icon.bWidth) == iXDiff &&
300 abs(height - entry->ResInfo.icon.bHeight) == iYDiff)
302 iTempColorDiff = abs(colors - entry->ResInfo.icon.bColorCount);
303 if(iColorDiff > iTempColorDiff)
305 bestEntry = entry;
306 iColorDiff = iTempColorDiff;
311 return bestEntry;
315 /**********************************************************************
316 * CURSORICON_FindBestCursor
318 * Find the cursor closest to the requested size.
319 * FIXME: parameter 'color' ignored and entries with more than 1 bpp
320 * ignored too
322 static CURSORICONDIRENTRY *CURSORICON_FindBestCursor( CURSORICONDIR *dir,
323 int width, int height, int color)
325 int i, maxwidth, maxheight;
326 CURSORICONDIRENTRY *entry, *bestEntry = NULL;
328 if (dir->idCount < 1)
330 WARN_(cursor)("Empty directory!\n" );
331 return NULL;
333 if (dir->idCount == 1) return &dir->idEntries[0]; /* No choice... */
335 /* Double height to account for AND and XOR masks */
337 height *= 2;
339 /* First find the largest one smaller than or equal to the requested size*/
341 maxwidth = maxheight = 0;
342 for(i = 0,entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
343 if ((entry->ResInfo.cursor.wWidth <= width) && (entry->ResInfo.cursor.wHeight <= height) &&
344 (entry->ResInfo.cursor.wWidth > maxwidth) && (entry->ResInfo.cursor.wHeight > maxheight) &&
345 (entry->wBitCount == 1))
347 bestEntry = entry;
348 maxwidth = entry->ResInfo.cursor.wWidth;
349 maxheight = entry->ResInfo.cursor.wHeight;
351 if (bestEntry) return bestEntry;
353 /* Now find the smallest one larger than the requested size */
355 maxwidth = maxheight = 255;
356 for(i = 0,entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
357 if ((entry->ResInfo.cursor.wWidth < maxwidth) && (entry->ResInfo.cursor.wHeight < maxheight) &&
358 (entry->wBitCount == 1))
360 bestEntry = entry;
361 maxwidth = entry->ResInfo.cursor.wWidth;
362 maxheight = entry->ResInfo.cursor.wHeight;
365 return bestEntry;
368 /*********************************************************************
369 * The main purpose of this function is to create fake resource directory
370 * and fake resource entries. There are several reasons for this:
371 * - CURSORICONDIR and CURSORICONFILEDIR differ in sizes and their
372 * fields
373 * There are some "bad" cursor files which do not have
374 * bColorCount initialized but instead one must read this info
375 * directly from corresponding DIB sections
376 * Note: wResId is index to array of pointer returned in ptrs (origin is 1)
378 BOOL CURSORICON_SimulateLoadingFromResourceW( LPWSTR filename, BOOL fCursor,
379 CURSORICONDIR **res, LPBYTE **ptr)
381 LPBYTE _free;
382 CURSORICONFILEDIR *bits;
383 int entries, size, i;
385 *res = NULL;
386 *ptr = NULL;
387 if (!(bits = map_fileW( filename ))) return FALSE;
389 /* FIXME: test for inimated icons
390 * hack to load the first icon from the *.ani file
392 if ( *(LPDWORD)bits==0x46464952 ) /* "RIFF" */
393 { LPBYTE pos = (LPBYTE) bits;
394 FIXME_(cursor)("Animated icons not correctly implemented! %p \n", bits);
396 for (;;)
397 { if (*(LPDWORD)pos==0x6e6f6369) /* "icon" */
398 { FIXME_(cursor)("icon entry found! %p\n", bits);
399 pos+=4;
400 if ( !*(LPWORD) pos==0x2fe) /* iconsize */
401 { goto fail;
403 bits=(CURSORICONFILEDIR*)(pos+4);
404 FIXME_(cursor)("icon size ok. offset=%p \n", bits);
405 break;
407 pos+=2;
408 if (pos>=(LPBYTE)bits+766) goto fail;
411 if (!(entries = bits->idCount)) goto fail;
412 size = sizeof(CURSORICONDIR) + sizeof(CURSORICONDIRENTRY) * (entries - 1);
413 _free = (LPBYTE) size;
415 for (i=0; i < entries; i++)
416 size += bits->idEntries[i].dwDIBSize + (fCursor ? sizeof(POINT16): 0);
418 if (!(*ptr = HeapAlloc( GetProcessHeap(), 0,
419 entries * sizeof (CURSORICONDIRENTRY*)))) goto fail;
420 if (!(*res = HeapAlloc( GetProcessHeap(), 0, size))) goto fail;
422 _free = (LPBYTE)(*res) + (int)_free;
423 memcpy((*res), bits, 6);
424 for (i=0; i<entries; i++)
426 ((LPBYTE*)(*ptr))[i] = _free;
427 if (fCursor) {
428 (*res)->idEntries[i].ResInfo.cursor.wWidth=bits->idEntries[i].bWidth;
429 (*res)->idEntries[i].ResInfo.cursor.wHeight=bits->idEntries[i].bHeight;
430 ((LPPOINT16)_free)->x=bits->idEntries[i].xHotspot;
431 ((LPPOINT16)_free)->y=bits->idEntries[i].yHotspot;
432 _free+=sizeof(POINT16);
433 } else {
434 (*res)->idEntries[i].ResInfo.icon.bWidth=bits->idEntries[i].bWidth;
435 (*res)->idEntries[i].ResInfo.icon.bHeight=bits->idEntries[i].bHeight;
436 (*res)->idEntries[i].ResInfo.icon.bColorCount = bits->idEntries[i].bColorCount;
438 (*res)->idEntries[i].wPlanes=1;
439 (*res)->idEntries[i].wBitCount = ((LPBITMAPINFOHEADER)((LPBYTE)bits +
440 bits->idEntries[i].dwDIBOffset))->biBitCount;
441 (*res)->idEntries[i].dwBytesInRes = bits->idEntries[i].dwDIBSize;
442 (*res)->idEntries[i].wResId=i+1;
444 memcpy(_free,(LPBYTE)bits +bits->idEntries[i].dwDIBOffset,
445 (*res)->idEntries[i].dwBytesInRes);
446 _free += (*res)->idEntries[i].dwBytesInRes;
448 UnmapViewOfFile( bits );
449 return TRUE;
450 fail:
451 if (*res) HeapFree( GetProcessHeap(), 0, *res );
452 if (*ptr) HeapFree( GetProcessHeap(), 0, *ptr );
453 UnmapViewOfFile( bits );
454 return FALSE;
458 /**********************************************************************
459 * CURSORICON_CreateFromResource
461 * Create a cursor or icon from in-memory resource template.
463 * FIXME: Convert to mono when cFlag is LR_MONOCHROME. Do something
464 * with cbSize parameter as well.
466 static HGLOBAL16 CURSORICON_CreateFromResource( HINSTANCE16 hInstance, HGLOBAL16 hObj, LPBYTE bits,
467 UINT cbSize, BOOL bIcon, DWORD dwVersion,
468 INT width, INT height, UINT loadflags )
470 static HDC hdcMem;
471 int sizeAnd, sizeXor;
472 HBITMAP hAndBits = 0, hXorBits = 0; /* error condition for later */
473 BITMAP bmpXor, bmpAnd;
474 POINT16 hotspot;
475 BITMAPINFO *bmi;
476 BOOL DoStretch;
477 INT size;
479 hotspot.x = ICON_HOTSPOT;
480 hotspot.y = ICON_HOTSPOT;
482 TRACE_(cursor)("%08x (%u bytes), ver %08x, %ix%i %s %s\n",
483 (unsigned)bits, cbSize, (unsigned)dwVersion, width, height,
484 bIcon ? "icon" : "cursor", (loadflags & LR_MONOCHROME) ? "mono" : "" );
485 if (dwVersion == 0x00020000)
487 FIXME_(cursor)("\t2.xx resources are not supported\n");
488 return 0;
491 if (bIcon)
492 bmi = (BITMAPINFO *)bits;
493 else /* get the hotspot */
495 POINT16 *pt = (POINT16 *)bits;
496 hotspot = *pt;
497 bmi = (BITMAPINFO *)(pt + 1);
499 size = DIB_BitmapInfoSize( bmi, DIB_RGB_COLORS );
501 if (!width) width = bmi->bmiHeader.biWidth;
502 if (!height) height = bmi->bmiHeader.biHeight/2;
503 DoStretch = (bmi->bmiHeader.biHeight/2 != height) ||
504 (bmi->bmiHeader.biWidth != width);
506 /* Check bitmap header */
508 if ( (bmi->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) &&
509 (bmi->bmiHeader.biSize != sizeof(BITMAPINFOHEADER) ||
510 bmi->bmiHeader.biCompression != BI_RGB) )
512 WARN_(cursor)("\tinvalid resource bitmap header.\n");
513 return 0;
516 if (!screen_dc) screen_dc = CreateDCA( "DISPLAY", NULL, NULL, NULL );
517 if (screen_dc)
519 BITMAPINFO* pInfo;
521 /* Make sure we have room for the monochrome bitmap later on.
522 * Note that BITMAPINFOINFO and BITMAPCOREHEADER are the same
523 * up to and including the biBitCount. In-memory icon resource
524 * format is as follows:
526 * BITMAPINFOHEADER icHeader // DIB header
527 * RGBQUAD icColors[] // Color table
528 * BYTE icXOR[] // DIB bits for XOR mask
529 * BYTE icAND[] // DIB bits for AND mask
532 if ((pInfo = (BITMAPINFO *)HeapAlloc( GetProcessHeap(), 0,
533 max(size, sizeof(BITMAPINFOHEADER) + 2*sizeof(RGBQUAD)))))
535 memcpy( pInfo, bmi, size );
536 pInfo->bmiHeader.biHeight /= 2;
538 /* Create the XOR bitmap */
540 if (DoStretch) {
541 if(bIcon)
543 hXorBits = CreateCompatibleBitmap(screen_dc, width, height);
545 else
547 hXorBits = CreateBitmap(width, height, 1, 1, NULL);
549 if(hXorBits)
551 HBITMAP hOld;
552 BOOL res = FALSE;
554 if (!hdcMem) hdcMem = CreateCompatibleDC(screen_dc);
555 if (hdcMem) {
556 hOld = SelectObject(hdcMem, hXorBits);
557 res = StretchDIBits(hdcMem, 0, 0, width, height, 0, 0,
558 bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight/2,
559 (char*)bmi + size, pInfo, DIB_RGB_COLORS, SRCCOPY);
560 SelectObject(hdcMem, hOld);
562 if (!res) { DeleteObject(hXorBits); hXorBits = 0; }
564 } else hXorBits = CreateDIBitmap( screen_dc, &pInfo->bmiHeader,
565 CBM_INIT, (char*)bmi + size, pInfo, DIB_RGB_COLORS );
566 if( hXorBits )
568 char* xbits = (char *)bmi + size +
569 DIB_GetDIBImageBytes(bmi->bmiHeader.biWidth,
570 bmi->bmiHeader.biHeight,
571 bmi->bmiHeader.biBitCount) / 2;
573 pInfo->bmiHeader.biBitCount = 1;
574 if (pInfo->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
576 RGBQUAD *rgb = pInfo->bmiColors;
578 pInfo->bmiHeader.biClrUsed = pInfo->bmiHeader.biClrImportant = 2;
579 rgb[0].rgbBlue = rgb[0].rgbGreen = rgb[0].rgbRed = 0x00;
580 rgb[1].rgbBlue = rgb[1].rgbGreen = rgb[1].rgbRed = 0xff;
581 rgb[0].rgbReserved = rgb[1].rgbReserved = 0;
583 else
585 RGBTRIPLE *rgb = (RGBTRIPLE *)(((BITMAPCOREHEADER *)pInfo) + 1);
587 rgb[0].rgbtBlue = rgb[0].rgbtGreen = rgb[0].rgbtRed = 0x00;
588 rgb[1].rgbtBlue = rgb[1].rgbtGreen = rgb[1].rgbtRed = 0xff;
591 /* Create the AND bitmap */
593 if (DoStretch) {
594 if ((hAndBits = CreateBitmap(width, height, 1, 1, NULL))) {
595 HBITMAP hOld;
596 BOOL res = FALSE;
598 if (!hdcMem) hdcMem = CreateCompatibleDC(screen_dc);
599 if (hdcMem) {
600 hOld = SelectObject(hdcMem, hAndBits);
601 res = StretchDIBits(hdcMem, 0, 0, width, height, 0, 0,
602 pInfo->bmiHeader.biWidth, pInfo->bmiHeader.biHeight,
603 xbits, pInfo, DIB_RGB_COLORS, SRCCOPY);
604 SelectObject(hdcMem, hOld);
606 if (!res) { DeleteObject(hAndBits); hAndBits = 0; }
608 } else hAndBits = CreateDIBitmap( screen_dc, &pInfo->bmiHeader,
609 CBM_INIT, xbits, pInfo, DIB_RGB_COLORS );
611 if( !hAndBits ) DeleteObject( hXorBits );
613 HeapFree( GetProcessHeap(), 0, pInfo );
617 if( !hXorBits || !hAndBits )
619 WARN_(cursor)("\tunable to create an icon bitmap.\n");
620 return 0;
623 /* Now create the CURSORICONINFO structure */
624 GetObjectA( hXorBits, sizeof(bmpXor), &bmpXor );
625 GetObjectA( hAndBits, sizeof(bmpAnd), &bmpAnd );
626 sizeXor = bmpXor.bmHeight * bmpXor.bmWidthBytes;
627 sizeAnd = bmpAnd.bmHeight * bmpAnd.bmWidthBytes;
629 if (hObj) hObj = GlobalReAlloc16( hObj,
630 sizeof(CURSORICONINFO) + sizeXor + sizeAnd, GMEM_MOVEABLE );
631 if (!hObj) hObj = GlobalAlloc16( GMEM_MOVEABLE,
632 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
633 if (hObj)
635 CURSORICONINFO *info;
637 /* Make it owned by the module */
638 if (hInstance) hInstance = GetExePtr(hInstance);
639 FarSetOwner16( hObj, hInstance );
641 info = (CURSORICONINFO *)GlobalLock16( hObj );
642 info->ptHotSpot.x = hotspot.x;
643 info->ptHotSpot.y = hotspot.y;
644 info->nWidth = bmpXor.bmWidth;
645 info->nHeight = bmpXor.bmHeight;
646 info->nWidthBytes = bmpXor.bmWidthBytes;
647 info->bPlanes = bmpXor.bmPlanes;
648 info->bBitsPerPixel = bmpXor.bmBitsPixel;
650 /* Transfer the bitmap bits to the CURSORICONINFO structure */
652 GetBitmapBits( hAndBits, sizeAnd, (char *)(info + 1) );
653 GetBitmapBits( hXorBits, sizeXor, (char *)(info + 1) + sizeAnd );
654 GlobalUnlock16( hObj );
657 DeleteObject( hAndBits );
658 DeleteObject( hXorBits );
659 return hObj;
663 /**********************************************************************
664 * CreateIconFromResourceEx (USER.450)
666 * FIXME: not sure about exact parameter types
668 HICON16 WINAPI CreateIconFromResourceEx16( LPBYTE bits, UINT16 cbSize, BOOL16 bIcon,
669 DWORD dwVersion, INT16 width, INT16 height, UINT16 cFlag )
671 return CreateIconFromResourceEx(bits, cbSize, bIcon, dwVersion,
672 width, height, cFlag);
676 /**********************************************************************
677 * CreateIconFromResource (USER32.@)
679 HICON WINAPI CreateIconFromResource( LPBYTE bits, UINT cbSize,
680 BOOL bIcon, DWORD dwVersion)
682 return CreateIconFromResourceEx( bits, cbSize, bIcon, dwVersion, 0,0,0);
686 /**********************************************************************
687 * CreateIconFromResourceEx (USER32.@)
689 HICON WINAPI CreateIconFromResourceEx( LPBYTE bits, UINT cbSize,
690 BOOL bIcon, DWORD dwVersion,
691 INT width, INT height,
692 UINT cFlag )
694 return CURSORICON_CreateFromResource( 0, 0, bits, cbSize, bIcon, dwVersion,
695 width, height, cFlag );
698 /**********************************************************************
699 * CURSORICON_Load
701 * Load a cursor or icon from resource or file.
703 HGLOBAL CURSORICON_Load( HINSTANCE hInstance, LPCWSTR name,
704 INT width, INT height, INT colors,
705 BOOL fCursor, UINT loadflags )
707 HANDLE handle = 0, h = 0;
708 HANDLE hRsrc;
709 CURSORICONDIR *dir;
710 CURSORICONDIRENTRY *dirEntry;
711 LPBYTE bits;
713 if ( loadflags & LR_LOADFROMFILE ) /* Load from file */
715 LPBYTE *ptr;
716 if (!CURSORICON_SimulateLoadingFromResourceW((LPWSTR)name, fCursor, &dir, &ptr))
717 return 0;
718 if (fCursor)
719 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor(dir, width, height, 1);
720 else
721 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon(dir, width, height, colors);
722 bits = ptr[dirEntry->wResId-1];
723 h = CURSORICON_CreateFromResource( 0, 0, bits, dirEntry->dwBytesInRes,
724 !fCursor, 0x00030000, width, height, loadflags);
725 HeapFree( GetProcessHeap(), 0, dir );
726 HeapFree( GetProcessHeap(), 0, ptr );
728 else /* Load from resource */
730 HANDLE hGroupRsrc;
731 WORD wResId;
732 DWORD dwBytesInRes;
734 if (!hInstance) /* Load OEM cursor/icon */
736 if (!(hInstance = GetModuleHandleA( "user32.dll" ))) return 0;
739 /* Normalize hInstance (must be uniquely represented for icon cache) */
741 if ( HIWORD( hInstance ) )
742 hInstance = MapHModuleLS( hInstance );
743 else
744 hInstance = GetExePtr( hInstance );
746 /* Get directory resource ID */
748 if (!(hRsrc = FindResourceW( hInstance, name,
749 fCursor ? RT_GROUP_CURSORW : RT_GROUP_ICONW )))
750 return 0;
751 hGroupRsrc = hRsrc;
753 /* Find the best entry in the directory */
755 if (!(handle = LoadResource( hInstance, hRsrc ))) return 0;
756 if (!(dir = (CURSORICONDIR*)LockResource( handle ))) return 0;
757 if (fCursor)
758 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor( dir,
759 width, height, 1);
760 else
761 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon( dir,
762 width, height, colors );
763 if (!dirEntry) return 0;
764 wResId = dirEntry->wResId;
765 dwBytesInRes = dirEntry->dwBytesInRes;
766 FreeResource( handle );
768 /* Load the resource */
770 if (!(hRsrc = FindResourceW(hInstance,MAKEINTRESOURCEW(wResId),
771 fCursor ? RT_CURSORW : RT_ICONW ))) return 0;
773 /* If shared icon, check whether it was already loaded */
774 if ( (loadflags & LR_SHARED)
775 && (h = CURSORICON_FindSharedIcon( hInstance, hRsrc ) ) != 0 )
776 return h;
778 if (!(handle = LoadResource( hInstance, hRsrc ))) return 0;
779 bits = (LPBYTE)LockResource( handle );
780 h = CURSORICON_CreateFromResource( 0, 0, bits, dwBytesInRes,
781 !fCursor, 0x00030000, width, height, loadflags);
782 FreeResource( handle );
784 /* If shared icon, add to icon cache */
786 if ( h && (loadflags & LR_SHARED) )
787 CURSORICON_AddSharedIcon( hInstance, hRsrc, hGroupRsrc, h );
790 return h;
793 /***********************************************************************
794 * CURSORICON_Copy
796 * Make a copy of a cursor or icon.
798 static HGLOBAL16 CURSORICON_Copy( HINSTANCE16 hInstance, HGLOBAL16 handle )
800 char *ptrOld, *ptrNew;
801 int size;
802 HGLOBAL16 hNew;
804 if (!(ptrOld = (char *)GlobalLock16( handle ))) return 0;
805 if (hInstance && !(hInstance = GetExePtr( hInstance ))) return 0;
806 size = GlobalSize16( handle );
807 hNew = GlobalAlloc16( GMEM_MOVEABLE, size );
808 FarSetOwner16( hNew, hInstance );
809 ptrNew = (char *)GlobalLock16( hNew );
810 memcpy( ptrNew, ptrOld, size );
811 GlobalUnlock16( handle );
812 GlobalUnlock16( hNew );
813 return hNew;
816 /*************************************************************************
817 * CURSORICON_ExtCopy
819 * Copies an Image from the Cache if LR_COPYFROMRESOURCE is specified
821 * PARAMS
822 * Handle [I] handle to an Image
823 * nType [I] Type of Handle (IMAGE_CURSOR | IMAGE_ICON)
824 * iDesiredCX [I] The Desired width of the Image
825 * iDesiredCY [I] The desired height of the Image
826 * nFlags [I] The flags from CopyImage
828 * RETURNS
829 * Success: The new handle of the Image
831 * NOTES
832 * LR_COPYDELETEORG and LR_MONOCHROME are currently not implemented.
833 * LR_MONOCHROME should be implemented by CURSORICON_CreateFromResource.
834 * LR_COPYFROMRESOURCE will only work if the Image is in the Cache.
839 HGLOBAL CURSORICON_ExtCopy(HGLOBAL Handle, UINT nType,
840 INT iDesiredCX, INT iDesiredCY,
841 UINT nFlags)
843 HGLOBAL16 hNew=0;
845 TRACE_(icon)("Handle %u, uType %u, iDesiredCX %i, iDesiredCY %i, nFlags %u\n",
846 Handle, nType, iDesiredCX, iDesiredCY, nFlags);
848 if(Handle == 0)
850 return 0;
853 /* Best Fit or Monochrome */
854 if( (nFlags & LR_COPYFROMRESOURCE
855 && (iDesiredCX > 0 || iDesiredCY > 0))
856 || nFlags & LR_MONOCHROME)
858 ICONCACHE* pIconCache = CURSORICON_FindCache(Handle);
860 /* Not Found in Cache, then do a straight copy
862 if(pIconCache == NULL)
864 hNew = CURSORICON_Copy(0, Handle);
865 if(nFlags & LR_COPYFROMRESOURCE)
867 TRACE_(icon)("LR_COPYFROMRESOURCE: Failed to load from cache\n");
870 else
872 int iTargetCY = iDesiredCY, iTargetCX = iDesiredCX;
873 LPBYTE pBits;
874 HANDLE hMem;
875 HRSRC hRsrc;
876 DWORD dwBytesInRes;
877 WORD wResId;
878 CURSORICONDIR *pDir;
879 CURSORICONDIRENTRY *pDirEntry;
880 BOOL bIsIcon = (nType == IMAGE_ICON);
882 /* Completing iDesiredCX CY for Monochrome Bitmaps if needed
884 if(((nFlags & LR_MONOCHROME) && !(nFlags & LR_COPYFROMRESOURCE))
885 || (iDesiredCX == 0 && iDesiredCY == 0))
887 iDesiredCY = GetSystemMetrics(bIsIcon ?
888 SM_CYICON : SM_CYCURSOR);
889 iDesiredCX = GetSystemMetrics(bIsIcon ?
890 SM_CXICON : SM_CXCURSOR);
893 /* Retrieve the CURSORICONDIRENTRY
895 if (!(hMem = LoadResource( pIconCache->hModule ,
896 pIconCache->hGroupRsrc)))
898 return 0;
900 if (!(pDir = (CURSORICONDIR*)LockResource( hMem )))
902 return 0;
905 /* Find Best Fit
907 if(bIsIcon)
909 pDirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon(
910 pDir, iDesiredCX, iDesiredCY, 256);
912 else
914 pDirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor(
915 pDir, iDesiredCX, iDesiredCY, 1);
918 wResId = pDirEntry->wResId;
919 dwBytesInRes = pDirEntry->dwBytesInRes;
920 FreeResource(hMem);
922 TRACE_(icon)("ResID %u, BytesInRes %lu, Width %d, Height %d DX %d, DY %d\n",
923 wResId, dwBytesInRes, pDirEntry->ResInfo.icon.bWidth,
924 pDirEntry->ResInfo.icon.bHeight, iDesiredCX, iDesiredCY);
926 /* Get the Best Fit
928 if (!(hRsrc = FindResourceW(pIconCache->hModule ,
929 MAKEINTRESOURCEW(wResId), bIsIcon ? RT_ICONW : RT_CURSORW)))
931 return 0;
933 if (!(hMem = LoadResource( pIconCache->hModule , hRsrc )))
935 return 0;
938 pBits = (LPBYTE)LockResource( hMem );
940 if(nFlags & LR_DEFAULTSIZE)
942 iTargetCY = GetSystemMetrics(SM_CYICON);
943 iTargetCX = GetSystemMetrics(SM_CXICON);
946 /* Create a New Icon with the proper dimension
948 hNew = CURSORICON_CreateFromResource( 0, 0, pBits, dwBytesInRes,
949 bIsIcon, 0x00030000, iTargetCX, iTargetCY, nFlags);
950 FreeResource(hMem);
953 else hNew = CURSORICON_Copy(0, Handle);
954 return hNew;
958 /***********************************************************************
959 * LoadCursor (USER.173)
961 HCURSOR16 WINAPI LoadCursor16( HINSTANCE16 hInstance, LPCSTR name )
963 return LoadCursorA( hInstance, name );
967 /***********************************************************************
968 * LoadIcon (USER.174)
970 HICON16 WINAPI LoadIcon16( HINSTANCE16 hInstance, LPCSTR name )
972 return LoadIconA( hInstance, name );
976 /***********************************************************************
977 * CreateCursor (USER.406)
979 HCURSOR16 WINAPI CreateCursor16( HINSTANCE16 hInstance,
980 INT16 xHotSpot, INT16 yHotSpot,
981 INT16 nWidth, INT16 nHeight,
982 LPCVOID lpANDbits, LPCVOID lpXORbits )
984 CURSORICONINFO info;
986 TRACE_(cursor)("%dx%d spot=%d,%d xor=%p and=%p\n",
987 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
989 info.ptHotSpot.x = xHotSpot;
990 info.ptHotSpot.y = yHotSpot;
991 info.nWidth = nWidth;
992 info.nHeight = nHeight;
993 info.nWidthBytes = 0;
994 info.bPlanes = 1;
995 info.bBitsPerPixel = 1;
997 return CreateCursorIconIndirect16( hInstance, &info, lpANDbits, lpXORbits );
1001 /***********************************************************************
1002 * CreateCursor (USER32.@)
1004 HCURSOR WINAPI CreateCursor( HINSTANCE hInstance,
1005 INT xHotSpot, INT yHotSpot,
1006 INT nWidth, INT nHeight,
1007 LPCVOID lpANDbits, LPCVOID lpXORbits )
1009 CURSORICONINFO info;
1011 TRACE_(cursor)("%dx%d spot=%d,%d xor=%p and=%p\n",
1012 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
1014 info.ptHotSpot.x = xHotSpot;
1015 info.ptHotSpot.y = yHotSpot;
1016 info.nWidth = nWidth;
1017 info.nHeight = nHeight;
1018 info.nWidthBytes = 0;
1019 info.bPlanes = 1;
1020 info.bBitsPerPixel = 1;
1022 return CreateCursorIconIndirect16( 0, &info, lpANDbits, lpXORbits );
1026 /***********************************************************************
1027 * CreateIcon (USER.407)
1029 HICON16 WINAPI CreateIcon16( HINSTANCE16 hInstance, INT16 nWidth,
1030 INT16 nHeight, BYTE bPlanes, BYTE bBitsPixel,
1031 LPCVOID lpANDbits, LPCVOID lpXORbits )
1033 CURSORICONINFO info;
1035 TRACE_(icon)("%dx%dx%d, xor=%p, and=%p\n",
1036 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
1038 info.ptHotSpot.x = ICON_HOTSPOT;
1039 info.ptHotSpot.y = ICON_HOTSPOT;
1040 info.nWidth = nWidth;
1041 info.nHeight = nHeight;
1042 info.nWidthBytes = 0;
1043 info.bPlanes = bPlanes;
1044 info.bBitsPerPixel = bBitsPixel;
1046 return CreateCursorIconIndirect16( hInstance, &info, lpANDbits, lpXORbits );
1050 /***********************************************************************
1051 * CreateIcon (USER32.@)
1053 * Creates an icon based on the specified bitmaps. The bitmaps must be
1054 * provided in a device dependent format and will be resized to
1055 * (SM_CXICON,SM_CYICON) and depth converted to match the screen's color
1056 * depth. The provided bitmaps must be top-down bitmaps.
1057 * Although Windows does not support 15bpp(*) this API must support it
1058 * for Winelib applications.
1060 * (*) Windows does not support 15bpp but it supports the 555 RGB 16bpp
1061 * format!
1063 * BUGS
1065 * - The provided bitmaps are not resized!
1066 * - The documentation says the lpXORbits bitmap must be in a device
1067 * dependent format. But we must still resize it and perform depth
1068 * conversions if necessary.
1069 * - I'm a bit unsure about the how the 'device dependent format' thing works.
1070 * I did some tests on windows and found that if you provide a 16bpp bitmap
1071 * in lpXORbits, then its format but be 565 RGB if the screen's bit depth
1072 * is 16bpp but it must be 555 RGB if the screen's bit depth is anything
1073 * else. I don't know if this is part of the GDI specs or if this is a
1074 * quirk of the graphics card driver.
1075 * - You may think that we check whether the bit depths match or not
1076 * as an optimization. But the truth is that the conversion using
1077 * CreateDIBitmap does not work for some bit depth (e.g. 8bpp) and I have
1078 * no idea why.
1079 * - I'm pretty sure that all the things we do in CreateIcon should
1080 * also be done in CreateIconIndirect...
1082 HICON WINAPI CreateIcon(
1083 HINSTANCE hInstance, /* [in] the application's hInstance, currently unused */
1084 INT nWidth, /* [in] the width of the provided bitmaps */
1085 INT nHeight, /* [in] the height of the provided bitmaps */
1086 BYTE bPlanes, /* [in] the number of planes in the provided bitmaps */
1087 BYTE bBitsPixel, /* [in] the number of bits per pixel of the lpXORbits bitmap */
1088 LPCVOID lpANDbits, /* [in] a monochrome bitmap representing the icon's mask */
1089 LPCVOID lpXORbits) /* [in] the icon's 'color' bitmap */
1091 HICON hIcon;
1092 HDC hdc;
1094 TRACE_(icon)("%dx%dx%d, xor=%p, and=%p\n",
1095 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
1097 hdc=GetDC(0);
1098 if (!hdc)
1099 return 0;
1101 if (GetDeviceCaps(hdc,BITSPIXEL)==bBitsPixel) {
1102 CURSORICONINFO info;
1104 info.ptHotSpot.x = ICON_HOTSPOT;
1105 info.ptHotSpot.y = ICON_HOTSPOT;
1106 info.nWidth = nWidth;
1107 info.nHeight = nHeight;
1108 info.nWidthBytes = 0;
1109 info.bPlanes = bPlanes;
1110 info.bBitsPerPixel = bBitsPixel;
1112 hIcon=CreateCursorIconIndirect16( 0, &info, lpANDbits, lpXORbits );
1113 } else {
1114 ICONINFO iinfo;
1115 BITMAPINFO bmi;
1117 iinfo.fIcon=TRUE;
1118 iinfo.xHotspot=ICON_HOTSPOT;
1119 iinfo.yHotspot=ICON_HOTSPOT;
1120 iinfo.hbmMask=CreateBitmap(nWidth,nHeight,1,1,lpANDbits);
1122 bmi.bmiHeader.biSize=sizeof(bmi.bmiHeader);
1123 bmi.bmiHeader.biWidth=nWidth;
1124 bmi.bmiHeader.biHeight=-nHeight;
1125 bmi.bmiHeader.biPlanes=bPlanes;
1126 bmi.bmiHeader.biBitCount=bBitsPixel;
1127 bmi.bmiHeader.biCompression=BI_RGB;
1128 bmi.bmiHeader.biSizeImage=0;
1129 bmi.bmiHeader.biXPelsPerMeter=0;
1130 bmi.bmiHeader.biYPelsPerMeter=0;
1131 bmi.bmiHeader.biClrUsed=0;
1132 bmi.bmiHeader.biClrImportant=0;
1134 iinfo.hbmColor = CreateDIBitmap( hdc, &bmi.bmiHeader,
1135 CBM_INIT, lpXORbits,
1136 &bmi, DIB_RGB_COLORS );
1138 hIcon=CreateIconIndirect(&iinfo);
1139 DeleteObject(iinfo.hbmMask);
1140 DeleteObject(iinfo.hbmColor);
1142 ReleaseDC(0,hdc);
1143 return hIcon;
1147 /***********************************************************************
1148 * CreateCursorIconIndirect (USER.408)
1150 HGLOBAL16 WINAPI CreateCursorIconIndirect16( HINSTANCE16 hInstance,
1151 CURSORICONINFO *info,
1152 LPCVOID lpANDbits,
1153 LPCVOID lpXORbits )
1155 HGLOBAL16 handle;
1156 char *ptr;
1157 int sizeAnd, sizeXor;
1159 hInstance = GetExePtr( hInstance ); /* Make it a module handle */
1160 if (!lpXORbits || !lpANDbits || info->bPlanes != 1) return 0;
1161 info->nWidthBytes = BITMAP_GetWidthBytes(info->nWidth,info->bBitsPerPixel);
1162 sizeXor = info->nHeight * info->nWidthBytes;
1163 sizeAnd = info->nHeight * BITMAP_GetWidthBytes( info->nWidth, 1 );
1164 if (!(handle = GlobalAlloc16( GMEM_MOVEABLE,
1165 sizeof(CURSORICONINFO) + sizeXor + sizeAnd)))
1166 return 0;
1167 FarSetOwner16( handle, hInstance );
1168 ptr = (char *)GlobalLock16( handle );
1169 memcpy( ptr, info, sizeof(*info) );
1170 memcpy( ptr + sizeof(CURSORICONINFO), lpANDbits, sizeAnd );
1171 memcpy( ptr + sizeof(CURSORICONINFO) + sizeAnd, lpXORbits, sizeXor );
1172 GlobalUnlock16( handle );
1173 return handle;
1177 /***********************************************************************
1178 * CopyIcon (USER.368)
1180 HICON16 WINAPI CopyIcon16( HINSTANCE16 hInstance, HICON16 hIcon )
1182 TRACE_(icon)("%04x %04x\n", hInstance, hIcon );
1183 return CURSORICON_Copy( hInstance, hIcon );
1187 /***********************************************************************
1188 * CopyIcon (USER32.@)
1190 HICON WINAPI CopyIcon( HICON hIcon )
1192 TRACE_(icon)("%04x\n", hIcon );
1193 return CURSORICON_Copy( 0, hIcon );
1197 /***********************************************************************
1198 * CopyCursor (USER.369)
1200 HCURSOR16 WINAPI CopyCursor16( HINSTANCE16 hInstance, HCURSOR16 hCursor )
1202 TRACE_(cursor)("%04x %04x\n", hInstance, hCursor );
1203 return CURSORICON_Copy( hInstance, hCursor );
1206 /**********************************************************************
1207 * DestroyIcon32 (USER.610)
1208 * DestroyIcon32 (USER32.@)
1210 * This routine is actually exported from Win95 USER under the name
1211 * DestroyIcon32 ... The behaviour implemented here should mimic
1212 * the Win95 one exactly, especially the return values, which
1213 * depend on the setting of various flags.
1215 WORD WINAPI DestroyIcon32( HGLOBAL16 handle, UINT16 flags )
1217 WORD retv;
1219 TRACE_(icon)("(%04x, %04x)\n", handle, flags );
1221 /* Check whether destroying active cursor */
1223 if ( hActiveCursor == handle )
1225 WARN_(cursor)("Destroying active cursor!\n" );
1226 SetCursor( 0 );
1229 /* Try shared cursor/icon first */
1231 if ( !(flags & CID_NONSHARED) )
1233 INT count = CURSORICON_DelSharedIcon( handle );
1235 if ( count != -1 )
1236 return (flags & CID_WIN32)? TRUE : (count == 0);
1238 /* FIXME: OEM cursors/icons should be recognized */
1241 /* Now assume non-shared cursor/icon */
1243 retv = GlobalFree16( handle );
1244 return (flags & CID_RESOURCE)? retv : TRUE;
1247 /***********************************************************************
1248 * DestroyIcon (USER.457)
1250 BOOL16 WINAPI DestroyIcon16( HICON16 hIcon )
1252 return DestroyIcon32( hIcon, 0 );
1255 /***********************************************************************
1256 * DestroyIcon (USER32.@)
1258 BOOL WINAPI DestroyIcon( HICON hIcon )
1260 return DestroyIcon32( hIcon, CID_WIN32 );
1263 /***********************************************************************
1264 * DestroyCursor (USER.458)
1266 BOOL16 WINAPI DestroyCursor16( HCURSOR16 hCursor )
1268 return DestroyIcon32( hCursor, 0 );
1271 /***********************************************************************
1272 * DestroyCursor (USER32.@)
1274 BOOL WINAPI DestroyCursor( HCURSOR hCursor )
1276 return DestroyIcon32( hCursor, CID_WIN32 );
1280 /***********************************************************************
1281 * DrawIcon (USER.84)
1283 BOOL16 WINAPI DrawIcon16( HDC16 hdc, INT16 x, INT16 y, HICON16 hIcon )
1285 return DrawIcon( hdc, x, y, hIcon );
1289 /***********************************************************************
1290 * DrawIcon (USER32.@)
1292 BOOL WINAPI DrawIcon( HDC hdc, INT x, INT y, HICON hIcon )
1294 CURSORICONINFO *ptr;
1295 HDC hMemDC;
1296 HBITMAP hXorBits, hAndBits;
1297 COLORREF oldFg, oldBg;
1299 if (!(ptr = (CURSORICONINFO *)GlobalLock16( hIcon ))) return FALSE;
1300 if (!(hMemDC = CreateCompatibleDC( hdc ))) return FALSE;
1301 hAndBits = CreateBitmap( ptr->nWidth, ptr->nHeight, 1, 1,
1302 (char *)(ptr+1) );
1303 hXorBits = CreateBitmap( ptr->nWidth, ptr->nHeight, ptr->bPlanes,
1304 ptr->bBitsPerPixel, (char *)(ptr + 1)
1305 + ptr->nHeight * BITMAP_GetWidthBytes(ptr->nWidth,1) );
1306 oldFg = SetTextColor( hdc, RGB(0,0,0) );
1307 oldBg = SetBkColor( hdc, RGB(255,255,255) );
1309 if (hXorBits && hAndBits)
1311 HBITMAP hBitTemp = SelectObject( hMemDC, hAndBits );
1312 BitBlt( hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0, SRCAND );
1313 SelectObject( hMemDC, hXorBits );
1314 BitBlt(hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0,SRCINVERT);
1315 SelectObject( hMemDC, hBitTemp );
1317 DeleteDC( hMemDC );
1318 if (hXorBits) DeleteObject( hXorBits );
1319 if (hAndBits) DeleteObject( hAndBits );
1320 GlobalUnlock16( hIcon );
1321 SetTextColor( hdc, oldFg );
1322 SetBkColor( hdc, oldBg );
1323 return TRUE;
1327 /***********************************************************************
1328 * IconSize (USER.86)
1330 * See "Undocumented Windows". Used by W2.0 paint.exe.
1332 DWORD WINAPI IconSize16( void )
1334 return MAKELONG(GetSystemMetrics(SM_CYICON), GetSystemMetrics(SM_CXICON));
1338 /***********************************************************************
1339 * DumpIcon (USER.459)
1341 DWORD WINAPI DumpIcon16( SEGPTR pInfo, WORD *lpLen,
1342 SEGPTR *lpXorBits, SEGPTR *lpAndBits )
1344 CURSORICONINFO *info = MapSL( pInfo );
1345 int sizeAnd, sizeXor;
1347 if (!info) return 0;
1348 sizeXor = info->nHeight * info->nWidthBytes;
1349 sizeAnd = info->nHeight * BITMAP_GetWidthBytes( info->nWidth, 1 );
1350 if (lpAndBits) *lpAndBits = pInfo + sizeof(CURSORICONINFO);
1351 if (lpXorBits) *lpXorBits = pInfo + sizeof(CURSORICONINFO) + sizeAnd;
1352 if (lpLen) *lpLen = sizeof(CURSORICONINFO) + sizeAnd + sizeXor;
1353 return MAKELONG( sizeXor, sizeXor );
1357 /***********************************************************************
1358 * SetCursor (USER.69)
1360 HCURSOR16 WINAPI SetCursor16( HCURSOR16 hCursor )
1362 return (HCURSOR16)SetCursor( hCursor );
1366 /***********************************************************************
1367 * SetCursor (USER32.@)
1368 * RETURNS:
1369 * A handle to the previous cursor shape.
1371 HCURSOR WINAPI SetCursor(
1372 HCURSOR hCursor /* [in] Handle of cursor to show */
1374 HCURSOR hOldCursor;
1376 if (hCursor == hActiveCursor) return hActiveCursor; /* No change */
1377 TRACE_(cursor)("%04x\n", hCursor );
1378 hOldCursor = hActiveCursor;
1379 hActiveCursor = hCursor;
1380 /* Change the cursor shape only if it is visible */
1381 if (CURSOR_ShowCount >= 0)
1383 USER_Driver.pSetCursor( (CURSORICONINFO*)GlobalLock16( hActiveCursor ) );
1384 GlobalUnlock16( hActiveCursor );
1386 return hOldCursor;
1390 /***********************************************************************
1391 * ShowCursor (USER.71)
1393 INT16 WINAPI ShowCursor16( BOOL16 bShow )
1395 return ShowCursor( bShow );
1399 /***********************************************************************
1400 * ShowCursor (USER32.@)
1402 INT WINAPI ShowCursor( BOOL bShow )
1404 TRACE_(cursor)("%d, count=%d\n",
1405 bShow, CURSOR_ShowCount );
1407 if (bShow)
1409 if (++CURSOR_ShowCount == 0) /* Show it */
1411 USER_Driver.pSetCursor( (CURSORICONINFO*)GlobalLock16( hActiveCursor ) );
1412 GlobalUnlock16( hActiveCursor );
1415 else
1417 if (--CURSOR_ShowCount == -1) /* Hide it */
1418 USER_Driver.pSetCursor( NULL );
1420 return CURSOR_ShowCount;
1424 /***********************************************************************
1425 * GetCursor (USER.247)
1427 HCURSOR16 WINAPI GetCursor16(void)
1429 return hActiveCursor;
1433 /***********************************************************************
1434 * GetCursor (USER32.@)
1436 HCURSOR WINAPI GetCursor(void)
1438 return hActiveCursor;
1442 /***********************************************************************
1443 * ClipCursor (USER.16)
1445 BOOL16 WINAPI ClipCursor16( const RECT16 *rect )
1447 if (!rect) SetRectEmpty( &CURSOR_ClipRect );
1448 else CONV_RECT16TO32( rect, &CURSOR_ClipRect );
1449 return TRUE;
1453 /***********************************************************************
1454 * ClipCursor (USER32.@)
1456 BOOL WINAPI ClipCursor( const RECT *rect )
1458 if (!rect) SetRectEmpty( &CURSOR_ClipRect );
1459 else CopyRect( &CURSOR_ClipRect, rect );
1460 return TRUE;
1464 /***********************************************************************
1465 * GetClipCursor (USER.309)
1467 void WINAPI GetClipCursor16( RECT16 *rect )
1469 if (rect) CONV_RECT32TO16( &CURSOR_ClipRect, rect );
1473 /***********************************************************************
1474 * GetClipCursor (USER32.@)
1476 BOOL WINAPI GetClipCursor( RECT *rect )
1478 if (rect)
1480 CopyRect( rect, &CURSOR_ClipRect );
1481 return TRUE;
1483 return FALSE;
1486 /**********************************************************************
1487 * LookupIconIdFromDirectoryEx (USER.364)
1489 * FIXME: exact parameter sizes
1491 INT16 WINAPI LookupIconIdFromDirectoryEx16( LPBYTE xdir, BOOL16 bIcon,
1492 INT16 width, INT16 height, UINT16 cFlag )
1494 CURSORICONDIR *dir = (CURSORICONDIR*)xdir;
1495 UINT16 retVal = 0;
1496 if( dir && !dir->idReserved && (dir->idType & 3) )
1498 CURSORICONDIRENTRY* entry;
1499 HDC hdc;
1500 UINT palEnts;
1501 int colors;
1502 hdc = GetDC(0);
1503 palEnts = GetSystemPaletteEntries(hdc, 0, 0, NULL);
1504 if (palEnts == 0)
1505 palEnts = 256;
1506 colors = (cFlag & LR_MONOCHROME) ? 2 : palEnts;
1508 ReleaseDC(0, hdc);
1510 if( bIcon )
1511 entry = CURSORICON_FindBestIcon( dir, width, height, colors );
1512 else
1513 entry = CURSORICON_FindBestCursor( dir, width, height, 1);
1515 if( entry ) retVal = entry->wResId;
1517 else WARN_(cursor)("invalid resource directory\n");
1518 return retVal;
1521 /**********************************************************************
1522 * LookupIconIdFromDirectoryEx (USER32.@)
1524 INT WINAPI LookupIconIdFromDirectoryEx( LPBYTE dir, BOOL bIcon,
1525 INT width, INT height, UINT cFlag )
1527 return LookupIconIdFromDirectoryEx16( dir, bIcon, width, height, cFlag );
1530 /**********************************************************************
1531 * LookupIconIdFromDirectory (USER.?)
1533 INT16 WINAPI LookupIconIdFromDirectory16( LPBYTE dir, BOOL16 bIcon )
1535 return LookupIconIdFromDirectoryEx16( dir, bIcon,
1536 bIcon ? GetSystemMetrics(SM_CXICON) : GetSystemMetrics(SM_CXCURSOR),
1537 bIcon ? GetSystemMetrics(SM_CYICON) : GetSystemMetrics(SM_CYCURSOR), bIcon ? 0 : LR_MONOCHROME );
1540 /**********************************************************************
1541 * LookupIconIdFromDirectory (USER32.@)
1543 INT WINAPI LookupIconIdFromDirectory( LPBYTE dir, BOOL bIcon )
1545 return LookupIconIdFromDirectoryEx( dir, bIcon,
1546 bIcon ? GetSystemMetrics(SM_CXICON) : GetSystemMetrics(SM_CXCURSOR),
1547 bIcon ? GetSystemMetrics(SM_CYICON) : GetSystemMetrics(SM_CYCURSOR), bIcon ? 0 : LR_MONOCHROME );
1550 /**********************************************************************
1551 * GetIconID (USER.455)
1553 WORD WINAPI GetIconID16( HGLOBAL16 hResource, DWORD resType )
1555 LPBYTE lpDir = (LPBYTE)GlobalLock16(hResource);
1557 TRACE_(cursor)("hRes=%04x, entries=%i\n",
1558 hResource, lpDir ? ((CURSORICONDIR*)lpDir)->idCount : 0);
1560 switch(resType)
1562 case RT_CURSOR16:
1563 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, FALSE,
1564 GetSystemMetrics(SM_CXCURSOR), GetSystemMetrics(SM_CYCURSOR), LR_MONOCHROME );
1565 case RT_ICON16:
1566 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, TRUE,
1567 GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), 0 );
1568 default:
1569 WARN_(cursor)("invalid res type %ld\n", resType );
1571 return 0;
1574 /**********************************************************************
1575 * LoadCursorIconHandler (USER.336)
1577 * Supposed to load resources of Windows 2.x applications.
1579 HGLOBAL16 WINAPI LoadCursorIconHandler16( HGLOBAL16 hResource, HMODULE16 hModule, HRSRC16 hRsrc )
1581 FIXME_(cursor)("(%04x,%04x,%04x): old 2.x resources are not supported!\n",
1582 hResource, hModule, hRsrc);
1583 return (HGLOBAL16)0;
1586 /**********************************************************************
1587 * LoadDIBIconHandler (USER.357)
1589 * RT_ICON resource loader, installed by USER_SignalProc when module
1590 * is initialized.
1592 HGLOBAL16 WINAPI LoadDIBIconHandler16( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1594 /* If hResource is zero we must allocate a new memory block, if it's
1595 * non-zero but GlobalLock() returns NULL then it was discarded and
1596 * we have to recommit some memory, otherwise we just need to check
1597 * the block size. See LoadProc() in 16-bit SDK for more.
1600 hMemObj = NE_DefResourceHandler( hMemObj, hModule, hRsrc );
1601 if( hMemObj )
1603 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1604 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1605 SizeofResource16(hModule, hRsrc), TRUE, 0x00030000,
1606 GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), LR_DEFAULTCOLOR );
1608 return hMemObj;
1611 /**********************************************************************
1612 * LoadDIBCursorHandler (USER.356)
1614 * RT_CURSOR resource loader. Same as above.
1616 HGLOBAL16 WINAPI LoadDIBCursorHandler16( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1618 hMemObj = NE_DefResourceHandler( hMemObj, hModule, hRsrc );
1619 if( hMemObj )
1621 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1622 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1623 SizeofResource16(hModule, hRsrc), FALSE, 0x00030000,
1624 GetSystemMetrics(SM_CXCURSOR), GetSystemMetrics(SM_CYCURSOR), LR_MONOCHROME );
1626 return hMemObj;
1629 /**********************************************************************
1630 * LoadIconHandler (USER.456)
1632 HICON16 WINAPI LoadIconHandler16( HGLOBAL16 hResource, BOOL16 bNew )
1634 LPBYTE bits = (LPBYTE)LockResource16( hResource );
1636 TRACE_(cursor)("hRes=%04x\n",hResource);
1638 return CURSORICON_CreateFromResource( 0, 0, bits, 0, TRUE,
1639 bNew ? 0x00030000 : 0x00020000, 0, 0, LR_DEFAULTCOLOR );
1642 /***********************************************************************
1643 * LoadCursorW (USER32.@)
1645 HCURSOR WINAPI LoadCursorW(HINSTANCE hInstance, LPCWSTR name)
1647 return LoadImageW( hInstance, name, IMAGE_CURSOR, 0, 0,
1648 LR_SHARED | LR_DEFAULTSIZE );
1651 /***********************************************************************
1652 * LoadCursorA (USER32.@)
1654 HCURSOR WINAPI LoadCursorA(HINSTANCE hInstance, LPCSTR name)
1656 return LoadImageA( hInstance, name, IMAGE_CURSOR, 0, 0,
1657 LR_SHARED | LR_DEFAULTSIZE );
1660 /***********************************************************************
1661 * LoadCursorFromFileW (USER32.@)
1663 HCURSOR WINAPI LoadCursorFromFileW (LPCWSTR name)
1665 return LoadImageW( 0, name, IMAGE_CURSOR, 0, 0,
1666 LR_LOADFROMFILE | LR_DEFAULTSIZE );
1669 /***********************************************************************
1670 * LoadCursorFromFileA (USER32.@)
1672 HCURSOR WINAPI LoadCursorFromFileA (LPCSTR name)
1674 return LoadImageA( 0, name, IMAGE_CURSOR, 0, 0,
1675 LR_LOADFROMFILE | LR_DEFAULTSIZE );
1678 /***********************************************************************
1679 * LoadIconW (USER32.@)
1681 HICON WINAPI LoadIconW(HINSTANCE hInstance, LPCWSTR name)
1683 return LoadImageW( hInstance, name, IMAGE_ICON, 0, 0,
1684 LR_SHARED | LR_DEFAULTSIZE );
1687 /***********************************************************************
1688 * LoadIconA (USER32.@)
1690 HICON WINAPI LoadIconA(HINSTANCE hInstance, LPCSTR name)
1692 return LoadImageA( hInstance, name, IMAGE_ICON, 0, 0,
1693 LR_SHARED | LR_DEFAULTSIZE );
1696 /**********************************************************************
1697 * GetIconInfo (USER.395)
1699 BOOL16 WINAPI GetIconInfo16(HICON16 hIcon,LPICONINFO16 iconinfo)
1701 ICONINFO ii32;
1702 BOOL16 ret = GetIconInfo((HICON)hIcon, &ii32);
1704 iconinfo->fIcon = ii32.fIcon;
1705 iconinfo->xHotspot = ii32.xHotspot;
1706 iconinfo->yHotspot = ii32.yHotspot;
1707 iconinfo->hbmMask = ii32.hbmMask;
1708 iconinfo->hbmColor = ii32.hbmColor;
1709 return ret;
1712 /**********************************************************************
1713 * GetIconInfo (USER32.@)
1715 BOOL WINAPI GetIconInfo(HICON hIcon,PICONINFO iconinfo) {
1716 CURSORICONINFO *ciconinfo;
1718 ciconinfo = GlobalLock16(hIcon);
1719 if (!ciconinfo)
1720 return FALSE;
1722 if ( (ciconinfo->ptHotSpot.x == ICON_HOTSPOT) &&
1723 (ciconinfo->ptHotSpot.y == ICON_HOTSPOT) )
1725 iconinfo->fIcon = TRUE;
1726 iconinfo->xHotspot = ciconinfo->nWidth / 2;
1727 iconinfo->yHotspot = ciconinfo->nHeight / 2;
1729 else
1731 iconinfo->fIcon = FALSE;
1732 iconinfo->xHotspot = ciconinfo->ptHotSpot.x;
1733 iconinfo->yHotspot = ciconinfo->ptHotSpot.y;
1736 iconinfo->hbmColor = CreateBitmap ( ciconinfo->nWidth, ciconinfo->nHeight,
1737 ciconinfo->bPlanes, ciconinfo->bBitsPerPixel,
1738 (char *)(ciconinfo + 1)
1739 + ciconinfo->nHeight *
1740 BITMAP_GetWidthBytes (ciconinfo->nWidth,1) );
1741 iconinfo->hbmMask = CreateBitmap ( ciconinfo->nWidth, ciconinfo->nHeight,
1742 1, 1, (char *)(ciconinfo + 1));
1744 GlobalUnlock16(hIcon);
1746 return TRUE;
1749 /**********************************************************************
1750 * CreateIconIndirect (USER32.@)
1752 HICON WINAPI CreateIconIndirect(PICONINFO iconinfo)
1754 BITMAP bmpXor,bmpAnd;
1755 HICON hObj;
1756 int sizeXor,sizeAnd;
1758 GetObjectA( iconinfo->hbmColor, sizeof(bmpXor), &bmpXor );
1759 GetObjectA( iconinfo->hbmMask, sizeof(bmpAnd), &bmpAnd );
1761 sizeXor = bmpXor.bmHeight * bmpXor.bmWidthBytes;
1762 sizeAnd = bmpAnd.bmHeight * bmpAnd.bmWidthBytes;
1764 hObj = GlobalAlloc16( GMEM_MOVEABLE,
1765 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
1766 if (hObj)
1768 CURSORICONINFO *info;
1770 info = (CURSORICONINFO *)GlobalLock16( hObj );
1772 /* If we are creating an icon, the hotspot is unused */
1773 if (iconinfo->fIcon)
1775 info->ptHotSpot.x = ICON_HOTSPOT;
1776 info->ptHotSpot.y = ICON_HOTSPOT;
1778 else
1780 info->ptHotSpot.x = iconinfo->xHotspot;
1781 info->ptHotSpot.y = iconinfo->yHotspot;
1784 info->nWidth = bmpXor.bmWidth;
1785 info->nHeight = bmpXor.bmHeight;
1786 info->nWidthBytes = bmpXor.bmWidthBytes;
1787 info->bPlanes = bmpXor.bmPlanes;
1788 info->bBitsPerPixel = bmpXor.bmBitsPixel;
1790 /* Transfer the bitmap bits to the CURSORICONINFO structure */
1792 GetBitmapBits( iconinfo->hbmMask ,sizeAnd,(char*)(info + 1) );
1793 GetBitmapBits( iconinfo->hbmColor,sizeXor,(char*)(info + 1) +sizeAnd);
1794 GlobalUnlock16( hObj );
1796 return hObj;
1800 /**********************************************************************
1801 * DrawIconEx (USER.394)
1803 BOOL16 WINAPI DrawIconEx16 (HDC16 hdc, INT16 xLeft, INT16 yTop, HICON16 hIcon,
1804 INT16 cxWidth, INT16 cyWidth, UINT16 istep,
1805 HBRUSH16 hbr, UINT16 flags)
1807 return DrawIconEx(hdc, xLeft, yTop, hIcon, cxWidth, cyWidth,
1808 istep, hbr, flags);
1812 /******************************************************************************
1813 * DrawIconEx (USER32.@) Draws an icon or cursor on device context
1815 * NOTES
1816 * Why is this using SM_CXICON instead of SM_CXCURSOR?
1818 * PARAMS
1819 * hdc [I] Handle to device context
1820 * x0 [I] X coordinate of upper left corner
1821 * y0 [I] Y coordinate of upper left corner
1822 * hIcon [I] Handle to icon to draw
1823 * cxWidth [I] Width of icon
1824 * cyWidth [I] Height of icon
1825 * istep [I] Index of frame in animated cursor
1826 * hbr [I] Handle to background brush
1827 * flags [I] Icon-drawing flags
1829 * RETURNS
1830 * Success: TRUE
1831 * Failure: FALSE
1833 BOOL WINAPI DrawIconEx( HDC hdc, INT x0, INT y0, HICON hIcon,
1834 INT cxWidth, INT cyWidth, UINT istep,
1835 HBRUSH hbr, UINT flags )
1837 CURSORICONINFO *ptr = (CURSORICONINFO *)GlobalLock16 (hIcon);
1838 HDC hDC_off = 0, hMemDC = CreateCompatibleDC (hdc);
1839 BOOL result = FALSE, DoOffscreen;
1840 HBITMAP hB_off = 0, hOld = 0;
1842 if (!ptr) return FALSE;
1843 TRACE_(icon)("(hdc=%x,pos=%d.%d,hicon=%x,extend=%d.%d,istep=%d,br=%x,flags=0x%08x)\n",
1844 hdc,x0,y0,hIcon,cxWidth,cyWidth,istep,hbr,flags
1847 if (istep)
1848 FIXME_(icon)("Ignoring istep=%d\n", istep);
1849 if (flags & DI_COMPAT)
1850 FIXME_(icon)("Ignoring flag DI_COMPAT\n");
1852 if (!flags) {
1853 FIXME_(icon)("no flags set? setting to DI_NORMAL\n");
1854 flags = DI_NORMAL;
1857 /* Calculate the size of the destination image. */
1858 if (cxWidth == 0)
1860 if (flags & DI_DEFAULTSIZE)
1861 cxWidth = GetSystemMetrics (SM_CXICON);
1862 else
1863 cxWidth = ptr->nWidth;
1865 if (cyWidth == 0)
1867 if (flags & DI_DEFAULTSIZE)
1868 cyWidth = GetSystemMetrics (SM_CYICON);
1869 else
1870 cyWidth = ptr->nHeight;
1873 DoOffscreen = (GetObjectType( hbr ) == OBJ_BRUSH);
1875 if (DoOffscreen) {
1876 RECT r;
1878 r.left = 0;
1879 r.top = 0;
1880 r.right = cxWidth;
1881 r.bottom = cxWidth;
1883 hDC_off = CreateCompatibleDC(hdc);
1884 hB_off = CreateCompatibleBitmap(hdc, cxWidth, cyWidth);
1885 if (hDC_off && hB_off) {
1886 hOld = SelectObject(hDC_off, hB_off);
1887 FillRect(hDC_off, &r, hbr);
1891 if (hMemDC && (!DoOffscreen || (hDC_off && hB_off)))
1893 HBITMAP hXorBits, hAndBits;
1894 COLORREF oldFg, oldBg;
1895 INT nStretchMode;
1897 nStretchMode = SetStretchBltMode (hdc, STRETCH_DELETESCANS);
1899 hXorBits = CreateBitmap ( ptr->nWidth, ptr->nHeight,
1900 ptr->bPlanes, ptr->bBitsPerPixel,
1901 (char *)(ptr + 1)
1902 + ptr->nHeight *
1903 BITMAP_GetWidthBytes(ptr->nWidth,1) );
1904 hAndBits = CreateBitmap ( ptr->nWidth, ptr->nHeight,
1905 1, 1, (char *)(ptr+1) );
1906 oldFg = SetTextColor( hdc, RGB(0,0,0) );
1907 oldBg = SetBkColor( hdc, RGB(255,255,255) );
1909 if (hXorBits && hAndBits)
1911 HBITMAP hBitTemp = SelectObject( hMemDC, hAndBits );
1912 if (flags & DI_MASK)
1914 if (DoOffscreen)
1915 StretchBlt (hDC_off, 0, 0, cxWidth, cyWidth,
1916 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
1917 else
1918 StretchBlt (hdc, x0, y0, cxWidth, cyWidth,
1919 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
1921 SelectObject( hMemDC, hXorBits );
1922 if (flags & DI_IMAGE)
1924 if (DoOffscreen)
1925 StretchBlt (hDC_off, 0, 0, cxWidth, cyWidth,
1926 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
1927 else
1928 StretchBlt (hdc, x0, y0, cxWidth, cyWidth,
1929 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
1931 SelectObject( hMemDC, hBitTemp );
1932 result = TRUE;
1935 SetTextColor( hdc, oldFg );
1936 SetBkColor( hdc, oldBg );
1937 if (hXorBits) DeleteObject( hXorBits );
1938 if (hAndBits) DeleteObject( hAndBits );
1939 SetStretchBltMode (hdc, nStretchMode);
1940 if (DoOffscreen) {
1941 BitBlt(hdc, x0, y0, cxWidth, cyWidth, hDC_off, 0, 0, SRCCOPY);
1942 SelectObject(hDC_off, hOld);
1945 if (hMemDC) DeleteDC( hMemDC );
1946 if (hDC_off) DeleteDC(hDC_off);
1947 if (hB_off) DeleteObject(hB_off);
1948 GlobalUnlock16( hIcon );
1949 return result;
1952 /***********************************************************************
1953 * DIB_FixColorsToLoadflags
1955 * Change color table entries when LR_LOADTRANSPARENT or LR_LOADMAP3DCOLORS
1956 * are in loadflags
1958 static void DIB_FixColorsToLoadflags(BITMAPINFO * bmi, UINT loadflags, BYTE pix)
1960 int colors;
1961 COLORREF c_W, c_S, c_F, c_L, c_C;
1962 int incr,i;
1963 RGBQUAD *ptr;
1965 if (bmi->bmiHeader.biBitCount > 8) return;
1966 if (bmi->bmiHeader.biSize == sizeof(BITMAPINFOHEADER)) incr = 4;
1967 else if (bmi->bmiHeader.biSize == sizeof(BITMAPCOREHEADER)) incr = 3;
1968 else {
1969 WARN_(resource)("Wrong bitmap header size!\n");
1970 return;
1972 colors = bmi->bmiHeader.biClrUsed;
1973 if (!colors && (bmi->bmiHeader.biBitCount <= 8))
1974 colors = 1 << bmi->bmiHeader.biBitCount;
1975 c_W = GetSysColor(COLOR_WINDOW);
1976 c_S = GetSysColor(COLOR_3DSHADOW);
1977 c_F = GetSysColor(COLOR_3DFACE);
1978 c_L = GetSysColor(COLOR_3DLIGHT);
1979 if (loadflags & LR_LOADTRANSPARENT) {
1980 switch (bmi->bmiHeader.biBitCount) {
1981 case 1: pix = pix >> 7; break;
1982 case 4: pix = pix >> 4; break;
1983 case 8: break;
1984 default:
1985 WARN_(resource)("(%d): Unsupported depth\n", bmi->bmiHeader.biBitCount);
1986 return;
1988 if (pix >= colors) {
1989 WARN_(resource)("pixel has color index greater than biClrUsed!\n");
1990 return;
1992 if (loadflags & LR_LOADMAP3DCOLORS) c_W = c_F;
1993 ptr = (RGBQUAD*)((char*)bmi->bmiColors+pix*incr);
1994 ptr->rgbBlue = GetBValue(c_W);
1995 ptr->rgbGreen = GetGValue(c_W);
1996 ptr->rgbRed = GetRValue(c_W);
1998 if (loadflags & LR_LOADMAP3DCOLORS)
1999 for (i=0; i<colors; i++) {
2000 ptr = (RGBQUAD*)((char*)bmi->bmiColors+i*incr);
2001 c_C = RGB(ptr->rgbRed, ptr->rgbGreen, ptr->rgbBlue);
2002 if (c_C == RGB(128, 128, 128)) {
2003 ptr->rgbRed = GetRValue(c_S);
2004 ptr->rgbGreen = GetGValue(c_S);
2005 ptr->rgbBlue = GetBValue(c_S);
2006 } else if (c_C == RGB(192, 192, 192)) {
2007 ptr->rgbRed = GetRValue(c_F);
2008 ptr->rgbGreen = GetGValue(c_F);
2009 ptr->rgbBlue = GetBValue(c_F);
2010 } else if (c_C == RGB(223, 223, 223)) {
2011 ptr->rgbRed = GetRValue(c_L);
2012 ptr->rgbGreen = GetGValue(c_L);
2013 ptr->rgbBlue = GetBValue(c_L);
2019 /**********************************************************************
2020 * BITMAP_Load
2022 static HBITMAP BITMAP_Load( HINSTANCE instance,LPCWSTR name, UINT loadflags )
2024 HBITMAP hbitmap = 0;
2025 HRSRC hRsrc;
2026 HGLOBAL handle;
2027 char *ptr = NULL;
2028 BITMAPINFO *info, *fix_info=NULL;
2029 HGLOBAL hFix;
2030 int size;
2032 if (!(loadflags & LR_LOADFROMFILE))
2034 if (!instance)
2036 /* OEM bitmap: try to load the resource from user32.dll */
2037 if (HIWORD(name)) return 0;
2038 if (!(instance = GetModuleHandleA("user32.dll"))) return 0;
2040 if (!(hRsrc = FindResourceW( instance, name, RT_BITMAPW ))) return 0;
2041 if (!(handle = LoadResource( instance, hRsrc ))) return 0;
2043 if ((info = (BITMAPINFO *)LockResource( handle )) == NULL) return 0;
2045 else
2047 if (!(ptr = map_fileW( name ))) return 0;
2048 info = (BITMAPINFO *)(ptr + sizeof(BITMAPFILEHEADER));
2050 size = DIB_BitmapInfoSize(info, DIB_RGB_COLORS);
2051 if ((hFix = GlobalAlloc(0, size))) fix_info=GlobalLock(hFix);
2052 if (fix_info) {
2053 BYTE pix;
2055 memcpy(fix_info, info, size);
2056 pix = *((LPBYTE)info+DIB_BitmapInfoSize(info, DIB_RGB_COLORS));
2057 DIB_FixColorsToLoadflags(fix_info, loadflags, pix);
2058 if (!screen_dc) screen_dc = CreateDCA( "DISPLAY", NULL, NULL, NULL );
2059 if (screen_dc)
2061 char *bits = (char *)info + size;
2062 if (loadflags & LR_CREATEDIBSECTION) {
2063 DIBSECTION dib;
2064 hbitmap = CreateDIBSection(screen_dc, fix_info, DIB_RGB_COLORS, NULL, 0, 0);
2065 GetObjectA(hbitmap, sizeof(DIBSECTION), &dib);
2066 SetDIBits(screen_dc, hbitmap, 0, dib.dsBm.bmHeight, bits, info,
2067 DIB_RGB_COLORS);
2069 else {
2070 hbitmap = CreateDIBitmap( screen_dc, &fix_info->bmiHeader, CBM_INIT,
2071 bits, fix_info, DIB_RGB_COLORS );
2074 GlobalUnlock(hFix);
2075 GlobalFree(hFix);
2077 if (loadflags & LR_LOADFROMFILE) UnmapViewOfFile( ptr );
2078 return hbitmap;
2082 /***********************************************************************
2083 * LoadImage (USER.389)
2086 HANDLE16 WINAPI LoadImage16( HINSTANCE16 hinst, LPCSTR name, UINT16 type,
2087 INT16 desiredx, INT16 desiredy, UINT16 loadflags)
2089 return LoadImageA( hinst, name, type, desiredx, desiredy, loadflags );
2092 /**********************************************************************
2093 * LoadImageA (USER32.@)
2095 * FIXME: implementation lacks some features, see LR_ defines in winuser.h
2098 /* filter for page-fault exceptions */
2099 static WINE_EXCEPTION_FILTER(page_fault)
2101 if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION)
2102 return EXCEPTION_EXECUTE_HANDLER;
2103 return EXCEPTION_CONTINUE_SEARCH;
2106 /*********************************************************************/
2108 HANDLE WINAPI LoadImageA( HINSTANCE hinst, LPCSTR name, UINT type,
2109 INT desiredx, INT desiredy, UINT loadflags)
2111 HANDLE res;
2112 LPWSTR u_name;
2114 if (!HIWORD(name))
2115 return LoadImageW(hinst, (LPWSTR)name, type, desiredx, desiredy, loadflags);
2117 __TRY {
2118 DWORD len = MultiByteToWideChar( CP_ACP, 0, name, -1, NULL, 0 );
2119 u_name = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
2120 MultiByteToWideChar( CP_ACP, 0, name, -1, u_name, len );
2122 __EXCEPT(page_fault) {
2123 SetLastError( ERROR_INVALID_PARAMETER );
2124 return 0;
2126 __ENDTRY
2127 res = LoadImageW(hinst, u_name, type, desiredx, desiredy, loadflags);
2128 HeapFree(GetProcessHeap(), 0, u_name);
2129 return res;
2133 /******************************************************************************
2134 * LoadImageW (USER32.@) Loads an icon, cursor, or bitmap
2136 * PARAMS
2137 * hinst [I] Handle of instance that contains image
2138 * name [I] Name of image
2139 * type [I] Type of image
2140 * desiredx [I] Desired width
2141 * desiredy [I] Desired height
2142 * loadflags [I] Load flags
2144 * RETURNS
2145 * Success: Handle to newly loaded image
2146 * Failure: NULL
2148 * FIXME: Implementation lacks some features, see LR_ defines in winuser.h
2150 HANDLE WINAPI LoadImageW( HINSTANCE hinst, LPCWSTR name, UINT type,
2151 INT desiredx, INT desiredy, UINT loadflags )
2153 if (HIWORD(name)) {
2154 TRACE_(resource)("(0x%04x,%p,%d,%d,%d,0x%08x)\n",
2155 hinst,name,type,desiredx,desiredy,loadflags);
2156 } else {
2157 TRACE_(resource)("(0x%04x,%p,%d,%d,%d,0x%08x)\n",
2158 hinst,name,type,desiredx,desiredy,loadflags);
2160 if (loadflags & LR_DEFAULTSIZE) {
2161 if (type == IMAGE_ICON) {
2162 if (!desiredx) desiredx = GetSystemMetrics(SM_CXICON);
2163 if (!desiredy) desiredy = GetSystemMetrics(SM_CYICON);
2164 } else if (type == IMAGE_CURSOR) {
2165 if (!desiredx) desiredx = GetSystemMetrics(SM_CXCURSOR);
2166 if (!desiredy) desiredy = GetSystemMetrics(SM_CYCURSOR);
2169 if (loadflags & LR_LOADFROMFILE) loadflags &= ~LR_SHARED;
2170 switch (type) {
2171 case IMAGE_BITMAP:
2172 return BITMAP_Load( hinst, name, loadflags );
2174 case IMAGE_ICON:
2175 if (!screen_dc) screen_dc = CreateDCA( "DISPLAY", NULL, NULL, NULL );
2176 if (screen_dc)
2178 UINT palEnts = GetSystemPaletteEntries(screen_dc, 0, 0, NULL);
2179 if (palEnts == 0) palEnts = 256;
2180 return CURSORICON_Load(hinst, name, desiredx, desiredy,
2181 palEnts, FALSE, loadflags);
2183 break;
2185 case IMAGE_CURSOR:
2186 return CURSORICON_Load(hinst, name, desiredx, desiredy,
2187 1, TRUE, loadflags);
2189 return 0;
2193 /******************************************************************************
2194 * CopyImage (USER.390) Creates new image and copies attributes to it
2197 HICON16 WINAPI CopyImage16( HANDLE16 hnd, UINT16 type, INT16 desiredx,
2198 INT16 desiredy, UINT16 flags )
2200 return (HICON16)CopyImage((HANDLE)hnd, (UINT)type, (INT)desiredx,
2201 (INT)desiredy, (UINT)flags);
2204 /******************************************************************************
2205 * CopyImage (USER32.@) Creates new image and copies attributes to it
2207 * PARAMS
2208 * hnd [I] Handle to image to copy
2209 * type [I] Type of image to copy
2210 * desiredx [I] Desired width of new image
2211 * desiredy [I] Desired height of new image
2212 * flags [I] Copy flags
2214 * RETURNS
2215 * Success: Handle to newly created image
2216 * Failure: NULL
2218 * FIXME: implementation still lacks nearly all features, see LR_*
2219 * defines in winuser.h
2221 HICON WINAPI CopyImage( HANDLE hnd, UINT type, INT desiredx,
2222 INT desiredy, UINT flags )
2224 switch (type)
2226 case IMAGE_BITMAP:
2227 return BITMAP_CopyBitmap(hnd);
2228 case IMAGE_ICON:
2229 return CURSORICON_ExtCopy(hnd,type, desiredx, desiredy, flags);
2230 case IMAGE_CURSOR:
2231 /* Should call CURSORICON_ExtCopy but more testing
2232 * needs to be done before we change this
2234 return CopyCursor(hnd);
2236 return 0;
2240 /******************************************************************************
2241 * LoadBitmapW (USER32.@) Loads bitmap from the executable file
2243 * RETURNS
2244 * Success: Handle to specified bitmap
2245 * Failure: NULL
2247 HBITMAP WINAPI LoadBitmapW(
2248 HINSTANCE instance, /* [in] Handle to application instance */
2249 LPCWSTR name) /* [in] Address of bitmap resource name */
2251 return LoadImageW( instance, name, IMAGE_BITMAP, 0, 0, 0 );
2254 /**********************************************************************
2255 * LoadBitmapA (USER32.@)
2257 HBITMAP WINAPI LoadBitmapA( HINSTANCE instance, LPCSTR name )
2259 return LoadImageA( instance, name, IMAGE_BITMAP, 0, 0, 0 );
2262 /**********************************************************************
2263 * LoadBitmap (USER.175)
2265 HBITMAP16 WINAPI LoadBitmap16( HINSTANCE16 instance, LPCSTR name )
2267 return LoadBitmapA( instance, name );