Added stub for WMMMIDIRUNONCE called by midimap.drv.
[wine/testsucceed.git] / objects / cursoricon.c
bloba0e609416867d086bdf69bffa7aeeab100cd155c
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 "wine/winbase16.h"
36 #include "wine/winuser16.h"
37 #include "heap.h"
38 #include "color.h"
39 #include "bitmap.h"
40 #include "cursoricon.h"
41 #include "dc.h"
42 #include "gdi.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 "display.h"
50 #include "message.h"
51 #include "winerror.h"
53 DECLARE_DEBUG_CHANNEL(cursor)
54 DECLARE_DEBUG_CHANNEL(icon)
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;
83 static DWORD ICON_HOTSPOT = 0x42424242;
85 /**********************************************************************
86 * CURSORICON_Init
88 void CURSORICON_Init( void )
90 InitializeCriticalSection( &IconCrst );
91 MakeCriticalSectionGlobal( &IconCrst );
94 /**********************************************************************
95 * CURSORICON_FindSharedIcon
97 static HANDLE CURSORICON_FindSharedIcon( HMODULE hModule, HRSRC hRsrc )
99 HANDLE handle = 0;
100 ICONCACHE *ptr;
102 EnterCriticalSection( &IconCrst );
104 for ( ptr = IconAnchor; ptr; ptr = ptr->next )
105 if ( ptr->hModule == hModule && ptr->hRsrc == hRsrc )
107 ptr->count++;
108 handle = ptr->handle;
109 break;
112 LeaveCriticalSection( &IconCrst );
114 return handle;
117 /*************************************************************************
118 * CURSORICON_FindCache
120 * Given a handle, find the coresponding cache element
122 * PARAMS
123 * Handle [I] handle to an Image
125 * RETURNS
126 * Success: The cache entry
127 * Failure: NULL
130 static ICONCACHE* CURSORICON_FindCache(HANDLE handle)
132 ICONCACHE *ptr;
133 ICONCACHE *pRet=NULL;
134 BOOL IsFound = FALSE;
135 int count;
137 EnterCriticalSection( &IconCrst );
139 for (count = 0, ptr = IconAnchor; ptr != NULL && !IsFound; ptr = ptr->next, count++ )
141 if ( handle == ptr->handle )
143 IsFound = TRUE;
144 pRet = ptr;
148 LeaveCriticalSection( &IconCrst );
150 return pRet;
153 /**********************************************************************
154 * CURSORICON_AddSharedIcon
156 static void CURSORICON_AddSharedIcon( HMODULE hModule, HRSRC hRsrc, HRSRC hGroupRsrc, HANDLE handle )
158 ICONCACHE *ptr = HeapAlloc( SystemHeap, 0, sizeof(ICONCACHE) );
159 if ( !ptr ) return;
161 ptr->hModule = hModule;
162 ptr->hRsrc = hRsrc;
163 ptr->handle = handle;
164 ptr->hGroupRsrc = hGroupRsrc;
165 ptr->count = 1;
167 EnterCriticalSection( &IconCrst );
168 ptr->next = IconAnchor;
169 IconAnchor = ptr;
170 LeaveCriticalSection( &IconCrst );
173 /**********************************************************************
174 * CURSORICON_DelSharedIcon
176 static INT CURSORICON_DelSharedIcon( HANDLE handle )
178 INT count = -1;
179 ICONCACHE *ptr;
181 EnterCriticalSection( &IconCrst );
183 for ( ptr = IconAnchor; ptr; ptr = ptr->next )
184 if ( ptr->handle == handle )
186 if ( ptr->count > 0 ) ptr->count--;
187 count = ptr->count;
188 break;
191 LeaveCriticalSection( &IconCrst );
193 return count;
196 /**********************************************************************
197 * CURSORICON_FreeModuleIcons
199 void CURSORICON_FreeModuleIcons( HMODULE hModule )
201 ICONCACHE **ptr = &IconAnchor;
203 if ( HIWORD( hModule ) )
204 hModule = MapHModuleLS( hModule );
205 else
206 hModule = GetExePtr( hModule );
208 EnterCriticalSection( &IconCrst );
210 while ( *ptr )
212 if ( (*ptr)->hModule == hModule )
214 ICONCACHE *freePtr = *ptr;
215 *ptr = freePtr->next;
217 GlobalFree16( freePtr->handle );
218 HeapFree( SystemHeap, 0, freePtr );
219 continue;
221 ptr = &(*ptr)->next;
224 LeaveCriticalSection( &IconCrst );
227 /**********************************************************************
228 * CURSORICON_FindBestIcon
230 * Find the icon closest to the requested size and number of colors.
232 static CURSORICONDIRENTRY *CURSORICON_FindBestIcon( CURSORICONDIR *dir, int width,
233 int height, int colors )
235 int i;
236 CURSORICONDIRENTRY *entry, *bestEntry = NULL;
237 UINT iTotalDiff, iXDiff=0, iYDiff=0, iColorDiff;
238 UINT iTempXDiff, iTempYDiff, iTempColorDiff;
240 if (dir->idCount < 1)
242 WARN_(icon)("Empty directory!\n" );
243 return NULL;
245 if (dir->idCount == 1) return &dir->idEntries[0]; /* No choice... */
247 /* Find Best Fit */
248 iTotalDiff = 0xFFFFFFFF;
249 iColorDiff = 0xFFFFFFFF;
250 for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
252 iTempXDiff = abs(width - entry->ResInfo.icon.bWidth);
253 iTempYDiff = abs(height - entry->ResInfo.icon.bHeight);
255 if(iTotalDiff > (iTempXDiff + iTempYDiff))
257 iXDiff = iTempXDiff;
258 iYDiff = iTempYDiff;
259 iTotalDiff = iXDiff + iYDiff;
263 /* Find Best Colors for Best Fit */
264 for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
266 if(abs(width - entry->ResInfo.icon.bWidth) == iXDiff &&
267 abs(height - entry->ResInfo.icon.bHeight) == iYDiff)
269 iTempColorDiff = abs(colors - entry->ResInfo.icon.bColorCount);
270 if(iColorDiff > iTempColorDiff)
272 bestEntry = entry;
273 iColorDiff = iTempColorDiff;
278 return bestEntry;
282 /**********************************************************************
283 * CURSORICON_FindBestCursor
285 * Find the cursor closest to the requested size.
286 * FIXME: parameter 'color' ignored and entries with more than 1 bpp
287 * ignored too
289 static CURSORICONDIRENTRY *CURSORICON_FindBestCursor( CURSORICONDIR *dir,
290 int width, int height, int color)
292 int i, maxwidth, maxheight;
293 CURSORICONDIRENTRY *entry, *bestEntry = NULL;
295 if (dir->idCount < 1)
297 WARN_(cursor)("Empty directory!\n" );
298 return NULL;
300 if (dir->idCount == 1) return &dir->idEntries[0]; /* No choice... */
302 /* Double height to account for AND and XOR masks */
304 height *= 2;
306 /* First find the largest one smaller than or equal to the requested size*/
308 maxwidth = maxheight = 0;
309 for(i = 0,entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
310 if ((entry->ResInfo.cursor.wWidth <= width) && (entry->ResInfo.cursor.wHeight <= height) &&
311 (entry->ResInfo.cursor.wWidth > maxwidth) && (entry->ResInfo.cursor.wHeight > maxheight) &&
312 (entry->wBitCount == 1))
314 bestEntry = entry;
315 maxwidth = entry->ResInfo.cursor.wWidth;
316 maxheight = entry->ResInfo.cursor.wHeight;
318 if (bestEntry) return bestEntry;
320 /* Now find the smallest one larger than the requested size */
322 maxwidth = maxheight = 255;
323 for(i = 0,entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
324 if ((entry->ResInfo.cursor.wWidth < maxwidth) && (entry->ResInfo.cursor.wHeight < maxheight) &&
325 (entry->wBitCount == 1))
327 bestEntry = entry;
328 maxwidth = entry->ResInfo.cursor.wWidth;
329 maxheight = entry->ResInfo.cursor.wHeight;
332 return bestEntry;
335 /*********************************************************************
336 * The main purpose of this function is to create fake resource directory
337 * and fake resource entries. There are several reasons for this:
338 * - CURSORICONDIR and CURSORICONFILEDIR differ in sizes and their
339 * fields
340 * There are some "bad" cursor files which do not have
341 * bColorCount initialized but instead one must read this info
342 * directly from corresponding DIB sections
343 * Note: wResId is index to array of pointer returned in ptrs (origin is 1)
345 BOOL CURSORICON_SimulateLoadingFromResourceW( LPWSTR filename, BOOL fCursor,
346 CURSORICONDIR **res, LPBYTE **ptr)
348 LPBYTE _free;
349 CURSORICONFILEDIR *bits;
350 int entries, size, i;
352 *res = NULL;
353 *ptr = NULL;
354 if (!(bits = (CURSORICONFILEDIR *)VIRTUAL_MapFileW( filename ))) return FALSE;
356 /* FIXME: test for inimated icons
357 * hack to load the first icon from the *.ani file
359 if ( *(LPDWORD)bits==0x46464952 ) /* "RIFF" */
360 { LPBYTE pos = (LPBYTE) bits;
361 FIXME_(cursor)("Animated icons not correctly implemented! %p \n", bits);
363 for (;;)
364 { if (*(LPDWORD)pos==0x6e6f6369) /* "icon" */
365 { FIXME_(cursor)("icon entry found! %p\n", bits);
366 pos+=4;
367 if ( !*(LPWORD) pos==0x2fe) /* iconsize */
368 { goto fail;
370 bits=(CURSORICONFILEDIR*)(pos+4);
371 FIXME_(cursor)("icon size ok. offset=%p \n", bits);
372 break;
374 pos+=2;
375 if (pos>=(LPBYTE)bits+766) goto fail;
378 if (!(entries = bits->idCount)) goto fail;
379 size = sizeof(CURSORICONDIR) + sizeof(CURSORICONDIRENTRY) * (entries - 1);
380 _free = (LPBYTE) size;
382 for (i=0; i < entries; i++)
383 size += bits->idEntries[i].dwDIBSize + (fCursor ? sizeof(POINT16): 0);
385 if (!(*ptr = HeapAlloc( GetProcessHeap(), 0,
386 entries * sizeof (CURSORICONDIRENTRY*)))) goto fail;
387 if (!(*res = HeapAlloc( GetProcessHeap(), 0, size))) goto fail;
389 _free = (LPBYTE)(*res) + (int)_free;
390 memcpy((*res), bits, 6);
391 for (i=0; i<entries; i++)
393 ((LPBYTE*)(*ptr))[i] = _free;
394 if (fCursor) {
395 (*res)->idEntries[i].ResInfo.cursor.wWidth=bits->idEntries[i].bWidth;
396 (*res)->idEntries[i].ResInfo.cursor.wHeight=bits->idEntries[i].bHeight;
397 ((LPPOINT16)_free)->x=bits->idEntries[i].xHotspot;
398 ((LPPOINT16)_free)->y=bits->idEntries[i].yHotspot;
399 _free+=sizeof(POINT16);
400 } else {
401 (*res)->idEntries[i].ResInfo.icon.bWidth=bits->idEntries[i].bWidth;
402 (*res)->idEntries[i].ResInfo.icon.bHeight=bits->idEntries[i].bHeight;
403 (*res)->idEntries[i].ResInfo.icon.bColorCount = bits->idEntries[i].bColorCount;
405 (*res)->idEntries[i].wPlanes=1;
406 (*res)->idEntries[i].wBitCount = ((LPBITMAPINFOHEADER)((LPBYTE)bits +
407 bits->idEntries[i].dwDIBOffset))->biBitCount;
408 (*res)->idEntries[i].dwBytesInRes = bits->idEntries[i].dwDIBSize;
409 (*res)->idEntries[i].wResId=i+1;
411 memcpy(_free,(LPBYTE)bits +bits->idEntries[i].dwDIBOffset,
412 (*res)->idEntries[i].dwBytesInRes);
413 _free += (*res)->idEntries[i].dwBytesInRes;
415 UnmapViewOfFile( bits );
416 return TRUE;
417 fail:
418 if (*res) HeapFree( GetProcessHeap(), 0, *res );
419 if (*ptr) HeapFree( GetProcessHeap(), 0, *ptr );
420 UnmapViewOfFile( bits );
421 return FALSE;
425 /**********************************************************************
426 * CURSORICON_CreateFromResource
428 * Create a cursor or icon from in-memory resource template.
430 * FIXME: Convert to mono when cFlag is LR_MONOCHROME. Do something
431 * with cbSize parameter as well.
433 static HGLOBAL16 CURSORICON_CreateFromResource( HINSTANCE16 hInstance, HGLOBAL16 hObj, LPBYTE bits,
434 UINT cbSize, BOOL bIcon, DWORD dwVersion,
435 INT width, INT height, UINT loadflags )
437 int sizeAnd, sizeXor;
438 HBITMAP hAndBits = 0, hXorBits = 0; /* error condition for later */
439 BITMAPOBJ *bmpXor, *bmpAnd;
440 POINT16 hotspot;
441 BITMAPINFO *bmi;
442 HDC hdc;
443 BOOL DoStretch;
444 INT size;
446 hotspot.x = ICON_HOTSPOT;
447 hotspot.y = ICON_HOTSPOT;
449 TRACE_(cursor)("%08x (%u bytes), ver %08x, %ix%i %s %s\n",
450 (unsigned)bits, cbSize, (unsigned)dwVersion, width, height,
451 bIcon ? "icon" : "cursor", (loadflags & LR_MONOCHROME) ? "mono" : "" );
452 if (dwVersion == 0x00020000)
454 FIXME_(cursor)("\t2.xx resources are not supported\n");
455 return 0;
458 if (bIcon)
459 bmi = (BITMAPINFO *)bits;
460 else /* get the hotspot */
462 POINT16 *pt = (POINT16 *)bits;
463 hotspot = *pt;
464 bmi = (BITMAPINFO *)(pt + 1);
466 size = DIB_BitmapInfoSize( bmi, DIB_RGB_COLORS );
468 if (!width) width = bmi->bmiHeader.biWidth;
469 if (!height) height = bmi->bmiHeader.biHeight/2;
470 DoStretch = (bmi->bmiHeader.biHeight/2 != height) ||
471 (bmi->bmiHeader.biWidth != width);
473 /* Check bitmap header */
475 if ( (bmi->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) &&
476 (bmi->bmiHeader.biSize != sizeof(BITMAPINFOHEADER) ||
477 bmi->bmiHeader.biCompression != BI_RGB) )
479 WARN_(cursor)("\tinvalid resource bitmap header.\n");
480 return 0;
483 if( (hdc = GetDC( 0 )) )
485 BITMAPINFO* pInfo;
487 /* Make sure we have room for the monochrome bitmap later on.
488 * Note that BITMAPINFOINFO and BITMAPCOREHEADER are the same
489 * up to and including the biBitCount. In-memory icon resource
490 * format is as follows:
492 * BITMAPINFOHEADER icHeader // DIB header
493 * RGBQUAD icColors[] // Color table
494 * BYTE icXOR[] // DIB bits for XOR mask
495 * BYTE icAND[] // DIB bits for AND mask
498 if ((pInfo = (BITMAPINFO *)HeapAlloc( GetProcessHeap(), 0,
499 MAX(size, sizeof(BITMAPINFOHEADER) + 2*sizeof(RGBQUAD)))))
501 memcpy( pInfo, bmi, size );
502 pInfo->bmiHeader.biHeight /= 2;
504 /* Create the XOR bitmap */
506 if (DoStretch) {
507 if(bIcon)
509 hXorBits = CreateCompatibleBitmap(hdc, width, height);
511 else
513 hXorBits = CreateBitmap(width, height, 1, 1, NULL);
515 if(hXorBits)
517 HBITMAP hOld;
518 HDC hMem = CreateCompatibleDC(hdc);
519 BOOL res;
521 if (hMem) {
522 hOld = SelectObject(hMem, hXorBits);
523 res = StretchDIBits(hMem, 0, 0, width, height, 0, 0,
524 bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight/2,
525 (char*)bmi + size, pInfo, DIB_RGB_COLORS, SRCCOPY);
526 SelectObject(hMem, hOld);
527 DeleteDC(hMem);
528 } else res = FALSE;
529 if (!res) { DeleteObject(hXorBits); hXorBits = 0; }
531 } else hXorBits = CreateDIBitmap( hdc, &pInfo->bmiHeader,
532 CBM_INIT, (char*)bmi + size, pInfo, DIB_RGB_COLORS );
533 if( hXorBits )
535 char* bits = (char *)bmi + size +
536 DIB_GetDIBImageBytes(bmi->bmiHeader.biWidth,
537 bmi->bmiHeader.biHeight,
538 bmi->bmiHeader.biBitCount) / 2;
540 pInfo->bmiHeader.biBitCount = 1;
541 if (pInfo->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
543 RGBQUAD *rgb = pInfo->bmiColors;
545 pInfo->bmiHeader.biClrUsed = pInfo->bmiHeader.biClrImportant = 2;
546 rgb[0].rgbBlue = rgb[0].rgbGreen = rgb[0].rgbRed = 0x00;
547 rgb[1].rgbBlue = rgb[1].rgbGreen = rgb[1].rgbRed = 0xff;
548 rgb[0].rgbReserved = rgb[1].rgbReserved = 0;
550 else
552 RGBTRIPLE *rgb = (RGBTRIPLE *)(((BITMAPCOREHEADER *)pInfo) + 1);
554 rgb[0].rgbtBlue = rgb[0].rgbtGreen = rgb[0].rgbtRed = 0x00;
555 rgb[1].rgbtBlue = rgb[1].rgbtGreen = rgb[1].rgbtRed = 0xff;
558 /* Create the AND bitmap */
560 if (DoStretch) {
561 if ((hAndBits = CreateBitmap(width, height, 1, 1, NULL))) {
562 HBITMAP hOld;
563 HDC hMem = CreateCompatibleDC(hdc);
564 BOOL res;
566 if (hMem) {
567 hOld = SelectObject(hMem, hAndBits);
568 res = StretchDIBits(hMem, 0, 0, width, height, 0, 0,
569 pInfo->bmiHeader.biWidth, pInfo->bmiHeader.biHeight,
570 bits, pInfo, DIB_RGB_COLORS, SRCCOPY);
571 SelectObject(hMem, hOld);
572 DeleteDC(hMem);
573 } else res = FALSE;
574 if (!res) { DeleteObject(hAndBits); hAndBits = 0; }
576 } else hAndBits = CreateDIBitmap( hdc, &pInfo->bmiHeader,
577 CBM_INIT, bits, pInfo, DIB_RGB_COLORS );
579 if( !hAndBits ) DeleteObject( hXorBits );
581 HeapFree( GetProcessHeap(), 0, pInfo );
583 ReleaseDC( 0, hdc );
586 if( !hXorBits || !hAndBits )
588 WARN_(cursor)("\tunable to create an icon bitmap.\n");
589 return 0;
592 /* Now create the CURSORICONINFO structure */
593 bmpXor = (BITMAPOBJ *) GDI_GetObjPtr( hXorBits, BITMAP_MAGIC );
594 bmpAnd = (BITMAPOBJ *) GDI_GetObjPtr( hAndBits, BITMAP_MAGIC );
595 sizeXor = bmpXor->bitmap.bmHeight * bmpXor->bitmap.bmWidthBytes;
596 sizeAnd = bmpAnd->bitmap.bmHeight * bmpAnd->bitmap.bmWidthBytes;
598 if (hObj) hObj = GlobalReAlloc16( hObj,
599 sizeof(CURSORICONINFO) + sizeXor + sizeAnd, GMEM_MOVEABLE );
600 if (!hObj) hObj = GlobalAlloc16( GMEM_MOVEABLE,
601 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
602 if (hObj)
604 CURSORICONINFO *info;
606 /* Make it owned by the module */
607 if (hInstance) FarSetOwner16( hObj, GetExePtr(hInstance) );
609 info = (CURSORICONINFO *)GlobalLock16( hObj );
610 info->ptHotSpot.x = hotspot.x;
611 info->ptHotSpot.y = hotspot.y;
612 info->nWidth = bmpXor->bitmap.bmWidth;
613 info->nHeight = bmpXor->bitmap.bmHeight;
614 info->nWidthBytes = bmpXor->bitmap.bmWidthBytes;
615 info->bPlanes = bmpXor->bitmap.bmPlanes;
616 info->bBitsPerPixel = bmpXor->bitmap.bmBitsPixel;
618 /* Transfer the bitmap bits to the CURSORICONINFO structure */
620 GetBitmapBits( hAndBits, sizeAnd, (char *)(info + 1) );
621 GetBitmapBits( hXorBits, sizeXor, (char *)(info + 1) + sizeAnd );
622 GlobalUnlock16( hObj );
625 DeleteObject( hXorBits );
626 DeleteObject( hAndBits );
627 return hObj;
631 /**********************************************************************
632 * CreateIconFromResourceEx16 (USER.450)
634 * FIXME: not sure about exact parameter types
636 HICON16 WINAPI CreateIconFromResourceEx16( LPBYTE bits, UINT16 cbSize, BOOL16 bIcon,
637 DWORD dwVersion, INT16 width, INT16 height, UINT16 cFlag )
639 return CreateIconFromResourceEx(bits, cbSize, bIcon, dwVersion,
640 width, height, cFlag);
644 /**********************************************************************
645 * CreateIconFromResource (USER32.76)
647 HICON WINAPI CreateIconFromResource( LPBYTE bits, UINT cbSize,
648 BOOL bIcon, DWORD dwVersion)
650 return CreateIconFromResourceEx( bits, cbSize, bIcon, dwVersion, 0,0,0);
654 /**********************************************************************
655 * CreateIconFromResourceEx32 (USER32.77)
657 HICON WINAPI CreateIconFromResourceEx( LPBYTE bits, UINT cbSize,
658 BOOL bIcon, DWORD dwVersion,
659 INT width, INT height,
660 UINT cFlag )
662 TDB* pTask = (TDB*)GlobalLock16( GetCurrentTask() );
663 if( pTask )
664 return CURSORICON_CreateFromResource( pTask->hInstance, 0, bits, cbSize, bIcon, dwVersion,
665 width, height, cFlag );
666 return 0;
669 /**********************************************************************
670 * CURSORICON_Load
672 * Load a cursor or icon from resource or file.
674 HGLOBAL CURSORICON_Load( HINSTANCE hInstance, LPCWSTR name,
675 INT width, INT height, INT colors,
676 BOOL fCursor, UINT loadflags )
678 HANDLE handle = 0, h = 0;
679 HANDLE hRsrc;
680 CURSORICONDIR *dir;
681 CURSORICONDIRENTRY *dirEntry;
682 LPBYTE bits;
684 if ( loadflags & LR_LOADFROMFILE ) /* Load from file */
686 LPBYTE *ptr;
687 if (!CURSORICON_SimulateLoadingFromResourceW((LPWSTR)name, fCursor, &dir, &ptr))
688 return 0;
689 if (fCursor)
690 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor(dir, width, height, 1);
691 else
692 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon(dir, width, height, colors);
693 bits = ptr[dirEntry->wResId-1];
694 h = CURSORICON_CreateFromResource( 0, 0, bits, dirEntry->dwBytesInRes,
695 !fCursor, 0x00030000, width, height, loadflags);
696 HeapFree( GetProcessHeap(), 0, dir );
697 HeapFree( GetProcessHeap(), 0, ptr );
700 else if ( !hInstance ) /* Load OEM cursor/icon */
702 WORD resid;
703 HDC hdc;
705 if ( HIWORD(name) )
707 LPSTR ansi = HEAP_strdupWtoA(GetProcessHeap(),0,name);
708 if( ansi[0]=='#') /*Check for '#xxx' name */
710 resid = atoi(ansi+1);
711 HeapFree( GetProcessHeap(), 0, ansi );
713 else
715 HeapFree( GetProcessHeap(), 0, ansi );
716 return 0;
719 else resid = LOWORD(name);
720 hdc = CreateDCA( "DISPLAY", NULL, NULL, NULL );
721 if (hdc) {
722 DC *dc = DC_GetDCPtr( hdc );
723 if (dc->funcs->pLoadOEMResource)
724 h = dc->funcs->pLoadOEMResource( resid, fCursor ? OEM_CURSOR : OEM_ICON );
725 GDI_HEAP_UNLOCK( hdc );
726 DeleteDC( hdc );
730 else /* Load from resource */
732 HANDLE hGroupRsrc;
733 WORD wResId;
734 DWORD dwBytesInRes;
736 /* Normalize hInstance (must be uniquely represented for icon cache) */
738 if ( HIWORD( hInstance ) )
739 hInstance = MapHModuleLS( hInstance );
740 else
741 hInstance = GetExePtr( hInstance );
743 /* Get directory resource ID */
745 if (!(hRsrc = FindResourceW( hInstance, name,
746 fCursor ? RT_GROUP_CURSORW : RT_GROUP_ICONW )))
747 return 0;
748 hGroupRsrc = hRsrc;
749 /* If shared icon, check whether it was already loaded */
751 if ( (loadflags & LR_SHARED)
752 && (h = CURSORICON_FindSharedIcon( hInstance, hRsrc ) ) != 0 )
753 return h;
755 /* Find the best entry in the directory */
757 if (!(handle = LoadResource( hInstance, hRsrc ))) return 0;
758 if (!(dir = (CURSORICONDIR*)LockResource( handle ))) return 0;
759 if (fCursor)
760 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor( dir,
761 width, height, 1);
762 else
763 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon( dir,
764 width, height, colors );
765 if (!dirEntry) return 0;
766 wResId = dirEntry->wResId;
767 dwBytesInRes = dirEntry->dwBytesInRes;
768 FreeResource( handle );
770 /* Load the resource */
772 if (!(hRsrc = FindResourceW(hInstance,MAKEINTRESOURCEW(wResId),
773 fCursor ? RT_CURSORW : RT_ICONW ))) return 0;
774 if (!(handle = LoadResource( hInstance, hRsrc ))) return 0;
775 bits = (LPBYTE)LockResource( handle );
776 h = CURSORICON_CreateFromResource( 0, 0, bits, dwBytesInRes,
777 !fCursor, 0x00030000, width, height, loadflags);
778 FreeResource( handle );
780 /* If shared icon, add to icon cache */
782 if ( h && (loadflags & LR_SHARED) )
783 CURSORICON_AddSharedIcon( hInstance, hRsrc, hGroupRsrc, h );
786 return h;
789 /***********************************************************************
790 * CURSORICON_Copy
792 * Make a copy of a cursor or icon.
794 static HGLOBAL16 CURSORICON_Copy( HINSTANCE16 hInstance, HGLOBAL16 handle )
796 char *ptrOld, *ptrNew;
797 int size;
798 HGLOBAL16 hNew;
800 if (!(ptrOld = (char *)GlobalLock16( handle ))) return 0;
801 if (!(hInstance = GetExePtr( hInstance ))) return 0;
802 size = GlobalSize16( handle );
803 hNew = GlobalAlloc16( GMEM_MOVEABLE, size );
804 FarSetOwner16( hNew, hInstance );
805 ptrNew = (char *)GlobalLock16( hNew );
806 memcpy( ptrNew, ptrOld, size );
807 GlobalUnlock16( handle );
808 GlobalUnlock16( hNew );
809 return hNew;
812 /*************************************************************************
813 * CURSORICON_ExtCopy
815 * Copies an Image from the Cache if LR_COPYFROMRESOURCE is specified
817 * PARAMS
818 * Handle [I] handle to an Image
819 * nType [I] Type of Handle (IMAGE_CURSOR | IMAGE_ICON)
820 * iDesiredCX [I] The Desired width of the Image
821 * iDesiredCY [I] The desired height of the Image
822 * nFlags [I] The flags from CopyImage
824 * RETURNS
825 * Success: The new handle of the Image
827 * NOTES
828 * LR_COPYDELETEORG and LR_MONOCHROME are currently not implemented.
829 * LR_MONOCHROME should be implemented by CURSORICON_CreateFromResource.
830 * LR_COPYFROMRESOURCE will only work if the Image is in the Cache.
835 HGLOBAL CURSORICON_ExtCopy(HGLOBAL Handle, UINT nType,
836 INT iDesiredCX, INT iDesiredCY,
837 UINT nFlags)
839 HGLOBAL16 hNew=0;
841 TRACE_(icon)("Handle %u, uType %u, iDesiredCX %i, iDesiredCY %i, nFlags %u\n",
842 Handle, nType, iDesiredCX, iDesiredCY, nFlags);
844 if(Handle == 0)
846 return 0;
849 /* Best Fit or Monochrome */
850 if( (nFlags & LR_COPYFROMRESOURCE
851 && (iDesiredCX > 0 || iDesiredCY > 0))
852 || nFlags & LR_MONOCHROME)
854 ICONCACHE* pIconCache = CURSORICON_FindCache(Handle);
856 /* Not Found in Cache, then do a strait copy
858 if(pIconCache == NULL)
860 TDB* pTask = (TDB *) GlobalLock16 (GetCurrentTask ());
861 hNew = CURSORICON_Copy(pTask->hInstance, Handle);
862 if(nFlags & LR_COPYFROMRESOURCE)
864 TRACE_(icon)("LR_COPYFROMRESOURCE: Failed to load from cache\n");
867 else
869 int iTargetCX, iTargetCY;
870 LPBYTE pBits;
871 HANDLE hMem;
872 HRSRC hRsrc;
873 DWORD dwBytesInRes;
874 WORD wResId;
875 CURSORICONDIR *pDir;
876 CURSORICONDIRENTRY *pDirEntry;
877 BOOL bIsIcon = (nType == IMAGE_ICON);
879 /* Completing iDesiredCX CY for Monochrome Bitmaps if needed
881 if(((nFlags & LR_MONOCHROME) && !(nFlags & LR_COPYFROMRESOURCE))
882 || (iDesiredCX == 0 && iDesiredCY == 0))
884 iDesiredCY = GetSystemMetrics(bIsIcon ?
885 SM_CYICON : SM_CYCURSOR);
886 iDesiredCX = GetSystemMetrics(bIsIcon ?
887 SM_CXICON : SM_CXCURSOR);
890 /* Retreive the CURSORICONDIRENTRY
892 if (!(hMem = LoadResource( pIconCache->hModule ,
893 pIconCache->hGroupRsrc)))
895 return 0;
897 if (!(pDir = (CURSORICONDIR*)LockResource( hMem )))
899 return 0;
902 /* Find Best Fit
904 if(bIsIcon)
906 pDirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon(
907 pDir, iDesiredCX, iDesiredCY, 256);
909 else
911 pDirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor(
912 pDir, iDesiredCX, iDesiredCY, 1);
915 wResId = pDirEntry->wResId;
916 dwBytesInRes = pDirEntry->dwBytesInRes;
917 FreeResource(hMem);
919 TRACE_(icon)("ResID %u, BytesInRes %lu, Width %d, Height %d DX %d, DY %d\n",
920 wResId, dwBytesInRes, pDirEntry->ResInfo.icon.bWidth,
921 pDirEntry->ResInfo.icon.bHeight, iDesiredCX, iDesiredCY);
923 /* Get the Best Fit
925 if (!(hRsrc = FindResourceW(pIconCache->hModule ,
926 MAKEINTRESOURCEW(wResId), bIsIcon ? RT_ICONW : RT_CURSORW)))
928 return 0;
930 if (!(hMem = LoadResource( pIconCache->hModule , hRsrc )))
932 return 0;
935 pBits = (LPBYTE)LockResource( hMem );
937 iTargetCY = GetSystemMetrics(SM_CYICON);
938 iTargetCX = GetSystemMetrics(SM_CXICON);
940 /* Create a New Icon with the proper dimension
942 hNew = CURSORICON_CreateFromResource( 0, 0, pBits, dwBytesInRes,
943 bIsIcon, 0x00030000, iTargetCX, iTargetCY, nFlags);
944 FreeResource(hMem);
947 else
949 TDB* pTask = (TDB *) GlobalLock16 (GetCurrentTask ());
950 hNew = CURSORICON_Copy(pTask->hInstance, Handle);
952 return hNew;
955 /***********************************************************************
956 * CURSORICON_IconToCursor
958 * Converts bitmap to mono and truncates if icon is too large (should
959 * probably do StretchBlt() instead).
961 HCURSOR16 CURSORICON_IconToCursor(HICON16 hIcon, BOOL bSemiTransparent)
963 HCURSOR16 hRet = 0;
964 CURSORICONINFO *pIcon = NULL;
965 HTASK16 hTask = GetCurrentTask();
966 TDB* pTask = (TDB *)GlobalLock16(hTask);
968 if(hIcon && pTask)
969 if (!(pIcon = (CURSORICONINFO*)GlobalLock16( hIcon ))) return FALSE;
970 if (pIcon->bPlanes * pIcon->bBitsPerPixel == 1)
972 hRet = CURSORICON_Copy( pTask->hInstance, hIcon );
975 pIcon = GlobalLock16(hRet);
977 pIcon->ptHotSpot.x = pIcon->ptHotSpot.y = 15;
979 GlobalUnlock(hRet);
981 else
983 BYTE pAndBits[128];
984 BYTE pXorBits[128];
985 int maxx, maxy, ix, iy, bpp = pIcon->bBitsPerPixel;
986 BYTE* psPtr, *pxbPtr = pXorBits;
987 unsigned xor_width, and_width, val_base = 0xffffffff >> (32 - bpp);
988 BYTE* pbc = NULL;
990 CURSORICONINFO cI;
992 TRACE_(icon)("[%04x] %ix%i %ibpp (bogus %ibps)\n",
993 hIcon, pIcon->nWidth, pIcon->nHeight, pIcon->bBitsPerPixel, pIcon->nWidthBytes );
995 xor_width = BITMAP_GetWidthBytes( pIcon->nWidth, bpp );
996 and_width = BITMAP_GetWidthBytes( pIcon->nWidth, 1 );
997 psPtr = (BYTE *)(pIcon + 1) + pIcon->nHeight * and_width;
999 memset(pXorBits, 0, 128);
1000 cI.bBitsPerPixel = 1; cI.bPlanes = 1;
1001 cI.ptHotSpot.x = cI.ptHotSpot.y = 15;
1002 cI.nWidth = 32; cI.nHeight = 32;
1003 cI.nWidthBytes = 4; /* 32x1bpp */
1005 maxx = (pIcon->nWidth > 32) ? 32 : pIcon->nWidth;
1006 maxy = (pIcon->nHeight > 32) ? 32 : pIcon->nHeight;
1008 for( iy = 0; iy < maxy; iy++ )
1010 unsigned shift = iy % 2;
1012 memcpy( pAndBits + iy * 4, (BYTE *)(pIcon + 1) + iy * and_width,
1013 (and_width > 4) ? 4 : and_width );
1014 for( ix = 0; ix < maxx; ix++ )
1016 if( bSemiTransparent && ((ix+shift)%2) )
1018 /* set AND bit, XOR bit stays 0 */
1020 pbc = pAndBits + iy * 4 + ix/8;
1021 *pbc |= 0x80 >> (ix%8);
1023 else
1025 /* keep AND bit, set XOR bit */
1027 unsigned *psc = (unsigned*)(psPtr + (ix * bpp)/8);
1028 unsigned val = ((*psc) >> (ix * bpp)%8) & val_base;
1029 if(!PALETTE_Driver->pIsDark(val))
1031 pbc = pxbPtr + ix/8;
1032 *pbc |= 0x80 >> (ix%8);
1036 psPtr += xor_width;
1037 pxbPtr += 4;
1040 hRet = CreateCursorIconIndirect16( pTask->hInstance , &cI, pAndBits, pXorBits);
1042 if( !hRet ) /* fall back on default drag cursor */
1043 hRet = CURSORICON_Copy( pTask->hInstance ,
1044 CURSORICON_Load(0,MAKEINTRESOURCEW(OCR_DRAGOBJECT),
1045 GetSystemMetrics(SM_CXCURSOR),
1046 GetSystemMetrics(SM_CYCURSOR), 1, TRUE, 0) );
1049 return hRet;
1053 /***********************************************************************
1054 * LoadCursor16 (USER.173)
1056 HCURSOR16 WINAPI LoadCursor16( HINSTANCE16 hInstance, SEGPTR name )
1058 LPCSTR nameStr = HIWORD(name)? PTR_SEG_TO_LIN(name) : (LPCSTR)name;
1059 return LoadCursorA( hInstance, nameStr );
1063 /***********************************************************************
1064 * LoadIcon16 (USER.174)
1066 HICON16 WINAPI LoadIcon16( HINSTANCE16 hInstance, SEGPTR name )
1068 LPCSTR nameStr = HIWORD(name)? PTR_SEG_TO_LIN(name) : (LPCSTR)name;
1069 return LoadIconA( hInstance, nameStr );
1073 /***********************************************************************
1074 * CreateCursor16 (USER.406)
1076 HCURSOR16 WINAPI CreateCursor16( HINSTANCE16 hInstance,
1077 INT16 xHotSpot, INT16 yHotSpot,
1078 INT16 nWidth, INT16 nHeight,
1079 LPCVOID lpANDbits, LPCVOID lpXORbits )
1081 CURSORICONINFO info;
1083 TRACE_(cursor)("%dx%d spot=%d,%d xor=%p and=%p\n",
1084 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
1086 info.ptHotSpot.x = xHotSpot;
1087 info.ptHotSpot.y = yHotSpot;
1088 info.nWidth = nWidth;
1089 info.nHeight = nHeight;
1090 info.nWidthBytes = 0;
1091 info.bPlanes = 1;
1092 info.bBitsPerPixel = 1;
1094 return CreateCursorIconIndirect16( hInstance, &info, lpANDbits, lpXORbits );
1098 /***********************************************************************
1099 * CreateCursor32 (USER32.67)
1101 HCURSOR WINAPI CreateCursor( HINSTANCE hInstance,
1102 INT xHotSpot, INT yHotSpot,
1103 INT nWidth, INT nHeight,
1104 LPCVOID lpANDbits, LPCVOID lpXORbits )
1106 CURSORICONINFO info;
1108 TRACE_(cursor)("%dx%d spot=%d,%d xor=%p and=%p\n",
1109 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
1111 info.ptHotSpot.x = xHotSpot;
1112 info.ptHotSpot.y = yHotSpot;
1113 info.nWidth = nWidth;
1114 info.nHeight = nHeight;
1115 info.nWidthBytes = 0;
1116 info.bPlanes = 1;
1117 info.bBitsPerPixel = 1;
1119 return CreateCursorIconIndirect16( 0, &info, lpANDbits, lpXORbits );
1123 /***********************************************************************
1124 * CreateIcon16 (USER.407)
1126 HICON16 WINAPI CreateIcon16( HINSTANCE16 hInstance, INT16 nWidth,
1127 INT16 nHeight, BYTE bPlanes, BYTE bBitsPixel,
1128 LPCVOID lpANDbits, LPCVOID lpXORbits )
1130 CURSORICONINFO info;
1132 TRACE_(icon)("%dx%dx%d, xor=%p, and=%p\n",
1133 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
1135 info.ptHotSpot.x = ICON_HOTSPOT;
1136 info.ptHotSpot.y = ICON_HOTSPOT;
1137 info.nWidth = nWidth;
1138 info.nHeight = nHeight;
1139 info.nWidthBytes = 0;
1140 info.bPlanes = bPlanes;
1141 info.bBitsPerPixel = bBitsPixel;
1143 return CreateCursorIconIndirect16( hInstance, &info, lpANDbits, lpXORbits );
1147 /***********************************************************************
1148 * CreateIcon32 (USER32.75)
1150 HICON WINAPI CreateIcon( HINSTANCE hInstance, INT nWidth,
1151 INT nHeight, BYTE bPlanes, BYTE bBitsPixel,
1152 LPCVOID lpANDbits, LPCVOID lpXORbits )
1154 CURSORICONINFO info;
1156 TRACE_(icon)("%dx%dx%d, xor=%p, and=%p\n",
1157 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
1159 info.ptHotSpot.x = ICON_HOTSPOT;
1160 info.ptHotSpot.y = ICON_HOTSPOT;
1161 info.nWidth = nWidth;
1162 info.nHeight = nHeight;
1163 info.nWidthBytes = 0;
1164 info.bPlanes = bPlanes;
1165 info.bBitsPerPixel = bBitsPixel;
1167 return CreateCursorIconIndirect16( 0, &info, lpANDbits, lpXORbits );
1171 /***********************************************************************
1172 * CreateCursorIconIndirect (USER.408)
1174 HGLOBAL16 WINAPI CreateCursorIconIndirect16( HINSTANCE16 hInstance,
1175 CURSORICONINFO *info,
1176 LPCVOID lpANDbits,
1177 LPCVOID lpXORbits )
1179 HGLOBAL16 handle;
1180 char *ptr;
1181 int sizeAnd, sizeXor;
1183 hInstance = GetExePtr( hInstance ); /* Make it a module handle */
1184 if (!lpXORbits || !lpANDbits || info->bPlanes != 1) return 0;
1185 info->nWidthBytes = BITMAP_GetWidthBytes(info->nWidth,info->bBitsPerPixel);
1186 sizeXor = info->nHeight * info->nWidthBytes;
1187 sizeAnd = info->nHeight * BITMAP_GetWidthBytes( info->nWidth, 1 );
1188 if (!(handle = GlobalAlloc16( GMEM_MOVEABLE,
1189 sizeof(CURSORICONINFO) + sizeXor + sizeAnd)))
1190 return 0;
1191 if (hInstance) FarSetOwner16( handle, hInstance );
1192 ptr = (char *)GlobalLock16( handle );
1193 memcpy( ptr, info, sizeof(*info) );
1194 memcpy( ptr + sizeof(CURSORICONINFO), lpANDbits, sizeAnd );
1195 memcpy( ptr + sizeof(CURSORICONINFO) + sizeAnd, lpXORbits, sizeXor );
1196 GlobalUnlock16( handle );
1197 return handle;
1201 /***********************************************************************
1202 * CopyIcon16 (USER.368)
1204 HICON16 WINAPI CopyIcon16( HINSTANCE16 hInstance, HICON16 hIcon )
1206 TRACE_(icon)("%04x %04x\n", hInstance, hIcon );
1207 return CURSORICON_Copy( hInstance, hIcon );
1211 /***********************************************************************
1212 * CopyIcon32 (USER32.60)
1214 HICON WINAPI CopyIcon( HICON hIcon )
1216 HTASK16 hTask = GetCurrentTask ();
1217 TDB* pTask = (TDB *) GlobalLock16 (hTask);
1218 TRACE_(icon)("%04x\n", hIcon );
1219 return CURSORICON_Copy( pTask->hInstance, hIcon );
1223 /***********************************************************************
1224 * CopyCursor16 (USER.369)
1226 HCURSOR16 WINAPI CopyCursor16( HINSTANCE16 hInstance, HCURSOR16 hCursor )
1228 TRACE_(cursor)("%04x %04x\n", hInstance, hCursor );
1229 return CURSORICON_Copy( hInstance, hCursor );
1232 /**********************************************************************
1233 * CURSORICON_Destroy (USER.610)
1235 * This routine is actually exported from Win95 USER under the name
1236 * DestroyIcon32 ... The behaviour implemented here should mimic
1237 * the Win95 one exactly, especially the return values, which
1238 * depend on the setting of various flags.
1240 WORD WINAPI CURSORICON_Destroy( HGLOBAL16 handle, UINT16 flags )
1242 WORD retv;
1244 TRACE_(icon)("(%04x, %04x)\n", handle, flags );
1246 /* Check whether destroying active cursor */
1248 if ( hActiveCursor == handle )
1250 ERR_(cursor)("Destroying active cursor!\n" );
1251 SetCursor( 0 );
1254 /* Try shared cursor/icon first */
1256 if ( !(flags & CID_NONSHARED) )
1258 INT count = CURSORICON_DelSharedIcon( handle );
1260 if ( count != -1 )
1261 return (flags & CID_WIN32)? TRUE : (count == 0);
1263 /* FIXME: OEM cursors/icons should be recognized */
1266 /* Now assume non-shared cursor/icon */
1268 retv = GlobalFree16( handle );
1269 return (flags & CID_RESOURCE)? retv : TRUE;
1272 /***********************************************************************
1273 * DestroyIcon16 (USER.457)
1275 BOOL16 WINAPI DestroyIcon16( HICON16 hIcon )
1277 return CURSORICON_Destroy( hIcon, 0 );
1280 /***********************************************************************
1281 * DestroyIcon (USER32.133)
1283 BOOL WINAPI DestroyIcon( HICON hIcon )
1285 return CURSORICON_Destroy( hIcon, CID_WIN32 );
1288 /***********************************************************************
1289 * DestroyCursor16 (USER.458)
1291 BOOL16 WINAPI DestroyCursor16( HCURSOR16 hCursor )
1293 return CURSORICON_Destroy( hCursor, 0 );
1296 /***********************************************************************
1297 * DestroyCursor (USER32.132)
1299 BOOL WINAPI DestroyCursor( HCURSOR hCursor )
1301 return CURSORICON_Destroy( hCursor, CID_WIN32 );
1305 /***********************************************************************
1306 * DrawIcon16 (USER.84)
1308 BOOL16 WINAPI DrawIcon16( HDC16 hdc, INT16 x, INT16 y, HICON16 hIcon )
1310 return DrawIcon( hdc, x, y, hIcon );
1314 /***********************************************************************
1315 * DrawIcon32 (USER32.159)
1317 BOOL WINAPI DrawIcon( HDC hdc, INT x, INT y, HICON hIcon )
1319 CURSORICONINFO *ptr;
1320 HDC hMemDC;
1321 HBITMAP hXorBits, hAndBits;
1322 COLORREF oldFg, oldBg;
1324 if (!(ptr = (CURSORICONINFO *)GlobalLock16( hIcon ))) return FALSE;
1325 if (!(hMemDC = CreateCompatibleDC( hdc ))) return FALSE;
1326 hAndBits = CreateBitmap( ptr->nWidth, ptr->nHeight, 1, 1,
1327 (char *)(ptr+1) );
1328 hXorBits = CreateBitmap( ptr->nWidth, ptr->nHeight, ptr->bPlanes,
1329 ptr->bBitsPerPixel, (char *)(ptr + 1)
1330 + ptr->nHeight * BITMAP_GetWidthBytes(ptr->nWidth,1) );
1331 oldFg = SetTextColor( hdc, RGB(0,0,0) );
1332 oldBg = SetBkColor( hdc, RGB(255,255,255) );
1334 if (hXorBits && hAndBits)
1336 HBITMAP hBitTemp = SelectObject( hMemDC, hAndBits );
1337 BitBlt( hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0, SRCAND );
1338 SelectObject( hMemDC, hXorBits );
1339 BitBlt(hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0,SRCINVERT);
1340 SelectObject( hMemDC, hBitTemp );
1342 DeleteDC( hMemDC );
1343 if (hXorBits) DeleteObject( hXorBits );
1344 if (hAndBits) DeleteObject( hAndBits );
1345 GlobalUnlock16( hIcon );
1346 SetTextColor( hdc, oldFg );
1347 SetBkColor( hdc, oldBg );
1348 return TRUE;
1352 /***********************************************************************
1353 * DumpIcon (USER.459)
1355 DWORD WINAPI DumpIcon16( SEGPTR pInfo, WORD *lpLen,
1356 SEGPTR *lpXorBits, SEGPTR *lpAndBits )
1358 CURSORICONINFO *info = PTR_SEG_TO_LIN( pInfo );
1359 int sizeAnd, sizeXor;
1361 if (!info) return 0;
1362 sizeXor = info->nHeight * info->nWidthBytes;
1363 sizeAnd = info->nHeight * BITMAP_GetWidthBytes( info->nWidth, 1 );
1364 if (lpAndBits) *lpAndBits = pInfo + sizeof(CURSORICONINFO);
1365 if (lpXorBits) *lpXorBits = pInfo + sizeof(CURSORICONINFO) + sizeAnd;
1366 if (lpLen) *lpLen = sizeof(CURSORICONINFO) + sizeAnd + sizeXor;
1367 return MAKELONG( sizeXor, sizeXor );
1371 /***********************************************************************
1372 * SetCursor16 (USER.69)
1374 HCURSOR16 WINAPI SetCursor16( HCURSOR16 hCursor )
1376 return (HCURSOR16)SetCursor( hCursor );
1380 /***********************************************************************
1381 * SetCursor32 (USER32.472)
1382 * RETURNS:
1383 * A handle to the previous cursor shape.
1385 HCURSOR WINAPI SetCursor(
1386 HCURSOR hCursor /* Handle of cursor to show */
1388 HCURSOR hOldCursor;
1390 if (hCursor == hActiveCursor) return hActiveCursor; /* No change */
1391 TRACE_(cursor)("%04x\n", hCursor );
1392 hOldCursor = hActiveCursor;
1393 hActiveCursor = hCursor;
1394 /* Change the cursor shape only if it is visible */
1395 if (CURSOR_ShowCount >= 0)
1397 DISPLAY_SetCursor( (CURSORICONINFO*)GlobalLock16( hActiveCursor ) );
1398 GlobalUnlock16( hActiveCursor );
1400 return hOldCursor;
1404 /***********************************************************************
1405 * SetCursorPos16 (USER.70)
1407 void WINAPI SetCursorPos16( INT16 x, INT16 y )
1409 SetCursorPos( x, y );
1413 /***********************************************************************
1414 * SetCursorPos32 (USER32.474)
1416 BOOL WINAPI SetCursorPos( INT x, INT y )
1418 DISPLAY_MoveCursor( x, y );
1419 return TRUE;
1423 /***********************************************************************
1424 * ShowCursor16 (USER.71)
1426 INT16 WINAPI ShowCursor16( BOOL16 bShow )
1428 return ShowCursor( bShow );
1432 /***********************************************************************
1433 * ShowCursor32 (USER32.530)
1435 INT WINAPI ShowCursor( BOOL bShow )
1437 TRACE_(cursor)("%d, count=%d\n",
1438 bShow, CURSOR_ShowCount );
1440 if (bShow)
1442 if (++CURSOR_ShowCount == 0) /* Show it */
1444 DISPLAY_SetCursor((CURSORICONINFO*)GlobalLock16( hActiveCursor ));
1445 GlobalUnlock16( hActiveCursor );
1448 else
1450 if (--CURSOR_ShowCount == -1) /* Hide it */
1451 DISPLAY_SetCursor( NULL );
1453 return CURSOR_ShowCount;
1457 /***********************************************************************
1458 * GetCursor16 (USER.247)
1460 HCURSOR16 WINAPI GetCursor16(void)
1462 return hActiveCursor;
1466 /***********************************************************************
1467 * GetCursor32 (USER32.227)
1469 HCURSOR WINAPI GetCursor(void)
1471 return hActiveCursor;
1475 /***********************************************************************
1476 * ClipCursor16 (USER.16)
1478 BOOL16 WINAPI ClipCursor16( const RECT16 *rect )
1480 if (!rect) SetRectEmpty( &CURSOR_ClipRect );
1481 else CONV_RECT16TO32( rect, &CURSOR_ClipRect );
1482 return TRUE;
1486 /***********************************************************************
1487 * ClipCursor32 (USER32.53)
1489 BOOL WINAPI ClipCursor( const RECT *rect )
1491 if (!rect) SetRectEmpty( &CURSOR_ClipRect );
1492 else CopyRect( &CURSOR_ClipRect, rect );
1493 return TRUE;
1497 /***********************************************************************
1498 * GetCursorPos16 (USER.17)
1500 BOOL16 WINAPI GetCursorPos16( POINT16 *pt )
1502 DWORD posX, posY, state;
1504 if (!pt) return 0;
1505 if (!EVENT_QueryPointer( &posX, &posY, &state ))
1506 pt->x = pt->y = 0;
1507 else
1509 pt->x = posX;
1510 pt->y = posY;
1511 if (state & MK_LBUTTON)
1512 AsyncMouseButtonsStates[0] = MouseButtonsStates[0] = TRUE;
1513 else
1514 MouseButtonsStates[0] = FALSE;
1515 if (state & MK_MBUTTON)
1516 AsyncMouseButtonsStates[1] = MouseButtonsStates[1] = TRUE;
1517 else
1518 MouseButtonsStates[1] = FALSE;
1519 if (state & MK_RBUTTON)
1520 AsyncMouseButtonsStates[2] = MouseButtonsStates[2] = TRUE;
1521 else
1522 MouseButtonsStates[2] = FALSE;
1524 TRACE_(cursor)("ret=%d,%d\n", pt->x, pt->y );
1525 return 1;
1529 /***********************************************************************
1530 * GetCursorPos32 (USER32.229)
1532 BOOL WINAPI GetCursorPos( POINT *pt )
1534 BOOL ret;
1536 POINT16 pt16;
1537 ret = GetCursorPos16( &pt16 );
1538 if (pt) CONV_POINT16TO32( &pt16, pt );
1539 return ((pt) ? ret : 0);
1543 /***********************************************************************
1544 * GetClipCursor16 (USER.309)
1546 void WINAPI GetClipCursor16( RECT16 *rect )
1548 if (rect) CONV_RECT32TO16( &CURSOR_ClipRect, rect );
1552 /***********************************************************************
1553 * GetClipCursor32 (USER32.221)
1555 BOOL WINAPI GetClipCursor( RECT *rect )
1557 if (rect)
1559 CopyRect( rect, &CURSOR_ClipRect );
1560 return TRUE;
1562 return FALSE;
1565 /**********************************************************************
1566 * LookupIconIdFromDirectoryEx16 (USER.364)
1568 * FIXME: exact parameter sizes
1570 INT16 WINAPI LookupIconIdFromDirectoryEx16( LPBYTE xdir, BOOL16 bIcon,
1571 INT16 width, INT16 height, UINT16 cFlag )
1573 CURSORICONDIR *dir = (CURSORICONDIR*)xdir;
1574 UINT16 retVal = 0;
1575 if( dir && !dir->idReserved && (dir->idType & 3) )
1577 CURSORICONDIRENTRY* entry;
1578 HDC hdc;
1579 UINT palEnts;
1580 int colors;
1581 hdc = GetDC(0);
1582 palEnts = GetSystemPaletteEntries(hdc, 0, 0, NULL);
1583 if (palEnts == 0)
1584 palEnts = 256;
1585 colors = (cFlag & LR_MONOCHROME) ? 2 : palEnts;
1587 ReleaseDC(0, hdc);
1589 if( bIcon )
1590 entry = CURSORICON_FindBestIcon( dir, width, height, colors );
1591 else
1592 entry = CURSORICON_FindBestCursor( dir, width, height, 1);
1594 if( entry ) retVal = entry->wResId;
1596 else WARN_(cursor)("invalid resource directory\n");
1597 return retVal;
1600 /**********************************************************************
1601 * LookupIconIdFromDirectoryEx32 (USER32.380)
1603 INT WINAPI LookupIconIdFromDirectoryEx( LPBYTE dir, BOOL bIcon,
1604 INT width, INT height, UINT cFlag )
1606 return LookupIconIdFromDirectoryEx16( dir, bIcon, width, height, cFlag );
1609 /**********************************************************************
1610 * LookupIconIdFromDirectory (USER.???)
1612 INT16 WINAPI LookupIconIdFromDirectory16( LPBYTE dir, BOOL16 bIcon )
1614 return LookupIconIdFromDirectoryEx16( dir, bIcon,
1615 bIcon ? GetSystemMetrics(SM_CXICON) : GetSystemMetrics(SM_CXCURSOR),
1616 bIcon ? GetSystemMetrics(SM_CYICON) : GetSystemMetrics(SM_CYCURSOR), bIcon ? 0 : LR_MONOCHROME );
1619 /**********************************************************************
1620 * LookupIconIdFromDirectory (USER32.379)
1622 INT WINAPI LookupIconIdFromDirectory( LPBYTE dir, BOOL bIcon )
1624 return LookupIconIdFromDirectoryEx( dir, bIcon,
1625 bIcon ? GetSystemMetrics(SM_CXICON) : GetSystemMetrics(SM_CXCURSOR),
1626 bIcon ? GetSystemMetrics(SM_CYICON) : GetSystemMetrics(SM_CYCURSOR), bIcon ? 0 : LR_MONOCHROME );
1629 /**********************************************************************
1630 * GetIconID (USER.455)
1632 WORD WINAPI GetIconID16( HGLOBAL16 hResource, DWORD resType )
1634 LPBYTE lpDir = (LPBYTE)GlobalLock16(hResource);
1636 TRACE_(cursor)("hRes=%04x, entries=%i\n",
1637 hResource, lpDir ? ((CURSORICONDIR*)lpDir)->idCount : 0);
1639 switch(resType)
1641 case RT_CURSOR16:
1642 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, FALSE,
1643 GetSystemMetrics(SM_CXCURSOR), GetSystemMetrics(SM_CYCURSOR), LR_MONOCHROME );
1644 case RT_ICON16:
1645 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, TRUE,
1646 GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), 0 );
1647 default:
1648 WARN_(cursor)("invalid res type %ld\n", resType );
1650 return 0;
1653 /**********************************************************************
1654 * LoadCursorIconHandler (USER.336)
1656 * Supposed to load resources of Windows 2.x applications.
1658 HGLOBAL16 WINAPI LoadCursorIconHandler16( HGLOBAL16 hResource, HMODULE16 hModule, HRSRC16 hRsrc )
1660 FIXME_(cursor)("(%04x,%04x,%04x): old 2.x resources are not supported!\n",
1661 hResource, hModule, hRsrc);
1662 return (HGLOBAL16)0;
1665 /**********************************************************************
1666 * LoadDIBIconHandler (USER.357)
1668 * RT_ICON resource loader, installed by USER_SignalProc when module
1669 * is initialized.
1671 HGLOBAL16 WINAPI LoadDIBIconHandler16( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1673 /* If hResource is zero we must allocate a new memory block, if it's
1674 * non-zero but GlobalLock() returns NULL then it was discarded and
1675 * we have to recommit some memory, otherwise we just need to check
1676 * the block size. See LoadProc() in 16-bit SDK for more.
1679 hMemObj = NE_DefResourceHandler( hMemObj, hModule, hRsrc );
1680 if( hMemObj )
1682 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1683 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1684 SizeofResource16(hModule, hRsrc), TRUE, 0x00030000,
1685 GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), LR_DEFAULTCOLOR );
1687 return hMemObj;
1690 /**********************************************************************
1691 * LoadDIBCursorHandler (USER.356)
1693 * RT_CURSOR resource loader. Same as above.
1695 HGLOBAL16 WINAPI LoadDIBCursorHandler16( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1697 hMemObj = NE_DefResourceHandler( hMemObj, hModule, hRsrc );
1698 if( hMemObj )
1700 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1701 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1702 SizeofResource16(hModule, hRsrc), FALSE, 0x00030000,
1703 GetSystemMetrics(SM_CXCURSOR), GetSystemMetrics(SM_CYCURSOR), LR_MONOCHROME );
1705 return hMemObj;
1708 /**********************************************************************
1709 * LoadIconHandler (USER.456)
1711 HICON16 WINAPI LoadIconHandler16( HGLOBAL16 hResource, BOOL16 bNew )
1713 LPBYTE bits = (LPBYTE)LockResource16( hResource );
1715 TRACE_(cursor)("hRes=%04x\n",hResource);
1717 return CURSORICON_CreateFromResource( 0, 0, bits, 0, TRUE,
1718 bNew ? 0x00030000 : 0x00020000, 0, 0, LR_DEFAULTCOLOR );
1721 /***********************************************************************
1722 * LoadCursorW (USER32.362)
1724 HCURSOR WINAPI LoadCursorW(HINSTANCE hInstance, LPCWSTR name)
1726 return LoadImageW( hInstance, name, IMAGE_CURSOR, 0, 0,
1727 LR_SHARED | LR_DEFAULTSIZE );
1730 /***********************************************************************
1731 * LoadCursorA (USER32.359)
1733 HCURSOR WINAPI LoadCursorA(HINSTANCE hInstance, LPCSTR name)
1735 return LoadImageA( hInstance, name, IMAGE_CURSOR, 0, 0,
1736 LR_SHARED | LR_DEFAULTSIZE );
1739 /***********************************************************************
1740 * LoadCursorFromFileW (USER32.361)
1742 HCURSOR WINAPI LoadCursorFromFileW (LPCWSTR name)
1744 return LoadImageW( 0, name, IMAGE_CURSOR, 0, 0,
1745 LR_LOADFROMFILE | LR_DEFAULTSIZE );
1748 /***********************************************************************
1749 * LoadCursorFromFileA (USER32.360)
1751 HCURSOR WINAPI LoadCursorFromFileA (LPCSTR name)
1753 return LoadImageA( 0, name, IMAGE_CURSOR, 0, 0,
1754 LR_LOADFROMFILE | LR_DEFAULTSIZE );
1757 /***********************************************************************
1758 * LoadIconW (USER32.364)
1760 HICON WINAPI LoadIconW(HINSTANCE hInstance, LPCWSTR name)
1762 return LoadImageW( hInstance, name, IMAGE_ICON, 0, 0,
1763 LR_SHARED | LR_DEFAULTSIZE );
1766 /***********************************************************************
1767 * LoadIconA (USER32.363)
1769 HICON WINAPI LoadIconA(HINSTANCE hInstance, LPCSTR name)
1771 return LoadImageA( hInstance, name, IMAGE_ICON, 0, 0,
1772 LR_SHARED | LR_DEFAULTSIZE );
1775 /**********************************************************************
1776 * GetIconInfo16 (USER.395)
1778 BOOL16 WINAPI GetIconInfo16(HICON16 hIcon,LPICONINFO16 iconinfo)
1780 ICONINFO ii32;
1781 BOOL16 ret = GetIconInfo((HICON)hIcon, &ii32);
1783 iconinfo->fIcon = ii32.fIcon;
1784 iconinfo->xHotspot = ii32.xHotspot;
1785 iconinfo->yHotspot = ii32.yHotspot;
1786 iconinfo->hbmMask = ii32.hbmMask;
1787 iconinfo->hbmColor = ii32.hbmColor;
1788 return ret;
1791 /**********************************************************************
1792 * GetIconInfo32 (USER32.242)
1794 BOOL WINAPI GetIconInfo(HICON hIcon,LPICONINFO iconinfo) {
1795 CURSORICONINFO *ciconinfo;
1797 ciconinfo = GlobalLock16(hIcon);
1798 if (!ciconinfo)
1799 return FALSE;
1801 if ( (ciconinfo->ptHotSpot.x == ICON_HOTSPOT) &&
1802 (ciconinfo->ptHotSpot.y == ICON_HOTSPOT) )
1804 iconinfo->fIcon = TRUE;
1805 iconinfo->xHotspot = 0;
1806 iconinfo->yHotspot = 0;
1808 else
1810 iconinfo->fIcon = FALSE;
1811 iconinfo->xHotspot = ciconinfo->ptHotSpot.x;
1812 iconinfo->yHotspot = ciconinfo->ptHotSpot.y;
1815 iconinfo->hbmColor = CreateBitmap ( ciconinfo->nWidth, ciconinfo->nHeight,
1816 ciconinfo->bPlanes, ciconinfo->bBitsPerPixel,
1817 (char *)(ciconinfo + 1)
1818 + ciconinfo->nHeight *
1819 BITMAP_GetWidthBytes (ciconinfo->nWidth,1) );
1820 iconinfo->hbmMask = CreateBitmap ( ciconinfo->nWidth, ciconinfo->nHeight,
1821 1, 1, (char *)(ciconinfo + 1));
1823 GlobalUnlock16(hIcon);
1825 return TRUE;
1828 /**********************************************************************
1829 * CreateIconIndirect (USER32.78)
1831 HICON WINAPI CreateIconIndirect(LPICONINFO iconinfo) {
1832 BITMAPOBJ *bmpXor,*bmpAnd;
1833 HICON hObj;
1834 int sizeXor,sizeAnd;
1836 bmpXor = (BITMAPOBJ *) GDI_GetObjPtr( iconinfo->hbmColor, BITMAP_MAGIC );
1837 bmpAnd = (BITMAPOBJ *) GDI_GetObjPtr( iconinfo->hbmMask, BITMAP_MAGIC );
1839 sizeXor = bmpXor->bitmap.bmHeight * bmpXor->bitmap.bmWidthBytes;
1840 sizeAnd = bmpAnd->bitmap.bmHeight * bmpAnd->bitmap.bmWidthBytes;
1842 hObj = GlobalAlloc16( GMEM_MOVEABLE,
1843 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
1844 if (hObj)
1846 CURSORICONINFO *info;
1848 info = (CURSORICONINFO *)GlobalLock16( hObj );
1850 /* If we are creating an icon, the hotspot is unused */
1851 if (iconinfo->fIcon)
1853 info->ptHotSpot.x = ICON_HOTSPOT;
1854 info->ptHotSpot.y = ICON_HOTSPOT;
1856 else
1858 info->ptHotSpot.x = iconinfo->xHotspot;
1859 info->ptHotSpot.y = iconinfo->yHotspot;
1862 info->nWidth = bmpXor->bitmap.bmWidth;
1863 info->nHeight = bmpXor->bitmap.bmHeight;
1864 info->nWidthBytes = bmpXor->bitmap.bmWidthBytes;
1865 info->bPlanes = bmpXor->bitmap.bmPlanes;
1866 info->bBitsPerPixel = bmpXor->bitmap.bmBitsPixel;
1868 /* Transfer the bitmap bits to the CURSORICONINFO structure */
1870 GetBitmapBits( iconinfo->hbmMask ,sizeAnd,(char*)(info + 1) );
1871 GetBitmapBits( iconinfo->hbmColor,sizeXor,(char*)(info + 1) +sizeAnd);
1872 GlobalUnlock16( hObj );
1874 return hObj;
1878 /**********************************************************************
1880 DrawIconEx16 (USER.394)
1882 BOOL16 WINAPI DrawIconEx16 (HDC16 hdc, INT16 xLeft, INT16 yTop, HICON16 hIcon,
1883 INT16 cxWidth, INT16 cyWidth, UINT16 istep,
1884 HBRUSH16 hbr, UINT16 flags)
1886 return DrawIconEx(hdc, xLeft, yTop, hIcon, cxWidth, cyWidth,
1887 istep, hbr, flags);
1891 /******************************************************************************
1892 * DrawIconEx32 [USER32.160] Draws an icon or cursor on device context
1894 * NOTES
1895 * Why is this using SM_CXICON instead of SM_CXCURSOR?
1897 * PARAMS
1898 * hdc [I] Handle to device context
1899 * x0 [I] X coordinate of upper left corner
1900 * y0 [I] Y coordinate of upper left corner
1901 * hIcon [I] Handle to icon to draw
1902 * cxWidth [I] Width of icon
1903 * cyWidth [I] Height of icon
1904 * istep [I] Index of frame in animated cursor
1905 * hbr [I] Handle to background brush
1906 * flags [I] Icon-drawing flags
1908 * RETURNS
1909 * Success: TRUE
1910 * Failure: FALSE
1912 BOOL WINAPI DrawIconEx( HDC hdc, INT x0, INT y0, HICON hIcon,
1913 INT cxWidth, INT cyWidth, UINT istep,
1914 HBRUSH hbr, UINT flags )
1916 CURSORICONINFO *ptr = (CURSORICONINFO *)GlobalLock16 (hIcon);
1917 HDC hDC_off = 0, hMemDC = CreateCompatibleDC (hdc);
1918 BOOL result = FALSE, DoOffscreen = FALSE;
1919 HBITMAP hB_off = 0, hOld = 0;
1921 if (!ptr) return FALSE;
1923 if (istep)
1924 FIXME_(icon)("Ignoring istep=%d\n", istep);
1925 if (flags & DI_COMPAT)
1926 FIXME_(icon)("Ignoring flag DI_COMPAT\n");
1928 /* Calculate the size of the destination image. */
1929 if (cxWidth == 0)
1931 if (flags & DI_DEFAULTSIZE)
1932 cxWidth = GetSystemMetrics (SM_CXICON);
1933 else
1934 cxWidth = ptr->nWidth;
1936 if (cyWidth == 0)
1938 if (flags & DI_DEFAULTSIZE)
1939 cyWidth = GetSystemMetrics (SM_CYICON);
1940 else
1941 cyWidth = ptr->nHeight;
1944 if (!(DoOffscreen = (hbr >= STOCK_WHITE_BRUSH) && (hbr <=
1945 STOCK_HOLLOW_BRUSH)))
1947 GDIOBJHDR *object = (GDIOBJHDR *) GDI_HEAP_LOCK(hbr);
1948 if (object)
1950 UINT16 magic = object->wMagic;
1951 GDI_HEAP_UNLOCK(hbr);
1952 DoOffscreen = magic == BRUSH_MAGIC;
1955 if (DoOffscreen) {
1956 RECT r;
1958 r.left = 0;
1959 r.top = 0;
1960 r.right = cxWidth;
1961 r.bottom = cxWidth;
1963 hDC_off = CreateCompatibleDC(hdc);
1964 hB_off = CreateCompatibleBitmap(hdc, cxWidth, cyWidth);
1965 if (hDC_off && hB_off) {
1966 hOld = SelectObject(hDC_off, hB_off);
1967 FillRect(hDC_off, &r, hbr);
1971 if (hMemDC && (!DoOffscreen || (hDC_off && hB_off)))
1973 HBITMAP hXorBits, hAndBits;
1974 COLORREF oldFg, oldBg;
1975 INT nStretchMode;
1977 nStretchMode = SetStretchBltMode (hdc, STRETCH_DELETESCANS);
1979 hXorBits = CreateBitmap ( ptr->nWidth, ptr->nHeight,
1980 ptr->bPlanes, ptr->bBitsPerPixel,
1981 (char *)(ptr + 1)
1982 + ptr->nHeight *
1983 BITMAP_GetWidthBytes(ptr->nWidth,1) );
1984 hAndBits = CreateBitmap ( ptr->nWidth, ptr->nHeight,
1985 1, 1, (char *)(ptr+1) );
1986 oldFg = SetTextColor( hdc, RGB(0,0,0) );
1987 oldBg = SetBkColor( hdc, RGB(255,255,255) );
1989 if (hXorBits && hAndBits)
1991 HBITMAP hBitTemp = SelectObject( hMemDC, hAndBits );
1992 if (flags & DI_MASK)
1994 if (DoOffscreen)
1995 StretchBlt (hDC_off, 0, 0, cxWidth, cyWidth,
1996 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
1997 else
1998 StretchBlt (hdc, x0, y0, cxWidth, cyWidth,
1999 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
2001 SelectObject( hMemDC, hXorBits );
2002 if (flags & DI_IMAGE)
2004 if (DoOffscreen)
2005 StretchBlt (hDC_off, 0, 0, cxWidth, cyWidth,
2006 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
2007 else
2008 StretchBlt (hdc, x0, y0, cxWidth, cyWidth,
2009 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
2011 SelectObject( hMemDC, hBitTemp );
2012 result = TRUE;
2015 SetTextColor( hdc, oldFg );
2016 SetBkColor( hdc, oldBg );
2017 if (hXorBits) DeleteObject( hXorBits );
2018 if (hAndBits) DeleteObject( hAndBits );
2019 SetStretchBltMode (hdc, nStretchMode);
2020 if (DoOffscreen) {
2021 BitBlt(hdc, x0, y0, cxWidth, cyWidth, hDC_off, 0, 0, SRCCOPY);
2022 SelectObject(hDC_off, hOld);
2025 if (hMemDC) DeleteDC( hMemDC );
2026 if (hDC_off) DeleteDC(hDC_off);
2027 if (hB_off) DeleteObject(hB_off);
2028 GlobalUnlock16( hIcon );
2029 return result;