- Implemented 73 CRT functions
[wine/hacks.git] / windows / cursoricon.c
blob561fa9953c897d64aca14580600a2cfd9a41a93e
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 "global.h"
44 #include "module.h"
45 #include "debugtools.h"
46 #include "task.h"
47 #include "user.h"
48 #include "input.h"
49 #include "message.h"
50 #include "winerror.h"
52 DECLARE_DEBUG_CHANNEL(cursor);
53 DECLARE_DEBUG_CHANNEL(icon);
54 DECLARE_DEBUG_CHANNEL(resource);
56 static HCURSOR hActiveCursor = 0; /* Active cursor */
57 static INT CURSOR_ShowCount = 0; /* Cursor display count */
58 static RECT CURSOR_ClipRect; /* Cursor clipping rect */
61 /**********************************************************************
62 * ICONCACHE for cursors/icons loaded with LR_SHARED.
64 * FIXME: This should not be allocated on the system heap, but on a
65 * subsystem-global heap (i.e. one for all Win16 processes,
66 * and one each for every Win32 process).
68 typedef struct tagICONCACHE
70 struct tagICONCACHE *next;
72 HMODULE hModule;
73 HRSRC hRsrc;
74 HRSRC hGroupRsrc;
75 HANDLE handle;
77 INT count;
79 } ICONCACHE;
81 static ICONCACHE *IconAnchor = NULL;
82 static CRITICAL_SECTION IconCrst = CRITICAL_SECTION_INIT;
83 static WORD ICON_HOTSPOT = 0x4242;
85 /**********************************************************************
86 * CURSORICON_FindSharedIcon
88 static HANDLE CURSORICON_FindSharedIcon( HMODULE hModule, HRSRC hRsrc )
90 HANDLE handle = 0;
91 ICONCACHE *ptr;
93 EnterCriticalSection( &IconCrst );
95 for ( ptr = IconAnchor; ptr; ptr = ptr->next )
96 if ( ptr->hModule == hModule && ptr->hRsrc == hRsrc )
98 ptr->count++;
99 handle = ptr->handle;
100 break;
103 LeaveCriticalSection( &IconCrst );
105 return handle;
108 /*************************************************************************
109 * CURSORICON_FindCache
111 * Given a handle, find the coresponding cache element
113 * PARAMS
114 * Handle [I] handle to an Image
116 * RETURNS
117 * Success: The cache entry
118 * Failure: NULL
121 static ICONCACHE* CURSORICON_FindCache(HANDLE handle)
123 ICONCACHE *ptr;
124 ICONCACHE *pRet=NULL;
125 BOOL IsFound = FALSE;
126 int count;
128 EnterCriticalSection( &IconCrst );
130 for (count = 0, ptr = IconAnchor; ptr != NULL && !IsFound; ptr = ptr->next, count++ )
132 if ( handle == ptr->handle )
134 IsFound = TRUE;
135 pRet = ptr;
139 LeaveCriticalSection( &IconCrst );
141 return pRet;
144 /**********************************************************************
145 * CURSORICON_AddSharedIcon
147 static void CURSORICON_AddSharedIcon( HMODULE hModule, HRSRC hRsrc, HRSRC hGroupRsrc, HANDLE handle )
149 ICONCACHE *ptr = HeapAlloc( SystemHeap, 0, sizeof(ICONCACHE) );
150 if ( !ptr ) return;
152 ptr->hModule = hModule;
153 ptr->hRsrc = hRsrc;
154 ptr->handle = handle;
155 ptr->hGroupRsrc = hGroupRsrc;
156 ptr->count = 1;
158 EnterCriticalSection( &IconCrst );
159 ptr->next = IconAnchor;
160 IconAnchor = ptr;
161 LeaveCriticalSection( &IconCrst );
164 /**********************************************************************
165 * CURSORICON_DelSharedIcon
167 static INT CURSORICON_DelSharedIcon( HANDLE handle )
169 INT count = -1;
170 ICONCACHE *ptr;
172 EnterCriticalSection( &IconCrst );
174 for ( ptr = IconAnchor; ptr; ptr = ptr->next )
175 if ( ptr->handle == handle )
177 if ( ptr->count > 0 ) ptr->count--;
178 count = ptr->count;
179 break;
182 LeaveCriticalSection( &IconCrst );
184 return count;
187 /**********************************************************************
188 * CURSORICON_FreeModuleIcons
190 void CURSORICON_FreeModuleIcons( HMODULE hModule )
192 ICONCACHE **ptr = &IconAnchor;
194 if ( HIWORD( hModule ) )
195 hModule = MapHModuleLS( hModule );
196 else
197 hModule = GetExePtr( hModule );
199 EnterCriticalSection( &IconCrst );
201 while ( *ptr )
203 if ( (*ptr)->hModule == hModule )
205 ICONCACHE *freePtr = *ptr;
206 *ptr = freePtr->next;
208 GlobalFree16( freePtr->handle );
209 HeapFree( SystemHeap, 0, freePtr );
210 continue;
212 ptr = &(*ptr)->next;
215 LeaveCriticalSection( &IconCrst );
218 /**********************************************************************
219 * CURSORICON_FindBestIcon
221 * Find the icon closest to the requested size and number of colors.
223 static CURSORICONDIRENTRY *CURSORICON_FindBestIcon( CURSORICONDIR *dir, int width,
224 int height, int colors )
226 int i;
227 CURSORICONDIRENTRY *entry, *bestEntry = NULL;
228 UINT iTotalDiff, iXDiff=0, iYDiff=0, iColorDiff;
229 UINT iTempXDiff, iTempYDiff, iTempColorDiff;
231 if (dir->idCount < 1)
233 WARN_(icon)("Empty directory!\n" );
234 return NULL;
236 if (dir->idCount == 1) return &dir->idEntries[0]; /* No choice... */
238 /* Find Best Fit */
239 iTotalDiff = 0xFFFFFFFF;
240 iColorDiff = 0xFFFFFFFF;
241 for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
243 iTempXDiff = abs(width - entry->ResInfo.icon.bWidth);
244 iTempYDiff = abs(height - entry->ResInfo.icon.bHeight);
246 if(iTotalDiff > (iTempXDiff + iTempYDiff))
248 iXDiff = iTempXDiff;
249 iYDiff = iTempYDiff;
250 iTotalDiff = iXDiff + iYDiff;
254 /* Find Best Colors for Best Fit */
255 for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
257 if(abs(width - entry->ResInfo.icon.bWidth) == iXDiff &&
258 abs(height - entry->ResInfo.icon.bHeight) == iYDiff)
260 iTempColorDiff = abs(colors - entry->ResInfo.icon.bColorCount);
261 if(iColorDiff > iTempColorDiff)
263 bestEntry = entry;
264 iColorDiff = iTempColorDiff;
269 return bestEntry;
273 /**********************************************************************
274 * CURSORICON_FindBestCursor
276 * Find the cursor closest to the requested size.
277 * FIXME: parameter 'color' ignored and entries with more than 1 bpp
278 * ignored too
280 static CURSORICONDIRENTRY *CURSORICON_FindBestCursor( CURSORICONDIR *dir,
281 int width, int height, int color)
283 int i, maxwidth, maxheight;
284 CURSORICONDIRENTRY *entry, *bestEntry = NULL;
286 if (dir->idCount < 1)
288 WARN_(cursor)("Empty directory!\n" );
289 return NULL;
291 if (dir->idCount == 1) return &dir->idEntries[0]; /* No choice... */
293 /* Double height to account for AND and XOR masks */
295 height *= 2;
297 /* First find the largest one smaller than or equal to the requested size*/
299 maxwidth = maxheight = 0;
300 for(i = 0,entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
301 if ((entry->ResInfo.cursor.wWidth <= width) && (entry->ResInfo.cursor.wHeight <= height) &&
302 (entry->ResInfo.cursor.wWidth > maxwidth) && (entry->ResInfo.cursor.wHeight > maxheight) &&
303 (entry->wBitCount == 1))
305 bestEntry = entry;
306 maxwidth = entry->ResInfo.cursor.wWidth;
307 maxheight = entry->ResInfo.cursor.wHeight;
309 if (bestEntry) return bestEntry;
311 /* Now find the smallest one larger than the requested size */
313 maxwidth = maxheight = 255;
314 for(i = 0,entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
315 if ((entry->ResInfo.cursor.wWidth < maxwidth) && (entry->ResInfo.cursor.wHeight < maxheight) &&
316 (entry->wBitCount == 1))
318 bestEntry = entry;
319 maxwidth = entry->ResInfo.cursor.wWidth;
320 maxheight = entry->ResInfo.cursor.wHeight;
323 return bestEntry;
326 /*********************************************************************
327 * The main purpose of this function is to create fake resource directory
328 * and fake resource entries. There are several reasons for this:
329 * - CURSORICONDIR and CURSORICONFILEDIR differ in sizes and their
330 * fields
331 * There are some "bad" cursor files which do not have
332 * bColorCount initialized but instead one must read this info
333 * directly from corresponding DIB sections
334 * Note: wResId is index to array of pointer returned in ptrs (origin is 1)
336 BOOL CURSORICON_SimulateLoadingFromResourceW( LPWSTR filename, BOOL fCursor,
337 CURSORICONDIR **res, LPBYTE **ptr)
339 LPBYTE _free;
340 CURSORICONFILEDIR *bits;
341 int entries, size, i;
343 *res = NULL;
344 *ptr = NULL;
345 if (!(bits = (CURSORICONFILEDIR *)VIRTUAL_MapFileW( filename ))) return FALSE;
347 /* FIXME: test for inimated icons
348 * hack to load the first icon from the *.ani file
350 if ( *(LPDWORD)bits==0x46464952 ) /* "RIFF" */
351 { LPBYTE pos = (LPBYTE) bits;
352 FIXME_(cursor)("Animated icons not correctly implemented! %p \n", bits);
354 for (;;)
355 { if (*(LPDWORD)pos==0x6e6f6369) /* "icon" */
356 { FIXME_(cursor)("icon entry found! %p\n", bits);
357 pos+=4;
358 if ( !*(LPWORD) pos==0x2fe) /* iconsize */
359 { goto fail;
361 bits=(CURSORICONFILEDIR*)(pos+4);
362 FIXME_(cursor)("icon size ok. offset=%p \n", bits);
363 break;
365 pos+=2;
366 if (pos>=(LPBYTE)bits+766) goto fail;
369 if (!(entries = bits->idCount)) goto fail;
370 size = sizeof(CURSORICONDIR) + sizeof(CURSORICONDIRENTRY) * (entries - 1);
371 _free = (LPBYTE) size;
373 for (i=0; i < entries; i++)
374 size += bits->idEntries[i].dwDIBSize + (fCursor ? sizeof(POINT16): 0);
376 if (!(*ptr = HeapAlloc( GetProcessHeap(), 0,
377 entries * sizeof (CURSORICONDIRENTRY*)))) goto fail;
378 if (!(*res = HeapAlloc( GetProcessHeap(), 0, size))) goto fail;
380 _free = (LPBYTE)(*res) + (int)_free;
381 memcpy((*res), bits, 6);
382 for (i=0; i<entries; i++)
384 ((LPBYTE*)(*ptr))[i] = _free;
385 if (fCursor) {
386 (*res)->idEntries[i].ResInfo.cursor.wWidth=bits->idEntries[i].bWidth;
387 (*res)->idEntries[i].ResInfo.cursor.wHeight=bits->idEntries[i].bHeight;
388 ((LPPOINT16)_free)->x=bits->idEntries[i].xHotspot;
389 ((LPPOINT16)_free)->y=bits->idEntries[i].yHotspot;
390 _free+=sizeof(POINT16);
391 } else {
392 (*res)->idEntries[i].ResInfo.icon.bWidth=bits->idEntries[i].bWidth;
393 (*res)->idEntries[i].ResInfo.icon.bHeight=bits->idEntries[i].bHeight;
394 (*res)->idEntries[i].ResInfo.icon.bColorCount = bits->idEntries[i].bColorCount;
396 (*res)->idEntries[i].wPlanes=1;
397 (*res)->idEntries[i].wBitCount = ((LPBITMAPINFOHEADER)((LPBYTE)bits +
398 bits->idEntries[i].dwDIBOffset))->biBitCount;
399 (*res)->idEntries[i].dwBytesInRes = bits->idEntries[i].dwDIBSize;
400 (*res)->idEntries[i].wResId=i+1;
402 memcpy(_free,(LPBYTE)bits +bits->idEntries[i].dwDIBOffset,
403 (*res)->idEntries[i].dwBytesInRes);
404 _free += (*res)->idEntries[i].dwBytesInRes;
406 UnmapViewOfFile( bits );
407 return TRUE;
408 fail:
409 if (*res) HeapFree( GetProcessHeap(), 0, *res );
410 if (*ptr) HeapFree( GetProcessHeap(), 0, *ptr );
411 UnmapViewOfFile( bits );
412 return FALSE;
416 /**********************************************************************
417 * CURSORICON_CreateFromResource
419 * Create a cursor or icon from in-memory resource template.
421 * FIXME: Convert to mono when cFlag is LR_MONOCHROME. Do something
422 * with cbSize parameter as well.
424 static HGLOBAL16 CURSORICON_CreateFromResource( HINSTANCE16 hInstance, HGLOBAL16 hObj, LPBYTE bits,
425 UINT cbSize, BOOL bIcon, DWORD dwVersion,
426 INT width, INT height, UINT loadflags )
428 int sizeAnd, sizeXor;
429 HBITMAP hAndBits = 0, hXorBits = 0; /* error condition for later */
430 BITMAP bmpXor, bmpAnd;
431 POINT16 hotspot;
432 BITMAPINFO *bmi;
433 HDC hdc;
434 BOOL DoStretch;
435 INT size;
437 hotspot.x = ICON_HOTSPOT;
438 hotspot.y = ICON_HOTSPOT;
440 TRACE_(cursor)("%08x (%u bytes), ver %08x, %ix%i %s %s\n",
441 (unsigned)bits, cbSize, (unsigned)dwVersion, width, height,
442 bIcon ? "icon" : "cursor", (loadflags & LR_MONOCHROME) ? "mono" : "" );
443 if (dwVersion == 0x00020000)
445 FIXME_(cursor)("\t2.xx resources are not supported\n");
446 return 0;
449 if (bIcon)
450 bmi = (BITMAPINFO *)bits;
451 else /* get the hotspot */
453 POINT16 *pt = (POINT16 *)bits;
454 hotspot = *pt;
455 bmi = (BITMAPINFO *)(pt + 1);
457 size = DIB_BitmapInfoSize( bmi, DIB_RGB_COLORS );
459 if (!width) width = bmi->bmiHeader.biWidth;
460 if (!height) height = bmi->bmiHeader.biHeight/2;
461 DoStretch = (bmi->bmiHeader.biHeight/2 != height) ||
462 (bmi->bmiHeader.biWidth != width);
464 /* Check bitmap header */
466 if ( (bmi->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) &&
467 (bmi->bmiHeader.biSize != sizeof(BITMAPINFOHEADER) ||
468 bmi->bmiHeader.biCompression != BI_RGB) )
470 WARN_(cursor)("\tinvalid resource bitmap header.\n");
471 return 0;
474 if( (hdc = GetDC( 0 )) )
476 BITMAPINFO* pInfo;
478 /* Make sure we have room for the monochrome bitmap later on.
479 * Note that BITMAPINFOINFO and BITMAPCOREHEADER are the same
480 * up to and including the biBitCount. In-memory icon resource
481 * format is as follows:
483 * BITMAPINFOHEADER icHeader // DIB header
484 * RGBQUAD icColors[] // Color table
485 * BYTE icXOR[] // DIB bits for XOR mask
486 * BYTE icAND[] // DIB bits for AND mask
489 if ((pInfo = (BITMAPINFO *)HeapAlloc( GetProcessHeap(), 0,
490 max(size, sizeof(BITMAPINFOHEADER) + 2*sizeof(RGBQUAD)))))
492 memcpy( pInfo, bmi, size );
493 pInfo->bmiHeader.biHeight /= 2;
495 /* Create the XOR bitmap */
497 if (DoStretch) {
498 if(bIcon)
500 hXorBits = CreateCompatibleBitmap(hdc, width, height);
502 else
504 hXorBits = CreateBitmap(width, height, 1, 1, NULL);
506 if(hXorBits)
508 HBITMAP hOld;
509 HDC hMem = CreateCompatibleDC(hdc);
510 BOOL res;
512 if (hMem) {
513 hOld = SelectObject(hMem, hXorBits);
514 res = StretchDIBits(hMem, 0, 0, width, height, 0, 0,
515 bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight/2,
516 (char*)bmi + size, pInfo, DIB_RGB_COLORS, SRCCOPY);
517 SelectObject(hMem, hOld);
518 DeleteDC(hMem);
519 } else res = FALSE;
520 if (!res) { DeleteObject(hXorBits); hXorBits = 0; }
522 } else hXorBits = CreateDIBitmap( hdc, &pInfo->bmiHeader,
523 CBM_INIT, (char*)bmi + size, pInfo, DIB_RGB_COLORS );
524 if( hXorBits )
526 char* xbits = (char *)bmi + size +
527 DIB_GetDIBImageBytes(bmi->bmiHeader.biWidth,
528 bmi->bmiHeader.biHeight,
529 bmi->bmiHeader.biBitCount) / 2;
531 pInfo->bmiHeader.biBitCount = 1;
532 if (pInfo->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
534 RGBQUAD *rgb = pInfo->bmiColors;
536 pInfo->bmiHeader.biClrUsed = pInfo->bmiHeader.biClrImportant = 2;
537 rgb[0].rgbBlue = rgb[0].rgbGreen = rgb[0].rgbRed = 0x00;
538 rgb[1].rgbBlue = rgb[1].rgbGreen = rgb[1].rgbRed = 0xff;
539 rgb[0].rgbReserved = rgb[1].rgbReserved = 0;
541 else
543 RGBTRIPLE *rgb = (RGBTRIPLE *)(((BITMAPCOREHEADER *)pInfo) + 1);
545 rgb[0].rgbtBlue = rgb[0].rgbtGreen = rgb[0].rgbtRed = 0x00;
546 rgb[1].rgbtBlue = rgb[1].rgbtGreen = rgb[1].rgbtRed = 0xff;
549 /* Create the AND bitmap */
551 if (DoStretch) {
552 if ((hAndBits = CreateBitmap(width, height, 1, 1, NULL))) {
553 HBITMAP hOld;
554 HDC hMem = CreateCompatibleDC(hdc);
555 BOOL res;
557 if (hMem) {
558 hOld = SelectObject(hMem, hAndBits);
559 res = StretchDIBits(hMem, 0, 0, width, height, 0, 0,
560 pInfo->bmiHeader.biWidth, pInfo->bmiHeader.biHeight,
561 xbits, pInfo, DIB_RGB_COLORS, SRCCOPY);
562 SelectObject(hMem, hOld);
563 DeleteDC(hMem);
564 } else res = FALSE;
565 if (!res) { DeleteObject(hAndBits); hAndBits = 0; }
567 } else hAndBits = CreateDIBitmap( hdc, &pInfo->bmiHeader,
568 CBM_INIT, xbits, pInfo, DIB_RGB_COLORS );
570 if( !hAndBits ) DeleteObject( hXorBits );
572 HeapFree( GetProcessHeap(), 0, pInfo );
574 ReleaseDC( 0, hdc );
577 if( !hXorBits || !hAndBits )
579 WARN_(cursor)("\tunable to create an icon bitmap.\n");
580 return 0;
583 /* Now create the CURSORICONINFO structure */
584 GetObjectA( hXorBits, sizeof(bmpXor), &bmpXor );
585 GetObjectA( hAndBits, sizeof(bmpAnd), &bmpAnd );
586 sizeXor = bmpXor.bmHeight * bmpXor.bmWidthBytes;
587 sizeAnd = bmpAnd.bmHeight * bmpAnd.bmWidthBytes;
589 if (hObj) hObj = GlobalReAlloc16( hObj,
590 sizeof(CURSORICONINFO) + sizeXor + sizeAnd, GMEM_MOVEABLE );
591 if (!hObj) hObj = GlobalAlloc16( GMEM_MOVEABLE,
592 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
593 if (hObj)
595 CURSORICONINFO *info;
597 /* Make it owned by the module */
598 if (hInstance) FarSetOwner16( hObj, GetExePtr(hInstance) );
600 info = (CURSORICONINFO *)GlobalLock16( hObj );
601 info->ptHotSpot.x = hotspot.x;
602 info->ptHotSpot.y = hotspot.y;
603 info->nWidth = bmpXor.bmWidth;
604 info->nHeight = bmpXor.bmHeight;
605 info->nWidthBytes = bmpXor.bmWidthBytes;
606 info->bPlanes = bmpXor.bmPlanes;
607 info->bBitsPerPixel = bmpXor.bmBitsPixel;
609 /* Transfer the bitmap bits to the CURSORICONINFO structure */
611 GetBitmapBits( hAndBits, sizeAnd, (char *)(info + 1) );
612 GetBitmapBits( hXorBits, sizeXor, (char *)(info + 1) + sizeAnd );
613 GlobalUnlock16( hObj );
616 DeleteObject( hAndBits );
617 DeleteObject( hXorBits );
618 return hObj;
622 /**********************************************************************
623 * CreateIconFromResourceEx16 (USER.450)
625 * FIXME: not sure about exact parameter types
627 HICON16 WINAPI CreateIconFromResourceEx16( LPBYTE bits, UINT16 cbSize, BOOL16 bIcon,
628 DWORD dwVersion, INT16 width, INT16 height, UINT16 cFlag )
630 return CreateIconFromResourceEx(bits, cbSize, bIcon, dwVersion,
631 width, height, cFlag);
635 /**********************************************************************
636 * CreateIconFromResource (USER32.76)
638 HICON WINAPI CreateIconFromResource( LPBYTE bits, UINT cbSize,
639 BOOL bIcon, DWORD dwVersion)
641 return CreateIconFromResourceEx( bits, cbSize, bIcon, dwVersion, 0,0,0);
645 /**********************************************************************
646 * CreateIconFromResourceEx (USER32.77)
648 HICON WINAPI CreateIconFromResourceEx( LPBYTE bits, UINT cbSize,
649 BOOL bIcon, DWORD dwVersion,
650 INT width, INT height,
651 UINT cFlag )
653 TDB* pTask = (TDB*)GlobalLock16( GetCurrentTask() );
654 if( pTask )
655 return CURSORICON_CreateFromResource( pTask->hInstance, 0, bits, cbSize, bIcon, dwVersion,
656 width, height, cFlag );
657 return 0;
660 /**********************************************************************
661 * CURSORICON_Load
663 * Load a cursor or icon from resource or file.
665 HGLOBAL CURSORICON_Load( HINSTANCE hInstance, LPCWSTR name,
666 INT width, INT height, INT colors,
667 BOOL fCursor, UINT loadflags )
669 HANDLE handle = 0, h = 0;
670 HANDLE hRsrc;
671 CURSORICONDIR *dir;
672 CURSORICONDIRENTRY *dirEntry;
673 LPBYTE bits;
675 if ( loadflags & LR_LOADFROMFILE ) /* Load from file */
677 LPBYTE *ptr;
678 if (!CURSORICON_SimulateLoadingFromResourceW((LPWSTR)name, fCursor, &dir, &ptr))
679 return 0;
680 if (fCursor)
681 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor(dir, width, height, 1);
682 else
683 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon(dir, width, height, colors);
684 bits = ptr[dirEntry->wResId-1];
685 h = CURSORICON_CreateFromResource( 0, 0, bits, dirEntry->dwBytesInRes,
686 !fCursor, 0x00030000, width, height, loadflags);
687 HeapFree( GetProcessHeap(), 0, dir );
688 HeapFree( GetProcessHeap(), 0, ptr );
691 else if ( !hInstance ) /* Load OEM cursor/icon */
693 WORD resid;
695 if ( HIWORD(name) )
697 LPSTR ansi = HEAP_strdupWtoA(GetProcessHeap(),0,name);
698 if( ansi[0]=='#') /*Check for '#xxx' name */
700 resid = atoi(ansi+1);
701 HeapFree( GetProcessHeap(), 0, ansi );
703 else
705 HeapFree( GetProcessHeap(), 0, ansi );
706 return 0;
709 else resid = LOWORD(name);
710 h = USER_Driver.pLoadOEMResource( resid, fCursor ? OEM_CURSOR : OEM_ICON );
713 else /* Load from resource */
715 HANDLE hGroupRsrc;
716 WORD wResId;
717 DWORD dwBytesInRes;
719 /* Normalize hInstance (must be uniquely represented for icon cache) */
721 if ( HIWORD( hInstance ) )
722 hInstance = MapHModuleLS( hInstance );
723 else
724 hInstance = GetExePtr( hInstance );
726 /* Get directory resource ID */
728 if (!(hRsrc = FindResourceW( hInstance, name,
729 fCursor ? RT_GROUP_CURSORW : RT_GROUP_ICONW )))
730 return 0;
731 hGroupRsrc = hRsrc;
733 /* Find the best entry in the directory */
735 if (!(handle = LoadResource( hInstance, hRsrc ))) return 0;
736 if (!(dir = (CURSORICONDIR*)LockResource( handle ))) return 0;
737 if (fCursor)
738 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor( dir,
739 width, height, 1);
740 else
741 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon( dir,
742 width, height, colors );
743 if (!dirEntry) return 0;
744 wResId = dirEntry->wResId;
745 dwBytesInRes = dirEntry->dwBytesInRes;
746 FreeResource( handle );
748 /* Load the resource */
750 if (!(hRsrc = FindResourceW(hInstance,MAKEINTRESOURCEW(wResId),
751 fCursor ? RT_CURSORW : RT_ICONW ))) return 0;
753 /* If shared icon, check whether it was already loaded */
754 if ( (loadflags & LR_SHARED)
755 && (h = CURSORICON_FindSharedIcon( hInstance, hRsrc ) ) != 0 )
756 return h;
758 if (!(handle = LoadResource( hInstance, hRsrc ))) return 0;
759 bits = (LPBYTE)LockResource( handle );
760 h = CURSORICON_CreateFromResource( 0, 0, bits, dwBytesInRes,
761 !fCursor, 0x00030000, width, height, loadflags);
762 FreeResource( handle );
764 /* If shared icon, add to icon cache */
766 if ( h && (loadflags & LR_SHARED) )
767 CURSORICON_AddSharedIcon( hInstance, hRsrc, hGroupRsrc, h );
770 return h;
773 /***********************************************************************
774 * CURSORICON_Copy
776 * Make a copy of a cursor or icon.
778 static HGLOBAL16 CURSORICON_Copy( HINSTANCE16 hInstance, HGLOBAL16 handle )
780 char *ptrOld, *ptrNew;
781 int size;
782 HGLOBAL16 hNew;
784 if (!(ptrOld = (char *)GlobalLock16( handle ))) return 0;
785 if (!(hInstance = GetExePtr( hInstance ))) return 0;
786 size = GlobalSize16( handle );
787 hNew = GlobalAlloc16( GMEM_MOVEABLE, size );
788 FarSetOwner16( hNew, hInstance );
789 ptrNew = (char *)GlobalLock16( hNew );
790 memcpy( ptrNew, ptrOld, size );
791 GlobalUnlock16( handle );
792 GlobalUnlock16( hNew );
793 return hNew;
796 /*************************************************************************
797 * CURSORICON_ExtCopy
799 * Copies an Image from the Cache if LR_COPYFROMRESOURCE is specified
801 * PARAMS
802 * Handle [I] handle to an Image
803 * nType [I] Type of Handle (IMAGE_CURSOR | IMAGE_ICON)
804 * iDesiredCX [I] The Desired width of the Image
805 * iDesiredCY [I] The desired height of the Image
806 * nFlags [I] The flags from CopyImage
808 * RETURNS
809 * Success: The new handle of the Image
811 * NOTES
812 * LR_COPYDELETEORG and LR_MONOCHROME are currently not implemented.
813 * LR_MONOCHROME should be implemented by CURSORICON_CreateFromResource.
814 * LR_COPYFROMRESOURCE will only work if the Image is in the Cache.
819 HGLOBAL CURSORICON_ExtCopy(HGLOBAL Handle, UINT nType,
820 INT iDesiredCX, INT iDesiredCY,
821 UINT nFlags)
823 HGLOBAL16 hNew=0;
825 TRACE_(icon)("Handle %u, uType %u, iDesiredCX %i, iDesiredCY %i, nFlags %u\n",
826 Handle, nType, iDesiredCX, iDesiredCY, nFlags);
828 if(Handle == 0)
830 return 0;
833 /* Best Fit or Monochrome */
834 if( (nFlags & LR_COPYFROMRESOURCE
835 && (iDesiredCX > 0 || iDesiredCY > 0))
836 || nFlags & LR_MONOCHROME)
838 ICONCACHE* pIconCache = CURSORICON_FindCache(Handle);
840 /* Not Found in Cache, then do a strait copy
842 if(pIconCache == NULL)
844 TDB* pTask = (TDB *) GlobalLock16 (GetCurrentTask ());
845 hNew = CURSORICON_Copy(pTask->hInstance, Handle);
846 if(nFlags & LR_COPYFROMRESOURCE)
848 TRACE_(icon)("LR_COPYFROMRESOURCE: Failed to load from cache\n");
851 else
853 int iTargetCY = iDesiredCY, iTargetCX = iDesiredCX;
854 LPBYTE pBits;
855 HANDLE hMem;
856 HRSRC hRsrc;
857 DWORD dwBytesInRes;
858 WORD wResId;
859 CURSORICONDIR *pDir;
860 CURSORICONDIRENTRY *pDirEntry;
861 BOOL bIsIcon = (nType == IMAGE_ICON);
863 /* Completing iDesiredCX CY for Monochrome Bitmaps if needed
865 if(((nFlags & LR_MONOCHROME) && !(nFlags & LR_COPYFROMRESOURCE))
866 || (iDesiredCX == 0 && iDesiredCY == 0))
868 iDesiredCY = GetSystemMetrics(bIsIcon ?
869 SM_CYICON : SM_CYCURSOR);
870 iDesiredCX = GetSystemMetrics(bIsIcon ?
871 SM_CXICON : SM_CXCURSOR);
874 /* Retreive the CURSORICONDIRENTRY
876 if (!(hMem = LoadResource( pIconCache->hModule ,
877 pIconCache->hGroupRsrc)))
879 return 0;
881 if (!(pDir = (CURSORICONDIR*)LockResource( hMem )))
883 return 0;
886 /* Find Best Fit
888 if(bIsIcon)
890 pDirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon(
891 pDir, iDesiredCX, iDesiredCY, 256);
893 else
895 pDirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor(
896 pDir, iDesiredCX, iDesiredCY, 1);
899 wResId = pDirEntry->wResId;
900 dwBytesInRes = pDirEntry->dwBytesInRes;
901 FreeResource(hMem);
903 TRACE_(icon)("ResID %u, BytesInRes %lu, Width %d, Height %d DX %d, DY %d\n",
904 wResId, dwBytesInRes, pDirEntry->ResInfo.icon.bWidth,
905 pDirEntry->ResInfo.icon.bHeight, iDesiredCX, iDesiredCY);
907 /* Get the Best Fit
909 if (!(hRsrc = FindResourceW(pIconCache->hModule ,
910 MAKEINTRESOURCEW(wResId), bIsIcon ? RT_ICONW : RT_CURSORW)))
912 return 0;
914 if (!(hMem = LoadResource( pIconCache->hModule , hRsrc )))
916 return 0;
919 pBits = (LPBYTE)LockResource( hMem );
921 if(nFlags & LR_DEFAULTSIZE)
923 iTargetCY = GetSystemMetrics(SM_CYICON);
924 iTargetCX = GetSystemMetrics(SM_CXICON);
927 /* Create a New Icon with the proper dimension
929 hNew = CURSORICON_CreateFromResource( 0, 0, pBits, dwBytesInRes,
930 bIsIcon, 0x00030000, iTargetCX, iTargetCY, nFlags);
931 FreeResource(hMem);
934 else
936 TDB* pTask = (TDB *) GlobalLock16 (GetCurrentTask ());
937 hNew = CURSORICON_Copy(pTask->hInstance, Handle);
939 return hNew;
942 /***********************************************************************
943 * CURSORICON_IconToCursor
945 * Converts bitmap to mono and truncates if icon is too large (should
946 * probably do StretchBlt() instead).
948 HCURSOR16 CURSORICON_IconToCursor(HICON16 hIcon, BOOL bSemiTransparent)
950 HCURSOR16 hRet = 0;
951 CURSORICONINFO *pIcon = NULL;
952 HTASK16 hTask = GetCurrentTask();
953 TDB* pTask = (TDB *)GlobalLock16(hTask);
955 if(hIcon && pTask)
956 if (!(pIcon = (CURSORICONINFO*)GlobalLock16( hIcon ))) return FALSE;
957 if (pIcon->bPlanes * pIcon->bBitsPerPixel == 1)
959 hRet = CURSORICON_Copy( pTask->hInstance, hIcon );
962 pIcon = GlobalLock16(hRet);
964 pIcon->ptHotSpot.x = pIcon->ptHotSpot.y = 15;
966 GlobalUnlock16(hRet);
968 else
970 BYTE pAndBits[128];
971 BYTE pXorBits[128];
972 int maxx, maxy, ix, iy, bpp = pIcon->bBitsPerPixel;
973 BYTE* psPtr, *pxbPtr = pXorBits;
974 unsigned xor_width, and_width, val_base = 0xffffffff >> (32 - bpp);
975 BYTE* pbc = NULL;
977 CURSORICONINFO cI;
979 TRACE_(icon)("[%04x] %ix%i %ibpp (bogus %ibps)\n",
980 hIcon, pIcon->nWidth, pIcon->nHeight, pIcon->bBitsPerPixel, pIcon->nWidthBytes );
982 xor_width = BITMAP_GetWidthBytes( pIcon->nWidth, bpp );
983 and_width = BITMAP_GetWidthBytes( pIcon->nWidth, 1 );
984 psPtr = (BYTE *)(pIcon + 1) + pIcon->nHeight * and_width;
986 memset(pXorBits, 0, 128);
987 cI.bBitsPerPixel = 1; cI.bPlanes = 1;
988 cI.ptHotSpot.x = cI.ptHotSpot.y = 15;
989 cI.nWidth = 32; cI.nHeight = 32;
990 cI.nWidthBytes = 4; /* 32x1bpp */
992 maxx = (pIcon->nWidth > 32) ? 32 : pIcon->nWidth;
993 maxy = (pIcon->nHeight > 32) ? 32 : pIcon->nHeight;
995 for( iy = 0; iy < maxy; iy++ )
997 unsigned shift = iy % 2;
999 memcpy( pAndBits + iy * 4, (BYTE *)(pIcon + 1) + iy * and_width,
1000 (and_width > 4) ? 4 : and_width );
1001 for( ix = 0; ix < maxx; ix++ )
1003 if( bSemiTransparent && ((ix+shift)%2) )
1005 /* set AND bit, XOR bit stays 0 */
1007 pbc = pAndBits + iy * 4 + ix/8;
1008 *pbc |= 0x80 >> (ix%8);
1010 else
1012 /* keep AND bit, set XOR bit */
1014 unsigned *psc = (unsigned*)(psPtr + (ix * bpp)/8);
1015 unsigned val = ((*psc) >> (ix * bpp)%8) & val_base;
1016 if(!PALETTE_Driver->pIsDark(val))
1018 pbc = pxbPtr + ix/8;
1019 *pbc |= 0x80 >> (ix%8);
1023 psPtr += xor_width;
1024 pxbPtr += 4;
1027 hRet = CreateCursorIconIndirect16( pTask->hInstance , &cI, pAndBits, pXorBits);
1029 if( !hRet ) /* fall back on default drag cursor */
1030 hRet = CURSORICON_Copy( pTask->hInstance ,
1031 CURSORICON_Load(0,MAKEINTRESOURCEW(OCR_DRAGOBJECT),
1032 GetSystemMetrics(SM_CXCURSOR),
1033 GetSystemMetrics(SM_CYCURSOR), 1, TRUE, 0) );
1036 return hRet;
1040 /***********************************************************************
1041 * LoadCursor16 (USER.173)
1043 HCURSOR16 WINAPI LoadCursor16( HINSTANCE16 hInstance, SEGPTR name )
1045 LPCSTR nameStr = HIWORD(name)? PTR_SEG_TO_LIN(name) : (LPCSTR)name;
1046 return LoadCursorA( hInstance, nameStr );
1050 /***********************************************************************
1051 * LoadIcon16 (USER.174)
1053 HICON16 WINAPI LoadIcon16( HINSTANCE16 hInstance, SEGPTR name )
1055 LPCSTR nameStr = HIWORD(name)? PTR_SEG_TO_LIN(name) : (LPCSTR)name;
1056 return LoadIconA( hInstance, nameStr );
1060 /***********************************************************************
1061 * CreateCursor16 (USER.406)
1063 HCURSOR16 WINAPI CreateCursor16( HINSTANCE16 hInstance,
1064 INT16 xHotSpot, INT16 yHotSpot,
1065 INT16 nWidth, INT16 nHeight,
1066 LPCVOID lpANDbits, LPCVOID lpXORbits )
1068 CURSORICONINFO info;
1070 TRACE_(cursor)("%dx%d spot=%d,%d xor=%p and=%p\n",
1071 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
1073 info.ptHotSpot.x = xHotSpot;
1074 info.ptHotSpot.y = yHotSpot;
1075 info.nWidth = nWidth;
1076 info.nHeight = nHeight;
1077 info.nWidthBytes = 0;
1078 info.bPlanes = 1;
1079 info.bBitsPerPixel = 1;
1081 return CreateCursorIconIndirect16( hInstance, &info, lpANDbits, lpXORbits );
1085 /***********************************************************************
1086 * CreateCursor (USER32.67)
1088 HCURSOR WINAPI CreateCursor( HINSTANCE hInstance,
1089 INT xHotSpot, INT yHotSpot,
1090 INT nWidth, INT nHeight,
1091 LPCVOID lpANDbits, LPCVOID lpXORbits )
1093 CURSORICONINFO info;
1095 TRACE_(cursor)("%dx%d spot=%d,%d xor=%p and=%p\n",
1096 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
1098 info.ptHotSpot.x = xHotSpot;
1099 info.ptHotSpot.y = yHotSpot;
1100 info.nWidth = nWidth;
1101 info.nHeight = nHeight;
1102 info.nWidthBytes = 0;
1103 info.bPlanes = 1;
1104 info.bBitsPerPixel = 1;
1106 return CreateCursorIconIndirect16( 0, &info, lpANDbits, lpXORbits );
1110 /***********************************************************************
1111 * CreateIcon16 (USER.407)
1113 HICON16 WINAPI CreateIcon16( HINSTANCE16 hInstance, INT16 nWidth,
1114 INT16 nHeight, BYTE bPlanes, BYTE bBitsPixel,
1115 LPCVOID lpANDbits, LPCVOID lpXORbits )
1117 CURSORICONINFO info;
1119 TRACE_(icon)("%dx%dx%d, xor=%p, and=%p\n",
1120 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
1122 info.ptHotSpot.x = ICON_HOTSPOT;
1123 info.ptHotSpot.y = ICON_HOTSPOT;
1124 info.nWidth = nWidth;
1125 info.nHeight = nHeight;
1126 info.nWidthBytes = 0;
1127 info.bPlanes = bPlanes;
1128 info.bBitsPerPixel = bBitsPixel;
1130 return CreateCursorIconIndirect16( hInstance, &info, lpANDbits, lpXORbits );
1134 /***********************************************************************
1135 * CreateIcon (USER32.75)
1137 HICON WINAPI CreateIcon( HINSTANCE hInstance, INT nWidth,
1138 INT nHeight, BYTE bPlanes, BYTE bBitsPixel,
1139 LPCVOID lpANDbits, LPCVOID lpXORbits )
1141 CURSORICONINFO info;
1143 TRACE_(icon)("%dx%dx%d, xor=%p, and=%p\n",
1144 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
1146 info.ptHotSpot.x = ICON_HOTSPOT;
1147 info.ptHotSpot.y = ICON_HOTSPOT;
1148 info.nWidth = nWidth;
1149 info.nHeight = nHeight;
1150 info.nWidthBytes = 0;
1151 info.bPlanes = bPlanes;
1152 info.bBitsPerPixel = bBitsPixel;
1154 return CreateCursorIconIndirect16( 0, &info, lpANDbits, lpXORbits );
1158 /***********************************************************************
1159 * CreateCursorIconIndirect (USER.408)
1161 HGLOBAL16 WINAPI CreateCursorIconIndirect16( HINSTANCE16 hInstance,
1162 CURSORICONINFO *info,
1163 LPCVOID lpANDbits,
1164 LPCVOID lpXORbits )
1166 HGLOBAL16 handle;
1167 char *ptr;
1168 int sizeAnd, sizeXor;
1170 hInstance = GetExePtr( hInstance ); /* Make it a module handle */
1171 if (!lpXORbits || !lpANDbits || info->bPlanes != 1) return 0;
1172 info->nWidthBytes = BITMAP_GetWidthBytes(info->nWidth,info->bBitsPerPixel);
1173 sizeXor = info->nHeight * info->nWidthBytes;
1174 sizeAnd = info->nHeight * BITMAP_GetWidthBytes( info->nWidth, 1 );
1175 if (!(handle = GlobalAlloc16( GMEM_MOVEABLE,
1176 sizeof(CURSORICONINFO) + sizeXor + sizeAnd)))
1177 return 0;
1178 if (hInstance) FarSetOwner16( handle, hInstance );
1179 ptr = (char *)GlobalLock16( handle );
1180 memcpy( ptr, info, sizeof(*info) );
1181 memcpy( ptr + sizeof(CURSORICONINFO), lpANDbits, sizeAnd );
1182 memcpy( ptr + sizeof(CURSORICONINFO) + sizeAnd, lpXORbits, sizeXor );
1183 GlobalUnlock16( handle );
1184 return handle;
1188 /***********************************************************************
1189 * CopyIcon16 (USER.368)
1191 HICON16 WINAPI CopyIcon16( HINSTANCE16 hInstance, HICON16 hIcon )
1193 TRACE_(icon)("%04x %04x\n", hInstance, hIcon );
1194 return CURSORICON_Copy( hInstance, hIcon );
1198 /***********************************************************************
1199 * CopyIcon (USER32.60)
1201 HICON WINAPI CopyIcon( HICON hIcon )
1203 HTASK16 hTask = GetCurrentTask ();
1204 TDB* pTask = (TDB *) GlobalLock16 (hTask);
1205 TRACE_(icon)("%04x\n", hIcon );
1206 return CURSORICON_Copy( pTask->hInstance, hIcon );
1210 /***********************************************************************
1211 * CopyCursor16 (USER.369)
1213 HCURSOR16 WINAPI CopyCursor16( HINSTANCE16 hInstance, HCURSOR16 hCursor )
1215 TRACE_(cursor)("%04x %04x\n", hInstance, hCursor );
1216 return CURSORICON_Copy( hInstance, hCursor );
1219 /**********************************************************************
1220 * CURSORICON_Destroy (USER.610)
1222 * This routine is actually exported from Win95 USER under the name
1223 * DestroyIcon32 ... The behaviour implemented here should mimic
1224 * the Win95 one exactly, especially the return values, which
1225 * depend on the setting of various flags.
1227 WORD WINAPI CURSORICON_Destroy( HGLOBAL16 handle, UINT16 flags )
1229 WORD retv;
1231 TRACE_(icon)("(%04x, %04x)\n", handle, flags );
1233 /* Check whether destroying active cursor */
1235 if ( hActiveCursor == handle )
1237 ERR_(cursor)("Destroying active cursor!\n" );
1238 SetCursor( 0 );
1241 /* Try shared cursor/icon first */
1243 if ( !(flags & CID_NONSHARED) )
1245 INT count = CURSORICON_DelSharedIcon( handle );
1247 if ( count != -1 )
1248 return (flags & CID_WIN32)? TRUE : (count == 0);
1250 /* FIXME: OEM cursors/icons should be recognized */
1253 /* Now assume non-shared cursor/icon */
1255 retv = GlobalFree16( handle );
1256 return (flags & CID_RESOURCE)? retv : TRUE;
1259 /***********************************************************************
1260 * DestroyIcon16 (USER.457)
1262 BOOL16 WINAPI DestroyIcon16( HICON16 hIcon )
1264 return CURSORICON_Destroy( hIcon, 0 );
1267 /***********************************************************************
1268 * DestroyIcon (USER32.133)
1270 BOOL WINAPI DestroyIcon( HICON hIcon )
1272 return CURSORICON_Destroy( hIcon, CID_WIN32 );
1275 /***********************************************************************
1276 * DestroyCursor16 (USER.458)
1278 BOOL16 WINAPI DestroyCursor16( HCURSOR16 hCursor )
1280 return CURSORICON_Destroy( hCursor, 0 );
1283 /***********************************************************************
1284 * DestroyCursor (USER32.132)
1286 BOOL WINAPI DestroyCursor( HCURSOR hCursor )
1288 return CURSORICON_Destroy( hCursor, CID_WIN32 );
1292 /***********************************************************************
1293 * DrawIcon16 (USER.84)
1295 BOOL16 WINAPI DrawIcon16( HDC16 hdc, INT16 x, INT16 y, HICON16 hIcon )
1297 return DrawIcon( hdc, x, y, hIcon );
1301 /***********************************************************************
1302 * DrawIcon (USER32.159)
1304 BOOL WINAPI DrawIcon( HDC hdc, INT x, INT y, HICON hIcon )
1306 CURSORICONINFO *ptr;
1307 HDC hMemDC;
1308 HBITMAP hXorBits, hAndBits;
1309 COLORREF oldFg, oldBg;
1311 if (!(ptr = (CURSORICONINFO *)GlobalLock16( hIcon ))) return FALSE;
1312 if (!(hMemDC = CreateCompatibleDC( hdc ))) return FALSE;
1313 hAndBits = CreateBitmap( ptr->nWidth, ptr->nHeight, 1, 1,
1314 (char *)(ptr+1) );
1315 hXorBits = CreateBitmap( ptr->nWidth, ptr->nHeight, ptr->bPlanes,
1316 ptr->bBitsPerPixel, (char *)(ptr + 1)
1317 + ptr->nHeight * BITMAP_GetWidthBytes(ptr->nWidth,1) );
1318 oldFg = SetTextColor( hdc, RGB(0,0,0) );
1319 oldBg = SetBkColor( hdc, RGB(255,255,255) );
1321 if (hXorBits && hAndBits)
1323 HBITMAP hBitTemp = SelectObject( hMemDC, hAndBits );
1324 BitBlt( hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0, SRCAND );
1325 SelectObject( hMemDC, hXorBits );
1326 BitBlt(hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0,SRCINVERT);
1327 SelectObject( hMemDC, hBitTemp );
1329 DeleteDC( hMemDC );
1330 if (hXorBits) DeleteObject( hXorBits );
1331 if (hAndBits) DeleteObject( hAndBits );
1332 GlobalUnlock16( hIcon );
1333 SetTextColor( hdc, oldFg );
1334 SetBkColor( hdc, oldBg );
1335 return TRUE;
1339 /***********************************************************************
1340 * IconSize16 (USER.86)
1342 * See "Undocumented Windows". Used by W2.0 paint.exe.
1344 DWORD WINAPI IconSize16( void )
1346 return MAKELONG(GetSystemMetrics(SM_CYICON), GetSystemMetrics(SM_CXICON));
1350 /***********************************************************************
1351 * DumpIcon (USER.459)
1353 DWORD WINAPI DumpIcon16( SEGPTR pInfo, WORD *lpLen,
1354 SEGPTR *lpXorBits, SEGPTR *lpAndBits )
1356 CURSORICONINFO *info = PTR_SEG_TO_LIN( pInfo );
1357 int sizeAnd, sizeXor;
1359 if (!info) return 0;
1360 sizeXor = info->nHeight * info->nWidthBytes;
1361 sizeAnd = info->nHeight * BITMAP_GetWidthBytes( info->nWidth, 1 );
1362 if (lpAndBits) *lpAndBits = pInfo + sizeof(CURSORICONINFO);
1363 if (lpXorBits) *lpXorBits = pInfo + sizeof(CURSORICONINFO) + sizeAnd;
1364 if (lpLen) *lpLen = sizeof(CURSORICONINFO) + sizeAnd + sizeXor;
1365 return MAKELONG( sizeXor, sizeXor );
1369 /***********************************************************************
1370 * SetCursor16 (USER.69)
1372 HCURSOR16 WINAPI SetCursor16( HCURSOR16 hCursor )
1374 return (HCURSOR16)SetCursor( hCursor );
1378 /***********************************************************************
1379 * SetCursor (USER32.472)
1380 * RETURNS:
1381 * A handle to the previous cursor shape.
1383 HCURSOR WINAPI SetCursor(
1384 HCURSOR hCursor /* Handle of cursor to show */
1386 HCURSOR hOldCursor;
1388 if (hCursor == hActiveCursor) return hActiveCursor; /* No change */
1389 TRACE_(cursor)("%04x\n", hCursor );
1390 hOldCursor = hActiveCursor;
1391 hActiveCursor = hCursor;
1392 /* Change the cursor shape only if it is visible */
1393 if (CURSOR_ShowCount >= 0)
1395 USER_Driver.pSetCursor( (CURSORICONINFO*)GlobalLock16( hActiveCursor ) );
1396 GlobalUnlock16( hActiveCursor );
1398 return hOldCursor;
1402 /***********************************************************************
1403 * SetCursorPos16 (USER.70)
1405 void WINAPI SetCursorPos16( INT16 x, INT16 y )
1407 SetCursorPos( x, y );
1411 /***********************************************************************
1412 * SetCursorPos (USER32.474)
1414 BOOL WINAPI SetCursorPos( INT x, INT y )
1416 USER_Driver.pMoveCursor( x, y );
1417 return TRUE;
1421 /***********************************************************************
1422 * ShowCursor16 (USER.71)
1424 INT16 WINAPI ShowCursor16( BOOL16 bShow )
1426 return ShowCursor( bShow );
1430 /***********************************************************************
1431 * ShowCursor (USER32.530)
1433 INT WINAPI ShowCursor( BOOL bShow )
1435 TRACE_(cursor)("%d, count=%d\n",
1436 bShow, CURSOR_ShowCount );
1438 if (bShow)
1440 if (++CURSOR_ShowCount == 0) /* Show it */
1442 USER_Driver.pSetCursor( (CURSORICONINFO*)GlobalLock16( hActiveCursor ) );
1443 GlobalUnlock16( hActiveCursor );
1446 else
1448 if (--CURSOR_ShowCount == -1) /* Hide it */
1449 USER_Driver.pSetCursor( NULL );
1451 return CURSOR_ShowCount;
1455 /***********************************************************************
1456 * GetCursor16 (USER.247)
1458 HCURSOR16 WINAPI GetCursor16(void)
1460 return hActiveCursor;
1464 /***********************************************************************
1465 * GetCursor (USER32.227)
1467 HCURSOR WINAPI GetCursor(void)
1469 return hActiveCursor;
1473 /***********************************************************************
1474 * ClipCursor16 (USER.16)
1476 BOOL16 WINAPI ClipCursor16( const RECT16 *rect )
1478 if (!rect) SetRectEmpty( &CURSOR_ClipRect );
1479 else CONV_RECT16TO32( rect, &CURSOR_ClipRect );
1480 return TRUE;
1484 /***********************************************************************
1485 * ClipCursor (USER32.53)
1487 BOOL WINAPI ClipCursor( const RECT *rect )
1489 if (!rect) SetRectEmpty( &CURSOR_ClipRect );
1490 else CopyRect( &CURSOR_ClipRect, rect );
1491 return TRUE;
1495 /***********************************************************************
1496 * GetCursorPos16 (USER.17)
1498 BOOL16 WINAPI GetCursorPos16( POINT16 *pt )
1500 if (!pt) return 0;
1502 pt->x = PosX;
1503 pt->y = PosY;
1505 TRACE_(cursor)("ret=%d,%d\n", pt->x, pt->y );
1506 return 1;
1510 /***********************************************************************
1511 * GetCursorPos (USER32.229)
1513 BOOL WINAPI GetCursorPos( POINT *pt )
1515 BOOL ret;
1517 POINT16 pt16;
1518 ret = GetCursorPos16( &pt16 );
1519 if (pt) CONV_POINT16TO32( &pt16, pt );
1520 return ((pt) ? ret : 0);
1524 /***********************************************************************
1525 * GetClipCursor16 (USER.309)
1527 void WINAPI GetClipCursor16( RECT16 *rect )
1529 if (rect) CONV_RECT32TO16( &CURSOR_ClipRect, rect );
1533 /***********************************************************************
1534 * GetClipCursor (USER32.221)
1536 BOOL WINAPI GetClipCursor( RECT *rect )
1538 if (rect)
1540 CopyRect( rect, &CURSOR_ClipRect );
1541 return TRUE;
1543 return FALSE;
1546 /**********************************************************************
1547 * LookupIconIdFromDirectoryEx16 (USER.364)
1549 * FIXME: exact parameter sizes
1551 INT16 WINAPI LookupIconIdFromDirectoryEx16( LPBYTE xdir, BOOL16 bIcon,
1552 INT16 width, INT16 height, UINT16 cFlag )
1554 CURSORICONDIR *dir = (CURSORICONDIR*)xdir;
1555 UINT16 retVal = 0;
1556 if( dir && !dir->idReserved && (dir->idType & 3) )
1558 CURSORICONDIRENTRY* entry;
1559 HDC hdc;
1560 UINT palEnts;
1561 int colors;
1562 hdc = GetDC(0);
1563 palEnts = GetSystemPaletteEntries(hdc, 0, 0, NULL);
1564 if (palEnts == 0)
1565 palEnts = 256;
1566 colors = (cFlag & LR_MONOCHROME) ? 2 : palEnts;
1568 ReleaseDC(0, hdc);
1570 if( bIcon )
1571 entry = CURSORICON_FindBestIcon( dir, width, height, colors );
1572 else
1573 entry = CURSORICON_FindBestCursor( dir, width, height, 1);
1575 if( entry ) retVal = entry->wResId;
1577 else WARN_(cursor)("invalid resource directory\n");
1578 return retVal;
1581 /**********************************************************************
1582 * LookupIconIdFromDirectoryEx (USER32.380)
1584 INT WINAPI LookupIconIdFromDirectoryEx( LPBYTE dir, BOOL bIcon,
1585 INT width, INT height, UINT cFlag )
1587 return LookupIconIdFromDirectoryEx16( dir, bIcon, width, height, cFlag );
1590 /**********************************************************************
1591 * LookupIconIdFromDirectory (USER.???)
1593 INT16 WINAPI LookupIconIdFromDirectory16( LPBYTE dir, BOOL16 bIcon )
1595 return LookupIconIdFromDirectoryEx16( dir, bIcon,
1596 bIcon ? GetSystemMetrics(SM_CXICON) : GetSystemMetrics(SM_CXCURSOR),
1597 bIcon ? GetSystemMetrics(SM_CYICON) : GetSystemMetrics(SM_CYCURSOR), bIcon ? 0 : LR_MONOCHROME );
1600 /**********************************************************************
1601 * LookupIconIdFromDirectory (USER32.379)
1603 INT WINAPI LookupIconIdFromDirectory( LPBYTE dir, BOOL bIcon )
1605 return LookupIconIdFromDirectoryEx( dir, bIcon,
1606 bIcon ? GetSystemMetrics(SM_CXICON) : GetSystemMetrics(SM_CXCURSOR),
1607 bIcon ? GetSystemMetrics(SM_CYICON) : GetSystemMetrics(SM_CYCURSOR), bIcon ? 0 : LR_MONOCHROME );
1610 /**********************************************************************
1611 * GetIconID (USER.455)
1613 WORD WINAPI GetIconID16( HGLOBAL16 hResource, DWORD resType )
1615 LPBYTE lpDir = (LPBYTE)GlobalLock16(hResource);
1617 TRACE_(cursor)("hRes=%04x, entries=%i\n",
1618 hResource, lpDir ? ((CURSORICONDIR*)lpDir)->idCount : 0);
1620 switch(resType)
1622 case RT_CURSOR16:
1623 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, FALSE,
1624 GetSystemMetrics(SM_CXCURSOR), GetSystemMetrics(SM_CYCURSOR), LR_MONOCHROME );
1625 case RT_ICON16:
1626 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, TRUE,
1627 GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), 0 );
1628 default:
1629 WARN_(cursor)("invalid res type %ld\n", resType );
1631 return 0;
1634 /**********************************************************************
1635 * LoadCursorIconHandler (USER.336)
1637 * Supposed to load resources of Windows 2.x applications.
1639 HGLOBAL16 WINAPI LoadCursorIconHandler16( HGLOBAL16 hResource, HMODULE16 hModule, HRSRC16 hRsrc )
1641 FIXME_(cursor)("(%04x,%04x,%04x): old 2.x resources are not supported!\n",
1642 hResource, hModule, hRsrc);
1643 return (HGLOBAL16)0;
1646 /**********************************************************************
1647 * LoadDIBIconHandler (USER.357)
1649 * RT_ICON resource loader, installed by USER_SignalProc when module
1650 * is initialized.
1652 HGLOBAL16 WINAPI LoadDIBIconHandler16( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1654 /* If hResource is zero we must allocate a new memory block, if it's
1655 * non-zero but GlobalLock() returns NULL then it was discarded and
1656 * we have to recommit some memory, otherwise we just need to check
1657 * the block size. See LoadProc() in 16-bit SDK for more.
1660 hMemObj = NE_DefResourceHandler( hMemObj, hModule, hRsrc );
1661 if( hMemObj )
1663 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1664 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1665 SizeofResource16(hModule, hRsrc), TRUE, 0x00030000,
1666 GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), LR_DEFAULTCOLOR );
1668 return hMemObj;
1671 /**********************************************************************
1672 * LoadDIBCursorHandler (USER.356)
1674 * RT_CURSOR resource loader. Same as above.
1676 HGLOBAL16 WINAPI LoadDIBCursorHandler16( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1678 hMemObj = NE_DefResourceHandler( hMemObj, hModule, hRsrc );
1679 if( hMemObj )
1681 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1682 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1683 SizeofResource16(hModule, hRsrc), FALSE, 0x00030000,
1684 GetSystemMetrics(SM_CXCURSOR), GetSystemMetrics(SM_CYCURSOR), LR_MONOCHROME );
1686 return hMemObj;
1689 /**********************************************************************
1690 * LoadIconHandler (USER.456)
1692 HICON16 WINAPI LoadIconHandler16( HGLOBAL16 hResource, BOOL16 bNew )
1694 LPBYTE bits = (LPBYTE)LockResource16( hResource );
1696 TRACE_(cursor)("hRes=%04x\n",hResource);
1698 return CURSORICON_CreateFromResource( 0, 0, bits, 0, TRUE,
1699 bNew ? 0x00030000 : 0x00020000, 0, 0, LR_DEFAULTCOLOR );
1702 /***********************************************************************
1703 * LoadCursorW (USER32.362)
1705 HCURSOR WINAPI LoadCursorW(HINSTANCE hInstance, LPCWSTR name)
1707 return LoadImageW( hInstance, name, IMAGE_CURSOR, 0, 0,
1708 LR_SHARED | LR_DEFAULTSIZE );
1711 /***********************************************************************
1712 * LoadCursorA (USER32.359)
1714 HCURSOR WINAPI LoadCursorA(HINSTANCE hInstance, LPCSTR name)
1716 return LoadImageA( hInstance, name, IMAGE_CURSOR, 0, 0,
1717 LR_SHARED | LR_DEFAULTSIZE );
1720 /***********************************************************************
1721 * LoadCursorFromFileW (USER32.361)
1723 HCURSOR WINAPI LoadCursorFromFileW (LPCWSTR name)
1725 return LoadImageW( 0, name, IMAGE_CURSOR, 0, 0,
1726 LR_LOADFROMFILE | LR_DEFAULTSIZE );
1729 /***********************************************************************
1730 * LoadCursorFromFileA (USER32.360)
1732 HCURSOR WINAPI LoadCursorFromFileA (LPCSTR name)
1734 return LoadImageA( 0, name, IMAGE_CURSOR, 0, 0,
1735 LR_LOADFROMFILE | LR_DEFAULTSIZE );
1738 /***********************************************************************
1739 * LoadIconW (USER32.364)
1741 HICON WINAPI LoadIconW(HINSTANCE hInstance, LPCWSTR name)
1743 return LoadImageW( hInstance, name, IMAGE_ICON, 0, 0,
1744 LR_SHARED | LR_DEFAULTSIZE );
1747 /***********************************************************************
1748 * LoadIconA (USER32.363)
1750 HICON WINAPI LoadIconA(HINSTANCE hInstance, LPCSTR name)
1752 return LoadImageA( hInstance, name, IMAGE_ICON, 0, 0,
1753 LR_SHARED | LR_DEFAULTSIZE );
1756 /**********************************************************************
1757 * GetIconInfo16 (USER.395)
1759 BOOL16 WINAPI GetIconInfo16(HICON16 hIcon,LPICONINFO16 iconinfo)
1761 ICONINFO ii32;
1762 BOOL16 ret = GetIconInfo((HICON)hIcon, &ii32);
1764 iconinfo->fIcon = ii32.fIcon;
1765 iconinfo->xHotspot = ii32.xHotspot;
1766 iconinfo->yHotspot = ii32.yHotspot;
1767 iconinfo->hbmMask = ii32.hbmMask;
1768 iconinfo->hbmColor = ii32.hbmColor;
1769 return ret;
1772 /**********************************************************************
1773 * GetIconInfo (USER32.242)
1775 BOOL WINAPI GetIconInfo(HICON hIcon,PICONINFO iconinfo) {
1776 CURSORICONINFO *ciconinfo;
1778 ciconinfo = GlobalLock16(hIcon);
1779 if (!ciconinfo)
1780 return FALSE;
1782 if ( (ciconinfo->ptHotSpot.x == ICON_HOTSPOT) &&
1783 (ciconinfo->ptHotSpot.y == ICON_HOTSPOT) )
1785 iconinfo->fIcon = TRUE;
1786 iconinfo->xHotspot = ciconinfo->nWidth / 2;
1787 iconinfo->yHotspot = ciconinfo->nHeight / 2;
1789 else
1791 iconinfo->fIcon = FALSE;
1792 iconinfo->xHotspot = ciconinfo->ptHotSpot.x;
1793 iconinfo->yHotspot = ciconinfo->ptHotSpot.y;
1796 iconinfo->hbmColor = CreateBitmap ( ciconinfo->nWidth, ciconinfo->nHeight,
1797 ciconinfo->bPlanes, ciconinfo->bBitsPerPixel,
1798 (char *)(ciconinfo + 1)
1799 + ciconinfo->nHeight *
1800 BITMAP_GetWidthBytes (ciconinfo->nWidth,1) );
1801 iconinfo->hbmMask = CreateBitmap ( ciconinfo->nWidth, ciconinfo->nHeight,
1802 1, 1, (char *)(ciconinfo + 1));
1804 GlobalUnlock16(hIcon);
1806 return TRUE;
1809 /**********************************************************************
1810 * CreateIconIndirect (USER32.78)
1812 HICON WINAPI CreateIconIndirect(PICONINFO iconinfo)
1814 BITMAP bmpXor,bmpAnd;
1815 HICON hObj;
1816 int sizeXor,sizeAnd;
1818 GetObjectA( iconinfo->hbmColor, sizeof(bmpXor), &bmpXor );
1819 GetObjectA( iconinfo->hbmMask, sizeof(bmpAnd), &bmpAnd );
1821 sizeXor = bmpXor.bmHeight * bmpXor.bmWidthBytes;
1822 sizeAnd = bmpAnd.bmHeight * bmpAnd.bmWidthBytes;
1824 hObj = GlobalAlloc16( GMEM_MOVEABLE,
1825 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
1826 if (hObj)
1828 CURSORICONINFO *info;
1830 info = (CURSORICONINFO *)GlobalLock16( hObj );
1832 /* If we are creating an icon, the hotspot is unused */
1833 if (iconinfo->fIcon)
1835 info->ptHotSpot.x = ICON_HOTSPOT;
1836 info->ptHotSpot.y = ICON_HOTSPOT;
1838 else
1840 info->ptHotSpot.x = iconinfo->xHotspot;
1841 info->ptHotSpot.y = iconinfo->yHotspot;
1844 info->nWidth = bmpXor.bmWidth;
1845 info->nHeight = bmpXor.bmHeight;
1846 info->nWidthBytes = bmpXor.bmWidthBytes;
1847 info->bPlanes = bmpXor.bmPlanes;
1848 info->bBitsPerPixel = bmpXor.bmBitsPixel;
1850 /* Transfer the bitmap bits to the CURSORICONINFO structure */
1852 GetBitmapBits( iconinfo->hbmMask ,sizeAnd,(char*)(info + 1) );
1853 GetBitmapBits( iconinfo->hbmColor,sizeXor,(char*)(info + 1) +sizeAnd);
1854 GlobalUnlock16( hObj );
1856 return hObj;
1860 /**********************************************************************
1862 DrawIconEx16 (USER.394)
1864 BOOL16 WINAPI DrawIconEx16 (HDC16 hdc, INT16 xLeft, INT16 yTop, HICON16 hIcon,
1865 INT16 cxWidth, INT16 cyWidth, UINT16 istep,
1866 HBRUSH16 hbr, UINT16 flags)
1868 return DrawIconEx(hdc, xLeft, yTop, hIcon, cxWidth, cyWidth,
1869 istep, hbr, flags);
1873 /******************************************************************************
1874 * DrawIconEx [USER32.160] Draws an icon or cursor on device context
1876 * NOTES
1877 * Why is this using SM_CXICON instead of SM_CXCURSOR?
1879 * PARAMS
1880 * hdc [I] Handle to device context
1881 * x0 [I] X coordinate of upper left corner
1882 * y0 [I] Y coordinate of upper left corner
1883 * hIcon [I] Handle to icon to draw
1884 * cxWidth [I] Width of icon
1885 * cyWidth [I] Height of icon
1886 * istep [I] Index of frame in animated cursor
1887 * hbr [I] Handle to background brush
1888 * flags [I] Icon-drawing flags
1890 * RETURNS
1891 * Success: TRUE
1892 * Failure: FALSE
1894 BOOL WINAPI DrawIconEx( HDC hdc, INT x0, INT y0, HICON hIcon,
1895 INT cxWidth, INT cyWidth, UINT istep,
1896 HBRUSH hbr, UINT flags )
1898 CURSORICONINFO *ptr = (CURSORICONINFO *)GlobalLock16 (hIcon);
1899 HDC hDC_off = 0, hMemDC = CreateCompatibleDC (hdc);
1900 BOOL result = FALSE, DoOffscreen;
1901 HBITMAP hB_off = 0, hOld = 0;
1903 if (!ptr) return FALSE;
1904 TRACE_(icon)("(hdc=%x,pos=%d.%d,hicon=%x,extend=%d.%d,istep=%d,br=%x,flags=0x%08x)\n",
1905 hdc,x0,y0,hIcon,cxWidth,cyWidth,istep,hbr,flags
1908 if (istep)
1909 FIXME_(icon)("Ignoring istep=%d\n", istep);
1910 if (flags & DI_COMPAT)
1911 FIXME_(icon)("Ignoring flag DI_COMPAT\n");
1913 if (!flags) {
1914 FIXME_(icon)("no flags set? setting to DI_NORMAL\n");
1915 flags = DI_NORMAL;
1918 /* Calculate the size of the destination image. */
1919 if (cxWidth == 0)
1921 if (flags & DI_DEFAULTSIZE)
1922 cxWidth = GetSystemMetrics (SM_CXICON);
1923 else
1924 cxWidth = ptr->nWidth;
1926 if (cyWidth == 0)
1928 if (flags & DI_DEFAULTSIZE)
1929 cyWidth = GetSystemMetrics (SM_CYICON);
1930 else
1931 cyWidth = ptr->nHeight;
1934 DoOffscreen = (GetObjectType( hbr ) == OBJ_BRUSH);
1936 if (DoOffscreen) {
1937 RECT r;
1939 r.left = 0;
1940 r.top = 0;
1941 r.right = cxWidth;
1942 r.bottom = cxWidth;
1944 hDC_off = CreateCompatibleDC(hdc);
1945 hB_off = CreateCompatibleBitmap(hdc, cxWidth, cyWidth);
1946 if (hDC_off && hB_off) {
1947 hOld = SelectObject(hDC_off, hB_off);
1948 FillRect(hDC_off, &r, hbr);
1952 if (hMemDC && (!DoOffscreen || (hDC_off && hB_off)))
1954 HBITMAP hXorBits, hAndBits;
1955 COLORREF oldFg, oldBg;
1956 INT nStretchMode;
1958 nStretchMode = SetStretchBltMode (hdc, STRETCH_DELETESCANS);
1960 hXorBits = CreateBitmap ( ptr->nWidth, ptr->nHeight,
1961 ptr->bPlanes, ptr->bBitsPerPixel,
1962 (char *)(ptr + 1)
1963 + ptr->nHeight *
1964 BITMAP_GetWidthBytes(ptr->nWidth,1) );
1965 hAndBits = CreateBitmap ( ptr->nWidth, ptr->nHeight,
1966 1, 1, (char *)(ptr+1) );
1967 oldFg = SetTextColor( hdc, RGB(0,0,0) );
1968 oldBg = SetBkColor( hdc, RGB(255,255,255) );
1970 if (hXorBits && hAndBits)
1972 HBITMAP hBitTemp = SelectObject( hMemDC, hAndBits );
1973 if (flags & DI_MASK)
1975 if (DoOffscreen)
1976 StretchBlt (hDC_off, 0, 0, cxWidth, cyWidth,
1977 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
1978 else
1979 StretchBlt (hdc, x0, y0, cxWidth, cyWidth,
1980 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
1982 SelectObject( hMemDC, hXorBits );
1983 if (flags & DI_IMAGE)
1985 if (DoOffscreen)
1986 StretchBlt (hDC_off, 0, 0, cxWidth, cyWidth,
1987 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
1988 else
1989 StretchBlt (hdc, x0, y0, cxWidth, cyWidth,
1990 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
1992 SelectObject( hMemDC, hBitTemp );
1993 result = TRUE;
1996 SetTextColor( hdc, oldFg );
1997 SetBkColor( hdc, oldBg );
1998 if (hXorBits) DeleteObject( hXorBits );
1999 if (hAndBits) DeleteObject( hAndBits );
2000 SetStretchBltMode (hdc, nStretchMode);
2001 if (DoOffscreen) {
2002 BitBlt(hdc, x0, y0, cxWidth, cyWidth, hDC_off, 0, 0, SRCCOPY);
2003 SelectObject(hDC_off, hOld);
2006 if (hMemDC) DeleteDC( hMemDC );
2007 if (hDC_off) DeleteDC(hDC_off);
2008 if (hB_off) DeleteObject(hB_off);
2009 GlobalUnlock16( hIcon );
2010 return result;
2013 /***********************************************************************
2014 * DIB_FixColorsToLoadflags
2016 * Change color table entries when LR_LOADTRANSPARENT or LR_LOADMAP3DCOLORS
2017 * are in loadflags
2019 static void DIB_FixColorsToLoadflags(BITMAPINFO * bmi, UINT loadflags, BYTE pix)
2021 int colors;
2022 COLORREF c_W, c_S, c_F, c_L, c_C;
2023 int incr,i;
2024 RGBQUAD *ptr;
2026 if (bmi->bmiHeader.biBitCount > 8) return;
2027 if (bmi->bmiHeader.biSize == sizeof(BITMAPINFOHEADER)) incr = 4;
2028 else if (bmi->bmiHeader.biSize == sizeof(BITMAPCOREHEADER)) incr = 3;
2029 else {
2030 WARN_(resource)("Wrong bitmap header size!\n");
2031 return;
2033 colors = bmi->bmiHeader.biClrUsed;
2034 if (!colors && (bmi->bmiHeader.biBitCount <= 8))
2035 colors = 1 << bmi->bmiHeader.biBitCount;
2036 c_W = GetSysColor(COLOR_WINDOW);
2037 c_S = GetSysColor(COLOR_3DSHADOW);
2038 c_F = GetSysColor(COLOR_3DFACE);
2039 c_L = GetSysColor(COLOR_3DLIGHT);
2040 if (loadflags & LR_LOADTRANSPARENT) {
2041 switch (bmi->bmiHeader.biBitCount) {
2042 case 1: pix = pix >> 7; break;
2043 case 4: pix = pix >> 4; break;
2044 case 8: break;
2045 default:
2046 WARN_(resource)("(%d): Unsupported depth\n", bmi->bmiHeader.biBitCount);
2047 return;
2049 if (pix >= colors) {
2050 WARN_(resource)("pixel has color index greater than biClrUsed!\n");
2051 return;
2053 if (loadflags & LR_LOADMAP3DCOLORS) c_W = c_F;
2054 ptr = (RGBQUAD*)((char*)bmi->bmiColors+pix*incr);
2055 ptr->rgbBlue = GetBValue(c_W);
2056 ptr->rgbGreen = GetGValue(c_W);
2057 ptr->rgbRed = GetRValue(c_W);
2059 if (loadflags & LR_LOADMAP3DCOLORS)
2060 for (i=0; i<colors; i++) {
2061 ptr = (RGBQUAD*)((char*)bmi->bmiColors+i*incr);
2062 c_C = RGB(ptr->rgbRed, ptr->rgbGreen, ptr->rgbBlue);
2063 if (c_C == RGB(128, 128, 128)) {
2064 ptr->rgbRed = GetRValue(c_S);
2065 ptr->rgbGreen = GetGValue(c_S);
2066 ptr->rgbBlue = GetBValue(c_S);
2067 } else if (c_C == RGB(192, 192, 192)) {
2068 ptr->rgbRed = GetRValue(c_F);
2069 ptr->rgbGreen = GetGValue(c_F);
2070 ptr->rgbBlue = GetBValue(c_F);
2071 } else if (c_C == RGB(223, 223, 223)) {
2072 ptr->rgbRed = GetRValue(c_L);
2073 ptr->rgbGreen = GetGValue(c_L);
2074 ptr->rgbBlue = GetBValue(c_L);
2080 /**********************************************************************
2081 * BITMAP_Load
2083 static HBITMAP BITMAP_Load( HINSTANCE instance,LPCWSTR name, UINT loadflags )
2085 HBITMAP hbitmap = 0;
2086 HDC hdc;
2087 HRSRC hRsrc;
2088 HGLOBAL handle;
2089 char *ptr = NULL;
2090 BITMAPINFO *info, *fix_info=NULL;
2091 HGLOBAL hFix;
2092 int size;
2094 if (!(loadflags & LR_LOADFROMFILE)) {
2095 if (!instance) /* OEM bitmap */
2097 if (HIWORD((int)name)) return 0;
2098 return USER_Driver.pLoadOEMResource( LOWORD((int)name), OEM_BITMAP );
2101 if (!(hRsrc = FindResourceW( instance, name, RT_BITMAPW ))) return 0;
2102 if (!(handle = LoadResource( instance, hRsrc ))) return 0;
2104 if ((info = (BITMAPINFO *)LockResource( handle )) == NULL) return 0;
2106 else
2108 if (!(ptr = (char *)VIRTUAL_MapFileW( name ))) return 0;
2109 info = (BITMAPINFO *)(ptr + sizeof(BITMAPFILEHEADER));
2111 size = DIB_BitmapInfoSize(info, DIB_RGB_COLORS);
2112 if ((hFix = GlobalAlloc(0, size))) fix_info=GlobalLock(hFix);
2113 if (fix_info) {
2114 BYTE pix;
2116 memcpy(fix_info, info, size);
2117 pix = *((LPBYTE)info+DIB_BitmapInfoSize(info, DIB_RGB_COLORS));
2118 DIB_FixColorsToLoadflags(fix_info, loadflags, pix);
2119 if ((hdc = GetDC(0)) != 0) {
2120 char *bits = (char *)info + size;
2121 if (loadflags & LR_CREATEDIBSECTION) {
2122 DIBSECTION dib;
2123 hbitmap = CreateDIBSection(hdc, fix_info, DIB_RGB_COLORS, NULL, 0, 0);
2124 GetObjectA(hbitmap, sizeof(DIBSECTION), &dib);
2125 SetDIBits(hdc, hbitmap, 0, dib.dsBm.bmHeight, bits, info,
2126 DIB_RGB_COLORS);
2128 else {
2129 hbitmap = CreateDIBitmap( hdc, &fix_info->bmiHeader, CBM_INIT,
2130 bits, fix_info, DIB_RGB_COLORS );
2132 ReleaseDC( 0, hdc );
2134 GlobalUnlock(hFix);
2135 GlobalFree(hFix);
2137 if (loadflags & LR_LOADFROMFILE) UnmapViewOfFile( ptr );
2138 return hbitmap;
2142 /***********************************************************************
2143 * LoadImage16 [USER.389]
2146 HANDLE16 WINAPI LoadImage16( HINSTANCE16 hinst, LPCSTR name, UINT16 type,
2147 INT16 desiredx, INT16 desiredy, UINT16 loadflags)
2149 LPCSTR nameStr = HIWORD(name)? PTR_SEG_TO_LIN(name) : (LPCSTR)name;
2150 return LoadImageA( hinst, nameStr, type,
2151 desiredx, desiredy, loadflags );
2154 /**********************************************************************
2155 * LoadImageA (USER32.365)
2157 * FIXME: implementation lacks some features, see LR_ defines in windows.h
2160 HANDLE WINAPI LoadImageA( HINSTANCE hinst, LPCSTR name, UINT type,
2161 INT desiredx, INT desiredy, UINT loadflags)
2163 HANDLE res;
2164 LPWSTR u_name;
2166 if (HIWORD(name)) u_name = HEAP_strdupAtoW(GetProcessHeap(), 0, name);
2167 else u_name=(LPWSTR)name;
2168 res = LoadImageW(hinst, u_name, type, desiredx, desiredy, loadflags);
2169 if (HIWORD(name)) HeapFree(GetProcessHeap(), 0, u_name);
2170 return res;
2174 /******************************************************************************
2175 * LoadImageW [USER32.366] Loads an icon, cursor, or bitmap
2177 * PARAMS
2178 * hinst [I] Handle of instance that contains image
2179 * name [I] Name of image
2180 * type [I] Type of image
2181 * desiredx [I] Desired width
2182 * desiredy [I] Desired height
2183 * loadflags [I] Load flags
2185 * RETURNS
2186 * Success: Handle to newly loaded image
2187 * Failure: NULL
2189 * FIXME: Implementation lacks some features, see LR_ defines in windows.h
2191 HANDLE WINAPI LoadImageW( HINSTANCE hinst, LPCWSTR name, UINT type,
2192 INT desiredx, INT desiredy, UINT loadflags )
2194 if (HIWORD(name)) {
2195 TRACE_(resource)("(0x%04x,%p,%d,%d,%d,0x%08x)\n",
2196 hinst,name,type,desiredx,desiredy,loadflags);
2197 } else {
2198 TRACE_(resource)("(0x%04x,%p,%d,%d,%d,0x%08x)\n",
2199 hinst,name,type,desiredx,desiredy,loadflags);
2201 if (loadflags & LR_DEFAULTSIZE) {
2202 if (type == IMAGE_ICON) {
2203 if (!desiredx) desiredx = GetSystemMetrics(SM_CXICON);
2204 if (!desiredy) desiredy = GetSystemMetrics(SM_CYICON);
2205 } else if (type == IMAGE_CURSOR) {
2206 if (!desiredx) desiredx = GetSystemMetrics(SM_CXCURSOR);
2207 if (!desiredy) desiredy = GetSystemMetrics(SM_CYCURSOR);
2210 if (loadflags & LR_LOADFROMFILE) loadflags &= ~LR_SHARED;
2211 switch (type) {
2212 case IMAGE_BITMAP:
2213 return BITMAP_Load( hinst, name, loadflags );
2215 case IMAGE_ICON:
2217 HDC hdc = GetDC(0);
2218 UINT palEnts = GetSystemPaletteEntries(hdc, 0, 0, NULL);
2219 if (palEnts == 0)
2220 palEnts = 256;
2221 ReleaseDC(0, hdc);
2223 return CURSORICON_Load(hinst, name, desiredx, desiredy,
2224 palEnts, FALSE, loadflags);
2227 case IMAGE_CURSOR:
2228 return CURSORICON_Load(hinst, name, desiredx, desiredy,
2229 1, TRUE, loadflags);
2231 return 0;
2235 /******************************************************************************
2236 * CopyImage16 [USER.390] Creates new image and copies attributes to it
2239 HICON16 WINAPI CopyImage16( HANDLE16 hnd, UINT16 type, INT16 desiredx,
2240 INT16 desiredy, UINT16 flags )
2242 return (HICON16)CopyImage((HANDLE)hnd, (UINT)type, (INT)desiredx,
2243 (INT)desiredy, (UINT)flags);
2246 /******************************************************************************
2247 * CopyImage [USER32.61] Creates new image and copies attributes to it
2249 * PARAMS
2250 * hnd [I] Handle to image to copy
2251 * type [I] Type of image to copy
2252 * desiredx [I] Desired width of new image
2253 * desiredy [I] Desired height of new image
2254 * flags [I] Copy flags
2256 * RETURNS
2257 * Success: Handle to newly created image
2258 * Failure: NULL
2260 * FIXME: implementation still lacks nearly all features, see LR_*
2261 * defines in windows.h
2263 HICON WINAPI CopyImage( HANDLE hnd, UINT type, INT desiredx,
2264 INT desiredy, UINT flags )
2266 switch (type)
2268 case IMAGE_BITMAP:
2269 return BITMAP_CopyBitmap(hnd);
2270 case IMAGE_ICON:
2271 return CURSORICON_ExtCopy(hnd,type, desiredx, desiredy, flags);
2272 case IMAGE_CURSOR:
2273 /* Should call CURSORICON_ExtCopy but more testing
2274 * needs to be done before we change this
2276 return CopyCursor(hnd);
2278 return 0;
2282 /******************************************************************************
2283 * LoadBitmapW [USER32.358] Loads bitmap from the executable file
2285 * RETURNS
2286 * Success: Handle to specified bitmap
2287 * Failure: NULL
2289 HBITMAP WINAPI LoadBitmapW(
2290 HINSTANCE instance, /* [in] Handle to application instance */
2291 LPCWSTR name) /* [in] Address of bitmap resource name */
2293 return LoadImageW( instance, name, IMAGE_BITMAP, 0, 0, 0 );
2296 /**********************************************************************
2297 * LoadBitmapA (USER32.357)
2299 HBITMAP WINAPI LoadBitmapA( HINSTANCE instance, LPCSTR name )
2301 return LoadImageA( instance, name, IMAGE_BITMAP, 0, 0, 0 );
2304 /**********************************************************************
2305 * LoadBitmap16 (USER.175)
2307 HBITMAP16 WINAPI LoadBitmap16( HINSTANCE16 instance, SEGPTR name )
2309 LPCSTR nameStr = HIWORD(name)? PTR_SEG_TO_LIN(name) : (LPCSTR)name;
2310 return LoadBitmapA( instance, nameStr );