Documentation ordinal fixes.
[wine.git] / windows / cursoricon.c
blob47fa677cf6cf83a9b344812adee46485822cbd31
1 /*
2 * Cursor and icon support
4 * Copyright 1995 Alexandre Julliard
5 * 1996 Martin Von Loewis
6 * 1997 Alex Korobka
7 * 1998 Turchanov Sergey
8 */
11 * Theory:
13 * http://www.microsoft.com/win32dev/ui/icons.htm
15 * Cursors and icons are stored in a global heap block, with the
16 * following layout:
18 * CURSORICONINFO info;
19 * BYTE[] ANDbits;
20 * BYTE[] XORbits;
22 * The bits structures are in the format of a device-dependent bitmap.
24 * This layout is very sub-optimal, as the bitmap bits are stored in
25 * the X client instead of in the server like other bitmaps; however,
26 * some programs (notably Paint Brush) expect to be able to manipulate
27 * the bits directly :-(
29 * FIXME: what are we going to do with animation and color (bpp > 1) cursors ?!
32 #include <string.h>
33 #include <stdlib.h>
35 #include "windef.h"
36 #include "wingdi.h"
37 #include "wine/winbase16.h"
38 #include "wine/winuser16.h"
39 #include "heap.h"
40 #include "palette.h"
41 #include "bitmap.h"
42 #include "cursoricon.h"
43 #include "module.h"
44 #include "debugtools.h"
45 #include "user.h"
46 #include "input.h"
47 #include "message.h"
48 #include "winerror.h"
50 DECLARE_DEBUG_CHANNEL(cursor);
51 DECLARE_DEBUG_CHANNEL(icon);
52 DECLARE_DEBUG_CHANNEL(resource);
54 static HCURSOR hActiveCursor = 0; /* Active cursor */
55 static INT CURSOR_ShowCount = 0; /* Cursor display count */
56 static RECT CURSOR_ClipRect; /* Cursor clipping rect */
58 static HDC screen_dc;
60 /**********************************************************************
61 * ICONCACHE for cursors/icons loaded with LR_SHARED.
63 * FIXME: This should not be allocated on the system heap, but on a
64 * subsystem-global heap (i.e. one for all Win16 processes,
65 * and one each for every Win32 process).
67 typedef struct tagICONCACHE
69 struct tagICONCACHE *next;
71 HMODULE hModule;
72 HRSRC hRsrc;
73 HRSRC hGroupRsrc;
74 HANDLE handle;
76 INT count;
78 } ICONCACHE;
80 static ICONCACHE *IconAnchor = NULL;
81 static CRITICAL_SECTION IconCrst = CRITICAL_SECTION_INIT;
82 static WORD ICON_HOTSPOT = 0x4242;
85 /***********************************************************************
86 * map_fileW
88 * Helper function to map a file to memory:
89 * name - file name
90 * [RETURN] ptr - pointer to mapped file
92 static void *map_fileW( LPCWSTR name )
94 HANDLE hFile, hMapping;
95 LPVOID ptr = NULL;
97 hFile = CreateFileW( name, GENERIC_READ, FILE_SHARE_READ, NULL,
98 OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, 0 );
99 if (hFile != INVALID_HANDLE_VALUE)
101 hMapping = CreateFileMappingA( hFile, NULL, PAGE_READONLY, 0, 0, NULL );
102 CloseHandle( hFile );
103 if (hMapping)
105 ptr = MapViewOfFile( hMapping, FILE_MAP_READ, 0, 0, 0 );
106 CloseHandle( hMapping );
109 return ptr;
113 /**********************************************************************
114 * CURSORICON_FindSharedIcon
116 static HANDLE CURSORICON_FindSharedIcon( HMODULE hModule, HRSRC hRsrc )
118 HANDLE handle = 0;
119 ICONCACHE *ptr;
121 EnterCriticalSection( &IconCrst );
123 for ( ptr = IconAnchor; ptr; ptr = ptr->next )
124 if ( ptr->hModule == hModule && ptr->hRsrc == hRsrc )
126 ptr->count++;
127 handle = ptr->handle;
128 break;
131 LeaveCriticalSection( &IconCrst );
133 return handle;
136 /*************************************************************************
137 * CURSORICON_FindCache
139 * Given a handle, find the corresponding cache element
141 * PARAMS
142 * Handle [I] handle to an Image
144 * RETURNS
145 * Success: The cache entry
146 * Failure: NULL
149 static ICONCACHE* CURSORICON_FindCache(HANDLE handle)
151 ICONCACHE *ptr;
152 ICONCACHE *pRet=NULL;
153 BOOL IsFound = FALSE;
154 int count;
156 EnterCriticalSection( &IconCrst );
158 for (count = 0, ptr = IconAnchor; ptr != NULL && !IsFound; ptr = ptr->next, count++ )
160 if ( handle == ptr->handle )
162 IsFound = TRUE;
163 pRet = ptr;
167 LeaveCriticalSection( &IconCrst );
169 return pRet;
172 /**********************************************************************
173 * CURSORICON_AddSharedIcon
175 static void CURSORICON_AddSharedIcon( HMODULE hModule, HRSRC hRsrc, HRSRC hGroupRsrc, HANDLE handle )
177 ICONCACHE *ptr = HeapAlloc( SystemHeap, 0, sizeof(ICONCACHE) );
178 if ( !ptr ) return;
180 ptr->hModule = hModule;
181 ptr->hRsrc = hRsrc;
182 ptr->handle = handle;
183 ptr->hGroupRsrc = hGroupRsrc;
184 ptr->count = 1;
186 EnterCriticalSection( &IconCrst );
187 ptr->next = IconAnchor;
188 IconAnchor = ptr;
189 LeaveCriticalSection( &IconCrst );
192 /**********************************************************************
193 * CURSORICON_DelSharedIcon
195 static INT CURSORICON_DelSharedIcon( HANDLE handle )
197 INT count = -1;
198 ICONCACHE *ptr;
200 EnterCriticalSection( &IconCrst );
202 for ( ptr = IconAnchor; ptr; ptr = ptr->next )
203 if ( ptr->handle == handle )
205 if ( ptr->count > 0 ) ptr->count--;
206 count = ptr->count;
207 break;
210 LeaveCriticalSection( &IconCrst );
212 return count;
215 /**********************************************************************
216 * CURSORICON_FreeModuleIcons
218 void CURSORICON_FreeModuleIcons( HMODULE hModule )
220 ICONCACHE **ptr = &IconAnchor;
222 if ( HIWORD( hModule ) )
223 hModule = MapHModuleLS( hModule );
224 else
225 hModule = GetExePtr( hModule );
227 EnterCriticalSection( &IconCrst );
229 while ( *ptr )
231 if ( (*ptr)->hModule == hModule )
233 ICONCACHE *freePtr = *ptr;
234 *ptr = freePtr->next;
236 GlobalFree16( freePtr->handle );
237 HeapFree( SystemHeap, 0, freePtr );
238 continue;
240 ptr = &(*ptr)->next;
243 LeaveCriticalSection( &IconCrst );
246 /**********************************************************************
247 * CURSORICON_FindBestIcon
249 * Find the icon closest to the requested size and number of colors.
251 static CURSORICONDIRENTRY *CURSORICON_FindBestIcon( CURSORICONDIR *dir, int width,
252 int height, int colors )
254 int i;
255 CURSORICONDIRENTRY *entry, *bestEntry = NULL;
256 UINT iTotalDiff, iXDiff=0, iYDiff=0, iColorDiff;
257 UINT iTempXDiff, iTempYDiff, iTempColorDiff;
259 if (dir->idCount < 1)
261 WARN_(icon)("Empty directory!\n" );
262 return NULL;
264 if (dir->idCount == 1) return &dir->idEntries[0]; /* No choice... */
266 /* Find Best Fit */
267 iTotalDiff = 0xFFFFFFFF;
268 iColorDiff = 0xFFFFFFFF;
269 for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
271 iTempXDiff = abs(width - entry->ResInfo.icon.bWidth);
272 iTempYDiff = abs(height - entry->ResInfo.icon.bHeight);
274 if(iTotalDiff > (iTempXDiff + iTempYDiff))
276 iXDiff = iTempXDiff;
277 iYDiff = iTempYDiff;
278 iTotalDiff = iXDiff + iYDiff;
282 /* Find Best Colors for Best Fit */
283 for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
285 if(abs(width - entry->ResInfo.icon.bWidth) == iXDiff &&
286 abs(height - entry->ResInfo.icon.bHeight) == iYDiff)
288 iTempColorDiff = abs(colors - entry->ResInfo.icon.bColorCount);
289 if(iColorDiff > iTempColorDiff)
291 bestEntry = entry;
292 iColorDiff = iTempColorDiff;
297 return bestEntry;
301 /**********************************************************************
302 * CURSORICON_FindBestCursor
304 * Find the cursor closest to the requested size.
305 * FIXME: parameter 'color' ignored and entries with more than 1 bpp
306 * ignored too
308 static CURSORICONDIRENTRY *CURSORICON_FindBestCursor( CURSORICONDIR *dir,
309 int width, int height, int color)
311 int i, maxwidth, maxheight;
312 CURSORICONDIRENTRY *entry, *bestEntry = NULL;
314 if (dir->idCount < 1)
316 WARN_(cursor)("Empty directory!\n" );
317 return NULL;
319 if (dir->idCount == 1) return &dir->idEntries[0]; /* No choice... */
321 /* Double height to account for AND and XOR masks */
323 height *= 2;
325 /* First find the largest one smaller than or equal to the requested size*/
327 maxwidth = maxheight = 0;
328 for(i = 0,entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
329 if ((entry->ResInfo.cursor.wWidth <= width) && (entry->ResInfo.cursor.wHeight <= height) &&
330 (entry->ResInfo.cursor.wWidth > maxwidth) && (entry->ResInfo.cursor.wHeight > maxheight) &&
331 (entry->wBitCount == 1))
333 bestEntry = entry;
334 maxwidth = entry->ResInfo.cursor.wWidth;
335 maxheight = entry->ResInfo.cursor.wHeight;
337 if (bestEntry) return bestEntry;
339 /* Now find the smallest one larger than the requested size */
341 maxwidth = maxheight = 255;
342 for(i = 0,entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
343 if ((entry->ResInfo.cursor.wWidth < maxwidth) && (entry->ResInfo.cursor.wHeight < maxheight) &&
344 (entry->wBitCount == 1))
346 bestEntry = entry;
347 maxwidth = entry->ResInfo.cursor.wWidth;
348 maxheight = entry->ResInfo.cursor.wHeight;
351 return bestEntry;
354 /*********************************************************************
355 * The main purpose of this function is to create fake resource directory
356 * and fake resource entries. There are several reasons for this:
357 * - CURSORICONDIR and CURSORICONFILEDIR differ in sizes and their
358 * fields
359 * There are some "bad" cursor files which do not have
360 * bColorCount initialized but instead one must read this info
361 * directly from corresponding DIB sections
362 * Note: wResId is index to array of pointer returned in ptrs (origin is 1)
364 BOOL CURSORICON_SimulateLoadingFromResourceW( LPWSTR filename, BOOL fCursor,
365 CURSORICONDIR **res, LPBYTE **ptr)
367 LPBYTE _free;
368 CURSORICONFILEDIR *bits;
369 int entries, size, i;
371 *res = NULL;
372 *ptr = NULL;
373 if (!(bits = map_fileW( filename ))) return FALSE;
375 /* FIXME: test for inimated icons
376 * hack to load the first icon from the *.ani file
378 if ( *(LPDWORD)bits==0x46464952 ) /* "RIFF" */
379 { LPBYTE pos = (LPBYTE) bits;
380 FIXME_(cursor)("Animated icons not correctly implemented! %p \n", bits);
382 for (;;)
383 { if (*(LPDWORD)pos==0x6e6f6369) /* "icon" */
384 { FIXME_(cursor)("icon entry found! %p\n", bits);
385 pos+=4;
386 if ( !*(LPWORD) pos==0x2fe) /* iconsize */
387 { goto fail;
389 bits=(CURSORICONFILEDIR*)(pos+4);
390 FIXME_(cursor)("icon size ok. offset=%p \n", bits);
391 break;
393 pos+=2;
394 if (pos>=(LPBYTE)bits+766) goto fail;
397 if (!(entries = bits->idCount)) goto fail;
398 size = sizeof(CURSORICONDIR) + sizeof(CURSORICONDIRENTRY) * (entries - 1);
399 _free = (LPBYTE) size;
401 for (i=0; i < entries; i++)
402 size += bits->idEntries[i].dwDIBSize + (fCursor ? sizeof(POINT16): 0);
404 if (!(*ptr = HeapAlloc( GetProcessHeap(), 0,
405 entries * sizeof (CURSORICONDIRENTRY*)))) goto fail;
406 if (!(*res = HeapAlloc( GetProcessHeap(), 0, size))) goto fail;
408 _free = (LPBYTE)(*res) + (int)_free;
409 memcpy((*res), bits, 6);
410 for (i=0; i<entries; i++)
412 ((LPBYTE*)(*ptr))[i] = _free;
413 if (fCursor) {
414 (*res)->idEntries[i].ResInfo.cursor.wWidth=bits->idEntries[i].bWidth;
415 (*res)->idEntries[i].ResInfo.cursor.wHeight=bits->idEntries[i].bHeight;
416 ((LPPOINT16)_free)->x=bits->idEntries[i].xHotspot;
417 ((LPPOINT16)_free)->y=bits->idEntries[i].yHotspot;
418 _free+=sizeof(POINT16);
419 } else {
420 (*res)->idEntries[i].ResInfo.icon.bWidth=bits->idEntries[i].bWidth;
421 (*res)->idEntries[i].ResInfo.icon.bHeight=bits->idEntries[i].bHeight;
422 (*res)->idEntries[i].ResInfo.icon.bColorCount = bits->idEntries[i].bColorCount;
424 (*res)->idEntries[i].wPlanes=1;
425 (*res)->idEntries[i].wBitCount = ((LPBITMAPINFOHEADER)((LPBYTE)bits +
426 bits->idEntries[i].dwDIBOffset))->biBitCount;
427 (*res)->idEntries[i].dwBytesInRes = bits->idEntries[i].dwDIBSize;
428 (*res)->idEntries[i].wResId=i+1;
430 memcpy(_free,(LPBYTE)bits +bits->idEntries[i].dwDIBOffset,
431 (*res)->idEntries[i].dwBytesInRes);
432 _free += (*res)->idEntries[i].dwBytesInRes;
434 UnmapViewOfFile( bits );
435 return TRUE;
436 fail:
437 if (*res) HeapFree( GetProcessHeap(), 0, *res );
438 if (*ptr) HeapFree( GetProcessHeap(), 0, *ptr );
439 UnmapViewOfFile( bits );
440 return FALSE;
444 /**********************************************************************
445 * CURSORICON_CreateFromResource
447 * Create a cursor or icon from in-memory resource template.
449 * FIXME: Convert to mono when cFlag is LR_MONOCHROME. Do something
450 * with cbSize parameter as well.
452 static HGLOBAL16 CURSORICON_CreateFromResource( HINSTANCE16 hInstance, HGLOBAL16 hObj, LPBYTE bits,
453 UINT cbSize, BOOL bIcon, DWORD dwVersion,
454 INT width, INT height, UINT loadflags )
456 static HDC hdcMem;
457 int sizeAnd, sizeXor;
458 HBITMAP hAndBits = 0, hXorBits = 0; /* error condition for later */
459 BITMAP bmpXor, bmpAnd;
460 POINT16 hotspot;
461 BITMAPINFO *bmi;
462 BOOL DoStretch;
463 INT size;
465 hotspot.x = ICON_HOTSPOT;
466 hotspot.y = ICON_HOTSPOT;
468 TRACE_(cursor)("%08x (%u bytes), ver %08x, %ix%i %s %s\n",
469 (unsigned)bits, cbSize, (unsigned)dwVersion, width, height,
470 bIcon ? "icon" : "cursor", (loadflags & LR_MONOCHROME) ? "mono" : "" );
471 if (dwVersion == 0x00020000)
473 FIXME_(cursor)("\t2.xx resources are not supported\n");
474 return 0;
477 if (bIcon)
478 bmi = (BITMAPINFO *)bits;
479 else /* get the hotspot */
481 POINT16 *pt = (POINT16 *)bits;
482 hotspot = *pt;
483 bmi = (BITMAPINFO *)(pt + 1);
485 size = DIB_BitmapInfoSize( bmi, DIB_RGB_COLORS );
487 if (!width) width = bmi->bmiHeader.biWidth;
488 if (!height) height = bmi->bmiHeader.biHeight/2;
489 DoStretch = (bmi->bmiHeader.biHeight/2 != height) ||
490 (bmi->bmiHeader.biWidth != width);
492 /* Check bitmap header */
494 if ( (bmi->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) &&
495 (bmi->bmiHeader.biSize != sizeof(BITMAPINFOHEADER) ||
496 bmi->bmiHeader.biCompression != BI_RGB) )
498 WARN_(cursor)("\tinvalid resource bitmap header.\n");
499 return 0;
502 if (!screen_dc) screen_dc = CreateDCA( "DISPLAY", NULL, NULL, NULL );
503 if (screen_dc)
505 BITMAPINFO* pInfo;
507 /* Make sure we have room for the monochrome bitmap later on.
508 * Note that BITMAPINFOINFO and BITMAPCOREHEADER are the same
509 * up to and including the biBitCount. In-memory icon resource
510 * format is as follows:
512 * BITMAPINFOHEADER icHeader // DIB header
513 * RGBQUAD icColors[] // Color table
514 * BYTE icXOR[] // DIB bits for XOR mask
515 * BYTE icAND[] // DIB bits for AND mask
518 if ((pInfo = (BITMAPINFO *)HeapAlloc( GetProcessHeap(), 0,
519 max(size, sizeof(BITMAPINFOHEADER) + 2*sizeof(RGBQUAD)))))
521 memcpy( pInfo, bmi, size );
522 pInfo->bmiHeader.biHeight /= 2;
524 /* Create the XOR bitmap */
526 if (DoStretch) {
527 if(bIcon)
529 hXorBits = CreateCompatibleBitmap(screen_dc, width, height);
531 else
533 hXorBits = CreateBitmap(width, height, 1, 1, NULL);
535 if(hXorBits)
537 HBITMAP hOld;
538 BOOL res = FALSE;
540 if (!hdcMem) hdcMem = CreateCompatibleDC(screen_dc);
541 if (hdcMem) {
542 hOld = SelectObject(hdcMem, hXorBits);
543 res = StretchDIBits(hdcMem, 0, 0, width, height, 0, 0,
544 bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight/2,
545 (char*)bmi + size, pInfo, DIB_RGB_COLORS, SRCCOPY);
546 SelectObject(hdcMem, hOld);
548 if (!res) { DeleteObject(hXorBits); hXorBits = 0; }
550 } else hXorBits = CreateDIBitmap( screen_dc, &pInfo->bmiHeader,
551 CBM_INIT, (char*)bmi + size, pInfo, DIB_RGB_COLORS );
552 if( hXorBits )
554 char* xbits = (char *)bmi + size +
555 DIB_GetDIBImageBytes(bmi->bmiHeader.biWidth,
556 bmi->bmiHeader.biHeight,
557 bmi->bmiHeader.biBitCount) / 2;
559 pInfo->bmiHeader.biBitCount = 1;
560 if (pInfo->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
562 RGBQUAD *rgb = pInfo->bmiColors;
564 pInfo->bmiHeader.biClrUsed = pInfo->bmiHeader.biClrImportant = 2;
565 rgb[0].rgbBlue = rgb[0].rgbGreen = rgb[0].rgbRed = 0x00;
566 rgb[1].rgbBlue = rgb[1].rgbGreen = rgb[1].rgbRed = 0xff;
567 rgb[0].rgbReserved = rgb[1].rgbReserved = 0;
569 else
571 RGBTRIPLE *rgb = (RGBTRIPLE *)(((BITMAPCOREHEADER *)pInfo) + 1);
573 rgb[0].rgbtBlue = rgb[0].rgbtGreen = rgb[0].rgbtRed = 0x00;
574 rgb[1].rgbtBlue = rgb[1].rgbtGreen = rgb[1].rgbtRed = 0xff;
577 /* Create the AND bitmap */
579 if (DoStretch) {
580 if ((hAndBits = CreateBitmap(width, height, 1, 1, NULL))) {
581 HBITMAP hOld;
582 BOOL res = FALSE;
584 if (!hdcMem) hdcMem = CreateCompatibleDC(screen_dc);
585 if (hdcMem) {
586 hOld = SelectObject(hdcMem, hAndBits);
587 res = StretchDIBits(hdcMem, 0, 0, width, height, 0, 0,
588 pInfo->bmiHeader.biWidth, pInfo->bmiHeader.biHeight,
589 xbits, pInfo, DIB_RGB_COLORS, SRCCOPY);
590 SelectObject(hdcMem, hOld);
592 if (!res) { DeleteObject(hAndBits); hAndBits = 0; }
594 } else hAndBits = CreateDIBitmap( screen_dc, &pInfo->bmiHeader,
595 CBM_INIT, xbits, pInfo, DIB_RGB_COLORS );
597 if( !hAndBits ) DeleteObject( hXorBits );
599 HeapFree( GetProcessHeap(), 0, pInfo );
603 if( !hXorBits || !hAndBits )
605 WARN_(cursor)("\tunable to create an icon bitmap.\n");
606 return 0;
609 /* Now create the CURSORICONINFO structure */
610 GetObjectA( hXorBits, sizeof(bmpXor), &bmpXor );
611 GetObjectA( hAndBits, sizeof(bmpAnd), &bmpAnd );
612 sizeXor = bmpXor.bmHeight * bmpXor.bmWidthBytes;
613 sizeAnd = bmpAnd.bmHeight * bmpAnd.bmWidthBytes;
615 if (hObj) hObj = GlobalReAlloc16( hObj,
616 sizeof(CURSORICONINFO) + sizeXor + sizeAnd, GMEM_MOVEABLE );
617 if (!hObj) hObj = GlobalAlloc16( GMEM_MOVEABLE,
618 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
619 if (hObj)
621 CURSORICONINFO *info;
623 /* Make it owned by the module */
624 if (hInstance) hInstance = GetExePtr(hInstance);
625 FarSetOwner16( hObj, hInstance );
627 info = (CURSORICONINFO *)GlobalLock16( hObj );
628 info->ptHotSpot.x = hotspot.x;
629 info->ptHotSpot.y = hotspot.y;
630 info->nWidth = bmpXor.bmWidth;
631 info->nHeight = bmpXor.bmHeight;
632 info->nWidthBytes = bmpXor.bmWidthBytes;
633 info->bPlanes = bmpXor.bmPlanes;
634 info->bBitsPerPixel = bmpXor.bmBitsPixel;
636 /* Transfer the bitmap bits to the CURSORICONINFO structure */
638 GetBitmapBits( hAndBits, sizeAnd, (char *)(info + 1) );
639 GetBitmapBits( hXorBits, sizeXor, (char *)(info + 1) + sizeAnd );
640 GlobalUnlock16( hObj );
643 DeleteObject( hAndBits );
644 DeleteObject( hXorBits );
645 return hObj;
649 /**********************************************************************
650 * CreateIconFromResourceEx (USER.450)
652 * FIXME: not sure about exact parameter types
654 HICON16 WINAPI CreateIconFromResourceEx16( LPBYTE bits, UINT16 cbSize, BOOL16 bIcon,
655 DWORD dwVersion, INT16 width, INT16 height, UINT16 cFlag )
657 return CreateIconFromResourceEx(bits, cbSize, bIcon, dwVersion,
658 width, height, cFlag);
662 /**********************************************************************
663 * CreateIconFromResource (USER32.@)
665 HICON WINAPI CreateIconFromResource( LPBYTE bits, UINT cbSize,
666 BOOL bIcon, DWORD dwVersion)
668 return CreateIconFromResourceEx( bits, cbSize, bIcon, dwVersion, 0,0,0);
672 /**********************************************************************
673 * CreateIconFromResourceEx (USER32.@)
675 HICON WINAPI CreateIconFromResourceEx( LPBYTE bits, UINT cbSize,
676 BOOL bIcon, DWORD dwVersion,
677 INT width, INT height,
678 UINT cFlag )
680 return CURSORICON_CreateFromResource( 0, 0, bits, cbSize, bIcon, dwVersion,
681 width, height, cFlag );
684 /**********************************************************************
685 * CURSORICON_Load
687 * Load a cursor or icon from resource or file.
689 HGLOBAL CURSORICON_Load( HINSTANCE hInstance, LPCWSTR name,
690 INT width, INT height, INT colors,
691 BOOL fCursor, UINT loadflags )
693 HANDLE handle = 0, h = 0;
694 HANDLE hRsrc;
695 CURSORICONDIR *dir;
696 CURSORICONDIRENTRY *dirEntry;
697 LPBYTE bits;
699 if ( loadflags & LR_LOADFROMFILE ) /* Load from file */
701 LPBYTE *ptr;
702 if (!CURSORICON_SimulateLoadingFromResourceW((LPWSTR)name, fCursor, &dir, &ptr))
703 return 0;
704 if (fCursor)
705 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor(dir, width, height, 1);
706 else
707 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon(dir, width, height, colors);
708 bits = ptr[dirEntry->wResId-1];
709 h = CURSORICON_CreateFromResource( 0, 0, bits, dirEntry->dwBytesInRes,
710 !fCursor, 0x00030000, width, height, loadflags);
711 HeapFree( GetProcessHeap(), 0, dir );
712 HeapFree( GetProcessHeap(), 0, ptr );
714 else /* Load from resource */
716 HANDLE hGroupRsrc;
717 WORD wResId;
718 DWORD dwBytesInRes;
720 if (!hInstance) /* Load OEM cursor/icon */
722 if (!(hInstance = GetModuleHandleA( "user32.dll" ))) return 0;
725 /* Normalize hInstance (must be uniquely represented for icon cache) */
727 if ( HIWORD( hInstance ) )
728 hInstance = MapHModuleLS( hInstance );
729 else
730 hInstance = GetExePtr( hInstance );
732 /* Get directory resource ID */
734 if (!(hRsrc = FindResourceW( hInstance, name,
735 fCursor ? RT_GROUP_CURSORW : RT_GROUP_ICONW )))
736 return 0;
737 hGroupRsrc = hRsrc;
739 /* Find the best entry in the directory */
741 if (!(handle = LoadResource( hInstance, hRsrc ))) return 0;
742 if (!(dir = (CURSORICONDIR*)LockResource( handle ))) return 0;
743 if (fCursor)
744 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor( dir,
745 width, height, 1);
746 else
747 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon( dir,
748 width, height, colors );
749 if (!dirEntry) return 0;
750 wResId = dirEntry->wResId;
751 dwBytesInRes = dirEntry->dwBytesInRes;
752 FreeResource( handle );
754 /* Load the resource */
756 if (!(hRsrc = FindResourceW(hInstance,MAKEINTRESOURCEW(wResId),
757 fCursor ? RT_CURSORW : RT_ICONW ))) return 0;
759 /* If shared icon, check whether it was already loaded */
760 if ( (loadflags & LR_SHARED)
761 && (h = CURSORICON_FindSharedIcon( hInstance, hRsrc ) ) != 0 )
762 return h;
764 if (!(handle = LoadResource( hInstance, hRsrc ))) return 0;
765 bits = (LPBYTE)LockResource( handle );
766 h = CURSORICON_CreateFromResource( 0, 0, bits, dwBytesInRes,
767 !fCursor, 0x00030000, width, height, loadflags);
768 FreeResource( handle );
770 /* If shared icon, add to icon cache */
772 if ( h && (loadflags & LR_SHARED) )
773 CURSORICON_AddSharedIcon( hInstance, hRsrc, hGroupRsrc, h );
776 return h;
779 /***********************************************************************
780 * CURSORICON_Copy
782 * Make a copy of a cursor or icon.
784 static HGLOBAL16 CURSORICON_Copy( HINSTANCE16 hInstance, HGLOBAL16 handle )
786 char *ptrOld, *ptrNew;
787 int size;
788 HGLOBAL16 hNew;
790 if (!(ptrOld = (char *)GlobalLock16( handle ))) return 0;
791 if (hInstance && !(hInstance = GetExePtr( hInstance ))) return 0;
792 size = GlobalSize16( handle );
793 hNew = GlobalAlloc16( GMEM_MOVEABLE, size );
794 FarSetOwner16( hNew, hInstance );
795 ptrNew = (char *)GlobalLock16( hNew );
796 memcpy( ptrNew, ptrOld, size );
797 GlobalUnlock16( handle );
798 GlobalUnlock16( hNew );
799 return hNew;
802 /*************************************************************************
803 * CURSORICON_ExtCopy
805 * Copies an Image from the Cache if LR_COPYFROMRESOURCE is specified
807 * PARAMS
808 * Handle [I] handle to an Image
809 * nType [I] Type of Handle (IMAGE_CURSOR | IMAGE_ICON)
810 * iDesiredCX [I] The Desired width of the Image
811 * iDesiredCY [I] The desired height of the Image
812 * nFlags [I] The flags from CopyImage
814 * RETURNS
815 * Success: The new handle of the Image
817 * NOTES
818 * LR_COPYDELETEORG and LR_MONOCHROME are currently not implemented.
819 * LR_MONOCHROME should be implemented by CURSORICON_CreateFromResource.
820 * LR_COPYFROMRESOURCE will only work if the Image is in the Cache.
825 HGLOBAL CURSORICON_ExtCopy(HGLOBAL Handle, UINT nType,
826 INT iDesiredCX, INT iDesiredCY,
827 UINT nFlags)
829 HGLOBAL16 hNew=0;
831 TRACE_(icon)("Handle %u, uType %u, iDesiredCX %i, iDesiredCY %i, nFlags %u\n",
832 Handle, nType, iDesiredCX, iDesiredCY, nFlags);
834 if(Handle == 0)
836 return 0;
839 /* Best Fit or Monochrome */
840 if( (nFlags & LR_COPYFROMRESOURCE
841 && (iDesiredCX > 0 || iDesiredCY > 0))
842 || nFlags & LR_MONOCHROME)
844 ICONCACHE* pIconCache = CURSORICON_FindCache(Handle);
846 /* Not Found in Cache, then do a strait copy
848 if(pIconCache == NULL)
850 hNew = CURSORICON_Copy(0, Handle);
851 if(nFlags & LR_COPYFROMRESOURCE)
853 TRACE_(icon)("LR_COPYFROMRESOURCE: Failed to load from cache\n");
856 else
858 int iTargetCY = iDesiredCY, iTargetCX = iDesiredCX;
859 LPBYTE pBits;
860 HANDLE hMem;
861 HRSRC hRsrc;
862 DWORD dwBytesInRes;
863 WORD wResId;
864 CURSORICONDIR *pDir;
865 CURSORICONDIRENTRY *pDirEntry;
866 BOOL bIsIcon = (nType == IMAGE_ICON);
868 /* Completing iDesiredCX CY for Monochrome Bitmaps if needed
870 if(((nFlags & LR_MONOCHROME) && !(nFlags & LR_COPYFROMRESOURCE))
871 || (iDesiredCX == 0 && iDesiredCY == 0))
873 iDesiredCY = GetSystemMetrics(bIsIcon ?
874 SM_CYICON : SM_CYCURSOR);
875 iDesiredCX = GetSystemMetrics(bIsIcon ?
876 SM_CXICON : SM_CXCURSOR);
879 /* Retreive the CURSORICONDIRENTRY
881 if (!(hMem = LoadResource( pIconCache->hModule ,
882 pIconCache->hGroupRsrc)))
884 return 0;
886 if (!(pDir = (CURSORICONDIR*)LockResource( hMem )))
888 return 0;
891 /* Find Best Fit
893 if(bIsIcon)
895 pDirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon(
896 pDir, iDesiredCX, iDesiredCY, 256);
898 else
900 pDirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor(
901 pDir, iDesiredCX, iDesiredCY, 1);
904 wResId = pDirEntry->wResId;
905 dwBytesInRes = pDirEntry->dwBytesInRes;
906 FreeResource(hMem);
908 TRACE_(icon)("ResID %u, BytesInRes %lu, Width %d, Height %d DX %d, DY %d\n",
909 wResId, dwBytesInRes, pDirEntry->ResInfo.icon.bWidth,
910 pDirEntry->ResInfo.icon.bHeight, iDesiredCX, iDesiredCY);
912 /* Get the Best Fit
914 if (!(hRsrc = FindResourceW(pIconCache->hModule ,
915 MAKEINTRESOURCEW(wResId), bIsIcon ? RT_ICONW : RT_CURSORW)))
917 return 0;
919 if (!(hMem = LoadResource( pIconCache->hModule , hRsrc )))
921 return 0;
924 pBits = (LPBYTE)LockResource( hMem );
926 if(nFlags & LR_DEFAULTSIZE)
928 iTargetCY = GetSystemMetrics(SM_CYICON);
929 iTargetCX = GetSystemMetrics(SM_CXICON);
932 /* Create a New Icon with the proper dimension
934 hNew = CURSORICON_CreateFromResource( 0, 0, pBits, dwBytesInRes,
935 bIsIcon, 0x00030000, iTargetCX, iTargetCY, nFlags);
936 FreeResource(hMem);
939 else hNew = CURSORICON_Copy(0, Handle);
940 return hNew;
943 /***********************************************************************
944 * CURSORICON_IconToCursor
946 * Converts bitmap to mono and truncates if icon is too large (should
947 * probably do StretchBlt() instead).
949 HCURSOR16 CURSORICON_IconToCursor(HICON16 hIcon, BOOL bSemiTransparent)
951 HCURSOR16 hRet = 0;
952 CURSORICONINFO *pIcon = NULL;
954 if(hIcon)
955 if (!(pIcon = (CURSORICONINFO*)GlobalLock16( hIcon ))) return FALSE;
956 if (pIcon->bPlanes * pIcon->bBitsPerPixel == 1)
958 hRet = CURSORICON_Copy( 0, hIcon );
961 pIcon = GlobalLock16(hRet);
963 pIcon->ptHotSpot.x = pIcon->ptHotSpot.y = 15;
965 GlobalUnlock16(hRet);
967 else
969 BYTE pAndBits[128];
970 BYTE pXorBits[128];
971 int maxx, maxy, ix, iy, bpp = pIcon->bBitsPerPixel;
972 BYTE* psPtr, *pxbPtr = pXorBits;
973 unsigned xor_width, and_width, val_base = 0xffffffff >> (32 - bpp);
974 BYTE* pbc = NULL;
976 CURSORICONINFO cI;
978 TRACE_(icon)("[%04x] %ix%i %ibpp (bogus %ibps)\n",
979 hIcon, pIcon->nWidth, pIcon->nHeight, pIcon->bBitsPerPixel, pIcon->nWidthBytes );
981 xor_width = BITMAP_GetWidthBytes( pIcon->nWidth, bpp );
982 and_width = BITMAP_GetWidthBytes( pIcon->nWidth, 1 );
983 psPtr = (BYTE *)(pIcon + 1) + pIcon->nHeight * and_width;
985 memset(pXorBits, 0, 128);
986 cI.bBitsPerPixel = 1; cI.bPlanes = 1;
987 cI.ptHotSpot.x = cI.ptHotSpot.y = 15;
988 cI.nWidth = 32; cI.nHeight = 32;
989 cI.nWidthBytes = 4; /* 32x1bpp */
991 maxx = (pIcon->nWidth > 32) ? 32 : pIcon->nWidth;
992 maxy = (pIcon->nHeight > 32) ? 32 : pIcon->nHeight;
994 for( iy = 0; iy < maxy; iy++ )
996 unsigned shift = iy % 2;
998 memcpy( pAndBits + iy * 4, (BYTE *)(pIcon + 1) + iy * and_width,
999 (and_width > 4) ? 4 : and_width );
1000 for( ix = 0; ix < maxx; ix++ )
1002 if( bSemiTransparent && ((ix+shift)%2) )
1004 /* set AND bit, XOR bit stays 0 */
1006 pbc = pAndBits + iy * 4 + ix/8;
1007 *pbc |= 0x80 >> (ix%8);
1009 else
1011 /* keep AND bit, set XOR bit */
1013 unsigned *psc = (unsigned*)(psPtr + (ix * bpp)/8);
1014 unsigned val = ((*psc) >> (ix * bpp)%8) & val_base;
1015 if(!PALETTE_Driver->pIsDark(val))
1017 pbc = pxbPtr + ix/8;
1018 *pbc |= 0x80 >> (ix%8);
1022 psPtr += xor_width;
1023 pxbPtr += 4;
1026 hRet = CreateCursorIconIndirect16( 0 , &cI, pAndBits, pXorBits);
1028 if( !hRet ) /* fall back on default drag cursor */
1029 hRet = CURSORICON_Copy( 0 ,
1030 CURSORICON_Load(0,MAKEINTRESOURCEW(OCR_DRAGOBJECT),
1031 GetSystemMetrics(SM_CXCURSOR),
1032 GetSystemMetrics(SM_CYCURSOR), 1, TRUE, 0) );
1035 return hRet;
1039 /***********************************************************************
1040 * LoadCursor (USER.173)
1042 HCURSOR16 WINAPI LoadCursor16( HINSTANCE16 hInstance, LPCSTR name )
1044 return LoadCursorA( hInstance, name );
1048 /***********************************************************************
1049 * LoadIcon (USER.174)
1051 HICON16 WINAPI LoadIcon16( HINSTANCE16 hInstance, LPCSTR name )
1053 return LoadIconA( hInstance, name );
1057 /***********************************************************************
1058 * CreateCursor (USER.406)
1060 HCURSOR16 WINAPI CreateCursor16( HINSTANCE16 hInstance,
1061 INT16 xHotSpot, INT16 yHotSpot,
1062 INT16 nWidth, INT16 nHeight,
1063 LPCVOID lpANDbits, LPCVOID lpXORbits )
1065 CURSORICONINFO info;
1067 TRACE_(cursor)("%dx%d spot=%d,%d xor=%p and=%p\n",
1068 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
1070 info.ptHotSpot.x = xHotSpot;
1071 info.ptHotSpot.y = yHotSpot;
1072 info.nWidth = nWidth;
1073 info.nHeight = nHeight;
1074 info.nWidthBytes = 0;
1075 info.bPlanes = 1;
1076 info.bBitsPerPixel = 1;
1078 return CreateCursorIconIndirect16( hInstance, &info, lpANDbits, lpXORbits );
1082 /***********************************************************************
1083 * CreateCursor (USER32.@)
1085 HCURSOR WINAPI CreateCursor( HINSTANCE hInstance,
1086 INT xHotSpot, INT yHotSpot,
1087 INT nWidth, INT nHeight,
1088 LPCVOID lpANDbits, LPCVOID lpXORbits )
1090 CURSORICONINFO info;
1092 TRACE_(cursor)("%dx%d spot=%d,%d xor=%p and=%p\n",
1093 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
1095 info.ptHotSpot.x = xHotSpot;
1096 info.ptHotSpot.y = yHotSpot;
1097 info.nWidth = nWidth;
1098 info.nHeight = nHeight;
1099 info.nWidthBytes = 0;
1100 info.bPlanes = 1;
1101 info.bBitsPerPixel = 1;
1103 return CreateCursorIconIndirect16( 0, &info, lpANDbits, lpXORbits );
1107 /***********************************************************************
1108 * CreateIcon (USER.407)
1110 HICON16 WINAPI CreateIcon16( HINSTANCE16 hInstance, INT16 nWidth,
1111 INT16 nHeight, BYTE bPlanes, BYTE bBitsPixel,
1112 LPCVOID lpANDbits, LPCVOID lpXORbits )
1114 CURSORICONINFO info;
1116 TRACE_(icon)("%dx%dx%d, xor=%p, and=%p\n",
1117 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
1119 info.ptHotSpot.x = ICON_HOTSPOT;
1120 info.ptHotSpot.y = ICON_HOTSPOT;
1121 info.nWidth = nWidth;
1122 info.nHeight = nHeight;
1123 info.nWidthBytes = 0;
1124 info.bPlanes = bPlanes;
1125 info.bBitsPerPixel = bBitsPixel;
1127 return CreateCursorIconIndirect16( hInstance, &info, lpANDbits, lpXORbits );
1131 /***********************************************************************
1132 * CreateIcon (USER32.@)
1134 HICON WINAPI CreateIcon( HINSTANCE hInstance, INT nWidth,
1135 INT nHeight, BYTE bPlanes, BYTE bBitsPixel,
1136 LPCVOID lpANDbits, LPCVOID lpXORbits )
1138 CURSORICONINFO info;
1140 TRACE_(icon)("%dx%dx%d, xor=%p, and=%p\n",
1141 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
1143 info.ptHotSpot.x = ICON_HOTSPOT;
1144 info.ptHotSpot.y = ICON_HOTSPOT;
1145 info.nWidth = nWidth;
1146 info.nHeight = nHeight;
1147 info.nWidthBytes = 0;
1148 info.bPlanes = bPlanes;
1149 info.bBitsPerPixel = bBitsPixel;
1151 return CreateCursorIconIndirect16( 0, &info, lpANDbits, lpXORbits );
1155 /***********************************************************************
1156 * CreateCursorIconIndirect (USER.408)
1158 HGLOBAL16 WINAPI CreateCursorIconIndirect16( HINSTANCE16 hInstance,
1159 CURSORICONINFO *info,
1160 LPCVOID lpANDbits,
1161 LPCVOID lpXORbits )
1163 HGLOBAL16 handle;
1164 char *ptr;
1165 int sizeAnd, sizeXor;
1167 hInstance = GetExePtr( hInstance ); /* Make it a module handle */
1168 if (!lpXORbits || !lpANDbits || info->bPlanes != 1) return 0;
1169 info->nWidthBytes = BITMAP_GetWidthBytes(info->nWidth,info->bBitsPerPixel);
1170 sizeXor = info->nHeight * info->nWidthBytes;
1171 sizeAnd = info->nHeight * BITMAP_GetWidthBytes( info->nWidth, 1 );
1172 if (!(handle = GlobalAlloc16( GMEM_MOVEABLE,
1173 sizeof(CURSORICONINFO) + sizeXor + sizeAnd)))
1174 return 0;
1175 FarSetOwner16( handle, hInstance );
1176 ptr = (char *)GlobalLock16( handle );
1177 memcpy( ptr, info, sizeof(*info) );
1178 memcpy( ptr + sizeof(CURSORICONINFO), lpANDbits, sizeAnd );
1179 memcpy( ptr + sizeof(CURSORICONINFO) + sizeAnd, lpXORbits, sizeXor );
1180 GlobalUnlock16( handle );
1181 return handle;
1185 /***********************************************************************
1186 * CopyIcon (USER.368)
1188 HICON16 WINAPI CopyIcon16( HINSTANCE16 hInstance, HICON16 hIcon )
1190 TRACE_(icon)("%04x %04x\n", hInstance, hIcon );
1191 return CURSORICON_Copy( hInstance, hIcon );
1195 /***********************************************************************
1196 * CopyIcon (USER32.@)
1198 HICON WINAPI CopyIcon( HICON hIcon )
1200 TRACE_(icon)("%04x\n", hIcon );
1201 return CURSORICON_Copy( 0, hIcon );
1205 /***********************************************************************
1206 * CopyCursor (USER.369)
1208 HCURSOR16 WINAPI CopyCursor16( HINSTANCE16 hInstance, HCURSOR16 hCursor )
1210 TRACE_(cursor)("%04x %04x\n", hInstance, hCursor );
1211 return CURSORICON_Copy( hInstance, hCursor );
1214 /**********************************************************************
1215 * DestroyIcon32 (USER.610)
1217 * This routine is actually exported from Win95 USER under the name
1218 * DestroyIcon32 ... The behaviour implemented here should mimic
1219 * the Win95 one exactly, especially the return values, which
1220 * depend on the setting of various flags.
1222 WORD WINAPI CURSORICON_Destroy( HGLOBAL16 handle, UINT16 flags )
1224 WORD retv;
1226 TRACE_(icon)("(%04x, %04x)\n", handle, flags );
1228 /* Check whether destroying active cursor */
1230 if ( hActiveCursor == handle )
1232 ERR_(cursor)("Destroying active cursor!\n" );
1233 SetCursor( 0 );
1236 /* Try shared cursor/icon first */
1238 if ( !(flags & CID_NONSHARED) )
1240 INT count = CURSORICON_DelSharedIcon( handle );
1242 if ( count != -1 )
1243 return (flags & CID_WIN32)? TRUE : (count == 0);
1245 /* FIXME: OEM cursors/icons should be recognized */
1248 /* Now assume non-shared cursor/icon */
1250 retv = GlobalFree16( handle );
1251 return (flags & CID_RESOURCE)? retv : TRUE;
1254 /***********************************************************************
1255 * DestroyIcon (USER.457)
1257 BOOL16 WINAPI DestroyIcon16( HICON16 hIcon )
1259 return CURSORICON_Destroy( hIcon, 0 );
1262 /***********************************************************************
1263 * DestroyIcon (USER32.@)
1265 BOOL WINAPI DestroyIcon( HICON hIcon )
1267 return CURSORICON_Destroy( hIcon, CID_WIN32 );
1270 /***********************************************************************
1271 * DestroyCursor (USER.458)
1273 BOOL16 WINAPI DestroyCursor16( HCURSOR16 hCursor )
1275 return CURSORICON_Destroy( hCursor, 0 );
1278 /***********************************************************************
1279 * DestroyCursor (USER32.@)
1281 BOOL WINAPI DestroyCursor( HCURSOR hCursor )
1283 return CURSORICON_Destroy( hCursor, CID_WIN32 );
1287 /***********************************************************************
1288 * DrawIcon (USER.84)
1290 BOOL16 WINAPI DrawIcon16( HDC16 hdc, INT16 x, INT16 y, HICON16 hIcon )
1292 return DrawIcon( hdc, x, y, hIcon );
1296 /***********************************************************************
1297 * DrawIcon (USER32.@)
1299 BOOL WINAPI DrawIcon( HDC hdc, INT x, INT y, HICON hIcon )
1301 CURSORICONINFO *ptr;
1302 HDC hMemDC;
1303 HBITMAP hXorBits, hAndBits;
1304 COLORREF oldFg, oldBg;
1306 if (!(ptr = (CURSORICONINFO *)GlobalLock16( hIcon ))) return FALSE;
1307 if (!(hMemDC = CreateCompatibleDC( hdc ))) return FALSE;
1308 hAndBits = CreateBitmap( ptr->nWidth, ptr->nHeight, 1, 1,
1309 (char *)(ptr+1) );
1310 hXorBits = CreateBitmap( ptr->nWidth, ptr->nHeight, ptr->bPlanes,
1311 ptr->bBitsPerPixel, (char *)(ptr + 1)
1312 + ptr->nHeight * BITMAP_GetWidthBytes(ptr->nWidth,1) );
1313 oldFg = SetTextColor( hdc, RGB(0,0,0) );
1314 oldBg = SetBkColor( hdc, RGB(255,255,255) );
1316 if (hXorBits && hAndBits)
1318 HBITMAP hBitTemp = SelectObject( hMemDC, hAndBits );
1319 BitBlt( hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0, SRCAND );
1320 SelectObject( hMemDC, hXorBits );
1321 BitBlt(hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0,SRCINVERT);
1322 SelectObject( hMemDC, hBitTemp );
1324 DeleteDC( hMemDC );
1325 if (hXorBits) DeleteObject( hXorBits );
1326 if (hAndBits) DeleteObject( hAndBits );
1327 GlobalUnlock16( hIcon );
1328 SetTextColor( hdc, oldFg );
1329 SetBkColor( hdc, oldBg );
1330 return TRUE;
1334 /***********************************************************************
1335 * IconSize (USER.86)
1337 * See "Undocumented Windows". Used by W2.0 paint.exe.
1339 DWORD WINAPI IconSize16( void )
1341 return MAKELONG(GetSystemMetrics(SM_CYICON), GetSystemMetrics(SM_CXICON));
1345 /***********************************************************************
1346 * DumpIcon (USER.459)
1348 DWORD WINAPI DumpIcon16( SEGPTR pInfo, WORD *lpLen,
1349 SEGPTR *lpXorBits, SEGPTR *lpAndBits )
1351 CURSORICONINFO *info = MapSL( pInfo );
1352 int sizeAnd, sizeXor;
1354 if (!info) return 0;
1355 sizeXor = info->nHeight * info->nWidthBytes;
1356 sizeAnd = info->nHeight * BITMAP_GetWidthBytes( info->nWidth, 1 );
1357 if (lpAndBits) *lpAndBits = pInfo + sizeof(CURSORICONINFO);
1358 if (lpXorBits) *lpXorBits = pInfo + sizeof(CURSORICONINFO) + sizeAnd;
1359 if (lpLen) *lpLen = sizeof(CURSORICONINFO) + sizeAnd + sizeXor;
1360 return MAKELONG( sizeXor, sizeXor );
1364 /***********************************************************************
1365 * SetCursor (USER.69)
1367 HCURSOR16 WINAPI SetCursor16( HCURSOR16 hCursor )
1369 return (HCURSOR16)SetCursor( hCursor );
1373 /***********************************************************************
1374 * SetCursor (USER32.@)
1375 * RETURNS:
1376 * A handle to the previous cursor shape.
1378 HCURSOR WINAPI SetCursor(
1379 HCURSOR hCursor /* [in] Handle of cursor to show */
1381 HCURSOR hOldCursor;
1383 if (hCursor == hActiveCursor) return hActiveCursor; /* No change */
1384 TRACE_(cursor)("%04x\n", hCursor );
1385 hOldCursor = hActiveCursor;
1386 hActiveCursor = hCursor;
1387 /* Change the cursor shape only if it is visible */
1388 if (CURSOR_ShowCount >= 0)
1390 USER_Driver.pSetCursor( (CURSORICONINFO*)GlobalLock16( hActiveCursor ) );
1391 GlobalUnlock16( hActiveCursor );
1393 return hOldCursor;
1397 /***********************************************************************
1398 * SetCursorPos (USER.70)
1400 void WINAPI SetCursorPos16( INT16 x, INT16 y )
1402 SetCursorPos( x, y );
1406 /***********************************************************************
1407 * SetCursorPos (USER32.@)
1409 BOOL WINAPI SetCursorPos( INT x, INT y )
1411 USER_Driver.pMoveCursor( x, y );
1412 return TRUE;
1416 /***********************************************************************
1417 * ShowCursor (USER.71)
1419 INT16 WINAPI ShowCursor16( BOOL16 bShow )
1421 return ShowCursor( bShow );
1425 /***********************************************************************
1426 * ShowCursor (USER32.@)
1428 INT WINAPI ShowCursor( BOOL bShow )
1430 TRACE_(cursor)("%d, count=%d\n",
1431 bShow, CURSOR_ShowCount );
1433 if (bShow)
1435 if (++CURSOR_ShowCount == 0) /* Show it */
1437 USER_Driver.pSetCursor( (CURSORICONINFO*)GlobalLock16( hActiveCursor ) );
1438 GlobalUnlock16( hActiveCursor );
1441 else
1443 if (--CURSOR_ShowCount == -1) /* Hide it */
1444 USER_Driver.pSetCursor( NULL );
1446 return CURSOR_ShowCount;
1450 /***********************************************************************
1451 * GetCursor (USER.247)
1453 HCURSOR16 WINAPI GetCursor16(void)
1455 return hActiveCursor;
1459 /***********************************************************************
1460 * GetCursor (USER32.@)
1462 HCURSOR WINAPI GetCursor(void)
1464 return hActiveCursor;
1468 /***********************************************************************
1469 * ClipCursor (USER.16)
1471 BOOL16 WINAPI ClipCursor16( const RECT16 *rect )
1473 if (!rect) SetRectEmpty( &CURSOR_ClipRect );
1474 else CONV_RECT16TO32( rect, &CURSOR_ClipRect );
1475 return TRUE;
1479 /***********************************************************************
1480 * ClipCursor (USER32.@)
1482 BOOL WINAPI ClipCursor( const RECT *rect )
1484 if (!rect) SetRectEmpty( &CURSOR_ClipRect );
1485 else CopyRect( &CURSOR_ClipRect, rect );
1486 return TRUE;
1490 /***********************************************************************
1491 * GetClipCursor (USER.309)
1493 void WINAPI GetClipCursor16( RECT16 *rect )
1495 if (rect) CONV_RECT32TO16( &CURSOR_ClipRect, rect );
1499 /***********************************************************************
1500 * GetClipCursor (USER32.@)
1502 BOOL WINAPI GetClipCursor( RECT *rect )
1504 if (rect)
1506 CopyRect( rect, &CURSOR_ClipRect );
1507 return TRUE;
1509 return FALSE;
1512 /**********************************************************************
1513 * LookupIconIdFromDirectoryEx (USER.364)
1515 * FIXME: exact parameter sizes
1517 INT16 WINAPI LookupIconIdFromDirectoryEx16( LPBYTE xdir, BOOL16 bIcon,
1518 INT16 width, INT16 height, UINT16 cFlag )
1520 CURSORICONDIR *dir = (CURSORICONDIR*)xdir;
1521 UINT16 retVal = 0;
1522 if( dir && !dir->idReserved && (dir->idType & 3) )
1524 CURSORICONDIRENTRY* entry;
1525 HDC hdc;
1526 UINT palEnts;
1527 int colors;
1528 hdc = GetDC(0);
1529 palEnts = GetSystemPaletteEntries(hdc, 0, 0, NULL);
1530 if (palEnts == 0)
1531 palEnts = 256;
1532 colors = (cFlag & LR_MONOCHROME) ? 2 : palEnts;
1534 ReleaseDC(0, hdc);
1536 if( bIcon )
1537 entry = CURSORICON_FindBestIcon( dir, width, height, colors );
1538 else
1539 entry = CURSORICON_FindBestCursor( dir, width, height, 1);
1541 if( entry ) retVal = entry->wResId;
1543 else WARN_(cursor)("invalid resource directory\n");
1544 return retVal;
1547 /**********************************************************************
1548 * LookupIconIdFromDirectoryEx (USER32.@)
1550 INT WINAPI LookupIconIdFromDirectoryEx( LPBYTE dir, BOOL bIcon,
1551 INT width, INT height, UINT cFlag )
1553 return LookupIconIdFromDirectoryEx16( dir, bIcon, width, height, cFlag );
1556 /**********************************************************************
1557 * LookupIconIdFromDirectory (USER.???)
1559 INT16 WINAPI LookupIconIdFromDirectory16( LPBYTE dir, BOOL16 bIcon )
1561 return LookupIconIdFromDirectoryEx16( dir, bIcon,
1562 bIcon ? GetSystemMetrics(SM_CXICON) : GetSystemMetrics(SM_CXCURSOR),
1563 bIcon ? GetSystemMetrics(SM_CYICON) : GetSystemMetrics(SM_CYCURSOR), bIcon ? 0 : LR_MONOCHROME );
1566 /**********************************************************************
1567 * LookupIconIdFromDirectory (USER32.@)
1569 INT WINAPI LookupIconIdFromDirectory( LPBYTE dir, BOOL bIcon )
1571 return LookupIconIdFromDirectoryEx( dir, bIcon,
1572 bIcon ? GetSystemMetrics(SM_CXICON) : GetSystemMetrics(SM_CXCURSOR),
1573 bIcon ? GetSystemMetrics(SM_CYICON) : GetSystemMetrics(SM_CYCURSOR), bIcon ? 0 : LR_MONOCHROME );
1576 /**********************************************************************
1577 * GetIconID (USER.455)
1579 WORD WINAPI GetIconID16( HGLOBAL16 hResource, DWORD resType )
1581 LPBYTE lpDir = (LPBYTE)GlobalLock16(hResource);
1583 TRACE_(cursor)("hRes=%04x, entries=%i\n",
1584 hResource, lpDir ? ((CURSORICONDIR*)lpDir)->idCount : 0);
1586 switch(resType)
1588 case RT_CURSOR16:
1589 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, FALSE,
1590 GetSystemMetrics(SM_CXCURSOR), GetSystemMetrics(SM_CYCURSOR), LR_MONOCHROME );
1591 case RT_ICON16:
1592 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, TRUE,
1593 GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), 0 );
1594 default:
1595 WARN_(cursor)("invalid res type %ld\n", resType );
1597 return 0;
1600 /**********************************************************************
1601 * LoadCursorIconHandler (USER.336)
1603 * Supposed to load resources of Windows 2.x applications.
1605 HGLOBAL16 WINAPI LoadCursorIconHandler16( HGLOBAL16 hResource, HMODULE16 hModule, HRSRC16 hRsrc )
1607 FIXME_(cursor)("(%04x,%04x,%04x): old 2.x resources are not supported!\n",
1608 hResource, hModule, hRsrc);
1609 return (HGLOBAL16)0;
1612 /**********************************************************************
1613 * LoadDIBIconHandler (USER.357)
1615 * RT_ICON resource loader, installed by USER_SignalProc when module
1616 * is initialized.
1618 HGLOBAL16 WINAPI LoadDIBIconHandler16( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1620 /* If hResource is zero we must allocate a new memory block, if it's
1621 * non-zero but GlobalLock() returns NULL then it was discarded and
1622 * we have to recommit some memory, otherwise we just need to check
1623 * the block size. See LoadProc() in 16-bit SDK for more.
1626 hMemObj = NE_DefResourceHandler( hMemObj, hModule, hRsrc );
1627 if( hMemObj )
1629 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1630 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1631 SizeofResource16(hModule, hRsrc), TRUE, 0x00030000,
1632 GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), LR_DEFAULTCOLOR );
1634 return hMemObj;
1637 /**********************************************************************
1638 * LoadDIBCursorHandler (USER.356)
1640 * RT_CURSOR resource loader. Same as above.
1642 HGLOBAL16 WINAPI LoadDIBCursorHandler16( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1644 hMemObj = NE_DefResourceHandler( hMemObj, hModule, hRsrc );
1645 if( hMemObj )
1647 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1648 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1649 SizeofResource16(hModule, hRsrc), FALSE, 0x00030000,
1650 GetSystemMetrics(SM_CXCURSOR), GetSystemMetrics(SM_CYCURSOR), LR_MONOCHROME );
1652 return hMemObj;
1655 /**********************************************************************
1656 * LoadIconHandler (USER.456)
1658 HICON16 WINAPI LoadIconHandler16( HGLOBAL16 hResource, BOOL16 bNew )
1660 LPBYTE bits = (LPBYTE)LockResource16( hResource );
1662 TRACE_(cursor)("hRes=%04x\n",hResource);
1664 return CURSORICON_CreateFromResource( 0, 0, bits, 0, TRUE,
1665 bNew ? 0x00030000 : 0x00020000, 0, 0, LR_DEFAULTCOLOR );
1668 /***********************************************************************
1669 * LoadCursorW (USER32.@)
1671 HCURSOR WINAPI LoadCursorW(HINSTANCE hInstance, LPCWSTR name)
1673 return LoadImageW( hInstance, name, IMAGE_CURSOR, 0, 0,
1674 LR_SHARED | LR_DEFAULTSIZE );
1677 /***********************************************************************
1678 * LoadCursorA (USER32.@)
1680 HCURSOR WINAPI LoadCursorA(HINSTANCE hInstance, LPCSTR name)
1682 return LoadImageA( hInstance, name, IMAGE_CURSOR, 0, 0,
1683 LR_SHARED | LR_DEFAULTSIZE );
1686 /***********************************************************************
1687 * LoadCursorFromFileW (USER32.@)
1689 HCURSOR WINAPI LoadCursorFromFileW (LPCWSTR name)
1691 return LoadImageW( 0, name, IMAGE_CURSOR, 0, 0,
1692 LR_LOADFROMFILE | LR_DEFAULTSIZE );
1695 /***********************************************************************
1696 * LoadCursorFromFileA (USER32.@)
1698 HCURSOR WINAPI LoadCursorFromFileA (LPCSTR name)
1700 return LoadImageA( 0, name, IMAGE_CURSOR, 0, 0,
1701 LR_LOADFROMFILE | LR_DEFAULTSIZE );
1704 /***********************************************************************
1705 * LoadIconW (USER32.@)
1707 HICON WINAPI LoadIconW(HINSTANCE hInstance, LPCWSTR name)
1709 return LoadImageW( hInstance, name, IMAGE_ICON, 0, 0,
1710 LR_SHARED | LR_DEFAULTSIZE );
1713 /***********************************************************************
1714 * LoadIconA (USER32.@)
1716 HICON WINAPI LoadIconA(HINSTANCE hInstance, LPCSTR name)
1718 return LoadImageA( hInstance, name, IMAGE_ICON, 0, 0,
1719 LR_SHARED | LR_DEFAULTSIZE );
1722 /**********************************************************************
1723 * GetIconInfo (USER.395)
1725 BOOL16 WINAPI GetIconInfo16(HICON16 hIcon,LPICONINFO16 iconinfo)
1727 ICONINFO ii32;
1728 BOOL16 ret = GetIconInfo((HICON)hIcon, &ii32);
1730 iconinfo->fIcon = ii32.fIcon;
1731 iconinfo->xHotspot = ii32.xHotspot;
1732 iconinfo->yHotspot = ii32.yHotspot;
1733 iconinfo->hbmMask = ii32.hbmMask;
1734 iconinfo->hbmColor = ii32.hbmColor;
1735 return ret;
1738 /**********************************************************************
1739 * GetIconInfo (USER32.@)
1741 BOOL WINAPI GetIconInfo(HICON hIcon,PICONINFO iconinfo) {
1742 CURSORICONINFO *ciconinfo;
1744 ciconinfo = GlobalLock16(hIcon);
1745 if (!ciconinfo)
1746 return FALSE;
1748 if ( (ciconinfo->ptHotSpot.x == ICON_HOTSPOT) &&
1749 (ciconinfo->ptHotSpot.y == ICON_HOTSPOT) )
1751 iconinfo->fIcon = TRUE;
1752 iconinfo->xHotspot = ciconinfo->nWidth / 2;
1753 iconinfo->yHotspot = ciconinfo->nHeight / 2;
1755 else
1757 iconinfo->fIcon = FALSE;
1758 iconinfo->xHotspot = ciconinfo->ptHotSpot.x;
1759 iconinfo->yHotspot = ciconinfo->ptHotSpot.y;
1762 iconinfo->hbmColor = CreateBitmap ( ciconinfo->nWidth, ciconinfo->nHeight,
1763 ciconinfo->bPlanes, ciconinfo->bBitsPerPixel,
1764 (char *)(ciconinfo + 1)
1765 + ciconinfo->nHeight *
1766 BITMAP_GetWidthBytes (ciconinfo->nWidth,1) );
1767 iconinfo->hbmMask = CreateBitmap ( ciconinfo->nWidth, ciconinfo->nHeight,
1768 1, 1, (char *)(ciconinfo + 1));
1770 GlobalUnlock16(hIcon);
1772 return TRUE;
1775 /**********************************************************************
1776 * CreateIconIndirect (USER32.@)
1778 HICON WINAPI CreateIconIndirect(PICONINFO iconinfo)
1780 BITMAP bmpXor,bmpAnd;
1781 HICON hObj;
1782 int sizeXor,sizeAnd;
1784 GetObjectA( iconinfo->hbmColor, sizeof(bmpXor), &bmpXor );
1785 GetObjectA( iconinfo->hbmMask, sizeof(bmpAnd), &bmpAnd );
1787 sizeXor = bmpXor.bmHeight * bmpXor.bmWidthBytes;
1788 sizeAnd = bmpAnd.bmHeight * bmpAnd.bmWidthBytes;
1790 hObj = GlobalAlloc16( GMEM_MOVEABLE,
1791 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
1792 if (hObj)
1794 CURSORICONINFO *info;
1796 info = (CURSORICONINFO *)GlobalLock16( hObj );
1798 /* If we are creating an icon, the hotspot is unused */
1799 if (iconinfo->fIcon)
1801 info->ptHotSpot.x = ICON_HOTSPOT;
1802 info->ptHotSpot.y = ICON_HOTSPOT;
1804 else
1806 info->ptHotSpot.x = iconinfo->xHotspot;
1807 info->ptHotSpot.y = iconinfo->yHotspot;
1810 info->nWidth = bmpXor.bmWidth;
1811 info->nHeight = bmpXor.bmHeight;
1812 info->nWidthBytes = bmpXor.bmWidthBytes;
1813 info->bPlanes = bmpXor.bmPlanes;
1814 info->bBitsPerPixel = bmpXor.bmBitsPixel;
1816 /* Transfer the bitmap bits to the CURSORICONINFO structure */
1818 GetBitmapBits( iconinfo->hbmMask ,sizeAnd,(char*)(info + 1) );
1819 GetBitmapBits( iconinfo->hbmColor,sizeXor,(char*)(info + 1) +sizeAnd);
1820 GlobalUnlock16( hObj );
1822 return hObj;
1826 /**********************************************************************
1827 * DrawIconEx (USER.394)
1829 BOOL16 WINAPI DrawIconEx16 (HDC16 hdc, INT16 xLeft, INT16 yTop, HICON16 hIcon,
1830 INT16 cxWidth, INT16 cyWidth, UINT16 istep,
1831 HBRUSH16 hbr, UINT16 flags)
1833 return DrawIconEx(hdc, xLeft, yTop, hIcon, cxWidth, cyWidth,
1834 istep, hbr, flags);
1838 /******************************************************************************
1839 * DrawIconEx (USER32.@) Draws an icon or cursor on device context
1841 * NOTES
1842 * Why is this using SM_CXICON instead of SM_CXCURSOR?
1844 * PARAMS
1845 * hdc [I] Handle to device context
1846 * x0 [I] X coordinate of upper left corner
1847 * y0 [I] Y coordinate of upper left corner
1848 * hIcon [I] Handle to icon to draw
1849 * cxWidth [I] Width of icon
1850 * cyWidth [I] Height of icon
1851 * istep [I] Index of frame in animated cursor
1852 * hbr [I] Handle to background brush
1853 * flags [I] Icon-drawing flags
1855 * RETURNS
1856 * Success: TRUE
1857 * Failure: FALSE
1859 BOOL WINAPI DrawIconEx( HDC hdc, INT x0, INT y0, HICON hIcon,
1860 INT cxWidth, INT cyWidth, UINT istep,
1861 HBRUSH hbr, UINT flags )
1863 CURSORICONINFO *ptr = (CURSORICONINFO *)GlobalLock16 (hIcon);
1864 HDC hDC_off = 0, hMemDC = CreateCompatibleDC (hdc);
1865 BOOL result = FALSE, DoOffscreen;
1866 HBITMAP hB_off = 0, hOld = 0;
1868 if (!ptr) return FALSE;
1869 TRACE_(icon)("(hdc=%x,pos=%d.%d,hicon=%x,extend=%d.%d,istep=%d,br=%x,flags=0x%08x)\n",
1870 hdc,x0,y0,hIcon,cxWidth,cyWidth,istep,hbr,flags
1873 if (istep)
1874 FIXME_(icon)("Ignoring istep=%d\n", istep);
1875 if (flags & DI_COMPAT)
1876 FIXME_(icon)("Ignoring flag DI_COMPAT\n");
1878 if (!flags) {
1879 FIXME_(icon)("no flags set? setting to DI_NORMAL\n");
1880 flags = DI_NORMAL;
1883 /* Calculate the size of the destination image. */
1884 if (cxWidth == 0)
1886 if (flags & DI_DEFAULTSIZE)
1887 cxWidth = GetSystemMetrics (SM_CXICON);
1888 else
1889 cxWidth = ptr->nWidth;
1891 if (cyWidth == 0)
1893 if (flags & DI_DEFAULTSIZE)
1894 cyWidth = GetSystemMetrics (SM_CYICON);
1895 else
1896 cyWidth = ptr->nHeight;
1899 DoOffscreen = (GetObjectType( hbr ) == OBJ_BRUSH);
1901 if (DoOffscreen) {
1902 RECT r;
1904 r.left = 0;
1905 r.top = 0;
1906 r.right = cxWidth;
1907 r.bottom = cxWidth;
1909 hDC_off = CreateCompatibleDC(hdc);
1910 hB_off = CreateCompatibleBitmap(hdc, cxWidth, cyWidth);
1911 if (hDC_off && hB_off) {
1912 hOld = SelectObject(hDC_off, hB_off);
1913 FillRect(hDC_off, &r, hbr);
1917 if (hMemDC && (!DoOffscreen || (hDC_off && hB_off)))
1919 HBITMAP hXorBits, hAndBits;
1920 COLORREF oldFg, oldBg;
1921 INT nStretchMode;
1923 nStretchMode = SetStretchBltMode (hdc, STRETCH_DELETESCANS);
1925 hXorBits = CreateBitmap ( ptr->nWidth, ptr->nHeight,
1926 ptr->bPlanes, ptr->bBitsPerPixel,
1927 (char *)(ptr + 1)
1928 + ptr->nHeight *
1929 BITMAP_GetWidthBytes(ptr->nWidth,1) );
1930 hAndBits = CreateBitmap ( ptr->nWidth, ptr->nHeight,
1931 1, 1, (char *)(ptr+1) );
1932 oldFg = SetTextColor( hdc, RGB(0,0,0) );
1933 oldBg = SetBkColor( hdc, RGB(255,255,255) );
1935 if (hXorBits && hAndBits)
1937 HBITMAP hBitTemp = SelectObject( hMemDC, hAndBits );
1938 if (flags & DI_MASK)
1940 if (DoOffscreen)
1941 StretchBlt (hDC_off, 0, 0, cxWidth, cyWidth,
1942 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
1943 else
1944 StretchBlt (hdc, x0, y0, cxWidth, cyWidth,
1945 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
1947 SelectObject( hMemDC, hXorBits );
1948 if (flags & DI_IMAGE)
1950 if (DoOffscreen)
1951 StretchBlt (hDC_off, 0, 0, cxWidth, cyWidth,
1952 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
1953 else
1954 StretchBlt (hdc, x0, y0, cxWidth, cyWidth,
1955 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
1957 SelectObject( hMemDC, hBitTemp );
1958 result = TRUE;
1961 SetTextColor( hdc, oldFg );
1962 SetBkColor( hdc, oldBg );
1963 if (hXorBits) DeleteObject( hXorBits );
1964 if (hAndBits) DeleteObject( hAndBits );
1965 SetStretchBltMode (hdc, nStretchMode);
1966 if (DoOffscreen) {
1967 BitBlt(hdc, x0, y0, cxWidth, cyWidth, hDC_off, 0, 0, SRCCOPY);
1968 SelectObject(hDC_off, hOld);
1971 if (hMemDC) DeleteDC( hMemDC );
1972 if (hDC_off) DeleteDC(hDC_off);
1973 if (hB_off) DeleteObject(hB_off);
1974 GlobalUnlock16( hIcon );
1975 return result;
1978 /***********************************************************************
1979 * DIB_FixColorsToLoadflags
1981 * Change color table entries when LR_LOADTRANSPARENT or LR_LOADMAP3DCOLORS
1982 * are in loadflags
1984 static void DIB_FixColorsToLoadflags(BITMAPINFO * bmi, UINT loadflags, BYTE pix)
1986 int colors;
1987 COLORREF c_W, c_S, c_F, c_L, c_C;
1988 int incr,i;
1989 RGBQUAD *ptr;
1991 if (bmi->bmiHeader.biBitCount > 8) return;
1992 if (bmi->bmiHeader.biSize == sizeof(BITMAPINFOHEADER)) incr = 4;
1993 else if (bmi->bmiHeader.biSize == sizeof(BITMAPCOREHEADER)) incr = 3;
1994 else {
1995 WARN_(resource)("Wrong bitmap header size!\n");
1996 return;
1998 colors = bmi->bmiHeader.biClrUsed;
1999 if (!colors && (bmi->bmiHeader.biBitCount <= 8))
2000 colors = 1 << bmi->bmiHeader.biBitCount;
2001 c_W = GetSysColor(COLOR_WINDOW);
2002 c_S = GetSysColor(COLOR_3DSHADOW);
2003 c_F = GetSysColor(COLOR_3DFACE);
2004 c_L = GetSysColor(COLOR_3DLIGHT);
2005 if (loadflags & LR_LOADTRANSPARENT) {
2006 switch (bmi->bmiHeader.biBitCount) {
2007 case 1: pix = pix >> 7; break;
2008 case 4: pix = pix >> 4; break;
2009 case 8: break;
2010 default:
2011 WARN_(resource)("(%d): Unsupported depth\n", bmi->bmiHeader.biBitCount);
2012 return;
2014 if (pix >= colors) {
2015 WARN_(resource)("pixel has color index greater than biClrUsed!\n");
2016 return;
2018 if (loadflags & LR_LOADMAP3DCOLORS) c_W = c_F;
2019 ptr = (RGBQUAD*)((char*)bmi->bmiColors+pix*incr);
2020 ptr->rgbBlue = GetBValue(c_W);
2021 ptr->rgbGreen = GetGValue(c_W);
2022 ptr->rgbRed = GetRValue(c_W);
2024 if (loadflags & LR_LOADMAP3DCOLORS)
2025 for (i=0; i<colors; i++) {
2026 ptr = (RGBQUAD*)((char*)bmi->bmiColors+i*incr);
2027 c_C = RGB(ptr->rgbRed, ptr->rgbGreen, ptr->rgbBlue);
2028 if (c_C == RGB(128, 128, 128)) {
2029 ptr->rgbRed = GetRValue(c_S);
2030 ptr->rgbGreen = GetGValue(c_S);
2031 ptr->rgbBlue = GetBValue(c_S);
2032 } else if (c_C == RGB(192, 192, 192)) {
2033 ptr->rgbRed = GetRValue(c_F);
2034 ptr->rgbGreen = GetGValue(c_F);
2035 ptr->rgbBlue = GetBValue(c_F);
2036 } else if (c_C == RGB(223, 223, 223)) {
2037 ptr->rgbRed = GetRValue(c_L);
2038 ptr->rgbGreen = GetGValue(c_L);
2039 ptr->rgbBlue = GetBValue(c_L);
2045 /**********************************************************************
2046 * BITMAP_Load
2048 static HBITMAP BITMAP_Load( HINSTANCE instance,LPCWSTR name, UINT loadflags )
2050 HBITMAP hbitmap = 0;
2051 HRSRC hRsrc;
2052 HGLOBAL handle;
2053 char *ptr = NULL;
2054 BITMAPINFO *info, *fix_info=NULL;
2055 HGLOBAL hFix;
2056 int size;
2058 if (!(loadflags & LR_LOADFROMFILE)) {
2059 if (!instance) /* OEM bitmap */
2061 if (HIWORD((int)name)) return 0;
2062 return USER_Driver.pLoadOEMResource( LOWORD((int)name), OEM_BITMAP );
2065 if (!(hRsrc = FindResourceW( instance, name, RT_BITMAPW ))) return 0;
2066 if (!(handle = LoadResource( instance, hRsrc ))) return 0;
2068 if ((info = (BITMAPINFO *)LockResource( handle )) == NULL) return 0;
2070 else
2072 if (!(ptr = map_fileW( name ))) return 0;
2073 info = (BITMAPINFO *)(ptr + sizeof(BITMAPFILEHEADER));
2075 size = DIB_BitmapInfoSize(info, DIB_RGB_COLORS);
2076 if ((hFix = GlobalAlloc(0, size))) fix_info=GlobalLock(hFix);
2077 if (fix_info) {
2078 BYTE pix;
2080 memcpy(fix_info, info, size);
2081 pix = *((LPBYTE)info+DIB_BitmapInfoSize(info, DIB_RGB_COLORS));
2082 DIB_FixColorsToLoadflags(fix_info, loadflags, pix);
2083 if (!screen_dc) screen_dc = CreateDCA( "DISPLAY", NULL, NULL, NULL );
2084 if (screen_dc)
2086 char *bits = (char *)info + size;
2087 if (loadflags & LR_CREATEDIBSECTION) {
2088 DIBSECTION dib;
2089 hbitmap = CreateDIBSection(screen_dc, fix_info, DIB_RGB_COLORS, NULL, 0, 0);
2090 GetObjectA(hbitmap, sizeof(DIBSECTION), &dib);
2091 SetDIBits(screen_dc, hbitmap, 0, dib.dsBm.bmHeight, bits, info,
2092 DIB_RGB_COLORS);
2094 else {
2095 hbitmap = CreateDIBitmap( screen_dc, &fix_info->bmiHeader, CBM_INIT,
2096 bits, fix_info, DIB_RGB_COLORS );
2099 GlobalUnlock(hFix);
2100 GlobalFree(hFix);
2102 if (loadflags & LR_LOADFROMFILE) UnmapViewOfFile( ptr );
2103 return hbitmap;
2107 /***********************************************************************
2108 * LoadImage (USER.389)
2111 HANDLE16 WINAPI LoadImage16( HINSTANCE16 hinst, LPCSTR name, UINT16 type,
2112 INT16 desiredx, INT16 desiredy, UINT16 loadflags)
2114 return LoadImageA( hinst, name, type, desiredx, desiredy, loadflags );
2117 /**********************************************************************
2118 * LoadImageA (USER32.@)
2120 * FIXME: implementation lacks some features, see LR_ defines in windows.h
2123 HANDLE WINAPI LoadImageA( HINSTANCE hinst, LPCSTR name, UINT type,
2124 INT desiredx, INT desiredy, UINT loadflags)
2126 HANDLE res;
2127 LPWSTR u_name;
2129 if (HIWORD(name)) u_name = HEAP_strdupAtoW(GetProcessHeap(), 0, name);
2130 else u_name=(LPWSTR)name;
2131 res = LoadImageW(hinst, u_name, type, desiredx, desiredy, loadflags);
2132 if (HIWORD(name)) HeapFree(GetProcessHeap(), 0, u_name);
2133 return res;
2137 /******************************************************************************
2138 * LoadImageW (USER32.@) Loads an icon, cursor, or bitmap
2140 * PARAMS
2141 * hinst [I] Handle of instance that contains image
2142 * name [I] Name of image
2143 * type [I] Type of image
2144 * desiredx [I] Desired width
2145 * desiredy [I] Desired height
2146 * loadflags [I] Load flags
2148 * RETURNS
2149 * Success: Handle to newly loaded image
2150 * Failure: NULL
2152 * FIXME: Implementation lacks some features, see LR_ defines in windows.h
2154 HANDLE WINAPI LoadImageW( HINSTANCE hinst, LPCWSTR name, UINT type,
2155 INT desiredx, INT desiredy, UINT loadflags )
2157 if (HIWORD(name)) {
2158 TRACE_(resource)("(0x%04x,%p,%d,%d,%d,0x%08x)\n",
2159 hinst,name,type,desiredx,desiredy,loadflags);
2160 } else {
2161 TRACE_(resource)("(0x%04x,%p,%d,%d,%d,0x%08x)\n",
2162 hinst,name,type,desiredx,desiredy,loadflags);
2164 if (loadflags & LR_DEFAULTSIZE) {
2165 if (type == IMAGE_ICON) {
2166 if (!desiredx) desiredx = GetSystemMetrics(SM_CXICON);
2167 if (!desiredy) desiredy = GetSystemMetrics(SM_CYICON);
2168 } else if (type == IMAGE_CURSOR) {
2169 if (!desiredx) desiredx = GetSystemMetrics(SM_CXCURSOR);
2170 if (!desiredy) desiredy = GetSystemMetrics(SM_CYCURSOR);
2173 if (loadflags & LR_LOADFROMFILE) loadflags &= ~LR_SHARED;
2174 switch (type) {
2175 case IMAGE_BITMAP:
2176 return BITMAP_Load( hinst, name, loadflags );
2178 case IMAGE_ICON:
2179 if (!screen_dc) screen_dc = CreateDCA( "DISPLAY", NULL, NULL, NULL );
2180 if (screen_dc)
2182 UINT palEnts = GetSystemPaletteEntries(screen_dc, 0, 0, NULL);
2183 if (palEnts == 0) palEnts = 256;
2184 return CURSORICON_Load(hinst, name, desiredx, desiredy,
2185 palEnts, FALSE, loadflags);
2187 break;
2189 case IMAGE_CURSOR:
2190 return CURSORICON_Load(hinst, name, desiredx, desiredy,
2191 1, TRUE, loadflags);
2193 return 0;
2197 /******************************************************************************
2198 * CopyImage (USER.390) Creates new image and copies attributes to it
2201 HICON16 WINAPI CopyImage16( HANDLE16 hnd, UINT16 type, INT16 desiredx,
2202 INT16 desiredy, UINT16 flags )
2204 return (HICON16)CopyImage((HANDLE)hnd, (UINT)type, (INT)desiredx,
2205 (INT)desiredy, (UINT)flags);
2208 /******************************************************************************
2209 * CopyImage (USER32.@) Creates new image and copies attributes to it
2211 * PARAMS
2212 * hnd [I] Handle to image to copy
2213 * type [I] Type of image to copy
2214 * desiredx [I] Desired width of new image
2215 * desiredy [I] Desired height of new image
2216 * flags [I] Copy flags
2218 * RETURNS
2219 * Success: Handle to newly created image
2220 * Failure: NULL
2222 * FIXME: implementation still lacks nearly all features, see LR_*
2223 * defines in windows.h
2225 HICON WINAPI CopyImage( HANDLE hnd, UINT type, INT desiredx,
2226 INT desiredy, UINT flags )
2228 switch (type)
2230 case IMAGE_BITMAP:
2231 return BITMAP_CopyBitmap(hnd);
2232 case IMAGE_ICON:
2233 return CURSORICON_ExtCopy(hnd,type, desiredx, desiredy, flags);
2234 case IMAGE_CURSOR:
2235 /* Should call CURSORICON_ExtCopy but more testing
2236 * needs to be done before we change this
2238 return CopyCursor(hnd);
2240 return 0;
2244 /******************************************************************************
2245 * LoadBitmapW (USER32.@) Loads bitmap from the executable file
2247 * RETURNS
2248 * Success: Handle to specified bitmap
2249 * Failure: NULL
2251 HBITMAP WINAPI LoadBitmapW(
2252 HINSTANCE instance, /* [in] Handle to application instance */
2253 LPCWSTR name) /* [in] Address of bitmap resource name */
2255 return LoadImageW( instance, name, IMAGE_BITMAP, 0, 0, 0 );
2258 /**********************************************************************
2259 * LoadBitmapA (USER32.@)
2261 HBITMAP WINAPI LoadBitmapA( HINSTANCE instance, LPCSTR name )
2263 return LoadImageA( instance, name, IMAGE_BITMAP, 0, 0, 0 );
2266 /**********************************************************************
2267 * LoadBitmap (USER.175)
2269 HBITMAP16 WINAPI LoadBitmap16( HINSTANCE16 instance, LPCSTR name )
2271 return LoadBitmapA( instance, name );