Use libwine and libwine_unicode directly from their build directory
[wine/multimedia.git] / windows / cursoricon.c
blobe52adea9f2c999818fbc79be680ad58c0fd4dfd5
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 corresponding 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, LPCSTR name )
1045 return LoadCursorA( hInstance, name );
1049 /***********************************************************************
1050 * LoadIcon16 (USER.174)
1052 HICON16 WINAPI LoadIcon16( HINSTANCE16 hInstance, LPCSTR name )
1054 return LoadIconA( hInstance, name );
1058 /***********************************************************************
1059 * CreateCursor16 (USER.406)
1061 HCURSOR16 WINAPI CreateCursor16( HINSTANCE16 hInstance,
1062 INT16 xHotSpot, INT16 yHotSpot,
1063 INT16 nWidth, INT16 nHeight,
1064 LPCVOID lpANDbits, LPCVOID lpXORbits )
1066 CURSORICONINFO info;
1068 TRACE_(cursor)("%dx%d spot=%d,%d xor=%p and=%p\n",
1069 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
1071 info.ptHotSpot.x = xHotSpot;
1072 info.ptHotSpot.y = yHotSpot;
1073 info.nWidth = nWidth;
1074 info.nHeight = nHeight;
1075 info.nWidthBytes = 0;
1076 info.bPlanes = 1;
1077 info.bBitsPerPixel = 1;
1079 return CreateCursorIconIndirect16( hInstance, &info, lpANDbits, lpXORbits );
1083 /***********************************************************************
1084 * CreateCursor (USER32.67)
1086 HCURSOR WINAPI CreateCursor( HINSTANCE hInstance,
1087 INT xHotSpot, INT yHotSpot,
1088 INT nWidth, INT nHeight,
1089 LPCVOID lpANDbits, LPCVOID lpXORbits )
1091 CURSORICONINFO info;
1093 TRACE_(cursor)("%dx%d spot=%d,%d xor=%p and=%p\n",
1094 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
1096 info.ptHotSpot.x = xHotSpot;
1097 info.ptHotSpot.y = yHotSpot;
1098 info.nWidth = nWidth;
1099 info.nHeight = nHeight;
1100 info.nWidthBytes = 0;
1101 info.bPlanes = 1;
1102 info.bBitsPerPixel = 1;
1104 return CreateCursorIconIndirect16( 0, &info, lpANDbits, lpXORbits );
1108 /***********************************************************************
1109 * CreateIcon16 (USER.407)
1111 HICON16 WINAPI CreateIcon16( HINSTANCE16 hInstance, INT16 nWidth,
1112 INT16 nHeight, BYTE bPlanes, BYTE bBitsPixel,
1113 LPCVOID lpANDbits, LPCVOID lpXORbits )
1115 CURSORICONINFO info;
1117 TRACE_(icon)("%dx%dx%d, xor=%p, and=%p\n",
1118 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
1120 info.ptHotSpot.x = ICON_HOTSPOT;
1121 info.ptHotSpot.y = ICON_HOTSPOT;
1122 info.nWidth = nWidth;
1123 info.nHeight = nHeight;
1124 info.nWidthBytes = 0;
1125 info.bPlanes = bPlanes;
1126 info.bBitsPerPixel = bBitsPixel;
1128 return CreateCursorIconIndirect16( hInstance, &info, lpANDbits, lpXORbits );
1132 /***********************************************************************
1133 * CreateIcon (USER32.75)
1135 HICON WINAPI CreateIcon( HINSTANCE hInstance, INT nWidth,
1136 INT nHeight, BYTE bPlanes, BYTE bBitsPixel,
1137 LPCVOID lpANDbits, LPCVOID lpXORbits )
1139 CURSORICONINFO info;
1141 TRACE_(icon)("%dx%dx%d, xor=%p, and=%p\n",
1142 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
1144 info.ptHotSpot.x = ICON_HOTSPOT;
1145 info.ptHotSpot.y = ICON_HOTSPOT;
1146 info.nWidth = nWidth;
1147 info.nHeight = nHeight;
1148 info.nWidthBytes = 0;
1149 info.bPlanes = bPlanes;
1150 info.bBitsPerPixel = bBitsPixel;
1152 return CreateCursorIconIndirect16( 0, &info, lpANDbits, lpXORbits );
1156 /***********************************************************************
1157 * CreateCursorIconIndirect (USER.408)
1159 HGLOBAL16 WINAPI CreateCursorIconIndirect16( HINSTANCE16 hInstance,
1160 CURSORICONINFO *info,
1161 LPCVOID lpANDbits,
1162 LPCVOID lpXORbits )
1164 HGLOBAL16 handle;
1165 char *ptr;
1166 int sizeAnd, sizeXor;
1168 hInstance = GetExePtr( hInstance ); /* Make it a module handle */
1169 if (!lpXORbits || !lpANDbits || info->bPlanes != 1) return 0;
1170 info->nWidthBytes = BITMAP_GetWidthBytes(info->nWidth,info->bBitsPerPixel);
1171 sizeXor = info->nHeight * info->nWidthBytes;
1172 sizeAnd = info->nHeight * BITMAP_GetWidthBytes( info->nWidth, 1 );
1173 if (!(handle = GlobalAlloc16( GMEM_MOVEABLE,
1174 sizeof(CURSORICONINFO) + sizeXor + sizeAnd)))
1175 return 0;
1176 if (hInstance) FarSetOwner16( handle, hInstance );
1177 ptr = (char *)GlobalLock16( handle );
1178 memcpy( ptr, info, sizeof(*info) );
1179 memcpy( ptr + sizeof(CURSORICONINFO), lpANDbits, sizeAnd );
1180 memcpy( ptr + sizeof(CURSORICONINFO) + sizeAnd, lpXORbits, sizeXor );
1181 GlobalUnlock16( handle );
1182 return handle;
1186 /***********************************************************************
1187 * CopyIcon16 (USER.368)
1189 HICON16 WINAPI CopyIcon16( HINSTANCE16 hInstance, HICON16 hIcon )
1191 TRACE_(icon)("%04x %04x\n", hInstance, hIcon );
1192 return CURSORICON_Copy( hInstance, hIcon );
1196 /***********************************************************************
1197 * CopyIcon (USER32.60)
1199 HICON WINAPI CopyIcon( HICON hIcon )
1201 HTASK16 hTask = GetCurrentTask ();
1202 TDB* pTask = (TDB *) GlobalLock16 (hTask);
1203 TRACE_(icon)("%04x\n", hIcon );
1204 return CURSORICON_Copy( pTask->hInstance, hIcon );
1208 /***********************************************************************
1209 * CopyCursor16 (USER.369)
1211 HCURSOR16 WINAPI CopyCursor16( HINSTANCE16 hInstance, HCURSOR16 hCursor )
1213 TRACE_(cursor)("%04x %04x\n", hInstance, hCursor );
1214 return CURSORICON_Copy( hInstance, hCursor );
1217 /**********************************************************************
1218 * CURSORICON_Destroy (USER.610)
1220 * This routine is actually exported from Win95 USER under the name
1221 * DestroyIcon32 ... The behaviour implemented here should mimic
1222 * the Win95 one exactly, especially the return values, which
1223 * depend on the setting of various flags.
1225 WORD WINAPI CURSORICON_Destroy( HGLOBAL16 handle, UINT16 flags )
1227 WORD retv;
1229 TRACE_(icon)("(%04x, %04x)\n", handle, flags );
1231 /* Check whether destroying active cursor */
1233 if ( hActiveCursor == handle )
1235 ERR_(cursor)("Destroying active cursor!\n" );
1236 SetCursor( 0 );
1239 /* Try shared cursor/icon first */
1241 if ( !(flags & CID_NONSHARED) )
1243 INT count = CURSORICON_DelSharedIcon( handle );
1245 if ( count != -1 )
1246 return (flags & CID_WIN32)? TRUE : (count == 0);
1248 /* FIXME: OEM cursors/icons should be recognized */
1251 /* Now assume non-shared cursor/icon */
1253 retv = GlobalFree16( handle );
1254 return (flags & CID_RESOURCE)? retv : TRUE;
1257 /***********************************************************************
1258 * DestroyIcon16 (USER.457)
1260 BOOL16 WINAPI DestroyIcon16( HICON16 hIcon )
1262 return CURSORICON_Destroy( hIcon, 0 );
1265 /***********************************************************************
1266 * DestroyIcon (USER32.133)
1268 BOOL WINAPI DestroyIcon( HICON hIcon )
1270 return CURSORICON_Destroy( hIcon, CID_WIN32 );
1273 /***********************************************************************
1274 * DestroyCursor16 (USER.458)
1276 BOOL16 WINAPI DestroyCursor16( HCURSOR16 hCursor )
1278 return CURSORICON_Destroy( hCursor, 0 );
1281 /***********************************************************************
1282 * DestroyCursor (USER32.132)
1284 BOOL WINAPI DestroyCursor( HCURSOR hCursor )
1286 return CURSORICON_Destroy( hCursor, CID_WIN32 );
1290 /***********************************************************************
1291 * DrawIcon16 (USER.84)
1293 BOOL16 WINAPI DrawIcon16( HDC16 hdc, INT16 x, INT16 y, HICON16 hIcon )
1295 return DrawIcon( hdc, x, y, hIcon );
1299 /***********************************************************************
1300 * DrawIcon (USER32.159)
1302 BOOL WINAPI DrawIcon( HDC hdc, INT x, INT y, HICON hIcon )
1304 CURSORICONINFO *ptr;
1305 HDC hMemDC;
1306 HBITMAP hXorBits, hAndBits;
1307 COLORREF oldFg, oldBg;
1309 if (!(ptr = (CURSORICONINFO *)GlobalLock16( hIcon ))) return FALSE;
1310 if (!(hMemDC = CreateCompatibleDC( hdc ))) return FALSE;
1311 hAndBits = CreateBitmap( ptr->nWidth, ptr->nHeight, 1, 1,
1312 (char *)(ptr+1) );
1313 hXorBits = CreateBitmap( ptr->nWidth, ptr->nHeight, ptr->bPlanes,
1314 ptr->bBitsPerPixel, (char *)(ptr + 1)
1315 + ptr->nHeight * BITMAP_GetWidthBytes(ptr->nWidth,1) );
1316 oldFg = SetTextColor( hdc, RGB(0,0,0) );
1317 oldBg = SetBkColor( hdc, RGB(255,255,255) );
1319 if (hXorBits && hAndBits)
1321 HBITMAP hBitTemp = SelectObject( hMemDC, hAndBits );
1322 BitBlt( hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0, SRCAND );
1323 SelectObject( hMemDC, hXorBits );
1324 BitBlt(hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0,SRCINVERT);
1325 SelectObject( hMemDC, hBitTemp );
1327 DeleteDC( hMemDC );
1328 if (hXorBits) DeleteObject( hXorBits );
1329 if (hAndBits) DeleteObject( hAndBits );
1330 GlobalUnlock16( hIcon );
1331 SetTextColor( hdc, oldFg );
1332 SetBkColor( hdc, oldBg );
1333 return TRUE;
1337 /***********************************************************************
1338 * IconSize16 (USER.86)
1340 * See "Undocumented Windows". Used by W2.0 paint.exe.
1342 DWORD WINAPI IconSize16( void )
1344 return MAKELONG(GetSystemMetrics(SM_CYICON), GetSystemMetrics(SM_CXICON));
1348 /***********************************************************************
1349 * DumpIcon (USER.459)
1351 DWORD WINAPI DumpIcon16( SEGPTR pInfo, WORD *lpLen,
1352 SEGPTR *lpXorBits, SEGPTR *lpAndBits )
1354 CURSORICONINFO *info = PTR_SEG_TO_LIN( pInfo );
1355 int sizeAnd, sizeXor;
1357 if (!info) return 0;
1358 sizeXor = info->nHeight * info->nWidthBytes;
1359 sizeAnd = info->nHeight * BITMAP_GetWidthBytes( info->nWidth, 1 );
1360 if (lpAndBits) *lpAndBits = pInfo + sizeof(CURSORICONINFO);
1361 if (lpXorBits) *lpXorBits = pInfo + sizeof(CURSORICONINFO) + sizeAnd;
1362 if (lpLen) *lpLen = sizeof(CURSORICONINFO) + sizeAnd + sizeXor;
1363 return MAKELONG( sizeXor, sizeXor );
1367 /***********************************************************************
1368 * SetCursor16 (USER.69)
1370 HCURSOR16 WINAPI SetCursor16( HCURSOR16 hCursor )
1372 return (HCURSOR16)SetCursor( hCursor );
1376 /***********************************************************************
1377 * SetCursor (USER32.472)
1378 * RETURNS:
1379 * A handle to the previous cursor shape.
1381 HCURSOR WINAPI SetCursor(
1382 HCURSOR hCursor /* [in] Handle of cursor to show */
1384 HCURSOR hOldCursor;
1386 if (hCursor == hActiveCursor) return hActiveCursor; /* No change */
1387 TRACE_(cursor)("%04x\n", hCursor );
1388 hOldCursor = hActiveCursor;
1389 hActiveCursor = hCursor;
1390 /* Change the cursor shape only if it is visible */
1391 if (CURSOR_ShowCount >= 0)
1393 USER_Driver.pSetCursor( (CURSORICONINFO*)GlobalLock16( hActiveCursor ) );
1394 GlobalUnlock16( hActiveCursor );
1396 return hOldCursor;
1400 /***********************************************************************
1401 * SetCursorPos16 (USER.70)
1403 void WINAPI SetCursorPos16( INT16 x, INT16 y )
1405 SetCursorPos( x, y );
1409 /***********************************************************************
1410 * SetCursorPos (USER32.474)
1412 BOOL WINAPI SetCursorPos( INT x, INT y )
1414 USER_Driver.pMoveCursor( x, y );
1415 return TRUE;
1419 /***********************************************************************
1420 * ShowCursor16 (USER.71)
1422 INT16 WINAPI ShowCursor16( BOOL16 bShow )
1424 return ShowCursor( bShow );
1428 /***********************************************************************
1429 * ShowCursor (USER32.530)
1431 INT WINAPI ShowCursor( BOOL bShow )
1433 TRACE_(cursor)("%d, count=%d\n",
1434 bShow, CURSOR_ShowCount );
1436 if (bShow)
1438 if (++CURSOR_ShowCount == 0) /* Show it */
1440 USER_Driver.pSetCursor( (CURSORICONINFO*)GlobalLock16( hActiveCursor ) );
1441 GlobalUnlock16( hActiveCursor );
1444 else
1446 if (--CURSOR_ShowCount == -1) /* Hide it */
1447 USER_Driver.pSetCursor( NULL );
1449 return CURSOR_ShowCount;
1453 /***********************************************************************
1454 * GetCursor16 (USER.247)
1456 HCURSOR16 WINAPI GetCursor16(void)
1458 return hActiveCursor;
1462 /***********************************************************************
1463 * GetCursor (USER32.227)
1465 HCURSOR WINAPI GetCursor(void)
1467 return hActiveCursor;
1471 /***********************************************************************
1472 * ClipCursor16 (USER.16)
1474 BOOL16 WINAPI ClipCursor16( const RECT16 *rect )
1476 if (!rect) SetRectEmpty( &CURSOR_ClipRect );
1477 else CONV_RECT16TO32( rect, &CURSOR_ClipRect );
1478 return TRUE;
1482 /***********************************************************************
1483 * ClipCursor (USER32.53)
1485 BOOL WINAPI ClipCursor( const RECT *rect )
1487 if (!rect) SetRectEmpty( &CURSOR_ClipRect );
1488 else CopyRect( &CURSOR_ClipRect, rect );
1489 return TRUE;
1493 /***********************************************************************
1494 * GetCursorPos16 (USER.17)
1496 BOOL16 WINAPI GetCursorPos16( POINT16 *pt )
1498 if (!pt) return 0;
1500 pt->x = PosX;
1501 pt->y = PosY;
1503 TRACE_(cursor)("ret=%d,%d\n", pt->x, pt->y );
1504 return 1;
1508 /***********************************************************************
1509 * GetCursorPos (USER32.229)
1511 BOOL WINAPI GetCursorPos( POINT *pt )
1513 BOOL ret;
1515 POINT16 pt16;
1516 ret = GetCursorPos16( &pt16 );
1517 if (pt) CONV_POINT16TO32( &pt16, pt );
1518 return ((pt) ? ret : 0);
1522 /***********************************************************************
1523 * GetClipCursor16 (USER.309)
1525 void WINAPI GetClipCursor16( RECT16 *rect )
1527 if (rect) CONV_RECT32TO16( &CURSOR_ClipRect, rect );
1531 /***********************************************************************
1532 * GetClipCursor (USER32.221)
1534 BOOL WINAPI GetClipCursor( RECT *rect )
1536 if (rect)
1538 CopyRect( rect, &CURSOR_ClipRect );
1539 return TRUE;
1541 return FALSE;
1544 /**********************************************************************
1545 * LookupIconIdFromDirectoryEx16 (USER.364)
1547 * FIXME: exact parameter sizes
1549 INT16 WINAPI LookupIconIdFromDirectoryEx16( LPBYTE xdir, BOOL16 bIcon,
1550 INT16 width, INT16 height, UINT16 cFlag )
1552 CURSORICONDIR *dir = (CURSORICONDIR*)xdir;
1553 UINT16 retVal = 0;
1554 if( dir && !dir->idReserved && (dir->idType & 3) )
1556 CURSORICONDIRENTRY* entry;
1557 HDC hdc;
1558 UINT palEnts;
1559 int colors;
1560 hdc = GetDC(0);
1561 palEnts = GetSystemPaletteEntries(hdc, 0, 0, NULL);
1562 if (palEnts == 0)
1563 palEnts = 256;
1564 colors = (cFlag & LR_MONOCHROME) ? 2 : palEnts;
1566 ReleaseDC(0, hdc);
1568 if( bIcon )
1569 entry = CURSORICON_FindBestIcon( dir, width, height, colors );
1570 else
1571 entry = CURSORICON_FindBestCursor( dir, width, height, 1);
1573 if( entry ) retVal = entry->wResId;
1575 else WARN_(cursor)("invalid resource directory\n");
1576 return retVal;
1579 /**********************************************************************
1580 * LookupIconIdFromDirectoryEx (USER32.380)
1582 INT WINAPI LookupIconIdFromDirectoryEx( LPBYTE dir, BOOL bIcon,
1583 INT width, INT height, UINT cFlag )
1585 return LookupIconIdFromDirectoryEx16( dir, bIcon, width, height, cFlag );
1588 /**********************************************************************
1589 * LookupIconIdFromDirectory (USER.???)
1591 INT16 WINAPI LookupIconIdFromDirectory16( LPBYTE dir, BOOL16 bIcon )
1593 return LookupIconIdFromDirectoryEx16( dir, bIcon,
1594 bIcon ? GetSystemMetrics(SM_CXICON) : GetSystemMetrics(SM_CXCURSOR),
1595 bIcon ? GetSystemMetrics(SM_CYICON) : GetSystemMetrics(SM_CYCURSOR), bIcon ? 0 : LR_MONOCHROME );
1598 /**********************************************************************
1599 * LookupIconIdFromDirectory (USER32.379)
1601 INT WINAPI LookupIconIdFromDirectory( LPBYTE dir, BOOL bIcon )
1603 return LookupIconIdFromDirectoryEx( dir, bIcon,
1604 bIcon ? GetSystemMetrics(SM_CXICON) : GetSystemMetrics(SM_CXCURSOR),
1605 bIcon ? GetSystemMetrics(SM_CYICON) : GetSystemMetrics(SM_CYCURSOR), bIcon ? 0 : LR_MONOCHROME );
1608 /**********************************************************************
1609 * GetIconID (USER.455)
1611 WORD WINAPI GetIconID16( HGLOBAL16 hResource, DWORD resType )
1613 LPBYTE lpDir = (LPBYTE)GlobalLock16(hResource);
1615 TRACE_(cursor)("hRes=%04x, entries=%i\n",
1616 hResource, lpDir ? ((CURSORICONDIR*)lpDir)->idCount : 0);
1618 switch(resType)
1620 case RT_CURSOR16:
1621 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, FALSE,
1622 GetSystemMetrics(SM_CXCURSOR), GetSystemMetrics(SM_CYCURSOR), LR_MONOCHROME );
1623 case RT_ICON16:
1624 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, TRUE,
1625 GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), 0 );
1626 default:
1627 WARN_(cursor)("invalid res type %ld\n", resType );
1629 return 0;
1632 /**********************************************************************
1633 * LoadCursorIconHandler (USER.336)
1635 * Supposed to load resources of Windows 2.x applications.
1637 HGLOBAL16 WINAPI LoadCursorIconHandler16( HGLOBAL16 hResource, HMODULE16 hModule, HRSRC16 hRsrc )
1639 FIXME_(cursor)("(%04x,%04x,%04x): old 2.x resources are not supported!\n",
1640 hResource, hModule, hRsrc);
1641 return (HGLOBAL16)0;
1644 /**********************************************************************
1645 * LoadDIBIconHandler (USER.357)
1647 * RT_ICON resource loader, installed by USER_SignalProc when module
1648 * is initialized.
1650 HGLOBAL16 WINAPI LoadDIBIconHandler16( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1652 /* If hResource is zero we must allocate a new memory block, if it's
1653 * non-zero but GlobalLock() returns NULL then it was discarded and
1654 * we have to recommit some memory, otherwise we just need to check
1655 * the block size. See LoadProc() in 16-bit SDK for more.
1658 hMemObj = NE_DefResourceHandler( hMemObj, hModule, hRsrc );
1659 if( hMemObj )
1661 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1662 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1663 SizeofResource16(hModule, hRsrc), TRUE, 0x00030000,
1664 GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), LR_DEFAULTCOLOR );
1666 return hMemObj;
1669 /**********************************************************************
1670 * LoadDIBCursorHandler (USER.356)
1672 * RT_CURSOR resource loader. Same as above.
1674 HGLOBAL16 WINAPI LoadDIBCursorHandler16( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1676 hMemObj = NE_DefResourceHandler( hMemObj, hModule, hRsrc );
1677 if( hMemObj )
1679 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1680 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1681 SizeofResource16(hModule, hRsrc), FALSE, 0x00030000,
1682 GetSystemMetrics(SM_CXCURSOR), GetSystemMetrics(SM_CYCURSOR), LR_MONOCHROME );
1684 return hMemObj;
1687 /**********************************************************************
1688 * LoadIconHandler (USER.456)
1690 HICON16 WINAPI LoadIconHandler16( HGLOBAL16 hResource, BOOL16 bNew )
1692 LPBYTE bits = (LPBYTE)LockResource16( hResource );
1694 TRACE_(cursor)("hRes=%04x\n",hResource);
1696 return CURSORICON_CreateFromResource( 0, 0, bits, 0, TRUE,
1697 bNew ? 0x00030000 : 0x00020000, 0, 0, LR_DEFAULTCOLOR );
1700 /***********************************************************************
1701 * LoadCursorW (USER32.362)
1703 HCURSOR WINAPI LoadCursorW(HINSTANCE hInstance, LPCWSTR name)
1705 return LoadImageW( hInstance, name, IMAGE_CURSOR, 0, 0,
1706 LR_SHARED | LR_DEFAULTSIZE );
1709 /***********************************************************************
1710 * LoadCursorA (USER32.359)
1712 HCURSOR WINAPI LoadCursorA(HINSTANCE hInstance, LPCSTR name)
1714 return LoadImageA( hInstance, name, IMAGE_CURSOR, 0, 0,
1715 LR_SHARED | LR_DEFAULTSIZE );
1718 /***********************************************************************
1719 * LoadCursorFromFileW (USER32.361)
1721 HCURSOR WINAPI LoadCursorFromFileW (LPCWSTR name)
1723 return LoadImageW( 0, name, IMAGE_CURSOR, 0, 0,
1724 LR_LOADFROMFILE | LR_DEFAULTSIZE );
1727 /***********************************************************************
1728 * LoadCursorFromFileA (USER32.360)
1730 HCURSOR WINAPI LoadCursorFromFileA (LPCSTR name)
1732 return LoadImageA( 0, name, IMAGE_CURSOR, 0, 0,
1733 LR_LOADFROMFILE | LR_DEFAULTSIZE );
1736 /***********************************************************************
1737 * LoadIconW (USER32.364)
1739 HICON WINAPI LoadIconW(HINSTANCE hInstance, LPCWSTR name)
1741 return LoadImageW( hInstance, name, IMAGE_ICON, 0, 0,
1742 LR_SHARED | LR_DEFAULTSIZE );
1745 /***********************************************************************
1746 * LoadIconA (USER32.363)
1748 HICON WINAPI LoadIconA(HINSTANCE hInstance, LPCSTR name)
1750 return LoadImageA( hInstance, name, IMAGE_ICON, 0, 0,
1751 LR_SHARED | LR_DEFAULTSIZE );
1754 /**********************************************************************
1755 * GetIconInfo16 (USER.395)
1757 BOOL16 WINAPI GetIconInfo16(HICON16 hIcon,LPICONINFO16 iconinfo)
1759 ICONINFO ii32;
1760 BOOL16 ret = GetIconInfo((HICON)hIcon, &ii32);
1762 iconinfo->fIcon = ii32.fIcon;
1763 iconinfo->xHotspot = ii32.xHotspot;
1764 iconinfo->yHotspot = ii32.yHotspot;
1765 iconinfo->hbmMask = ii32.hbmMask;
1766 iconinfo->hbmColor = ii32.hbmColor;
1767 return ret;
1770 /**********************************************************************
1771 * GetIconInfo (USER32.242)
1773 BOOL WINAPI GetIconInfo(HICON hIcon,PICONINFO iconinfo) {
1774 CURSORICONINFO *ciconinfo;
1776 ciconinfo = GlobalLock16(hIcon);
1777 if (!ciconinfo)
1778 return FALSE;
1780 if ( (ciconinfo->ptHotSpot.x == ICON_HOTSPOT) &&
1781 (ciconinfo->ptHotSpot.y == ICON_HOTSPOT) )
1783 iconinfo->fIcon = TRUE;
1784 iconinfo->xHotspot = ciconinfo->nWidth / 2;
1785 iconinfo->yHotspot = ciconinfo->nHeight / 2;
1787 else
1789 iconinfo->fIcon = FALSE;
1790 iconinfo->xHotspot = ciconinfo->ptHotSpot.x;
1791 iconinfo->yHotspot = ciconinfo->ptHotSpot.y;
1794 iconinfo->hbmColor = CreateBitmap ( ciconinfo->nWidth, ciconinfo->nHeight,
1795 ciconinfo->bPlanes, ciconinfo->bBitsPerPixel,
1796 (char *)(ciconinfo + 1)
1797 + ciconinfo->nHeight *
1798 BITMAP_GetWidthBytes (ciconinfo->nWidth,1) );
1799 iconinfo->hbmMask = CreateBitmap ( ciconinfo->nWidth, ciconinfo->nHeight,
1800 1, 1, (char *)(ciconinfo + 1));
1802 GlobalUnlock16(hIcon);
1804 return TRUE;
1807 /**********************************************************************
1808 * CreateIconIndirect (USER32.78)
1810 HICON WINAPI CreateIconIndirect(PICONINFO iconinfo)
1812 BITMAP bmpXor,bmpAnd;
1813 HICON hObj;
1814 int sizeXor,sizeAnd;
1816 GetObjectA( iconinfo->hbmColor, sizeof(bmpXor), &bmpXor );
1817 GetObjectA( iconinfo->hbmMask, sizeof(bmpAnd), &bmpAnd );
1819 sizeXor = bmpXor.bmHeight * bmpXor.bmWidthBytes;
1820 sizeAnd = bmpAnd.bmHeight * bmpAnd.bmWidthBytes;
1822 hObj = GlobalAlloc16( GMEM_MOVEABLE,
1823 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
1824 if (hObj)
1826 CURSORICONINFO *info;
1828 info = (CURSORICONINFO *)GlobalLock16( hObj );
1830 /* If we are creating an icon, the hotspot is unused */
1831 if (iconinfo->fIcon)
1833 info->ptHotSpot.x = ICON_HOTSPOT;
1834 info->ptHotSpot.y = ICON_HOTSPOT;
1836 else
1838 info->ptHotSpot.x = iconinfo->xHotspot;
1839 info->ptHotSpot.y = iconinfo->yHotspot;
1842 info->nWidth = bmpXor.bmWidth;
1843 info->nHeight = bmpXor.bmHeight;
1844 info->nWidthBytes = bmpXor.bmWidthBytes;
1845 info->bPlanes = bmpXor.bmPlanes;
1846 info->bBitsPerPixel = bmpXor.bmBitsPixel;
1848 /* Transfer the bitmap bits to the CURSORICONINFO structure */
1850 GetBitmapBits( iconinfo->hbmMask ,sizeAnd,(char*)(info + 1) );
1851 GetBitmapBits( iconinfo->hbmColor,sizeXor,(char*)(info + 1) +sizeAnd);
1852 GlobalUnlock16( hObj );
1854 return hObj;
1858 /**********************************************************************
1860 DrawIconEx16 (USER.394)
1862 BOOL16 WINAPI DrawIconEx16 (HDC16 hdc, INT16 xLeft, INT16 yTop, HICON16 hIcon,
1863 INT16 cxWidth, INT16 cyWidth, UINT16 istep,
1864 HBRUSH16 hbr, UINT16 flags)
1866 return DrawIconEx(hdc, xLeft, yTop, hIcon, cxWidth, cyWidth,
1867 istep, hbr, flags);
1871 /******************************************************************************
1872 * DrawIconEx [USER32.160] Draws an icon or cursor on device context
1874 * NOTES
1875 * Why is this using SM_CXICON instead of SM_CXCURSOR?
1877 * PARAMS
1878 * hdc [I] Handle to device context
1879 * x0 [I] X coordinate of upper left corner
1880 * y0 [I] Y coordinate of upper left corner
1881 * hIcon [I] Handle to icon to draw
1882 * cxWidth [I] Width of icon
1883 * cyWidth [I] Height of icon
1884 * istep [I] Index of frame in animated cursor
1885 * hbr [I] Handle to background brush
1886 * flags [I] Icon-drawing flags
1888 * RETURNS
1889 * Success: TRUE
1890 * Failure: FALSE
1892 BOOL WINAPI DrawIconEx( HDC hdc, INT x0, INT y0, HICON hIcon,
1893 INT cxWidth, INT cyWidth, UINT istep,
1894 HBRUSH hbr, UINT flags )
1896 CURSORICONINFO *ptr = (CURSORICONINFO *)GlobalLock16 (hIcon);
1897 HDC hDC_off = 0, hMemDC = CreateCompatibleDC (hdc);
1898 BOOL result = FALSE, DoOffscreen;
1899 HBITMAP hB_off = 0, hOld = 0;
1901 if (!ptr) return FALSE;
1902 TRACE_(icon)("(hdc=%x,pos=%d.%d,hicon=%x,extend=%d.%d,istep=%d,br=%x,flags=0x%08x)\n",
1903 hdc,x0,y0,hIcon,cxWidth,cyWidth,istep,hbr,flags
1906 if (istep)
1907 FIXME_(icon)("Ignoring istep=%d\n", istep);
1908 if (flags & DI_COMPAT)
1909 FIXME_(icon)("Ignoring flag DI_COMPAT\n");
1911 if (!flags) {
1912 FIXME_(icon)("no flags set? setting to DI_NORMAL\n");
1913 flags = DI_NORMAL;
1916 /* Calculate the size of the destination image. */
1917 if (cxWidth == 0)
1919 if (flags & DI_DEFAULTSIZE)
1920 cxWidth = GetSystemMetrics (SM_CXICON);
1921 else
1922 cxWidth = ptr->nWidth;
1924 if (cyWidth == 0)
1926 if (flags & DI_DEFAULTSIZE)
1927 cyWidth = GetSystemMetrics (SM_CYICON);
1928 else
1929 cyWidth = ptr->nHeight;
1932 DoOffscreen = (GetObjectType( hbr ) == OBJ_BRUSH);
1934 if (DoOffscreen) {
1935 RECT r;
1937 r.left = 0;
1938 r.top = 0;
1939 r.right = cxWidth;
1940 r.bottom = cxWidth;
1942 hDC_off = CreateCompatibleDC(hdc);
1943 hB_off = CreateCompatibleBitmap(hdc, cxWidth, cyWidth);
1944 if (hDC_off && hB_off) {
1945 hOld = SelectObject(hDC_off, hB_off);
1946 FillRect(hDC_off, &r, hbr);
1950 if (hMemDC && (!DoOffscreen || (hDC_off && hB_off)))
1952 HBITMAP hXorBits, hAndBits;
1953 COLORREF oldFg, oldBg;
1954 INT nStretchMode;
1956 nStretchMode = SetStretchBltMode (hdc, STRETCH_DELETESCANS);
1958 hXorBits = CreateBitmap ( ptr->nWidth, ptr->nHeight,
1959 ptr->bPlanes, ptr->bBitsPerPixel,
1960 (char *)(ptr + 1)
1961 + ptr->nHeight *
1962 BITMAP_GetWidthBytes(ptr->nWidth,1) );
1963 hAndBits = CreateBitmap ( ptr->nWidth, ptr->nHeight,
1964 1, 1, (char *)(ptr+1) );
1965 oldFg = SetTextColor( hdc, RGB(0,0,0) );
1966 oldBg = SetBkColor( hdc, RGB(255,255,255) );
1968 if (hXorBits && hAndBits)
1970 HBITMAP hBitTemp = SelectObject( hMemDC, hAndBits );
1971 if (flags & DI_MASK)
1973 if (DoOffscreen)
1974 StretchBlt (hDC_off, 0, 0, cxWidth, cyWidth,
1975 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
1976 else
1977 StretchBlt (hdc, x0, y0, cxWidth, cyWidth,
1978 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
1980 SelectObject( hMemDC, hXorBits );
1981 if (flags & DI_IMAGE)
1983 if (DoOffscreen)
1984 StretchBlt (hDC_off, 0, 0, cxWidth, cyWidth,
1985 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
1986 else
1987 StretchBlt (hdc, x0, y0, cxWidth, cyWidth,
1988 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
1990 SelectObject( hMemDC, hBitTemp );
1991 result = TRUE;
1994 SetTextColor( hdc, oldFg );
1995 SetBkColor( hdc, oldBg );
1996 if (hXorBits) DeleteObject( hXorBits );
1997 if (hAndBits) DeleteObject( hAndBits );
1998 SetStretchBltMode (hdc, nStretchMode);
1999 if (DoOffscreen) {
2000 BitBlt(hdc, x0, y0, cxWidth, cyWidth, hDC_off, 0, 0, SRCCOPY);
2001 SelectObject(hDC_off, hOld);
2004 if (hMemDC) DeleteDC( hMemDC );
2005 if (hDC_off) DeleteDC(hDC_off);
2006 if (hB_off) DeleteObject(hB_off);
2007 GlobalUnlock16( hIcon );
2008 return result;
2011 /***********************************************************************
2012 * DIB_FixColorsToLoadflags
2014 * Change color table entries when LR_LOADTRANSPARENT or LR_LOADMAP3DCOLORS
2015 * are in loadflags
2017 static void DIB_FixColorsToLoadflags(BITMAPINFO * bmi, UINT loadflags, BYTE pix)
2019 int colors;
2020 COLORREF c_W, c_S, c_F, c_L, c_C;
2021 int incr,i;
2022 RGBQUAD *ptr;
2024 if (bmi->bmiHeader.biBitCount > 8) return;
2025 if (bmi->bmiHeader.biSize == sizeof(BITMAPINFOHEADER)) incr = 4;
2026 else if (bmi->bmiHeader.biSize == sizeof(BITMAPCOREHEADER)) incr = 3;
2027 else {
2028 WARN_(resource)("Wrong bitmap header size!\n");
2029 return;
2031 colors = bmi->bmiHeader.biClrUsed;
2032 if (!colors && (bmi->bmiHeader.biBitCount <= 8))
2033 colors = 1 << bmi->bmiHeader.biBitCount;
2034 c_W = GetSysColor(COLOR_WINDOW);
2035 c_S = GetSysColor(COLOR_3DSHADOW);
2036 c_F = GetSysColor(COLOR_3DFACE);
2037 c_L = GetSysColor(COLOR_3DLIGHT);
2038 if (loadflags & LR_LOADTRANSPARENT) {
2039 switch (bmi->bmiHeader.biBitCount) {
2040 case 1: pix = pix >> 7; break;
2041 case 4: pix = pix >> 4; break;
2042 case 8: break;
2043 default:
2044 WARN_(resource)("(%d): Unsupported depth\n", bmi->bmiHeader.biBitCount);
2045 return;
2047 if (pix >= colors) {
2048 WARN_(resource)("pixel has color index greater than biClrUsed!\n");
2049 return;
2051 if (loadflags & LR_LOADMAP3DCOLORS) c_W = c_F;
2052 ptr = (RGBQUAD*)((char*)bmi->bmiColors+pix*incr);
2053 ptr->rgbBlue = GetBValue(c_W);
2054 ptr->rgbGreen = GetGValue(c_W);
2055 ptr->rgbRed = GetRValue(c_W);
2057 if (loadflags & LR_LOADMAP3DCOLORS)
2058 for (i=0; i<colors; i++) {
2059 ptr = (RGBQUAD*)((char*)bmi->bmiColors+i*incr);
2060 c_C = RGB(ptr->rgbRed, ptr->rgbGreen, ptr->rgbBlue);
2061 if (c_C == RGB(128, 128, 128)) {
2062 ptr->rgbRed = GetRValue(c_S);
2063 ptr->rgbGreen = GetGValue(c_S);
2064 ptr->rgbBlue = GetBValue(c_S);
2065 } else if (c_C == RGB(192, 192, 192)) {
2066 ptr->rgbRed = GetRValue(c_F);
2067 ptr->rgbGreen = GetGValue(c_F);
2068 ptr->rgbBlue = GetBValue(c_F);
2069 } else if (c_C == RGB(223, 223, 223)) {
2070 ptr->rgbRed = GetRValue(c_L);
2071 ptr->rgbGreen = GetGValue(c_L);
2072 ptr->rgbBlue = GetBValue(c_L);
2078 /**********************************************************************
2079 * BITMAP_Load
2081 static HBITMAP BITMAP_Load( HINSTANCE instance,LPCWSTR name, UINT loadflags )
2083 HBITMAP hbitmap = 0;
2084 HDC hdc;
2085 HRSRC hRsrc;
2086 HGLOBAL handle;
2087 char *ptr = NULL;
2088 BITMAPINFO *info, *fix_info=NULL;
2089 HGLOBAL hFix;
2090 int size;
2092 if (!(loadflags & LR_LOADFROMFILE)) {
2093 if (!instance) /* OEM bitmap */
2095 if (HIWORD((int)name)) return 0;
2096 return USER_Driver.pLoadOEMResource( LOWORD((int)name), OEM_BITMAP );
2099 if (!(hRsrc = FindResourceW( instance, name, RT_BITMAPW ))) return 0;
2100 if (!(handle = LoadResource( instance, hRsrc ))) return 0;
2102 if ((info = (BITMAPINFO *)LockResource( handle )) == NULL) return 0;
2104 else
2106 if (!(ptr = (char *)VIRTUAL_MapFileW( name ))) return 0;
2107 info = (BITMAPINFO *)(ptr + sizeof(BITMAPFILEHEADER));
2109 size = DIB_BitmapInfoSize(info, DIB_RGB_COLORS);
2110 if ((hFix = GlobalAlloc(0, size))) fix_info=GlobalLock(hFix);
2111 if (fix_info) {
2112 BYTE pix;
2114 memcpy(fix_info, info, size);
2115 pix = *((LPBYTE)info+DIB_BitmapInfoSize(info, DIB_RGB_COLORS));
2116 DIB_FixColorsToLoadflags(fix_info, loadflags, pix);
2117 if ((hdc = GetDC(0)) != 0) {
2118 char *bits = (char *)info + size;
2119 if (loadflags & LR_CREATEDIBSECTION) {
2120 DIBSECTION dib;
2121 hbitmap = CreateDIBSection(hdc, fix_info, DIB_RGB_COLORS, NULL, 0, 0);
2122 GetObjectA(hbitmap, sizeof(DIBSECTION), &dib);
2123 SetDIBits(hdc, hbitmap, 0, dib.dsBm.bmHeight, bits, info,
2124 DIB_RGB_COLORS);
2126 else {
2127 hbitmap = CreateDIBitmap( hdc, &fix_info->bmiHeader, CBM_INIT,
2128 bits, fix_info, DIB_RGB_COLORS );
2130 ReleaseDC( 0, hdc );
2132 GlobalUnlock(hFix);
2133 GlobalFree(hFix);
2135 if (loadflags & LR_LOADFROMFILE) UnmapViewOfFile( ptr );
2136 return hbitmap;
2140 /***********************************************************************
2141 * LoadImage16 [USER.389]
2144 HANDLE16 WINAPI LoadImage16( HINSTANCE16 hinst, LPCSTR name, UINT16 type,
2145 INT16 desiredx, INT16 desiredy, UINT16 loadflags)
2147 LPCSTR nameStr = HIWORD(name)? PTR_SEG_TO_LIN(name) : (LPCSTR)name;
2148 return LoadImageA( hinst, nameStr, type,
2149 desiredx, desiredy, loadflags );
2152 /**********************************************************************
2153 * LoadImageA (USER32.365)
2155 * FIXME: implementation lacks some features, see LR_ defines in windows.h
2158 HANDLE WINAPI LoadImageA( HINSTANCE hinst, LPCSTR name, UINT type,
2159 INT desiredx, INT desiredy, UINT loadflags)
2161 HANDLE res;
2162 LPWSTR u_name;
2164 if (HIWORD(name)) u_name = HEAP_strdupAtoW(GetProcessHeap(), 0, name);
2165 else u_name=(LPWSTR)name;
2166 res = LoadImageW(hinst, u_name, type, desiredx, desiredy, loadflags);
2167 if (HIWORD(name)) HeapFree(GetProcessHeap(), 0, u_name);
2168 return res;
2172 /******************************************************************************
2173 * LoadImageW [USER32.366] Loads an icon, cursor, or bitmap
2175 * PARAMS
2176 * hinst [I] Handle of instance that contains image
2177 * name [I] Name of image
2178 * type [I] Type of image
2179 * desiredx [I] Desired width
2180 * desiredy [I] Desired height
2181 * loadflags [I] Load flags
2183 * RETURNS
2184 * Success: Handle to newly loaded image
2185 * Failure: NULL
2187 * FIXME: Implementation lacks some features, see LR_ defines in windows.h
2189 HANDLE WINAPI LoadImageW( HINSTANCE hinst, LPCWSTR name, UINT type,
2190 INT desiredx, INT desiredy, UINT loadflags )
2192 if (HIWORD(name)) {
2193 TRACE_(resource)("(0x%04x,%p,%d,%d,%d,0x%08x)\n",
2194 hinst,name,type,desiredx,desiredy,loadflags);
2195 } else {
2196 TRACE_(resource)("(0x%04x,%p,%d,%d,%d,0x%08x)\n",
2197 hinst,name,type,desiredx,desiredy,loadflags);
2199 if (loadflags & LR_DEFAULTSIZE) {
2200 if (type == IMAGE_ICON) {
2201 if (!desiredx) desiredx = GetSystemMetrics(SM_CXICON);
2202 if (!desiredy) desiredy = GetSystemMetrics(SM_CYICON);
2203 } else if (type == IMAGE_CURSOR) {
2204 if (!desiredx) desiredx = GetSystemMetrics(SM_CXCURSOR);
2205 if (!desiredy) desiredy = GetSystemMetrics(SM_CYCURSOR);
2208 if (loadflags & LR_LOADFROMFILE) loadflags &= ~LR_SHARED;
2209 switch (type) {
2210 case IMAGE_BITMAP:
2211 return BITMAP_Load( hinst, name, loadflags );
2213 case IMAGE_ICON:
2215 HDC hdc = GetDC(0);
2216 UINT palEnts = GetSystemPaletteEntries(hdc, 0, 0, NULL);
2217 if (palEnts == 0)
2218 palEnts = 256;
2219 ReleaseDC(0, hdc);
2221 return CURSORICON_Load(hinst, name, desiredx, desiredy,
2222 palEnts, FALSE, loadflags);
2225 case IMAGE_CURSOR:
2226 return CURSORICON_Load(hinst, name, desiredx, desiredy,
2227 1, TRUE, loadflags);
2229 return 0;
2233 /******************************************************************************
2234 * CopyImage16 [USER.390] Creates new image and copies attributes to it
2237 HICON16 WINAPI CopyImage16( HANDLE16 hnd, UINT16 type, INT16 desiredx,
2238 INT16 desiredy, UINT16 flags )
2240 return (HICON16)CopyImage((HANDLE)hnd, (UINT)type, (INT)desiredx,
2241 (INT)desiredy, (UINT)flags);
2244 /******************************************************************************
2245 * CopyImage [USER32.61] Creates new image and copies attributes to it
2247 * PARAMS
2248 * hnd [I] Handle to image to copy
2249 * type [I] Type of image to copy
2250 * desiredx [I] Desired width of new image
2251 * desiredy [I] Desired height of new image
2252 * flags [I] Copy flags
2254 * RETURNS
2255 * Success: Handle to newly created image
2256 * Failure: NULL
2258 * FIXME: implementation still lacks nearly all features, see LR_*
2259 * defines in windows.h
2261 HICON WINAPI CopyImage( HANDLE hnd, UINT type, INT desiredx,
2262 INT desiredy, UINT flags )
2264 switch (type)
2266 case IMAGE_BITMAP:
2267 return BITMAP_CopyBitmap(hnd);
2268 case IMAGE_ICON:
2269 return CURSORICON_ExtCopy(hnd,type, desiredx, desiredy, flags);
2270 case IMAGE_CURSOR:
2271 /* Should call CURSORICON_ExtCopy but more testing
2272 * needs to be done before we change this
2274 return CopyCursor(hnd);
2276 return 0;
2280 /******************************************************************************
2281 * LoadBitmapW [USER32.358] Loads bitmap from the executable file
2283 * RETURNS
2284 * Success: Handle to specified bitmap
2285 * Failure: NULL
2287 HBITMAP WINAPI LoadBitmapW(
2288 HINSTANCE instance, /* [in] Handle to application instance */
2289 LPCWSTR name) /* [in] Address of bitmap resource name */
2291 return LoadImageW( instance, name, IMAGE_BITMAP, 0, 0, 0 );
2294 /**********************************************************************
2295 * LoadBitmapA (USER32.357)
2297 HBITMAP WINAPI LoadBitmapA( HINSTANCE instance, LPCSTR name )
2299 return LoadImageA( instance, name, IMAGE_BITMAP, 0, 0, 0 );
2302 /**********************************************************************
2303 * LoadBitmap16 (USER.175)
2305 HBITMAP16 WINAPI LoadBitmap16( HINSTANCE16 instance, LPCSTR name )
2307 return LoadBitmapA( instance, name );